summaryrefslogtreecommitdiff
path: root/src/gsmd
diff options
context:
space:
mode:
authorlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-01-12 23:57:33 +0000
committerlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-01-12 23:57:33 +0000
commita04e6effed0b81ec7495df2a1448484645b20cc5 (patch)
tree6292af769d08022e68cd183358ccc78c6a27238c /src/gsmd
parent496d202f517dbecc1be4e1afc6782c0e3dc48373 (diff)
- use talloc (of samba project) to debug memory allocations and simplify code
- introduce new ucmd_alloc() function - add DTMF support to gsmd, libgsmd and gsmd-util - fix crash of libgsmd when events don't have handlers registered - implement call progress for TI modem - split modem init string in separate commands to fit our parser git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@544 99fdad57-331a-0410-800a-d7fa5415bdb3
Diffstat (limited to 'src/gsmd')
-rw-r--r--src/gsmd/atcmd.c58
-rw-r--r--src/gsmd/gsmd.c45
-rw-r--r--src/gsmd/sms_cb.c3
-rw-r--r--src/gsmd/unsolicited.c35
-rw-r--r--src/gsmd/usock.c59
-rw-r--r--src/gsmd/vendor_ti.c93
6 files changed, 240 insertions, 53 deletions
diff --git a/src/gsmd/atcmd.c b/src/gsmd/atcmd.c
index 7f95465..c5c0a04 100644
--- a/src/gsmd/atcmd.c
+++ b/src/gsmd/atcmd.c
@@ -14,6 +14,7 @@
#include <gsmd/ts0707.h>
#include <gsmd/gsmd.h>
#include <gsmd/atcmd.h>
+#include <gsmd/talloc.h>
#include <gsmd/unsolicited.h>
/* libgsmd / gsmd AT command interpreter / parser / constructor
@@ -22,6 +23,8 @@
* Written for First International Computer, Inc., Taiwan
*/
+static void *__atcmd_ctx;
+
enum final_result_codes {
GSMD_RESULT_OK = 0,
GSMD_RESULT_ERR = 1,
@@ -153,7 +156,7 @@ static int parse_final_result(const char *res)
static int ml_parse(const char *buf, int len, void *ctx)
{
struct gsmd *g = ctx;
- struct gsmd_atcmd *cmd;
+ struct gsmd_atcmd *cmd = NULL;
int rc = 0, final = 0;
DEBUGP("buf=`%s'(%d)\n", buf, len);
@@ -165,7 +168,9 @@ static int ml_parse(const char *buf, int len, void *ctx)
/* responses come in order, so first response has to be for first
* command we sent, i.e. first entry in list */
- cmd = llist_entry(g->busy_atcmds.next, struct gsmd_atcmd, list);
+ if (!llist_empty(&g->busy_atcmds))
+ cmd = llist_entry(g->busy_atcmds.next,
+ struct gsmd_atcmd, list);
/* we have to differentiate between the following cases:
*
@@ -194,15 +199,16 @@ static int ml_parse(const char *buf, int len, void *ctx)
unsigned long err_nr;
err_nr = strtoul(colon+1, NULL, 10);
DEBUGP("error number %lu\n", err_nr);
- cmd->ret = err_nr;
+ if (cmd)
+ cmd->ret = err_nr;
final = 1;
goto final_cb;
}
- if (strncmp(buf, &cmd->buf[2], colon-buf)) {
+ if (!cmd || strncmp(buf, &cmd->buf[2], colon-buf)) {
/* Assuming Case 'B' */
DEBUGP("extd reply `%s' to cmd `%s', must be "
- "unsolicited\n", buf, &cmd->buf[2]);
+ "unsolicited\n", buf, cmd ? &cmd->buf[2] : "NONE");
colon++;
if (colon > buf+len)
colon = NULL;
@@ -216,19 +222,21 @@ static int ml_parse(const char *buf, int len, void *ctx)
/* contine, not 'B' */
}
- if (cmd->buf[2] != '+') {
- gsmd_log(GSMD_ERROR, "extd reply to non-extd command?\n");
- return -EINVAL;
- }
+ if (cmd) {
+ if (cmd->buf[2] != '+') {
+ gsmd_log(GSMD_ERROR, "extd reply to non-extd command?\n");
+ return -EINVAL;
+ }
- /* if we survive till here, it's a valid extd response
- * to an extended command and thus Case 'A' */
+ /* if we survive till here, it's a valid extd response
+ * to an extended command and thus Case 'A' */
- /* FIXME: solve multi-line responses ! */
- if (cmd->buflen < len)
- len = cmd->buflen;
+ /* FIXME: solve multi-line responses ! */
+ if (cmd->buflen < len)
+ len = cmd->buflen;
- memcpy(cmd->buf, buf, len);
+ memcpy(cmd->buf, buf, len);
+ }
} else {
if (!strcmp(buf, "RING")) {
/* this is the only non-extended unsolicited return
@@ -237,18 +245,20 @@ static int ml_parse(const char *buf, int len, void *ctx)
}
if (!strcmp(buf, "ERROR") ||
- ((g->flags & GSMD_FLAG_V0) && cmd->buf[0] == '4')) {
+ ((g->flags & GSMD_FLAG_V0) && buf[0] == '4')) {
/* Part of Case 'C' */
DEBUGP("unspecified error\n");
- cmd->ret = 4;
+ if (cmd)
+ cmd->ret = 4;
final = 1;
goto final_cb;
}
if (!strncmp(buf, "OK", 2)
- || ((g->flags & GSMD_FLAG_V0) && cmd->buf[0] == '0')) {
+ || ((g->flags & GSMD_FLAG_V0) && buf[0] == '0')) {
/* Part of Case 'C' */
- cmd->ret = 0;
+ if (cmd)
+ cmd->ret = 0;
final = 1;
goto final_cb;
}
@@ -274,8 +284,10 @@ static int ml_parse(const char *buf, int len, void *ctx)
final_cb:
/* if we reach here, the final result code of a command has been reached */
+ if (!cmd)
+ return rc;
- if (cmd->ret != 0)
+ if (cmd && cmd->ret != 0)
generate_event_from_cme(g, cmd->ret);
if (!cmd->cb) {
@@ -292,7 +304,7 @@ final_cb:
if (final) {
/* remove from list of currently executing cmds */
llist_del(&cmd->list);
- free(cmd);
+ talloc_free(cmd);
/* if we're finished with current commands, but still have pending
* commands: we want to WRITE again */
@@ -377,7 +389,7 @@ struct gsmd_atcmd *atcmd_fill(const char *cmd, int rlen,
if (rlen > buflen)
buflen = rlen;
- atcmd = malloc(sizeof(*atcmd)+ buflen);
+ atcmd = talloc_size(__atcmd_ctx, sizeof(*atcmd)+ buflen);
if (!atcmd)
return NULL;
@@ -421,6 +433,8 @@ void atcmd_drain(int fd)
/* init atcmd parser */
int atcmd_init(struct gsmd *g, int sockfd)
{
+ __atcmd_ctx = talloc_named_const(gsmd_tallocs, 1, "atcmds");
+
g->gfd_uart.fd = sockfd;
g->gfd_uart.when = GSMD_FD_READ;
g->gfd_uart.data = g;
diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c
index c56e74c..a16e6b5 100644
--- a/src/gsmd/gsmd.c
+++ b/src/gsmd/gsmd.c
@@ -5,6 +5,7 @@
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
+#include <signal.h>
#define _GNU_SOURCE
#include <getopt.h>
@@ -19,6 +20,7 @@
#include <gsmd/select.h>
#include <gsmd/usock.h>
#include <gsmd/vendorplugin.h>
+#include <gsmd/talloc.h>
static int gsmd_test_atcb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
@@ -40,8 +42,22 @@ int gsmd_initsettings(struct gsmd *gsmd)
{
int rc;
+ /* echo on, verbose */
rc |= gsmd_simplecmd(gsmd, "ATE0V1");
- rc |= gsmd_simplecmd(gsmd, "AT+CRC=1;+CREG=2;+CMEE=1;+CLIP=1;+COLP=1;+CTZR=1;+CFUN=1");
+ /* use +CRING instead of RING */
+ rc |= gsmd_simplecmd(gsmd, "AT+CRC=1");
+ /* enable +CREG: unsolicited response if registration status changes */
+ rc |= gsmd_simplecmd(gsmd, "AT+CREG=2");
+ /* use +CME ERROR: instead of ERROR */
+ rc |= gsmd_simplecmd(gsmd, "AT+CMEE=1");
+ /* use +CLIP: to indicate CLIP */
+ rc |= gsmd_simplecmd(gsmd, "AT+CLIP=1");
+ /* use +COLP: to indicate COLP */
+ rc |= gsmd_simplecmd(gsmd, "AT+COLP=1");
+ /* use +CTZR: to report time zone changes */
+ rc |= gsmd_simplecmd(gsmd, "AT+CTZR=1");
+ /* power on the phone */
+ rc |= gsmd_simplecmd(gsmd, "AT+CFUN=1");
if (gsmd->vendorpl && gsmd->vendorpl->initsettings)
return gsmd->vendorpl->initsettings(gsmd);
@@ -108,6 +124,7 @@ static struct option opts[] = {
{ "device", 1, NULL, 'p' },
{ "speed", 1, NULL, 's' },
{ "logfile", 1, NULL, 'l' },
+ { "leak-report", 0, NULL, 'L' },
{ 0, 0, 0, 0 }
};
@@ -125,6 +142,20 @@ static void print_help(void)
);
}
+static void sig_handler(int signr)
+{
+ switch (signr) {
+ case SIGTERM:
+ case SIGINT:
+ talloc_report_full(gsmd_tallocs, stderr);
+ exit(0);
+ break;
+ case SIGUSR1:
+ talloc_report_full(gsmd_tallocs, stderr);
+ break;
+ }
+}
+
int main(int argc, char **argv)
{
int fd, argch;
@@ -134,12 +165,22 @@ int main(int argc, char **argv)
char *device = "/dev/ttyUSB0";
char *logfile = "syslog";
+ signal(SIGTERM, sig_handler);
+ signal(SIGINT, sig_handler);
+ signal(SIGSEGV, sig_handler);
+ signal(SIGUSR1, sig_handler);
+
+ gsmd_tallocs = talloc_named_const(NULL, 1, "GSMD");
+
/*FIXME: parse commandline, set daemonize, device, ... */
- while ((argch = getopt_long(argc, argv, "Vdhp:s:l:", opts, NULL)) != -1) {
+ while ((argch = getopt_long(argc, argv, "VLdhp:s:l:", opts, NULL)) != -1) {
switch (argch) {
case 'V':
/* FIXME */
break;
+ case 'L':
+ talloc_enable_leak_report_full();
+ break;
case 'd':
daemonize = 1;
break;
diff --git a/src/gsmd/sms_cb.c b/src/gsmd/sms_cb.c
index 5ca8956..5c62333 100644
--- a/src/gsmd/sms_cb.c
+++ b/src/gsmd/sms_cb.c
@@ -62,8 +62,7 @@ struct gsmd_sms_storage {
static int usock_cpms_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
- struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd) +
- sizeof(struct gsmd_sms_storage));
+ struct gsmd_ucmd *ucmd = ucmd_alloc(sizeof(struct gsmd_sms_storage));
DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
diff --git a/src/gsmd/unsolicited.c b/src/gsmd/unsolicited.c
index 57a4e59..0c12f32 100644
--- a/src/gsmd/unsolicited.c
+++ b/src/gsmd/unsolicited.c
@@ -11,10 +11,11 @@
#include <gsmd/event.h>
#include <gsmd/ts0707.h>
#include <gsmd/unsolicited.h>
+#include <gsmd/talloc.h>
struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int8_t len)
{
- struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+len);
+ struct gsmd_ucmd *ucmd = ucmd_alloc(len);
if (!ucmd)
return NULL;
@@ -29,11 +30,10 @@ struct gsmd_ucmd *usock_build_event(u_int8_t type, u_int8_t subtype, u_int8_t le
static struct gsmd_ucmd *ucmd_copy(const struct gsmd_ucmd *orig)
{
- int size = sizeof(*orig) + orig->hdr.len;
- struct gsmd_ucmd *copy = malloc(size);
+ struct gsmd_ucmd *copy = ucmd_alloc(orig->hdr.len);
if (copy)
- memcpy(copy, orig, size);
+ memcpy(copy, orig, orig->hdr.len);
return copy;
}
@@ -47,17 +47,25 @@ int usock_evt_send(struct gsmd *gsmd, struct gsmd_ucmd *ucmd, u_int32_t evt)
llist_for_each_entry(gu, &gsmd->users, list) {
if (gu->subscriptions & (1 << evt)) {
- struct gsmd_ucmd *cpy = ucmd_copy(ucmd);
- usock_cmd_enqueue(ucmd, gu);
- num_sent++;
- ucmd = cpy;
- if (!ucmd) {
- fprintf(stderr, "can't allocate memory for copy of ucmd\n");
- return num_sent;
+ if (num_sent == 0)
+ usock_cmd_enqueue(ucmd, gu);
+ else {
+ struct gsmd_ucmd *cpy = ucmd_copy(ucmd);
+ if (!cpy) {
+ fprintf(stderr,
+ "can't allocate memory for "
+ "copy of ucmd\n");
+ return num_sent;
+ }
+ usock_cmd_enqueue(cpy, gu);
}
+ num_sent++;
}
}
+ if (num_sent == 0)
+ talloc_free(ucmd);
+
return num_sent;
}
@@ -101,7 +109,7 @@ static int cring_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
aux->u.call.type = GSMD_CALL_FAX;
} else if (!strncmp(param, "GPRS ", 5)) {
/* FIXME: change event type to GPRS */
- free(ucmd);
+ talloc_free(ucmd);
return 0;
}
/* FIXME: parse all the ALT* profiles, Chapter 6.11 */
@@ -322,7 +330,8 @@ int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param)
rc = vpl->unsolicit[i].parse(buf, len, colon, g);
if (rc < 0)
gsmd_log(GSMD_ERROR, "error %d during parse of "
- "unsolicied response `%s'\n", rc, buf);
+ "vendor unsolicied response `%s'\n",
+ rc, buf);
return rc;
}
}
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 42f8099..4f2ba4f 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -3,6 +3,7 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -14,6 +15,15 @@
#include <gsmd/select.h>
#include <gsmd/atcmd.h>
#include <gsmd/usock.h>
+#include <gsmd/talloc.h>
+
+static void *__ucmd_ctx, *__gu_ctx;
+
+struct gsmd_ucmd *ucmd_alloc(int extra_size)
+{
+ return talloc_size(__ucmd_ctx,
+ sizeof(struct gsmd_ucmd) + extra_size);
+}
void usock_cmd_enqueue(struct gsmd_ucmd *ucmd, struct gsmd_user *gu)
{
@@ -31,7 +41,7 @@ static int usock_cmd_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
int rlen = strlen(resp)+1;
- struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+rlen);
+ struct gsmd_ucmd *ucmd = ucmd_alloc(rlen);
DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
@@ -83,6 +93,8 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
{
struct gsmd_atcmd *cmd = NULL;
struct gsmd_addr *ga;
+ struct gsmd_dtmf *gd;
+ int atcmd_len;
switch (gph->msg_subtype) {
case GSMD_VOICECALL_DIAL:
@@ -92,6 +104,8 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
ga->number[GSMD_ADDR_MAXLEN] = '\0';
cmd = atcmd_fill("ATD", 5 + strlen(ga->number),
&usock_cmd_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
sprintf(cmd->buf, "ATD%s;", ga->number);
/* FIXME: number type! */
break;
@@ -101,6 +115,26 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
case GSMD_VOICECALL_ANSWER:
cmd = atcmd_fill("ATA", 4, &usock_cmd_cb, gu, gph->id);
break;
+ case GSMD_VOICECALL_DTMF:
+ if (len < sizeof(*gph) + sizeof(*gd))
+ return -EINVAL;
+
+ gd = (struct gsmd_dtmf *) ((void *)gph + sizeof(*gph));
+ if (len < sizeof(*gph) + sizeof(*gd) + gd->len)
+ return -EINVAL;
+
+ /* FIXME: we don't yet support DTMF of multiple digits */
+ if (gd->len != 1)
+ return -EINVAL;
+
+ atcmd_len = 1 + strlen("AT+VTS=") + (gd->len * 2);
+ cmd = atcmd_fill("AT+VTS=", atcmd_len, &usock_cmd_cb,
+ gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+
+ sprintf(cmd->buf, "AT+VTS=%c;", gd->dtmf[0]);
+ break;
default:
return -EINVAL;
}
@@ -173,11 +207,12 @@ static int network_vmail_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
struct gsmd_voicemail *vmail;
- struct gsmd_ucmd *ucmd = malloc(sizeof(*ucmd)+sizeof(*vmail));
+ struct gsmd_ucmd *ucmd;
char *comma;
DEBUGP("entering(cmd=%p, gu=%p)\n", cmd, gu);
+ ucmd = ucmd_alloc(sizeof(*vmail));
if (!ucmd)
return -ENOMEM;
@@ -218,7 +253,7 @@ static int network_vmail_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
out_free_einval:
gsmd_log(GSMD_ERROR, "can't understand voicemail response\n");
- free(ucmd);
+ talloc_free(ucmd);
return -EINVAL;
}
@@ -227,7 +262,7 @@ static struct gsmd_ucmd *gsmd_ucmd_fill(int len, u_int8_t msg_type, u_int8_t msg
{
struct gsmd_ucmd *ucmd;
- ucmd = malloc(sizeof(*ucmd)+len);
+ ucmd = ucmd_alloc(len);
if (!ucmd)
return NULL;
@@ -256,7 +291,7 @@ static int network_sigq_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
gsq->rssi = atoi(resp);
comma = strchr(resp, ',');
if (!comma) {
- free(ucmd);
+ talloc_free(ucmd);
return -EIO;
}
gsq->ber = atoi(comma+1);
@@ -336,12 +371,14 @@ static int gsmd_usock_user_cb(int fd, unsigned int what, void *data)
/* read data from socket, determine what he wants */
rcvlen = read(fd, buf, sizeof(buf));
if (rcvlen == 0) {
+ DEBUGP("EOF, this client has just vanished\n");
/* EOF, this client has just vanished */
gsmd_unregister_fd(&gu->gfd);
close(fd);
/* destroy whole user structure */
llist_del(&gu->list);
- /* FIXME: delete budy ucmds from finished_ucmds */
+ /* FIXME: delete busy ucmds from finished_ucmds */
+ talloc_free(gu);
return 0;
} else if (rcvlen < 0)
return rcvlen;
@@ -370,8 +407,9 @@ static int gsmd_usock_user_cb(int fd, unsigned int what, void *data)
break;
}
+ DEBUGP("successfully sent cmd %p to user %p, freeing\n", ucmd, gu);
llist_del(&ucmd->list);
- free(ucmd);
+ talloc_free(ucmd);
}
if (llist_empty(&gu->finished_ucmds))
gu->gfd.when &= ~GSMD_FD_WRITE;
@@ -389,7 +427,7 @@ static int gsmd_usock_cb(int fd, unsigned int what, void *data)
/* FIXME: implement this */
if (what & GSMD_FD_READ) {
/* new incoming connection */
- newuser = malloc(sizeof(*newuser));
+ newuser = talloc(__gu_ctx, struct gsmd_user);
if (!newuser)
return -ENOMEM;
@@ -397,7 +435,7 @@ static int gsmd_usock_cb(int fd, unsigned int what, void *data)
if (newuser->gfd.fd < 0) {
DEBUGP("error accepting incoming conn: `%s'\n",
strerror(errno));
- free(newuser);
+ talloc_free(newuser);
}
newuser->gfd.when = GSMD_FD_READ;
newuser->gfd.data = newuser;
@@ -419,6 +457,9 @@ int usock_init(struct gsmd *g)
struct sockaddr_un sun;
int fd, rc;
+ __ucmd_ctx = talloc_named_const(gsmd_tallocs, 1, "ucmd");
+ __gu_ctx = talloc_named_const(gsmd_tallocs, 1, "gsmd_user");
+
fd = socket(PF_UNIX, GSMD_UNIX_SOCKET_TYPE, 0);
if (fd < 0)
return fd;
diff --git a/src/gsmd/vendor_ti.c b/src/gsmd/vendor_ti.c
index 53ca7ed..6ec12c5 100644
--- a/src/gsmd/vendor_ti.c
+++ b/src/gsmd/vendor_ti.c
@@ -43,7 +43,7 @@ ti_setopt(struct gsmd *gh, int optname, const void *optval, int optlen)
#endif
-static int csq_parse(char *buf, int len, char *param,
+static int csq_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
char *tok;
@@ -57,7 +57,7 @@ static int csq_parse(char *buf, int len, char *param,
aux = (struct gsmd_evt_auxdata *) ucmd->buf;
- tok = strtok(param, ",");
+ tok = strtok(buf, ",");
if (!tok)
goto out_free_io;
@@ -81,12 +81,85 @@ out_free_io:
static int cpri_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
-
+ /* FIXME: parse ciphering indication */
}
+/* Call Progress Information */
static int cpi_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
{
+ char *tok;
+ struct gsmd_evt_auxdata *aux;
+ struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
+ GSMD_EVT_OUT_STATUS,
+ sizeof(*aux));
+
+ DEBUGP("entering cpi_parse param=`%s'\n", param);
+ if (!ucmd)
+ return -EINVAL;
+
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ /* Format: cId, msgType, ibt, tch, dir,[mode],[number],[type],[alpha],[cause],line */
+
+ /* call ID */
+ tok = strtok(buf, ",");
+ if (!tok)
+ goto out_free_io;
+ /* message type (layer 3) */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+ aux->u.call_status.prog = atoi(tok);
+
+ /* in-band tones */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ if (*tok == '1')
+ aux->u.call_status.ibt = 1;
+ else
+ aux->u.call_status.ibt = 0;
+
+ /* TCH allocated */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ if (*tok == '1')
+ aux->u.call_status.tch = 1;
+ else
+ aux->u.call_status.tch = 0;
+
+ /* direction */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ switch (*tok) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ aux->u.call_status.dir = (*tok - '0');
+ break;
+ default:
+ break;
+ }
+
+ /* mode */
+ tok = strtok(NULL, ",");
+ if (!tok)
+ goto out_free_io;
+
+ usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_STATUS);
+
+ return 0;
+
+out_free_io:
+ free(ucmd);
+ return -EIO;
}
static const struct gsmd_unsolicit ticalypso_unsolicit[] = {
@@ -114,13 +187,23 @@ static int ticalypso_detect(struct gsmd *g)
static int ticalypso_initsettings(struct gsmd *g)
{
- return gsmd_simplecmd(g, "AT\%CPI=3;\%CPRI=1;\%CSQ=1");
+ int rc;
+ /* enable %CPI: call progress indication */
+ rc = gsmd_simplecmd(g, "AT\%CPI=3");
+ /* enable %CPRI: ciphering indications */
+ rc |= gsmd_simplecmd(g, "AT\%CPRI=1");
+ /* enable %CSQ: signal quality reports */
+ rc |= gsmd_simplecmd(g, "AT\%CSQ=1");
+ /* send unsolicited commands at any time */
+ rc |= gsmd_simplecmd(g, "AT\%CUNS=0");
+
+ return rc;
}
static struct gsmd_vendor_plugin plugin_ticalypso = {
.name = "TI Calypso",
.num_unsolicit = ARRAY_SIZE(ticalypso_unsolicit),
- .unsolicit = &ticalypso_unsolicit,
+ .unsolicit = ticalypso_unsolicit,
.detect = &ticalypso_detect,
.initsettings = &ticalypso_initsettings,
};
personal git repositories of Harald Welte. Your mileage may vary