[RFC] gsmd on HTC Magician

Philipp Zabel philipp.zabel at gmail.com
Fri Feb 16 20:09:26 CET 2007


Hi!

I tried to run gsmd on a HTC Magician, which (like Blueangel, Himalaya,
Alpine and Apache) is built around a TI Calypso GSM/GPRS chip, but with
a HTC-specific firmware.
I have attached the patch I used because I have some questions regarding
HTC specifics that look like they don't fit into a vendor plugin.

- I introduced the "ready" variable to stop the atcmd_select_cb from
  writing out commands until the "AT-Command Interpreter ready" message
  is seen. Also I commented out the call to "gsmd_initsettings" in
  gsmd.c. We only turn on power to the phone in the kernel when the tty
  is opened, so it takes a while for the interpreter to be ready. The
  unpatched gsmd would run the complete init sequence twice in this
  case. Is there a sane way for gsmd to support this behaviour?

- The HTC firmware envelopes all serial communication in frames which
  start with 0x02 0x02 0x16, followed by the data, followed by 0x02.
  0x16 indicates the AT command channel, there are other channels for
  debug messages and configuration of the GSM chip.
  I therefore added ti_htc_filter which filters the incoming AT channel
  out of the incoming communication (and drops the rest) and I added
  the envelope for outgoing data.
  Will there be a facility to plug in this kind of manipulation of the
  serial stream or should this be done somewhere else?

- The HTC firmware does not have support for +CTZR. Because of this
  the AT+CTZR=1 in the default init sequence produces an ERROR which
  somehow causes the init sequence not to complete. At least the vendor
  specific init commands are never called unless I comment out AT+CTZR.
  Is this expected behaviour?

Also the HTC firmware in my device only supports the parameters 0,1,2
for the call progress indication command (AT%CPI). I have no idea what
those parameters mean, is this documented somewhere or chipset specific?

thanks!
Philipp

Index: gsm/src/gsmd/atcmd.c
===================================================================
--- gsm/src/gsmd/atcmd.c	(revision 1018)
+++ gsm/src/gsmd/atcmd.c	(working copy)
@@ -20,6 +20,8 @@
  *
  */ 
 
+#define TI_HTC
+
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -40,6 +42,7 @@
 #include <gsmd/unsolicited.h>
 
 static void *__atcmd_ctx;
+static int ready = 0;
 
 enum final_result_codes {
 	GSMD_RESULT_OK = 0,
@@ -179,6 +182,7 @@
 	
 	if (!strcmp(buf, "AT-Command Interpreter ready")) {
 		gsmd_initsettings(g);
+		ready = 1;
 		return 0;
 	}
 
@@ -331,6 +335,56 @@
 	return rc;
 }	
 
+#ifdef TI_HTC
+/* filter AT frames from the TI HTC chipset */
+int ti_htc_filter(char *buf, unsigned int len)
+{
+	static int open_frame = 0;
+	char *src = buf;
+	char *end = src+len;
+	char *dst = buf;
+	int i;
+
+	/* strip 0x2 (0x2) 0x16 [data] 0x2 frames */
+	i = 0;
+	while (src < end) {
+		if (open_frame == 0) {
+			/* strip initial 0x02's */
+			while (*src == 0x2) {
+				if (src >= end)
+					return i;
+				src++;
+			}
+			open_frame = *src++;
+			if (src >= end)
+				return i;
+		}
+		/* only consider AT channel (0x16) */
+		if (open_frame == 0x16) {
+			/* read until frame end (0x02) */
+			while (*src != 0x2) {
+				if (src >= end)
+					return i;
+				*dst = *src;
+				dst++; i++;
+				src++;
+			}
+			open_frame = 0;
+		} else {
+			/* ignore until frame end (0x02) */
+			while (*src != 0x2) {
+				if (src >= end)
+					return i;
+				src++;
+			}
+			open_frame = 0;
+		}
+		/* next packet */
+	}
+	return i;
+}
+#endif
+
 /* callback to be called if [virtual] UART has some data for us */
 static int atcmd_select_cb(int fd, unsigned int what, void *data)
 {
@@ -348,6 +402,22 @@
 					strerror(errno));
 					return len;
 			}
+#ifdef TI_HTC
+			for (rc = 0; rc < len; rc++) {
+				if (rxbuf[rc] >= 32)
+					printf("%c", rxbuf[rc]);
+				else switch (rxbuf[rc]) {
+				case 0xd:
+					printf("\\r");break;
+				case 0xa:
+					printf("\\n");break;
+				default:
+					printf("\\x%x", rxbuf[rc]);
+				}
+			}
+			printf("\n");
+			len = ti_htc_filter(rxbuf, len);
+#endif
 			rc = llparse_string(&g->llp, rxbuf, len);
 			if (rc < 0) {
 				gsmd_log(GSMD_ERROR, "ERROR during llparse_string: %d\n", rc);
@@ -357,9 +427,12 @@
 	}
 
 	/* write pending commands to UART */
