device: Return -EOPNOTSUPP if the device does not support scanning
[platform/upstream/connman.git] / src / device.c
index b4bf284..55a6d8e 100644 (file)
@@ -39,7 +39,7 @@ enum connman_pending_type {
 };
 
 struct connman_device {
-       gint refcount;
+       int refcount;
        enum connman_device_type type;
        enum connman_pending_type powered_pending;      /* Indicates a pending
                                                        enable/disable request */
@@ -58,7 +58,6 @@ struct connman_device {
        char *devname;
        int phyindex;
        int index;
-       unsigned int connections;
        guint scan_timeout;
        guint pending_timeout;
 
@@ -97,6 +96,14 @@ static void clear_scan_trigger(struct connman_device *device)
        }
 }
 
+static void clear_pending_trigger(struct connman_device *device)
+{
+       if (device->pending_timeout > 0) {
+               g_source_remove(device->pending_timeout);
+               device->pending_timeout = 0;
+       }
+}
+
 static void reset_scan_trigger(struct connman_device *device)
 {
        clear_scan_trigger(device);
@@ -299,6 +306,16 @@ int __connman_device_disable(struct connman_device *device)
 
        clear_scan_trigger(device);
 
+       if (device->network) {
+               struct connman_service *service =
+                       __connman_service_lookup_from_network(device->network);
+
+               if (service != NULL)
+                       __connman_service_disconnect(service);
+               else
+                       connman_network_set_connected(device->network, FALSE);
+       }
+
        err = device->driver->disable(device);
        if (err == 0) {
                connman_device_set_powered(device, FALSE);
@@ -436,6 +453,7 @@ static void device_destruct(struct connman_device *device)
 {
        DBG("device %p name %s", device, device->name);
 
+       clear_pending_trigger(device);
        clear_scan_trigger(device);
 
        g_free(device->ident);
@@ -521,11 +539,13 @@ struct connman_device *connman_device_create(const char *node,
  *
  * Increase reference counter of device
  */
-struct connman_device *connman_device_ref(struct connman_device *device)
+struct connman_device *connman_device_ref_debug(struct connman_device *device,
+                               const char *file, int line, const char *caller)
 {
-       DBG("%p", device);
+       DBG("%p ref %d by %s:%d:%s()", device, device->refcount + 1,
+               file, line, caller);
 
-       g_atomic_int_inc(&device->refcount);
+       __sync_fetch_and_add(&device->refcount, 1);
 
        return device;
 }
@@ -536,9 +556,13 @@ struct connman_device *connman_device_ref(struct connman_device *device)
  *
  * Decrease reference counter of device
  */
-void connman_device_unref(struct connman_device *device)
+void connman_device_unref_debug(struct connman_device *device,
+                               const char *file, int line, const char *caller)
 {
-       if (g_atomic_int_dec_and_test(&device->refcount) == FALSE)
+       DBG("%p ref %d by %s:%d:%s()", device, device->refcount - 1,
+               file, line, caller);
+
+       if (__sync_fetch_and_sub(&device->refcount, 1) != 1)
                return;
 
        if (device->driver) {
@@ -661,11 +685,7 @@ int connman_device_set_powered(struct connman_device *device,
        if (device->powered == powered)
                return -EALREADY;
 
-       if (device->pending_timeout) {
-               /* Reset pending request */
-               g_source_remove(device->pending_timeout);
-               device->pending_timeout = 0;
-       }
+       clear_pending_trigger(device);
 
        device->powered_pending = PENDING_NONE;
 
@@ -678,10 +698,8 @@ int connman_device_set_powered(struct connman_device *device,
        else
                __connman_technology_disabled(type);
 
-       if (powered == FALSE) {
-               device->connections = 0;
+       if (powered == FALSE)
                return 0;
-       }
 
        connman_device_set_disconnected(device, FALSE);
        device->scanning = FALSE;
@@ -829,9 +847,6 @@ int connman_device_set_scanning(struct connman_device *device,
 
        __connman_device_cleanup_networks(device);
 
-       if (device->connections > 0)
-               return 0;
-
        __connman_service_auto_connect();
 
        return 0;
@@ -855,7 +870,10 @@ int connman_device_set_disconnected(struct connman_device *device,
        device->disconnected = disconnected;
 
        if (disconnected == TRUE)
+       {
                force_scan_trigger(device);
+               device->backoff_interval = SCAN_INITIAL_DELAY;
+       }
 
        return 0;
 }
@@ -929,25 +947,6 @@ const char *connman_device_get_string(struct connman_device *device,
        return NULL;
 }
 
-void __connman_device_increase_connections(struct connman_device *device)
-{
-       if (device == NULL)
-               return;
-
-       device->connections++;
-}
-
-void __connman_device_decrease_connections(struct connman_device *device)
-{
-       if (device == NULL)
-               return;
-
-       device->connections--;
-
-       if (device->connections == 0)
-               device->backoff_interval = SCAN_INITIAL_DELAY;
-}
-
 /**
  * connman_device_add_network:
  * @device: device structure
@@ -1172,7 +1171,7 @@ int __connman_device_request_scan(enum connman_service_type type)
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
-               return 0;
+               return -EOPNOTSUPP;
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_WIMAX:
                break;
@@ -1199,6 +1198,23 @@ int __connman_device_request_scan(enum connman_service_type type)
        return 0;
 }
 
+int __connman_device_request_hidden_scan(struct connman_device *device,
+                               const char *ssid, unsigned int ssid_len,
+                               const char *identity, const char *passphrase)
+{
+       DBG("device %p", device);
+
+       if (device == NULL || device->driver == NULL ||
+                       device->driver->scan_hidden == NULL)
+               return -EINVAL;
+
+       if (device->scanning == TRUE)
+               return -EALREADY;
+
+       return device->driver->scan_hidden(device, ssid, ssid_len,
+                                       identity, passphrase);
+}
+
 connman_bool_t __connman_device_isfiltered(const char *devname)
 {
        char **pattern;