Successfully sending SMS messages
This commit is contained in:
parent
353a2b7282
commit
db7c61e9b9
436
src/gsm.c
436
src/gsm.c
|
@ -36,6 +36,11 @@
|
|||
/* GSM */
|
||||
/* private */
|
||||
/* types */
|
||||
typedef enum _GSMMode
|
||||
{
|
||||
GSM_MODE_INIT = 0, GSM_MODE_COMMAND, GSM_MODE_PDU
|
||||
} GSMMode;
|
||||
|
||||
typedef enum _GSMPriority
|
||||
{
|
||||
GSM_PRIORITY_LOW = 0, GSM_PRIORITY_NORMAL, GSM_PRIORITY_HIGH
|
||||
|
@ -49,13 +54,9 @@ typedef struct _GSMCommand
|
|||
char * command;
|
||||
GSMError error;
|
||||
GSMCommandCallback callback;
|
||||
GSMMode mode;
|
||||
} GSMCommand;
|
||||
|
||||
typedef enum _GSMMode
|
||||
{
|
||||
GSM_MODE_INIT = 0, GSM_MODE_COMMAND
|
||||
} GSMMode;
|
||||
|
||||
typedef struct _GSMTrigger
|
||||
{
|
||||
char const * trigger;
|
||||
|
@ -113,14 +114,40 @@ static struct
|
|||
{ 13, N_("SIM failure") },
|
||||
{ 14, N_("SIM busy") },
|
||||
{ 15, N_("SIM wrong") },
|
||||
{ 16, N_("Incorrect password") },
|
||||
{ 17, N_("SIM PIN2 required") },
|
||||
{ 18, N_("SIM PUK2 required") },
|
||||
{ 20, N_("Memory full") },
|
||||
{ 21, N_("Invalid index") },
|
||||
{ 22, N_("Not found") },
|
||||
{ 23, N_("Memory failure") },
|
||||
{ 24, N_("Text string too long") },
|
||||
{ 25, N_("Invalid characters in text string") },
|
||||
{ 26, N_("Dial string too long") },
|
||||
{ 27, N_("Invalid characters in dial string") },
|
||||
{ 30, N_("No network service") },
|
||||
{ 31, N_("Network timeout") },
|
||||
{ 32, N_("Network not allowed - emergency calls only")},
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/* CMS ERROR */
|
||||
static struct
|
||||
{
|
||||
int code;
|
||||
char const * error;
|
||||
} _gsm_cms_errors[] =
|
||||
{
|
||||
{ 300, N_("ME failure") },
|
||||
{ 301, N_("SMS service of ME reserved") },
|
||||
{ 302, N_("Operation not allowed") },
|
||||
{ 303, N_("Operation not supported") },
|
||||
{ 304, N_("Invalid PDU mode parameter") },
|
||||
{ 310, N_("SIM not inserted") },
|
||||
{ 311, N_("SIM PIN required") },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
/* prototypes */
|
||||
static int _is_code(char const * code);
|
||||
|
@ -128,10 +155,15 @@ static int _is_figure(int c);
|
|||
static int _is_number(char const * number);
|
||||
|
||||
/* commands */
|
||||
static GSMCommand * _gsm_command_new(GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback);
|
||||
static GSMCommand * _gsm_command_new(char const * command);
|
||||
static void _gsm_command_delete(GSMCommand * command);
|
||||
static GSMMode _gsm_command_get_mode(GSMCommand * gsmc);
|
||||
static GSMPriority _gsm_command_get_priority(GSMCommand * gsmc);
|
||||
static void _gsm_command_set_callback(GSMCommand * gsmc,
|
||||
GSMCommandCallback callback);
|
||||
static void _gsm_command_set_error(GSMCommand * gsmc, GSMError error);
|
||||
static void _gsm_command_set_mode(GSMCommand * gsmc, GSMMode mode);
|
||||
static void _gsm_command_set_priority(GSMCommand * gsmc, GSMPriority priority);
|
||||
|
||||
/* events */
|
||||
static int _gsm_event(GSM * gsm, GSMEventType type, ...);
|
||||
|
@ -171,15 +203,22 @@ static int _gsm_parse(GSM * gsm);
|
|||
static int _gsm_parse_line(GSM * gsm, char const * line, gboolean * answered);
|
||||
|
||||
/* queue management */
|
||||
static int _gsm_queue_command(GSM * gsm, GSMPriority priority,
|
||||
static GSMCommand * _gsm_queue(GSM * gsm, char const * command);
|
||||
static int _gsm_queue_error(GSM * gsm, char const * command, GSMError error);
|
||||
static int _gsm_queue_full(GSM * gsm, GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback);
|
||||
static int _gsm_queue_full_mode(GSM * gsm, GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback, GSMMode mode);
|
||||
static int _gsm_queue_command(GSM * gsm, GSMCommand * command);
|
||||
static void _gsm_queue_flush(GSM * gsm);
|
||||
static void _gsm_queue_pop(GSM * gsm);
|
||||
static int _gsm_queue_push(GSM * gsm);
|
||||
|
||||
/* triggers */
|
||||
static int _gsm_trigger_cme_error(GSM * gsm, char const * result);
|
||||
static int _gsm_trigger_cms_error(GSM * gsm, char const * result);
|
||||
static int _gsm_trigger_cmgl(GSM * gsm, char const * result);
|
||||
static int _gsm_trigger_cops(GSM * gsm, char const * result);
|
||||
static int _gsm_trigger_cpbr(GSM * gsm, char const * result);
|
||||
|
@ -193,6 +232,7 @@ static GSMTrigger _gsm_triggers[] =
|
|||
#define GSM_TRIGGER(trigger, callback) \
|
||||
{ trigger, sizeof(trigger) - 1, _gsm_trigger_ ## callback }
|
||||
GSM_TRIGGER("+CME ERROR: ", cme_error),
|
||||
GSM_TRIGGER("+CMS ERROR: ", cms_error),
|
||||
GSM_TRIGGER("+CMGL: ", cmgl),
|
||||
GSM_TRIGGER("+COPS: ", cops),
|
||||
GSM_TRIGGER("+CPBR: ", cpbr),
|
||||
|
@ -504,21 +544,20 @@ static int _is_number(char const * number)
|
|||
|
||||
/* commands */
|
||||
/* gsm_command_new */
|
||||
static GSMCommand * _gsm_command_new(GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback)
|
||||
static GSMCommand * _gsm_command_new(char const * command)
|
||||
{
|
||||
GSMCommand * gsmc;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(%u, \"%s\")\n", __func__, priority, command);
|
||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, command);
|
||||
#endif
|
||||
if((gsmc = malloc(sizeof(*gsmc))) == NULL)
|
||||
return NULL; /* XXX report error */
|
||||
gsmc->priority = priority;
|
||||
gsmc->priority = GSM_PRIORITY_NORMAL;
|
||||
gsmc->command = strdup(command);
|
||||
gsmc->error = error;
|
||||
gsmc->callback = callback;
|
||||
gsmc->error = GSM_ERROR_UNKNOWN;
|
||||
gsmc->callback = NULL;
|
||||
gsmc->mode = GSM_MODE_COMMAND;
|
||||
/* check errors */
|
||||
if(gsmc->command == NULL)
|
||||
{
|
||||
|
@ -540,6 +579,49 @@ static void _gsm_command_delete(GSMCommand * gsmc)
|
|||
}
|
||||
|
||||
|
||||
/* gsm_command_get_mode */
|
||||
static GSMMode _gsm_command_get_mode(GSMCommand * gsmc)
|
||||
{
|
||||
return gsmc->mode;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_command_get_priority */
|
||||
static GSMPriority _gsm_command_get_priority(GSMCommand * gsmc)
|
||||
{
|
||||
return gsmc->priority;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_command_set_callback */
|
||||
static void _gsm_command_set_callback(GSMCommand * gsmc,
|
||||
GSMCommandCallback callback)
|
||||
{
|
||||
gsmc->callback = callback;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_command_set_error */
|
||||
static void _gsm_command_set_error(GSMCommand * gsmc, GSMError error)
|
||||
{
|
||||
gsmc->error = error;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_command_set_mode */
|
||||
static void _gsm_command_set_mode(GSMCommand * gsmc, GSMMode mode)
|
||||
{
|
||||
gsmc->mode = mode;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_command_set_priority */
|
||||
static void _gsm_command_set_priority(GSMCommand * gsmc, GSMPriority priority)
|
||||
{
|
||||
gsmc->priority = priority;
|
||||
}
|
||||
|
||||
|
||||
/* events */
|
||||
/* gsm_event */
|
||||
static int _gsm_event(GSM * gsm, GSMEventType type, ...)
|
||||
|
@ -648,7 +730,7 @@ static int _gsm_modem_call(GSM * gsm, GSMCallType calltype, char const * number)
|
|||
if((buf = malloc(len)) == NULL)
|
||||
return 1;
|
||||
snprintf(buf, len, "%s%s%s", cmd, number, suffix);
|
||||
ret = _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, buf,
|
||||
ret = _gsm_queue_full(gsm, GSM_PRIORITY_HIGH, buf,
|
||||
GSM_ERROR_CALL_FAILED, NULL);
|
||||
free(buf);
|
||||
return ret;
|
||||
|
@ -674,7 +756,7 @@ static int _gsm_modem_call_contact(GSM * gsm, GSMCallType calltype,
|
|||
return 1;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%u%s", cmd, index, suffix);
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, buf,
|
||||
return _gsm_queue_full(gsm, GSM_PRIORITY_HIGH, buf,
|
||||
GSM_ERROR_CALL_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
@ -697,7 +779,7 @@ static int _gsm_modem_call_last(GSM * gsm, GSMCallType calltype)
|
|||
default:
|
||||
return 1;
|
||||
}
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
return _gsm_queue_full(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_CALL_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
@ -716,7 +798,7 @@ static int _gsm_modem_enter_pin(GSM * gsm, char const * code)
|
|||
if((buf = malloc(len)) == NULL)
|
||||
return 1;
|
||||
snprintf(buf, len, "%s%s", cmd, code);
|
||||
ret = _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, buf,
|
||||
ret = _gsm_queue_full(gsm, GSM_PRIORITY_HIGH, buf,
|
||||
GSM_ERROR_SIM_PIN_WRONG,
|
||||
(GSMCommandCallback)_gsm_modem_is_pin_needed);
|
||||
free(buf);
|
||||
|
@ -729,8 +811,7 @@ static int _gsm_modem_get_contact_list(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "AT+CPBR=?";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_CONTACT_LIST_FAILED, NULL);
|
||||
return _gsm_queue_error(gsm, cmd, GSM_ERROR_CONTACT_LIST_FAILED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -741,8 +822,7 @@ static int _gsm_modem_get_contacts(GSM * gsm, unsigned int start,
|
|||
char cmd[32];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s%u,%u", "AT+CPBR=", start, end);
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_LOW, cmd,
|
||||
return _gsm_queue_full(gsm, GSM_PRIORITY_LOW, cmd,
|
||||
GSM_ERROR_CONTACT_LIST_FAILED, /* XXX not accurate */
|
||||
NULL);
|
||||
}
|
||||
|
@ -753,8 +833,7 @@ static int _gsm_modem_get_message_list(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "AT+CMGL=?";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_MESSAGE_LIST_FAILED, NULL);
|
||||
return _gsm_queue_error(gsm, cmd, GSM_ERROR_MESSAGE_LIST_FAILED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -765,8 +844,7 @@ static int _gsm_modem_get_messages(GSM * gsm, unsigned int start,
|
|||
char cmd[32];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s%u,%u", "AT+CMGR=", start, end);
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_LOW, cmd,
|
||||
return _gsm_queue_full(gsm, GSM_PRIORITY_LOW, cmd,
|
||||
GSM_ERROR_MESSAGE_LIST_FAILED, /* XXX not accurate */
|
||||
NULL);
|
||||
}
|
||||
|
@ -777,8 +855,7 @@ static int _gsm_modem_get_operator(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "AT+COPS?";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -787,8 +864,7 @@ static int _gsm_modem_get_registration(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "AT+CREG?";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -797,8 +873,7 @@ static int _gsm_modem_get_signal_level(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "AT+CSQ";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_LOW, cmd,
|
||||
GSM_ERROR_SIGNAL_LEVEL_FAILED, NULL);
|
||||
return _gsm_queue_error(gsm, cmd, GSM_ERROR_SIGNAL_LEVEL_FAILED);
|
||||
}
|
||||
|
||||
|
||||
|
@ -808,33 +883,17 @@ static int _gsm_modem_hangup(GSM * gsm)
|
|||
char const cmd[] = "ATH";
|
||||
|
||||
/* XXX probably should query the call status after that */
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
return _gsm_queue_full(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_HANGUP_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_hangup */
|
||||
static int _gsm_modem_send_message(GSM * gsm, char const * number,
|
||||
char const * text)
|
||||
{
|
||||
char const cmd[] = "AT+CMGS=?"; /* FIXME this is just a test */
|
||||
|
||||
if(!_is_number(number) || text == NULL)
|
||||
return 1;
|
||||
if(_gsm_modem_set_message_format(gsm, GSM_MESSAGE_FORMAT_PDU) != 0)
|
||||
return 1;
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_is_pin_needed */
|
||||
static int _gsm_modem_is_pin_needed(GSM * gsm)
|
||||
{
|
||||
char const cmd[] = "AT+CPIN?";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -843,8 +902,7 @@ static int _gsm_modem_is_registered(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "AT+CREG?";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -853,19 +911,140 @@ static int _gsm_modem_reset(GSM * gsm)
|
|||
{
|
||||
char const cmd[] = "ATZ";
|
||||
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
return _gsm_queue_full(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_RESET_FAILED, NULL);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_send_message */
|
||||
static char * _number_to_address(char const * number);
|
||||
static char * _text_to_sept(char const * text);
|
||||
|
||||
static int _gsm_modem_send_message(GSM * gsm, char const * number,
|
||||
char const * text)
|
||||
{
|
||||
int ret;
|
||||
char const cmd1[] = "AT+CMGS=";
|
||||
char * buf1;
|
||||
size_t len1;
|
||||
char const cmd2[] = "1100";
|
||||
char * buf2;
|
||||
size_t len2;
|
||||
char * addr;
|
||||
char * sept;
|
||||
char const pid[] = "00";
|
||||
char const dcs[] = "00";
|
||||
char const vp[] = "AA";
|
||||
|
||||
if(!_is_number(number) || text == NULL
|
||||
|| _gsm_modem_set_message_format(gsm,
|
||||
GSM_MESSAGE_FORMAT_PDU) != 0)
|
||||
return _gsm_event(gsm, GSM_EVENT_TYPE_ERROR,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL);
|
||||
addr = _number_to_address(number);
|
||||
sept = _text_to_sept(text);
|
||||
len2 = sizeof(cmd2) + 2 + strlen(addr ? addr : "") + sizeof(pid)
|
||||
+ sizeof(dcs) + 2 + strlen(sept ? sept : "") + 1;
|
||||
buf2 = malloc(len2);
|
||||
len1 = sizeof(cmd1) + 2;
|
||||
buf1 = malloc(len1);
|
||||
if(addr == NULL || sept == NULL || buf1 == NULL || buf2 == NULL)
|
||||
{
|
||||
free(addr);
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return _gsm_event(gsm, GSM_EVENT_TYPE_ERROR,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL);
|
||||
}
|
||||
snprintf(buf2, len2, "%s%02zX%s%s%s%s%02zX%s\x1a", cmd2,
|
||||
number[0] == '+' ? strlen(number) - 1 : strlen(number),
|
||||
addr, pid, dcs, vp, strlen(text), sept);
|
||||
snprintf(buf1, len1, "%s%zu", cmd1, (len2 - 1) / 2);
|
||||
free(addr);
|
||||
free(sept);
|
||||
ret = _gsm_queue_full_mode(gsm, GSM_PRIORITY_NORMAL, buf1,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL, GSM_MODE_PDU);
|
||||
/* FIXME race condition if something urgent is queued */
|
||||
ret |= _gsm_queue_full_mode(gsm, GSM_PRIORITY_NORMAL, buf2,
|
||||
GSM_ERROR_MESSAGE_SEND_FAILED, NULL, GSM_MODE_COMMAND);
|
||||
free(buf1);
|
||||
free(buf2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char * _number_to_address(char const * number)
|
||||
{
|
||||
char * buf;
|
||||
size_t len;
|
||||
size_t i;
|
||||
|
||||
len = 2 + strlen(number) + 2;
|
||||
if((buf = malloc(len)) == NULL)
|
||||
return NULL;
|
||||
snprintf(buf, len, "%02X", (number[0] == '+') ? 145 : 129);
|
||||
if(number[0] == '+')
|
||||
number++;
|
||||
for(i = 2; i < len; i+=2)
|
||||
{
|
||||
if(number[i - 2] == '\0')
|
||||
break;
|
||||
buf[i] = number[i - 1];
|
||||
buf[i + 1] = number[i - 2];
|
||||
if(number[i - 1] == '\0')
|
||||
{
|
||||
buf[i] = 'F';
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf[i] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* this function is heavily inspired from gsmd, (c) 2007 OpenMoko, Inc. */
|
||||
static char * _text_to_sept(char const * text)
|
||||
{
|
||||
char const tab[] = "0123456789ABCDEF";
|
||||
unsigned char const * t = (unsigned char const *)text;
|
||||
char * buf;
|
||||
size_t len;
|
||||
char * p;
|
||||
size_t i;
|
||||
unsigned char ch1;
|
||||
unsigned char ch2;
|
||||
int shift = 0;
|
||||
|
||||
len = strlen(text);
|
||||
if((buf = malloc(len + 1)) == NULL)
|
||||
return NULL;
|
||||
p = buf;
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
ch1 = t[i] & 0x7f;
|
||||
ch1 = (ch1 >> shift);
|
||||
ch2 = t[i + 1] & 0x7f;
|
||||
ch2 = ch2 << (7 - shift);
|
||||
ch1 = ch1 | ch2;
|
||||
*(p++) = tab[(ch1 & 0xf0) >> 4];
|
||||
*(p++) = tab[ch1 & 0x0f];
|
||||
if(++shift == 7)
|
||||
{
|
||||
shift = 0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_modem_set_echo */
|
||||
static int _gsm_modem_set_echo(GSM * gsm, gboolean echo)
|
||||
{
|
||||
char cmd[] = "ATE?";
|
||||
|
||||
cmd[3] = echo ? '1' : '0';
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_HIGH, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -883,8 +1062,7 @@ static int _gsm_modem_set_message_format(GSM * gsm, GSMMessageFormat format)
|
|||
return 1;
|
||||
}
|
||||
cmd[8] = format + '0';
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -904,8 +1082,7 @@ static int _gsm_modem_set_operator_format(GSM * gsm, GSMOperatorFormat format)
|
|||
}
|
||||
cmd[8] = GSM_OPERATOR_MODE_SET_FORMAT + '0';
|
||||
cmd[10] = format + '0';
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -926,8 +1103,7 @@ static int _gsm_modem_set_operator_mode(GSM * gsm, GSMOperatorMode mode)
|
|||
return 1;
|
||||
}
|
||||
cmd[8] = mode + '0';
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -947,12 +1123,12 @@ static int _gsm_modem_set_registration_report(GSM * gsm,
|
|||
return 1;
|
||||
}
|
||||
cmd[8] = report + '0';
|
||||
return _gsm_queue_command(gsm, GSM_PRIORITY_NORMAL, cmd,
|
||||
GSM_ERROR_UNKNOWN, NULL);
|
||||
return (_gsm_queue(gsm, cmd) != NULL) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_parse */
|
||||
static int _parse_pdu(GSM * gsm);
|
||||
static int _parse_do(GSM * gsm);
|
||||
|
||||
static int _gsm_parse(GSM * gsm)
|
||||
|
@ -981,9 +1157,30 @@ static int _gsm_parse(GSM * gsm)
|
|||
gsm->rd_buf = p; /* we can ignore errors */
|
||||
i = 0;
|
||||
}
|
||||
if(gsm->mode == GSM_MODE_PDU)
|
||||
return _parse_pdu(gsm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _parse_pdu(GSM * gsm)
|
||||
{
|
||||
size_t i = 0;
|
||||
char * p;
|
||||
|
||||
if(gsm->rd_buf_cnt < 2)
|
||||
return 0;
|
||||
if(gsm->rd_buf[i++] == '>' && gsm->rd_buf[i++] == ' ')
|
||||
{
|
||||
_gsm_queue_pop(gsm);
|
||||
_gsm_queue_push(gsm);
|
||||
}
|
||||
gsm->rd_buf_cnt -= i;
|
||||
memmove(gsm->rd_buf, &gsm->rd_buf[i], gsm->rd_buf_cnt);
|
||||
if((p = realloc(gsm->rd_buf, gsm->rd_buf_cnt)) != NULL)
|
||||
gsm->rd_buf = p; /* we can ignore errors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _parse_do(GSM * gsm)
|
||||
{
|
||||
gboolean answered = FALSE;
|
||||
|
@ -1057,40 +1254,64 @@ static int _gsm_parse_line(GSM * gsm, char const * line, gboolean * answered)
|
|||
|
||||
|
||||
/* queue management */
|
||||
/* gsm_queue_command */
|
||||
static int _gsm_queue_command(GSM * gsm, GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback)
|
||||
/* gsm_queue */
|
||||
static GSMCommand * _gsm_queue(GSM * gsm, char const * command)
|
||||
{
|
||||
GSMCommand * gsmc;
|
||||
|
||||
if(command == NULL || command[0] == '\0')
|
||||
return NULL;
|
||||
if((gsmc = _gsm_command_new(command)) == NULL)
|
||||
return NULL;
|
||||
if(_gsm_queue_command(gsm, gsmc) == 0)
|
||||
return gsmc;
|
||||
_gsm_command_delete(gsmc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_queue_command */
|
||||
static int _gsm_queue_command(GSM * gsm, GSMCommand * command)
|
||||
{
|
||||
GSMPriority priority;
|
||||
GSList * l;
|
||||
GSMCommand * p;
|
||||
|
||||
if(command == NULL || command[0] == '\0')
|
||||
return 1;
|
||||
if((gsmc = _gsm_command_new(priority, command, error, callback))
|
||||
== NULL)
|
||||
if(command == NULL)
|
||||
return 1;
|
||||
priority = _gsm_command_get_priority(command);
|
||||
for(l = gsm->queue; l != NULL; l = l->next)
|
||||
{
|
||||
p = l->data;
|
||||
if(p->priority < priority)
|
||||
if(_gsm_command_get_priority(p) < priority)
|
||||
break;
|
||||
}
|
||||
if(l != NULL)
|
||||
gsm->queue = g_slist_insert_before(gsm->queue, l, gsmc);
|
||||
gsm->queue = g_slist_insert_before(gsm->queue, l, command);
|
||||
else if(gsm->queue == NULL && gsm->mode == GSM_MODE_COMMAND)
|
||||
{
|
||||
gsm->queue = g_slist_append(gsm->queue, gsmc);
|
||||
gsm->queue = g_slist_append(gsm->queue, command);
|
||||
_gsm_queue_push(gsm);
|
||||
}
|
||||
else if(gsm->mode == GSM_MODE_INIT && gsm->wr_source == 0)
|
||||
{
|
||||
gsm->queue = g_slist_append(gsm->queue, gsmc);
|
||||
gsm->queue = g_slist_append(gsm->queue, command);
|
||||
_gsm_queue_push(gsm);
|
||||
}
|
||||
else
|
||||
gsm->queue = g_slist_append(gsm->queue, gsmc);
|
||||
gsm->queue = g_slist_append(gsm->queue, command);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_queue_error */
|
||||
static int _gsm_queue_error(GSM * gsm, char const * command, GSMError error)
|
||||
{
|
||||
GSMCommand * gsmc;
|
||||
|
||||
if((gsmc = _gsm_queue(gsm, command)) == NULL)
|
||||
return 1;
|
||||
_gsm_command_set_error(gsmc, error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1123,6 +1344,38 @@ static void _gsm_queue_flush(GSM * gsm)
|
|||
}
|
||||
|
||||
|
||||
/* gsm_queue_full */
|
||||
static int _gsm_queue_full(GSM * gsm, GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback)
|
||||
{
|
||||
return _gsm_queue_full_mode(gsm, priority, command, error, callback,
|
||||
GSM_MODE_COMMAND);
|
||||
}
|
||||
|
||||
|
||||
/* gsm_queue_full_mode */
|
||||
static int _gsm_queue_full_mode(GSM * gsm, GSMPriority priority,
|
||||
char const * command, GSMError error,
|
||||
GSMCommandCallback callback, GSMMode mode)
|
||||
{
|
||||
GSMCommand * gsmc;
|
||||
|
||||
if(command == NULL || command[0] == '\0')
|
||||
return 1;
|
||||
if((gsmc = _gsm_command_new(command)) == NULL)
|
||||
return 1;
|
||||
_gsm_command_set_priority(gsmc, priority);
|
||||
_gsm_command_set_error(gsmc, error);
|
||||
_gsm_command_set_callback(gsmc, callback);
|
||||
_gsm_command_set_mode(gsmc, mode);
|
||||
if(_gsm_queue_command(gsm, gsmc) == 0)
|
||||
return 0;
|
||||
_gsm_command_delete(gsmc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* gsm_queue_pop */
|
||||
static void _gsm_queue_pop(GSM * gsm)
|
||||
{
|
||||
|
@ -1189,6 +1442,30 @@ static int _gsm_trigger_cme_error(GSM * gsm, char const * result)
|
|||
}
|
||||
|
||||
|
||||
/* gsm_trigger_cms_error */
|
||||
static int _gsm_trigger_cms_error(GSM * gsm, char const * result)
|
||||
{
|
||||
int code;
|
||||
char * p;
|
||||
size_t i;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, result);
|
||||
#endif
|
||||
code = strtol(result, &p, 10);
|
||||
if(result[0] == '\0' || *p != '\0')
|
||||
return 1;
|
||||
for(i = 0; _gsm_cms_errors[i].error != NULL; i++)
|
||||
if(_gsm_cms_errors[i].code == code)
|
||||
break;
|
||||
if(_gsm_cms_errors[i].error == NULL)
|
||||
return 1;
|
||||
/* FIXME implement errors */
|
||||
return _gsm_event(gsm, GSM_EVENT_TYPE_ERROR, GSM_ERROR_UNKNOWN,
|
||||
_(_gsm_cms_errors[i].error));
|
||||
}
|
||||
|
||||
|
||||
/* gsm_trigger_cmgl */
|
||||
static int _gsm_trigger_cmgl(GSM * gsm, char const * result)
|
||||
{
|
||||
|
@ -1475,6 +1752,7 @@ static gboolean _on_watch_can_write(GIOChannel * source, GIOCondition condition,
|
|||
GError * error = NULL;
|
||||
GIOStatus status;
|
||||
char * p;
|
||||
GSMCommand * gsmc;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: %s() cnt=%zu\n", __func__, gsm->wr_buf_cnt);
|
||||
|
@ -1512,5 +1790,7 @@ static gboolean _on_watch_can_write(GIOChannel * source, GIOCondition condition,
|
|||
gsm->wr_source = 0;
|
||||
if(gsm->mode == GSM_MODE_INIT)
|
||||
_gsm_queue_pop(gsm);
|
||||
if(gsm->queue != NULL && (gsmc = gsm->queue->data) != NULL)
|
||||
gsm->mode = _gsm_command_get_mode(gsmc);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user