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

Reply via email to