All pastes #420712 Raw Edit

Diff

public text v1 · immutable
·published 2007-04-02 10:33 UTC
rendered paste body
Index: gsm/include/gsmd/gsmd.h===================================================================--- gsm/include/gsmd/gsmd.h	(revision 1588)+++ gsm/include/gsmd/gsmd.h	(working copy)@@ -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===================================================================--- gsm/include/gsmd/machineplugin.h	(revision 0)+++ gsm/include/gsmd/machineplugin.h	(revision 0)@@ -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__ */++#endifIndex: gsm/src/gsmd/machine_tihtc.c===================================================================--- gsm/src/gsmd/machine_tihtc.c	(revision 0)+++ gsm/src/gsmd/machine_tihtc.c	(revision 0)@@ -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===================================================================--- gsm/src/gsmd/machine_generic.c	(revision 0)+++ gsm/src/gsmd/machine_generic.c	(revision 0)@@ -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===================================================================--- gsm/src/gsmd/machine.c	(revision 0)+++ gsm/src/gsmd/machine.c	(revision 0)@@ -0,0 +1,133 @@+/* 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);+				return gsmd_machine_plugin_load(machines[i].machine);+//				gsmd_vendor_plugin_load(machines[i].vendor);+			}+		}+	}+}Index: gsm/src/gsmd/vendor_qc.c===================================================================--- gsm/src/gsmd/vendor_qc.c	(revision 0)+++ gsm/src/gsmd/vendor_qc.c	(revision 0)@@ -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/src/gsmd/Makefile.am	(revision 1588)+++ gsm/src/gsmd/Makefile.am	(working copy)@@ -1,11 +1,27 @@ 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_CFLAGS = -D PLUGINDIR=\"$(plugindir)\"+gsmd_SOURCES = gsmd.c atcmd.c select.c machine.c vendor.c usock.c unsolicited.c log.c \+	       talloc.c operator_cache.c ext_response.c+gsmd_LDADD = -ldl #gsmd_LDADD = ../libgsmd/libgsmd.la #gsmd_LDFLAGS = -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.hIndex: gsm/src/gsmd/atcmd.c===================================================================--- gsm/src/gsmd/atcmd.c	(revision 1588)+++ gsm/src/gsmd/atcmd.c	(working copy)@@ -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/vendor_tihtc.c===================================================================--- gsm/src/gsmd/vendor_tihtc.c	(revision 0)+++ gsm/src/gsmd/vendor_tihtc.c	(revision 0)@@ -0,0 +1,288 @@+/* 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;+}++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/src/gsmd/vendor_ti.c	(revision 1588)+++ gsm/src/gsmd/vendor_ti.c	(working copy)@@ -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/src/gsmd/gsmd.c	(revision 1588)+++ gsm/src/gsmd/gsmd.c	(working copy)@@ -254,6 +253,23 @@ 		exit(1); 	} +	if (gsmd_machine_plugin_init(&g) < 0) {+		fprintf(stderr, "no machine plugins found\n");+		exit(1);+	}++	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);+		}++	/* now that we have an initialized machine plugin, load vendor plugins */+	gsmd_vendor_plugin_init(&g);+ 	if (atcmd_init(&g, fd) < 0) { 		fprintf(stderr, "can't initialize UART device\n"); 		exit(1);@@ -275,12 +291,10 @@ 		setsid(); 	} -	/* FIXME: do this dynamically */-	ticalypso_init();- 	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/src/gsmd/vendor.c	(revision 1588)+++ gsm/src/gsmd/vendor.c	(working copy)@@ -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,37 @@  	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;+}++/* FIXME!! */+int gsmd_vendor_plugin_init(struct gsmd *g, int fd)+{+	gsmd_vendor_plugin_load("ti");+	gsmd_vendor_plugin_load("tihtc");+	gsmd_vendor_plugin_load("qc");+}