summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gsmd/usock.h51
-rw-r--r--include/libgsmd/voicecall.h3
-rw-r--r--src/gsmd/usock.c98
-rw-r--r--src/libgsmd/libgsmd_voicecall.c5
-rw-r--r--src/util/shell.c37
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: <err> */
+ 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: <id1>,<dir>,<stat>,<mode>,<mpty>[,
+ * <number>,<type>[,<alpha>]]
+ * [<CR><LF>+CLCC: <id2>,<dir>,<stat>,<mode>,<mpty>[,
+ * <number>,<type>[,<alpha>]]
+ * [...]]]
+ */
+
+ 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: <id1>,<dir>,<stat>,<mode>,<mpty>[,
+ * <number>,<type>[,<alpha>]]
+ * [<CR><LF>+CLCC: <id2>,<dir>,<stat>,<mode>,<mpty>[,
+ * <number>,<type>[,<alpha>]]
+ * [...]]]
+ */
+
+ 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);
}
personal git repositories of Harald Welte. Your mileage may vary