From 5722b4f23ee01f31aecf2de9ee9ceb244bf27744 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Fri, 10 Apr 2015 14:30:12 +0300 Subject: [PATCH] [usb-moded] Connman tethering support Contributes to JB#15005 --- src/usb_moded-dyn-config.c | 6 +++ src/usb_moded-dyn-config.h | 8 +++- src/usb_moded-modesetting.c | 10 ++++ src/usb_moded-network.c | 94 +++++++++++++++++++++++++++++++++++++ src/usb_moded-network.h | 9 +++- 5 files changed, 125 insertions(+), 2 deletions(-) diff --git a/src/usb_moded-dyn-config.c b/src/usb_moded-dyn-config.c index 0de7e2f..00f8bcb 100644 --- a/src/usb_moded-dyn-config.c +++ b/src/usb_moded-dyn-config.c @@ -51,6 +51,9 @@ void list_item_free(mode_list_elem *list_item) free(list_item->android_extra_sysfs_path2); free(list_item->android_extra_sysfs_value2); free(list_item->idProduct); +#ifdef CONNMAN + free(list_item->connman_tethering); +#endif free(list_item); } @@ -146,6 +149,9 @@ static struct mode_list_elem *read_mode_file(const gchar *filename) list_item->idProduct = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_IDPRODUCT, NULL); list_item->nat = g_key_file_get_integer(settingsfile, MODE_OPTIONS_ENTRY, MODE_HAS_NAT, NULL); list_item->dhcp_server = g_key_file_get_integer(settingsfile, MODE_OPTIONS_ENTRY, MODE_HAS_DHCP_SERVER, NULL); +#ifdef CONNMAN + list_item->connman_tethering = g_key_file_get_string(settingsfile, MODE_OPTIONS_ENTRY, MODE_CONNMAN_TETHERING, NULL); +#endif g_key_file_free(settingsfile); if(list_item->mode_name == NULL || list_item->mode_module == NULL) diff --git a/src/usb_moded-dyn-config.h b/src/usb_moded-dyn-config.h index b489cc9..1498ac0 100644 --- a/src/usb_moded-dyn-config.h +++ b/src/usb_moded-dyn-config.h @@ -51,6 +51,9 @@ android engineers prefered to have sysfs entries... go figure... */ #define MODE_IDPRODUCT "idProduct" #define MODE_HAS_NAT "nat" #define MODE_HAS_DHCP_SERVER "dhcp_server" +#ifdef CONNMAN +#define MODE_CONNMAN_TETHERING "connman_tethering" +#endif /** * Struct keeping all the data needed for the definition of a dynamic mode @@ -77,7 +80,10 @@ typedef struct mode_list_elem char *idProduct; /* product id to assign to a specific profile */ int nat; /* If NAT should be set up in this mode or not */ int dhcp_server; /* if a DHCP server needs to be configured and started or not */ - /*@} */ +#ifdef CONNMAN + char* connman_tethering; /* connman's tethering technology path */ +#endif + /*@} */ }mode_list_elem; /* diag is used to select a secondary configuration location for diagnostic purposes */ diff --git a/src/usb_moded-modesetting.c b/src/usb_moded-modesetting.c index 6331b40..1867c9a 100644 --- a/src/usb_moded-modesetting.c +++ b/src/usb_moded-modesetting.c @@ -449,6 +449,11 @@ int set_dynamic_mode(void) if(data->appsync && !ret) activate_sync_post(data->mode_name); +#ifdef CONNMAN + if(data->connman_tethering) + connman_set_tethering(data->connman_tethering, TRUE); +#endif + if(ret) usb_moded_send_error_signal(MODE_SETTING_FAILED); return(ret); @@ -471,6 +476,11 @@ void unset_dynamic_mode(void) return; } +#ifdef CONNMAN + if(data->connman_tethering) + connman_set_tethering(data->connman_tethering, FALSE); +#endif + if(data->network) { usb_network_down(data); diff --git a/src/usb_moded-network.c b/src/usb_moded-network.c index c8db9a8..1035841 100644 --- a/src/usb_moded-network.c +++ b/src/usb_moded-network.c @@ -411,6 +411,100 @@ static int write_udhcpd_conf(struct ipforward_data *ipforward, struct mode_list_ } #ifdef CONNMAN + +#define CONNMAN_SERVICE "net.connman" +#define CONNMAN_TECH_INTERFACE "net.connman.Technology" +#define CONNMAN_ERROR_INTERFACE CONNMAN_SERVICE ".Error" +#define CONNMAN_ERROR_ALREADY_ENABLED CONNMAN_ERROR_INTERFACE ".AlreadyEnabled" +#define CONNMAN_ERROR_ALREADY_DISABLED CONNMAN_ERROR_INTERFACE ".AlreadyDisabled" + +/* + * Configures tethering for the specified connman technology. + */ +static gboolean connman_try_set_tethering(DBusConnection *connection, const char *path, gboolean on) +{ + gboolean ok = FALSE; + DBusMessage *message = dbus_message_new_method_call(CONNMAN_SERVICE, path, CONNMAN_TECH_INTERFACE, "SetProperty"); + if (message) + { + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter iter2; + DBusError error; + + const char* key = "Tethering"; + dbus_bool_t value = (on != FALSE); + + dbus_message_iter_init_append(message, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING, &iter2); + dbus_message_iter_append_basic(&iter2, DBUS_TYPE_BOOLEAN, &value); + dbus_message_iter_close_container(&iter, &iter2); + + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error); + dbus_message_unref(message); + if (reply) + { + log_debug("%s tethering %s", path, on ? "on" : "off"); + dbus_message_unref(reply); + ok = TRUE; + } + else + { + if ((on && !g_strcmp0(error.name, CONNMAN_ERROR_ALREADY_ENABLED)) || + (!on && (!g_strcmp0(error.name, CONNMAN_ERROR_ALREADY_DISABLED) || + !g_strcmp0(error.name, DBUS_ERROR_UNKNOWN_OBJECT)))) + { + ok = TRUE; + } + else + { + log_err("%s\n", error.message); + } + dbus_error_free(&error); + } + } + return ok; +} + +gboolean connman_set_tethering(const char *path, gboolean on) +{ + gboolean ok = FALSE; + DBusError error; + DBusConnection *connection; + + dbus_error_init(&error); + connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (connection) + { + int i; + for (i=0; i<10; i++) + { + if (i>0) + { + struct timespec tv; + tv.tv_sec = 0; + tv.tv_nsec = 200000000; + nanosleep(&tv, NULL); + } + if (connman_try_set_tethering(connection, path, on)) + { + ok = TRUE; + break; + } + } + dbus_connection_unref(connection); + } + else + { + log_err("%s\n", error.message); + dbus_error_free (&error); + } + + return ok; +} + /** * Connman message handling */ diff --git a/src/usb_moded-network.h b/src/usb_moded-network.h index d88d313..3be8f4c 100644 --- a/src/usb_moded-network.h +++ b/src/usb_moded-network.h @@ -20,7 +20,8 @@ usb-moded_network : (De)activates network depending on the network setting system. */ -/*============================================================================= */ +#ifndef USB_MODED_NETWORK_H_ +#define USB_MODED_NETWORK_H_ #include "usb_moded-dyn-config.h" @@ -28,3 +29,9 @@ int usb_network_up(struct mode_list_elem *data); int usb_network_down(struct mode_list_elem *data); int usb_network_update(void); int usb_network_set_up_dhcpd(struct mode_list_elem *data); + +#ifdef CONNMAN +gboolean connman_set_tethering(const char *path, gboolean on); +#endif + +#endif /* USB_MODED_NETWORK_H_ */