From 9deaa6e70f62aaa71e3b72f4c4967e30dac8d204 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 2 Sep 2009 03:19:02 -0700 Subject: [PATCH] Add initial plugin for Ericsson MBM devices --- Makefile.am | 5 ++ plugins/chat.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++ plugins/chat.h | 29 +++++++++ plugins/mbm.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 358 insertions(+) create mode 100644 plugins/chat.c create mode 100644 plugins/chat.h create mode 100644 plugins/mbm.c diff --git a/Makefile.am b/Makefile.am index aaa3e39f..264b3a70 100644 --- a/Makefile.am +++ b/Makefile.am @@ -81,8 +81,13 @@ builtin_sources += $(gatchat_sources) drivers/atmodem/at.h \ drivers/atmodem/ssn.c \ drivers/atmodem/devinfo.c +builtin_sources += plugins/chat.h plugins/chat.c + builtin_modules += generic_at builtin_sources += plugins/generic_at.c + +builtin_modules += mbm +builtin_sources += plugins/mbm.c endif if MAINTAINER_MODE diff --git a/plugins/chat.c b/plugins/chat.c new file mode 100644 index 00000000..251ba5c8 --- /dev/null +++ b/plugins/chat.c @@ -0,0 +1,165 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2009 Intel Corporation. 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 version 2 as + * published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "chat.h" + +struct chat_data { + GIOChannel *io; + guint timeout; + + chat_callback_t callback; + gpointer user_data; +}; + +static gboolean connect_callback(GIOChannel *io, + GIOCondition cond, gpointer user_data) +{ + struct chat_data *data = user_data; + GAtChat *chat; + GAtSyntax *syntax; + + if (cond & G_IO_NVAL) + return FALSE; + + if (cond & (G_IO_HUP | G_IO_ERR)) + return FALSE; + + syntax = g_at_syntax_new_gsmv1(); + chat = g_at_chat_new(io, syntax); + g_at_syntax_unref(syntax); + + if (!chat) + return FALSE; + + data->callback(chat, data->user_data); + + g_at_chat_unref(chat); + + return FALSE; +} + +static gboolean connect_timeout(gpointer user_data) +{ + struct chat_data *data = user_data; + + data->timeout = 0; + + g_io_channel_close(data->io); + + data->callback(NULL, data->user_data); + + return FALSE; +} + +static void connect_destroy(gpointer user_data) +{ + struct chat_data *data = user_data; + + if (data->timeout > 0) { + g_source_remove(data->timeout); + data->timeout = 0; + } + + data->io = NULL; +} + +int chat_connect(const char *device, chat_callback_t callback, + gpointer user_data) +{ + struct chat_data *data; + struct termios newtio; + int fd; + + data = g_try_new0(struct chat_data, 1); + if (!data) + return -ENOMEM; + + fd = open(device, O_RDWR | O_NOCTTY); + if (fd < 0) { + ofono_error("Can't open TTY %s: %s (%d)", + device, strerror(errno), errno); + g_free(data); + return -EIO; + } + + newtio.c_cflag = B115200 | CRTSCTS | CLOCAL | CREAD; + newtio.c_iflag = IGNPAR; + newtio.c_oflag = 0; + newtio.c_lflag = 0; + + newtio.c_cc[VTIME] = 1; + newtio.c_cc[VMIN] = 5; + + tcflush(fd, TCIFLUSH); + + if (tcsetattr(fd, TCSANOW, &newtio) < 0) { + ofono_error("Can't change TTY termios: %s (%d)", + strerror(errno), errno); + close(fd); + g_free(data); + return -EIO; + } + + data->io = g_io_channel_unix_new(fd); + + g_io_channel_set_close_on_unref(data->io, TRUE); + + if (g_io_channel_set_flags(data->io, G_IO_FLAG_NONBLOCK, + NULL) != G_IO_STATUS_NORMAL) { + g_io_channel_unref(data->io); + g_free(data); + return -EIO; + } + + data->callback = callback; + data->user_data = user_data; + + data->timeout = g_timeout_add_seconds(10, connect_timeout, data); + + g_io_add_watch_full(data->io, G_PRIORITY_DEFAULT, + G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + connect_callback, data, connect_destroy); + + g_io_channel_unref(data->io); + + return 0; +} + +void chat_disconnect(GAtChat *chat) +{ +} diff --git a/plugins/chat.h b/plugins/chat.h new file mode 100644 index 00000000..a9c2902b --- /dev/null +++ b/plugins/chat.h @@ -0,0 +1,29 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2009 Intel Corporation. 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 version 2 as + * published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +typedef void (*chat_callback_t)(GAtChat *chat, gpointer user_data); + +int chat_connect(const char *device, chat_callback_t callback, + gpointer user_data); +void chat_disconnect(GAtChat *chat); diff --git a/plugins/mbm.c b/plugins/mbm.c new file mode 100644 index 00000000..4945dcec --- /dev/null +++ b/plugins/mbm.c @@ -0,0 +1,159 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2009 Intel Corporation. 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 version 2 as + * published by the Free Software Foundation. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#define OFONO_API_SUBJECT_TO_CHANGE +#include +#include +#include +#include +#include +#include + +#include "chat.h" + +struct mbm_data { + GAtChat *chat; +}; + +static int mbm_probe(struct ofono_modem *modem) +{ + struct mbm_data *data; + + ofono_info("MBM probe"); + + data = g_try_new0(struct mbm_data, 1); + if (!data) + return -ENOMEM; + + ofono_modem_set_data(modem, data); + + return 0; +} + +static void mbm_remove(struct ofono_modem *modem) +{ + struct mbm_data *data = ofono_modem_get_data(modem); + + ofono_info("MBM remove"); + + g_free(data); +} + +static void mbm_debug(const char *str, void *user_data) +{ + ofono_info("%s", str); +} + +static void connect_callback(GAtChat *chat, gpointer user_data) +{ + struct ofono_modem *modem = user_data; + struct mbm_data *data = ofono_modem_get_data(modem); + + if (!chat) { + ofono_modem_set_powered(modem, FALSE); + return; + } + + data->chat = g_at_chat_ref(chat); + + if (getenv("OFONO_MBM_DEBUG")) + g_at_chat_set_debug(data->chat, mbm_debug, NULL); + + ofono_modem_set_powered(modem, TRUE); + + g_at_chat_send(data->chat, "AT+CFUN=1", NULL, NULL, NULL, NULL); +} + +static int mbm_enable(struct ofono_modem *modem) +{ + int err; + + ofono_info("MBM enable"); + + err = chat_connect("/dev/ttyACM0", connect_callback, modem); + if (err < 0) + return err; + + return -EINPROGRESS; +} + +static int mbm_disable(struct ofono_modem *modem) +{ + struct mbm_data *data = ofono_modem_get_data(modem); + + ofono_info("MBM disable"); + + if (!data->chat) + return 0; + + g_at_chat_shutdown(data->chat); + + chat_disconnect(data->chat); + + g_at_chat_unref(data->chat); + data->chat = NULL; + + return 0; +} + +static void mbm_populate(struct ofono_modem *modem) +{ + struct mbm_data *data = ofono_modem_get_data(modem); + + ofono_info("MBM populate"); + + ofono_devinfo_create(modem, 0, "atmodem", data->chat); + ofono_netreg_create(modem, 0, "atmodem", data->chat); + ofono_sms_create(modem, 0, "atmodem", data->chat); +} + +static struct ofono_modem_driver mbm_driver = { + .name = "mbm", + .probe = mbm_probe, + .remove = mbm_remove, + .enable = mbm_enable, + .disable = mbm_disable, + .populate = mbm_populate, +}; + +static int mbm_init(void) +{ + return ofono_modem_driver_register(&mbm_driver); +} + +static void mbm_exit(void) +{ + ofono_modem_driver_unregister(&mbm_driver); +} + +OFONO_PLUGIN_DEFINE(mbm, "Ericsson MBM modem driver", VERSION, + OFONO_PLUGIN_PRIORITY_DEFAULT, mbm_init, mbm_exit)