summaryrefslogtreecommitdiff
path: root/src/gsmd
diff options
context:
space:
mode:
authorerin_yueh <erin_yueh@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-12-17 09:31:02 +0000
committererin_yueh <erin_yueh@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-12-17 09:31:02 +0000
commitcbbf4601211669ededac8d41d6adaec277af3e3b (patch)
tree4a89c2808f5d40f09e7d0cafd5749e3d89915c71 /src/gsmd
parente4fa3bc9cd52873af5cd1b3382b065778c7ebc3e (diff)
gsmd: conference call support (Sean Chiang)
git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@3657 99fdad57-331a-0410-800a-d7fa5415bdb3
Diffstat (limited to 'src/gsmd')
-rw-r--r--src/gsmd/ext_response.c18
-rw-r--r--src/gsmd/gsmd.c2
-rw-r--r--src/gsmd/unsolicited.c64
-rw-r--r--src/gsmd/usock.c56
4 files changed, 114 insertions, 26 deletions
diff --git a/src/gsmd/ext_response.c b/src/gsmd/ext_response.c
index 37edf59..f2a94a7 100644
--- a/src/gsmd/ext_response.c
+++ b/src/gsmd/ext_response.c
@@ -109,16 +109,16 @@ struct gsm_extrsp *extrsp_parse(const void *ctx, const char *input)
}
break;
case TOKEN_NUMERIC:
- if (isdigit(*cur)) {
- *cur_buf = *cur;
- cur_buf++;
- }
-
- if (*cur == ',' || *(cur+1) == '\0') {
+ if (*cur == ',') {
/* end of number */
cur_token->u.numeric = atoi(buf);
er->num_tokens++;
state = IDLE;
+ } else if (isdigit(*cur)) {
+ *cur_buf = *cur;
+ cur_buf++;
+ } else {
+ /* ERORR */
}
break;
case TOKEN_STRING:
@@ -170,6 +170,12 @@ struct gsm_extrsp *extrsp_parse(const void *ctx, const char *input)
cur++;
}
+ if (state == TOKEN_NUMERIC) {
+ /* end of number */
+ cur_token->u.numeric = atoi(buf);
+ er->num_tokens++;
+ }
+
//extrsp_dump(er);
return er;
}
diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c
index ce8ec7e..53b43a8 100644
--- a/src/gsmd/gsmd.c
+++ b/src/gsmd/gsmd.c
@@ -171,6 +171,8 @@ static int gsmd_initsettings2(struct gsmd *gsmd)
rc |= gsmd_simplecmd(gsmd, "AT+CLIP=1");
/* use +COLP: to indicate COLP */
rc |= gsmd_simplecmd(gsmd, "AT+COLP=1");
+ /* use +CCWA: to indicate waiting call */
+ rc |= gsmd_simplecmd(gsmd, "AT+CCWA=1,1");
/* configure message format as PDU mode*/
/* FIXME: TEXT mode support!! */
rc |= gsmd_simplecmd(gsmd, "AT+CMGF=0");
diff --git a/src/gsmd/unsolicited.c b/src/gsmd/unsolicited.c
index 6e96b35..8c99183 100644
--- a/src/gsmd/unsolicited.c
+++ b/src/gsmd/unsolicited.c
@@ -253,33 +253,57 @@ static int creg_parse(char *buf, int len, const char *param,
static int ccwa_parse(char *buf, int len, const char *param,
struct gsmd *gsmd)
{
- const char *token;
- unsigned int type;
+ struct gsmd_evt_auxdata *aux;
+ struct gsm_extrsp *er;
struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_CALL_WAIT,
- sizeof(struct gsmd_addr));
- struct gsmd_addr *gaddr;
-
+ sizeof(struct gsmd_evt_auxdata));
+
if (!ucmd)
return -ENOMEM;
- gaddr = (struct gsmd_addr *) ucmd->buf;
- memset(gaddr, 0, sizeof(*gaddr));
+ aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+ er = extrsp_parse(gsmd_tallocs, param);
- /* parse address (phone number) */
- token = strtok(buf, ",");
- if (!token)
- return -EINVAL;
- strncpy(gaddr->number, token, GSMD_ADDR_MAXLEN);
+ if ( !er )
+ return -ENOMEM;
- /* parse type */
- token = strtok(NULL, ",");
- if (!token)
+ if ( er->num_tokens == 5 &&
+ er->tokens[0].type == GSMD_ECMD_RTT_STRING &&
+ er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC &&
+ er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC &&
+ er->tokens[3].type == GSMD_ECMD_RTT_EMPTY &&
+ er->tokens[4].type == GSMD_ECMD_RTT_NUMERIC ) {
+ /*
+ * <number>,<type>,<class>,[<alpha>][,<CLI validity>]
+ */
+
+ strcpy(aux->u.ccwa.addr.number, er->tokens[0].u.string);
+ aux->u.ccwa.addr.type = er->tokens[1].u.numeric;
+ aux->u.ccwa.classx = er->tokens[2].u.numeric;
+ aux->u.ccwa.alpha[0] = '\0';
+ aux->u.ccwa.cli = er->tokens[4].u.numeric;
+ }
+ else if ( er->num_tokens == 5 &&
+ er->tokens[0].type == GSMD_ECMD_RTT_STRING &&
+ er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC &&
+ er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC &&
+ er->tokens[3].type == GSMD_ECMD_RTT_STRING &&
+ er->tokens[4].type == GSMD_ECMD_RTT_NUMERIC ) {
+ /*
+ * <number>,<type>,<class>,[<alpha>][,<CLI validity>]
+ */
+
+ strcpy(aux->u.ccwa.addr.number, er->tokens[0].u.string);
+ aux->u.ccwa.addr.type = er->tokens[1].u.numeric;
+ aux->u.ccwa.classx = er->tokens[2].u.numeric;
+ strcpy(aux->u.ccwa.alpha, er->tokens[3].u.string);
+ aux->u.ccwa.cli = er->tokens[4].u.numeric;
+ }
+ else {
+ DEBUGP("Invalid Input : Parse error\n");
return -EINVAL;
- type = atoi(token) & 0xff;
- gaddr->type = type;
-
- /* FIXME: parse class */
- token = strtok(NULL, ",");
+ }
return usock_evt_send(gsmd, ucmd, GSMD_EVT_CALL_WAIT);
}
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 0a4acd7..80f2e01 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -200,6 +200,23 @@ static int voicecall_get_stat_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
cmd->id, sizeof(gcs), &gcs);
}
+static int voicecall_ctrl_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ int ret = 0;
+
+ DEBUGP("resp: %s\n", resp);
+
+ if ( !strncmp(resp, "+CME", 4) ) {
+ /* +CME ERROR: <err> */
+ DEBUGP("+CME error\n");
+ ret = atoi(strpbrk(resp, "0123456789"));
+ }
+
+ return gsmd_ucmd_submit(gu, GSMD_MSG_VOICECALL, GSMD_VOICECALL_CTRL,
+ cmd->id, sizeof(ret), &ret);
+}
+
static int usock_ringing_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
@@ -217,6 +234,7 @@ 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;
+ struct gsmd_call_ctrl *gcc;
int atcmd_len;
switch (gph->msg_subtype) {
@@ -274,6 +292,44 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
if (!cmd)
return -ENOMEM;
break;
+ case GSMD_VOICECALL_CTRL:
+ if (len < sizeof(*gph) + sizeof(*gcc))
+ return -EINVAL;
+
+ gcc = (struct gsmd_call_ctrl *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = 1 + strlen("AT+CHLD=") + 2;
+ cmd = atcmd_fill("AT+CHLD=", atcmd_len, &voicecall_ctrl_cb,
+ gu, gph->id, NULL);
+ if (!cmd)
+ return -ENOMEM;
+
+ switch (gcc->proc) {
+ case GSMD_CALL_CTRL_R_HLDS:
+ case GSMD_CALL_CTRL_UDUB:
+ sprintf(cmd->buf, "AT+CHLD=%d", 0);
+ break;
+ case GSMD_CALL_CTRL_R_ACTS_A_HLD_WAIT:
+ sprintf(cmd->buf, "AT+CHLD=%d", 1);
+ break;
+ case GSMD_CALL_CTRL_R_ACT_X:
+ sprintf(cmd->buf, "AT+CHLD=%d%d", 1, gcc->idx);
+ break;
+ case GSMD_CALL_CTRL_H_ACTS_A_HLD_WAIT:
+ sprintf(cmd->buf, "AT+CHLD=%d", 2);
+ break;
+ case GSMD_CALL_CTRL_H_ACTS_EXCEPT_X:
+ sprintf(cmd->buf, "AT+CHLD=%d%d", 2, gcc->idx);
+ break;
+ case GSMD_CALL_CTRL_M_HELD:
+ sprintf(cmd->buf, "AT+CHLD=%d", 3);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ break;
+
default:
return -EINVAL;
}
personal git repositories of Harald Welte. Your mileage may vary