This email list is read-only. Emails sent to this list will be discarded ---------------------------------- plugins/Makefile.am | 2 +- plugins/hso.c | 193 +++++++++++++++++++++++++++++++- plugins/modem.c | 313 +++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/modem.h | 39 +++++++ 4 files changed, 544 insertions(+), 3 deletions(-)
New commits: commit 655c0e47d64295fd94fbd4bfb09539cb9300e300 Author: Marcel Holtmann <[email protected]> Date: Tue Dec 30 20:19:00 2008 +0100 Add more HSO implementation details commit eee11dfca5d8c21eaad3f1958a4db2483e634734 Author: Marcel Holtmann <[email protected]> Date: Tue Dec 30 20:17:23 2008 +0100 Add support for async events callbacks commit e7b4ef1fb306580fa5bb0baabe83149d6f7d93dc Author: Marcel Holtmann <[email protected]> Date: Tue Dec 30 19:48:44 2008 +0100 Add initial general purpose modem helper Diff in this email is a maximum of 400 lines. diff --git a/plugins/Makefile.am b/plugins/Makefile.am index f616c0d..44d510f 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -17,7 +17,7 @@ wifi_la_LIBADD = @GDBUS_LIBS@ bluetooth_la_SOURCES = bluetooth.c bluetooth_la_LIBADD = @GDBUS_LIBS@ -hso_la_SOURCES = hso.c +hso_la_SOURCES = hso.c modem.h modem.c udhcp_la_SOURCES = udhcp.c inet.h inet.c task.h task.c udhcp_la_CFLAGS = @GLIB_CFLAGS@ @GDBUS_CFLAGS@ -DUDHCPC=\"@udh...@\" \ diff --git a/plugins/hso.c b/plugins/hso.c index ac851d8..335655c 100644 --- a/plugins/hso.c +++ b/plugins/hso.c @@ -23,38 +23,227 @@ #include <config.h> #endif +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include <glib.h> + #define CONNMAN_API_SUBJECT_TO_CHANGE #include <connman/plugin.h> #include <connman/device.h> +#include <connman/resolver.h> #include <connman/log.h> +#include "modem.h" + +struct hso_data { + int index; + GIOChannel *channel; + struct modem_data *modem; +}; + +static void owandata_callback(const char *buf, void *user_data) +{ + //struct hso_data *data = user_data; + char *str, ip[16], nm[16], ns1[16], ns2[16], ns3[16], ns4[16], val[20]; + int err, num; + + str = g_strrstr(buf, "_OWANDATA"); + if (str == NULL || strstr(buf, "ERROR") != NULL) + return; + + err = sscanf(str, "_OWANDATA: %d, %[^,], %[^,], " + "%[^,], %[^,], %[^,], %[^,], %s", + &num, ip, nm, ns1, ns2, ns3, ns4, val); + + if (err != 8) { + DBG("parsed %d arguments", err); + return; + } + + DBG("ip %s dns %s %s val %s", ip, ns1, ns2, val); + + //connman_resolver_append(data->iface, NULL, ns1); + //connman_resolver_append(data->iface, NULL, ns2); +} + +static void owancall_callback(const char *buf, void *user_data) +{ + struct hso_data *data = user_data; + + DBG(""); + + if (g_strrstr(buf, "_OWANCALL: 1, 3") != NULL) { + DBG("%s", buf); + //modem_command(modem, owancall_callback, data, + // "_OWANCALL", "%d,%d,%d", 1, 1, 1); + } + + if (g_strrstr(buf, "_OWANCALL: 1, 1") != NULL) { + DBG("%s", buf); + modem_command(data->modem, owandata_callback, data, + "_OWANDATA", "%d", 1); + } + + if (g_strrstr(buf, "\r\nOK\r\n") != NULL) { + modem_command(data->modem, owandata_callback, data, + "_OWANDATA", "%d", 1); + } +} + +static int network_probe(struct connman_network *network) +{ + DBG("network %p", network); + + return 0; +} + +static void network_remove(struct connman_network *network) +{ + DBG("network %p", network); +} + +static int network_connect(struct connman_network *network) +{ + DBG("network %p", network); + + return 0; +} + +static int network_disconnect(struct connman_network *network) +{ + DBG("network %p", network); + + return 0; +} + +static struct connman_network_driver network_driver = { + .name = "hso-network", + .type = CONNMAN_NETWORK_TYPE_HSO, + .probe = network_probe, + .remove = network_remove, + .connect = network_connect, + .disconnect = network_disconnect, +}; + static int hso_probe(struct connman_device *device) { + struct hso_data *data; + DBG("device %p", device); + data = g_try_new0(struct hso_data, 1); + if (data == NULL) + return -ENOMEM; + + data->index = connman_device_get_index(device); + + data->modem = modem_create("/dev/ttyHS0"); + if (data->modem == NULL) { + g_free(data); + return -EIO; + } + + connman_device_set_data(device, data); + + modem_add_callback(data->modem, "_OWANCALL", + owancall_callback, data); + return 0; } static void hso_remove(struct connman_device *device) { + struct hso_data *data = connman_device_get_data(device); + DBG("device %p", device); + + connman_device_set_data(device, NULL); + + modem_destroy(data->modem); + + g_free(data); +} + +static int hso_enable(struct connman_device *device) +{ + struct hso_data *data = connman_device_get_data(device); + struct connman_network *network; + int err; + + DBG("device %p", device); + + err = modem_open(data->modem); + if (err < 0) + return err; + + connman_device_set_powered(device, TRUE); + + modem_command(data->modem, NULL, NULL, "Z", NULL); + modem_command(data->modem, NULL, NULL, "I", NULL); + + modem_command(data->modem, owancall_callback, data, + "_OWANCALL", "%d,%d,%d", 1, 1, 1); + + network = connman_network_create("internet", CONNMAN_NETWORK_TYPE_HSO); + connman_device_add_network(device, network); + + return 0; +} + +static int hso_disable(struct connman_device *device) +{ + struct hso_data *data = connman_device_get_data(device); + //const char *iface = connman_device_get_interface(device); + + DBG("device %p", device); + + //connman_resolver_remove_all(iface); + + modem_command(data->modem, owancall_callback, data, + "_OWANCALL", "%d,%d,%d", 1, 0, 0); + + connman_device_set_powered(device, FALSE); + + modem_close(data->modem); + + g_io_channel_shutdown(data->channel, TRUE, NULL); + g_io_channel_unref(data->channel); + + return 0; } static struct connman_device_driver hso_driver = { - .name = "hso", + .name = "hso-device", .type = CONNMAN_DEVICE_TYPE_HSO, .probe = hso_probe, .remove = hso_remove, + .enable = hso_enable, + .disable = hso_disable, }; static int hso_init(void) { - return connman_device_driver_register(&hso_driver); + int err; + + err = connman_network_driver_register(&network_driver); + if (err < 0) + return err; + + err = connman_device_driver_register(&hso_driver); + if (err < 0) { + connman_network_driver_unregister(&network_driver); + return err; + } + + return 0; } static void hso_exit(void) { connman_device_driver_unregister(&hso_driver); + connman_network_driver_register(&network_driver); } CONNMAN_PLUGIN_DEFINE(hso, "Option HSO device plugin", VERSION, diff --git a/plugins/modem.c b/plugins/modem.c new file mode 100644 index 0000000..4668bd3 --- /dev/null +++ b/plugins/modem.c @@ -0,0 +1,313 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2008 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 <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdarg.h> +#include <string.h> +#include <termios.h> + +#include <glib.h> + +#include <connman/log.h> + +#include "modem.h" + +struct modem_data { + char *device; + GIOChannel *channel; + GSList *callbacks; + GSList *commands; + char buf[1024]; + int offset; +}; + +struct modem_callback { + char *command; + modem_cb_t function; + void *user_data; +}; + +struct modem_cmd { + char *cmd; + char *arg; + modem_cb_t callback; + void *user_data; +}; + +static int send_command(struct modem_data *modem, struct modem_cmd *cmd) +{ + char *buf; + int fd, err; + + if (cmd->arg == NULL) { + DBG("AT%s", cmd->cmd); + buf = g_strdup_printf("AT%s\r\n", cmd->cmd); + } else { + DBG("AT%s=%s", cmd->cmd, cmd->arg); + buf = g_strdup_printf("AT%s=%s\r\n", cmd->cmd, cmd->arg); + } + + fd = g_io_channel_unix_get_fd(modem->channel); + err = write(fd, buf, strlen(buf)); + + fsync(fd); + + g_free(buf); + + return err; +} + +static int queue_command(struct modem_data *modem, struct modem_cmd *cmd) +{ + modem->commands = g_slist_append(modem->commands, cmd); + + if (g_slist_length(modem->commands) > 1) + return 0; + + return send_command(modem, cmd); +} + +struct modem_data *modem_create(const char *device) +{ + struct modem_data *modem; + + DBG("device %s", device); + + modem = g_try_new0(struct modem_data, 1); + if (modem == NULL) + return NULL; + + modem->device = g_strdup(device); + + DBG("modem %p", modem); + + return modem; +} + +void modem_destroy(struct modem_data *modem) +{ + DBG("modem %p", modem); + + if (modem == NULL) + return; + + g_free(modem->device); + g_free(modem); +} + +static gboolean modem_event(GIOChannel *channel, + GIOCondition condition, gpointer user_data) +{ + struct modem_data *modem = user_data; + struct modem_cmd *cmd; + GSList *list; + gsize len; + GIOError err; + + if (condition & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + err = g_io_channel_read(channel, modem->buf + modem->offset, + sizeof(modem->buf) - modem->offset, &len); + if (err) { + if (err == G_IO_ERROR_AGAIN) + return TRUE; + return FALSE; + } + + DBG("Read %d bytes (offset %d)", len, modem->offset); + + if (g_str_has_suffix(modem->buf, "\r\n") == TRUE) { + for (list = modem->callbacks; list; list = list->next) { + struct modem_callback *callback = list->data; _______________________________________________ Commits mailing list [email protected] https://lists.moblin.org/mailman/listinfo/commits
