int supplicant_stop(struct connman_device *device) { int index = connman_device_get_index(device); struct supplicant_task *task; _DBG_SUPPLICANT("device %p", device); task = find_task_by_index(index); if (task == NULL) return -ENODEV; g_free(task->range); task_list = g_slist_remove(task_list, task); if (task->scan_call != NULL) { dbus_pending_call_cancel(task->scan_call); task->scan_call = NULL; } if (task->result_call != NULL) { dbus_pending_call_cancel(task->result_call); task->result_call = NULL; } if (task->scanning == TRUE) connman_device_set_scanning(task->device, FALSE); remove_network(task); disconnect_network(task); return remove_interface(task); }
static void get_properties(struct supplicant_task *task) { DBusMessage *message; char *path; path = g_slist_nth_data(task->scan_results, 0); if (path == NULL) goto noscan; message = dbus_message_new_method_call(SUPPLICANT_NAME, path, SUPPLICANT_INTF ".BSSID", "properties"); task->scan_results = g_slist_remove(task->scan_results, path); g_free(path); if (message == NULL) goto noscan; dbus_message_set_auto_start(message, FALSE); if (dbus_connection_send_with_reply(connection, message, &task->result_call, TIMEOUT) == FALSE) { connman_error("Failed to get network properties"); dbus_message_unref(message); goto noscan; } if (task->result_call == NULL) { connman_error("D-Bus connection not available"); dbus_message_unref(message); goto noscan; } dbus_pending_call_set_notify(task->result_call, properties_reply, task, NULL); dbus_message_unref(message); return; noscan: task->result_call = NULL; if (task->scanning == TRUE) { connman_device_set_scanning(task->device, FALSE); task->scanning = FALSE; } }
static void scan_reply(DBusPendingCall *call, void *user_data) { struct supplicant_task *task = user_data; DBusMessage *reply; _DBG_SUPPLICANT("task %p", task); task->scan_call = NULL; reply = dbus_pending_call_steal_reply(call); if (reply == NULL) return; if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { connman_device_set_scanning(task->device, FALSE); goto done; } if (task->scanning == TRUE) connman_device_set_scanning(task->device, TRUE); done: dbus_message_unref(reply); }
static gboolean adapter_changed(DBusConnection *conn, DBusMessage *message, void *user_data) { const char *path = dbus_message_get_path(message); struct connman_device *device; DBusMessageIter iter, value; const char *key; DBG("path %s", path); device = g_hash_table_lookup(bluetooth_devices, path); if (device == NULL) return TRUE; if (dbus_message_iter_init(message, &iter) == FALSE) return TRUE; dbus_message_iter_get_basic(&iter, &key); dbus_message_iter_next(&iter); dbus_message_iter_recurse(&iter, &value); if (g_str_equal(key, "Powered") == TRUE) { dbus_bool_t val; dbus_message_iter_get_basic(&value, &val); connman_device_set_powered(device, val); if (val == TRUE) check_pending_networks(path); } else if (g_str_equal(key, "Discovering") == TRUE) { dbus_bool_t val; dbus_message_iter_get_basic(&value, &val); connman_device_set_scanning(device, val); } else if (g_str_equal(key, "Devices") == TRUE) { check_networks(&value); } return TRUE; }
int supplicant_scan(struct connman_device *device) { int index = connman_device_get_index(device); struct supplicant_task *task; int err; _DBG_SUPPLICANT("device %p", device); task = find_task_by_index(index); if (task == NULL) return -ENODEV; switch (task->state) { case WPA_SCANNING: return -EALREADY; case WPA_ASSOCIATING: case WPA_ASSOCIATED: case WPA_4WAY_HANDSHAKE: case WPA_GROUP_HANDSHAKE: return -EBUSY; default: break; } task->scanning = TRUE; err = initiate_scan(task); if (err < 0) { if (err == -EINPROGRESS) return 0; task->scanning = FALSE; return err; } connman_device_set_scanning(task->device, TRUE); return 0; }
static void scan_results_available(struct supplicant_task *task) { DBusMessage *message; _DBG_SUPPLICANT("task %p", task); if (task->result_call != NULL) return; message = dbus_message_new_method_call(SUPPLICANT_NAME, task->path, SUPPLICANT_INTF ".Interface", "scanResults"); if (message == NULL) return; dbus_message_set_auto_start(message, FALSE); if (dbus_connection_send_with_reply(connection, message, &task->result_call, TIMEOUT) == FALSE) { connman_error("Failed to request scan result"); goto done; } if (task->result_call == NULL) { connman_error("D-Bus connection not available"); goto done; } if (task->scanning == TRUE) connman_device_set_scanning(task->device, TRUE); dbus_pending_call_set_notify(task->result_call, scan_results_reply, task, NULL); done: dbus_message_unref(message); }
static void state_change(struct supplicant_task *task, DBusMessage *msg) { DBusError error; const char *newstate, *oldstate; unsigned char bssid[ETH_ALEN]; unsigned int bssid_len; enum supplicant_state state, ostate; dbus_error_init(&error); if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &newstate, DBUS_TYPE_STRING, &oldstate, DBUS_TYPE_INVALID) == FALSE) { if (dbus_error_is_set(&error) == TRUE) { connman_error("%s", error.message); dbus_error_free(&error); } else connman_error("Wrong arguments for state change"); return; } connman_info("%s state change %s -> %s%s", task->ifname, oldstate, newstate, task->scanning == TRUE ? " (scanning)" : ""); state = string2state(newstate); if (state == WPA_INVALID) return; if (task->scanning == TRUE && state != WPA_SCANNING) { connman_device_set_scanning(task->device, FALSE); task->scanning = FALSE; } ostate = task->state; task->state = state; if (task->network == NULL) return; switch (task->state) { case WPA_COMPLETED: if (ostate != WPA_ASSOCIATED && ostate != WPA_GROUP_HANDSHAKE) goto badstate; /* reset bg scan reschedule */ connman_device_reset_scan(task->device); if (get_bssid(task->device, bssid, &bssid_len) == 0) connman_network_set_address(task->network, bssid, bssid_len); /* carrier on */ connman_network_set_connected(task->network, TRUE); break; case WPA_ASSOCIATING: if (ostate != WPA_SCANNING && ostate != WPA_COMPLETED) goto badstate; if (ostate == WPA_SCANNING) connman_network_set_associating(task->network, TRUE); break; case WPA_INACTIVE: if (ostate != WPA_SCANNING && ostate != WPA_DISCONNECTED) goto badstate; /* fall thru... */ case WPA_DISCONNECTED: /* carrier off */ connman_network_set_connected(task->network, FALSE); if (task->disconnecting == TRUE) { connman_network_unref(task->network); task->disconnecting = FALSE; if (task->pending_network != NULL) { task->network = task->pending_network; task->pending_network = NULL; task_connect(task); } else task->network = NULL; } break; default: connman_network_set_associating(task->network, FALSE); break; } return; badstate: connman_error("%s invalid state change %s -> %s%s", task->ifname, oldstate, newstate, task->scanning == TRUE ? " (scanning)" : ""); }
static void scan_results_reply(DBusPendingCall *call, void *user_data) { struct supplicant_task *task = user_data; DBusMessage *reply; DBusError error; char **results; int i, num_results; _DBG_SUPPLICANT("task %p", task); reply = dbus_pending_call_steal_reply(call); if (reply == NULL) goto noscan; if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) goto done; dbus_error_init(&error); if (dbus_message_get_args(reply, &error, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &results, &num_results, DBUS_TYPE_INVALID) == FALSE) { if (dbus_error_is_set(&error) == TRUE) { connman_error("%s", error.message); dbus_error_free(&error); } else connman_error("Wrong arguments for scan result"); goto done; } if (num_results == 0) goto done; task->scangen++; for (i = 0; i < num_results; i++) { char *path = g_strdup(results[i]); if (path == NULL) continue; task->scan_results = g_slist_append(task->scan_results, path); } g_strfreev(results); dbus_message_unref(reply); get_properties(task); return; done: dbus_message_unref(reply); noscan: task->result_call = NULL; if (task->scanning == TRUE) { connman_device_set_scanning(task->device, FALSE); task->scanning = FALSE; } }
static void stop_autoscan(struct connman_device *device) { reset_autoscan(device); connman_device_set_scanning(device, FALSE); }
static void adapter_properties_reply(DBusPendingCall *call, void *user_data) { char *path = user_data; struct connman_device *device; DBusMessage *reply; DBusMessageIter networks; const char *address = NULL, *name = NULL; dbus_bool_t powered = FALSE, scanning = FALSE; struct ether_addr addr; char ident[13]; DBG("path %s", path); reply = dbus_pending_call_steal_reply(call); if (path == NULL) goto done; extract_properties(reply, NULL, &address, &name, NULL, &powered, &scanning, NULL, &networks); if (address == NULL) goto done; if (g_strcmp0(address, "00:00:00:00:00:00") == 0) goto done; device = g_hash_table_lookup(bluetooth_devices, path); if (device != NULL) goto update; ether_aton_r(address, &addr); snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x", addr.ether_addr_octet[0], addr.ether_addr_octet[1], addr.ether_addr_octet[2], addr.ether_addr_octet[3], addr.ether_addr_octet[4], addr.ether_addr_octet[5]); device = connman_device_create("bluetooth_legacy", CONNMAN_DEVICE_TYPE_BLUETOOTH); if (device == NULL) goto done; g_hash_table_insert(bluetooth_devices, g_strdup(path), device); connman_device_set_ident(device, ident); connman_device_set_string(device, "Path", path); if (connman_device_register(device) < 0) { connman_device_unref(device); g_hash_table_remove(bluetooth_devices, path); goto done; } update: connman_device_set_string(device, "Address", address); connman_device_set_string(device, "Name", name); connman_device_set_string(device, "Path", path); connman_device_set_powered(device, powered); connman_device_set_scanning(device, scanning); if (powered == FALSE) { remove_device_networks(device); add_pending_networks(path, &networks); } else check_networks(&networks); done: dbus_message_unref(reply); dbus_pending_call_unref(call); }