summaryrefslogtreecommitdiff
path: root/src/gsmd/usock.c
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/usock.c
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/usock.c')
-rw-r--r--src/gsmd/usock.c59
1 files changed, 50 insertions, 9 deletions
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;
personal git repositories of Harald Welte. Your mileage may vary