commit 577ffc2616620c5991d42c715e63df3eb0120f82
Author: Andrzej Zaborowski <balrog at zabor.org>
Date:   Fri Jul 27 21:25:33 2007 +0200

    Add retrieving phone's own subscriber number.

---
 include/gsmd/usock.h          |   18 +++++++++++++++
 include/libgsmd/misc.h        |    3 ++
 src/gsmd/usock.c              |   49 ++++++++++++++++++++++++++++++++++++++++++
 src/libgsmd/libgsmd_network.c |    5 ++++
 src/util/event.c              |    1 
 src/util/shell.c              |   22 ++++++++++++++++++
 6 files changed, 98 insertions(+)

Index: gsm/include/gsmd/usock.h
===================================================================
--- gsm.orig/include/gsmd/usock.h	2007-08-15 00:34:28.000000000 +0800
+++ gsm/include/gsmd/usock.h	2007-08-15 00:36:04.000000000 +0800
@@ -478,6 +478,24 @@
 	char storage[3];
 } __attribute__ ((packed));
 
+/* Subscriber number information from 3GPP TS 07.07, Clause 7.1 */
+enum gsmd_subscriber_service {
+	GSMD_SERVICE_UNKNOWN		= -1,
+	GSMD_SERVICE_ASYNC_MODEM	= 0,
+	GSMD_SERVICE_SYNC_MODEM,
+	GSMD_SERVICE_PAD_ACCESS,
+	GSMD_SERVICE_PACKET_ACCESS,
+	GSMD_SERVICE_VOICE,
+	GSMD_SERVICE_FAX,
+};
+
+struct gsmd_own_number {
+	int is_last;
+	enum gsmd_subscriber_service service;
+	struct gsmd_addr addr;
+	char name[0];
+};
+
 struct gsmd_msg_hdr {
 	u_int8_t version;
 	u_int8_t msg_type;
Index: gsm/include/libgsmd/misc.h
===================================================================
--- gsm.orig/include/libgsmd/misc.h	2007-08-15 00:34:14.000000000 +0800
+++ gsm/include/libgsmd/misc.h	2007-08-15 00:36:04.000000000 +0800
@@ -68,6 +68,9 @@
 extern int lgsm_prefoper_add(struct lgsm_handle *lh, gsmd_oper_numeric oper);
 extern int lgsm_prefoper_get_space(struct lgsm_handle *lh);
 
+/* Get subscriber's own phone number */
+extern int lgsm_get_subscriber_num(struct lgsm_handle *lh);
+
 /* CLIP, CLIR, COLP, Call Forwarding, Call Waiting, Call Deflecting */
 /* TBD */
 
Index: gsm/src/gsmd/usock.c
===================================================================
--- gsm.orig/src/gsmd/usock.c	2007-08-15 00:34:28.000000000 +0800
+++ gsm/src/gsmd/usock.c	2007-08-15 00:36:04.000000000 +0800
@@ -548,6 +548,51 @@
 	return 0;
 }
 
+static int network_ownnumbers_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
+{
+	struct gsmd_user *gu = (struct gsmd_user *) ctx;
+	struct gsmd_ucmd *ucmd;
+	struct gsmd_own_number *num;
+	int len, ret, type;
+	char dummy;
+
+	if (cmd->ret && cmd->ret != -255)
+		return 0;
+
+	if (sscanf(resp, "+CNUM: \"%*[^\"]\"%c%n", &dummy, &len) > 0)
+		len -= strlen("+CNUM: \"\",");
+	else
+		len = 0;
+
+	ucmd = gsmd_ucmd_fill(sizeof(*num) + len + 1,
+			GSMD_MSG_NETWORK, GSMD_NETWORK_GET_NUMBER, cmd->id);
+	if (!ucmd)
+		return -ENOMEM;
+
+	num = (struct gsmd_own_number *) ucmd->buf;
+	if (len)
+		ret = sscanf(resp, "+CNUM: \"%[^\"]\",\"%32[^\"]\",%i,%*i,%i,",
+				num->name, num->addr.number,
+				&type, &num->service) - 1;
+	else
+		ret = sscanf(resp, "+CNUM: ,\"%32[^\"]\",%i,%*i,%i,",
+				num->addr.number,
+				&type, &num->service);
+	if (ret < 2) {
+		talloc_free(ucmd);
+		return -EINVAL;
+	}
+	if (ret < 3)
+		num->service = GSMD_SERVICE_UNKNOWN;
+	num->name[len] = 0;
+	num->addr.type = type;
+	num->is_last = (cmd->ret == 0);
+
+	usock_cmd_enqueue(ucmd, gu);
+
+	return 0;
+}
+
 static int usock_rcv_network(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, 
 			     int len)
 {
@@ -607,6 +652,10 @@
 		cmd = atcmd_fill("AT+CPOL=?", 9 + 1,
 				&network_pref_num_cb, gu, 0);
 		break;
+	case GSMD_NETWORK_GET_NUMBER:
+		cmd = atcmd_fill("AT+CNUM", 7 + 1,
+				&network_ownnumbers_cb, gu, 0);
+		break;
 	default:
 		return -EINVAL;
 	}
