r96 - in trunk/src/target/gsm: . doc include/gsmd src/gsmd src/libgsmd src/util

laforge at gta01.hmw-consulting.de laforge at gta01.hmw-consulting.de
Sun Oct 22 16:05:55 CEST 2006


Author: laforge
Date: 2006-10-22 14:05:53 +0000 (Sun, 22 Oct 2006)
New Revision: 96

Added:
   trunk/src/target/gsm/doc/
   trunk/src/target/gsm/doc/functions.txt
   trunk/src/target/gsm/src/libgsmd/libgsmd_passthrough.c
   trunk/src/target/gsm/src/util/shell.c
Modified:
   trunk/src/target/gsm/README.txt
   trunk/src/target/gsm/include/gsmd/event.h
   trunk/src/target/gsm/include/gsmd/usock.h
   trunk/src/target/gsm/src/gsmd/gsmd.c
   trunk/src/target/gsm/src/gsmd/select.c
   trunk/src/target/gsm/src/gsmd/unsolicited.c
   trunk/src/target/gsm/src/gsmd/usock.c
   trunk/src/target/gsm/src/libgsmd/lgsm_internals.h
   trunk/src/target/gsm/src/libgsmd/libgsmd.c
   trunk/src/target/gsm/src/util/Makefile.am
   trunk/src/target/gsm/src/util/libgsmd-tool.c
Log:
some further gsmd/libgsmd work


Modified: trunk/src/target/gsm/README.txt
===================================================================
--- trunk/src/target/gsm/README.txt	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/README.txt	2006-10-22 14:05:53 UTC (rev 96)
@@ -2,15 +2,37 @@
 
 1. GSMD api towards libgsmd 
 	- provides api for other processes to interact with GSM subsystem
+	- is not documented and subject to change
 
 2. GSMD api towards vendor-specific plugins
 	- implement vendor-specific AT commands
+	- is not documented and will initially only support TI 
+	- later, a Motorola plugin is planned.
 
 3. libgsmd api towards applications
 	- wraps GSMD-libgsmd api into C functions that can be used by applications
+	- will be documented and is supposed to be stable.
 
+3.1. Events
 
+The application registers callback handlers for events.  libgsmd can call these callback
+handlers at any given time.  Events include "incoming call", "remote end hangup", ...
 
+3.2. Commands
+
+Commands have the form of command-reply.  Usually they will be performed
+synchronously, i.e. the the caller will be blocked until a response to the command has been
+received.
+
+If this behaviour is not desired, a completion handler callback function can be
+registered.  In this case, the function call will return immediately after the
+command has been sent to gsmd.  Further incoming packets on the gsmd socket
+will be handled to libgsmd by calling lgsm_handle_packet().  If one such packet is the
+response to a currently-executing command, the completion handler will be
+called from within lgsm_handle_packet().  Matching of responses to requests is done by 
+assigning a unique id to each request.  gsmd responses will have a matching id.
+
+
 code flow in gsmd:
 
 - select loop detects data has arrived on user socket

Added: trunk/src/target/gsm/doc/functions.txt
===================================================================
--- trunk/src/target/gsm/doc/functions.txt	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/doc/functions.txt	2006-10-22 14:05:53 UTC (rev 96)
@@ -0,0 +1,51 @@
+0. general
+
+commands
+- power up/down phone
+- operator selection
+- get list of operators
+- get operator name / id list
+- get (and edit) preferred operator list
+- get manufacturer/device/serial info
+- get IMSI
+- obtain network registration status
+
+
+events
+- some pin required
+- network registration status
+- time zone update
+
+
+1. voice calls
+
+commands (request/response)
+- dial outgoing call
+- send dtmf digit (during call)
+- hang up (incoming/outgoing)
+- accept currently pending incoming call
+- enable/disable clip
+- enable/disable colp
+- enable/disable clir
+- call forwarding
+- call deflection
+
+events
+- incoming call
+- clip
+- colp
+- call waiting
+- 
+
+2. SMS
+
+commands
+- send outgoing message
+
+3. data calls
+
+TBD
+
+4. GPRS
+
+TBD

