diff options
author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-13 20:47:52 +0000 |
---|---|---|
committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2006-03-13 20:47:52 +0000 |
commit | 1fe7ab081842276d8db73a44cc64c2115b618cc2 (patch) | |
tree | 5fe2f882ea3f2cf0fe99737956d11aea65cac0c1 | |
parent | 5a7676dd838717f9ce483af8e9be0acf80f2960c (diff) |
Added remote name resolving queue
-rw-r--r-- | hcid/dbus-adapter.c | 84 | ||||
-rw-r--r-- | hcid/dbus.c | 182 | ||||
-rw-r--r-- | hcid/dbus.h | 6 | ||||
-rw-r--r-- | hcid/hcid.h | 4 | ||||
-rw-r--r-- | hcid/security.c | 7 |
5 files changed, 217 insertions, 66 deletions
diff --git a/hcid/dbus-adapter.c b/hcid/dbus-adapter.c index c535b788..33ef99eb 100644 --- a/hcid/dbus-adapter.c +++ b/hcid/dbus-adapter.c @@ -1165,6 +1165,7 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D { DBusMessage *reply = NULL; const char *requestor_name; + const char *method; inquiry_cp cp; evt_cmd_status rp; struct hci_request rq; @@ -1176,6 +1177,12 @@ static DBusHandlerResult handle_dev_discover_devices_req(DBusConnection *conn, D if (dbus_data->requestor_name) return error_discover_in_progress(conn, msg); + method = dbus_message_get_member(msg); + if (strcmp("DiscoverDevicesWithoutNameResolving", method) == 0) + dbus_data->resolve_name = 0; + else + dbus_data->resolve_name = 1; + dd = hci_open_dev(dbus_data->dev_id); if (dd < 0) return error_no_such_adapter(conn, msg); @@ -1265,45 +1272,46 @@ static DBusHandlerResult handle_dev_cancel_discovery_req(DBusConnection *conn, D } static struct service_data dev_services[] = { - { "GetAddress", handle_dev_get_address_req, }, - { "GetVersion", handle_dev_get_version_req, }, - { "GetRevision", handle_dev_get_revision_req, }, - { "GetManufacturer", handle_dev_get_manufacturer_req, }, - { "GetCompany", handle_dev_get_company_req, }, - { "GetMode", handle_dev_get_mode_req, }, - { "SetMode", handle_dev_set_mode_req, }, - { "GetDiscoverableTimeout", handle_dev_get_discoverable_to_req, }, - { "SetDiscoverableTimeout", handle_dev_set_discoverable_to_req, }, - { "IsConnectable", handle_dev_is_connectable_req, }, - { "IsDiscoverable", handle_dev_is_discoverable_req, }, - { "GetMajorClass", handle_dev_get_major_class_req, }, - { "ListAvailableMinorClasses", handle_dev_list_minor_classes_req, }, - { "GetMinorClass", handle_dev_get_minor_class_req, }, - { "SetMinorClass", handle_dev_set_minor_class_req, }, - { "GetServicesClasses", handle_dev_get_service_classes_req, }, - { "GetName", handle_dev_get_name_req, }, - { "SetName", handle_dev_set_name_req, }, + { "GetAddress", handle_dev_get_address_req, }, + { "GetVersion", handle_dev_get_version_req, }, + { "GetRevision", handle_dev_get_revision_req, }, + { "GetManufacturer", handle_dev_get_manufacturer_req, }, + { "GetCompany", handle_dev_get_company_req, }, + { "GetMode", handle_dev_get_mode_req, }, + { "SetMode", handle_dev_set_mode_req, }, + { "GetDiscoverableTimeout", handle_dev_get_discoverable_to_req, }, + { "SetDiscoverableTimeout", handle_dev_set_discoverable_to_req, }, + { "IsConnectable", handle_dev_is_connectable_req, }, + { "IsDiscoverable", handle_dev_is_discoverable_req, }, + { "GetMajorClass", handle_dev_get_major_class_req, }, + { "ListAvailableMinorClasses", handle_dev_list_minor_classes_req, }, + { "GetMinorClass", handle_dev_get_minor_class_req, }, + { "SetMinorClass", handle_dev_set_minor_class_req, }, + { "GetServicesClasses", handle_dev_get_service_classes_req, }, + { "GetName", handle_dev_get_name_req, }, + { "SetName", handle_dev_set_name_req, }, - { "GetRemoteVersion", handle_dev_get_remote_version_req, }, - { "GetRemoteRevision", handle_dev_get_remote_revision_req, }, - { "GetRemoteManufacturer", handle_dev_get_remote_manufacturer_req, }, - { "GetRemoteCompany", handle_dev_get_remote_company_req, }, - { "GetRemoteName", handle_dev_get_remote_name_req, }, - { "GetRemoteAlias", handle_dev_get_remote_alias_req, }, - { "SetRemoteAlias", handle_dev_set_remote_alias_req, }, - - { "LastSeen", handle_dev_last_seen_req, }, - { "LastUsed", handle_dev_last_used_req, }, - - { "CreateBonding", handle_dev_create_bonding_req, }, - { "RemoveBonding", handle_dev_remove_bonding_req, }, - { "HasBonding", handle_dev_has_bonding_req, }, - { "ListBondings", handle_dev_list_bondings_req, }, - { "GetPinCodeLength", handle_dev_get_pin_code_length_req, }, - { "GetEncryptionKeySize", handle_dev_get_encryption_key_size_req, }, - - { "DiscoverDevices", handle_dev_discover_devices_req, }, - { "CancelDiscovery", handle_dev_cancel_discovery_req, }, + { "GetRemoteVersion", handle_dev_get_remote_version_req, }, + { "GetRemoteRevision", handle_dev_get_remote_revision_req, }, + { "GetRemoteManufacturer", handle_dev_get_remote_manufacturer_req, }, + { "GetRemoteCompany", handle_dev_get_remote_company_req, }, + { "GetRemoteName", handle_dev_get_remote_name_req, }, + { "GetRemoteAlias", handle_dev_get_remote_alias_req, }, + { "SetRemoteAlias", handle_dev_set_remote_alias_req, }, + + { "LastSeen", handle_dev_last_seen_req, }, + { "LastUsed", handle_dev_last_used_req, }, + + { "CreateBonding", handle_dev_create_bonding_req, }, + { "RemoveBonding", handle_dev_remove_bonding_req, }, + { "HasBonding", handle_dev_has_bonding_req, }, + { "ListBondings", handle_dev_list_bondings_req, }, + { "GetPinCodeLength", handle_dev_get_pin_code_length_req, }, + { "GetEncryptionKeySize", handle_dev_get_encryption_key_size_req, }, + + { "DiscoverDevices", handle_dev_discover_devices_req, }, + { "DiscoverDevicesWithoutNameResolving", handle_dev_discover_devices_req }, + { "CancelDiscovery", handle_dev_cancel_discovery_req, }, { NULL, NULL } }; diff --git a/hcid/dbus.c b/hcid/dbus.c index 988aa56c..4efc7457 100644 --- a/hcid/dbus.c +++ b/hcid/dbus.c @@ -45,6 +45,7 @@ #include "hcid.h" #include "dbus.h" #include "textfile.h" +#include "list.h" #ifndef DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT #define DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT 0x00 @@ -100,6 +101,57 @@ static const char *phone_minor_cls[] = { "isdn" }; +static bdaddr_t *remote_name_find(struct slist *list, bdaddr_t *addr) +{ + 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; + } + + return NULL; +} + +static int remote_name_add(struct slist **list, bdaddr_t *addr) +{ + bdaddr_t *data; + + /* ignore repeated entries */ + data = remote_name_find(*list, addr); + + if (data) + return -1; + + data = malloc(sizeof(bdaddr_t)); + if (!data) + return -1; + + data = malloc(sizeof(bdaddr_t)); + memcpy(data, addr, sizeof(bdaddr_t)); + + *list = slist_append(*list, data); + + return 0; +} + +static int remote_name_remove(struct slist **list, bdaddr_t *addr) +{ + bdaddr_t *data; + int ret_val = -1; + + data = remote_name_find(*list, addr); + + if (data) { + *list = slist_remove(*list, data); + free(data); + ret_val = 0; + } + + return ret_val; +} + /* * Timeout functions Protypes */ @@ -203,6 +255,7 @@ static gboolean register_dbus_path(const char *path, uint16_t path_id, uint16_t data->timeout_hits = 0; data->timeout_handler = NULL; data->requestor_name = NULL; + data->discovered_devices = NULL; if (fallback) { if (!dbus_connection_register_fallback(connection, path, pvtable, data)) { @@ -472,6 +525,36 @@ failed: bt_free(local_addr); } +static inline int remote_name_resolve(struct hci_dbus_data *dbus_data) +{ + bdaddr_t *bdaddr; + remote_name_req_cp cp; + int dd; + + /*get the next remote address */ + if (!dbus_data->discovered_devices) + return -1; + + bdaddr = (bdaddr_t *) dbus_data->discovered_devices->data; + if (!bdaddr) + return -1; + + dd = hci_open_dev(dbus_data->dev_id); + if (dd < 0) + return -1; + + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.bdaddr, bdaddr); + cp.pscan_rep_mode = 0x02; + + hci_send_cmd(dd, OGF_LINK_CTL, OCF_REMOTE_NAME_REQ, + REMOTE_NAME_REQ_CP_SIZE, &cp); + + hci_close_dev(dd); + + return 0; +} + void hcid_dbus_inquiry_complete(bdaddr_t *local) { DBusMessage *message = NULL; @@ -492,6 +575,10 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); if (dbus_connection_get_object_path_data(connection, path, (void*) &pdata)) { + if (pdata->resolve_name) + if (!remote_name_resolve(pdata)) + goto failed; /* skip, send discovery complete after resolve all remote names */ + if (pdata->requestor_name) { free(pdata->requestor_name); pdata->requestor_name = NULL; @@ -513,17 +600,20 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local) dbus_connection_flush(connection); failed: - dbus_message_unref(message); + if (message) + dbus_message_unref(message); bt_free(local_addr); } void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, int8_t rssi) { char filename[PATH_MAX + 1]; - DBusMessage *message = NULL; + DBusMessage *signal_device = NULL; + DBusMessage *signal_name = NULL; DBusMessageIter iter; DBusMessageIter array_iter; char path[MAX_PATH_LENGTH]; + struct hci_dbus_data *pdata = NULL; char *local_addr, *peer_addr, *name = NULL; const char *major_ptr; char invalid_minor_class[] = ""; @@ -544,9 +634,16 @@ 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); - message = dbus_message_new_signal(path, ADAPTER_INTERFACE, + 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; + } + + signal_device = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteDeviceFound"); - if (message == NULL) { + if (signal_device == NULL) { error("Can't allocate D-Bus inquiry result message"); goto failed; } @@ -569,7 +666,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i break; } - dbus_message_iter_init_append(message, &iter); + dbus_message_iter_init_append(signal_device, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &peer_addr); dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT16, &tmp_rssi); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &major_ptr); @@ -586,7 +683,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i dbus_message_iter_close_container(&iter, &array_iter); - if (dbus_connection_send(connection, message, NULL) == FALSE) { + if (dbus_connection_send(connection, signal_device, NULL) == FALSE) { error("Can't send D-Bus inquiry result message"); goto failed; } @@ -595,31 +692,36 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i name = textfile_get(filename, peer_addr); - if (!name) - goto failed; + if (!name) { + /* FIXME: if necessary create a queue to resolve the name */ - dbus_message_unref(message); + if (!dbus_connection_get_object_path_data(connection, path, (void*) &pdata)) { + error("Getting %s path data failed!", path); + goto failed; + } + + if (!pdata->resolve_name) + goto failed; /* skip - it is a normal request */ + else + remote_name_add(&pdata->discovered_devices, peer); - message = dbus_message_new_signal(path, ADAPTER_INTERFACE, - "RemoteDeviceFound"); - if (message == NULL) { - error("Can't allocate D-Bus inquiry result message"); goto failed; } - dbus_message_append_args(message, + + dbus_message_append_args(signal_name, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); - if (dbus_connection_send(connection, message, NULL) == FALSE) { + if (dbus_connection_send(connection, signal_name, NULL) == FALSE) error("Can't send D-Bus inquiry result message"); - goto failed; - } - - dbus_connection_flush(connection); failed: - dbus_message_unref(message); + if (signal_device) + dbus_message_unref(signal_device); + + if (signal_name) + dbus_message_unref(signal_name); bt_free(local_addr); bt_free(peer_addr); @@ -629,8 +731,9 @@ failed: } -void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name) +void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name) { + struct hci_dbus_data *pdata = NULL; DBusMessage *message = NULL; char path[MAX_PATH_LENGTH]; char *local_addr, *peer_addr; @@ -648,6 +751,16 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name) snprintf(path, sizeof(path), "%s/hci%d", ADAPTER_PATH, id); + + /* remove from remote name request list */ + if (dbus_connection_get_object_path_data(connection, path, (void*) &pdata)) + remote_name_remove(&pdata->discovered_devices, peer); + + if (!status) + goto request_next; + + + /* send the remote name update signal */ message = dbus_message_new_signal(path, ADAPTER_INTERFACE, "RemoteNameUpdated"); if (message == NULL) { @@ -667,6 +780,33 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name) dbus_connection_flush(connection); +request_next: + if (!pdata->requestor_name) + goto failed; /* handle requests from external app */ + + if (!remote_name_resolve(pdata)) + goto failed; /* skip: there is more remote name to resolve */ + + if (message) + dbus_message_unref(message); + + message = dbus_message_new_signal(path, ADAPTER_INTERFACE, + "DiscoveryCompleted"); + if (message == NULL) { + error("Can't allocate D-Bus inquiry complete message"); + goto failed; + } + + if (dbus_connection_send(connection, message, NULL) == FALSE) { + error("Can't send D-Bus inquiry complete message"); + goto failed; + } + + dbus_connection_flush(connection); + + free(pdata->requestor_name); + pdata->requestor_name = NULL; + failed: if (message) dbus_message_unref(message); diff --git a/hcid/dbus.h b/hcid/dbus.h index 86008489..14011fa4 100644 --- a/hcid/dbus.h +++ b/hcid/dbus.h @@ -75,8 +75,10 @@ struct hci_dbus_data { uint32_t discoverable_timeout; uint32_t timeout_hits; timeout_handler_func_t *timeout_handler; - uint8_t mode; - char *requestor_name; + uint8_t mode; /* scan mode */ + uint8_t resolve_name; /* send name on discover process */ + struct slist *discovered_devices; + char *requestor_name; /* requestor unique name */ }; struct passkey_agent { diff --git a/hcid/hcid.h b/hcid/hcid.h index b4e6f290..ca39bc1d 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -115,7 +115,7 @@ void hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci); void hcid_dbus_inquiry_start(bdaddr_t *local); void hcid_dbus_inquiry_complete(bdaddr_t *local); void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, int8_t rssi); -void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name); +void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name); void hcid_dbus_conn_complete(bdaddr_t *local, bdaddr_t *peer); void hcid_dbus_disconn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t reason); void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status); @@ -125,7 +125,7 @@ void hcid_dbus_setscan_enable_complete(bdaddr_t *local); static inline void hcid_dbus_inquiry_start(bdaddr_t *local) {} static inline void hcid_dbus_inquiry_complete(bdaddr_t *local) {} static inline void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, int8_t rssi) {} -static inline void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name) {} +static inline void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name) {} static inline void hcid_dbus_conn_complete(bdaddr_t *local, bdaddr_t *peer) {} static inline void hcid_dbus_disconn_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t reason) {} static inline void hcid_dbus_bonding_created_complete(bdaddr_t *local, bdaddr_t *peer, const uint8_t status) {} diff --git a/hcid/security.c b/hcid/security.c index cff54d9d..f3c03ef2 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -325,16 +325,17 @@ static inline void remote_name_information(int dev, bdaddr_t *sba, void *ptr) { evt_remote_name_req_complete *evt = ptr; bdaddr_t dba; + char name[249]; + memset(name, 0, sizeof(name)); bacpy(&dba, &evt->bdaddr); if (!evt->status) { - char name[249]; - memset(name, 0, sizeof(name)); memcpy(name, evt->name, 248); write_device_name(sba, &dba, name); - hcid_dbus_remote_name(sba, &dba, name); } + + hcid_dbus_remote_name(sba, &dba, evt->status, name); } static inline void remote_version_information(int dev, bdaddr_t *sba, void *ptr) |