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.
diff --git a/src/dbus-hci.c b/src/dbus-hci.c
index a943b9b..176e27b 100644
--- a/src/dbus-hci.c
+++ b/src/dbus-hci.c
@@ -472,6 +472,7 @@
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 @@
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 @@
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 @@
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 @@
}
}
-
if (name && name_type != 0x08)
name_status = NAME_SENT;
diff --git a/src/storage.c b/src/storage.c
index 1a1deb7..981c744 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -515,6 +515,51 @@
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 d4542d4..ed50734 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -48,6 +48,7 @@
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);