Modified: trunk/src/target/gsm/include/gsmd/event.h
===================================================================
--- trunk/src/target/gsm/include/gsmd/event.h	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/include/gsmd/event.h	2006-10-22 14:05:53 UTC (rev 96)
@@ -13,6 +13,7 @@
 	GSMD_EVT_OUT_STATUS	= 8,	/* Outgoing call status */
 	GSMD_EVT_OUT_COLP	= 9,	/* Outgoing COLP */
 	GSMD_EVT_CALL_WAIT	= 10,	/* Call Waiting */
+	GSMD_EVT_TIMEZONE	= 11,	/* Timezone change */
 	__NUM_GSMD_EVT
 };
 

Modified: trunk/src/target/gsm/include/gsmd/usock.h
===================================================================
--- trunk/src/target/gsm/include/gsmd/usock.h	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/include/gsmd/usock.h	2006-10-22 14:05:53 UTC (rev 96)
@@ -11,28 +11,17 @@
 
 #define GSMD_MSGSIZE_MAX	4096
 
-enum gsmd_prot_cmd {
-	GSMD_PCMD_NONE,
-	GSMD_PCMD_EVT_SUBSCRIPTIONS,		/* alter event subscriptions */
-	GSMD_PCMD_PASSTHROUGH,			/* transparent atcmd passthrough */
-};
-
-enum gsmd_pcmd_result {
-	GSMD_PCMD_OK		= 0,
-	GSMD_PCMD_ERR_UNSPEC	= 0xff,
-};
-
-struct gsmd_prot_hdr {
-	u_int16_t cmd;
-	u_int8_t result;
-	u_int8_t version;
-} __attribute__((packed));
-
-
 enum gsmd_msg_type {
 	GSMD_MSG_NONE		= 0,
 	GSMD_MSG_EVENT		= 1,
 	GSMD_MSG_PASSTHROUGH	= 2,
+	GSMD_MSG_VOICECALL	= 3,
+	GSMD_MSG_DATACALL	= 4,
+	GSMD_MSG_PHONEBOOK	= 5,
+	GSMD_MSG_NETWORK	= 6,
+	GSMD_MSG_PHONE		= 7,
+	GSMD_MSG_PIN		= 8,
+	__NUM_GSMD_MSGS
 };
 
 enum gsmd_passthrough_type {
@@ -41,6 +30,27 @@
 	GSMD_PASSTHROUGH_RESP	= 2,
 };
 
+enum gsmd_event_type {
+	GSMD_EVENT_NONE		= 0,
+	GSMD_EVENT_SUBSCRIPTIONS= 1,
+	GSMD_EVENT_HAPPENED	= 2,
+};
+
+enum gsmd_msg_voicecall_type {
+	GSMD_VOICECALL_DIAL	= 1,
+	GSMD_VOICECALL_HANGUP	= 2,
+};
+
+/* Handset / MT related commands */
+enum gsmd_msg_phone_type {
+	GSMD_PHONE_VOLUME	= 1,
+	GSMD_PHONE_VIBRATOR	= 2,
+};
+
+enum gsmd_msg_pin_type {
+	GSMD_PIN_INPUT		= 1,
+};
+
 /* Length from 3GPP TS 04.08, Clause 10.5.4.7 */
 
 #define GSMD_ADDR_MAXLEN	13
@@ -72,6 +82,9 @@
 			u_int16_t lac;
 			u_int16_t ci;
 		} netreg;
+		struct {
+			u_int8_t tz;
+		} timezone;
 	} u;
 } __attribute__((packed));
 
@@ -79,7 +92,9 @@
 	u_int8_t version;
 	u_int8_t msg_type;
 	u_int8_t msg_subtype;
-	u_int8_t len;
+	u_int8_t _pad;
+	u_int16_t id;
+	u_int16_t len;
 } __attribute__((packed));
 
 

Modified: trunk/src/target/gsm/src/gsmd/gsmd.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/gsmd.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/gsmd/gsmd.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -51,7 +51,7 @@
 	if (rc < 0)
 		return rc;
 
-	cmd = atcmd_fill("+CRC=1;+CREG=2;+CMEE=2;+CLIP=1;+COLP=1", 255, &gsmd_test_atcb, NULL);
+	cmd = atcmd_fill("+CRC=1;+CREG=2;+CMEE=2;+CLIP=1;+COLP=1;+CTZR=1", 255, &gsmd_test_atcb, NULL);
 	return atcmd_submit(gsmd, cmd);
 }
 

