diff options
author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2009-01-10 17:00:12 -0300 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2009-01-11 19:17:08 +0200 |
commit | c4338c0b7a46d6288e350b8c05fc02ee28b4bdbc (patch) | |
tree | 4f0002fd8c6fb30a75cf3a08de526ea092dbb476 | |
parent | 2aad1cf41acbc69481915d24cef33fa721d4e1fd (diff) |
Handle active connection using device object.
-rw-r--r-- | src/adapter.c | 194 | ||||
-rw-r--r-- | src/adapter.h | 19 | ||||
-rw-r--r-- | src/dbus-hci.c | 37 | ||||
-rw-r--r-- | src/device.c | 76 | ||||
-rw-r--r-- | src/device.h | 9 |
5 files changed, 149 insertions, 186 deletions
diff --git a/src/adapter.c b/src/adapter.c index 5df012e6..458d536f 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -107,7 +107,7 @@ struct btd_adapter { DBusMessage *discovery_cancel; /* discovery cancel message request */ GSList *passkey_agents; struct agent *agent; /* For the new API */ - GSList *active_conn; + GSList *connections; /* Connected devices */ GSList *devices; /* Devices structure pointers */ GSList *mode_sessions; /* Request Mode sessions */ GSList *disc_sessions; /* Discovery sessions */ @@ -176,25 +176,6 @@ static inline DBusMessage *unsupported_major_class(DBusMessage *msg) "Unsupported Major Class"); } -static int active_conn_find_by_bdaddr(const void *data, const void *user_data) -{ - const struct active_conn_info *con = data; - const bdaddr_t *bdaddr = user_data; - - return bacmp(&con->bdaddr, bdaddr); -} - -static int active_conn_find_by_handle(const void *data, const void *user_data) -{ - const struct active_conn_info *dev = data; - const uint16_t *handle = user_data; - - if (dev->handle == *handle) - return 0; - - return -1; -} - static void send_out_of_range(const char *path, GSList *l) { while (l) { @@ -900,6 +881,21 @@ struct btd_device *adapter_find_device(struct btd_adapter *adapter, const char * return device; } +struct btd_device *adapter_find_connection(struct btd_adapter *adapter, + uint16_t handle) +{ + GSList *l; + + for (l = adapter->connections; l; l = l->next) { + struct btd_device *device = l->data; + + if (device_has_connection(device, handle)) + return device; + } + + return NULL; +} + static void adapter_update_devices(struct btd_adapter *adapter) { char **devices; @@ -1816,20 +1812,6 @@ static int adapter_setup(struct btd_adapter *adapter, int dd) return 0; } -static int active_conn_append(GSList **list, bdaddr_t *bdaddr, - uint16_t handle) -{ - struct active_conn_info *dev; - - dev = g_new0(struct active_conn_info, 1); - - bacpy(&dev->bdaddr, bdaddr); - dev->handle = handle; - - *list = g_slist_append(*list, dev); - return 0; -} - static void create_stored_device_from_profiles(char *key, char *value, void *user_data) { @@ -1904,6 +1886,36 @@ static void load_drivers(struct btd_adapter *adapter) } } +static void load_connections(struct btd_adapter *adapter, int dd) +{ + struct hci_conn_list_req *cl = NULL; + struct hci_conn_info *ci; + int i; + + cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); + + cl->dev_id = adapter->dev_id; + cl->conn_num = 10; + ci = cl->conn_info; + + if (ioctl(dd, HCIGETCONNLIST, cl) != 0) { + g_free(cl); + return; + } + + for (i = 0; i < cl->conn_num; i++, ci++) { + struct btd_device *device; + char address[18]; + + ba2str(&ci->bdaddr, address); + device = adapter_get_device(connection, adapter, address); + if (device) + adapter_add_connection(adapter, device, ci->handle); + } + + g_free(cl); +} + static int get_discoverable_timeout(const char *src) { int timeout; @@ -1927,7 +1939,6 @@ static int get_pairable_timeout(const char *src) static int adapter_up(struct btd_adapter *adapter, int dd) { char mode[14], srcaddr[18]; - int i; uint8_t scan_mode; gboolean powered, dev_down = FALSE; @@ -1980,39 +1991,23 @@ static int adapter_up(struct btd_adapter *adapter, int dd) } proceed: - if (dev_down == FALSE) + if (dev_down == FALSE) { hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &scan_mode); - /* retrieve the active connections: address the scenario where - * the are active connections before the daemon've started */ - if (adapter->initialized == FALSE) { - struct hci_conn_list_req *cl = NULL; - struct hci_conn_info *ci; - - cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); - - cl->dev_id = adapter->dev_id; - cl->conn_num = 10; - ci = cl->conn_info; - - if (ioctl(dd, HCIGETCONNLIST, cl) == 0) { - for (i = 0; i < cl->conn_num; i++, ci++) - active_conn_append(&adapter->active_conn, - &ci->bdaddr, ci->handle); - } - - g_free(cl); - } - - if (dev_down == FALSE) emit_property_changed(connection, adapter->path, ADAPTER_INTERFACE, "Powered", DBUS_TYPE_BOOLEAN, &powered); + } if (adapter->initialized == FALSE) { load_drivers(adapter); load_devices(adapter); + + /* retrieve the active connections: address the scenario where + * the are active connections before the daemon've started */ + load_connections(adapter, dd); + adapter->initialized = TRUE; } @@ -2211,10 +2206,9 @@ int adapter_stop(struct btd_adapter *adapter) adapter->oor_devices = NULL; } - if (adapter->active_conn) { - g_slist_foreach(adapter->active_conn, (GFunc) g_free, NULL); - g_slist_free(adapter->active_conn); - adapter->active_conn = NULL; + if (adapter->connections) { + g_slist_free(adapter->connections); + adapter->connections = NULL; } if (adapter->scan_mode == (SCAN_PAGE | SCAN_INQUIRY)) { @@ -2645,62 +2639,43 @@ struct agent *adapter_get_agent(struct btd_adapter *adapter) return adapter->agent; } -void adapter_add_active_conn(struct btd_adapter *adapter, bdaddr_t *bdaddr, - uint16_t handle) +void adapter_add_connection(struct btd_adapter *adapter, + struct btd_device *device, uint16_t handle) { - struct active_conn_info *dev; - - if (!adapter) + if (g_slist_find(adapter->connections, device)) { + error("Unable to add connection %d", handle); return; + } - dev = g_new0(struct active_conn_info, 1); - - bacpy(&dev->bdaddr, bdaddr); - dev->handle = handle; - - adapter->active_conn = g_slist_append(adapter->active_conn, dev); -} - -void adapter_remove_active_conn(struct btd_adapter *adapter, - struct active_conn_info *dev) -{ - if (!adapter || !adapter->active_conn) - return; + device_add_connection(device, connection, handle); - adapter->active_conn = g_slist_remove(adapter->active_conn, dev); - g_free(dev); + adapter->connections = g_slist_append(adapter->connections, device); } -struct active_conn_info *adapter_search_active_conn_by_bdaddr(struct btd_adapter *adapter, - bdaddr_t *bda) +void adapter_remove_connection(struct btd_adapter *adapter, + struct btd_device *device, uint16_t handle) { - GSList *l; - - if (!adapter || !adapter->active_conn) - return NULL; + bdaddr_t bdaddr; - l = g_slist_find_custom(adapter->active_conn, bda, - active_conn_find_by_bdaddr); - if (l) - return l->data; + if (!g_slist_find(adapter->connections, device)) { + error("No matching connection for handle %u", handle); + return; + } - return NULL; -} + device_remove_connection(device, connection, handle); -struct active_conn_info *adapter_search_active_conn_by_handle(struct btd_adapter *adapter, - uint16_t handle) -{ - GSList *l; + adapter->connections = g_slist_remove(adapter->connections, device); - if (!adapter || !adapter->active_conn) - return NULL; + /* clean pending HCI cmds */ + device_get_address(device, &bdaddr); + hci_req_queue_remove(adapter->dev_id, &bdaddr); - l = g_slist_find_custom(adapter->active_conn, &handle, - active_conn_find_by_handle); - if (l) - return l->data; + if (device_is_temporary(device)) { + const char *path = device_get_path(device); - return NULL; + debug("Removing temporary device %s", path); + adapter_remove_device(connection, adapter, device); + } } gboolean adapter_has_discov_sessions(struct btd_adapter *adapter) @@ -2761,12 +2736,15 @@ static int btd_adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *ds gboolean trusted; const gchar *dev_path; + ba2str(dst, address); + device = adapter_find_device(adapter, address); + if (!device) + return -EPERM; + /* Device connected? */ - if (!g_slist_find_custom(adapter->active_conn, - dst, active_conn_find_by_bdaddr)) + if (!g_slist_find(adapter->connections, device)) return -ENOTCONN; - ba2str(dst, address); trusted = read_trust(&adapter->bdaddr, address, GLOBAL_TRUST); if (trusted) { diff --git a/src/adapter.h b/src/adapter.h index 2f9068f2..6c63b7e0 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -53,11 +53,6 @@ struct remote_dev_info { name_status_t name_status; }; -struct active_conn_info { - bdaddr_t bdaddr; - uint16_t handle; -}; - struct hci_dev { int ignore; @@ -89,6 +84,8 @@ struct btd_device *adapter_get_device(DBusConnection *conn, struct btd_device *adapter_find_device(struct btd_adapter *adapter, const char *dest); +struct btd_device *adapter_find_connection(struct btd_adapter *adapter, uint16_t handle); + void adapter_remove_device(DBusConnection *conn, struct btd_adapter *adapter, struct btd_device *device); struct btd_device *adapter_create_device(DBusConnection *conn, @@ -116,14 +113,10 @@ void adapter_update_oor_devices(struct btd_adapter *adapter); void adapter_remove_oor_device(struct btd_adapter *adapter, char *peer_addr); void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode); struct agent *adapter_get_agent(struct btd_adapter *adapter); -void adapter_add_active_conn(struct btd_adapter *adapter, bdaddr_t *bdaddr, - uint16_t handle); -void adapter_remove_active_conn(struct btd_adapter *adapter, - struct active_conn_info *dev); -struct active_conn_info *adapter_search_active_conn_by_bdaddr(struct btd_adapter *adapter, - bdaddr_t *bda); -struct active_conn_info *adapter_search_active_conn_by_handle(struct btd_adapter *adapter, - uint16_t handle); +void adapter_add_connection(struct btd_adapter *adapter, + struct btd_device *device, uint16_t handle); +void adapter_remove_connection(struct btd_adapter *adapter, + struct btd_device *device, uint16_t handle); gboolean adapter_has_discov_sessions(struct btd_adapter *adapter); struct btd_adapter_driver { diff --git a/src/dbus-hci.c b/src/dbus-hci.c index 0e574aff..49154a61 100644 --- a/src/dbus-hci.c +++ b/src/dbus-hci.c @@ -936,7 +936,7 @@ void hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer) return; } - if (!device_get_connected(device)) + if (!device_is_connected(device)) device_set_secmode3_conn(device, TRUE); else if (!device_is_bonding(device, NULL)) hcid_dbus_bonding_process_complete(local, peer, 0); @@ -970,20 +970,15 @@ void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, return; } - device_set_connected(device, connection, TRUE); - - /* add in the active connetions list */ - adapter_add_active_conn(adapter, peer, handle); + /* add in the device connetions list */ + adapter_add_connection(adapter, device, handle); } void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason) { - char peer_addr[18]; struct btd_adapter *adapter; struct btd_device *device; - struct active_conn_info *dev; - uint16_t dev_id; if (status) { error("Disconnection failed: 0x%02x", status); @@ -996,31 +991,13 @@ void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, return; } - dev = adapter_search_active_conn_by_handle(adapter, handle); - if (!dev) { - error("No matching connection for handle %u", handle); + device = adapter_find_connection(adapter, handle); + if (!device) { + error("No matching connection found for handle %u", handle); return; } - ba2str(&dev->bdaddr, peer_addr); - - dev_id = adapter_get_dev_id(adapter); - - /* clean pending HCI cmds */ - hci_req_queue_remove(dev_id, &dev->bdaddr); - - adapter_remove_active_conn(adapter, dev); - - device = adapter_find_device(adapter, peer_addr); - if (!device) - return; - - device_set_connected(device, connection, FALSE); - - if (device_is_temporary(device)) { - debug("Removing temporary device %s", peer_addr); - adapter_remove_device(connection, adapter, device); - } + adapter_remove_connection(adapter, device, handle); } int set_service_classes(int dd, const uint8_t *cls, uint8_t value) diff --git a/src/device.c b/src/device.c index 7891d1e5..8317dcb9 100644 --- a/src/device.c +++ b/src/device.c @@ -102,7 +102,7 @@ struct btd_device { uint8_t cap; uint8_t auth; - gboolean connected; + uint16_t handle; /* Connection handle */ /* Whether were creating a security mode 3 connection */ gboolean secmode3; @@ -225,7 +225,6 @@ static DBusMessage *get_properties(DBusConnection *conn, uint32_t class; int i; GSList *l; - struct active_conn_info *dev; ba2str(&device->bdaddr, dstaddr); @@ -287,13 +286,9 @@ static DBusMessage *get_properties(DBusConnection *conn, dict_append_entry(&dict, "Trusted", DBUS_TYPE_BOOLEAN, &boolean); /* Connected */ - dev = adapter_search_active_conn_by_bdaddr(adapter, &device->bdaddr); - if (dev) - boolean = TRUE; - else - boolean = FALSE; - - dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &boolean); + boolean = (device->handle != 0); + dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, + &boolean); /* UUIDs */ uuids = g_new0(char *, g_slist_length(device->uuids) + 1); @@ -493,25 +488,18 @@ static DBusMessage *cancel_discover(DBusConnection *conn, static gboolean disconnect_timeout(gpointer user_data) { struct btd_device *device = user_data; - struct active_conn_info *ci; disconnect_cp cp; int dd; uint16_t dev_id = adapter_get_dev_id(device->adapter); device->disconn_timer = 0; - ci = adapter_search_active_conn_by_bdaddr(device->adapter, - &device->bdaddr); - - if (!ci) - return FALSE; - dd = hci_open_dev(dev_id); if (dd < 0) goto fail; memset(&cp, 0, sizeof(cp)); - cp.handle = htobs(ci->handle); + cp.handle = htobs(device->handle); cp.reason = HCI_OE_USER_ENDED_CONNECTION; hci_send_cmd(dd, OGF_LINK_CTL, OCF_DISCONNECT, @@ -527,12 +515,8 @@ static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct btd_device *device = user_data; - struct active_conn_info *dev; - - dev = adapter_search_active_conn_by_bdaddr(device->adapter, - &device->bdaddr); - if (!dev) + if (!device->handle) return g_dbus_create_error(msg, ERROR_INTERFACE ".NotConnected", "Device is not connected"); @@ -563,16 +547,14 @@ static GDBusSignalTable device_signals[] = { { } }; -gboolean device_get_connected(struct btd_device *device) +gboolean device_is_connected(struct btd_device *device) { - return device->connected; + return (device->handle != 0); } -void device_set_connected(struct btd_device *device, DBusConnection *conn, +static void device_set_connected(struct btd_device *device, DBusConnection *conn, gboolean connected) { - device->connected = connected; - emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Connected", DBUS_TYPE_BOOLEAN, &connected); @@ -588,6 +570,39 @@ void device_set_connected(struct btd_device *device, DBusConnection *conn, } } +void device_add_connection(struct btd_device *device, DBusConnection *conn, + uint16_t handle) +{ + if (device->handle) { + error("%s: Unable to add connection %u, %u already exist)", + device->path, handle, device->handle); + return; + } + + device->handle = handle; + + device_set_connected(device, conn, TRUE); +} + +void device_remove_connection(struct btd_device *device, DBusConnection *conn, + uint16_t handle) +{ + if (device->handle != handle) { + error("%s: Unable to remove connection %u, handle mismatch (%u)", + device->path, handle, device->handle); + return; + } + + device->handle = 0; + + device_set_connected(device, conn, FALSE); +} + +gboolean device_has_connection(struct btd_device *device, uint16_t handle) +{ + return (handle == device->handle); +} + void device_set_secmode3_conn(struct btd_device *device, gboolean enable) { device->secmode3 = enable; @@ -626,7 +641,6 @@ struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapt static void device_remove_bonding(struct btd_device *device, DBusConnection *conn) { - struct active_conn_info *ci; char filename[PATH_MAX + 1]; char *str, srcaddr[18], dstaddr[18]; int dd, dev_id; @@ -661,10 +675,8 @@ static void device_remove_bonding(struct btd_device *device, DBusConnection *con hci_delete_stored_link_key(dd, &device->bdaddr, 0, HCI_REQ_TIMEOUT); /* Send the HCI disconnect command */ - ci = adapter_search_active_conn_by_bdaddr(device->adapter, - &device->bdaddr); - if (ci) { - int err = hci_disconnect(dd, htobs(ci->handle), + if (device->handle) { + int err = hci_disconnect(dd, htobs(device->handle), HCI_OE_USER_ENDED_CONNECTION, HCI_REQ_TIMEOUT); if (err < 0) diff --git a/src/device.h b/src/device.h index c9137f7c..2b2735c0 100644 --- a/src/device.h +++ b/src/device.h @@ -55,9 +55,7 @@ void device_set_temporary(struct btd_device *device, gboolean temporary); void device_set_cap(struct btd_device *device, uint8_t cap); void device_set_auth(struct btd_device *device, uint8_t auth); uint8_t device_get_auth(struct btd_device *device); -gboolean device_get_connected(struct btd_device *device); -void device_set_connected(struct btd_device *device, DBusConnection *conn, - gboolean connected); +gboolean device_is_connected(struct btd_device *device); void device_set_secmode3_conn(struct btd_device *device, gboolean enable); DBusMessage *device_create_bonding(struct btd_device *device, DBusConnection *conn, DBusMessage *msg, @@ -70,6 +68,11 @@ int device_request_authentication(struct btd_device *device, auth_type_t type, uint32_t passkey, void *cb); void device_cancel_authentication(struct btd_device *device); gboolean device_is_authenticating(struct btd_device *device); +void device_add_connection(struct btd_device *device, DBusConnection *conn, + uint16_t handle); +void device_remove_connection(struct btd_device *device, DBusConnection *conn, + uint16_t handle); +gboolean device_has_connection(struct btd_device *device, uint16_t handle); #define BTD_UUIDS(args...) ((const char *[]) { args, NULL } ) |