Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Commit

Permalink
Add dsci configuration option
Browse files Browse the repository at this point in the history
Some Quectel modules (EP06) do not have `ccinfo` notifications.
You may switch back to (less efficient) `dsci` notifications by `dsci=on` configuration switch.
  • Loading branch information
RoEdAl committed Jul 25, 2023
1 parent b1ff30f commit 7335cee
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 48 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,11 @@ Supported modules:
* `UCS-2` encoding is mandatory now.
* Hanging-up calls using `AT+QHUP` command with specific *release cause*.
* Handling calls is based on `ccinfo` notifications (see `AT+QINDCFG="ccinfo"` command) instead of `DSCI` (`AT^DSCI` command) call status notifications.
* Call handling is based on automatic call status contifications.
* For *Quectel* modules `ccinfo` (`AT+QINDCFG="ccinfo"` command) notifications are used by default.\
You can switch back to (less efficient) `dsci` (`AT^DSCI` command) notifications by `dcsi` (on/**off**) configuration switch.
* For *SimCOM* modules `clcc` (`AT+CLCC=1` command) notifications are used.
* Improved/extended *AT* commands response handler.
Changes required to properly handle `AT+CMGL` command response.
Expand Down
2 changes: 2 additions & 0 deletions etc/quectel.conf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ initstate=start ; specified initial state of device, must be one of 'stop' 's
;msg_storage=auto ; auto,sm,me,mt,sr
;msg_direct=none ; none,on,off

;dsci=off ; on,off

; quectel required settings
[quectel0]
audio=/dev/ttyUSB1 ; tty port for Audio, set as ttyUSB4 for SimCOM if no other dev present
Expand Down
2 changes: 2 additions & 0 deletions quectel.conf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ initstate=start ; specified initial state of device, must be one of 'stop' 's
;msg_storage=auto ; auto,sm,me,mt,sr
;msg_direct=none ; none,on,off

;dsci=off ; on,off

; quectel required settings
[quectel0]
audio=/dev/ttyUSB1 ; tty port for Audio, set as ttyUSB4 for Simcom if no other dev present
Expand Down
11 changes: 9 additions & 2 deletions src/at_command.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,13 @@ int at_enqueue_initialization(struct cpvt *cpvt)
return 0;
}

int at_enqueue_initialization_quectel(struct cpvt *cpvt)
int at_enqueue_initialization_quectel(struct cpvt *cpvt, unsigned int dsci)
{
static const char cmd_qpcmv[] = "AT+QPCMV?\r";

static const char cmd_at_qindcfg_cc[] = "AT+QINDCFG=\"ccinfo\",1,0\r";
static const char cmd_at_dsci[] = "AT^DSCI=1\r";

static const char cmd_at_qindcfg_csq[] = "AT+QINDCFG=\"csq\",1,0\r";
static const char cmd_at_qindcfg_act[] = "AT+QINDCFG=\"act\",1,0\r";
static const char cmd_at_qindcfg_ring[] = "AT+QINDCFG=\"ring\",0,0\r";
Expand All @@ -292,6 +294,11 @@ int at_enqueue_initialization_quectel(struct cpvt *cpvt)

static const char cmd_at_qccid[] = "AT+QCCID\r";

static const at_queue_cmd_t ccinfo_cmds[] = {
ATQ_CMD_DECLARE_ST(CMD_AT_QINDCFG_CC, cmd_at_qindcfg_cc),
ATQ_CMD_DECLARE_ST(CMD_AT_DSCI, cmd_at_dsci)
};

static const at_queue_cmd_t tonedet_cmds[] = {
ATQ_CMD_DECLARE_STI(CMD_AT_QTONEDET_0, cmd_at_qtonedet_0),
ATQ_CMD_DECLARE_STI(CMD_AT_QTONEDET_1, cmd_at_qtonedet_1),
Expand All @@ -306,7 +313,7 @@ int at_enqueue_initialization_quectel(struct cpvt *cpvt)
ATQ_CMD_DECLARE_STI(CMD_AT_QCCID, cmd_at_qccid),
ATQ_CMD_DECLARE_STI(CMD_AT_QTONEDET_1, cmd_at_qtonedet_1),
ATQ_CMD_DECLARE_ST(CMD_AT_CVOICE, cmd_qpcmv), /* read the current voice mode, and return sampling rate、data bit、frame period */
ATQ_CMD_DECLARE_ST(CMD_AT_QINDCFG_CC, cmd_at_qindcfg_cc),
ccinfo_cmds[dsci? 1:0],
ATQ_CMD_DECLARE_ST(CMD_AT_QINDCFG_CSQ, cmd_at_qindcfg_csq),
ATQ_CMD_DECLARE_ST(CMD_AT_QINDCFG_ACT, cmd_at_qindcfg_act),
ATQ_CMD_DECLARE_ST(CMD_AT_QINDCFG_RING, cmd_at_qindcfg_ring),
Expand Down
2 changes: 1 addition & 1 deletion src/at_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ struct cpvt;
const char *at_cmd2str(at_cmd_t cmd);
int at_enqueue_at(struct cpvt* cpvt);
int at_enqueue_initialization(struct cpvt *cpvt);
int at_enqueue_initialization_quectel(struct cpvt*);
int at_enqueue_initialization_quectel(struct cpvt*, unsigned int);
int at_enqueue_initialization_simcom(struct cpvt*);
int at_enqueue_initialization_other(struct cpvt*);
int at_enqueue_ping(struct cpvt *cpvt);
Expand Down
4 changes: 0 additions & 4 deletions src/at_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,8 +1052,6 @@ int at_parse_csca(char* str, char ** csca)
return 0;
}

