diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2010-02-03 12:02:42 -0800 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@nokia.com> | 2010-02-03 12:07:51 -0800 |
commit | 989c60c0b9c96edf1fbdf80356abf05bac336673 (patch) | |
tree | 5d7250b3147de0d87a0fb7133b249ebcb053ab75 | |
parent | c7eadb0e913a7979510a66c74f2113b8b12523ab (diff) | |
download | bluez-989c60c0b9c96edf1fbdf80356abf05bac336673.tar.gz bluez-989c60c0b9c96edf1fbdf80356abf05bac336673.tar.xz bluez-989c60c0b9c96edf1fbdf80356abf05bac336673.zip |
Check for cached remote host features during discovery
If a remote name is cached and we didn't got a non-EIR event we should
check for cached remote host features for SSP support to behave
correctly with SSP & non-EIR devices.
-rw-r--r-- | src/dbus-hci.c | 18 | ||||
-rw-r--r-- | src/storage.c | 45 | ||||
-rw-r--r-- | src/storage.h | 1 |
3 files changed, 60 insertions, 4 deletions
diff --git a/src/dbus-hci.c b/src/dbus-hci.c index a943b9b3..176e27b2 100644 --- a/src/dbus-hci.c +++ b/src/dbus-hci.c @@ -472,6 +472,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, name_status_t name_status; int state; dbus_bool_t legacy; + unsigned char features[8]; ba2str(local, local_addr); ba2str(peer, peer_addr); @@ -497,8 +498,6 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, adapter_set_state(adapter, state); } - legacy = (data == NULL); - memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, peer); match.name_status = NAME_SENT; @@ -506,7 +505,7 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, dev = adapter_search_found_devices(adapter, &match); if (dev) { adapter_update_found_devices(adapter, peer, rssi, class, - NULL, NULL, legacy, + NULL, NULL, dev->legacy, NAME_NOT_REQUIRED); return; } @@ -523,6 +522,18 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names"); name = textfile_get(filename, peer_addr); + if (data) + legacy = FALSE; + else if (name == NULL) + legacy = TRUE; + else if (read_remote_features(local, peer, NULL, features) == 0) { + if (features[0] & 0x01) + legacy = FALSE; + else + legacy = TRUE; + } else + legacy = TRUE; + tmp_name = extract_eir_name(data, &name_type); if (tmp_name) { if (name_type == 0x09) { @@ -541,7 +552,6 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, } } - if (name && name_type != 0x08) name_status = NAME_SENT; diff --git a/src/storage.c b/src/storage.c index 1a1deb7b..981c7440 100644 --- a/src/storage.c +++ b/src/storage.c @@ -515,6 +515,51 @@ int write_features_info(bdaddr_t *local, bdaddr_t *peer, return textfile_put(filename, addr, str); } +static int decode_bytes(const char *str, unsigned char *bytes, size_t len) +{ + unsigned int i; + + for (i = 0; i < len; i++) { + if (sscanf(str + (i * 2), "%02hhX", &bytes[i]) != 1) + return -EINVAL; + } + + return 0; +} + +int read_remote_features(bdaddr_t *local, bdaddr_t *peer, + unsigned char *page1, unsigned char *page2) +{ + char filename[PATH_MAX + 1], addr[18], *str; + size_t len; + int err; + + if (page1 == NULL && page2 == NULL) + return -EINVAL; + + create_filename(filename, PATH_MAX, local, "features"); + + ba2str(peer, addr); + + str = textfile_get(filename, addr); + if (!str) + return -ENOENT; + + len = strlen(str); + + err = -ENOENT; + + if (page1 && len >= 16) + err = decode_bytes(str, page1, 8); + + if (page2 && len >= 33) + err = decode_bytes(str + 17, page2, 8); + + free(str); + + return err; +} + int write_lastseen_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm) { char filename[PATH_MAX + 1], addr[18], str[24]; diff --git a/src/storage.h b/src/storage.h index d4542d42..ed507342 100644 --- a/src/storage.h +++ b/src/storage.h @@ -48,6 +48,7 @@ int read_l2cap_info(bdaddr_t *local, bdaddr_t *peer, uint16_t *mask_result, uint32_t *mask); int write_version_info(bdaddr_t *local, bdaddr_t *peer, uint16_t manufacturer, uint8_t lmp_ver, uint16_t lmp_subver); int write_features_info(bdaddr_t *local, bdaddr_t *peer, unsigned char *page1, unsigned char *page2); +int read_remote_features(bdaddr_t *local, bdaddr_t *peer, unsigned char *page1, unsigned char *page2); int write_lastseen_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm); int write_lastused_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm); int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, uint8_t type, int length); |