diff options
-rw-r--r-- | plugins/gadget.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/plugins/gadget.c b/plugins/gadget.c index 94f66487..cce51e26 100644 --- a/plugins/gadget.c +++ b/plugins/gadget.c @@ -25,6 +25,8 @@ #include <errno.h> #include <net/if.h> +#include <stdio.h> +#include <string.h> #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 @@ -226,6 +228,71 @@ static struct connman_device_driver gadget_dev_driver = { }; static GList *cdc_interface_list = NULL; +static GHashTable *cdc_mac_hash = NULL; + +static void add_station(int index) +{ + char *path, line[128] = {'\0'}; + char *ifname = connman_inet_ifname(index); + char *mac; + FILE *f; + + if (ifname == NULL) + return; + + path = g_strdup_printf("/sys/class/usb_mode/%s/f_rndis/ethaddr", + ifname); + + f = fopen(path, "re"); + + g_free(ifname); + g_free(path); + + if (f == NULL) + return; + + if (fgets(line, sizeof(line), f) == NULL) { + fclose(f); + return; + } + + fclose(f); + + mac = g_ascii_strdown(line, strlen(line) - 1); + DBG("Add station %s in Technology %d", mac, + CONNMAN_SERVICE_TYPE_GADGET); + + g_hash_table_insert(cdc_mac_hash, GINT_TO_POINTER(index), + mac); + + connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_GADGET, + mac); +} + +static void remove_station(int index) +{ + char *mac; + mac = g_hash_table_lookup(cdc_mac_hash, GINT_TO_POINTER(index)); + if (mac == NULL) + return; + + connman_technology_tethering_remove_station(mac); + + g_hash_table_remove(cdc_mac_hash, GINT_TO_POINTER(index)); +} + +static gboolean remove_all_station(gpointer key, gpointer value, gpointer user_data) +{ + char *mac; + mac = value; + if (mac == NULL) + return TRUE; + + connman_technology_tethering_remove_station(mac); + + return TRUE; +} + static void gadget_tech_add_interface(struct connman_technology *technology, int index, const char *name, const char *ident) @@ -246,6 +313,8 @@ static void gadget_tech_remove_interface(struct connman_technology *technology, cdc_interface_list = g_list_remove(cdc_interface_list, GINT_TO_POINTER((int) index)); + + remove_station(index); } static void gadget_tech_enable_tethering(struct connman_technology *technology, @@ -270,6 +339,8 @@ static void gadget_tech_enable_tethering(struct connman_technology *technology, connman_inet_ifup(index); connman_inet_add_to_bridge(index, bridge); + + add_station(index); } } @@ -283,6 +354,8 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology, connman_inet_remove_from_bridge(index, bridge); + remove_station(index); + connman_inet_ifdown(index); connman_technology_tethering_notify(technology, false); @@ -305,14 +378,28 @@ static int gadget_tech_set_tethering(struct connman_technology *technology, static int gadget_tech_probe(struct connman_technology *technology) { + DBG("tech probe %p", technology); + + cdc_mac_hash = g_hash_table_new_full(g_direct_hash, + g_direct_equal, NULL, g_free); + return 0; } static void gadget_tech_remove(struct connman_technology *technology) { + DBG("tech remove %p", technology); + g_list_free(cdc_interface_list); cdc_interface_list = NULL; + + if (cdc_mac_hash) { + g_hash_table_foreach_remove(cdc_mac_hash, remove_all_station, + NULL); + g_hash_table_destroy(cdc_mac_hash); + cdc_mac_hash = NULL; + } } static struct connman_technology_driver gadget_tech_driver = { |