libgsmd: experimental plugin infrastructure for magician and universal
authorPhilipp Zabel <philipp.zabel@gmail.com>
Thu, 5 Apr 2007 09:04:17 +0000 (09:04 +0000)
committerPhilipp Zabel <philipp.zabel@gmail.com>
Thu, 5 Apr 2007 09:04:17 +0000 (09:04 +0000)
- subject to change

packages/gsm/files/htcuniversal/.mtn2git_empty [new file with mode: 0644]
packages/gsm/files/htcuniversal/default [new file with mode: 0644]
packages/gsm/files/interpreter-ready.patch [deleted file]
packages/gsm/files/magician/default
packages/gsm/files/magician/ldisc.patch [deleted file]
packages/gsm/files/magician/vendor-tihtc.patch [deleted file]
packages/gsm/files/numeric.patch [new file with mode: 0644]
packages/gsm/files/plugin.patch [new file with mode: 0644]
packages/gsm/libgsmd_svn.bb

diff --git a/packages/gsm/files/htcuniversal/.mtn2git_empty b/packages/gsm/files/htcuniversal/.mtn2git_empty
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/packages/gsm/files/htcuniversal/default b/packages/gsm/files/htcuniversal/default
new file mode 100644 (file)
index 0000000..3c9a8da
--- /dev/null
@@ -0,0 +1,10 @@
+# gsmd This shell script configures for the gsmd init script.
+
+GSMD_OPTS="-s 115200 -F"
+
+# If your GSM device needs to be powered up, uncomment and modify the next line
+#GSM_POW="/sys/bus/platform/devices/gta01-pm-gsm.0/power_on"
+
+# this should be in a common /etc/default/serial, together
+# with BT_DEV, and IR_DEV
+GSM_DEV="/dev/ttyS0"
diff --git a/packages/gsm/files/interpreter-ready.patch b/packages/gsm/files/interpreter-ready.patch
deleted file mode 100644 (file)
index cc6b9c6..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Index: gsm/include/gsmd/gsmd.h
-===================================================================
---- gsm.orig/include/gsmd/gsmd.h       2007-03-29 17:07:10.000000000 +0200
-+++ gsm/include/gsmd/gsmd.h    2007-03-29 17:07:43.000000000 +0200
-@@ -58,6 +58,7 @@
- struct gsmd {
-       unsigned int flags;
-+      int interpreter_ready;
-       struct gsmd_fd gfd_uart;
-       struct gsmd_fd gfd_sock;
-       struct llparser llp;
-Index: gsm/src/gsmd/atcmd.c
-===================================================================
---- gsm.orig/src/gsmd/atcmd.c  2007-03-29 17:06:01.000000000 +0200
-+++ gsm/src/gsmd/atcmd.c       2007-03-29 17:08:27.000000000 +0200
-@@ -183,6 +183,7 @@
-        * an empty string or that 'ready' string, we need to init the modem */
-       if (strlen(buf) == 0 ||
-           !strcmp(buf, "AT-Command Interpreter ready")) {
-+              g->interpreter_ready = 1;
-               gsmd_initsettings(g);
-               return 0;
-       }
-@@ -372,7 +373,7 @@
-       }
-       /* write pending commands to UART */
--      if (what & GSMD_FD_WRITE) {
-+      if ((what & GSMD_FD_WRITE) && g->interpreter_ready) {
-               struct gsmd_atcmd *pos, *pos2;
-               llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
-                       len = strlen(pos->buf);
-Index: gsm/src/gsmd/gsmd.c
-===================================================================
---- gsm.orig/src/gsmd/gsmd.c   2007-03-29 17:06:04.000000000 +0200
-+++ gsm/src/gsmd/gsmd.c        2007-03-29 17:08:59.000000000 +0200
-@@ -291,7 +291,8 @@
-       gsmd_vendor_plugin_find(&g);
--      gsmd_initsettings(&g);
-+      if (g.interpreter_ready)
-+              gsmd_initsettings(&g);
-       gsmd_opname_init(&g);
index a9c3b94..523d0b9 100644 (file)
@@ -1,9 +1,10 @@
 # gsmd This shell script configures for the gsmd init script.
 
-# Set line Discipline 17 (N_TIHTC), needs ldisc.patch-ed gsmd
-GSMD_OPTS="-s 115200 -F -D 17"
+GSMD_OPTS="-s 115200 -F"
 
 # If your GSM device needs to be powered up, uncomment and modify the next line
 #GSM_POW="/sys/bus/platform/devices/gta01-pm-gsm.0/power_on"
 
+# this should be in a common /etc/default/serial, together
+# with BT_DEV, and IR_DEV
 GSM_DEV="/dev/ttyS1"
diff --git a/packages/gsm/files/magician/ldisc.patch b/packages/gsm/files/magician/ldisc.patch
deleted file mode 100644 (file)
index 30d4a88..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-Index: gsm/src/gsmd/gsmd.c
-===================================================================
---- gsm.orig/src/gsmd/gsmd.c   2007-03-29 15:29:31.000000000 +0200
-+++ gsm/src/gsmd/gsmd.c        2007-03-29 15:33:07.000000000 +0200
-@@ -32,6 +32,7 @@
- #define _GNU_SOURCE
- #include <getopt.h>
-+#include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-@@ -150,6 +151,7 @@
-       { "speed", 1, NULL, 's' },
-       { "logfile", 1, NULL, 'l' },
-       { "hwflow", 0, NULL, 'F' },
-+      { "ldisc", 1, NULL, 'D' },
-       { "leak-report", 0, NULL, 'L' },
-       { 0, 0, 0, 0 }
- };
-@@ -165,6 +167,7 @@
-              "\t-p dev\t--device dev\tSpecify serial device to be used\n"
-              "\t-s spd\t--speed spd\tSpecify speed in bps (9600,38400,115200,...)\n"
-              "\t-F\t--hwflow\tHardware Flow Control (RTS/CTS)\n"
-+             "\t-D\t--ldisc num\tSet line discipline (0=N_TTY,...)\n"
-              "\t-L\t--leak-report\tLeak Report of talloc memory allocator\n"
-              "\t-l file\t--logfile file\tSpecify a logfile to log to\n"
-              );
-@@ -191,6 +194,7 @@
-       int daemonize = 0;
-       int bps = 115200;
-       int hwflow = 0;
-+      int ldisc = 0;
-       char *device = "/dev/ttyUSB0";
-       char *logfile = "syslog";
-@@ -202,7 +206,7 @@
-       gsmd_tallocs = talloc_named_const(NULL, 1, "GSMD");
-       /*FIXME: parse commandline, set daemonize, device, ... */
--      while ((argch = getopt_long(argc, argv, "FVLdhp:s:l:", opts, NULL)) != -1) {
-+      while ((argch = getopt_long(argc, argv, "FVLdhp:s:l:D:", opts, NULL)) != -1) {
-               switch (argch) {
-               case 'V':
-                       /* FIXME */
-@@ -232,6 +236,8 @@
-                               fprintf(stderr, "can't open logfile `%s'\n", optarg);
-                               exit(2);
-                       }
-+              case 'D':
-+                      ldisc = atoi(optarg);
-                       break;
-               }
-       }
-@@ -249,6 +255,11 @@
-               exit(1);
-       }
-+      if (ldisc && ioctl(fd, TIOCSETD, &ldisc) < 0) {
-+              fprintf(stderr, "can't set line discipline\n");
-+              exit(1);
-+      }
-+
-       if (gsmd_initialize(&g) < 0) {
-               fprintf(stderr, "internal error\n");
-               exit(1);
diff --git a/packages/gsm/files/magician/vendor-tihtc.patch b/packages/gsm/files/magician/vendor-tihtc.patch
deleted file mode 100644 (file)
index a2f22ff..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-Index: gsm/src/gsmd/vendor_tihtc.c
-===================================================================
---- /dev/null  1970-01-01 00:00:00.000000000 +0000
-+++ gsm/src/gsmd/vendor_tihtc.c        2007-03-27 13:12:05.000000000 +0200
-@@ -0,0 +1,294 @@
-+/* TI [Calypso] with HTC firmware gsmd plugin
-+ *
-+ * Written by Philipp Zabel <philipp.zabel@gmail.com>
-+ * based on vendor_ti.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along
-+ * with this program; if not, write to the Free Software Foundation, Inc.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
-+
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdio.h>
-+#include <errno.h>
-+
-+#include "gsmd.h"
-+
-+#include <gsmd/gsmd.h>
-+#include <gsmd/usock.h>
-+#include <gsmd/event.h>
-+#include <gsmd/talloc.h>
-+#include <gsmd/extrsp.h>
-+#include <gsmd/atcmd.h>
-+#include <gsmd/vendorplugin.h>
-+#include <gsmd/unsolicited.h>
-+
-+#if 0
-+#include "vendorplugin.h"
-+
-+static int
-+ti_getopt(struct gsmd *gh, int optname, void *optval, int *optlen)
-+{
-+      switch (optname) {
-+      case GSMD_OPT_CIPHER_IND:
-+              /* FIXME: send AT%CPRI=? */
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+static int
-+ti_setopt(struct gsmd *gh, int optname, const void *optval, int optlen)
-+{
-+      switch (optname) {
-+      case GSMD_OPT_CIPHER_IND:
-+              /* FIXME: send AT%CPRI= */
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+#endif
-+
-+
-+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 htccsq_parse param=`%s'\n", param);
-+      if (!ucmd)
-+              return -EINVAL;
-+
-+
-+      aux = (struct gsmd_evt_auxdata *) ucmd->buf;
-+
-+      /* FIXME: contains values 1-5, should be mapped to 0-31 somehow? */
-+      /* 2 --> 11 */
-+      aux->u.signal.sigq.rssi = atoi(buf);
-+      aux->u.signal.sigq.ber = 99;
-+
-+      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)
-+{
-+      char *tok1, *tok2;
-+
-+      tok1 = strtok(buf, ",");
-+      if (!tok1)
-+              return -EIO;
-+
-+      tok2 = strtok(NULL, ",");
-+      if (!tok2) {
-+              switch (atoi(tok1)) {
-+              case 0:
-+                      gsmd->dev_state.ciph_ind.flags &= ~GSMD_CIPHIND_ACTIVE;
-+                      break;
-+              case 1:
-+                      gsmd->dev_state.ciph_ind.flags |= GSMD_CIPHIND_ACTIVE;
-+                      break;
-+              case 2:
-+                      gsmd->dev_state.ciph_ind.flags |= GSMD_CIPHIND_DISABLED_SIM;
-+                      break;
-+              }
-+      } else {
-+              struct gsmd_evt_auxdata *aux;
-+              struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
-+                                                         GSMD_EVT_CIPHER,
-+                                                         sizeof(*aux));
-+              if (!ucmd)
-+                      return -ENOMEM;
-+
-+              aux = (struct gsmd_evt_auxdata *) ucmd->buf;
-+
-+              aux->u.cipher.net_state_gsm = atoi(tok1);
-+              aux->u.cipher.net_state_gsm = atoi(tok2);
-+
-+              usock_evt_send(gsmd, ucmd, GSMD_EVT_CIPHER);
-+      }
-+
-+      return 0;
-+}
-+
-+/* Call Progress Information */
-+static int cpi_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_OUT_STATUS,
-+                                                 sizeof(*aux));
-+
-+      DEBUGP("entering cpi_parse param=`%s'\n", param);
-+      if (!ucmd)
-+              return -EINVAL;
-+
-+      aux = (struct gsmd_evt_auxdata *) ucmd->buf;
-+
-+      /* Format: cId, msgType, ibt, tch, dir,[mode],[number],[type],[alpha],[cause],line */
-+
-+      /* call ID */
-+      tok = strtok(buf, ",");
-+      if (!tok)
-+              goto out_free_io;
-+
-+      /* message type (layer 3) */
-+      tok = strtok(NULL, ",");
-+      if (!tok)
-+              goto out_free_io;
-+      aux->u.call_status.prog = atoi(tok);
-+
-+      /* in-band tones */
-+      tok = strtok(NULL, ",");
-+      if (!tok)
-+              goto out_free_io;
-+
-+      if (*tok == '1')
-+              aux->u.call_status.ibt = 1;
-+      else
-+              aux->u.call_status.ibt = 0;
-+
-+      /* TCH allocated */
-+      tok = strtok(NULL, ",");
-+      if (!tok)
-+              goto out_free_io;
-+
-+      if (*tok == '1')
-+              aux->u.call_status.tch = 1;
-+      else
-+              aux->u.call_status.tch = 0;
-+
-+      /* direction */
-+      tok = strtok(NULL, ",");
-+      if (!tok)
-+              goto out_send;
-+
-+      switch (*tok) {
-+      case '0':
-+      case '1':
-+      case '2':
-+      case '3':
-+              aux->u.call_status.dir = (*tok - '0');
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      /* mode */
-+      tok = strtok(NULL, ",");
-+      if (!tok)
-+              goto out_send;
-+
-+out_send:
-+      usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_STATUS);
-+
-+      return 0;
-+
-+out_free_io:
-+      talloc_free(ucmd);
-+      return -EIO;
-+}
-+
-+static const struct gsmd_unsolicit tihtc_unsolicit[] = {
-+      { "%HTCCSQ",    &htccsq_parse },        /* Signal Quality */
-+      { "%CPRI",      &cpri_parse },  /* Ciphering Indication */
-+      { "%CPI",       &cpi_parse },   /* Call Progress Information */
-+
-+      /* FIXME: parse the below and generate the respective events */
-+
-+      /* %CGREG: reports extended information about GPRS registration state */
-+};
-+
-+static int cpi_detect_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
-+{
-+      struct gsmd *g = ctx;
-+      struct gsm_extrsp *er;
-+
-+      if (strncmp(resp, "%CPI: ", 6))
-+              return -EINVAL;
-+      resp += 6;
-+
-+      er = extrsp_parse(cmd, resp);
-+      if (!er)
-+              return -EINVAL;
-+
-+      if (extrsp_supports(er, 0, 3))
-+              return gsmd_simplecmd(g, "AT%CPI=3");
-+      else if (extrsp_supports(er, 0, 2))
-+              return gsmd_simplecmd(g, "AT%CPI=2");
-+      else
-+              DEBUGP("Call Progress Indication mode 2 or 3 not supported!!\n");
-+
-+      talloc_free(er);
-+      return 0;
-+}
-+
-+static int tihtc_detect(struct gsmd *g)
-+{
-+      /* FIXME: do actual detection of vendor if we have multiple vendors */
-+      /* open /proc/cpuinfo and check for HTC Magician or HTC Blueangel? */
-+      /* check for N_TIHTC ldisc? or set it ourselves? */
-+      return 1;
-+}
-+
-+static int tihtc_initsettings(struct gsmd *g)
-+{
-+      int rc;
-+      struct gsmd_atcmd *cmd;
-+
-+      /* use %CGREG */
-+      //rc |= gsmd_simplecmd(g, "AT%CGREG=3");
-+      /* enable %CPRI: ciphering indications */
-+      rc |= gsmd_simplecmd(g, "AT%CPRI=1");
-+      /* enable %HTCCSQ: signal quality reports */
-+      rc |= gsmd_simplecmd(g, "AT%HTCCSQ=1");
-+      /* send unsolicited commands at any time */
-+      rc |= gsmd_simplecmd(g, "AT%CUNS=0");
-+
-+      /* enable %CPI: call progress indication */
-+      cmd = atcmd_fill("AT%CPI=?", 9, &cpi_detect_cb, g, 0);
-+      if (cmd)
-+              atcmd_submit(g, cmd);
-+
-+      return rc;
-+}
-+
-+static struct gsmd_vendor_plugin plugin_tihtc = {
-+      .name = "TI Calypso / HTC firmware",
-+      .num_unsolicit = ARRAY_SIZE(tihtc_unsolicit),
-+      .unsolicit = tihtc_unsolicit,
-+      .detect = &tihtc_detect,
-+      .initsettings = &tihtc_initsettings,
-+};
-+
-+/* FIXME: this will be _init() when we make this a plugin */
-+int tihtc_init(void)
-+{
-+      return gsmd_vendor_plugin_register(&plugin_tihtc);
-+}
-Index: gsm/src/gsmd/gsmd.c
-===================================================================
---- gsm.orig/src/gsmd/gsmd.c   2007-03-27 13:07:59.000000000 +0200
-+++ gsm/src/gsmd/gsmd.c        2007-03-27 13:08:08.000000000 +0200
-@@ -276,7 +276,7 @@
-       }
-       /* FIXME: do this dynamically */
--      ticalypso_init();
-+      tihtc_init();
-       gsmd_vendor_plugin_find(&g);
-Index: gsm/src/gsmd/Makefile.am
-===================================================================
---- gsm.orig/src/gsmd/Makefile.am      2007-03-27 13:09:11.000000000 +0200
-+++ gsm/src/gsmd/Makefile.am   2007-03-27 13:09:20.000000000 +0200
-@@ -4,7 +4,7 @@
- sbin_PROGRAMS = gsmd
- gsmd_SOURCES = gsmd.c atcmd.c select.c vendor.c usock.c unsolicited.c log.c \
--             vendor_ti.c talloc.c operator_cache.c ext_response.c
-+             vendor_ti.c vendor_tihtc.c talloc.c operator_cache.c ext_response.c
- #gsmd_LDADD = ../libgsmd/libgsmd.la
- #gsmd_LDFLAGS = -dynamic
diff --git a/packages/gsm/files/numeric.patch b/packages/gsm/files/numeric.patch
new file mode 100644 (file)
index 0000000..cd1990c
--- /dev/null
@@ -0,0 +1,56 @@
+Index: gsm/src/gsmd/atcmd.c
+===================================================================
+--- gsm.orig/src/gsmd/atcmd.c  2007-04-02 09:59:16.000000000 +0200
++++ gsm/src/gsmd/atcmd.c       2007-04-02 10:10:54.000000000 +0200
+@@ -207,7 +207,7 @@
+        *    TBD
+        */
+-      if (buf[0] == '+' || buf[0] == '%') {
++      if (buf[0] == '+' || buf[0] == '%' || buf[0] == '@') {
+               /* an extended response */
+               const char *colon = strchr(buf, ':');
+               if (!colon) {
+@@ -269,14 +269,13 @@
+                       memcpy(cmd->buf, buf, len);
+               }
+       } else {
+-              if (!strcmp(buf, "RING")) {
++              if (!strcmp(buf, "RING") || buf[0] == '2') {
+                       /* this is the only non-extended unsolicited return
+                        * code, part of Case 'B' */
+                       return unsolicited_parse(g, buf, len, NULL);
+               }
+-              if (!strcmp(buf, "ERROR") ||
+-                  ((g->flags & GSMD_FLAG_V0) && buf[0] == '4')) {
++              if (!strcmp(buf, "ERROR") || buf[0] == '4') {
+                       /* Part of Case 'C' */
+                       DEBUGP("unspecified error\n");
+                       if (cmd)
+@@ -285,8 +284,7 @@
+                       goto final_cb;
+               }
+-              if (!strncmp(buf, "OK", 2)
+-                  || ((g->flags & GSMD_FLAG_V0) && buf[0] == '0')) {
++              if (!strncmp(buf, "OK", 2) || buf[0] == '0') {
+                       /* Part of Case 'C' */
+                       if (cmd)
+                               cmd->ret = 0;
+@@ -296,13 +294,13 @@
+               /* FIXME: handling of those special commands in response to
+                * ATD / ATA */
+-              if (!strncmp(buf, "NO CARRIER", 11)) {
++              if (!strncmp(buf, "NO CARRIER", 11) || buf[0] == '3') {
+                       /* Part of Case 'D' */
+                       final = 1;
+                       goto final_cb;
+               }
+-              if (!strncmp(buf, "BUSY", 4)) {
++              if (!strncmp(buf, "BUSY", 4) || buf[0] == '7') {
+                       /* Part of Case 'D' */
+                       final = 1;
+                       goto final_cb;
diff --git a/packages/gsm/files/plugin.patch b/packages/gsm/files/plugin.patch
new file mode 100644 (file)
index 0000000..7f455ce
--- /dev/null
@@ -0,0 +1,935 @@
+Index: gsm/include/gsmd/gsmd.h
+===================================================================
+--- gsm.orig/include/gsmd/gsmd.h       2007-04-02 09:58:55.000000000 +0200
++++ gsm/include/gsmd/gsmd.h    2007-04-02 11:03:41.000000000 +0200
+@@ -7,6 +7,7 @@
+ #include <common/linux_list.h>
++#include <gsmd/machineplugin.h>
+ #include <gsmd/vendorplugin.h>
+ #include <gsmd/select.h>
+ #include <gsmd/state.h>
+@@ -58,12 +59,14 @@
+ struct gsmd {
+       unsigned int flags;
++      int interpreter_ready;
+       struct gsmd_fd gfd_uart;
+       struct gsmd_fd gfd_sock;
+       struct llparser llp;
+       struct llist_head users;
+       struct llist_head pending_atcmds;       /* our busy gsmd_atcmds */
+       struct llist_head busy_atcmds;  /* our busy gsmd_atcmds */
++      struct gsmd_machine_plugin *machinepl;
+       struct gsmd_vendor_plugin *vendorpl;
+       struct gsmd_device_state dev_state;
+Index: gsm/include/gsmd/machineplugin.h
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ gsm/include/gsmd/machineplugin.h   2007-04-02 11:03:41.000000000 +0200
+@@ -0,0 +1,24 @@
++#ifndef _GSMD_MACHINEPLUG_H
++#define _GSMD_MACHINEPLUG_H
++
++#ifdef __GSMD__
++
++#include <common/linux_list.h>
++#include <gsmd/gsmd.h>
++
++struct gsmd;
++
++struct gsmd_machine_plugin {
++      struct llist_head list;
++      unsigned char *name;
++      int (*detect)(struct gsmd *g);
++      int (*init)(struct gsmd *g, int fd);
++};
++
++extern int gsmd_machine_plugin_register(struct gsmd_machine_plugin *pl);
++extern void gsmd_machine_plugin_unregister(struct gsmd_machine_plugin *pl);
++extern int gsmd_machine_plugin_find(struct gsmd *g);
++
++#endif /* __GSMD__ */
++
++#endif
+Index: gsm/src/gsmd/machine_tihtc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ gsm/src/gsmd/machine_tihtc.c       2007-04-02 11:03:41.000000000 +0200
+@@ -0,0 +1,71 @@
++/* TI [Calypso] with HTC firmware machine plugin
++ *
++ * Written by Philipp Zabel <philipp.zabel@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++#include <sys/ioctl.h>
++
++#include "gsmd.h"
++
++#include <gsmd/gsmd.h>
++#include <gsmd/usock.h>
++#include <gsmd/event.h>
++#include <gsmd/talloc.h>
++#include <gsmd/extrsp.h>
++#include <gsmd/machineplugin.h>
++
++#define N_TIHTC 17
++
++static int tihtc_detect(struct gsmd *g)
++{
++      /* FIXME: do actual detection of machine if we have multiple machines */
++      return 1;
++}
++
++static int tihtc_init(struct gsmd *g, int fd)
++{
++      int ldisc = N_TIHTC;
++      int rc;
++
++      /*
++       * Himalaya, Blueangel, Alpine and Magican
++       * power up their GSM chipsets when the
++       * tty is opened. Wait for the "AT-Command
++       * Interpreter ready" message before trying
++       * to send commands.
++       */
++      g->interpreter_ready = 0;
++
++      /* Set the line discipline to N_TIHTC */
++      rc = ioctl(fd, TIOCSETD, &ldisc);
++      if (rc < 0)
++              fprintf(stderr, "can't set line discipline\n");
++
++      return rc;
++}
++
++struct gsmd_machine_plugin gsmd_machine_plugin = {
++      .name = "TI Calypso / HTC firmware",
++      .detect = &tihtc_detect,
++      .init = &tihtc_init,
++};
+Index: gsm/src/gsmd/machine_generic.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ gsm/src/gsmd/machine_generic.c     2007-04-02 11:03:41.000000000 +0200
+@@ -0,0 +1,61 @@
++/* generic machine plugin
++ *
++ * Written by Philipp Zabel <philipp.zabel@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#include "gsmd.h"
++
++#include <gsmd/gsmd.h>
++#include <gsmd/usock.h>
++#include <gsmd/event.h>
++#include <gsmd/talloc.h>
++#include <gsmd/extrsp.h>
++#include <gsmd/machineplugin.h>
++
++static int generic_detect(struct gsmd *g)
++{
++      /* FIXME: do actual detection of machine if we have multiple machines */
++      return 1;
++}
++
++static int generic_init(struct gsmd *g, int fd)
++{
++      int rc;
++
++      /*
++       * We assume that the GSM chipset can take
++       * input immediately, so we don't have to
++       * wait for the "AT-Command Interpreter ready"
++       * message before trying to send commands.
++       */
++      g->interpreter_ready = 1;
++
++      return 0;
++}
++
++struct gsmd_machine_plugin gsmd_machine_plugin = {
++      .name = "generic",
++      .detect = &generic_detect,
++      .init = &generic_init,
++};
+Index: gsm/src/gsmd/machine.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ gsm/src/gsmd/machine.c     2007-04-02 13:43:04.000000000 +0200
+@@ -0,0 +1,140 @@
++/* gsmd machine plugin core
++ *
++ * Written by Philipp Zabel <philipp.zabel@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ */
++
++#include <dlfcn.h>
++#include <errno.h>
++#include <stdio.h>
++#include <string.h>
++
++#include <common/linux_list.h>
++
++#include "gsmd.h"
++
++#include <gsmd/gsmd.h>
++#include <gsmd/machineplugin.h>
++
++static LLIST_HEAD(machinepl_list);
++
++int gsmd_machine_plugin_register(struct gsmd_machine_plugin *pl)
++{
++      llist_add(&pl->list, &machinepl_list);
++
++      return 0;
++}
++
++void gsmd_machine_plugin_unregister(struct gsmd_machine_plugin *pl)
++{
++      llist_del(&pl->list);
++}
++
++int gsmd_machine_plugin_find(struct gsmd *g)
++{
++      struct gsmd_machine_plugin *pl;
++
++      if (g->machinepl)
++              return -EEXIST;
++
++      llist_for_each_entry(pl, &machinepl_list, list) {
++              if (pl->detect(g) == 1) {
++                      DEBUGP("selecting machine plugin \"%s\"\n", pl->name);
++                      g->machinepl = pl;
++                      return 1;
++              }
++      }
++
++      return 0;
++}
++
++int gsmd_machine_plugin_load(char *name)
++{
++      int rc = -1;
++      void *plugin;
++      struct gsmd_machine_plugin *pl;
++      char buf[128];
++
++      DEBUGP("loading machine plugin \"%s\"\n", name);
++
++      snprintf(buf, sizeof(buf), PLUGINDIR"/libgsmd-machine_%s.so", name);
++
++      plugin = dlopen(buf, RTLD_LAZY);
++      if (!plugin) {
++              fprintf(stderr, "gsmd_machine_plugin_load: %s\n", dlerror());
++              return -1;
++      }
++
++      pl = dlsym(plugin, "gsmd_machine_plugin");
++      if (pl)
++              rc = gsmd_machine_plugin_register(pl);
++      else
++              dlclose(plugin);
++
++      return rc;
++}
++
++/* maybe /etc/gsmd/cpuinfo */
++struct machines {
++      char *cpuinfo;
++      char *machine;
++      char *vendor;
++} machines[] = {
++      { "GTA01",              "generic",      "ti" },
++      { "HTC Blueangel",      "tihtc",        "tihtc" },
++      { "HTC Himalaya",       "tihtc",        "tihtc" },
++      { "HTC Magician",       "tihtc",        "tihtc" },
++      { "HTC Universal",      "generic",      "qc" },
++      { NULL, NULL, NULL },
++};
++
++int gsmd_machine_plugin_init(struct gsmd *g, int fd)
++{
++      FILE *cpuinfo;
++      char buf[1024];
++      char *line, *machine = NULL;
++      int i, rc;
++
++      cpuinfo = fopen("/proc/cpuinfo", "r");
++      fread(buf, sizeof(buf), 1, cpuinfo);
++      fclose(cpuinfo);
++
++      line = strtok(buf, "\n");
++      while (line = strtok(NULL, "\n")) {
++              if (strncmp(line, "Hardware\t: ", 11) == 0) {
++                      machine = line+11;
++                      break;
++              }
++      }
++      /* FIXME: do this dynamically */
++      if (machine) {
++              for (i = 0; machines[i].cpuinfo; i++) {
++                      if (strcmp(machine, machines[i].cpuinfo) == 0) {
++                              DEBUGP("detected %s\n", machine);
++                              rc = gsmd_machine_plugin_load(machines[i].machine);
++                              rc |= gsmd_vendor_plugin_load(machines[i].vendor);
++                              return rc;
++                      }
++              }
++      }
++      /* load generic machine and all vendor plugins */
++      rc = gsmd_machine_plugin_load("generic");
++      gsmd_vendor_plugin_load("ti");
++      gsmd_vendor_plugin_load("tihtc");
++      gsmd_vendor_plugin_load("qc");
++      return rc;
++}
+Index: gsm/src/gsmd/vendor_qc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ gsm/src/gsmd/vendor_qc.c   2007-04-02 11:03:41.000000000 +0200
+@@ -0,0 +1,104 @@
++/* Qualcomm [msm6250] gsmd plugin
++ *
++ * Written by Philipp Zabel <philipp.zabel@gmail.com>
++ * based on vendor_ti.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#include "gsmd.h"
++
++#include <gsmd/gsmd.h>
++#include <gsmd/usock.h>
++#include <gsmd/event.h>
++#include <gsmd/talloc.h>
++#include <gsmd/extrsp.h>
++#include <gsmd/atcmd.h>
++#include <gsmd/vendorplugin.h>
++#include <gsmd/unsolicited.h>
++
++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));
++      static int rssi_table[] = { 0,5,10,15,20,25,99 }; /* FIXME */
++      unsigned int i;
++
++      DEBUGP("entering htccsq_parse param=`%s'\n", param);
++      if (!ucmd)
++              return -EINVAL;
++
++
++      aux = (struct gsmd_evt_auxdata *) ucmd->buf;
++
++      i = atoi(buf);
++      if (i > 6)
++              i = 6;
++      aux->u.signal.sigq.rssi = rssi_table[atoi(buf)];
++      aux->u.signal.sigq.ber = 99;
++
++      DEBUGP("sending EVT_SIGNAL\n");
++      usock_evt_send(gsmd, ucmd, GSMD_EVT_SIGNAL);
++
++      return 0;
++
++out_free_io:
++      free(ucmd);
++      return -EIO;
++}
++
++static const struct gsmd_unsolicit qc_unsolicit[] = {
++      { "@HTCCSQ",    &htccsq_parse },        /* Signal Quality */
++
++      /* FIXME: parse the below and generate the respective events */
++
++      /* %CGREG: reports extended information about GPRS registration state */
++};
++
++static int qc_detect(struct gsmd *g)
++{
++      /* FIXME: do actual detection of vendor if we have multiple vendors */
++      /* open /proc/cpuinfo and check for HTC Universal? */
++      return 1;
++}
++
++static int qc_initsettings(struct gsmd *g)
++{
++      int rc;
++      struct gsmd_atcmd *cmd;
++
++      /* enable @HTCCSQ: signal quality reports */
++      rc |= gsmd_simplecmd(g, "AT@HTCCSQ=1");
++
++      return rc;
++}
++
++struct gsmd_vendor_plugin gsmd_vendor_plugin = {
++      .name = "Qualcomm msm6250",
++      .num_unsolicit = ARRAY_SIZE(qc_unsolicit),
++      .unsolicit = qc_unsolicit,
++      .detect = &qc_detect,
++      .initsettings = &qc_initsettings,
++};
+Index: gsm/src/gsmd/Makefile.am
+===================================================================
+--- gsm.orig/src/gsmd/Makefile.am      2007-04-02 09:58:55.000000000 +0200
++++ gsm/src/gsmd/Makefile.am   2007-04-02 13:33:11.000000000 +0200
+@@ -1,11 +1,26 @@
+ INCLUDES = $(all_includes) -I$(top_srcdir)/include
+ AM_CFLAGS = -std=gnu99
++plugindir = $(libdir)/gsmd
+ sbin_PROGRAMS = gsmd
+-gsmd_SOURCES = gsmd.c atcmd.c select.c vendor.c usock.c unsolicited.c log.c \
+-             vendor_ti.c talloc.c operator_cache.c ext_response.c
+-#gsmd_LDADD = ../libgsmd/libgsmd.la
+-#gsmd_LDFLAGS = -dynamic
++gsmd_CFLAGS = -D PLUGINDIR=\"$(plugindir)\"
++gsmd_SOURCES = gsmd.c atcmd.c select.c machine.c vendor.c unsolicited.c log.c \
++             usock.c talloc.c operator_cache.c ext_response.c
++gsmd_LDADD = -ldl
++gsmd_LDFLAGS = -Wl,--export-dynamic
++
++plugin_LTLIBRARIES = libgsmd-machine_generic.la \
++                   libgsmd-machine_tihtc.la \
++                   libgsmd-vendor_ti.la \
++                   libgsmd-vendor_tihtc.la \
++                   libgsmd-vendor_qc.la
++
++libgsmd_machine_generic_la_SOURCES = machine_generic.c
++libgsmd_machine_tihtc_la_SOURCES = machine_tihtc.c
++
++libgsmd_vendor_ti_la_SOURCES = vendor_ti.c
++libgsmd_vendor_tihtc_la_SOURCES = vendor_tihtc.c
++libgsmd_vendor_qc_la_SOURCES = vendor_qc.c
+ noinst_HEADERS = gsmd.h
+Index: gsm/src/gsmd/atcmd.c
+===================================================================
+--- gsm.orig/src/gsmd/atcmd.c  2007-04-02 11:03:40.000000000 +0200
++++ gsm/src/gsmd/atcmd.c       2007-04-02 11:03:41.000000000 +0200
+@@ -183,6 +183,7 @@
+        * an empty string or that 'ready' string, we need to init the modem */
+       if (strlen(buf) == 0 ||
+           !strcmp(buf, "AT-Command Interpreter ready")) {
++              g->interpreter_ready = 1;
+               gsmd_initsettings(g);
+               return 0;
+       }
+@@ -370,7 +371,7 @@
+       }
+       /* write pending commands to UART */
+-      if (what & GSMD_FD_WRITE) {
++      if ((what & GSMD_FD_WRITE) && g->interpreter_ready) {
+               struct gsmd_atcmd *pos, *pos2;
+               llist_for_each_entry_safe(pos, pos2, &g->pending_atcmds, list) {
+                       len = strlen(pos->buf);
+Index: gsm/src/gsmd/vendor_tihtc.c
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ gsm/src/gsmd/vendor_tihtc.c        2007-04-02 13:16:45.000000000 +0200
+@@ -0,0 +1,305 @@
++/* TI [Calypso] with HTC firmware gsmd plugin
++ *
++ * Written by Philipp Zabel <philipp.zabel@gmail.com>
++ * based on vendor_ti.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ */
++
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#include "gsmd.h"
++
++#include <gsmd/gsmd.h>
++#include <gsmd/usock.h>
++#include <gsmd/event.h>
++#include <gsmd/talloc.h>
++#include <gsmd/extrsp.h>
++#include <gsmd/atcmd.h>
++#include <gsmd/vendorplugin.h>
++#include <gsmd/unsolicited.h>
++
++static int gsmd_test_atcb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
++{
++      printf("`%s' returned `%s'\n", cmd->buf, resp);
++      return 0;
++}
++
++int gsmd_simplecmd(struct gsmd *gsmd, char *cmdtxt)
++{
++      struct gsmd_atcmd *cmd;
++      cmd = atcmd_fill(cmdtxt, strlen(cmdtxt)+1, &gsmd_test_atcb, NULL, 0);
++      if (!cmd)
++              return -ENOMEM;
++
++      return atcmd_submit(gsmd, cmd);
++}
++
++
++#if 0
++#include "vendorplugin.h"
++
++static int
++ti_getopt(struct gsmd *gh, int optname, void *optval, int *optlen)
++{
++      switch (optname) {
++      case GSMD_OPT_CIPHER_IND:
++              /* FIXME: send AT%CPRI=? */
++              break;
++      default:
++              return -EINVAL;
++      }
++}
++
++static int
++ti_setopt(struct gsmd *gh, int optname, const void *optval, int optlen)
++{
++      switch (optname) {
++      case GSMD_OPT_CIPHER_IND:
++              /* FIXME: send AT%CPRI= */
++              break;
++      default:
++              return -EINVAL;
++      }
++}
++
++#endif
++
++
++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 htccsq_parse param=`%s'\n", param);
++      if (!ucmd)
++              return -EINVAL;
++
++
++      aux = (struct gsmd_evt_auxdata *) ucmd->buf;
++
++      /* FIXME: contains values 1-5, should be mapped to 0-31 somehow? */
++      /* 2 --> 11 */
++      aux->u.signal.sigq.rssi = atoi(buf);
++      aux->u.signal.sigq.ber = 99;
++
++      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)
++{
++      char *tok1, *tok2;
++
++      tok1 = strtok(buf, ",");
++      if (!tok1)
++              return -EIO;
++
++      tok2 = strtok(NULL, ",");
++      if (!tok2) {
++              switch (atoi(tok1)) {
++              case 0:
++                      gsmd->dev_state.ciph_ind.flags &= ~GSMD_CIPHIND_ACTIVE;
++                      break;
++              case 1:
++                      gsmd->dev_state.ciph_ind.flags |= GSMD_CIPHIND_ACTIVE;
++                      break;
++              case 2:
++                      gsmd->dev_state.ciph_ind.flags |= GSMD_CIPHIND_DISABLED_SIM;
++                      break;
++              }
++      } else {
++              struct gsmd_evt_auxdata *aux;
++              struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT,
++                                                         GSMD_EVT_CIPHER,
++                                                         sizeof(*aux));
++              if (!ucmd)
++                      return -ENOMEM;
++
++              aux = (struct gsmd_evt_auxdata *) ucmd->buf;
++
++              aux->u.cipher.net_state_gsm = atoi(tok1);
++              aux->u.cipher.net_state_gsm = atoi(tok2);
++
++              usock_evt_send(gsmd, ucmd, GSMD_EVT_CIPHER);
++      }
++
++      return 0;
++}
++
++/* Call Progress Information */
++static int cpi_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_OUT_STATUS,
++                                                 sizeof(*aux));
++
++      DEBUGP("entering cpi_parse param=`%s'\n", param);
++      if (!ucmd)
++              return -EINVAL;
++
++      aux = (struct gsmd_evt_auxdata *) ucmd->buf;
++
++      /* Format: cId, msgType, ibt, tch, dir,[mode],[number],[type],[alpha],[cause],line */
++
++      /* call ID */
++      tok = strtok(buf, ",");
++      if (!tok)
++              goto out_free_io;
++
++      /* message type (layer 3) */
++      tok = strtok(NULL, ",");
++      if (!tok)
++              goto out_free_io;
++      aux->u.call_status.prog = atoi(tok);
++
++      /* in-band tones */
++      tok = strtok(NULL, ",");
++      if (!tok)
++              goto out_free_io;
++
++      if (*tok == '1')
++              aux->u.call_status.ibt = 1;
++      else
++              aux->u.call_status.ibt = 0;
++
++      /* TCH allocated */
++      tok = strtok(NULL, ",");
++      if (!tok)
++              goto out_free_io;
++
++      if (*tok == '1')
++              aux->u.call_status.tch = 1;
++      else
++              aux->u.call_status.tch = 0;
++
++      /* direction */
++      tok = strtok(NULL, ",");
++      if (!tok)
++              goto out_send;
++
++      switch (*tok) {
++      case '0':
++      case '1':
++      case '2':
++      case '3':
++              aux->u.call_status.dir = (*tok - '0');
++              break;
++      default:
++              break;
++      }
++
++      /* mode */
++      tok = strtok(NULL, ",");
++      if (!tok)
++              goto out_send;
++
++out_send:
++      usock_evt_send(gsmd, ucmd, GSMD_EVT_OUT_STATUS);
++
++      return 0;
++
++out_free_io:
++      talloc_free(ucmd);
++      return -EIO;
++}
++
++static const struct gsmd_unsolicit tihtc_unsolicit[] = {
++      { "%HTCCSQ",    &htccsq_parse },        /* Signal Quality */
++      { "%CPRI",      &cpri_parse },  /* Ciphering Indication */
++      { "%CPI",       &cpi_parse },   /* Call Progress Information */
++
++      /* FIXME: parse the below and generate the respective events */
++
++      /* %CGREG: reports extended information about GPRS registration state */
++};
++
++static int cpi_detect_cb(struct gsmd_atcmd *cmd, void *ctx, char *resp)
++{
++      struct gsmd *g = ctx;
++      struct gsm_extrsp *er;
++
++      if (strncmp(resp, "%CPI: ", 6))
++              return -EINVAL;
++      resp += 6;
++
++      er = extrsp_parse(cmd, resp);
++      if (!er)
++              return -EINVAL;
++
++      if (extrsp_supports(er, 0, 3))
++              return gsmd_simplecmd(g, "AT%CPI=3");
++      else if (extrsp_supports(er, 0, 2))
++              return gsmd_simplecmd(g, "AT%CPI=2");
++      else
++              DEBUGP("Call Progress Indication mode 2 or 3 not supported!!\n");
++
++      talloc_free(er);
++      return 0;
++}
++
++static int tihtc_detect(struct gsmd *g)
++{
++      /* FIXME: do actual detection of vendor if we have multiple vendors */
++      /* open /proc/cpuinfo and check for HTC Magician or HTC Blueangel? */
++      /* check for N_TIHTC ldisc? or set it ourselves? */
++      return 1;
++}
++
++static int tihtc_initsettings(struct gsmd *g)
++{
++      int rc;
++      struct gsmd_atcmd *cmd;
++
++      /* use %CGREG */
++      //rc |= gsmd_simplecmd(g, "AT%CGREG=3");
++      /* enable %CPRI: ciphering indications */
++      rc |= gsmd_simplecmd(g, "AT%CPRI=1");
++      /* enable %HTCCSQ: signal quality reports */
++      rc |= gsmd_simplecmd(g, "AT%HTCCSQ=1");
++      /* send unsolicited commands at any time */
++      rc |= gsmd_simplecmd(g, "AT%CUNS=0");
++
++      /* enable %CPI: call progress indication */
++      cmd = atcmd_fill("AT%CPI=?", 9, &cpi_detect_cb, g, 0);
++      if (cmd)
++              atcmd_submit(g, cmd);
++
++      return rc;
++}
++
++struct gsmd_vendor_plugin gsmd_vendor_plugin = {
++      .name = "TI Calypso / HTC firmware",
++      .num_unsolicit = ARRAY_SIZE(tihtc_unsolicit),
++      .unsolicit = tihtc_unsolicit,
++      .detect = &tihtc_detect,
++      .initsettings = &tihtc_initsettings,
++};
+Index: gsm/src/gsmd/vendor_ti.c
+===================================================================
+--- gsm.orig/src/gsmd/vendor_ti.c      2007-04-02 09:58:55.000000000 +0200
++++ gsm/src/gsmd/vendor_ti.c   2007-04-02 11:03:41.000000000 +0200
+@@ -301,16 +301,10 @@
+       return rc;
+ }
+-static struct gsmd_vendor_plugin plugin_ticalypso = {
++struct gsmd_vendor_plugin gsmd_vendor_plugin = {
+       .name = "TI Calypso",
+       .num_unsolicit = ARRAY_SIZE(ticalypso_unsolicit),
+       .unsolicit = ticalypso_unsolicit,
+       .detect = &ticalypso_detect,
+       .initsettings = &ticalypso_initsettings,
+ };
+- 
+-/* FIXME: this will be _init() when we make this a plugin */
+-int ticalypso_init(void)
+-{
+-      return gsmd_vendor_plugin_register(&plugin_ticalypso);
+-}
+Index: gsm/src/gsmd/gsmd.c
+===================================================================
+--- gsm.orig/src/gsmd/gsmd.c   2007-04-02 09:58:55.000000000 +0200
++++ gsm/src/gsmd/gsmd.c        2007-04-02 13:39:40.000000000 +0200
+@@ -254,6 +254,21 @@
+               exit(1);
+       }
++      if (gsmd_machine_plugin_init(&g) < 0) {
++              fprintf(stderr, "no machine plugins found\n");
++              exit(1);
++      }
++
++      /* select a machine plugin and load possible vendor plugins */
++      gsmd_machine_plugin_find(&g);
++
++      /* initialize the machine plugin */
++      if (g.machinepl->init)
++              if (g.machinepl->init(&g, fd) < 0) {
++                      fprintf(stderr, "couldn't initialize machine plugin\n");
++                      exit(1);
++              }
++
+       if (atcmd_init(&g, fd) < 0) {
+               fprintf(stderr, "can't initialize UART device\n");
+               exit(1);
+@@ -275,12 +290,11 @@
+               setsid();
+       }
+-      /* FIXME: do this dynamically */
+-      ticalypso_init();
+-
++      /* select a vendor plugin */
+       gsmd_vendor_plugin_find(&g);
+-      gsmd_initsettings(&g);
++      if (g.interpreter_ready)
++              gsmd_initsettings(&g);
+       gsmd_opname_init(&g);
+Index: gsm/src/gsmd/vendor.c
+===================================================================
+--- gsm.orig/src/gsmd/vendor.c 2007-04-02 09:58:55.000000000 +0200
++++ gsm/src/gsmd/vendor.c      2007-04-02 13:38:38.000000000 +0200
+@@ -20,7 +20,10 @@
+  *
+  */ 
++#include <dlfcn.h>
+ #include <errno.h>
++#include <stdio.h>
++#include <string.h>
+ #include <common/linux_list.h>
+@@ -52,6 +55,7 @@
+       
+       llist_for_each_entry(pl, &vendorpl_list, list) {
+               if (pl->detect(g) == 1) {
++                      DEBUGP("selecting vendor plugin \"%s\"\n", pl->name);
+                       g->vendorpl = pl;
+                       return 1;
+               }
+@@ -59,3 +63,29 @@
+       return 0;
+ }
++
++int gsmd_vendor_plugin_load(char *name)
++{
++      int rc = -1;
++      void *lib;
++      struct gsmd_vendor_plugin *pl;
++      char buf[128];
++
++      DEBUGP("loading vendor plugin \"%s\"\n", name);
++
++      snprintf(buf, sizeof(buf), PLUGINDIR"/libgsmd-vendor_%s.so", name);
++
++      lib = dlopen(buf, RTLD_LAZY);
++      if (!lib) {
++              fprintf(stderr, "gsmd_vendor_plugin_load: %s\n", dlerror());
++              return -1;
++      }
++
++      pl = dlsym(lib, "gsmd_vendor_plugin");
++      if (pl)
++              rc = gsmd_vendor_plugin_register(pl);
++      else
++              dlclose(lib);
++
++      return rc;
++}
index 2019185..607d4db 100644 (file)
@@ -4,17 +4,17 @@ LICENSE = "GPL"
 SECTION = "libs/gsm"
 PROVIDES += "gsmd"
 PV = "0.0+svn${SRCDATE}"
-PR = "r8"
+PR = "r10"
 
 SRC_URI = "svn://svn.openmoko.org/trunk/src/target;module=gsm;proto=http \
            file://gsmd \
            file://default"
 S = "${WORKDIR}/gsm"
 
-SRC_URI_append_htcuniversal = " file://interpreter-ready.patch;patch=1"
-SRC_URI_append_magician = " file://vendor-tihtc.patch;patch=1 \
-                            file://interpreter-ready.patch;patch=1 \
-                            file://ldisc.patch;patch=1"
+SRC_URI_append_magician = "file://numeric.patch;patch=1 \
+                           file://plugin.patch;patch=1"
+SRC_URI_append_htcuniversal = "file://numeric.patch;patch=1 \
+                               file://plugin.patch;patch=1"
 
 inherit autotools pkgconfig update-rc.d
 
@@ -32,10 +32,12 @@ do_install_append() {
        install ${WORKDIR}/default ${D}/${sysconfdir}/default/gsmd
 }
 
-PACKAGES =+ "${PN}-tools gsmd"
+PACKAGES =+ "${PN}-tools gsmd gsmd-plugins"
 RDEPENDS_${PN} = "gsmd"
+RRECOMMENDS_gsmd = "gsmd-plugins"
 FILES_${PN}-tools = "${bindir}/*"
 FILES_gsmd = "${sbindir}/gsmd ${sysconfdir}"
+FILES_gsmd-plugins = "${libdir}/gsmd/*.so*"
 
 PACKAGES_DYNAMIC = "libgsmd* gsmd"