Modified: trunk/src/target/gsm/src/gsmd/select.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/select.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/gsmd/select.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -53,7 +53,7 @@
 
 int gsmd_select_main()
 {
-	struct gsmd_fd *ufd;
+	struct gsmd_fd *ufd, *ufd2;
 	fd_set readset, writeset, exceptset;
 	int i;
 
@@ -76,7 +76,7 @@
 	i = select(maxfd+1, &readset, &writeset, &exceptset, NULL);
 	if (i > 0) {
 		/* call registered callback functions */
-		llist_for_each_entry(ufd, &gsmd_fds, list) {
+		llist_for_each_entry_safe(ufd, ufd2, &gsmd_fds, list) {
 			int flags = 0;
 
 			if (FD_ISSET(ufd->fd, &readset))

Modified: trunk/src/target/gsm/src/gsmd/unsolicited.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/unsolicited.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/gsmd/unsolicited.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -59,7 +59,7 @@
 	return num_sent;
 }
 
-static int ring_parse(const char *buf, int len, const char *param,
+static int ring_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	/* FIXME: generate ring event */
@@ -76,7 +76,7 @@
 	return usock_evt_send(gsmd, ucmd, GSMD_EVT_IN_CALL);
 }
 
-static int cring_parse(const char *buf, int len, const char *param, struct gsmd *gsmd)
+static int cring_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
 {
 	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CALL,
 					     sizeof(struct gsmd_evt_auxdata));
@@ -108,7 +108,7 @@
 }
 
 /* Chapter 7.2, network registration */
-static int creg_parse(const char *buf, int len, const char *param,
+static int creg_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	const char *comma = strchr(param, ',');
@@ -121,25 +121,54 @@
 
 	aux->u.netreg.state = atoi(param);
 	if (comma) {
-		/* FIXME: we also have location area code and cell id to parse (hex) */
+		/* we also have location area code and cell id to parse (hex) */
+		aux->u.netreg.lac = atoi(comma+1);
+		comma = strchr(comma+1, ',');
+		if (!comma)
+			return -EINVAL;
+		aux->u.netreg.ci = atoi(comma+1);
 	}
 
 	return usock_evt_send(gsmd, ucmd, GSMD_EVT_NETREG);
 }
 
 /* Chapter 7.11, call waiting */
-static int ccwa_parse(const char *buf, int len, const char *param,
+static int ccwa_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
-	const char *number;
-	u_int8_t type, class;
+	const char *token;
+	unsigned int type;
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_CALL_WAIT,
+					     sizeof(struct gsmd_addr));
+	struct gsmd_addr *gaddr;
 
-	/* FIXME: parse */
-	return 0;
+	if (!ucmd)
+		return -ENOMEM;
+
+	gaddr = (struct gsmd_addr *) ucmd->buf;
+	memset(gaddr, 0, sizeof(*gaddr));
+
+	/* parse address (phone number) */
+	token = strtok(buf, ",");
+	if (!token)
+		return -EINVAL;
+	strncpy(gaddr->number, token, GSMD_ADDR_MAXLEN);
+
+	/* parse type */
+	token = strtok(NULL, ",");
+	if (!token)
+		return -EINVAL;
+	type = atoi(token) & 0xff;
+	gaddr->type = type;
+
+	/* FIXME: parse class */
+	token = strtok(NULL, ",");
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_CALL_WAIT);
 }
 
 /* Chapter 7.14, unstructured supplementary service data */
-static int cusd_parse(const char *buf, int len, const char *param,
+static int cusd_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	/* FIXME: parse */
@@ -147,7 +176,7 @@
 }
 
 /* Chapter 7.15, advise of charge */
-static int cccm_parse(const char *buf, int len, const char *param,
+static int cccm_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	/* FIXME: parse */
@@ -155,7 +184,7 @@
 }
 
 /* Chapter 10.1.13, GPRS event reporting */
-static int cgev_parse(const char *buf, int len, const char *param,
+static int cgev_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	/* FIXME: parse */
@@ -163,7 +192,7 @@
 }
 
 /* Chapter 10.1.14, GPRS network registration status */
