From a04e6effed0b81ec7495df2a1448484645b20cc5 Mon Sep 17 00:00:00 2001 From: laforge Date: Fri, 12 Jan 2007 23:57:33 +0000 Subject: - 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 --- src/gsmd/usock.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 9 deletions(-) (limited to 'src/gsmd/usock.c') 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 #include #include +#include #include #include @@ -14,6 +15,15 @@ #include #include #include +#include + +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; -- cgit v1.2.3