* [PATCH 2/4] neard: Move device object checking into separate helper
2012-11-19 15:03 [PATCH 1/4] neard: Use ENONET error when adapter is not enabled Szymon Janc
@ 2012-11-19 15:03 ` Szymon Janc
2012-11-19 15:03 ` [PATCH 3/4] neard: Add support for nokia.com:bt type Szymon Janc
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Szymon Janc @ 2012-11-19 15:03 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This will also be used by 'nokia.com:bt' handler.
---
plugins/neard.c | 47 +++++++++++++++++++++++++++++------------------
1 file changed, 29 insertions(+), 18 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 1576be5..8319445 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -248,13 +248,38 @@ static void bonding_complete(struct btd_adapter *adapter,
error("D-Bus send failed");
}
+static int check_device(struct btd_adapter *adapter, const char *address)
+{
+ struct btd_device *device;
+
+ device = adapter_find_device(adapter, address);
+
+ /* If already paired */
+ if (device && device_is_paired(device)) {
+ DBG("already paired");
+ return 1;
+ }
+
+ /* Pairing in progress... */
+ if (device && device_is_bonding(device, NULL)) {
+ DBG("pairing in progress");
+ return -EINPROGRESS;
+ }
+
+ /* If we have unpaired device hanging around, purge it */
+ if (device)
+ adapter_remove_device(adapter, device, TRUE);
+
+ return 0;
+}
+
/* returns 1 if pairing is not needed */
static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
bdaddr_t *remote)
{
- struct btd_device *device;
struct eir_data eir_data;
char remote_address[18];
+ int ret;
DBG("size %zu", size);
@@ -267,26 +292,12 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
- device = adapter_find_device(adapter, remote_address);
-
- /* If already paired do nothing */
- if (device && device_is_paired(device)) {
- DBG("already paired");
+ ret = check_device (adapter, remote_address);
+ if (ret != 0) {
eir_data_free(&eir_data);
- return 1;
+ return ret;
}
- /* Pairing in progress... */
- if (device && device_is_bonding(device, NULL)) {
- DBG("pairing in progress");
- eir_data_free(&eir_data);
- return -EINPROGRESS;
- }
-
- /* If we have unpaired device hanging around, purge it */
- if (device)
- adapter_remove_device(adapter, device, TRUE);
-
/* store OOB data */
if (eir_data.class != 0)
write_remote_class(adapter_get_address(adapter),
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/4] neard: Add support for nokia.com:bt type
2012-11-19 15:03 [PATCH 1/4] neard: Use ENONET error when adapter is not enabled Szymon Janc
2012-11-19 15:03 ` [PATCH 2/4] neard: Move device object checking into separate helper Szymon Janc
@ 2012-11-19 15:03 ` Szymon Janc
2012-11-19 15:03 ` [PATCH 4/4] neard: Append hash/randomizer in EIR only if remote provided it Szymon Janc
2012-11-20 10:25 ` [PATCH 1/4] neard: Use ENONET error when adapter is not enabled Johan Hedberg
3 siblings, 0 replies; 5+ messages in thread
From: Szymon Janc @ 2012-11-19 15:03 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This adds support for parsing nokia.com:bt type supported by some Nokia
NFC enabled devices. This is not fully documented Nokia extension so
to keep implementation sane and simple only PushOOB method suports
this type so only static handover is possible.
---
plugins/neard.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 196 insertions(+), 2 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 8319445..4627f52 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -322,6 +322,194 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
return 0;
}
+/*
+ * This is (barely documented) Nokia extension format, most work was done by
+ * reverse engineering.
+ *
+ * Binary format varies among different devices, type depends on first byte
+ * 0x00 - BT address not reversed, 16 bytes authentication data (all zeros)
+ * 0x01 - BT address not reversed, 16 bytes authentication data (4 digit PIN,
+ * padded with zeros)
+ * 0x02 - BT address not reversed, 16 bytes authentication data (not sure if
+ * 16 digit PIN or link key?, Nokia refers to it as ' Public Key')
+ * 0x10 - BT address reversed, no authentication data
+ * 0x24 - BT address not reversed, 4 bytes authentication data (4 digit PIN)
+ *
+ * General structure:
+ * 1 byte - marker
+ * 6 bytes - BT address (reversed or not, depends on marker)
+ * 3 bytes - Class of Device
+ * 0, 4 or 16 bytes - authentication data, interpretation depends on marker
+ * 1 bytes - name length
+ * N bytes - name
+ */
+
+struct nokia_com_bt {
+ bdaddr_t address;
+ uint32_t cod;
+ uint8_t pin[16];
+ int pin_len;
+ char *name;
+};
+
+static int process_nokia_long (void *data, size_t size, uint8_t marker,
+ struct nokia_com_bt *nokia)
+{
+ struct {
+ bdaddr_t address;
+ uint8_t class[3];
+ uint8_t authentication[16];
+ uint8_t name_len;
+ uint8_t name[0];
+ }__attribute__((packed)) *n = data;
+
+ if (size != sizeof(*n) + n->name_len)
+ return -EINVAL;
+
+ /* address is not reverted */
+ baswap(&nokia->address, &n->address);
+
+ nokia->cod = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
+
+ if (n->name_len > 0)
+ nokia->name = g_strndup((char *)n->name, n->name_len);
+
+ if (marker == 0x01) {
+ memcpy(nokia->pin, n->authentication, 4);
+ nokia->pin_len = 4;
+ } else if (marker == 0x02) {
+ memcpy(nokia->pin, n->authentication, 16);
+ nokia->pin_len = 16;
+ }
+
+ return 0;
+}
+
+static int process_nokia_short (void *data, size_t size,
+ struct nokia_com_bt *nokia)
+{
+ struct {
+ bdaddr_t address;
+ uint8_t class[3];
+ uint8_t authentication[4];
+ uint8_t name_len;
+ uint8_t name[0];
+ }__attribute__((packed)) *n = data;
+
+ if (size != sizeof(*n) + n->name_len)
+ return -EINVAL;
+
+ /* address is not reverted */
+ baswap(&nokia->address, &n->address);
+
+ nokia->cod = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
+
+ if (n->name_len > 0)
+ nokia->name = g_strndup((char *)n->name, n->name_len);
+
+ memcpy(nokia->pin, n->authentication, 4);
+ nokia->pin_len = 4;
+
+ return 0;
+}
+
+static int process_nokia_extra_short (void *data, size_t size,
+ struct nokia_com_bt *nokia)
+{
+ struct {
+ bdaddr_t address;
+ uint8_t class[3];
+ uint8_t name_len;
+ uint8_t name[0];
+ }__attribute__((packed)) *n = data;
+
+ if (size != sizeof(*n) + n->name_len)
+ return -EINVAL;
+
+ bacpy(&nokia->address, &n->address);
+
+ nokia->cod = n->class[0] | (n->class[1] << 8) | (n->class[2] << 16);
+
+ if (n->name_len > 0)
+ nokia->name = g_strndup((char *)n->name, n->name_len);
+
+ return 0;
+}
+
+/* returns 1 if pairing is not needed */
+static int process_nokia_com_bt(struct btd_adapter *adapter, void *data,
+ size_t size, bdaddr_t *remote)
+{
+ uint8_t *marker;
+ struct nokia_com_bt nokia;
+ int ret;
+ char remote_address[18];
+
+ /* Support this only for PushOOB */
+ if (!remote)
+ return -EOPNOTSUPP;
+
+ marker = data++;
+ size --;
+
+ DBG("marker: 0x%.2x size: %zu", *marker, size);
+
+ memset(&nokia, 0, sizeof(nokia));
+
+ switch (*marker) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ ret = process_nokia_long(data, size, *marker, &nokia);
+ break;
+ case 0x10:
+ ret = process_nokia_extra_short(data, size, &nokia);
+ break;
+ case 0x24:
+ ret = process_nokia_short(data, size, &nokia);
+ break;
+ default:
+ info("Not supported Nokia NFC extension (0x%.2x)", *marker);
+ ret = -EPROTONOSUPPORT;
+ break;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ ba2str(&nokia.address, remote_address);
+ DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
+
+ ret = check_device(adapter, remote_address);
+ if (ret != 0) {
+ g_free(nokia.name);
+ return ret;
+ }
+
+ DBG("hci%u remote:%s", adapter_get_dev_id(adapter), remote_address);
+
+ if (nokia.name) {
+ btd_event_remote_name(adapter_get_address(adapter), remote,
+ nokia.name);
+ g_free(nokia.name);
+ }
+
+ if (nokia.cod != 0)
+ write_remote_class(adapter_get_address(adapter), remote,
+ nokia.cod);
+
+ if (nokia.pin_len > 0) {
+ /* TODO
+ * Handle PIN, for now only discovery mode and 'common' PINs
+ * that might be provided by agent will work correctly.
+ */
+ }
+
+ bacpy(remote, &nokia.address);
+
+ return 0;
+}
+
static int process_params(DBusMessage *msg, struct btd_adapter *adapter,
bdaddr_t *remote)
{
@@ -371,8 +559,14 @@ static int process_params(DBusMessage *msg, struct btd_adapter *adapter,
return process_eir(adapter, eir, size, remote);
} else if (strcasecmp(key, "nokia.com:bt") == 0) {
- /* TODO add support for Nokia BT 2.0 proprietary stuff */
- return -ENOTSUP;
+ DBusMessageIter array;
+ uint8_t *data;
+ int size;
+
+ dbus_message_iter_recurse(&value, &array);
+ dbus_message_iter_get_fixed_array(&array, &data, &size);
+
+ return process_nokia_com_bt(adapter, data, size, remote);
}
return -EINVAL;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 4/4] neard: Append hash/randomizer in EIR only if remote provided it
2012-11-19 15:03 [PATCH 1/4] neard: Use ENONET error when adapter is not enabled Szymon Janc
2012-11-19 15:03 ` [PATCH 2/4] neard: Move device object checking into separate helper Szymon Janc
2012-11-19 15:03 ` [PATCH 3/4] neard: Add support for nokia.com:bt type Szymon Janc
@ 2012-11-19 15:03 ` Szymon Janc
2012-11-20 10:25 ` [PATCH 1/4] neard: Use ENONET error when adapter is not enabled Johan Hedberg
3 siblings, 0 replies; 5+ messages in thread
From: Szymon Janc @ 2012-11-19 15:03 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
Read local OOB data for RequestOOB reply only if remote also provided
hash and randomizer in EIR. This will allow for faster reply when only
discovery is done OOB. It is also required to pass NFC handover test
related to Bluetooth just-works pairing.
---
plugins/neard.c | 89 ++++++++++++++++++++++++++++++++++---------------------
1 file changed, 55 insertions(+), 34 deletions(-)
diff --git a/plugins/neard.c b/plugins/neard.c
index 4627f52..f8d023c 100644
--- a/plugins/neard.c
+++ b/plugins/neard.c
@@ -158,6 +158,46 @@ unregister:
AGENT_INTERFACE);
}
+static DBusMessage *create_request_oob_reply(struct btd_adapter *adapter,
+ uint8_t *hash,
+ uint8_t *randomizer,
+ DBusMessage *msg)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ uint8_t eir[NFC_OOB_EIR_MAX];
+ uint8_t *peir = eir;
+ int len;
+
+ len = eir_create_oob(adapter_get_address(adapter),
+ btd_adapter_get_name(adapter),
+ btd_adapter_get_class(adapter), hash,
+ randomizer, main_opts.did_vendor,
+ main_opts.did_product, main_opts.did_version,
+ main_opts.did_source,
+ btd_adapter_get_services(adapter), eir);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict);
+
+ dict_append_array(&dict, "EIR", DBUS_TYPE_BYTE, &peir, len);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
static void read_local_complete(struct btd_adapter *adapter, uint8_t *hash,
uint8_t *randomizer, void *user_data)
{
@@ -177,39 +217,10 @@ static void read_local_complete(struct btd_adapter *adapter, uint8_t *hash,
return;
}
- if (hash && randomizer) {
- int len;
- uint8_t eir[NFC_OOB_EIR_MAX];
- uint8_t *peir = eir;
- DBusMessageIter iter;
- DBusMessageIter dict;
-
- len = eir_create_oob(adapter_get_address(adapter),
- btd_adapter_get_name(adapter),
- btd_adapter_get_class(adapter), hash,
- randomizer, main_opts.did_vendor,
- main_opts.did_product, main_opts.did_version,
- main_opts.did_source,
- btd_adapter_get_services(adapter), eir);
-
- reply = dbus_message_new_method_return(msg);
-
- dbus_message_iter_init_append(reply, &iter);
-
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING
- DBUS_TYPE_VARIANT_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
- &dict);
-
- dict_append_array(&dict, "EIR", DBUS_TYPE_BYTE, &peir, len);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- } else {
+ if (hash && randomizer)
+ reply = create_request_oob_reply(adapter, hash, randomizer, msg);
+ else
reply = error_reply(msg, EIO);
- }
dbus_message_unref(msg);
@@ -273,7 +284,7 @@ static int check_device(struct btd_adapter *adapter, const char *address)
return 0;
}
-/* returns 1 if pairing is not needed */
+/* returns 1 if action (pairing or reading local data) is not needed */
static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
bdaddr_t *remote)
{
@@ -317,9 +328,16 @@ static int process_eir(struct btd_adapter *adapter, uint8_t *eir, size_t size,
if (remote)
bacpy(remote, &eir_data.addr);
+ /*
+ * In RequestOOB reply append local hash and randomizer only if
+ * received EIR also contained it.
+ */
+ if (!remote && !eir_data.hash)
+ ret = 1;
+
eir_data_free(&eir_data);
- return 0;
+ return ret;
}
/*
@@ -651,6 +669,9 @@ static DBusMessage *request_oob(DBusConnection *conn, DBusMessage *msg,
if (ret < 0)
return error_reply(msg, -ret);
+ if (ret == 1)
+ return create_request_oob_reply(adapter, NULL, NULL, msg);
+
ret = btd_adapter_read_local_oob_data(adapter);
if (ret < 0)
return error_reply(msg, -ret);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 1/4] neard: Use ENONET error when adapter is not enabled
2012-11-19 15:03 [PATCH 1/4] neard: Use ENONET error when adapter is not enabled Szymon Janc
` (2 preceding siblings ...)
2012-11-19 15:03 ` [PATCH 4/4] neard: Append hash/randomizer in EIR only if remote provided it Szymon Janc
@ 2012-11-20 10:25 ` Johan Hedberg
3 siblings, 0 replies; 5+ messages in thread
From: Johan Hedberg @ 2012-11-20 10:25 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
Hi Szymon,
On Mon, Nov 19, 2012, Szymon Janc wrote:
> This results in returning error 'Disabled' instead of 'No such Device'.
> Will allow neard to properly set power state of Bluetooth carrier.
> ---
> plugins/neard.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
All four patches have been applied after some minor coding style fixes
in patches 3 and 4. Thanks.
Johan
^ permalink raw reply [flat|nested] 5+ messages in thread