summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hcid/dbus-adapter.c8
-rw-r--r--hcid/dbus.c134
-rw-r--r--hcid/dbus.h12
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