summaryrefslogtreecommitdiff
path: root/packages/gsm/files/plugin.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packages/gsm/files/plugin.patch')
-rw-r--r--packages/gsm/files/plugin.patch935
1 files changed, 935 insertions, 0 deletions
diff --git a/packages/gsm/files/plugin.patch b/packages/gsm/files/plugin.patch
new file mode 100644
index 0000000000..7f455ce718
--- /dev/null
+++ b/packages/gsm/files/plugin.patch
@@ -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;
++}