forked from wdoekes/asterisk-chan-dongle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chan_dongle.h
273 lines (209 loc) · 11 KB
/
chan_dongle.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
/*
Copyright (C) 2009-2015
bg <[email protected]>
http://www.e1550.mobi
Artem Makhutov <[email protected]>
http://www.makhutov.org
Dmitry Vagin <[email protected]>
*/
#ifndef CHAN_DONGLE_H_INCLUDED
#define CHAN_DONGLE_H_INCLUDED
#include "ast_config.h"
#include <asterisk/lock.h>
#include <asterisk/linkedlists.h>
#include "ast_compat.h" /* asterisk compatibility fixes */
#include "mixbuffer.h" /* struct mixbuffer */
//#include "ringbuffer.h" /* struct ringbuffer */
#include "cpvt.h" /* struct cpvt */
#include "export.h" /* EXPORT_DECL EXPORT_DEF */
#include "dc_config.h" /* pvt_config_t */
#include "at_command.h"
#define MODULE_DESCRIPTION "Huawei 3G Dongle Channel Driver"
#define MAXDONGLEDEVICES 128
INLINE_DECL const char * dev_state2str(dev_state_t state)
{
return enum2str(state, dev_state_strs, ITEMS_OF(dev_state_strs));
}
INLINE_DECL const char * dev_state2str_msg(dev_state_t state)
{
static const char * const states[] = { "Stop scheduled", "Restart scheduled", "Removal scheduled", "Start scheduled" };
return enum2str(state, states, ITEMS_OF(states));
}
#if ASTERISK_VERSION_NUM >= 100000 && ASTERISK_VERSION_NUM < 130000 /* 10-13 */
/* Only linear is allowed */
EXPORT_DECL struct ast_format chan_dongle_format;
EXPORT_DECL struct ast_format_cap * chan_dongle_format_cap;
#endif /* ^10-13 */
typedef enum {
RESTATE_TIME_NOW = 0,
RESTATE_TIME_GRACEFULLY,
RESTATE_TIME_CONVENIENT,
} restate_time_t;
/* state */
typedef struct pvt_state
{
char audio_tty[DEVPATHLEN]; /*!< tty for audio connection */
char data_tty[DEVPATHLEN]; /*!< tty for AT commands */
uint32_t at_tasks; /*!< number of active tasks in at_queue */
uint32_t at_cmds; /*!< number of active commands in at_queue */
uint32_t chansno; /*!< number of channels in channels list */
uint8_t chan_count[CALL_STATES_NUMBER]; /*!< channel number grouped by state */
} pvt_state_t;
#define PVT_STATE_T(state, name) ((state)->name)
/* statictics */
typedef struct pvt_stat
{
uint32_t at_tasks; /*!< number of tasks added to queue */
uint32_t at_cmds; /*!< number of commands added to queue */
uint32_t at_responses; /*!< number of responses handled */
uint32_t d_read_bytes; /*!< number of bytes of commands actually read from device */
uint32_t d_write_bytes; /*!< number of bytes of commands actually written to device */
uint64_t a_read_bytes; /*!< number of bytes of audio read from device */
uint64_t a_write_bytes; /*!< number of bytes of audio written to device */
uint32_t read_frames; /*!< number of frames read from device */
uint32_t read_sframes; /*!< number of truncated frames read from device */
uint32_t write_frames; /*!< number of tries to frame write */
uint32_t write_tframes; /*!< number of truncated frames to write */
uint32_t write_sframes; /*!< number of silence frames to write */
uint64_t write_rb_overflow_bytes; /*!< number of overflow bytes */
uint32_t write_rb_overflow; /*!< number of times when a_write_rb overflowed */
uint32_t in_calls; /*!< number of incoming calls not including waiting */
uint32_t cw_calls; /*!< number of waiting calls */
uint32_t out_calls; /*!< number of all outgoing calls attempts */
uint32_t in_calls_handled; /*!< number of ncoming/waiting calls passed to dialplan */
uint32_t in_pbx_fails; /*!< number of start_pbx fails */
uint32_t calls_answered[2]; /*!< number of outgoing and incoming/waiting calls answered */
uint32_t calls_duration[2]; /*!< seconds of outgoing and incoming/waiting calls */
} pvt_stat_t;
#define PVT_STAT_T(stat, name) ((stat)->name)
struct at_queue_task;
typedef unsigned int sms_inbox_item_type;
#define SMS_INBOX_ITEM_BITS (sizeof(sms_inbox_item_type) * 8)
#define SMS_INBOX_ARRAY_SIZE ((SMS_INDEX_MAX + SMS_INBOX_ITEM_BITS - 1) / SMS_INBOX_ITEM_BITS)
typedef struct pvt
{
AST_LIST_ENTRY (pvt) entry; /*!< linked list pointers */
ast_mutex_t lock; /*!< pvt lock */
AST_LIST_HEAD_NOLOCK (, at_queue_task) at_queue; /*!< queue for commands to modem */
AST_LIST_HEAD_NOLOCK (, cpvt) chans; /*!< list of channels */
struct cpvt sys_chan; /*!< system channel */
struct cpvt *last_dialed_cpvt; /*!< channel what last call successfully set ATDnum; leave until ^ORIG received; need because real call idx of dialing call unknown until ^ORIG */
pthread_t monitor_thread; /*!< monitor (at commands reader) thread handle */
int audio_fd; /*!< audio descriptor */
int data_fd; /*!< data descriptor */
char * alock; /*!< name of lockfile for audio */
char * dlock; /*!< name of lockfile for data */
struct ast_dsp* dsp; /*!< silence/DTMF detector - FIXME: must be in cpvt */
dc_dtmf_setting_t real_dtmf; /*!< real DTMF setting */
struct ast_timer* a_timer; /*!< audio write timer */
char a_write_buf[FRAME_SIZE * 5]; /*!< audio write buffer */
struct mixbuffer a_write_mixb; /*!< audio mix buffer */
// struct ringbuffer a_write_rb; /*!< audio ring buffer */
// char a_read_buf[FRAME_SIZE + AST_FRIENDLY_OFFSET]; /*!< audio read buffer */
// struct ast_frame a_read_frame; /*!< read frame buffer */
char dtmf_digit; /*!< last DTMF digit */
struct timeval dtmf_begin_time; /*!< time of begin of last DTMF digit */
struct timeval dtmf_end_time; /*!< time of end of last DTMF digit */
int timeout; /*!< used to set the timeout for data */
#define DATA_READ_TIMEOUT 10000 /* 10 seconds */
unsigned long channel_instance; /*!< number of channels created on this device */
unsigned int rings; /*!< ring/ccwa number distributed to at_response_clcc() */
/* device state */
int gsm_reg_status;
int rssi;
int linkmode;
int linksubmode;
char provider_name[32];
char manufacturer[32];
char model[32];
char firmware[32];
char imei[17];
char imsi[17];
char subscriber_number[128];
char location_area_code[8];
char cell_id[8];
char sms_scenter[20];
unsigned int incoming_sms_index;
sms_inbox_item_type incoming_sms_inbox[SMS_INBOX_ARRAY_SIZE];
volatile unsigned int connected:1; /*!< do we have an connection to a device */
unsigned int initialized:1; /*!< whether a service level connection exists or not */
unsigned int gsm_registered:1; /*!< do we have an registration to a GSM */
unsigned int dialing; /*!< HW state; true from ATD response OK until CEND or CONN for this call idx */
unsigned int ring:1; /*!< HW state; true if has incoming call from first RING until CEND or CONN */
unsigned int cwaiting:1; /*!< HW state; true if has incoming call waiting from first CCWA until CEND or CONN for */
unsigned int outgoing_sms:1; /*!< outgoing sms */
unsigned int volume_sync_step:2; /*!< volume synchronized stage */
#define VOLUME_SYNC_BEGIN 0
#define VOLUME_SYNC_DONE 3
unsigned int has_sms:1; /*!< device has SMS support */
unsigned int has_voice:1; /*!< device has voice call support */
unsigned int has_voice_quectel:1; /*!< device has Quectel voice call support */
unsigned int has_call_waiting:1; /*!< call waiting enabled on device */
unsigned int group_last_used:1; /*!< mark the last used device */
unsigned int prov_last_used:1; /*!< mark the last used device */
unsigned int sim_last_used:1; /*!< mark the last used device */
unsigned int terminate_monitor:1; /*!< non-zero if we want terminate monitor thread i.e. restart, stop, remove */
// unsigned int off:1; /*!< device not used */
// unsigned int prevent_new:1; /*!< prevent new usage */
unsigned int has_subscriber_number:1; /*!< subscriber_number field is valid */
// unsigned int monitor_running:1; /*!< true if monitor thread is running */
unsigned int must_remove:1; /*!< mean must removed from list: NOT FULLY THREADSAFE */
volatile dev_state_t desired_state; /*!< desired state */
volatile restate_time_t restart_time; /*!< time when change state */
volatile dev_state_t current_state; /*!< current state */
pvt_config_t settings; /*!< all device settings from config file */
pvt_state_t state; /*!< state */
pvt_stat_t stat; /*!< various statistics */
} pvt_t;
#define CONF_GLOBAL(name) (gpublic->global_settings.name)
#define SCONF_GLOBAL(state, name) ((state)->global_settings.name)
#define CONF_SHARED(pvt, name) SCONFIG(&((pvt)->settings), name)
#define CONF_UNIQ(pvt, name) UCONFIG(&((pvt)->settings), name)
#define PVT_ID(pvt) UCONFIG(&((pvt)->settings), id)
#define PVT_STATE(pvt, name) PVT_STATE_T(&(pvt)->state, name)
#define PVT_STAT(pvt, name) PVT_STAT_T(&(pvt)->stat, name)
typedef struct public_state
{
AST_RWLIST_HEAD(devices, pvt) devices;
ast_mutex_t discovery_lock;
pthread_t discovery_thread; /* The discovery thread handler */
volatile int unloading_flag; /* no need mutex or other locking for protect this variable because no concurent r/w and set non-0 atomically */
struct dc_gconfig global_settings;
} public_state_t;
EXPORT_DECL public_state_t * gpublic;
EXPORT_DEF int sms_inbox_set(struct pvt* pvt, int index);
EXPORT_DEF int sms_inbox_clear(struct pvt* pvt, int index);
EXPORT_DEF int is_sms_inbox_set(const struct pvt* pvt, int index);
EXPORT_DECL void clean_read_data(const char * devname, int fd);
EXPORT_DECL int pvt_get_pseudo_call_idx(const struct pvt * pvt);
EXPORT_DECL int ready4voice_call(const struct pvt* pvt, const struct cpvt * current_cpvt, int opts);
EXPORT_DECL int is_dial_possible(const struct pvt * pvt, int opts);
EXPORT_DECL const char * pvt_str_state(const struct pvt* pvt);
EXPORT_DECL struct ast_str * pvt_str_state_ex(const struct pvt* pvt);
EXPORT_DECL const char * GSM_regstate2str(int gsm_reg_status);
EXPORT_DECL const char * sys_mode2str(int sys_mode);
EXPORT_DECL const char * sys_submode2str(int sys_submode);
EXPORT_DECL char* rssi2dBm(int rssi, char* buf, unsigned len);
EXPORT_DECL void pvt_on_create_1st_channel(struct pvt* pvt);
EXPORT_DECL void pvt_on_remove_last_channel(struct pvt* pvt);
EXPORT_DECL void pvt_reload(restate_time_t when);
EXPORT_DECL int pvt_enabled(const struct pvt * pvt);
EXPORT_DECL void pvt_try_restate(struct pvt * pvt);
EXPORT_DECL int opentty (const char* dev, char ** lockfile);
EXPORT_DECL void closetty(int fd, char ** lockfname);
EXPORT_DECL int lock_try(const char * devname, char ** lockname);
EXPORT_DECL struct pvt * find_device_ex(struct public_state * state, const char * name);
INLINE_DECL struct pvt * find_device (const char* name)
{
return find_device_ex(gpublic, name);
}
EXPORT_DECL struct pvt * find_device_ext(const char* name);
EXPORT_DECL struct pvt * find_device_by_resource_ex(struct public_state * state, const char * resource, int opts, const struct ast_channel * requestor, int * exists);
EXPORT_DECL void pvt_dsp_setup(struct pvt * pvt, const char * id, dc_dtmf_setting_t dtmf_new);
INLINE_DECL struct pvt * find_device_by_resource(const char * resource, int opts, const struct ast_channel * requestor, int * exists)
{
return find_device_by_resource_ex(gpublic, resource, opts, requestor, exists);
}
EXPORT_DECL struct ast_module * self_module();
#define PVT_NO_CHANS(pvt) (PVT_STATE(pvt, chansno) == 0)
#endif /* CHAN_DONGLE_H_INCLUDED */