summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-04-15 09:47:23 +0000
committerlaforge <laforge@99fdad57-331a-0410-800a-d7fa5415bdb3>2007-04-15 09:47:23 +0000
commitf243da86ed3c515740870ce0a817f2e768b420fe (patch)
treeb39801affc667465169392855e942e94fb94f4a3 /src
parent6766b42717e386d505ba5f3f7b4732e88eece54e (diff)
* add (still incomplete) SMS and phonebook support from Sean Chiang
git-svn-id: http://svn.openmoko.org/trunk/src/target/gsm@1765 99fdad57-331a-0410-800a-d7fa5415bdb3
Diffstat (limited to 'src')
-rw-r--r--src/gsmd/gsmd.c7
-rw-r--r--src/gsmd/usock.c429
-rw-r--r--src/libgsmd/Makefile.am2
-rw-r--r--src/libgsmd/libgsmd_phonebook.c146
-rw-r--r--src/libgsmd/libgsmd_sms.c231
-rw-r--r--src/util/shell.c164
6 files changed, 978 insertions, 1 deletions
diff --git a/src/gsmd/gsmd.c b/src/gsmd/gsmd.c
index 8254ae0..e2ecaa7 100644
--- a/src/gsmd/gsmd.c
+++ b/src/gsmd/gsmd.c
@@ -78,6 +78,13 @@ int gsmd_initsettings(struct gsmd *gsmd)
rc |= gsmd_simplecmd(gsmd, "AT+COLP=1");
/* power on the phone */
rc |= gsmd_simplecmd(gsmd, "AT+CFUN=1");
+ /* configure message format as PDU mode*/
+ /* FIXME: TEXT mode support!! */
+ rc |= gsmd_simplecmd(gsmd, "AT+CMGF=0");
+#if 0
+ /* Select TE character set */
+ rc |= gsmd_simplecmd(gsmd, "AT+CSCS=\"UCS2\"");
+#endif
if (gsmd->vendorpl && gsmd->vendorpl->initsettings)
return gsmd->vendorpl->initsettings(gsmd);
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 31292e8..2f678dd 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -412,6 +412,433 @@ static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
return atcmd_submit(gu->gsmd, cmd);
}
+static int sms_list_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_LIST, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ /* FIXME: implementation */
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ /* FIXME: implementation */
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_READ, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_send_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_SEND, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_WRITE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int sms_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_SMS,
+ GSMD_SMS_DELETE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ /* FIXME: TEXT mode support!! */
+ struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_sms_delete *gsd;
+ struct gsmd_sms *gs;
+ struct gsmd_sms_write *gsw;
+ int *stat, *index;
+ int atcmd_len;
+ char buf[1024];
+
+ switch (gph->msg_subtype) {
+ case GSMD_SMS_LIST:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ stat = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *stat);
+
+ atcmd_len = 1 + strlen("AT+CMGL=") + strlen(buf);
+ cmd = atcmd_fill("AT+CMGL=", atcmd_len,
+ &sms_list_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGL=%s", buf);
+ break;
+ case GSMD_SMS_READ:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CMGR=", atcmd_len,
+ &sms_read_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGR=%s", buf);
+ break;
+#if 0
+ case GSMD_SMS_SEND:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(*gs))
+ return -EINVAL;
+ gs = (struct gsmd_sms *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + 1;
+ cmd = atcmd_fill("AT+CMGR=", atcmd_len,
+ &sms_send_cb, gu, gph->id);
+ if (!cmd)GSMD_SMS_WRITE
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGR=%d", index);
+ break;
+ case GSMD_SMS_WRITE:
+ /* FIXME: only support PDU mode!! */
+ if(len < sizeof(*gph) + sizeof(*gsw))
+ return -EINVAL;
+ &index = (int *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + 1;
+ cmd = atcmd_fill("AT+CMGR=", atcmd_len,
+ &sms_write_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGR=%d", index);
+ break;
+#endif
+ case GSMD_SMS_DELETE:
+ if(len < sizeof(*gph) + sizeof(*gsd))
+ return -EINVAL;
+ gsd = (struct gsmd_sms_delete *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d,%d", gsd->index, gsd->delflg);
+
+ atcmd_len = 1 + strlen("AT+CMGR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CMGD=", atcmd_len,
+ &sms_delete_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CMGD=%s", buf);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ gsmd_log(GSMD_DEBUG, "%s\n", cmd->buf);
+ if (cmd)
+ return atcmd_submit(gu->gsmd, cmd);
+ else
+ return 0;
+}
+
+#if 0
+static int phonebook_find_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ /* FIXME: implementation */
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_FIND, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+ return 0;
+}
+
+static int phonebook_read_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_phonebook *gp;
+ struct gsmd_ucmd *ucmd;
+ char *fcomma, *lcomma;
+ char *ptr;
+ /* FIXME: We should check this case "When the entry is empty" */
+ ucmd = gsmd_ucmd_fill(sizeof(*gp), GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_READ, 0);
+
+ if (!ucmd)
+ return -ENOMEM;
+ gp = (struct gsmd_phonebook *) ucmd->buf;
+
+ ptr = strchr(resp, ' ');
+ gp->index = atoi(ptr+1);
+
+ fcomma = strchr(resp, '"');
+ lcomma = strchr(fcomma+1, '"');
+ strncpy(gp->numb, fcomma+1, (lcomma-fcomma-1));
+ gp->numb[(lcomma-fcomma)-1] = '\0';
+
+ gp->type = atoi(lcomma+2);
+
+ ptr = strrchr(resp, ',');
+ fcomma = ptr+1;
+ lcomma = strchr(fcomma+1, '"');
+ strncpy(gp->text, fcomma+1, (lcomma-fcomma-1));
+ gp->text[(lcomma-fcomma)-1] = '\0';
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_readrg_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ /* FIXME: implementation */
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_READRG, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_write_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_WRITE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_delete_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+
+ ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_DELETE, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ strcpy(ucmd->buf, resp);
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ return 0;
+}
+
+static int phonebook_support_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+ struct gsmd_user *gu = ctx;
+ struct gsmd_phonebook_support *gps;
+ struct gsmd_ucmd *ucmd;
+ char *fcomma, *lcomma;
+ char *dash;
+
+ ucmd = gsmd_ucmd_fill(sizeof(*gps), GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_GET_SUPPORT, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ gps = (struct gsmd_phonebook_support *) ucmd->buf;
+
+ dash = strchr(resp, '-');
+ if (!dash) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gps->index = atoi(dash+1);
+
+ fcomma = strchr(resp, ',');
+ if (!fcomma) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gps->nlength = atoi(fcomma+1);
+
+ lcomma = strrchr(resp, ',');
+ if (!lcomma) {
+ talloc_free(ucmd);
+ return -EIO;
+ }
+ gps->tlength = atoi(lcomma+1);
+
+ usock_cmd_enqueue(ucmd, gu);
+ return 0;
+}
+
+static int usock_rcv_phonebook(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
+ int len)
+{
+ struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_phonebook_readrg *gpr;
+ struct gsmd_phonebook *gp;
+ struct gsmd_phonebook_find *gpf;
+ int *index;
+ int atcmd_len;
+ char buf[1024];
+
+ switch (gph->msg_subtype) {
+ case GSMD_PHONEBOOK_FIND:
+ if(len < sizeof(*gph) + sizeof(*gpf))
+ return -EINVAL;
+ gpf = (struct gsmd_phonebook_find *) ((void *)gph + sizeof(*gph));
+
+ atcmd_len = 1 + strlen("AT+CPBF=\"") + strlen(gpf->findtext) + strlen("\"");
+ cmd = atcmd_fill("AT+CPBF=\"", atcmd_len,
+ &phonebook_find_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBF=\"%s\"", gpf->findtext);
+ break;
+ case GSMD_PHONEBOOK_READ:
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBR=", atcmd_len,
+ &phonebook_read_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBR=%d", *index);
+ break;
+ case GSMD_PHONEBOOK_READRG:
+ if(len < sizeof(*gph) + sizeof(*gpr))
+ return -EINVAL;
+ gpr = (struct gsmd_phonebook_readrg *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d,%d", gpr->index1, gpr->index2);
+
+ atcmd_len = 1 + strlen("AT+CPBR=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBR=", atcmd_len,
+ &phonebook_readrg_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBR=%s", buf);
+ break;
+ case GSMD_PHONEBOOK_WRITE:
+ if(len < sizeof(*gph) + sizeof(*gp))
+ return -EINVAL;
+ gp = (struct gsmd_phonebook *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d,\"%s\",%d,\"%s\"", gp->index, gp->numb, gp->type, gp->text);
+
+ atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBW=", atcmd_len,
+ &phonebook_write_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBW=%s", buf);
+ break;
+ case GSMD_PHONEBOOK_DELETE:
+ if(len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+ index = (int *) ((void *)gph + sizeof(*gph));
+
+ sprintf(buf, "%d", *index);
+
+ atcmd_len = 1 + strlen("AT+CPBW=") + strlen(buf);
+ cmd = atcmd_fill("AT+CPBW=", atcmd_len,
+ &phonebook_delete_cb, gu, gph->id);
+ if (!cmd)
+ return -ENOMEM;
+ sprintf(cmd->buf, "AT+CPBW=%s", buf);
+ break;
+ case GSMD_PHONEBOOK_GET_SUPPORT:
+ cmd = atcmd_fill("AT+CPBR=?", 9+1,
+ &phonebook_support_cb, gu, gph->id);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (cmd)
+ return atcmd_submit(gu->gsmd, cmd);
+ else
+ return 0;
+}
+#endif
static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {
[GSMD_MSG_PASSTHROUGH] = &usock_rcv_passthrough,
@@ -420,6 +847,8 @@ static usock_msg_handler *pcmd_type_handlers[__NUM_GSMD_MSGS] = {
[GSMD_MSG_PIN] = &usock_rcv_pin,
[GSMD_MSG_PHONE] = &usock_rcv_phone,
[GSMD_MSG_NETWORK] = &usock_rcv_network,
+ [GSMD_MSG_SMS] = &usock_rcv_sms,
+ //[GSMD_MSG_PHONEBOOK] = &usock_rcv_phonebook,
};
static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
diff --git a/src/libgsmd/Makefile.am b/src/libgsmd/Makefile.am
index 5ea36f1..20a6725 100644
--- a/src/libgsmd/Makefile.am
+++ b/src/libgsmd/Makefile.am
@@ -5,6 +5,6 @@ AM_CFLAGS = -std=gnu99
lib_LTLIBRARIES = libgsmd.la
libgsmd_la_LDFLAGS = -Wc,-nostartfiles -version-info $(LIBVERSION)
-libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c libgsmd_pin.c
+libgsmd_la_SOURCES = libgsmd.c libgsmd_input.c libgsmd_voicecall.c libgsmd_passthrough.c libgsmd_event.c libgsmd_phone.c libgsmd_network.c libgsmd_pin.c libgsmd_sms.c libgsmd_phonebook.c
noinst_HEADERS = lgsm_internals.h
diff --git a/src/libgsmd/libgsmd_phonebook.c b/src/libgsmd/libgsmd_phonebook.c
new file mode 100644
index 0000000..c569e02
--- /dev/null
+++ b/src/libgsmd/libgsmd_phonebook.c
@@ -0,0 +1,146 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/misc.h>
+#include <libgsmd/phonebook.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#include "lgsm_internals.h"
+
+int lgsm_pb_find_entry(struct lgsm_handle *lh,
+ const struct lgsm_phonebook_find *pb_find)
+{
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_phonebook_find *gpf;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_FIND, sizeof(*gpf));
+ if (!gmh)
+ return -ENOMEM;
+ gpf = (struct gsmd_phonebook_find *)gmh->data;
+ memcpy(gpf->findtext, pb_find->findtext, sizeof(gpf->findtext));
+ gpf->findtext[sizeof(gpf->findtext)-1] = '\0';
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsm_pb_read_entry(struct lgsm_handle *lh, int index)
+{
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_READ, sizeof(int));
+ if (!gmh)
+ return -ENOMEM;
+ *(int *) gmh->data = index;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsm_pb_read_entryies(struct lgsm_handle *lh,
+ const struct lgsm_phonebook_readrg *pb_readrg)
+{
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_phonebook_readrg *gpr;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_READRG, sizeof(*gpr));
+ if (!gmh)
+ return -ENOMEM;
+ gpr = (struct gsmd_phonebook_readrg *) gmh->data;
+ gpr->index1 = pb_readrg->index1;
+ gpr->index2 = pb_readrg->index2;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsmd_pb_del_entry(struct lgsm_handle *lh, int index)
+{
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_DELETE, sizeof(int));
+ if (!gmh)
+ return -ENOMEM;
+
+ *(int *)(gmh->data) = index;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsmd_pb_write_entry(struct lgsm_handle *lh,
+ const struct lgsm_phonebook *pb)
+{
+ /* FIXME: only support alphabet now */
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_phonebook *gp;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_WRITE, sizeof(*gp));
+ if (!gmh)
+ return -ENOMEM;
+ gp = (struct gsmd_phonebook *) gmh->data;
+ gp->index = pb->index;
+ memcpy(gp->numb, pb->numb, sizeof(gp->numb));
+ gp->numb[sizeof(gp->numb)-1] = '\0';
+ gp->type = pb->type;
+ memcpy(gp->text, pb->text, sizeof(gp->text));
+ gp->text[sizeof(gp->text)-1] = '\0';
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+
+int lgsm_pb_get_support(struct lgsm_handle *lh)
+{
+ return lgsm_send_simple(lh, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_GET_SUPPORT);
+}
diff --git a/src/libgsmd/libgsmd_sms.c b/src/libgsmd/libgsmd_sms.c
new file mode 100644
index 0000000..261dca3
--- /dev/null
+++ b/src/libgsmd/libgsmd_sms.c
@@ -0,0 +1,231 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <libgsmd/libgsmd.h>
+#include <libgsmd/misc.h>
+#include <libgsmd/sms.h>
+
+#include <gsmd/usock.h>
+#include <gsmd/event.h>
+
+#include "lgsm_internals.h"
+
+int lgsm_sms_list(struct lgsm_handle *lh, enum gsmd_msg_sms_type stat)
+{
+ /* FIXME: only support PDU mode now */
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_SMS,
+ GSMD_SMS_LIST, sizeof(int));
+ if (!gmh)
+ return -ENOMEM;
+ *(int *) gmh->data = stat;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsm_sms_read(struct lgsm_handle *lh, int index)
+{
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_SMS,
+ GSMD_SMS_READ, sizeof(int));
+ if (!gmh)
+ return -ENOMEM;
+ *(int *) gmh->data = index;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);;
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsmd_sms_delete(struct lgsm_handle *lh,
+ const struct lgsm_sms_delete *sms_del)
+{
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_sms_delete *gsd;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_SMS,
+ GSMD_SMS_DELETE, sizeof(*gsd));
+ if (!gmh)
+ return -ENOMEM;
+ gsd = (struct gsmd_sms_delete *) gmh->data;
+ gsd->index = sms_del->index;
+ gsd->delflg = sms_del->delflg;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsmd_sms_send(struct lgsm_handle *lh,
+ const struct lgsm_sms *sms)
+{
+ /* FIXME: only support PDU mode */
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_sms *gs;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_SMS,
+ GSMD_SMS_SEND, sizeof(*gs));
+ if (!gmh)
+ return -ENOMEM;
+ gs = (struct gsmd_sms *) gmh->data;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int lgsmd_sms_write(struct lgsm_handle *lh,
+ const struct lgsm_sms_write *sms_write)
+{
+ /* FIXME: only support PDU mode */
+ struct gsmd_msg_hdr *gmh;
+ struct gsmd_sms_write *gsw;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_SMS,
+ GSMD_SMS_WRITE, sizeof(*gsw));
+ if (!gmh)
+ return -ENOMEM;
+ gsw = (struct gsmd_sms_write *) gmh->data;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
+
+int packing_7bit_character(char *src, char *dest)
+{
+ int i,j = 0;
+ unsigned char ch1, ch2;
+ char tmp[2];
+ int shift = 0;
+
+ *dest = '\0';
+
+ for ( i=0; i<strlen(src); i++ ) {
+
+ ch1 = src[i] & 0x7F;
+ ch1 = ch1 >> shift;
+ ch2 = src[(i+1)] & 0x7F;
+ ch2 = ch2 << (7-shift);
+
+ ch1 = ch1 | ch2;
+
+ j = strlen(dest);
+ sprintf(tmp, "%x", (ch1 >> 4));
+ dest[j++] = tmp[0];
+ sprintf(tmp, "%x", (ch1 & 0x0F));
+ dest[j++] = tmp[0];
+ dest[j++] = '\0';
+
+ shift++;
+
+ if ( 7 == shift ) {
+ shift = 0;
+ i++;
+ }
+ }
+
+ return 0;
+}
+
+int unpacking_7bit_character(char *src, char *dest)
+{
+ unsigned char ch1, ch2 = '\0';
+ int i, j;
+ char buf[8];
+ int shift = 0;
+
+ *dest = '\0';
+
+ for ( i=0; i<strlen(src); i+=2 ) {
+ sprintf(buf, "%c%c", src[i], src[i+1]);
+ ch1 = strtol(buf, NULL, 16);
+
+ j = strlen(dest);
+ dest[j++] = ((ch1 & (0x7F >> shift)) << shift) | ch2;
+ dest[j++] = '\0';
+
+ ch2 = ch1 >> (7-shift);
+
+ shift++;
+ }
+
+ return 0;
+}
+
+/* Refer to 3GPP TS 11.11 Annex B */
+int packing_UCS2_80(char *src, char *dest)
+{
+ return 0;
+}
+
+/* Refer to 3GPP TS 11.11 Annex B */
+int unpacking_UCS2_80(char *src, char *dest)
+{
+ return 0;
+}
+
+/* Refer to 3GPP TS 11.11 Annex B */
+int packing_UCS2_81(char *src, char *dest)
+{
+ return 0;
+}
+
+/* Refer to 3GPP TS 11.11 Annex B */
+int unpacking_UCS2_81(char *src, char *dest)
+{
+ return 0;
+}
+
+/* Refer to 3GPP TS 11.11 Annex B */
+int packing_UCS2_82(char *src, char *dest)
+{
+ return 0;
+}
+
+/* Refer to 3GPP TS 11.11 Annex B */
+int unpacking_UCS2_82(char *src, char *dest)
+{
+ return 0;
+}
diff --git a/src/util/shell.c b/src/util/shell.c
index 4fef8f9..dfd14cf 100644
--- a/src/util/shell.c
+++ b/src/util/shell.c
@@ -29,6 +29,9 @@
#include <libgsmd/libgsmd.h>
#include <libgsmd/voicecall.h>
#include <libgsmd/misc.h>
+#include <libgsmd/phonebook.h>
+#include <libgsmd/sms.h>
+#include <gsmd/usock.h>
#define STDIN_BUF_SIZE 1024
@@ -39,6 +42,58 @@ static int pt_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
printf("RSTR=`%s'\n", payload);
}
+/* this is the handler for receiving phonebook responses */
+static int pb_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ struct gsmd_phonebook *gp;
+ struct gsmd_phonebook_support *gps;
+ char *payload;
+
+ switch (gmh->msg_subtype) {
+ case GSMD_PHONEBOOK_FIND:
+ break;
+ case GSMD_PHONEBOOK_READRG:
+ payload = (char *)gmh + sizeof(*gmh);
+ printf("%s\n", payload);
+ break;
+ case GSMD_PHONEBOOK_READ:
+ gp = (struct gsmd_phonebook *) ((char *)gmh + sizeof(*gmh));
+ printf("%d, %s, %d, %s\n", gp->index, gp->numb, gp->type, gp->text);
+ break;
+ case GSMD_PHONEBOOK_WRITE:
+ case GSMD_PHONEBOOK_DELETE:
+ payload = (char *)gmh + sizeof(*gmh);
+ printf("%s\n", payload);
+ break;
+ case GSMD_PHONEBOOK_GET_SUPPORT:
+ gps = (struct gsmd_phonebook_support *) ((char *)gmh + sizeof(*gmh));
+ printf("(1-%d), %d, %d\n", gps->index, gps->nlength, gps->tlength);
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
+/* this is the handler for receiving sms responses */
+static int sms_msghandler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+ char *payload;
+
+ switch (gmh->msg_subtype) {
+ case GSMD_SMS_LIST:
+ break;
+ case GSMD_SMS_READ:
+ case GSMD_SMS_SEND:
+ case GSMD_SMS_WRITE:
+ case GSMD_SMS_DELETE:
+ payload = (char *)gmh + sizeof(*gmh);
+ printf("%s\n", payload);
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
static int shell_help(void)
{
printf( "\tA\tAnswer incoming call\n"
@@ -48,6 +103,17 @@ static int shell_help(void)
"\to\tPower Off\n"
"\tR\tRegister Netowrk\n"
"\tT\tSend DTMF Tone\n"
+ "\tpd\tPB Delete (pb=index)\n"
+ "\tpr\tPB Read (pr=index)\n"
+ "\tprr\tPB Read Range (prr=index1,index2)\n"
+ "\tpf\tPB Find (pff=indtext)\n"
+ "\tpw\tPB Write (pw=index,number,text)\n"
+ "\tps\tPB Support\n"
+ "\tsd\tSMS Delete (sd=index,delflg)\n"
+ "\tsl\tSMS List (sl=stat)\n"
+ "\tsr\tSMS Read (sr=index)\n"
+ "\tss\tSMS Send (ss=number,text)\n"
+ "\tsw\tSMS Write (sw=stat,number,text)\n"
"\tq\tQuit\n"
);
}
@@ -59,8 +125,11 @@ int shell_main(struct lgsm_handle *lgsmh)
char rbuf[STDIN_BUF_SIZE+1];
int rlen = sizeof(rbuf);
fd_set readset;
+ char *ptr, *fcomma, *lcomma;
lgsm_register_handler(lgsmh, GSMD_MSG_PASSTHROUGH, &pt_msghandler);
+ lgsm_register_handler(lgsmh, GSMD_MSG_PHONEBOOK, &pb_msghandler);
+ lgsm_register_handler(lgsmh, GSMD_MSG_SMS, &sms_msghandler);
fcntl(0, F_SETFD, O_NONBLOCK);
fcntl(lgsm_fd(lgsmh), F_SETFD, O_NONBLOCK);
@@ -135,6 +204,101 @@ int shell_main(struct lgsm_handle *lgsmh)
continue;
printf("DTMF: %c\n", buf[1]);
lgsm_voice_dtmf(lgsmh, buf[1]);
+ } else if ( !strncmp(buf, "pd", 2)) {
+ printf("Delete Phonebook Entry\n");
+ ptr = strchr(buf, '=');
+ lgsmd_pb_del_entry(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "prr", 3)) {
+ printf("Read Phonebook Entries\n");
+ struct lgsm_phonebook_readrg pb_readrg;
+
+ ptr = strchr(buf, '=');
+ pb_readrg.index1 = atoi(ptr+1);
+ ptr = strchr(buf, ',');
+ pb_readrg.index2 = atoi(ptr+1);
+
+ lgsm_pb_read_entryies(lgsmh, &pb_readrg);
+ } else if ( !strncmp(buf, "pr", 2)) {
+ printf("Read Phonebook Entry\n");
+ ptr = strchr(buf, '=');
+ lgsm_pb_read_entry(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "pf", 2)) {
+ printf("Find Phonebook Entry\n");
+ struct lgsm_phonebook_find pb_find;
+
+ ptr = strchr(buf, '=');
+ strncpy(pb_find.findtext, ptr+1, sizeof(pb_find.findtext)-1);
+ pb_find.findtext[strlen(ptr+1)] = '\0';
+
+ lgsm_pb_find_entry(lgsmh, &pb_find);
+ } else if ( !strncmp(buf, "pw", 2)) {
+ printf("Write Phonebook Entry\n");
+ struct lgsm_phonebook pb;
+
+ ptr = strchr(buf, '=');
+ pb.index = atoi(ptr+1);
+
+ fcomma = strchr(buf, ',');
+ lcomma = strrchr(buf, ',');
+ strncpy(pb.numb, fcomma+1, (lcomma-fcomma-1));
+ pb.numb[(lcomma-fcomma-1)] = '\0';
+ if ( '+' == pb.numb[0] )
+ pb.type = LGSM_PB_ATYPE_INTL;
+ else
+ pb.type = LGSM_PB_ATYPE_OTHE;
+ strncpy(pb.text, lcomma+1, strlen(lcomma+1));
+ pb.text[strlen(lcomma+1)] = '\0';
+
+ lgsmd_pb_write_entry(lgsmh, &pb);
+ } else if ( !strncmp(buf, "ps", 2)) {
+ printf("Get Phonebook Support\n");
+ lgsm_pb_get_support(lgsmh);
+ } else if ( !strncmp(buf, "sd", 2)) {
+ printf("Delete SMS\n");
+ struct lgsm_sms_delete sms_del;
+
+ ptr = strchr(buf, '=');
+ sms_del.index = atoi(ptr+1);
+ ptr = strchr(buf, ',');
+ sms_del.delflg = atoi(ptr+1);
+
+ lgsmd_sms_delete(lgsmh, &sms_del);
+ } else if ( !strncmp(buf, "sl", 2)) {
+ printf("List SMS\n");
+ ptr = strchr(buf, '=');
+
+ lgsm_sms_list(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "sr", 2)) {
+ printf("Read SMS\n");
+ ptr = strchr(buf, '=');
+
+ lgsm_sms_read(lgsmh, atoi(ptr+1));
+ } else if ( !strncmp(buf, "ss", 2)) {
+ printf("Send SMS\n");
+ struct lgsm_sms sms;
+
+ ptr = strchr(buf, '=');
+ fcomma = strchr(buf, ',');
+ strncpy(sms.addr, ptr+1, (fcomma-ptr-1));
+ sms.addr[fcomma-ptr-1] = '\0';
+ strncpy(sms.data, fcomma+1, strlen(fcomma+1));
+ sms.data[strlen(fcomma+1)] = '\0';
+
+ lgsmd_sms_send(lgsmh, &sms);
+ } else if ( !strncmp(buf, "sw", 2)) {
+ printf("Write SMS\n");
+ struct lgsm_sms_write sms_write;
+
+ ptr = strchr(buf, '=');
+ sms_write.stat = atoi(ptr+1);
+ fcomma = strchr(buf, ',');
+ lcomma = strrchr(buf, ',');
+ strncpy(sms_write.sms.addr, fcomma+1, (lcomma-fcomma-1));
+ sms_write.sms.addr[lcomma-fcomma-1] = '\0';
+ strncpy(sms_write.sms.data, lcomma+1, strlen(lcomma+1));
+ sms_write.sms.data[strlen(lcomma+1)] = '\0';
+
+ lgsmd_sms_write(lgsmh, &sms_write);
} else {
printf("Unknown command `%s'\n", buf);
}
personal git repositories of Harald Welte. Your mileage may vary