#ifdef HANDLE_DSCI

#/* */
int at_parse_dsci(char* str, unsigned* call_idx, unsigned* dir, unsigned* state, unsigned* call_type, char** number, unsigned* toa)
{
Expand Down Expand Up @@ -1088,8 +1086,6 @@ int at_parse_dsci(char* str, unsigned* call_idx, unsigned* dir, unsigned* state,
return -1;
}

#endif

#/* */
int at_parse_clcc(char* str, unsigned* call_idx, unsigned* dir, unsigned* state, unsigned* mode, unsigned* mpty, char** number, unsigned* toa)
{
Expand Down
2 changes: 0 additions & 2 deletions src/at_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ int at_parse_qind_csq(const char* params, int* rssi);
int at_parse_qind_act(char* params, int* act);
int at_parse_qind_cc(char* params, unsigned* call_idx, unsigned* dir, unsigned* state, unsigned* mode, unsigned* mpty, char** number, unsigned* toa);
int at_parse_csca(char* str, char ** csca);
#ifdef HANDLE_DSCI
int at_parse_dsci(char* str, unsigned* call_idx, unsigned* dir, unsigned* state, unsigned* call_type, char** number, unsigned* toa);
#endif
int at_parse_clcc(char* str, unsigned* call_idx, unsigned* dir, unsigned* state, unsigned* mode, unsigned* mpty, char** number, unsigned* toa);
int at_parse_ccwa(char* str, unsigned * class);
int at_parse_qtonedet(const char* str, int* dtmf);
Expand Down
54 changes: 29 additions & 25 deletions src/at_response.c
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ static void handle_clcc(struct pvt* pvt,
{
struct cpvt* cpvt = pvt_find_cpvt(pvt, (int)call_idx);

if(cpvt) {
if (cpvt) {
/* cpvt alive */
CPVT_SET_FLAGS(cpvt, CALL_FLAG_ALIVE);

Expand All @@ -887,35 +887,40 @@ static void handle_clcc(struct pvt* pvt,
return;
}

if (CONF_SHARED(pvt, multiparty)) {
if(mpty)
CPVT_SET_FLAGS(cpvt, CALL_FLAG_MULTIPARTY);
else
CPVT_RESET_FLAGS(cpvt, CALL_FLAG_MULTIPARTY);
}
else {
if (!CPVT_TEST_FLAG(cpvt, CALL_FLAG_MULTIPARTY) && mpty) {
ast_log(LOG_ERROR, "[%s] Rejecting multiparty call - idx:%d\n", PVT_ID(pvt), call_idx);
at_enqueue_hangup(&pvt->sys_chan, call_idx, AST_CAUSE_CALL_REJECTED);
// mpty == 2u : ignore this flag
if (mpty != 2u) {
if (CONF_SHARED(pvt, multiparty)) {
if (mpty)
CPVT_SET_FLAGS(cpvt, CALL_FLAG_MULTIPARTY);
else
CPVT_RESET_FLAGS(cpvt, CALL_FLAG_MULTIPARTY);
}
else {
if (!CPVT_TEST_FLAG(cpvt, CALL_FLAG_MULTIPARTY) && mpty) {
ast_log(LOG_ERROR, "[%s] Rejecting multiparty call - idx:%d\n", PVT_ID(pvt), call_idx);
at_enqueue_hangup(&pvt->sys_chan, call_idx, AST_CAUSE_CALL_REJECTED);
}
}
}

if(state != cpvt->state) {
if (state != cpvt->state) {
change_channel_state(cpvt, state, 0);
}
else {
return;
}
}
else {
switch (state)
{
switch (state) {
case CALL_STATE_DIALING:
case CALL_STATE_ALERTING:
cpvt = last_initialized_cpvt(pvt);
if (!CONF_SHARED(pvt, multiparty)) {
if (!CPVT_TEST_FLAG(cpvt, CALL_FLAG_MULTIPARTY) && mpty) {
cpvt = NULL;
// mpty == 2u : ignore this flag
if (mpty != 2u) {
if (!CONF_SHARED(pvt, multiparty)) {
if (!CPVT_TEST_FLAG(cpvt, CALL_FLAG_MULTIPARTY) && mpty) {
cpvt = NULL;
}
}
}

Expand Down Expand Up @@ -1090,7 +1095,6 @@ static int at_response_clcc(struct pvt* pvt, char* str)
return 0;
}

#ifdef HANDLE_DSCI
/*!
* \brief Handle ^DSCI response
* \param pvt -- pvt structure
Expand Down Expand Up @@ -1125,13 +1129,17 @@ static int at_response_dsci(struct pvt* pvt, char* str)
break;

default: // request CLCC anyway
request_clcc(pvt);
if (CONF_SHARED(pvt, multiparty)) {
request_clcc(pvt);
}
else {
handle_clcc(pvt, call_index, call_dir, call_state, call_type, 2u, number, number_type);
}
break;
}

return 0;
}
#endif

/*!
* \brief Handle +QIND response.
Expand Down Expand Up @@ -2050,7 +2058,7 @@ static int at_response_cgmi(struct pvt* pvt, const struct ast_str* const respons
ast_verb(1, "[%s] Quectel module\n", PVT_ID(pvt));
pvt->is_simcom = 0;
pvt->has_voice = 0;
return at_enqueue_initialization_quectel(&pvt->sys_chan);
return at_enqueue_initialization_quectel(&pvt->sys_chan, CONF_SHARED(pvt, dsci));
}
else if (!strncasecmp(ast_str_buffer(response), MANUFACTURER_SIMCOM, STRLEN(MANUFACTURER_SIMCOM))) {
ast_verb(1, "[%s] SimCOM module\n", PVT_ID(pvt));
Expand Down Expand Up @@ -2644,11 +2652,7 @@ int at_response(struct pvt* pvt, const struct ast_str* const result, at_res_t at
return 0;

case RES_DSCI:
#ifdef HANDLE_DSCI
return at_response_dsci(pvt, str);
#else
return 0;
#endif

case RES_CEND:
#ifdef HANDLE_CEND
Expand Down
1 change: 1 addition & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ static char* cli_show_device_settings (struct ast_cli_entry* e, int cmd, struct
ast_cli (a->fd, " Group : %d\n", CONF_SHARED(pvt, group));
ast_cli (a->fd, " RX gain : %d\n", CONF_SHARED(pvt, rxgain));
ast_cli (a->fd, " TX gain : %d\n", CONF_SHARED(pvt, txgain));
ast_cli (a->fd, " Use ^DSCI notifications : %s\n", AST_CLI_YESNO(CONF_SHARED(pvt, dsci)));
ast_cli (a->fd, " Use CallingPres : %s\n", AST_CLI_YESNO(CONF_SHARED(pvt, usecallingpres)));
ast_cli (a->fd, " Default CallingPres : %s\n", CONF_SHARED(pvt, callingpres) < 0 ? "<Not set>" : ast_describe_caller_presentation (CONF_SHARED(pvt, callingpres)));
ast_cli (a->fd, " Disable SMS : %s\n", AST_CLI_YESNO(CONF_SHARED(pvt, disablesms)));
Expand Down
44 changes: 31 additions & 13 deletions src/dc_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,21 @@ const char* dc_3stbool2str_capitalized(int v)
return enum2str_def(b, strs, ITEMS_OF(strs), "None");
}

static unsigned int parse_on_off(const char* const name, const char* const value, unsigned int defval) {
if (!value) {
return defval;
}
if (ast_true(value)) {
return 1u;
}
if (ast_false(value)) {
return 0u;
}

ast_log(LOG_ERROR, "Invalid value '%s' for configuration option '%s'\n", value, name);
return defval;
}

static const char* const msgstor_strs[] = {
"AUTO",
"SM",
Expand Down Expand Up @@ -166,14 +181,13 @@ static int dc_uconfig_fill(struct ast_config * cfg, const char * cat, struct dc_
}

if (slin16_str) {
slin16 = ast_true(slin16_str);
slin16 = parse_on_off("slin16", slin16_str, 0u);
}
else {
slin16 = 0;
}

if(!data_tty && !imei && !imsi)
{
if (!data_tty && !imei && !imsi) {
ast_log (LOG_ERROR, "Skipping device %s. Missing required data_tty setting\n", cat);
return 1;
}
Expand Down Expand Up @@ -265,19 +279,20 @@ void dc_sconfig_fill(struct ast_config * cfg, const char * cat, struct dc_sconfi
}
}
else if (!strcasecmp (v->name, "usecallingpres")) {
config->usecallingpres = ast_true (v->value); /* usecallingpres is set to 0 if invalid */
config->usecallingpres = parse_on_off(v->name, v->value, 0u); /* usecallingpres is set to 0 if invalid */
}
else if (!strcasecmp (v->name, "autodeletesms")) {
config->autodeletesms = ast_true (v->value); /* autodeletesms is set to 0 if invalid */
config->autodeletesms = parse_on_off(v->name, v->value, 0u); /* autodeletesms is set to 0 if invalid */
}
else if (!strcasecmp (v->name, "resetquectel")) {
config->resetquectel = ast_true (v->value); /* resetquectel is set to 0 if invalid */
config->resetquectel = parse_on_off(v->name, v->value, 0u); /* resetquectel is set to 0 if invalid */
}
else if (!strcasecmp (v->name, "disablesms")) {
config->disablesms = ast_true (v->value); /* disablesms is set to 0 if invalid */
config->disablesms = parse_on_off(v->name, v->value, 0u); /* disablesms is set to 0 if invalid */
}
else if (!strcasecmp (v->name, "disable")) {
config->initstate = ast_true (v->value) ? DEV_STATE_REMOVED : DEV_STATE_STARTED;
const unsigned int is = parse_on_off(v->name, v->value, 0u);
config->initstate = is ? DEV_STATE_REMOVED : DEV_STATE_STARTED;
}
else if (!strcasecmp (v->name, "initstate")) {
const dev_state_t val = str2dev_state(v->value);
Expand All @@ -288,13 +303,13 @@ void dc_sconfig_fill(struct ast_config * cfg, const char * cat, struct dc_sconfi
}
else if (!strcasecmp (v->name, "callwaiting")) {
if(strcasecmp(v->value, "auto"))
config->callwaiting = ast_true (v->value);
config->callwaiting = parse_on_off(v->name, v->value, 0u);
}
else if (!strcasecmp (v->name, "multiparty")) {
config->multiparty = ast_true(v->value);
config->multiparty = parse_on_off(v->name, v->value, 0u);
}
else if (!strcasecmp (v->name, "dtmf")) {
config->dtmf = ast_true(v->value);
config->dtmf = parse_on_off(v->name, v->value, 0u);
}
else if (!strcasecmp (v->name, "dtmf_duration")) {
config->dtmf_duration = strtol(v->value, (char**) NULL, 10);
Expand All @@ -303,10 +318,13 @@ void dc_sconfig_fill(struct ast_config * cfg, const char * cat, struct dc_sconfi
}
}
else if (!strcasecmp (v->name, "moh")) {
config->moh = ast_true(v->value);
config->moh = parse_on_off(v->name, v->value, 0u);
}
else if (!strcasecmp (v->name, "query_time")) {
config->query_time = ast_true(v->value);
config->query_time = parse_on_off(v->name, v->value, 0u);
}
else if (!strcasecmp (v->name, "dsci")) {
config->dsci = parse_on_off(v->name, v->value, 0u);
}
else if (!strcasecmp (v->name, "msg_direct")) {
config->msg_direct = dc_str23stbool(v->value);
Expand Down
1 change: 1 addition & 0 deletions src/dc_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ typedef struct dc_sconfig
unsigned int dtmf:1; /*! 0 */
unsigned int moh:1; /*! 0 */
unsigned int query_time:1; /*! 0 */
unsigned int dsci:1; /*!< use ^DSCI call state notifications */

long dtmf_duration; /*! duration of DTMF in miliseconds */
dev_state_t initstate; /*! DEV_STATE_STARTED */
Expand Down
2 changes: 2 additions & 0 deletions uac/quectel.conf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ initstate=start ; specified initial state of device, must be one of 'stop' 's
;msg_storage=auto ; auto,sm,me,mt,sr
;msg_direct=none ; none,on,off

;dsci=off ; on,off

; quectel required settings
[quectel0]
data=/dev/ttyUSB2 ; tty port for AT commands; no default value
Expand Down

0 comments on commit 7335cee

Please sign in to comment.