diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gsmd/Makefile.am | 5 | ||||
-rw-r--r-- | src/gsmd/vendor_wavecom.c | 152 |
2 files changed, 156 insertions, 1 deletions
diff --git a/src/gsmd/Makefile.am b/src/gsmd/Makefile.am index 01d6a8d..ad2692e 100644 --- a/src/gsmd/Makefile.am +++ b/src/gsmd/Makefile.am @@ -30,7 +30,8 @@ plugin_LTLIBRARIES = libgsmd-machine_generic.la \ libgsmd-vendor_tihtc.la \ libgsmd-vendor_qc.la \ libgsmd-vendor_bcm.la \ - libgsmd-vendor_telit.la + libgsmd-vendor_telit.la \ + libgsmd-vendor_wavecom.la libgsmd_machine_generic_la_SOURCES = machine_generic.c libgsmd_machine_generic_la_LDFLAGS = -module @@ -51,6 +52,8 @@ libgsmd_vendor_bcm_la_SOURCES = vendor_bcm.c libgsmd_vendor_bcm_la_LDFLAGS = -module libgsmd_vendor_telit_la_SOURCES = vendor_telit.c libgsmd_vendor_telit_la_LDFLAGS = -module +libgsmd_vendor_wavecom_la_SOURCES = vendor_wavecom.c +libgsmd_vendor_wavecom_la_LDFLAGS = -module noinst_HEADERS = gsmd.h diff --git a/src/gsmd/vendor_wavecom.c b/src/gsmd/vendor_wavecom.c new file mode 100644 index 0000000..514145d --- /dev/null +++ b/src/gsmd/vendor_wavecom.c @@ -0,0 +1,152 @@ +/* Wavecom Q26 gsmd plugin + * + * (C) 2012 by Harald Welte <laforge@openmoko.org> + * All Rights Reserved + * + * 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 <stdint.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> + +struct cell_info_fsq { + uint8_t cur; + uint8_t full; + uint8_t sub; +}; + +#define TOK_OR_OUT(in) do { tok = strchr(in, ','); if (!tok || *(tok+1) == 0) goto out; tok += 1; } while (0) + +static int cced_parse(const char *buf, int len, const char *param, + struct gsmd *gsmd) +{ + struct gsmd_evt_auxdata *aux; + struct gsmd_ucmd *ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_CELLINFO, sizeof(*aux)); + char *tok = buf; + int rc; + + if (!ucmd) + return -ENOMEM; + + aux = (struct gsmd_evt_auxdata *) ucmd->buf; + + DEBUGP("entering cced_parse param=`%s'\n", param); + + aux->u.cell_info.mcc = atoi(tok); + TOK_OR_OUT(tok); + aux->u.cell_info.mnc = atoi(tok); + TOK_OR_OUT(tok); + sscanf(tok, "%x", &aux->u.cell_info.lac); + TOK_OR_OUT(tok); + sscanf(tok, "%x", &aux->u.cell_info.ci); + TOK_OR_OUT(tok); + aux->u.cell_info.bsic = atoi(tok); + TOK_OR_OUT(tok); + aux->u.cell_info.arfcn = atoi(tok); + TOK_OR_OUT(tok); + aux->u.cell_info.rxlev = atoi(tok); + + usock_evt_send(gsmd, ucmd, GSMD_EVT_SIGNAL); + ucmd = NULL; + + TOK_OR_OUT(tok); + TOK_OR_OUT(tok); + TOK_OR_OUT(tok); + TOK_OR_OUT(tok); + TOK_OR_OUT(tok); + TOK_OR_OUT(tok); + TOK_OR_OUT(tok); + + /* iterate over neighbor cell records */ + while (tok) { + //DEBUGP("remaining: `%s'\n", tok); + + ucmd = usock_build_event(GSMD_MSG_EVENT, GSMD_EVT_CELLINFO, sizeof(*aux)); + if (!ucmd) + return -ENOMEM; + aux = (struct gsmd_evt_auxdata *) ucmd->buf; + + aux->u.cell_info.mcc = atoi(tok); + TOK_OR_OUT(tok); + aux->u.cell_info.mnc = atoi(tok); + TOK_OR_OUT(tok); + sscanf(tok, "%x", &aux->u.cell_info.lac); + TOK_OR_OUT(tok); + sscanf(tok, "%x", &aux->u.cell_info.ci); + TOK_OR_OUT(tok); + aux->u.cell_info.bsic = atoi(tok); + TOK_OR_OUT(tok); + aux->u.cell_info.arfcn = atoi(tok); + TOK_OR_OUT(tok); + aux->u.cell_info.rxlev = atoi(tok); + + usock_evt_send(gsmd, ucmd, GSMD_EVT_SIGNAL); + ucmd = NULL; + + TOK_OR_OUT(tok); + } + + return 0; +out: + talloc_free(ucmd); + return 0; +} + +static const struct gsmd_unsolicit wavecom_unsolicit[] = { + { "+CCED", &cced_parse }, /* Cell Environment Report */ +}; + +static int wavecom_detect(struct gsmd *g) +{ + /* FIXME: do actual detection of vendor if we have multiple vendors */ + return 1; +} + +static int wavecom_initsettings(struct gsmd *g) +{ + int rc = 0; + struct gsmd_atcmd *cmd; + + /* use +WREGC to enter "spy mode" (no transmit / registration) */ + rc |= gsmd_simplecmd(g, "AT+WREGC=1"); + rc |= gsmd_simplecmd(g, "AT+CCED=1,3"); + + return rc; +} + +struct gsmd_vendor_plugin gsmd_vendor_plugin = { + .name = "Wavecom Q26", + .ext_chars = "", + .num_unsolicit = ARRAY_SIZE(wavecom_unsolicit), + .unsolicit = wavecom_unsolicit, + .detect = &wavecom_detect, + .initsettings = &wavecom_initsettings, +}; |