Index: gsm/src/libgsmd/libgsmd_network.c
===================================================================
--- gsm.orig/src/libgsmd/libgsmd_network.c	2007-08-15 00:34:14.000000000 +0800
+++ gsm/src/libgsmd/libgsmd_network.c	2007-08-15 00:36:04.000000000 +0800
@@ -128,3 +128,8 @@
 {
 	return lgsm_send_simple(lh, GSMD_MSG_NETWORK, GSMD_NETWORK_PREF_SPACE);
 }
+
+int lgsm_get_subscriber_num(struct lgsm_handle *lh)
+{
+	return lgsm_send_simple(lh, GSMD_MSG_NETWORK, GSMD_NETWORK_GET_NUMBER);
+}
Index: gsm/src/util/event.c
===================================================================
--- gsm.orig/src/util/event.c	2007-08-15 00:33:51.000000000 +0800
+++ gsm/src/util/event.c	2007-08-15 00:36:04.000000000 +0800
@@ -26,6 +26,7 @@
 #include <common/linux_list.h>
 #include <libgsmd/libgsmd.h>
 #include <libgsmd/event.h>
+#include <libgsmd/sms.h>
 
 static int incall_handler(struct lgsm_handle *lh, int evt, struct gsmd_evt_auxdata *aux)
 {
Index: gsm/src/util/shell.c
===================================================================
--- gsm.orig/src/util/shell.c	2007-08-15 00:34:28.000000000 +0800
+++ gsm/src/util/shell.c	2007-08-15 00:36:04.000000000 +0800
@@ -298,12 +298,22 @@
 	const char *oper = (char *) gmh + sizeof(*gmh);
 	const struct gsmd_msg_oper *opers = (struct gsmd_msg_oper *)
 		((void *) gmh + sizeof(*gmh));
+	const struct gsmd_own_number *num = (struct gsmd_own_number *)
+		((void *) gmh + sizeof(*gmh));
 	static const char *oper_stat[] = {
 		[GSMD_OPER_UNKNOWN] = "of unknown status",
 		[GSMD_OPER_AVAILABLE] = "available",
 		[GSMD_OPER_CURRENT] = "our current operator",
 		[GSMD_OPER_FORBIDDEN] = "forbidden",
 	};
+	static const char *srvname[] = {
+		[GSMD_SERVICE_ASYNC_MODEM] = "asynchronous modem",
+		[GSMD_SERVICE_SYNC_MODEM] = "synchronous modem",
+		[GSMD_SERVICE_PAD_ACCESS] = "PAD Access (asynchronous)",
+		[GSMD_SERVICE_PACKET_ACCESS] = "Packet Access (synchronous)",
+		[GSMD_SERVICE_VOICE] = "voice",
+		[GSMD_SERVICE_FAX] = "fax",
+	};
 
 	switch (gmh->msg_subtype) {
 	case GSMD_NETWORK_SIGQ_GET:
@@ -333,6 +343,15 @@
 					opers->opname_shortalpha,
 					oper_stat[opers->stat]);
 		break;
+	case GSMD_NETWORK_GET_NUMBER:
+		printf("\t%s\t%10s%s%s%s\n", num->addr.number, num->name,
+				(num->service == GSMD_SERVICE_UNKNOWN) ?
+				"" : " related to ",
+				(num->service == GSMD_SERVICE_UNKNOWN) ?
+				"" : srvname[num->service],
+				(num->service == GSMD_SERVICE_UNKNOWN) ?
+				"" : " services");
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -352,6 +371,7 @@
 		"\tL\tDetect available operators\n"
 		"\tQ\tRead signal quality\n"
 		"\tT\tSend DTMF Tone\n"
+		"\tn\tPrint subscriber numbers\n"
 		"\tpd\tPB Delete (pb=index)\n"
 		"\tpr\tPB Read (pr=index)\n"
 		"\tprr\tPB Read Range (prr=index1,index2)\n"
@@ -630,6 +650,8 @@
 					printf("No.\n");
 				else
 					lgsm_sms_set_smsc(lgsmh, ptr + 1);
+			} else if (!strcmp(buf, "n")) {
+				lgsm_get_subscriber_num(lgsmh);
 			} else {
 				printf("Unknown command `%s'\n", buf);
 			}
