Add more HSO implementation details
authorMarcel Holtmann <marcel@holtmann.org>
Tue, 30 Dec 2008 19:19:00 +0000 (20:19 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 30 Dec 2008 19:19:00 +0000 (20:19 +0100)
plugins/Makefile.am
plugins/hso.c

index f616c0d..44d510f 100644 (file)
@@ -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=\"@UDHCPC@\" \
index ac851d8..335655c 100644 (file)
 #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,