-	if (what & GSMD_FD_WRITE) {
+	if ((what & GSMD_FD_WRITE) && (ready)) {
 		struct gsmd_atcmd *pos, *pos2;
 		llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
+#ifdef TI_HTC
+			write(fd, "\x02\x16", 2);
+#endif
 			len = strlen(pos->buf);
 			rc = write(fd, pos->buf, strlen(pos->buf));
 			if (rc == 0) {
@@ -374,7 +447,11 @@
 				gsmd_log(GSMD_FATAL, "short write!!! FIXME!\n");
 				exit(3);
 			}
+#ifdef TI_HTC
+			write(fd, "\r\x02", 2);
+#else
 			write(fd, "\r", 1);
+#endif
 			/* success: remove from global list of to-be-sent atcmds */
 			llist_del(&pos->list);
 			/* append to global list of executing atcmds */
Index: vendor_ti.c
===================================================================
--- vendor_ti.c	(revision 1018)
+++ vendor_ti.c	(working copy)
@@ -99,6 +99,32 @@
 	return -EIO;
 }
 
+static int htccsq_parse(char *buf, int len, const char *param,
+		     struct gsmd *gsmd)
+{
+	char *tok;
+	struct gsmd_evt_auxdata *aux;
+	struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_SIGNAL,
+					     sizeof(*aux));
+
+	DEBUGP("entering csq_parse param=`%s'\n", param);
+	if (!ucmd)
+		return -EINVAL;
+
+/* fixme: what does %HTCCSQ return, actually? */
+	aux->u.signal.sigq.rssi = atoi(param);
+//	aux->u.signal.sigq.ber = atoi(param);
+
+	DEBUGP("sending EVT_SIGNAL\n");
+	usock_evt_send(gsmd, ucmd, GSMD_EVT_SIGNAL);
+
+	return 0;
+
+out_free_io:
+	free(ucmd);
+	return -EIO;
+}
+
 static int cpri_parse(char *buf, int len, const char *param, struct gsmd *gsmd)
 {
 	/* FIXME: parse ciphering indication */
@@ -184,6 +210,7 @@
 
 static const struct gsmd_unsolicit ticalypso_unsolicit[] = {
 	{ "\%CSQ",	&csq_parse },	/* Signal Quality */
+	{ "\%HTCCSQ",	&htccsq_parse },/* Signal Quality */
 	{ "\%CPRI",	&cpri_parse },	/* Ciphering Indication */
 	{ "\%CPI",	&cpi_parse },	/* Call Progress Information */
 
@@ -208,12 +235,13 @@
 static int ticalypso_initsettings(struct gsmd *g)
 {
 	int rc;
-	/* enable %CPI: call progress indication */
-	rc = gsmd_simplecmd(g, "AT\%CPI=3");
+//	/* enable %CPI: call progress indication */
+//	rc = gsmd_simplecmd(g, "AT\%CPI=3");		// HTC only supports 0,1,2
 	/* enable %CPRI: ciphering indications */
 	rc |= gsmd_simplecmd(g, "AT\%CPRI=1");
 	/* enable %CSQ: signal quality reports */
-	rc |= gsmd_simplecmd(g, "AT\%CSQ=1");
+//	rc |= gsmd_simplecmd(g, "AT\%CSQ=1");		// %HTCCSQ instead
+	rc |= gsmd_simplecmd(g, "AT\%HTCCSQ=1");
 	/* send unsolicited commands at any time */
 	rc |= gsmd_simplecmd(g, "AT\%CUNS=0");
 
Index: gsmd.c
===================================================================
--- gsmd.c	(revision 1018)
+++ gsmd.c	(working copy)
@@ -76,8 +76,8 @@
 	rc |= gsmd_simplecmd(gsmd, "AT+CLIP=1");
 	/* use +COLP: to indicate COLP */
 	rc |= gsmd_simplecmd(gsmd, "AT+COLP=1");
-	/* use +CTZR: to report time zone changes */
-	rc |= gsmd_simplecmd(gsmd, "AT+CTZR=1");
+//	/* use +CTZR: to report time zone changes */
+//	rc |= gsmd_simplecmd(gsmd, "AT+CTZR=1");
 	/* power on the phone */
 	rc |= gsmd_simplecmd(gsmd, "AT+CFUN=1");
 
@@ -282,7 +282,7 @@
 
 	gsmd_vendor_plugin_find(&g);
 
-	gsmd_initsettings(&g);
+//	gsmd_initsettings(&g);	/* <-- called after receiving "interpreter ready" */
 
 	while (1) {
 		int ret = gsmd_select_main();





More information about the gsmd-devel mailing list