X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fdevice.c;h=b4bf28467a92500e38a222df8d1d13b2c45d5138;hb=ff76ad35726a05cd5bf66ab09c2681f3bee8912d;hp=3fab97caed2d74aa791948d97ccc07cfee0e6c69;hpb=e5f53e12026cfe0a3499c1c423436b6840ecf123;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/device.c b/src/device.c index 3fab97c..b4bf284 100644 --- a/src/device.c +++ b/src/device.c @@ -28,26 +28,39 @@ #include "connman.h" +static GSList *device_list = NULL; +static gchar **device_filter = NULL; +static gchar **nodevice_filter = NULL; + +enum connman_pending_type { + PENDING_NONE = 0, + PENDING_ENABLE = 1, + PENDING_DISABLE = 2, +}; + struct connman_device { - struct connman_element element; + gint refcount; enum connman_device_type type; - connman_bool_t offlinemode; - connman_bool_t blocked; + enum connman_pending_type powered_pending; /* Indicates a pending + enable/disable request */ connman_bool_t powered; - connman_bool_t powered_pending; - connman_bool_t powered_persistent; connman_bool_t scanning; connman_bool_t disconnected; connman_bool_t reconnect; connman_uint16_t scan_interval; + connman_uint16_t backoff_interval; char *name; char *node; char *address; char *interface; char *ident; + char *path; + char *devname; int phyindex; + int index; unsigned int connections; guint scan_timeout; + guint pending_timeout; struct connman_device_driver *driver; void *driver_data; @@ -57,6 +70,8 @@ struct connman_device { GHashTable *networks; }; +#define SCAN_INITIAL_DELAY 10 + static gboolean device_scan_trigger(gpointer user_data) { struct connman_device *device = user_data; @@ -87,9 +102,23 @@ static void reset_scan_trigger(struct connman_device *device) clear_scan_trigger(device); if (device->scan_interval > 0) { - guint interval = device->scan_interval; + guint interval; + + if (g_hash_table_size(device->networks) == 0) { + if (device->backoff_interval >= device->scan_interval) + device->backoff_interval = SCAN_INITIAL_DELAY; + interval = device->backoff_interval; + } else + interval = device->scan_interval; + + DBG("interval %d", interval); + device->scan_timeout = g_timeout_add_seconds(interval, device_scan_trigger, device); + + device->backoff_interval *= 2; + if (device->backoff_interval > device->scan_interval) + device->backoff_interval = device->scan_interval; } } @@ -124,6 +153,9 @@ static const char *type2description(enum connman_device_type type) return "GPS"; case CONNMAN_DEVICE_TYPE_CELLULAR: return "Cellular"; + case CONNMAN_DEVICE_TYPE_GADGET: + return "Gadget"; + } return NULL; @@ -147,6 +179,9 @@ static const char *type2string(enum connman_device_type type) return "gps"; case CONNMAN_DEVICE_TYPE_CELLULAR: return "cellular"; + case CONNMAN_DEVICE_TYPE_GADGET: + return "gadget"; + } return NULL; @@ -171,46 +206,73 @@ enum connman_service_type __connman_device_get_service_type(struct connman_devic return CONNMAN_SERVICE_TYPE_BLUETOOTH; case CONNMAN_DEVICE_TYPE_CELLULAR: return CONNMAN_SERVICE_TYPE_CELLULAR; + case CONNMAN_DEVICE_TYPE_GADGET: + return CONNMAN_SERVICE_TYPE_GADGET; + } return CONNMAN_SERVICE_TYPE_UNKNOWN; } +static gboolean device_pending_reset(gpointer user_data) +{ + struct connman_device *device = user_data; + + DBG("device %p", device); + + /* Power request timedout, reset power pending state. */ + device->pending_timeout = 0; + device->powered_pending = PENDING_NONE; + + return FALSE; +} + int __connman_device_enable(struct connman_device *device) { int err; - DBG("device %p %d", device, device->blocked); + DBG("device %p", device); if (!device->driver || !device->driver->enable) return -EOPNOTSUPP; - if (device->powered_pending == TRUE) + /* There is an ongoing power disable request. */ + if (device->powered_pending == PENDING_DISABLE) + return -EBUSY; + + if (device->powered_pending == PENDING_ENABLE) return -EALREADY; - if (device->blocked == TRUE) - return -ENOLINK; + if (device->powered_pending == PENDING_NONE && device->powered == TRUE) + return -EALREADY; + + device->powered_pending = PENDING_ENABLE; err = device->driver->enable(device); - if (err < 0) { - if (err == -EINPROGRESS) { - device->powered_pending = TRUE; - device->offlinemode = FALSE; - if (__connman_profile_get_offlinemode() == TRUE) - __connman_profile_set_offlinemode(FALSE, FALSE); - } - return err; + /* + * device gets enabled right away. + * Invoke the callback + */ + if (err == 0) { + connman_device_set_powered(device, TRUE); + goto done; } - device->powered_pending = TRUE; - device->powered = TRUE; - device->offlinemode = FALSE; - if (__connman_profile_get_offlinemode() == TRUE) - __connman_profile_set_offlinemode(FALSE, FALSE); - - __connman_technology_enable_device(device); - - return 0; + if (err == -EALREADY) { + /* If device is already powered, but connman is not updated */ + connman_device_set_powered(device, TRUE); + goto done; + } + /* + * if err == -EINPROGRESS, then the DBus call to the respective daemon + * was successful. We set a 4 sec timeout so if the daemon never + * returns a reply, we would reset the pending request. + */ + if (err == -EINPROGRESS) + device->pending_timeout = g_timeout_add_seconds(4, + device_pending_reset, device); +done: + return err; } int __connman_device_disable(struct connman_device *device) @@ -222,79 +284,61 @@ int __connman_device_disable(struct connman_device *device) if (!device->driver || !device->driver->disable) return -EOPNOTSUPP; - if (device->powered == FALSE) - return -ENOLINK; + /* Ongoing power enable request */ + if (device->powered_pending == PENDING_ENABLE) + return -EBUSY; - if (device->powered_pending == FALSE) + if (device->powered_pending == PENDING_DISABLE) return -EALREADY; + if (device->powered_pending == PENDING_NONE && device->powered == FALSE) + return -EALREADY; + + device->powered_pending = PENDING_DISABLE; device->reconnect = FALSE; clear_scan_trigger(device); - g_hash_table_remove_all(device->networks); - err = device->driver->disable(device); - if (err < 0) { - if (err == -EINPROGRESS) - device->powered_pending = FALSE; - return err; + if (err == 0) { + connman_device_set_powered(device, FALSE); + goto done; } - device->powered_pending = FALSE; - device->powered = FALSE; - - __connman_technology_disable_device(device); - - return 0; -} - -static int set_powered(struct connman_device *device, connman_bool_t powered) -{ - DBG("device %p powered %d", device, powered); - - if (powered == TRUE) - return __connman_device_enable(device); - else - return __connman_device_disable(device); -} - -static int setup_device(struct connman_device *device) -{ - DBG("device %p", device); - - __connman_technology_add_device(device); - - if (device->offlinemode == FALSE && - device->powered_persistent == TRUE) - __connman_device_enable(device); + if (err == -EALREADY) { + connman_device_set_powered(device, FALSE); + goto done; + } - return 0; + if (err == -EINPROGRESS) + device->pending_timeout = g_timeout_add_seconds(4, + device_pending_reset, device); +done: + return err; } -static void probe_driver(struct connman_element *element, gpointer user_data) +static void probe_driver(struct connman_device_driver *driver) { - struct connman_device_driver *driver = user_data; - - DBG("element %p name %s", element, element->name); + GSList *list; - if (element->device == NULL) - return; + DBG("driver %p name %s", driver, driver->name); - if (element->device->driver != NULL) - return; + for (list = device_list; list != NULL; list = list->next) { + struct connman_device *device = list->data; - if (driver->type != element->device->type) - return; + if (device->driver != NULL) + continue; - if (driver->probe(element->device) < 0) - return; + if (driver->type != device->type) + continue; - element->device->driver = driver; + if (driver->probe(device) < 0) + continue; - __connman_element_set_driver(element); + device->driver = driver; - setup_device(element->device); + __connman_technology_add_device(device); + } } static void remove_device(struct connman_device *device) @@ -311,17 +355,18 @@ static void remove_device(struct connman_device *device) device->driver = NULL; } -static void remove_driver(struct connman_element *element, gpointer user_data) +static void remove_driver(struct connman_device_driver *driver) { - struct connman_device_driver *driver = user_data; + GSList *list; - DBG("element %p name %s", element, element->name); + DBG("driver %p name %s", driver, driver->name); - if (element->device == NULL) - return; + for (list = device_list; list != NULL; list = list->next) { + struct connman_device *device = list->data; - if (element->device->driver == driver) - remove_device(element->device); + if (device->driver == driver) + remove_device(device); + } } connman_bool_t __connman_device_has_driver(struct connman_device *device) @@ -356,9 +401,7 @@ int connman_device_driver_register(struct connman_device_driver *driver) driver_list = g_slist_insert_sorted(driver_list, driver, compare_priority); - - __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, - probe_driver, driver); + probe_driver(driver); return 0; } @@ -375,28 +418,23 @@ void connman_device_driver_unregister(struct connman_device_driver *driver) driver_list = g_slist_remove(driver_list, driver); - __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, - remove_driver, driver); + remove_driver(driver); } -static void unregister_network(gpointer data) +static void free_network(gpointer data) { struct connman_network *network = data; DBG("network %p", network); - connman_element_unregister((struct connman_element *) network); - __connman_network_set_device(network, NULL); connman_network_unref(network); } -static void device_destruct(struct connman_element *element) +static void device_destruct(struct connman_device *device) { - struct connman_device *device = element->device; - - DBG("element %p name %s", element, element->name); + DBG("device %p name %s", device, device->name); clear_scan_trigger(device); @@ -405,11 +443,15 @@ static void device_destruct(struct connman_element *element) g_free(device->name); g_free(device->address); g_free(device->interface); + g_free(device->path); + g_free(device->devname); g_free(device->last_network); g_hash_table_destroy(device->networks); device->networks = NULL; + + g_free(device); } /** @@ -425,8 +467,7 @@ struct connman_device *connman_device_create(const char *node, enum connman_device_type type) { struct connman_device *device; - const char *str; - enum connman_service_type service_type; + connman_bool_t bg_scan; DBG("node %s type %d", node, type); @@ -436,56 +477,40 @@ struct connman_device *connman_device_create(const char *node, DBG("device %p", device); - __connman_element_initialize(&device->element); - - device->element.name = g_strdup(node); - device->element.type = CONNMAN_ELEMENT_TYPE_DEVICE; - - device->element.device = device; - device->element.destruct = device_destruct; + device->refcount = 1; - str = type2string(type); - if (str != NULL) - connman_element_set_string(&device->element, - CONNMAN_PROPERTY_ID_TYPE, str); - - device->element.ipv4.method = CONNMAN_IPCONFIG_METHOD_DHCP; + bg_scan = connman_setting_get_bool("BackgroundScanning"); device->type = type; device->name = g_strdup(type2description(device->type)); - device->powered_persistent = TRUE; - device->phyindex = -1; - service_type = __connman_device_get_service_type(device); - device->blocked = __connman_technology_get_blocked(service_type); + device->backoff_interval = SCAN_INITIAL_DELAY; switch (type) { case CONNMAN_DEVICE_TYPE_UNKNOWN: - case CONNMAN_DEVICE_TYPE_VENDOR: - device->scan_interval = 0; - break; case CONNMAN_DEVICE_TYPE_ETHERNET: - case CONNMAN_DEVICE_TYPE_WIFI: - device->scan_interval = 300; - break; case CONNMAN_DEVICE_TYPE_WIMAX: - device->scan_interval = 0; - break; case CONNMAN_DEVICE_TYPE_BLUETOOTH: - device->scan_interval = 0; - break; + case CONNMAN_DEVICE_TYPE_CELLULAR: case CONNMAN_DEVICE_TYPE_GPS: + case CONNMAN_DEVICE_TYPE_GADGET: + case CONNMAN_DEVICE_TYPE_VENDOR: device->scan_interval = 0; break; - case CONNMAN_DEVICE_TYPE_CELLULAR: - device->scan_interval = 0; + case CONNMAN_DEVICE_TYPE_WIFI: + if (bg_scan == TRUE) + device->scan_interval = 300; + else + device->scan_interval = 0; break; } device->networks = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, unregister_network); + g_free, free_network); + + device_list = g_slist_append(device_list, device); return device; } @@ -498,8 +523,9 @@ struct connman_device *connman_device_create(const char *node, */ struct connman_device *connman_device_ref(struct connman_device *device) { - if (connman_element_ref(&device->element) == NULL) - return NULL; + DBG("%p", device); + + g_atomic_int_inc(&device->refcount); return device; } @@ -512,7 +538,17 @@ struct connman_device *connman_device_ref(struct connman_device *device) */ void connman_device_unref(struct connman_device *device) { - connman_element_unref(&device->element); + if (g_atomic_int_dec_and_test(&device->refcount) == FALSE) + return; + + if (device->driver) { + device->driver->remove(device); + device->driver = NULL; + } + + device_list = g_slist_remove(device_list, device); + + device_destruct(device); } const char *__connman_device_get_type(struct connman_device *device) @@ -540,7 +576,7 @@ enum connman_device_type connman_device_get_type(struct connman_device *device) */ void connman_device_set_index(struct connman_device *device, int index) { - device->element.index = index; + device->index = index; } /** @@ -551,7 +587,7 @@ void connman_device_set_index(struct connman_device *device, int index) */ int connman_device_get_index(struct connman_device *device) { - return device->element.index; + return device->index; } int __connman_device_get_phyindex(struct connman_device *device) @@ -575,8 +611,8 @@ void __connman_device_set_phyindex(struct connman_device *device, void connman_device_set_interface(struct connman_device *device, const char *interface) { - g_free(device->element.devname); - device->element.devname = g_strdup(interface); + g_free(device->devname); + device->devname = g_strdup(interface); g_free(device->interface); device->interface = g_strdup(interface); @@ -618,68 +654,49 @@ const char *connman_device_get_ident(struct connman_device *device) int connman_device_set_powered(struct connman_device *device, connman_bool_t powered) { + enum connman_service_type type; + DBG("driver %p powered %d", device, powered); - if (device->powered == powered) { - device->powered_pending = powered; + if (device->powered == powered) return -EALREADY; + + if (device->pending_timeout) { + /* Reset pending request */ + g_source_remove(device->pending_timeout); + device->pending_timeout = 0; } - if (powered == TRUE) - __connman_device_enable(device); - else - __connman_device_disable(device); + device->powered_pending = PENDING_NONE; device->powered = powered; - device->powered_pending = powered; + + type = __connman_device_get_service_type(device); if (device->powered == TRUE) - __connman_technology_enable_device(device); + __connman_technology_enabled(type); else - __connman_technology_disable_device(device); + __connman_technology_disabled(type); - if (device->offlinemode == TRUE && powered == TRUE) - return connman_device_set_powered(device, FALSE); - - if (powered == FALSE) + if (powered == FALSE) { + device->connections = 0; return 0; + } + + connman_device_set_disconnected(device, FALSE); + device->scanning = FALSE; reset_scan_trigger(device); - if (device->driver && device->driver->scan) + if (device->driver && device->driver->scan_fast) + device->driver->scan_fast(device); + else if (device->driver && device->driver->scan) device->driver->scan(device); return 0; } -int __connman_device_set_blocked(struct connman_device *device, - connman_bool_t blocked) -{ - connman_bool_t powered; - - DBG("device %p blocked %d", device, blocked); - - device->blocked = blocked; - - if (device->offlinemode == TRUE) - return 0; - - connman_info("%s {rfkill} blocked %d", device->interface, blocked); - - if (blocked == FALSE) - powered = device->powered_persistent; - else - powered = FALSE; - - return set_powered(device, powered); -} - -connman_bool_t __connman_device_get_blocked(struct connman_device *device) -{ - return device->blocked; -} - -int __connman_device_scan(struct connman_device *device) +static int device_scan(struct connman_device *device) { if (!device->driver || !device->driver->scan) return -EOPNOTSUPP; @@ -692,40 +709,6 @@ int __connman_device_scan(struct connman_device *device) return device->driver->scan(device); } -int __connman_device_enable_persistent(struct connman_device *device) -{ - int err; - - DBG("device %p", device); - - device->powered_persistent = TRUE; - - __connman_storage_save_device(device); - - err = __connman_device_enable(device); - if (err == 0 || err == -EINPROGRESS) { - device->offlinemode = FALSE; - if (__connman_profile_get_offlinemode() == TRUE) { - __connman_profile_set_offlinemode(FALSE, FALSE); - - __connman_profile_save_default(); - } - } - - return err; -} - -int __connman_device_disable_persistent(struct connman_device *device) -{ - DBG("device %p", device); - - device->powered_persistent = FALSE; - - __connman_storage_save_device(device); - - return __connman_device_disable(device); -} - int __connman_device_disconnect(struct connman_device *device) { GHashTableIter iter; @@ -740,7 +723,7 @@ int __connman_device_disconnect(struct connman_device *device) while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { struct connman_network *network = value; - if (__connman_network_get_connecting(network) == TRUE) { + if (connman_network_get_connecting(network) == TRUE) { /* * Skip network in the process of connecting. * This is a workaround for WiFi networks serviced @@ -751,7 +734,7 @@ int __connman_device_disconnect(struct connman_device *device) * will fail. There is nothing to be gained by * removing the network here anyway. */ - connman_warn("Skipping disconnect of %s", + connman_warn("Skipping disconnect of %s, network is connecting.", connman_network_get_identifier(network)); continue; } @@ -762,6 +745,14 @@ int __connman_device_disconnect(struct connman_device *device) return 0; } +static void mark_network_available(gpointer key, gpointer value, + gpointer user_data) +{ + struct connman_network *network = value; + + connman_network_set_available(network, TRUE); +} + static void mark_network_unavailable(gpointer key, gpointer value, gpointer user_data) { @@ -793,6 +784,20 @@ void __connman_device_cleanup_networks(struct connman_device *device) remove_unavailable_network, NULL); } +connman_bool_t __connman_device_scanning(struct connman_device *device) +{ + return device->scanning; +} + +void connman_device_reset_scanning(struct connman_device *device) +{ + device->scanning = FALSE; + + g_hash_table_foreach(device->networks, + mark_network_available, NULL); + +} + /** * connman_device_set_scanning: * @device: device structure @@ -827,9 +832,6 @@ int connman_device_set_scanning(struct connman_device *device, if (device->connections > 0) return 0; - if (device->disconnected == TRUE) - return 0; - __connman_service_auto_connect(); return 0; @@ -891,9 +893,14 @@ int connman_device_set_string(struct connman_device *device, } else if (g_str_equal(key, "Node") == TRUE) { g_free(device->node); device->node = g_strdup(value); + } else if (g_str_equal(key, "Path") == TRUE) { + g_free(device->path); + device->path = g_strdup(value); + } else { + return -EINVAL; } - return connman_element_set_string(&device->element, key, value); + return 0; } /** @@ -916,47 +923,10 @@ const char *connman_device_get_string(struct connman_device *device, return device->node; else if (g_str_equal(key, "Interface") == TRUE) return device->interface; + else if (g_str_equal(key, "Path") == TRUE) + return device->path; - return connman_element_get_string(&device->element, key); -} - -static void set_offlinemode(struct connman_element *element, gpointer user_data) -{ - struct connman_device *device = element->device; - connman_bool_t offlinemode = GPOINTER_TO_UINT(user_data); - connman_bool_t powered; - - DBG("element %p name %s", element, element->name); - - if (device == NULL) - return; - - device->offlinemode = offlinemode; - - if (device->blocked == TRUE) - return; - - powered = (offlinemode == TRUE) ? FALSE : TRUE; - - if (device->powered == powered) - return; - - if (device->powered_persistent == FALSE) - powered = FALSE; - - set_powered(device, powered); -} - -int __connman_device_set_offlinemode(connman_bool_t offlinemode) -{ - DBG("offlinmode %d", offlinemode); - - __connman_element_foreach(NULL, CONNMAN_ELEMENT_TYPE_DEVICE, - set_offlinemode, GUINT_TO_POINTER(offlinemode)); - - __connman_notifier_offlinemode(offlinemode); - - return 0; + return NULL; } void __connman_device_increase_connections(struct connman_device *device) @@ -973,6 +943,9 @@ void __connman_device_decrease_connections(struct connman_device *device) return; device->connections--; + + if (device->connections == 0) + device->backoff_interval = SCAN_INITIAL_DELAY; } /** @@ -986,21 +959,15 @@ int connman_device_add_network(struct connman_device *device, struct connman_network *network) { const char *identifier = connman_network_get_identifier(network); - int err; DBG("device %p network %p", device, network); if (identifier == NULL) return -EINVAL; - __connman_network_set_device(network, device); + connman_network_ref(network); - err = connman_element_register((struct connman_element *) network, - &device->element); - if (err < 0) { - __connman_network_set_device(network, NULL); - return err; - } + __connman_network_set_device(network, device); g_hash_table_insert(device->networks, g_strdup(identifier), network); @@ -1031,10 +998,16 @@ struct connman_network *connman_device_get_network(struct connman_device *device * Remove network for given identifier */ int connman_device_remove_network(struct connman_device *device, - const char *identifier) + struct connman_network *network) { - DBG("device %p identifier %s", device, identifier); + const char *identifier; + DBG("device %p network %p", device, network); + + if (network == NULL) + return 0; + + identifier = connman_network_get_identifier(network); g_hash_table_remove(device->networks, identifier); return 0; @@ -1056,16 +1029,12 @@ void __connman_device_set_network(struct connman_device *device, if (device->network == network) return; - if (device->network != NULL) - connman_network_unref(device->network); - if (network != NULL) { - name = connman_network_get_string(network, - CONNMAN_PROPERTY_ID_NAME); + name = connman_network_get_string(network, "Name"); g_free(device->last_network); device->last_network = g_strdup(name); - device->network = connman_network_ref(network); + device->network = network; } else { g_free(device->last_network); device->last_network = NULL; @@ -1086,6 +1055,16 @@ connman_bool_t __connman_device_get_reconnect( return device->reconnect; } +static gboolean match_driver(struct connman_device *device, + struct connman_device_driver *driver) +{ + if (device->type == driver->type || + driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN) + return TRUE; + + return FALSE; +} + /** * connman_device_register: * @device: device structure @@ -1094,11 +1073,31 @@ connman_bool_t __connman_device_get_reconnect( */ int connman_device_register(struct connman_device *device) { - __connman_storage_load_device(device); + GSList *list; + + DBG("device %p name %s", device, device->name); + + if (device->driver != NULL) + return -EALREADY; - device->offlinemode = __connman_profile_get_offlinemode(); + for (list = driver_list; list; list = list->next) { + struct connman_device_driver *driver = list->data; + + if (match_driver(device, driver) == FALSE) + continue; + + DBG("driver %p name %s", driver, driver->name); + + if (driver->probe(device) == 0) { + device->driver = driver; + break; + } + } + + if (device->driver == NULL) + return 0; - return connman_element_register(&device->element, NULL); + return __connman_technology_add_device(device); } /** @@ -1109,9 +1108,12 @@ int connman_device_register(struct connman_device *device) */ void connman_device_unregister(struct connman_device *device) { - __connman_storage_save_device(device); + DBG("device %p name %s", device, device->name); - connman_element_unregister(&device->element); + if (device->driver == NULL) + return; + + remove_device(device); } /** @@ -1137,163 +1139,116 @@ void connman_device_set_data(struct connman_device *device, void *data) device->driver_data = data; } -static gboolean match_driver(struct connman_device *device, - struct connman_device_driver *driver) -{ - if (device->type == driver->type || - driver->type == CONNMAN_DEVICE_TYPE_UNKNOWN) - return TRUE; - - return FALSE; -} - -static int device_probe(struct connman_element *element) +struct connman_device *__connman_device_find_device( + enum connman_service_type type) { - struct connman_device *device = element->device; GSList *list; - DBG("element %p name %s", element, element->name); + for (list = device_list; list != NULL; list = list->next) { + struct connman_device *device = list->data; + enum connman_service_type service_type = + __connman_device_get_service_type(device); - if (device == NULL) - return -ENODEV; - - if (device->driver != NULL) - return -EALREADY; - - for (list = driver_list; list; list = list->next) { - struct connman_device_driver *driver = list->data; - - if (match_driver(device, driver) == FALSE) + if (service_type != type) continue; - DBG("driver %p name %s", driver, driver->name); - - if (driver->probe(device) == 0) { - device->driver = driver; - break; - } + return device; } - if (device->driver == NULL) - return -ENODEV; - - return setup_device(device); -} - -static void device_remove(struct connman_element *element) -{ - struct connman_device *device = element->device; - - DBG("element %p name %s", element, element->name); - - if (device == NULL) - return; - - if (device->driver == NULL) - return; - - remove_device(device); + return NULL; } -static struct connman_driver device_driver = { - .name = "device", - .type = CONNMAN_ELEMENT_TYPE_DEVICE, - .priority = CONNMAN_DRIVER_PRIORITY_LOW, - .probe = device_probe, - .remove = device_remove, -}; - -static int device_load(struct connman_device *device) +int __connman_device_request_scan(enum connman_service_type type) { - const char *ident = __connman_profile_active_ident(); - GKeyFile *keyfile; - GError *error = NULL; - gchar *identifier; - connman_bool_t powered; - int val; - - DBG("device %p", device); + GSList *list; + int err; - keyfile = __connman_storage_open_profile(ident); - if (keyfile == NULL) + switch (type) { + case CONNMAN_SERVICE_TYPE_UNKNOWN: + case CONNMAN_SERVICE_TYPE_SYSTEM: + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_GPS: + case CONNMAN_SERVICE_TYPE_VPN: + case CONNMAN_SERVICE_TYPE_GADGET: return 0; + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_WIMAX: + break; + } - identifier = g_strdup_printf("device_%s", device->element.name); - if (identifier == NULL) - goto done; - - powered = g_key_file_get_boolean(keyfile, identifier, - "Powered", &error); - if (error == NULL) - device->powered_persistent = powered; - g_clear_error(&error); - - val = g_key_file_get_integer(keyfile, identifier, - "ScanInterval", &error); - if (error == NULL) - device->scan_interval = val; - g_clear_error(&error); + for (list = device_list; list != NULL; list = list->next) { + struct connman_device *device = list->data; + enum connman_service_type service_type = + __connman_device_get_service_type(device); -done: - g_free(identifier); + if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN && + service_type != type) { + continue; + } - __connman_storage_close_profile(ident, keyfile, FALSE); + err = device_scan(device); + if (err < 0 && err != -EINPROGRESS) { + DBG("err %d", err); + /* XXX maybe only a continue? */ + return err; + } + } return 0; } -static int device_save(struct connman_device *device) +connman_bool_t __connman_device_isfiltered(const char *devname) { - const char *ident = __connman_profile_active_ident(); - GKeyFile *keyfile; - gchar *identifier; - - DBG("device %p", device); - - keyfile = __connman_storage_open_profile(ident); - if (keyfile == NULL) - return 0; + char **pattern; - identifier = g_strdup_printf("device_%s", device->element.name); - if (identifier == NULL) - goto done; + if (device_filter == NULL) + goto nodevice; - g_key_file_set_boolean(keyfile, identifier, - "Powered", device->powered_persistent); + for (pattern = device_filter; *pattern; pattern++) { + if (g_pattern_match_simple(*pattern, devname) == FALSE) { + DBG("ignoring device %s (match)", devname); + return TRUE; + } + } - g_key_file_set_integer(keyfile, identifier, - "ScanInterval", device->scan_interval); +nodevice: + if (g_pattern_match_simple("dummy*", devname) == TRUE) { + DBG("ignoring dummy networking devices"); + return TRUE; + } -done: - g_free(identifier); + if (nodevice_filter == NULL) + return FALSE; - __connman_storage_close_profile(ident, keyfile, TRUE); + for (pattern = nodevice_filter; *pattern; pattern++) { + if (g_pattern_match_simple(*pattern, devname) == TRUE) { + DBG("ignoring device %s (no match)", devname); + return TRUE; + } + } - return 0; + return FALSE; } -static struct connman_storage device_storage = { - .name = "device", - .priority = CONNMAN_STORAGE_PRIORITY_LOW, - .device_load = device_load, - .device_save = device_save, -}; - -int __connman_device_init(void) +int __connman_device_init(const char *device, const char *nodevice) { DBG(""); - if (connman_storage_register(&device_storage) < 0) - connman_error("Failed to register device storage"); + if (device != NULL) + device_filter = g_strsplit(device, ",", -1); + + if (nodevice != NULL) + nodevice_filter = g_strsplit(nodevice, ",", -1); - return connman_driver_register(&device_driver); + return 0; } void __connman_device_cleanup(void) { DBG(""); - connman_driver_unregister(&device_driver); - - connman_storage_unregister(&device_storage); + g_strfreev(nodevice_filter); + g_strfreev(device_filter); }