summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/gsmd/gsmd.h3
-rw-r--r--include/gsmd/usock.h20
-rw-r--r--include/libgsmd/phonebook.h6
-rw-r--r--src/gsmd/usock.c188
-rw-r--r--src/libgsmd/libgsmd_phonebook.c48
5 files changed, 240 insertions, 25 deletions
diff --git a/include/gsmd/gsmd.h b/include/gsmd/gsmd.h
index f1773c3..ed334f1 100644
--- a/include/gsmd/gsmd.h
+++ b/include/gsmd/gsmd.h
@@ -92,6 +92,9 @@ struct gsmd_user {
struct gsmd *gsmd;
struct gsmd_fd gfd; /* the socket */
u_int32_t subscriptions; /* bitmaks of subscribed event groups */
+
+ struct llist_head pb_readrg_list; /* our READRG phonebook list */
+ struct llist_head pb_find_list; /* our FIND phonebook list */
};
#define GSMD_DEBUG 1 /* debugging information */
diff --git a/include/gsmd/usock.h b/include/gsmd/usock.h
index c2f03f5..66cdf48 100644
--- a/include/gsmd/usock.h
+++ b/include/gsmd/usock.h
@@ -194,6 +194,8 @@ enum gsmd_msg_phonebook {
GSMD_PHONEBOOK_GET_SUPPORT = 6,
GSMD_PHONEBOOK_LIST_STORAGE = 7,
GSMD_PHONEBOOK_SET_STORAGE = 8,
+ GSMD_PHONEBOOK_RETRIEVE_READRG = 9,
+ GSMD_PHONEBOOK_RETRIEVE_FIND = 10,
};
/* Type-of-Address, Numbering-Plan-Identification field, GSM 03.40, 9.1.2.5 */
@@ -432,7 +434,6 @@ struct gsmd_phonebook {
char text[GSMD_PB_TEXT_MAXLEN+1];
} __attribute__ ((packed));
-
/* Refer to GSM 07.07 subclause 8.13 */
/* FIXME: the tlength depends on SIM, use +CPBR=? to get */
struct gsmd_phonebook_find {
@@ -472,8 +473,18 @@ struct gsmd_msg_prefoper {
char opname_longalpha[16];
};
+/* Refer to GSM 07.07 subclause 8.11 */
+struct gsmd_phonebook_mem {
+ u_int8_t type[3];
+ u_int8_t pad;
+ u_int16_t used;
+ u_int16_t total;
+} __attribute__ ((packed));
+
struct gsmd_phonebook_storage {
- char storage[3];
+ /* FIXME the amount of phonebook storage should be dynamic */
+ u_int8_t num;
+ struct gsmd_phonebook_mem mem[20];
} __attribute__ ((packed));
/* Subscriber number information from 3GPP TS 07.07, Clause 7.1 */
@@ -518,6 +529,11 @@ struct gsmd_ucmd {
char buf[];
} __attribute__ ((packed));
+struct gsmd_phonebooks {
+ struct llist_head list;
+ struct gsmd_phonebook pb;
+} __attribute__ ((packed));
+
extern struct gsmd_ucmd *ucmd_alloc(int extra_size);
extern int usock_init(struct gsmd *g);
extern void usock_cmd_enqueue(struct gsmd_ucmd *ucmd, struct gsmd_user *gu);
diff --git a/include/libgsmd/phonebook.h b/include/libgsmd/phonebook.h
index badb76f..6e2d2b1 100644
--- a/include/libgsmd/phonebook.h
+++ b/include/libgsmd/phonebook.h
@@ -106,4 +106,10 @@ extern int lgsm_pb_write_entry(struct lgsm_handle *lh,
/* Get the location range/nlength/tlength supported */
extern int lgsm_pb_get_support(struct lgsm_handle *lh);
+/* Retrieve the records of READRG request */
+extern int lgsm_pb_retrieve_readrg(struct lgsm_handle *lh, int num);
+
+/* Retrieve the records of FIND request */
+extern int lgsm_pb_retrieve_find(struct lgsm_handle *lh, int num);
+
#endif
diff --git a/src/gsmd/usock.c b/src/gsmd/usock.c
index 56ef3f4..a53c8a1 100644
--- a/src/gsmd/usock.c
+++ b/src/gsmd/usock.c
@@ -41,7 +41,7 @@
#include <gsmd/ts0707.h>
#include <gsmd/sms.h>
-static void *__ucmd_ctx, *__gu_ctx;
+static void *__ucmd_ctx, *__gu_ctx, *__pb_ctx;
struct gsmd_ucmd *ucmd_alloc(int extra_size)
{
@@ -1035,21 +1035,56 @@ static int usock_rcv_sms(struct gsmd_user *gu, struct gsmd_msg_hdr *gph,
static int phonebook_find_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
- struct gsmd_user *gu = ctx;
- struct gsmd_ucmd *ucmd;
-
+ struct gsmd_user *gu = ctx;
+ struct gsmd_ucmd *ucmd;
+ struct gsmd_phonebooks *gps;
+ char *fcomma, *lcomma, *ptr1, *ptr2 = NULL;
+ int *num;
+
DEBUGP("resp: %s\n", resp);
- /* FIXME: using link list, also we need to handle the case of
- * no query result */
- ucmd = gsmd_ucmd_fill(strlen(resp) + 1, GSMD_MSG_PHONEBOOK,
+ /*
+ * [+CPBF: <index1>,<number>,<type>,<text>[[...]
+ * <CR><LF>+CPBF: <index2>,<unmber>,<type>,<text>]]
+ */
+ ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_PHONEBOOK,
GSMD_PHONEBOOK_FIND, 0);
if (!ucmd)
return -ENOMEM;
- strcpy(ucmd->buf, resp);
+ num = (int*) ucmd->buf;
+
+ *num = 0;
+
+ ptr1 = strtok(resp, "\n");
+
+ while (ptr1) {
+ gps = talloc(__pb_ctx, struct gsmd_phonebooks);
+ ptr2 = strchr(ptr1, ' ');
+ gps->pb.index = atoi(ptr2+1);
+
+ fcomma = strchr(ptr1, '"');
+ lcomma = strchr(fcomma+1, '"');
+ strncpy(gps->pb.numb, fcomma + 1, (lcomma-fcomma-1));
+ gps->pb.numb[(lcomma - fcomma) - 1] = '\0';
+
+ gps->pb.type = atoi(lcomma + 2);
+
+ ptr2 = strrchr(ptr1, ',');
+ fcomma = ptr2 + 1;
+ lcomma = strchr(fcomma + 1, '"');
+ strncpy(gps->pb.text, fcomma + 1, (lcomma - fcomma - 1));
+ gps->pb.text[(lcomma - fcomma) - 1] = '\0';
+
+ llist_add_tail(&gps->list, &gu->pb_find_list);
+
+ (*num)++;
+
+ ptr1 = strtok(NULL, "\n");
+ }
usock_cmd_enqueue(ucmd, gu);
+ talloc_free(__pb_ctx);
return 0;
}
@@ -1102,25 +1137,54 @@ static int phonebook_readrg_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
{
struct gsmd_user *gu = ctx;
struct gsmd_ucmd *ucmd;
+ struct gsmd_phonebooks *gps;
+ char *fcomma, *lcomma, *ptr1, *ptr2 = NULL;
+ int *num;
DEBUGP("resp: %s\n", resp);
/*
- * +CPBR: 4,"1234",129,"6C5F745E7965"
- * +CPBR: 5,"5678",129,"800062115BB6"
- * +CPBR: 6,"7890",129,"810280AA591A"
- * +CPBR: 8,"36874",129,"005300650061006E"
- *
+ * [+CPBR: <index1>,<number>,<type>,<text>[[...]
+ * <CR><LF>+CPBR: <index2>,<unmber>,<type>,<text>]]
*/
- ucmd = gsmd_ucmd_fill(strlen(resp)+1, GSMD_MSG_PHONEBOOK,
+ ucmd = gsmd_ucmd_fill(sizeof(int), GSMD_MSG_PHONEBOOK,
GSMD_PHONEBOOK_READRG, 0);
if (!ucmd)
return -ENOMEM;
- strcpy(ucmd->buf, resp);
+ num = (int*) ucmd->buf;
- usock_cmd_enqueue(ucmd, gu);
+ *num = 0;
+
+ ptr1 = strtok(resp, "\n");
+
+ while (ptr1) {
+ gps = talloc(__pb_ctx, struct gsmd_phonebooks);
+ ptr2 = strchr(ptr1, ' ');
+ gps->pb.index = atoi(ptr2+1);
+
+ fcomma = strchr(ptr1, '"');
+ lcomma = strchr(fcomma+1, '"');
+ strncpy(gps->pb.numb, fcomma + 1, (lcomma-fcomma-1));
+ gps->pb.numb[(lcomma - fcomma) - 1] = '\0';
+ gps->pb.type = atoi(lcomma + 2);
+
+ ptr2 = strrchr(ptr1, ',');
+ fcomma = ptr2 + 1;
+ lcomma = strchr(fcomma + 1, '"');
+ strncpy(gps->pb.text, fcomma + 1, (lcomma - fcomma - 1));
+ gps->pb.text[(lcomma - fcomma) - 1] = '\0';
+
+ llist_add_tail(&gps->list, &gu->pb_readrg_list);
+
+ (*num)++;
+
+ ptr1 = strtok(NULL, "\n");
+ }
+
+ usock_cmd_enqueue(ucmd, gu);
+ talloc_free(__pb_ctx);
return 0;
}
@@ -1209,22 +1273,38 @@ static int phonebook_get_support_cb(struct gsmd_atcmd *cmd, void *ctx, char *res
static int phonebook_list_storage_cb(struct gsmd_atcmd *cmd,
void *ctx, char *resp)
{
- /* +CPBS: ("EN","BD","FD","DC","LD","RC","LR","MT","AD",
- * "SM","SD","MC","LM","AF","ON","UD") */
/* TODO; using link list ; need to handle command error */
struct gsmd_user *gu = ctx;
struct gsmd_ucmd *ucmd;
+ struct gsmd_phonebook_storage *gps;
+ char *ptr;
DEBUGP("resp: %s\n", resp);
- ucmd = gsmd_ucmd_fill(strlen(resp) + 1,
+ /*
+ * +CPBS: (<storage>s)
+ */
+
+ ucmd = gsmd_ucmd_fill(sizeof(*gps),
GSMD_MSG_PHONEBOOK,
GSMD_PHONEBOOK_LIST_STORAGE, 0);
if (!ucmd)
return -ENOMEM;
- strcpy(ucmd->buf, resp);
+ gps = (struct gsmd_phonebook_storage *) ucmd->buf;
+ gps->num = 0;
+
+ if (!strncmp(resp, "+CPBS", 5)) {
+ char* delim = "(,";
+ ptr = strpbrk(resp, delim);
+ while ( ptr ) {
+ strncpy(gps->mem[gps->num].type, ptr+2, 2);
+ gps->mem[gps->num].type[2] = '\0';
+ ptr = strpbrk(ptr+2, delim);
+ gps->num++;
+ }
+ }
usock_cmd_enqueue(ucmd, gu);
@@ -1235,11 +1315,13 @@ static int usock_rcv_phonebook(struct gsmd_user *gu,
struct gsmd_msg_hdr *gph,int len)
{
struct gsmd_atcmd *cmd = NULL;
+ struct gsmd_ucmd *ucmd = NULL;
struct gsmd_phonebook_readrg *gpr;
struct gsmd_phonebook *gp;
struct gsmd_phonebook_find *gpf;
- int *index;
- int atcmd_len;
+ struct gsmd_phonebooks *cur, *cur2;
+ int *index, *num;
+ int atcmd_len, i;
char *storage;
char buf[1024];
@@ -1343,6 +1425,66 @@ static int usock_rcv_phonebook(struct gsmd_user *gu,
cmd = atcmd_fill("AT+CPBR=?", 9+1,
&phonebook_get_support_cb, gu, gph->id);
break;
+ case GSMD_PHONEBOOK_RETRIEVE_READRG:
+ if (len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+
+ num = (int *) ((void *)gph + sizeof(*gph));
+
+ ucmd = gsmd_ucmd_fill(sizeof(struct gsmd_phonebook)*(*num),
+ GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_RETRIEVE_READRG, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ gp = (struct gsmd_phonebook*) ucmd->buf;
+
+ if (!llist_empty(&gu->pb_readrg_list)) {
+
+ llist_for_each_entry_safe(cur, cur2,
+ &gu->pb_readrg_list, list) {
+ gp->index = cur->pb.index;
+ strcpy(gp->numb, cur->pb.numb);
+ gp->type = cur->pb.type;
+ strcpy(gp->text, cur->pb.text);
+ gp++;
+
+ llist_del(&cur->list);
+ free(cur);
+ }
+ }
+
+ usock_cmd_enqueue(ucmd, gu);
+
+ break;
+ case GSMD_PHONEBOOK_RETRIEVE_FIND:
+ if (len < sizeof(*gph) + sizeof(int))
+ return -EINVAL;
+
+ num = (int *) ((void *)gph + sizeof(*gph));
+
+ ucmd = gsmd_ucmd_fill(sizeof(struct gsmd_phonebook)*(*num), GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_RETRIEVE_FIND, 0);
+ if (!ucmd)
+ return -ENOMEM;
+
+ gp = (struct gsmd_phonebook*) ucmd->buf;
+
+ if (!llist_empty(&gu->pb_find_list)) {
+ llist_for_each_entry_safe(cur, cur2, &gu->pb_find_list, list) {
+ gp->index = cur->pb.index;
+ strcpy(gp->numb, cur->pb.numb);
+ gp->type = cur->pb.type;
+ strcpy(gp->text, cur->pb.text);
+ gp++;
+
+ llist_del(&cur->list);
+ free(cur);
+ }
+ }
+
+ usock_cmd_enqueue(ucmd, gu);
+ break;
default:
return -EINVAL;
}
@@ -1468,6 +1610,8 @@ static int gsmd_usock_cb(int fd, unsigned int what, void *data)
newuser->gsmd = g;
newuser->subscriptions = 0xffffffff;
INIT_LLIST_HEAD(&newuser->finished_ucmds);
+ INIT_LLIST_HEAD(&newuser->pb_readrg_list);
+ INIT_LLIST_HEAD(&newuser->pb_find_list);
llist_add(&newuser->list, &g->users);
gsmd_register_fd(&newuser->gfd);
diff --git a/src/libgsmd/libgsmd_phonebook.c b/src/libgsmd/libgsmd_phonebook.c
index 671566b..1f59e34 100644
--- a/src/libgsmd/libgsmd_phonebook.c
+++ b/src/libgsmd/libgsmd_phonebook.c
@@ -33,7 +33,7 @@ int lgsm_pb_set_storage(struct lgsm_handle *lh, char *storage)
gmh->data[2] = '\0';
rc = lgsm_send(lh, gmh);
- if (rc < gmh->len + 3) {
+ if (rc < gmh->len + sizeof(*gmh)) {
lgsm_gmh_free(gmh);
return -EIO;
}
@@ -177,3 +177,49 @@ int lgsm_pb_get_support(struct lgsm_handle *lh)
{
return lgsm_send_simple(lh, GSMD_MSG_PHONEBOOK, GSMD_PHONEBOOK_GET_SUPPORT);
}
+
+int lgsm_pb_retrieve_readrg(struct lgsm_handle *lh, int num)
+{
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_RETRIEVE_READRG, sizeof(int));
+ if (!gmh)
+ return -ENOMEM;
+
+ *(int *)(gmh->data) = num;
+
+ 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_retrieve_find(struct lgsm_handle *lh, int num)
+{
+ struct gsmd_msg_hdr *gmh;
+ int rc;
+
+ gmh = lgsm_gmh_fill(GSMD_MSG_PHONEBOOK,
+ GSMD_PHONEBOOK_RETRIEVE_FIND, sizeof(int));
+ if (!gmh)
+ return -ENOMEM;
+
+ *(int *)(gmh->data) = num;
+
+ rc = lgsm_send(lh, gmh);
+ if (rc < gmh->len + sizeof(*gmh)) {
+ lgsm_gmh_free(gmh);
+ return -EIO;
+ }
+
+ lgsm_gmh_free(gmh);
+
+ return 0;
+}
personal git repositories of Harald Welte. Your mileage may vary