X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fdevice.c;h=ffec3f2c5915dfa7c41260685babf7a8b95cc80d;hb=770ed7e6a3173290e071662a385b892756ff5072;hp=a97d790e585ce546eb61fb5389b5074bb6825243;hpb=1b9d0a62f59bb48c8deb2f0b98d9acdffdd9abe7;p=platform%2Fupstream%2Fconnman.git diff --git a/src/device.c b/src/device.c old mode 100644 new mode 100755 index a97d790..ffec3f2 --- a/src/device.c +++ b/src/device.c @@ -38,6 +38,10 @@ static GSList *device_list = NULL; static gchar **device_filter = NULL; static gchar **nodevice_filter = NULL; +#if defined TIZEN_EXT +static DBusConnection *connection; +#endif + enum connman_pending_type { PENDING_NONE = 0, PENDING_ENABLE = 1, @@ -52,8 +56,7 @@ struct connman_device { * request */ bool powered; - bool scanning; - bool disconnected; + bool scanning[MAX_CONNMAN_SERVICE_TYPES]; char *name; char *node; char *address; @@ -69,10 +72,27 @@ struct connman_device { char *last_network; struct connman_network *network; GHashTable *networks; +#if defined TIZEN_EXT + time_t last_user_selection_time; + char *last_user_selection_ident; + char *last_connected_ident; + DBusMessage *pending_reply; + int max_scan_ssids; + bool is_5_0_ghz_supported; + unsigned int mac_policy; + unsigned int preassoc_mac_policy; + unsigned int random_mac_lifetime; +#endif }; static void clear_pending_trigger(struct connman_device *device) { +#if defined TIZEN_EXT + if (device->pending_reply) { + dbus_message_unref(device->pending_reply); + device->pending_reply = NULL; + } +#endif if (device->pending_timeout > 0) { g_source_remove(device->pending_timeout); device->pending_timeout = 0; @@ -153,12 +173,52 @@ enum connman_service_type __connman_device_get_service_type( return CONNMAN_SERVICE_TYPE_UNKNOWN; } +static bool device_has_service_type(struct connman_device *device, + enum connman_service_type service_type) +{ + enum connman_service_type device_service_type = + __connman_device_get_service_type(device); + + /* + * For devices whose device_service_type is unknown we should + * allow to decide whether they support specific service_type + * by themself. + */ + if (device_service_type == CONNMAN_SERVICE_TYPE_UNKNOWN) + return true; + +#if defined TIZEN_EXT_WIFI_MESH + if (device_service_type == CONNMAN_SERVICE_TYPE_MESH) + return service_type != CONNMAN_SERVICE_TYPE_MESH; +#endif + + if (device_service_type == CONNMAN_SERVICE_TYPE_WIFI) { + return service_type == CONNMAN_SERVICE_TYPE_WIFI || + service_type == CONNMAN_SERVICE_TYPE_P2P; + } + + return service_type == device_service_type; +} + static gboolean device_pending_reset(gpointer user_data) { struct connman_device *device = user_data; DBG("device %p", device); +#if defined TIZEN_EXT + DBusMessage *reply; + + /* Power request timed out, send ETIMEDOUT. */ + if (device->pending_reply) { + reply = __connman_error_failed(device->pending_reply, ETIMEDOUT); + if (reply) + g_dbus_send_message(connection, reply); + + dbus_message_unref(device->pending_reply); + device->pending_reply = NULL; + } +#endif /* Power request timedout, reset power pending state. */ device->pending_timeout = 0; device->powered_pending = PENDING_NONE; @@ -180,11 +240,17 @@ int __connman_device_enable(struct connman_device *device) return -EBUSY; if (device->powered_pending == PENDING_ENABLE) - return -EALREADY; + return -EINPROGRESS; if (device->powered_pending == PENDING_NONE && device->powered) return -EALREADY; + if (device->index > 0) { + err = connman_inet_ifup(device->index); + if (err < 0 && err != -EALREADY) + return err; + } + device->powered_pending = PENDING_ENABLE; err = device->driver->enable(device); @@ -225,7 +291,7 @@ int __connman_device_disable(struct connman_device *device) return -EBUSY; if (device->powered_pending == PENDING_DISABLE) - return -EALREADY; + return -EINPROGRESS; if (device->powered_pending == PENDING_NONE && !device->powered) return -EALREADY; @@ -379,6 +445,9 @@ static void device_destruct(struct connman_device *device) clear_pending_trigger(device); + g_hash_table_destroy(device->networks); + device->networks = NULL; + g_free(device->ident); g_free(device->node); g_free(device->name); @@ -388,12 +457,59 @@ static void device_destruct(struct connman_device *device) g_free(device->last_network); - g_hash_table_destroy(device->networks); - device->networks = NULL; +#if defined TIZEN_EXT + g_free(device->last_user_selection_ident); + g_free(device->last_connected_ident); +#endif g_free(device); } +#if defined TIZEN_EXT +static void device_send_changed(const char *ifname, enum connman_service_type type, + const char *key, bool state) +{ + DBusMessage *signal; + DBusMessageIter iter, dict; + dbus_bool_t value = state; + const char *tech_path = connman_techonology_get_path(type); + + if (!tech_path || !ifname) + return; + + DBG("%s %s %s", ifname, key, state ? "TRUE" : "FALSE"); + + signal = dbus_message_new_signal(tech_path, + CONNMAN_TECHNOLOGY_INTERFACE, "DeviceChanged"); + if (!signal) + return; + + dbus_message_iter_init_append(signal, &iter); + + connman_dbus_dict_open(&iter, &dict); + connman_dbus_dict_append_basic(&dict, "Ifname", + DBUS_TYPE_STRING, + &ifname); + connman_dbus_dict_append_basic(&dict, key, + DBUS_TYPE_BOOLEAN, + &value); + connman_dbus_dict_close(&iter, &dict); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); +} + +static void device_send_reply(struct connman_device *device) +{ + if (device->pending_reply) { + g_dbus_send_reply(connection, + device->pending_reply, DBUS_TYPE_INVALID); + dbus_message_unref(device->pending_reply); + device->pending_reply = NULL; + } +} +#endif + /** * connman_device_create: * @node: device node name (for example an address) @@ -541,6 +657,11 @@ void connman_device_set_interface(struct connman_device *device, void connman_device_set_ident(struct connman_device *device, const char *ident) { +#ifdef TIZEN_EXT + if (device->ident) + return; + else +#endif g_free(device->ident); device->ident = g_strdup(ident); } @@ -560,13 +681,19 @@ const char *connman_device_get_ident(struct connman_device *device) int connman_device_set_powered(struct connman_device *device, bool powered) { + struct connman_device_scan_params params; enum connman_service_type type; + int i; - DBG("driver %p powered %d", device, powered); + DBG("device %p powered %d", device, powered); if (device->powered == powered) return -EALREADY; +#if defined TIZEN_EXT + device_send_reply(device); +#endif + clear_pending_trigger(device); device->powered_pending = PENDING_NONE; @@ -575,6 +702,11 @@ int connman_device_set_powered(struct connman_device *device, type = __connman_device_get_service_type(device); +#if defined TIZEN_EXT + device_send_changed(device->interface, type, "Powered", powered); + technology_save_device(device); +#endif + if (!device->powered) { __connman_technology_disabled(type); return 0; @@ -582,12 +714,15 @@ int connman_device_set_powered(struct connman_device *device, __connman_technology_enabled(type); - connman_device_set_disconnected(device, false); - device->scanning = false; + for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++) + device->scanning[i] = false; - if (device->driver && device->driver->scan) - device->driver->scan(CONNMAN_SERVICE_TYPE_UNKNOWN, device, - NULL, 0, NULL, NULL, NULL, NULL); + if (device->driver && device->driver->scan) { + memset(¶ms, 0, sizeof(params)); + params.type = CONNMAN_SERVICE_TYPE_UNKNOWN; + + device->driver->scan(device, ¶ms); + } return 0; } @@ -598,16 +733,22 @@ bool connman_device_get_powered(struct connman_device *device) } static int device_scan(enum connman_service_type type, - struct connman_device *device) + struct connman_device *device, + bool force_full_scan) { + struct connman_device_scan_params params; + if (!device->driver || !device->driver->scan) return -EOPNOTSUPP; if (!device->powered) return -ENOLINK; - return device->driver->scan(type, device, NULL, 0, - NULL, NULL, NULL, NULL); + memset(¶ms, 0, sizeof(params)); + params.type = type; + params.force_full_scan = force_full_scan; + + return device->driver->scan(device, ¶ms); } int __connman_device_disconnect(struct connman_device *device) @@ -617,8 +758,6 @@ int __connman_device_disconnect(struct connman_device *device) DBG("device %p", device); - connman_device_set_disconnected(device, true); - g_hash_table_iter_init(&iter, device->networks); while (g_hash_table_iter_next(&iter, &key, &value)) { @@ -655,6 +794,194 @@ int connman_device_reconnect_service(struct connman_device *device) return 0; } +#if defined TIZEN_EXT +bool connman_device_set_last_user_selection_time(struct connman_device *device, + time_t time) +{ + if (device->last_user_selection_time != time) { + device->last_user_selection_time = time; + return true; + } + + return false; +} + +time_t connman_device_get_last_user_selection_time(struct connman_device *device) +{ + return device->last_user_selection_time; +} + +bool connman_device_set_last_user_selection_ident(struct connman_device *device, + const char *ident) +{ + if (g_strcmp0(device->last_user_selection_ident, ident) != 0) { + g_free(device->last_user_selection_ident); + device->last_user_selection_ident = g_strdup(ident); + + return true; + } + + return false; +} + +const char *connman_device_get_last_user_selection_ident(struct connman_device *device) +{ + return device->last_user_selection_ident; +} + +bool connman_device_set_last_connected_ident(struct connman_device *device, + const char *ident) +{ + if (g_strcmp0(device->last_connected_ident, ident) != 0) { + g_free(device->last_connected_ident); + device->last_connected_ident = g_strdup(ident); + + return true; + } + + return false; +} + +const char *connman_device_get_last_connected_ident(struct connman_device *device) +{ + return device->last_connected_ident; +} + +void connman_device_save_last_user_selection(struct connman_device *device) +{ + GKeyFile *keyfile; + gchar *get_str; + gchar *selection_str; + + keyfile = __connman_storage_load_ins(); + + selection_str = g_strdup_printf("%s:%ld", + device->last_user_selection_ident, device->last_user_selection_time); + + if (!keyfile) { + keyfile = g_key_file_new(); + + g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str); + DBG("%s", selection_str); + __connman_storage_save_ins(keyfile); + + } else { + get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL); + if (!get_str || g_strcmp0(get_str, selection_str) != 0) { + g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str); + DBG("%s -> %s", get_str, selection_str); + __connman_storage_save_ins(keyfile); + } + + g_free(get_str); + } + + g_free(selection_str); + g_key_file_free(keyfile); +} + +void connman_device_load_last_user_selection(struct connman_device *device) +{ + GKeyFile *keyfile; + gchar *get_str; + char **selection_str; + + keyfile = __connman_storage_load_ins(); + if (!keyfile) + return; + + get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL); + if (get_str) { + selection_str = g_strsplit(get_str, ":", 0); + if (selection_str) { + time_t ref_time; + struct tm* timeinfo; + time_t last_user_selection_time; + + /* Only events that occur within 8 hours are counted. */ + ref_time = time(NULL); + timeinfo = localtime(&ref_time); + timeinfo->tm_hour -= 8; + ref_time = mktime(timeinfo); + + last_user_selection_time = strtol(selection_str[1], NULL, 10); + + if (last_user_selection_time > ref_time) { + if (g_strcmp0(selection_str[0], device->last_user_selection_ident) != 0) { + g_free(device->last_user_selection_ident); + device->last_user_selection_ident = g_strdup(selection_str[0]); + } + + device->last_user_selection_time = last_user_selection_time; + + DBG("%s %ld", device->last_user_selection_ident, device->last_user_selection_time); + } + + g_strfreev(selection_str); + } + + g_free(get_str); + } + + g_key_file_free(keyfile); +} + +void connman_device_save_last_connected(struct connman_device *device) +{ + GKeyFile *keyfile; + gchar *get_str; + + if (!device->last_connected_ident) + return; + + keyfile = __connman_storage_load_ins(); + + if (!keyfile) { + keyfile = g_key_file_new(); + + g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident); + DBG("%s", device->last_connected_ident); + __connman_storage_save_ins(keyfile); + + } else { + get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL); + if (!get_str || g_strcmp0(get_str, device->last_connected_ident) != 0) { + g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident); + DBG("%s -> %s", get_str, device->last_connected_ident); + __connman_storage_save_ins(keyfile); + } + + g_free(get_str); + } + + g_key_file_free(keyfile); +} + +void connman_device_load_last_connected(struct connman_device *device) +{ + GKeyFile *keyfile; + gchar *get_str; + + keyfile = __connman_storage_load_ins(); + if (!keyfile) + return; + + get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL); + if (get_str) { + if (g_strcmp0(get_str, device->last_connected_ident) != 0) { + g_free(device->last_connected_ident); + device->last_connected_ident = g_strdup(get_str); + } + + DBG("%s", device->last_connected_ident); + + g_free(get_str); + } + + g_key_file_free(keyfile); +} +#endif + static void mark_network_available(gpointer key, gpointer value, gpointer user_data) { @@ -680,7 +1007,8 @@ static gboolean remove_unavailable_network(gpointer key, gpointer value, { struct connman_network *network = value; - if (connman_network_get_connected(network)) + if (connman_network_get_connected(network) || + connman_network_get_connecting(network)) return FALSE; if (connman_network_get_available(network)) @@ -695,9 +1023,19 @@ void __connman_device_cleanup_networks(struct connman_device *device) remove_unavailable_network, NULL); } -bool connman_device_get_scanning(struct connman_device *device) +bool connman_device_get_scanning(struct connman_device *device, + enum connman_service_type type) { - return device->scanning; + int i; + + if (type != CONNMAN_SERVICE_TYPE_UNKNOWN) + return device->scanning[type]; + + for (i = 0; i < MAX_CONNMAN_SERVICE_TYPES; i++) + if (device->scanning[i]) + return true; + + return false; } void connman_device_reset_scanning(struct connman_device *device) @@ -721,10 +1059,13 @@ int connman_device_set_scanning(struct connman_device *device, if (!device->driver || !device->driver->scan) return -EINVAL; - if (device->scanning == scanning) + if (type == CONNMAN_SERVICE_TYPE_UNKNOWN) + return -EINVAL; + + if (device->scanning[type] == scanning) return -EALREADY; - device->scanning = scanning; + device->scanning[type] = scanning; if (scanning) { __connman_technology_scan_started(device); @@ -741,41 +1082,15 @@ int connman_device_set_scanning(struct connman_device *device, __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); - return 0; -} - -/** - * connman_device_set_disconnected: - * @device: device structure - * @disconnected: disconnected state - * - * Change disconnected state of device (only for device with networks) - */ -int connman_device_set_disconnected(struct connman_device *device, - bool disconnected) -{ - DBG("device %p disconnected %d", device, disconnected); - - if (device->disconnected == disconnected) - return -EALREADY; - - device->disconnected = disconnected; +#if defined TIZEN_EXT_WIFI_MESH + if (type == CONNMAN_SERVICE_TYPE_MESH) + __connman_mesh_auto_connect(); +#endif return 0; } /** - * connman_device_get_disconnected: - * @device: device structure - * - * Get device disconnected state - */ -bool connman_device_get_disconnected(struct connman_device *device) -{ - return device->disconnected; -} - -/** * connman_device_set_string: * @device: device structure * @key: unique identifier @@ -789,6 +1104,11 @@ int connman_device_set_string(struct connman_device *device, DBG("device %p key %s value %s", device, key, value); if (g_str_equal(key, "Address")) { +#ifdef TIZEN_EXT + if (device->address) + return 0; + else +#endif g_free(device->address); device->address = g_strdup(value); } else if (g_str_equal(key, "Name")) { @@ -817,6 +1137,9 @@ int connman_device_set_string(struct connman_device *device, const char *connman_device_get_string(struct connman_device *device, const char *key) { +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("device %p key %s", device, key); if (g_str_equal(key, "Address")) @@ -844,7 +1167,9 @@ int connman_device_add_network(struct connman_device *device, struct connman_network *network) { const char *identifier = connman_network_get_identifier(network); - +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("device %p network %p", device, network); if (!identifier) @@ -870,11 +1195,62 @@ int connman_device_add_network(struct connman_device *device, struct connman_network *connman_device_get_network(struct connman_device *device, const char *identifier) { +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("device %p identifier %s", device, identifier); return g_hash_table_lookup(device->networks, identifier); } +#if defined TIZEN_EXT +struct connman_network *connman_device_get_default_network( + struct connman_device *device) +{ + return device->network; +} + +void connman_device_set_pending_reply(struct connman_device *device, + DBusMessage *msg) +{ + device->pending_reply = dbus_message_ref(msg); +} + +void connman_device_send_connected_signal(struct connman_device *device, + bool connected) +{ + enum connman_service_type type; + + if (!device) + return; + + type = __connman_device_get_service_type(device); + device_send_changed(device->interface, type, "Connected", connected); +} + +void connman_device_set_max_scan_ssids(struct connman_device *device, + int max_scan_ssids) +{ + device->max_scan_ssids = max_scan_ssids; +} + +int connman_device_get_max_scan_ssids(struct connman_device *device) +{ + return device->max_scan_ssids; +} + +void connman_device_set_wifi_5ghz_supported(struct connman_device *device, + bool is_5_0_ghz_supported) +{ + device->is_5_0_ghz_supported = is_5_0_ghz_supported; +} + +bool connman_device_get_wifi_5ghz_supported(struct connman_device *device) +{ + return device->is_5_0_ghz_supported; +} +#endif + /** * connman_device_remove_network: * @device: device structure @@ -1071,7 +1447,23 @@ void connman_device_regdom_notify(struct connman_device *device, __connman_technology_notify_regdom_by_device(device, result, alpha2); } -int __connman_device_request_scan(enum connman_service_type type) +#if defined TIZEN_EXT +static int device_specific_scan(enum connman_service_type type, + struct connman_device *device, + int scan_type, GSList *specific_scan_list) +{ + if (!device->driver || !device->driver->specific_scan) + return -EOPNOTSUPP; + + if (!device->powered) + return -ENOLINK; + + return device->driver->specific_scan(type, device, scan_type, + specific_scan_list, NULL); +} + +int __connman_device_request_specific_scan(enum connman_service_type type, + const char *ifname, int scan_type, GSList *specific_scan_list) { bool success = false; int last_err = -ENOSYS; @@ -1090,6 +1482,9 @@ int __connman_device_request_scan(enum connman_service_type type) return -EOPNOTSUPP; case CONNMAN_SERVICE_TYPE_WIFI: case CONNMAN_SERVICE_TYPE_P2P: +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: +#endif break; } @@ -1106,8 +1501,213 @@ int __connman_device_request_scan(enum connman_service_type type) continue; } - err = device_scan(type, device); + if (ifname && g_strcmp0(device->interface, ifname) != 0) + continue; + + err = device_specific_scan(type, device, scan_type, specific_scan_list); + if (err == 0 || err == -EINPROGRESS) { + success = true; + } else { + last_err = err; + DBG("device %p err %d", device, err); + } + } + + if (success) + return 0; + + return last_err; +} + +int connman_device_request_device_scan(enum connman_service_type type, + const char * ifname, bool force_full_scan) +{ + bool success = false; + int last_err = -ENOSYS; + GSList *list; + int err; + + 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 -EOPNOTSUPP; + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_P2P: +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: +#endif + break; + } + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (!device_has_service_type(device, type)) + continue; + + if (g_strcmp0(device->interface, ifname) != 0) + continue; + + err = device_scan(type, device, force_full_scan); + + if (err == 0 || err == -EINPROGRESS) { + success = true; + } else { + last_err = err; + DBG("device %p err %d", device, err); + } + break; + } + + if (success) + return 0; + + return last_err; +} + +#if defined TIZEN_EXT_WIFI_MESH +static int device_abort_scan(enum connman_service_type type, + struct connman_device *device) +{ + if (!device->driver || !device->driver->scan) + return -EOPNOTSUPP; + + if (!device->powered) + return -ENOLINK; + + return device->driver->abort_scan(type, device); +} + +int __connman_device_abort_scan(enum connman_service_type type) +{ + GSList *list; + int err = -EINVAL; + + if (type != CONNMAN_SERVICE_TYPE_MESH) + return -EINVAL; + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + enum connman_service_type service_type = + __connman_device_get_service_type(device); + + if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) { + if (type == CONNMAN_SERVICE_TYPE_MESH) + if (service_type != CONNMAN_SERVICE_TYPE_WIFI) + continue; + + if (!device->scanning) { + err = -EEXIST; + continue; + } + + err = device_abort_scan(type, device); + } + } + return err; +} + +static int device_mesh_specific_scan(enum connman_service_type type, + struct connman_device *device, const char *name, + unsigned int freq) +{ + if (!device->driver || !device->driver->mesh_specific_scan) + return -EOPNOTSUPP; + + if (!device->powered) + return -ENOLINK; + + return device->driver->mesh_specific_scan(type, device, name, freq, NULL); +} + +int __connman_device_request_mesh_specific_scan(enum connman_service_type type, + const char *name, + unsigned int freq) +{ + bool success = false; + int last_err = -ENOSYS; + GSList *list; + int err; + + if (type != CONNMAN_SERVICE_TYPE_MESH) + return -EINVAL; + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + enum connman_service_type service_type = + __connman_device_get_service_type(device); + + if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) { + if (type == CONNMAN_SERVICE_TYPE_MESH) + if (service_type != CONNMAN_SERVICE_TYPE_WIFI) + continue; + } + + err = device_mesh_specific_scan(type, device, name, freq); + if (err == 0 || err == -EALREADY || err == -EINPROGRESS) { + success = true; + } else { + last_err = err; + DBG("device %p err %d", device, err); + } + } + + if (success) + return 0; + + return last_err; +} +#endif /* TIZEN_EXT_WIFI_MESH */ +#endif + +static int connman_device_request_scan(enum connman_service_type type, + bool force_full_scan) +{ + bool success = false; + int last_err = -ENOSYS; + GSList *list; + int err; + + 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 -EOPNOTSUPP; + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_P2P: +#if defined TIZEN_EXT_WIFI_MESH + case CONNMAN_SERVICE_TYPE_MESH: +#endif + break; + } + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (!device_has_service_type(device, type)) + continue; + + err = device_scan(type, device, force_full_scan); +#if defined TIZEN_EXT + /* When Scan is already in progress then return Error so that + * wifi-manager can block the scan-done signal to be sent to + * application and start requested scan after scan already in progress + * is completed then notify to application about the scan event */ + if (err == 0 || err == -EINPROGRESS) { +#else if (err == 0 || err == -EALREADY || err == -EINPROGRESS) { +#endif success = true; } else { last_err = err; @@ -1121,23 +1721,141 @@ int __connman_device_request_scan(enum connman_service_type type) return last_err; } +int __connman_device_request_scan(enum connman_service_type type) +{ + return connman_device_request_scan(type, false); +} + +int __connman_device_request_scan_full(enum connman_service_type type) +{ + return connman_device_request_scan(type, true); +} + int __connman_device_request_hidden_scan(struct connman_device *device, const char *ssid, unsigned int ssid_len, const char *identity, const char *passphrase, const char *security, void *user_data) { + struct connman_device_scan_params params; + DBG("device %p", device); if (!device || !device->driver || !device->driver->scan) return -EINVAL; - return device->driver->scan(CONNMAN_SERVICE_TYPE_UNKNOWN, - device, ssid, ssid_len, identity, - passphrase, security, user_data); + params.type = CONNMAN_SERVICE_TYPE_UNKNOWN; + params.ssid = ssid; + params.ssid_len = ssid_len; + params.identity = identity; + params.passphrase = passphrase; + params.security = security; + params.user_data = user_data; + + return device->driver->scan(device, ¶ms); +} + +void __connman_device_stop_scan(enum connman_service_type type) +{ + GSList *list; + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + + if (!device_has_service_type(device, type)) + continue; + + if (device->driver && device->driver->stop_scan) + device->driver->stop_scan(type, device); + } +} + +#if defined TIZEN_EXT +#define WIFI_MAC "/opt/etc/.mac.info" +#define MAC_ADDR_LEN 18 + +char *_get_wifi_addr(void) +{ + FILE *fp = NULL; + char* rv = 0; + char wifi_mac[MAC_ADDR_LEN + 1]; + char *str; + + fp = fopen(WIFI_MAC, "r"); + if (!fp){ + connman_error("[%s] not present", WIFI_MAC); + return NULL; + } + + rv = fgets(wifi_mac, MAC_ADDR_LEN, fp); + if (!rv) { + connman_error("Failed to get wifi mac address"); + fclose(fp); + return NULL; + } + + str = g_try_malloc0(MAC_ADDR_LEN); + if (!str) { + connman_error("memory allocation failed"); + fclose(fp); + return NULL; + } + + snprintf(str, MAC_ADDR_LEN, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", + g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]), + g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]), + g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]), + g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]), + g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]), + g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16])); + fclose(fp); + return str; +} + +char *_get_wifi_ident(void) +{ + FILE *fp = NULL; + char* rv = 0; + char wifi_mac[MAC_ADDR_LEN + 1]; + char *str; + + fp = fopen(WIFI_MAC, "r"); + if (!fp){ + connman_error("[%s] not present", WIFI_MAC); + return NULL; + } + + rv = fgets(wifi_mac, MAC_ADDR_LEN, fp); + if (!rv) { + connman_error("Failed to get wifi mac address"); + fclose(fp); + return NULL; + } + + str = g_try_malloc0(MAC_ADDR_LEN); + if (!str) { + connman_error("memory allocation failed"); + fclose(fp); + return NULL; + } + + snprintf(str, MAC_ADDR_LEN, "%c%c%c%c%c%c%c%c%c%c%c%c", + g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]), + g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]), + g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]), + g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]), + g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]), + g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16])); + fclose(fp); + return str; } +#endif +#if defined TIZEN_EXT +char *index2ident(int index, const char *prefix) +#else static char *index2ident(int index, const char *prefix) +#endif { struct ifreq ifr; struct ether_addr eth; @@ -1183,7 +1901,11 @@ static char *index2ident(int index, const char *prefix) return str; } +#if defined TIZEN_EXT +char *index2addr(int index) +#else static char *index2addr(int index) +#endif { struct ifreq ifr; struct ether_addr eth; @@ -1256,7 +1978,17 @@ struct connman_device *connman_device_create_from_index(int index) case CONNMAN_DEVICE_TYPE_ETHERNET: case CONNMAN_DEVICE_TYPE_GADGET: case CONNMAN_DEVICE_TYPE_WIFI: +#if defined TIZEN_EXT + if (type == CONNMAN_DEVICE_TYPE_WIFI) + name = _get_wifi_ident(); + if (!name) +#endif name = index2ident(index, ""); +#if defined TIZEN_EXT + if (type == CONNMAN_DEVICE_TYPE_WIFI) + addr = _get_wifi_addr(); + if (!addr) +#endif addr = index2addr(index); break; case CONNMAN_DEVICE_TYPE_BLUETOOTH: @@ -1281,6 +2013,10 @@ struct connman_device *connman_device_create_from_index(int index) ident = index2ident(index, NULL); break; case CONNMAN_DEVICE_TYPE_WIFI: +#if defined TIZEN_EXT + ident = _get_wifi_ident(); + if (!ident) +#endif ident = index2ident(index, NULL); break; case CONNMAN_DEVICE_TYPE_BLUETOOTH: @@ -1292,6 +2028,10 @@ struct connman_device *connman_device_create_from_index(int index) connman_device_set_index(device, index); connman_device_set_interface(device, devname); +#if defined TIZEN_EXT + connman_device_load_last_connected(device); + connman_device_load_last_user_selection(device); +#endif if (ident) { connman_device_set_ident(device, ident); @@ -1346,6 +2086,11 @@ nodevice: } list: + if (__connman_inet_isrootnfs_device(devname)) { + DBG("ignoring device %s (rootnfs)", devname); + return true; + } + blacklisted_interfaces = connman_setting_get_string_list("NetworkInterfaceBlacklist"); if (!blacklisted_interfaces) @@ -1418,6 +2163,9 @@ static void cleanup_devices(void) DBG("cleaning up %s index %d", interfaces[i], index); +#if defined TIZEN_EXT + if (strcmp(interfaces[i], "wlan0") != 0) +#endif connman_inet_ifdown(index); /* @@ -1433,6 +2181,10 @@ int __connman_device_init(const char *device, const char *nodevice) { DBG(""); +#if defined TIZEN_EXT + connection = connman_dbus_get_connection(); +#endif + if (device) device_filter = g_strsplit(device, ",", -1); @@ -1450,4 +2202,86 @@ void __connman_device_cleanup(void) g_strfreev(nodevice_filter); g_strfreev(device_filter); + +#if defined TIZEN_EXT + dbus_connection_unref(connection); +#endif } + +#ifdef TIZEN_EXT +void connman_device_mac_policy_notify(struct connman_device *device, + int result, unsigned int policy) +{ + device->mac_policy = policy; + __connman_technology_notify_mac_policy_by_device(device, result, policy); +} + +int connman_device_set_mac_policy(struct connman_device *device, + unsigned int policy) +{ + int err = 0; + + if (!device || !device->driver || !device->driver->set_mac_policy) + return -EOPNOTSUPP; + + device->mac_policy = policy; + err = device->driver->set_mac_policy(device, policy); + return err; +} + +unsigned int connman_device_get_mac_policy(struct connman_device *device) +{ + return device->mac_policy; +} + +void connman_device_preassoc_mac_policy_notify(struct connman_device *device, + int result, unsigned int policy) +{ + device->preassoc_mac_policy = policy; + __connman_technology_notify_preassoc_mac_policy_by_device(device, result, policy); +} + +int connman_device_set_preassoc_mac_policy(struct connman_device *device, + unsigned int policy) +{ + int err = 0; + + if (!device || !device->driver || !device->driver->set_preassoc_mac_policy) + return -EOPNOTSUPP; + + device->preassoc_mac_policy = policy; + err = device->driver->set_preassoc_mac_policy(device, policy); + return err; +} + +unsigned int connman_device_get_preassoc_mac_policy(struct connman_device *device) +{ + return device->preassoc_mac_policy; +} + +void connman_device_random_mac_lifetime_notify(struct connman_device *device, + int result, unsigned int lifetime) +{ + device->random_mac_lifetime = lifetime; + __connman_technology_notify_random_mac_lifetime_by_device(device, result, lifetime); +} + +int connman_device_set_random_mac_lifetime(struct connman_device *device, + unsigned int lifetime) +{ + int err = 0; + + if (!device || !device->driver || !device->driver->set_random_mac_lifetime) + return -EOPNOTSUPP; + + device->random_mac_lifetime = lifetime; + err = device->driver->set_random_mac_lifetime(device, lifetime); + return err; +} + +unsigned int connman_device_get_random_mac_lifetime(struct connman_device *device) +{ + return device->random_mac_lifetime; +} + +#endif