diff options
-rw-r--r-- | hcid/dbus-adapter.c | 8 | ||||
-rw-r--r-- | hcid/dbus.c | 134 | ||||
-rw-r--r-- | hcid/dbus.h | 12 |
3 files changed, 111 insertions, 43 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index 136ac5fc..2ff247de 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -73,12 +73,6 @@ static const char *phone_minor_cls[] = { "isdn" }; -static void remote_name_data_free(void *data, void *user_data) -{ - bdaddr_t *addr = data; - bt_free(addr); -} - static DBusHandlerResult handle_dev_get_address_req(DBusConnection *conn, DBusMessage *msg, void *data) { struct hci_dbus_data *dbus_data = data; @@ -1280,7 +1274,7 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D break; } - slist_foreach(dbus_data->discovered_devices, remote_name_data_free, NULL); + slist_foreach(dbus_data->discovered_devices, discovered_device_free, NULL); slist_free(dbus_data->discovered_devices); dbus_data->discovered_devices = NULL; diff --git a/hcid/dbus.c b/hcid/dbus.c index 30c01b01..54bc54b4 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -101,35 +101,59 @@ static const char *phone_minor_cls[] = { "isdn" }; -static bdaddr_t *remote_name_find(struct slist *list, bdaddr_t *addr) +void discovered_device_free(void *data, void *user_data) { - struct slist *current; - - for (current = list; current != NULL; current = current->next) { - bdaddr_t *data = current->data; - if (memcmp(data, addr, sizeof(*addr)) == 0) - return data; + struct discovered_dev_info *dev = data; + if (dev) { + free(dev->addr); + free(dev); } +} + +int remote_name_find_by_address(const void *a, const void *b) +{ + const struct discovered_dev_info *dev = a; + const bdaddr_t *addr = b; + + if (memcmp(dev->addr, addr, sizeof(*addr)) == 0) + return 0; + + return -1; +} + +int remote_name_find_by_name_status(const void *a, const void *b) +{ + const struct discovered_dev_info *dev = a; + const name_status_t *name_status = b; + + if (dev->name_status == *name_status) + return 0; - return NULL; + return -1; } -static int remote_name_add(struct slist **list, bdaddr_t *addr) +static int remote_name_append(struct slist **list, bdaddr_t *addr, name_status_t name_status) { - bdaddr_t *data; + struct discovered_dev_info *data = NULL; + struct slist *tmp_list; /* ignore repeated entries */ - data = remote_name_find(*list, addr); + tmp_list = slist_find(*list, addr, remote_name_find_by_address); - if (data) + if (tmp_list) { + /* device found, update the attributes */ + data = tmp_list->data; + data->name_status = name_status; return -1; + } - data = malloc(sizeof(bdaddr_t)); + data = malloc(sizeof(*data)); if (!data) return -1; - data = malloc(sizeof(bdaddr_t)); - memcpy(data, addr, sizeof(bdaddr_t)); + data->addr = malloc(sizeof(*data->addr)); + memcpy(data->addr, addr, sizeof(*data->addr)); + data->name_status = name_status; *list = slist_append(*list, data); @@ -138,13 +162,16 @@ static int remote_name_add(struct slist **list, bdaddr_t *addr) static int remote_name_remove(struct slist **list, bdaddr_t *addr) { - bdaddr_t *data; + struct discovered_dev_info *data; + struct slist *tmp_list; int ret_val = -1; - data = remote_name_find(*list, addr); + tmp_list = slist_find(*list, addr, remote_name_find_by_address); - if (data) { + if (tmp_list) { + data = tmp_list->data; *list = slist_remove(*list, data); + free(data->addr); free(data); ret_val = 0; } @@ -525,16 +552,23 @@ failed: static inline int remote_name_resolve(struct hci_dbus_data *dbus_data) { - bdaddr_t *bdaddr; + struct discovered_dev_info *data; + struct slist *tmp_list = NULL; remote_name_req_cp cp; int dd; + name_status_t name_status = NAME_PENDING; /*get the next remote address */ if (!dbus_data->discovered_devices) return -1; - bdaddr = (bdaddr_t *) dbus_data->discovered_devices->data; - if (!bdaddr) + tmp_list = slist_find(dbus_data->discovered_devices, &name_status, remote_name_find_by_name_status); + + if (!tmp_list) + return -1; + + data = tmp_list->data; + if (!data) return -1; dd = hci_open_dev(dbus_data->dev_id); @@ -542,7 +576,7 @@ static inline int remote_name_resolve(struct hci_dbus_data *dbus_data) return -1; memset(&cp, 0, sizeof(cp)); - bacpy(&cp.bdaddr, bdaddr); + bacpy(&cp.bdaddr, data->addr); cp.pscan_rep_mode = 0x02; hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, @@ -579,10 +613,16 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) if (!remote_name_resolve(pdata)) goto failed; /* skip, sending the first name to resolve */ - else - pdata->discover_state = DISCOVER_OFF; /* no names to resolve */ + + pdata->discover_state = DISCOVER_OFF; /* no names to resolve */ + } + /* free discovered devices list */ + slist_foreach(pdata->discovered_devices, discovered_device_free, NULL); + slist_free(pdata->discovered_devices); + pdata->discovered_devices = NULL; + if (pdata->requestor_name) { free(pdata->requestor_name); pdata->requestor_name = NULL; @@ -618,6 +658,8 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i DBusMessageIter array_iter; char path[MAX_PATH_LENGTH]; struct hci_dbus_data *pdata = NULL; + struct slist *list = NULL; + struct discovered_dev_info *dev; char *local_addr, *peer_addr, *name = NULL; const char *major_ptr; char invalid_minor_class[] = ""; @@ -626,6 +668,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i bdaddr_t tmp; int id, i; uint8_t service_index, major_index, minor_index; + name_status_t name_status = NAME_PENDING; baswap(&tmp, local); local_addr = batostr(&tmp); baswap(&tmp, peer); peer_addr = batostr(&tmp); @@ -638,13 +681,12 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); - signal_name = dbus_message_new_signal(path, ADAPTER_INTERFACE, - "RemoteNameUpdated"); - if (signal_name == NULL) { - error("Can't allocate D-Bus inquiry result message"); + if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { + error("Getting %s path data failed!", path); goto failed; } + /* send the device found signal */ signal_device = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceFound"); if (signal_device == NULL) { @@ -692,28 +734,43 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i goto failed; } + /* send the remote name signal */ + list = slist_find(pdata->discovered_devices, peer, remote_name_find_by_address); + + if (list) { + dev = list->data; + if (dev->name_status == NAME_SENT) + goto failed; /* don't sent the name again */ + } + + signal_name = dbus_message_new_signal(path, ADAPTER_INTERFACE, + "RemoteNameUpdated"); + if (signal_name == NULL) { + error("Can't allocate D-Bus inquiry result message"); + goto failed; + } + snprintf(filename, PATH_MAX, "%s/%s/names", STORAGEDIR, local_addr); name = textfile_get(filename, peer_addr); if (name) { dbus_message_append_args(signal_name, + DBUS_TYPE_STRING, &peer_addr, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); if (dbus_connection_send(connection, signal_name, NULL) == FALSE) error("Can't send D-Bus inquiry result message"); - } else { - if (!dbus_connection_get_object_path_data(connection, path, (void *) &pdata)) { - error("Getting %s path data failed!", path); - goto failed; - } - - if (pdata->discover_state == DISCOVER_RUNNING_WITH_NAMES) - remote_name_add(&pdata->discovered_devices, peer); + name_status = NAME_SENT; } + /* handle only requests triggered by dbus applications */ + if ((pdata->discover_state == DISCOVER_RUNNING_WITH_NAMES) || + (pdata->discover_state == DISCOVER_RUNNING)) + remote_name_append(&pdata->discovered_devices, peer, name_status); + failed: if (signal_device) dbus_message_unref(signal_device); @@ -785,6 +842,11 @@ request_next: if (!remote_name_resolve(pdata)) goto failed; /* skip: there is more remote name to resolve */ + /* free discovered devices list */ + slist_foreach(pdata->discovered_devices, discovered_device_free, NULL); + slist_free(pdata->discovered_devices); + pdata->discovered_devices = NULL; + if (message) dbus_message_unref(message); diff --git a/hcid/dbus.h b/hcid/dbus.h index c791e112..ec2efd93 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -79,6 +79,16 @@ typedef enum { RESOLVING_NAMES } discover_state_t; +typedef enum { + NAME_PENDING, + NAME_SENT +}name_status_t; + +struct discovered_dev_info { + bdaddr_t *addr; + name_status_t name_status; +}; + struct hci_dbus_data { uint16_t dev_id; uint16_t path_id; @@ -156,6 +166,8 @@ static inline DBusHandlerResult send_reply_and_unref(DBusConnection *conn, DBusM return DBUS_HANDLER_RESULT_HANDLED; } +void discovered_device_free(void *data, void *user_data); + /* * Scanning modes, used by DEV_SET_MODE * off: remote devices are not allowed to find or connect to this device |