From c30754e2f07d987fa60950bad385261f1144471e Mon Sep 17 00:00:00 2001 From: tick Date: Tue, 4 Dec 2007 07:22:17 +0000 Subject: gsmd: Provide Current Call status (sean_chiang) git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@3557 99fdad57-331a-0410-800a-d7fa5415bdb3 --- include/gsmd/usock.h | 51 +++++++++++++++++++++ include/libgsmd/voicecall.h | 3 ++ src/gsmd/usock.c | 98 +++++++++++++++++++++++++++++++++++++++-- src/libgsmd/libgsmd_voicecall.c | 5 +++ src/util/shell.c | 37 ++++++++++++++++ 5 files changed, 191 insertions(+), 3 deletions(-) diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h index 4f1da7a..162599a 100644 --- a/include/gsmd/usock.h +++ b/include/gsmd/usock.h @@ -41,6 +41,44 @@ enum gsmd_msg_voicecall_type { GSMD_VOICECALL_DTMF = 4, GSMD_VOICECALL_VOL_SET = 5, GSMD_VOICECALL_VOL_GET = 6, + GSMD_VOICECALL_GET_STAT = 7, +}; + + +/* call direction from 3GPP TS 07.07, Clause 7.17 */ +enum gsmd_call_dire { + GSMD_CALL_DIRE_MO = 0, + GSMD_CALL_DIRE_MT = 1, +}; + +/* call state from 3GPP TS 07.07, Clause 7.17 */ +enum gsmd_call_stat { + GSMD_CALL_STAT_ACTIVE = 0, + GSMD_CALL_STAT_HELD = 1, + GSMD_CALL_STAT_DIALING = 2, + GSMD_CALL_STAT_ALERTING = 3, + GSMD_CALL_STAT_INCOMING = 4, + GSMD_CALL_STAT_WAITING = 5, +}; + +/* call mode from 3GPP TS 07.07, Clause 7.17 */ +enum gsmd_call_mode { + GSMD_CALL_MODE_VOICE = 0, + GSMD_CALL_MODE_DATA = 1, + GSMD_CALL_MODE_FAX = 2, + GSMD_CALL_MODE_VOICE_DATA = 3, + GSMD_CALL_MODE_VOICE_DATA_ALT = 4, + GSMD_CALL_MODE_VOICE_FAX_ALT = 5, + GSMD_CALL_MODE_DATA_VOICE = 6, + GSMD_CALL_MODE_DATA_VOICE_ALT = 7, + GSMD_CALL_MODE_FAX_VOICE_ALT = 8, + GSMD_CALL_MODE_UNKNOWN = 9, +}; + +/* multiparty(conference) from 3GPP TS 07.07, Clause 7.17 */ +enum gsmd_call_mpty { + GSMD_CALL_MPTY_NO = 0, + GSMD_CALL_MPTY_YES = 1, }; /* Handset / MT related commands */ @@ -308,6 +346,19 @@ struct gsmd_voicemail { struct gsmd_addr addr; } __attribute__ ((packed)); +/* call status from 3GPP TS 07.07 clause 07.17 */ +struct gsmd_call_status { + int8_t idx; + u_int8_t dir; + u_int8_t stat; + u_int8_t mode; + u_int8_t mpty; + char number[GSMD_ADDR_MAXLEN+1]; + u_int8_t type; + char alpha[8+1]; + int is_last; +} __attribute__ ((packed)); + #define GSMD_PIN_MAXLEN 8 struct gsmd_pin { enum gsmd_pin_type type; diff --git a/include/libgsmd/voicecall.h b/include/libgsmd/voicecall.h index 4141283..2d9609c 100644 --- a/include/libgsmd/voicecall.h +++ b/include/libgsmd/voicecall.h @@ -18,4 +18,7 @@ extern int lgsm_voice_hangup(struct lgsm_handle *lh); /* Send DTMF character during voice call */ extern int lgsm_voice_dtmf(struct lgsm_handle *lh, char dtmf_char); +/* Get call status */ +extern int lgsm_voice_get_status(struct lgsm_handle *lh); + #endif diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c index 128a83f..b16aff5 100644 --- a/src/gsmd/usock.c +++ b/src/gsmd/usock.c @@ -114,6 +114,92 @@ static int usock_rcv_event(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int l gu->subscriptions = *evtmask; } +static int voicecall_get_stat_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) +{ + struct gsmd_user *gu = ctx; + struct gsmd_call_status gcs; + struct gsm_extrsp *er; + + DEBUGP("resp: %s\n", resp); + + er = extrsp_parse(cmd, resp); + + if ( !er ) + return -ENOMEM; + + gcs.is_last = (cmd->ret == 0 || cmd->ret == 4)? 1:0; + + if ( !strncmp(resp, "OK", 2) ) { + /* No existing call */ + gcs.idx = 0; + } + else if ( !strncmp(resp, "+CME", 4) ) { + /* +CME ERROR: */ + DEBUGP("+CME error\n"); + gcs.idx = 0 - atoi(strpbrk(resp, "0123456789")); + } + else if ( er->num_tokens == 7 && + er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[3].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[4].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[5].type == GSMD_ECMD_RTT_STRING && + er->tokens[6].type == GSMD_ECMD_RTT_NUMERIC ) { + /* + * [+CLCC: ,,,,[, + * ,[,]] + * [+CLCC: ,,,,[, + * ,[,]] + * [...]]] + */ + + gcs.idx = er->tokens[0].u.numeric; + gcs.dir = er->tokens[1].u.numeric; + gcs.stat = er->tokens[2].u.numeric; + gcs.mode = er->tokens[3].u.numeric; + gcs.mpty = er->tokens[4].u.numeric; + strcpy(gcs.number, er->tokens[5].u.string); + gcs.type = er->tokens[6].u.numeric; + } + else if ( er->num_tokens == 8 && + er->tokens[0].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[1].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[2].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[3].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[4].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[5].type == GSMD_ECMD_RTT_STRING && + er->tokens[6].type == GSMD_ECMD_RTT_NUMERIC && + er->tokens[7].type == GSMD_ECMD_RTT_STRING ) { + + /* + * [+CLCC: ,,,,[, + * ,[,]] + * [+CLCC: ,,,,[, + * ,[,]] + * [...]]] + */ + + gcs.idx = er->tokens[0].u.numeric; + gcs.dir = er->tokens[1].u.numeric; + gcs.stat = er->tokens[2].u.numeric; + gcs.mode = er->tokens[3].u.numeric; + gcs.mpty = er->tokens[4].u.numeric; + strcpy(gcs.number, er->tokens[5].u.string); + gcs.type = er->tokens[6].u.numeric; + strncpy(gcs.alpha, er->tokens[7].u.string, 8+1); + } + else { + DEBUGP("Invalid Input : Parse error\n"); + return -EINVAL; + } + + talloc_free(er); + + return gsmd_ucmd_submit(gu, GSMD_MSG_VOICECALL, GSMD_VOICECALL_GET_STAT, + cmd->id, sizeof(gcs), &gcs); +} + static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len) { @@ -121,7 +207,7 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, struct gsmd_addr *ga; struct gsmd_dtmf *gd; int atcmd_len; - + switch (gph->msg_subtype) { case GSMD_VOICECALL_DIAL: if (len < sizeof(*gph) + sizeof(*ga)) @@ -168,6 +254,12 @@ static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, sprintf(cmd->buf, "AT+VTS=%c;", gd->dtmf[0]); break; + case GSMD_VOICECALL_GET_STAT: + cmd = atcmd_fill("AT+CLCC", 7+1, &voicecall_get_stat_cb, + gu, gph->id, NULL); + if (!cmd) + return -ENOMEM; + break; default: return -EINVAL; } @@ -731,7 +823,7 @@ static int phonebook_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) gp.index = 0; } else if ( !strncmp(resp, "+CME", 4) ) { - DEBUGP("== +CME error\n"); + DEBUGP("+CME error\n"); /* +CME ERROR: 21 */ gp.index = 0 - atoi(strpbrk(resp, "0123456789")); } @@ -782,7 +874,7 @@ static int phonebook_readrg_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp) gps.pb.index = 0; } else if ( !strncmp(resp, "+CME", 4) ) { - DEBUGP("== +CME error\n"); + DEBUGP("+CME error\n"); /* +CME ERROR: 21 */ gps.pb.index = 0 - atoi(strpbrk(resp, "0123456789")); } diff --git a/src/libgsmd/libgsmd_voicecall.c b/src/libgsmd/libgsmd_voicecall.c index d78fb3d..214ae0c 100644 --- a/src/libgsmd/libgsmd_voicecall.c +++ b/src/libgsmd/libgsmd_voicecall.c @@ -95,3 +95,8 @@ int lgsm_voice_volume_set(struct lgsm_handle *lh, int volume) /* FIXME: we need to pass along the parameter */ return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_VOL_SET); } + +int lgsm_voice_get_status(struct lgsm_handle *lh) +{ + return lgsm_send_simple(lh, GSMD_MSG_VOICECALL, GSMD_VOICECALL_GET_STAT); +} diff --git a/src/util/shell.c b/src/util/shell.c index 103e161..12914d8 100644 --- a/src/util/shell.c +++ b/src/util/shell.c @@ -387,6 +387,37 @@ static int pin_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) return 0; } +static int call_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh) +{ + struct gsmd_call_status *gcs; + + switch (gmh->msg_subtype) { + case GSMD_VOICECALL_GET_STAT: + gcs = (struct gsmd_call_status*) ((char *)gmh + sizeof(*gmh)); + + if (gcs->idx > 0) + printf("%d, %d, %d, %d, %d, %s, %d\n", + gcs->idx, gcs->dir, + gcs->stat, gcs->mode, + gcs->mpty, gcs->number, + gcs->type); + else if (gcs->idx < 0) + /* If index < 0, error happens */ + printf("+CME ERROR %d\n", (0-(gcs->idx))); + else + /* No existing call */ + printf("Doesn't exist\n"); + + if (gcs->is_last) + pending_responses --; + break; + default: + return -EINVAL; + } + pending_responses --; + return 0; +} + static const struct msghandler_s { int type; lgsm_msg_handler *fn; @@ -397,6 +428,7 @@ static const struct msghandler_s { { GSMD_MSG_NETWORK, net_msghandler }, { GSMD_MSG_PHONE, phone_msghandler }, { GSMD_MSG_PIN, pin_msghandler }, + { GSMD_MSG_VOICECALL, call_msghandler }, { 0, 0 } }; @@ -437,6 +469,7 @@ static int shell_help(void) "\tsc\tSMS Show Service Centre\n" "\tsC\tSMS Set Service Centre (sC=number)\n" "\tim\tGet imsi\n" + "\tcs\tGet Call status\n" "\tq\tQuit\n" ); } @@ -724,6 +757,10 @@ int shell_main(struct lgsm_handle *lgsmh, int sync) printf("Modem Power Off\n"); lgsm_modem_power(lgsmh, 0); pending_responses ++; + } else if ( !strncmp(buf, "cs", 2)) { + printf("List current call status\n"); + lgsm_voice_get_status(lgsmh); + pending_responses ++; } else { printf("Unknown command `%s'\n", buf); } -- cgit v1.2.3