-static int cgreg_parse(const char *buf, int len, const char *param,
+static int cgreg_parse(char *buf, int len, const char *param,
 		       struct gsmd *gsmd)
 {
 	/* FIXME: parse */
@@ -171,7 +200,7 @@
 }
 
 /* Chapter 7.6, calling line identification presentation */
-static int clip_parse(const char *buf, int len, const char *param,
+static int clip_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_IN_CLIP,
@@ -197,7 +226,7 @@
 }
 
 /* Chapter 7.9, calling line identification presentation */
-static int colp_parse(const char *buf, int len, const char *param,
+static int colp_parse(char *buf, int len, const char *param,
 		      struct gsmd *gsmd)
 {
 	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_OUT_COLP,
@@ -222,22 +251,47 @@
 	return usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_COLP);
 }
 
+static int ctzv_parse(char *buf, int len, const char *param,
+		      struct gsmd *gsmd)
+{
+	struct gsmd_ucmd *ucmd = build_event(GSMD_MSG_EVENT, GSMD_EVT_TIMEZONE,
+					     sizeof(struct gsmd_evt_auxdata));
+	struct gsmd_evt_auxdata *aux;
+	int tz;
+
+	if (!ucmd)
+		return -ENOMEM;
+	
+	aux = (struct gsmd_evt_auxdata *) ucmd->buf;
+
+	/* timezones are expressed in quarters of hours +/- GMT (-48...+48) */
+	tz = atoi(param);
+
+	if (tz < -48  || tz > 48)
+		return -EINVAL;
+	
+	aux->u.timezone.tz = tz;
+
+	return usock_evt_send(gsmd, ucmd, GSMD_EVT_TIMEZONE);
+}
+
 struct gsmd_unsolicit {
 	const char *prefix;
-	int (*parse)(const char *unsol, int len, const char *param, struct gsmd *gsmd);
+	int (*parse)(char *unsol, int len, const char *param, struct gsmd *gsmd);
 };
 
 static const struct gsmd_unsolicit gsm0707_unsolicit[] = {
 	{ "RING",	&ring_parse },
 	{ "+CRING", 	&cring_parse },
-	{ "+CREG",	&creg_parse },
-	{ "+CCWA",	&ccwa_parse },
-	{ "+CUSD",	&cusd_parse },
-	{ "+CCCM",	&cccm_parse },
-	{ "+CGEV",	&cgev_parse },
-	{ "+CGREG",	&cgreg_parse },
+	{ "+CREG",	&creg_parse },	/* Network registration */
+	{ "+CCWA",	&ccwa_parse },	/* Call waiting */
+	{ "+CUSD",	&cusd_parse },	/* Unstructured supplementary data */
+	{ "+CCCM",	&cccm_parse },	/* Advice of Charge */
+	{ "+CGEV",	&cgev_parse },	/* GPRS Event */
+	{ "+CGREG",	&cgreg_parse },	/* GPRS Registration */
 	{ "+CLIP",	&clip_parse },
 	{ "+COLP",	&colp_parse },
+	{ "+CTZV",	&ctzv_parse },	/* Timezone */
 	/*
 	{ "+CKEV",	&ckev_parse },
 	{ "+CDEV",	&cdev_parse },
@@ -250,7 +304,7 @@
 };
 
 /* called by midlevel parser if a response seems unsolicited */
-int unsolicited_parse(struct gsmd *g, const char *buf, int len, const char *param)
+int unsolicited_parse(struct gsmd *g, char *buf, int len, const char *param)
 {
 	int i;
 

Modified: trunk/src/target/gsm/src/gsmd/usock.c
===================================================================
--- trunk/src/target/gsm/src/gsmd/usock.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/gsmd/usock.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -39,32 +39,62 @@
 	return 0;
 }
 
-static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
+typedef int usock_msg_handler(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len);
+
+static int usock_rcv_passthrough(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
 {
-	struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;
+	struct gsmd_atcmd *cmd;
+	cmd = atcmd_fill((char *)gph+sizeof(*gph), 255, &usock_cmd_cb, gu);
+	if (!cmd)
+		return -ENOMEM;
 
-	if (gph->version != GSMD_PROTO_VERSION)
+	return atcmd_submit(gu->gsmd, cmd);
+}
+
+static int usock_rcv_event(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+	u_int32_t *evtmask = (u_int32_t *) ((char *)gph + sizeof(*gph));
+
+	if (len < sizeof(*gph) + sizeof(u_int32_t))
 		return -EINVAL;
 
-	switch (gph->msg_type) {
-	case GSMD_MSG_PASSTHROUGH: 
-		{
-			struct gsmd_atcmd *cmd;
-			cmd = atcmd_fill((char *)gph+sizeof(*gph),
-					 255, &usock_cmd_cb, gu);
-			if (!cmd)
-				return -ENOMEM;
-			return atcmd_submit(gu->gsmd, cmd);
-		}
+	if (gph->msg_subtype != GSMD_EVENT_SUBSCRIPTIONS)
+		return -EINVAL;
+
+	gu->subscriptions = *evtmask;
+}
+
+static int usock_rcv_voicecall(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+	struct gsmd_atcmd *cmd;
+
+	switch (gph->msg_subtype) {
+	case GSMD_VOICECALL_DIAL:
+		/* FIXME */
 		break;
-	case GSMD_PCMD_EVT_SUBSCRIPTIONS:
-		{
-			u_int32_t *evtmask = (u_int32_t *) (buf + sizeof(*gph));
-			if (len < sizeof(*gph) + sizeof(u_int32_t))
-				return -EINVAL;
+	case GSMD_VOICECALL_HANGUP:
+		cmd = atcmd_fill("ATH0", 5, &usock_cmd_cb, gu);
+		break;
+	default:
+		return -EINVAL;
+	}
 
-			gu->subscriptions = *evtmask;
-		}
+	return 0;
+}
+
+#define GSMD_PIN_MAXLEN 16
+
+static int usock_rcv_pin(struct gsmd_user *gu, struct gsmd_msg_hdr *gph, int len)
+{
+	u_int8_t *pin = (u_int8_t *)gph + sizeof(*gph);
+	int pin_len = len - sizeof(*gph);
+	char pinbuf[GSMD_PIN_MAXLEN + 11]; /* `AT+CPIN=""\0' */
+
+	snprintf(pinbuf, sizeof(pinbuf), "AT+CPIN=\"%s\"", pin);
+
+	switch (gph->msg_subtype) {
+	case GSMD_PIN_INPUT:
+		/* FIXME */
 		break;
 	default:
 		return -EINVAL;
@@ -73,6 +103,31 @@
 	return 0;
 }
 
+static usock_msg_handler *pcmd_type_handlers[] = {
+	[GSMD_MSG_PASSTHROUGH]	= &usock_rcv_passthrough,
+	[GSMD_MSG_EVENT]	= &usock_rcv_event,
+	[GSMD_MSG_VOICECALL]	= &usock_rcv_voicecall,
+	[GSMD_MSG_PIN]		= &usock_rcv_pin,
+};
+
+static int usock_rcv_pcmd(struct gsmd_user *gu, char *buf, int len)
+{
+	struct gsmd_msg_hdr *gph = (struct gsmd_msg_hdr *)buf;
+	usock_msg_handler *umh;
+
+	if (gph->version != GSMD_PROTO_VERSION)
+		return -EINVAL;
+
+	if (gph->msg_type >= ARRAY_SIZE(pcmd_type_handlers))
+		return -EINVAL;
+	
+	umh = pcmd_type_handlers[gph->msg_type];
+	if (!umh)
+		return -EINVAL;
+
+	return umh(gu, gph, len);
+}
+
 /* callback for read/write on client (libgsmd) socket */
 static int gsmd_usock_user_cb(int fd, unsigned int what, void *data)
 {

Modified: trunk/src/target/gsm/src/libgsmd/lgsm_internals.h
===================================================================
--- trunk/src/target/gsm/src/libgsmd/lgsm_internals.h	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/libgsmd/lgsm_internals.h	2006-10-22 14:05:53 UTC (rev 96)
@@ -1,4 +1,13 @@
+#ifndef _LGSM_INTERNALS_H
+#define _LGSM_INTERNALS_H
 
+#include <gsmd/usock.h>
+
+typedef int lgsm_msg_handler(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh);
+
 struct lgsm_handle {
 	int fd;
+	lgsm_msg_handler *handler[__NUM_GSMD_MSGS];
 };
+
+#endif /* _LGSM_INTERNALS_H */

Modified: trunk/src/target/gsm/src/libgsmd/libgsmd.c
===================================================================
--- trunk/src/target/gsm/src/libgsmd/libgsmd.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/libgsmd/libgsmd.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -36,7 +36,6 @@
 	return 0;
 }
 
-
 static int lgsm_open_backend(struct lgsm_handle *lh, const char *device)
 {
 	int rc;
@@ -52,7 +51,6 @@
 		memset(&sun, 0, sizeof(sun));
 		sun.sun_family = AF_UNIX;
 		memcpy(sun.sun_path, GSMD_UNIX_SOCKET, sizeof(GSMD_UNIX_SOCKET));
-		printf("sizeof(GSMD_UNIX_SOCKET) = %u\n", sizeof(GSMD_UNIX_SOCKET));
 
 		rc = connect(lh->fd, (struct sockaddr *)&sun, sizeof(sun));
 		if (rc < 0) {
@@ -66,6 +64,49 @@
 	return 0;
 }
 
+/* handle a packet that was received on the gsmd socket */
+int lgsm_handle_packet(struct lgsm_handle *lh, char *buf, int len)
+{
+	struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)buf;
+	if (len < sizeof(*gmh))
+		return -EINVAL;
+	
+	if (len - sizeof(*gmh) < gmh->len)
+		return -EINVAL;
+	
+	if (gmh->msg_type >= __NUM_GSMD_MSGS)
+		return -EINVAL;
+	
+	return lh->handler[gmh->msg_type](lh, gmh);
+}
+
+/* blocking read and processing of packets until packet matching 'id' is found */
+int lgsm_blocking_wait_packet(struct lgsm_handle *lh, u_int16_t id, 
+			      struct gsmd_msg_hdr *gmh, int rlen)
+{
+	int rc;
+	fd_set readset;
+
+	FD_ZERO(&readset);
+
+	while (1) {
+		FD_SET(lh->fd, &readset);
+		rc = select(lh->fd+1, &readset, NULL, NULL, NULL);
+		if (rc <= 0)
+			return rc;
+
+		rc = read(lh->fd, (char *)gmh, rlen);
+		if (rc <= 0)
+			return rc;
+
+		if (gmh->id == id) {
+			/* we've found the matching packet, return to calling function */
+			return rc;
+		} else
+			rc = lgsm_handle_packet(lh, (char *)gmh, rc);
+	}
+}
+
 int lgsm_fd(struct lgsm_handle *lh)
 {
 	return lh->fd;

Added: trunk/src/target/gsm/src/libgsmd/libgsmd_passthrough.c
===================================================================
--- trunk/src/target/gsm/src/libgsmd/libgsmd_passthrough.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/libgsmd/libgsmd_passthrough.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -0,0 +1,65 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+
+#include <gsmd/usock.h>
+#include <libgsmd/libgsmd.h>
+
+#include "lgsm_internals.h"
+
+static u_int16_t next_msg_id;
+
+static int lgsm_send(struct lgsm_handle *lh, struct gsmd_msg_hdr *gmh)
+{
+	gmh->id = next_msg_id++;
+	return send(lh->fd, (char *) gmh, sizeof(*gmh) + gmh->len);
+}
+
+#define PT_BUF_SIZE	1024
+static char passthrough_buf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE];
+static char passthrough_rbuf[sizeof(struct gsmd_msg_hdr)+PT_BUF_SIZE];
+
+int lgsm_passthrough(struct lgsm_handle *lh, const char *tx, char *rx, unsigned int *rx_len)
+{
+	struct gsmd_msg_hdr *gmh = (struct gsmd_msg_hdr *)passthrough_buf;
+	struct gsmd_msg_hdr *rgmh = (struct gsmd_msg_hdr *)passthrough_rbuf;
+	char *tx_buf = (char *)gmh + sizeof(*gmh);
+	char *rx_buf = (char *)rgmh + sizeof(*rgmh);
+	int len = strlen(tx);
+	int rc;
+
+	if (len > PT_BUF_SIZE)
+		return -EINVAL;
+
+	gmh->version = GSMD_PROTO_VERSION;
+	gmh->msg_type = GSMD_MSG_PASSTHROUGH;
+	gmh->msg_subtype = GSMD_PASSTHROUGH_REQUEST;
+	gmh->len = len;
+	strcpy(tx_buf, tx);
+
+	rc = lgsm_send(lh, gmh);
+	if (rc < len+sizeof(*gmh))
+		return rc;
+
+	/* since we synchronously want to wait for a response, we need to _internally_ loop over
+	 * incoming packets and call the callbacks for intermediate messages (if applicable) */
+	rc = lgsm_blocking_wait_packet(lh, gmh->id, passthrough_rbuf, sizeof(passthrough_rbuf));
+	if (rc <= 0)
+		return rc;
+
+	if (rc < sizeof(*rgmh))
+		return -EINVAL;
+
+	if (rc < sizeof(*rgmh) + rgmh->len)
+		return -EINVAL;
+	
+	/* FIXME: make sure rx_buf is zero-terminated */
+	strcpy(rx, rx_buf);
+	*rx_len = rgmh->len;
+
+	return rx_len;
+}

Modified: trunk/src/target/gsm/src/util/Makefile.am
===================================================================
--- trunk/src/target/gsm/src/util/Makefile.am	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/util/Makefile.am	2006-10-22 14:05:53 UTC (rev 96)
@@ -3,7 +3,7 @@
 
 bin_PROGRAMS = libgsmd-tool
 
-libgsmd_tool_SOURCES = libgsmd-tool.c
+libgsmd_tool_SOURCES = libgsmd-tool.c shell.c
 libgsmd_tool_LDADD = ../libgsmd/libgsmd.la
 libgsmd_tool_LDFLAGS = -dynamic
 

Modified: trunk/src/target/gsm/src/util/libgsmd-tool.c
===================================================================
--- trunk/src/target/gsm/src/util/libgsmd-tool.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/util/libgsmd-tool.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -8,13 +8,42 @@
 
 #include <libgsmd/libgsmd.h>
 
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
 static struct lgsm_handle *lgsmh;
 static int verbose = 0;
 
+enum mode_enum {
+	MODE_NONE,
+	MODE_SHELL,
+	MODE_EVENTLOG,
+};
+
+static char *modes[] = {
+	[MODE_NONE]	= "",
+	[MODE_SHELL]	= "shell",
+	[MODE_EVENTLOG]	= "eventlog",
+};
+
+static int parse_mode(char *modestr)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(modes); i++) {
+		if (!strcmp(modes[i], modestr))
+			return i;
+	}
+
+	return -1;
+}
+
 static struct option opts[] = {
 	{ "help", 0, 0, 'h' },
 	{ "version", 0, 0, 'V' },
 	{ "verbose", 0, 0, 'v' },
+	{ "mode", 1, 0, 'm' },
 	{ 0, 0, 0, 0 }
 };
 
@@ -28,14 +57,14 @@
 
 int main(int argc, char **argv)
 {
-	int rc, i;
+	int rc, i, mode;
 
 	printf("libgsm-tool - (C) 2006 by Harald Welte\n"
 		"This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n");
 
 	while (1) {
 		int c, option_index = 0;
-		c = getopt_long(argc, argv, "hVv", opts, &option_index);
+		c = getopt_long(argc, argv, "vVhm:", opts, &option_index);
 		if (c == -1)
 			break;
 
@@ -50,6 +79,13 @@
 			help();
 			exit(0);
 			break;
+		case 'm':
+			mode = parse_mode(optarg);
+			if (mode < 0) {
+				fprintf(stderr, "unknown/unsupported mode `%s'\n", optarg);
+				exit(2);
+			}
+			break;
 		}
 	}
 
@@ -59,6 +95,11 @@
 		exit(1);
 	}
 
+	switch (mode) {
+	case MODE_SHELL:
+		shell_main(lgsmh);
+		break;
+	}
 
 	exit(0);
 }

Added: trunk/src/target/gsm/src/util/shell.c
===================================================================
--- trunk/src/target/gsm/src/util/shell.c	2006-10-22 02:34:06 UTC (rev 95)
+++ trunk/src/target/gsm/src/util/shell.c	2006-10-22 14:05:53 UTC (rev 96)
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <string.h>
+
+#include <libgsmd/libgsmd.h>
+
+#define STDIN_BUF_SIZE	1024
+
+int shell_main(struct lgsmd_handle *lgsmh)
+{
+	int rc;
+	char buf[STDIN_BUF_SIZE+1];
+
+	while (1) {
+		rc = fscanf(stdin, "%s", buf);
+		if (rc == EOF) {
+			printf("EOF\n");
+			return -1;
+		}
+		if (rc <= 0) {
+			printf("NULL\n");
+			continue;
+		}
+		printf("STR=`%s'\n", buf);
+	}
+}





More information about the commitlog mailing list