X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=plugins%2Fwifi.c;h=6459f7603d15369fed3bb9ad882c1958b4cf5d66;hb=decb27a1cd8cfb19eafd80fc46bc328161738898;hp=b7eea7b1a199f7643db2add296776e54977497fa;hpb=91b02d3430e53b5bf7d974e37cd60102a93f92ad;p=connman diff --git a/plugins/wifi.c b/plugins/wifi.c index b7eea7b..6459f76 100644 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2009 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 @@ -31,11 +31,12 @@ #include #include -#include +#include +#define CONNMAN_API_SUBJECT_TO_CHANGE #include +#include #include -#include #include #include "inet.h" @@ -67,7 +68,7 @@ static void network_remove(struct connman_element *element) static int network_enable(struct connman_element *element) { - struct connman_element *device = element->parent; + struct connman_device *device = (struct connman_device *) element->parent; char *name, *security = NULL, *passphrase = NULL; unsigned char *ssid; int ssid_len; @@ -83,7 +84,7 @@ static int network_enable(struct connman_element *element) return -EIO; if (device != NULL) { - struct wifi_data *data = connman_element_get_data(device); + struct wifi_data *data = connman_device_get_data(device); if (data != NULL) { if (data->connected == TRUE) @@ -140,7 +141,7 @@ static struct connman_element *find_current_element(struct wifi_data *data, struct connman_element *element = list->data; if (connman_element_match_static_property(element, - "Name", &identifier) == TRUE) + "Name", &identifier) == TRUE) return element; } @@ -156,7 +157,7 @@ static struct connman_element *find_pending_element(struct wifi_data *data, struct connman_element *element = list->data; if (connman_element_match_static_property(element, - "Name", &identifier) == TRUE) + "Name", &identifier) == TRUE) return element; } @@ -165,15 +166,10 @@ static struct connman_element *find_pending_element(struct wifi_data *data, static gboolean inactive_scan(gpointer user_data) { - struct connman_element *device = user_data; - struct wifi_data *data = connman_element_get_data(device); + struct connman_device *device = user_data; + struct wifi_data *data = connman_device_get_data(device); - DBG(""); - - if (data->cleanup_timer > 0) { - g_source_remove(data->cleanup_timer); - data->cleanup_timer = 0; - } + DBG("device %p", device); __supplicant_scan(device); @@ -182,12 +178,12 @@ static gboolean inactive_scan(gpointer user_data) return FALSE; } -static void connect_known_networks(struct connman_element *device) +static void connect_known_networks(struct connman_device *device) { - struct wifi_data *data = connman_element_get_data(device); + struct wifi_data *data = connman_device_get_data(device); GSList *list; - DBG(""); + DBG("device %p", device); if (data->inactive_timer > 0) { g_source_remove(data->inactive_timer); @@ -209,17 +205,24 @@ static void connect_known_networks(struct connman_element *device) inactive_scan, device); } -static void state_change(struct connman_element *device, +static void state_change(struct connman_device *device, enum supplicant_state state) { - struct wifi_data *data = connman_element_get_data(device); + struct wifi_data *data = connman_device_get_data(device); struct connman_element *element; - DBG("state %d", state); + DBG("device %p state %d", device, state); + + if (state == STATE_SCANNING) + connman_device_set_scanning(device, TRUE); + else + connman_device_set_scanning(device, FALSE); if (data == NULL) return; + DBG("identifier %s", data->identifier); + if (data->identifier == NULL) goto reconnect; @@ -227,7 +230,7 @@ static void state_change(struct connman_element *device, if (element == NULL) goto reconnect; - if (state == STATE_COMPLETED) { + if (state == STATE_COMPLETED && data->connected == FALSE) { struct connman_element *dhcp; data->connected = TRUE; @@ -238,7 +241,8 @@ static void state_change(struct connman_element *device, dhcp->type = CONNMAN_ELEMENT_TYPE_DHCP; dhcp->index = element->index; - connman_element_register(dhcp, element); + if (connman_element_register(dhcp, element) < 0) + connman_element_unref(dhcp); } else if (state == STATE_INACTIVE || state == STATE_DISCONNECTED) { data->connected = FALSE; connman_element_set_enabled(element, FALSE); @@ -247,7 +251,7 @@ static void state_change(struct connman_element *device, } reconnect: - if (state == STATE_INACTIVE || state == STATE_DISCONNECTED) { + if (state == STATE_INACTIVE) { data->connected = FALSE; connect_known_networks(device); } @@ -277,32 +281,34 @@ static gboolean cleanup_pending(gpointer user_data) return FALSE; } -static void clear_results(struct connman_element *device) +static void clear_results(struct connman_device *device) { - struct wifi_data *data = connman_element_get_data(device); + struct wifi_data *data = connman_device_get_data(device); DBG("pending %d", g_slist_length(data->pending)); DBG("current %d", g_slist_length(data->current)); + if (data->cleanup_timer > 0) { + g_source_remove(data->cleanup_timer); + cleanup_pending(data); + } + data->pending = data->current; data->current = NULL; - if (data->cleanup_timer > 0) - return; - data->cleanup_timer = g_timeout_add_seconds(CLEANUP_TIMEOUT, cleanup_pending, data); } -static void scan_result(struct connman_element *device, +static void scan_result(struct connman_device *device, struct supplicant_network *network) { - struct wifi_data *data = connman_element_get_data(device); + struct wifi_data *data = connman_device_get_data(device); struct connman_element *element; gchar *temp; - int i; + unsigned int i; - DBG("network %p identifier %s", network, network->identifier); + DBG("device %p identifier %s", device, network->identifier); if (data == NULL) return; @@ -316,18 +322,21 @@ static void scan_result(struct connman_element *device, temp = g_strdup(network->identifier); for (i = 0; i < strlen(temp); i++) { - gchar tmp = g_ascii_tolower(temp[i]); - - if (tmp < 'a' || tmp > 'z') + char tmp = temp[i]; + if ((tmp < '0' || tmp > '9') && (tmp < 'A' || tmp > 'Z') && + (tmp < 'a' || tmp > 'z')) temp[i] = '_'; } element = find_pending_element(data, network->identifier); if (element == NULL) { + const char *mode; + element = connman_element_create(temp); - element->type = CONNMAN_ELEMENT_TYPE_NETWORK; - element->index = device->index; + element->type = CONNMAN_ELEMENT_TYPE_NETWORK; + element->subtype = CONNMAN_ELEMENT_SUBTYPE_WIFI; + element->index = connman_device_get_index(device); connman_element_add_static_property(element, "Name", DBUS_TYPE_STRING, &network->identifier); @@ -335,6 +344,10 @@ static void scan_result(struct connman_element *device, connman_element_add_static_array_property(element, "WiFi.SSID", DBUS_TYPE_BYTE, &network->ssid, network->ssid_len); + mode = (network->adhoc == TRUE) ? "adhoc" : "managed"; + connman_element_add_static_property(element, "WiFi.Mode", + DBUS_TYPE_STRING, &mode); + if (element->wifi.security == NULL) { const char *security; @@ -355,10 +368,14 @@ static void scan_result(struct connman_element *device, connman_element_add_static_property(element, "Strength", DBUS_TYPE_BYTE, &element->strength); - DBG("%s (%s) strength %d", network->identifier, + DBG("%s (%s %s) strength %d", network->identifier, mode, element->wifi.security, element->strength); - connman_element_register(element, device); + if (connman_element_register(element, + (struct connman_element *) device) < 0) { + connman_element_unref(element); + goto done; + } } else { data->pending = g_slist_remove(data->pending, element); @@ -376,6 +393,7 @@ static void scan_result(struct connman_element *device, element->available = TRUE; +done: g_free(temp); } @@ -385,11 +403,11 @@ static struct supplicant_callback wifi_callback = { .scan_result = scan_result, }; -static int wifi_probe(struct connman_element *element) +static int wifi_probe(struct connman_device *device) { struct wifi_data *data; - DBG("element %p name %s", element, element->name); + DBG("device %p", device); data = g_try_new0(struct wifi_data, 1); if (data == NULL) @@ -397,57 +415,50 @@ static int wifi_probe(struct connman_element *element) data->connected = FALSE; - connman_element_set_data(element, data); + connman_device_set_data(device, data); return 0; } -static void wifi_remove(struct connman_element *element) +static void wifi_remove(struct connman_device *device) { - struct wifi_data *data = connman_element_get_data(element); + struct wifi_data *data = connman_device_get_data(device); - DBG("element %p name %s", element, element->name); + DBG("device %p", device); - connman_element_set_data(element, NULL); + connman_device_set_data(device, NULL); g_free(data->identifier); g_free(data); } -static int wifi_update(struct connman_element *element) -{ - DBG("element %p name %s", element, element->name); - - __supplicant_scan(element); - - return 0; -} - -static int wifi_enable(struct connman_element *element) +static int wifi_enable(struct connman_device *device) { int err; - DBG("element %p name %s", element, element->name); + DBG("device %p", device); - err = __supplicant_start(element, &wifi_callback); + err = __supplicant_start(device, &wifi_callback); if (err < 0) return err; - __supplicant_scan(element); + connman_device_set_powered(device, TRUE); + + __supplicant_scan(device); return 0; } -static int wifi_disable(struct connman_element *element) +static int wifi_disable(struct connman_device *device) { - struct wifi_data *data = connman_element_get_data(element); + struct wifi_data *data = connman_device_get_data(device); GSList *list; - DBG("element %p name %s", element, element->name); + DBG("device %p", device); if (data->cleanup_timer > 0) { g_source_remove(data->cleanup_timer); - data->cleanup_timer = 0; + cleanup_pending(data); } if (data->inactive_timer > 0) { @@ -455,205 +466,88 @@ static int wifi_disable(struct connman_element *element) data->inactive_timer = 0; } - __supplicant_disconnect(element); - - for (list = data->pending; list; list = list->next) { - struct connman_element *network = list->data; - - connman_element_unref(network); - } - - g_slist_free(data->pending); - data->pending = NULL; - for (list = data->current; list; list = list->next) { struct connman_element *network = list->data; + if (network->enabled == TRUE) + __supplicant_disconnect(network); + connman_element_unref(network); } g_slist_free(data->current); data->current = NULL; - connman_element_unregister_children(element); - - __supplicant_stop(element); - - return 0; -} - -static struct connman_driver wifi_driver = { - .name = "wifi-device", - .type = CONNMAN_ELEMENT_TYPE_DEVICE, - .subtype = CONNMAN_ELEMENT_SUBTYPE_WIFI, - .probe = wifi_probe, - .remove = wifi_remove, - .update = wifi_update, - .enable = wifi_enable, - .disable = wifi_disable, -}; - -static GSList *device_list = NULL; + connman_element_unregister_children((struct connman_element *) device); -static void wifi_newlink(unsigned short type, int index, - unsigned flags, unsigned change) -{ - struct connman_element *device; - GSList *list; - gboolean exists = FALSE; - gchar *name, *devname; - struct iwreq iwr; - int sk; - - DBG("index %d", index); - - if (type != ARPHRD_ETHER) - return; - - name = inet_index2ident(index, "dev_"); - devname = inet_index2name(index); - - memset(&iwr, 0, sizeof(iwr)); - strncpy(iwr.ifr_ifrn.ifrn_name, devname, IFNAMSIZ); - - sk = socket(PF_INET, SOCK_DGRAM, 0); - - if (ioctl(sk, SIOCGIWNAME, &iwr) < 0) { - g_free(name); - close(sk); - return; - } - - close(sk); - - for (list = device_list; list; list = list->next) { - struct connman_element *device = list->data; - - if (device->index == index) { - exists = TRUE; - break; - } - } + __supplicant_stop(device); - if (exists == TRUE) { - g_free(name); - return; - } + connman_device_set_powered(device, FALSE); - device = connman_element_create(NULL); - device->type = CONNMAN_ELEMENT_TYPE_DEVICE; - device->subtype = CONNMAN_ELEMENT_SUBTYPE_WIFI; - - device->index = index; - device->name = name; - device->devname = devname; - - connman_element_register(device, NULL); - device_list = g_slist_append(device_list, device); + return 0; } -static void wifi_dellink(unsigned short type, int index, - unsigned flags, unsigned change) +static int wifi_scan(struct connman_device *device) { - GSList *list; - - DBG("index %d", index); + DBG("device %p", device); - for (list = device_list; list; list = list->next) { - struct connman_element *device = list->data; + __supplicant_scan(device); - if (device->index == index) { - device_list = g_slist_remove(device_list, device); - connman_element_unregister(device); - connman_element_unref(device); - break; - } - } + return 0; } -static struct connman_rtnl wifi_rtnl = { +static struct connman_device_driver wifi_driver = { .name = "wifi", - .newlink = wifi_newlink, - .dellink = wifi_dellink, + .type = CONNMAN_DEVICE_TYPE_WIFI, + .probe = wifi_probe, + .remove = wifi_remove, + .enable = wifi_enable, + .disable = wifi_disable, + .scan = wifi_scan, }; -static void supplicant_connect(DBusConnection *connection, void *user_data) +static void wifi_register(void) { - DBG("connection %p", connection); - - __supplicant_init(connection); - - if (connman_rtnl_register(&wifi_rtnl) < 0) - return; + DBG(""); - connman_rtnl_send_getlink(); + connman_device_driver_register(&wifi_driver); } -static void supplicant_disconnect(DBusConnection *connection, void *user_data) +static void wifi_unregister(void) { - GSList *list; - - DBG("connection %p", connection); - - connman_rtnl_unregister(&wifi_rtnl); - - for (list = device_list; list; list = list->next) { - struct connman_element *device = list->data; - - connman_element_unregister(device); - connman_element_unref(device); - } - - g_slist_free(device_list); - device_list = NULL; + DBG(""); - __supplicant_exit(); + connman_device_driver_unregister(&wifi_driver); } -static DBusConnection *connection; -static guint watch; +static struct supplicant_driver supplicant = { + .name = "wifi", + .probe = wifi_register, + .remove = wifi_unregister, +}; static int wifi_init(void) { int err; - connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - if (connection == NULL) - return -EIO; - err = connman_driver_register(&network_driver); - if (err < 0) { - dbus_connection_unref(connection); + if (err < 0) return err; - } - err = connman_driver_register(&wifi_driver); + err = supplicant_register(&supplicant); if (err < 0) { connman_driver_unregister(&network_driver); - dbus_connection_unref(connection); return err; } - watch = g_dbus_add_service_watch(connection, SUPPLICANT_NAME, - supplicant_connect, supplicant_disconnect, NULL, NULL); - - if (g_dbus_check_service(connection, SUPPLICANT_NAME) == TRUE) - supplicant_connect(connection, NULL); - return 0; } static void wifi_exit(void) { - connman_driver_unregister(&network_driver); - connman_driver_unregister(&wifi_driver); + supplicant_unregister(&supplicant); - if (watch > 0) - g_dbus_remove_watch(connection, watch); - - supplicant_disconnect(connection, NULL); - - dbus_connection_unref(connection); + connman_driver_unregister(&network_driver); } CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,