asterisk-chan-dongle/chan_dongle.h

274 lines
11 KiB
C

/*
Copyright (C) 2009-2015
bg <bg_one@mail.ru>
http://www.e1550.mobi
Artem Makhutov <artem@makhutov.org>
http://www.makhutov.org
Dmitry Vagin <dmitry2004@yandex.ru>
*/
#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 */