All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/8] Autopair
@ 2013-05-09  0:37 Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 1/8] core: Convert the pincode callback to an interable list Alex Deymo
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

Hi again!
Changes from the v4 are:
* uint32_t --> unsigned int for the "attempt" argument. I think that
restrict that value to unsigned given that -1 is never used for
attempt is a good practice.
* "pincb_iter" --> "btd_adapter_pin_cb_iter". The "pin_cb" instead
of "pincb" is to match the btd_adapter_pin_cb_t callback type
already used in the code.
* Added a bool pincode_requested member to btd_adapter (see patch 4/8)
to signal if the device requested a pincode during the bonding attempt.
This is basically to fix the case were we keep retrying the bonding
and the device keeps sending an authentication error without consuming
a pin code from the pincode callback list. This ensures that either a
pincode was consumed from the list before retrying. Together with the
fact that the pin codes provided by the callback list is a finite list,
this ensures the retry mechanism will finish.

Please consider this version for bluez. We are actively testing this
patchset in our last chromiumos release and I don't have any bug reported
regarding this feature. Thanks!
Alex.

Alex Deymo (8):
  core: Convert the pincode callback to an interable list.
  plugins: Extend the pin code callback with the call number
  core: Add support for retrying a bonding
  core: retry bonding attempt until the iterator reaches the end.
  core: Add device_get_class to the public interface.
  autopair: Add the autopair plugin.
  core: Expose the last bonding attempt timeout on retry
  autopair: Try a fixed pincode for keyboards rejecting random codes

 Makefile.plugins   |   3 +
 plugins/autopair.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++
 plugins/wiimote.c  |   7 ++-
 src/adapter.c      | 175 ++++++++++++++++++++++++++++++++++++++++++++++-------
 src/adapter.h      |  11 +++-
 src/device.c       | 135 +++++++++++++++++++++++++++++++++++++++++
 src/device.h       |   7 +++
 7 files changed, 478 insertions(+), 25 deletions(-)
 create mode 100644 plugins/autopair.c

-- 
1.8.2.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v5 1/8] core: Convert the pincode callback to an interable list.
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
@ 2013-05-09  0:37 ` Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 2/8] plugins: Extend the pin code callback with the call number Alex Deymo
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

The current pincode callback list on the adapter keeps track of all the
pincode callbacks registered by a plugin for that adapter and calls each
one until one provides a pincode for the current bonding. This mechanism
forgets about what happened with previous bonding attempts and pushes the
status track to the plugin side.

This patch creates an iterator struct (struct pincb_iter) that keeps track
of the last function called and the number of times called. This will
allow to provide more information about the bonding status to the pincode
callback.
---
 src/adapter.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
 src/adapter.h |  5 +++++
 src/device.c  | 14 ++++++++++++++
 src/device.h  |  1 +
 4 files changed, 70 insertions(+), 8 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 1252e74..b317d47 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -121,6 +121,12 @@ struct service_auth {
 	struct agent *agent;		/* NULL for queued auths */
 };
 
+struct btd_adapter_pin_cb_iter {
+	GSList *it;			/* current callback function */
+	unsigned int attempt;		/* numer of times it() was called */
+	/* When the iterator reaches the end, it is NULL and attempt is 0 */
+};
+
 struct btd_adapter {
 	int ref_count;
 
@@ -4755,22 +4761,50 @@ static void user_passkey_notify_callback(uint16_t index, uint16_t length,
 		error("device_notify_passkey: %s", strerror(-err));
 }
 
-static ssize_t adapter_get_pin(struct btd_adapter *adapter,
-					struct btd_device *dev, char *pin_buf,
+struct btd_adapter_pin_cb_iter *btd_adapter_pin_cb_iter_new(
+						struct btd_adapter *adapter)
+{
+	struct btd_adapter_pin_cb_iter *iter =
+				g_new0(struct btd_adapter_pin_cb_iter, 1);
+
+	iter->it = adapter->pin_callbacks;
+	iter->attempt = 1;
+
+	return iter;
+}
+
+void btd_adapter_pin_cb_iter_free(struct btd_adapter_pin_cb_iter *iter)
+{
+	g_free(iter);
+}
+
+bool btd_adapter_pin_cb_iter_end(struct btd_adapter_pin_cb_iter *iter)
+{
+	return iter->it == NULL && iter->attempt == 0;
+}
+
+static ssize_t btd_adapter_pin_cb_iter_next(
+					struct btd_adapter_pin_cb_iter *iter,
+					struct btd_adapter *adapter,
+					struct btd_device *device,
+					char *pin_buf,
 					gboolean *display)
 {
 	btd_adapter_pin_cb_t cb;
 	ssize_t ret;
-	GSList *l;
 
-	for (l = adapter->pin_callbacks; l != NULL; l = g_slist_next(l)) {
-		cb = l->data;
-		ret = cb(adapter, dev, pin_buf, display);
+	while (iter->it != NULL) {
+		cb = iter->it->data;
+		ret = cb(adapter, device, pin_buf, display);
+		iter->attempt++;
 		if (ret > 0)
 			return ret;
+		iter->attempt = 1;
+		iter->it = g_slist_next(iter->it);
 	}
+	iter->attempt = 0;
 
-	return -1;
+	return 0;
 }
 
 static void pin_code_request_callback(uint16_t index, uint16_t length,
@@ -4784,6 +4818,7 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
 	ssize_t pinlen;
 	char addr[18];
 	int err;
+	struct btd_adapter_pin_cb_iter *iter;
 
 	if (length < sizeof(*ev)) {
 		error("Too small PIN code request event");
@@ -4801,7 +4836,14 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
 	}
 
 	memset(pin, 0, sizeof(pin));
-	pinlen = adapter_get_pin(adapter, device, pin, &display);
+
+	iter = device_bonding_iter(device);
+	if (iter == NULL)
+		pinlen = 0;
+	else
+		pinlen = btd_adapter_pin_cb_iter_next(iter, adapter, device,
+								pin, &display);
+
 	if (pinlen > 0 && (!ev->secure || pinlen == 16)) {
 		if (display && device_is_bonding(device, NULL)) {
 			err = device_notify_pincode(device, ev->secure, pin);
diff --git a/src/adapter.h b/src/adapter.h
index 6b6515a..425a11f 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -138,6 +138,11 @@ void btd_adapter_register_pin_cb(struct btd_adapter *adapter,
 void btd_adapter_unregister_pin_cb(struct btd_adapter *adapter,
 						btd_adapter_pin_cb_t cb);
 
+struct btd_adapter_pin_cb_iter *btd_adapter_pin_cb_iter_new(
+						struct btd_adapter *adapter);
+void btd_adapter_pin_cb_iter_free(struct btd_adapter_pin_cb_iter *iter);
+bool btd_adapter_pin_cb_iter_end(struct btd_adapter_pin_cb_iter *iter);
+
 /* If TRUE, enables fast connectabe, i.e. reduces page scan interval and changes
  * type. If FALSE, disables fast connectable, i.e. sets page scan interval and
  * type to default values. Valid for both connectable and discoverable modes. */
diff --git a/src/device.c b/src/device.c
index ff4c553..005acb3 100644
--- a/src/device.c
+++ b/src/device.c
@@ -87,6 +87,7 @@ struct bonding_req {
 	guint listener_id;
 	struct btd_device *device;
 	struct agent *agent;
+	struct btd_adapter_pin_cb_iter *cb_iter;
 };
 
 typedef enum {
@@ -1488,6 +1489,8 @@ static struct bonding_req *bonding_request_new(DBusMessage *msg,
 
 	bonding->msg = dbus_message_ref(msg);
 
+	bonding->cb_iter = btd_adapter_pin_cb_iter_new(device->adapter);
+
 	if (agent)
 		bonding->agent = agent_ref(agent);
 
@@ -1613,6 +1616,9 @@ static void bonding_request_free(struct bonding_req *bonding)
 	if (bonding->msg)
 		dbus_message_unref(bonding->msg);
 
+	if (bonding->cb_iter)
+		g_free(bonding->cb_iter);
+
 	if (bonding->agent) {
 		agent_cancel(bonding->agent);
 		agent_unref(bonding->agent);
@@ -3819,6 +3825,14 @@ void device_bonding_failed(struct btd_device *device, uint8_t status)
 	bonding_request_free(bonding);
 }
 
+struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device)
+{
+	if (device->bonding == NULL)
+		return NULL;
+
+	return device->bonding->cb_iter;
+}
+
 static void pincode_cb(struct agent *agent, DBusError *err, const char *pin,
 								void *data)
 {
diff --git a/src/device.h b/src/device.h
index 7cd11af..0869e22 100644
--- a/src/device.h
+++ b/src/device.h
@@ -77,6 +77,7 @@ gboolean device_is_connected(struct btd_device *device);
 void device_bonding_complete(struct btd_device *device, uint8_t status);
 gboolean device_is_bonding(struct btd_device *device, const char *sender);
 void device_bonding_failed(struct btd_device *device, uint8_t status);
+struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device);
 int device_request_pincode(struct btd_device *device, gboolean secure);
 int device_request_passkey(struct btd_device *device);
 int device_confirm_passkey(struct btd_device *device, uint32_t passkey,
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 2/8] plugins: Extend the pin code callback with the call number
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 1/8] core: Convert the pincode callback to an interable list Alex Deymo
@ 2013-05-09  0:37 ` Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 3/8] core: Add support for retrying a bonding Alex Deymo
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

The plugin's pin code callback doesn't know about the pairing process. It
just provides a pin code based on the information provided to this function.
Although limited state could be added through other new callbacks, this fix
achieves this by providing more information to the callback itself. The
new argument "attempt" states the pin callback attempt of the particular
plugin for the current pairing of the device. This allows a plugin to try
different pincodes for the same device in the same pairing process.

To signal that the plugin doesn't provide any pin code for the provided device
the current implementation returns 0 (an empty pin code). Analogously, with
this fix, a plugin should return 0 when it doesn't have any other pin code to
provide for the given device.
---
 plugins/wiimote.c | 7 ++++++-
 src/adapter.c     | 2 +-
 src/adapter.h     | 3 ++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/plugins/wiimote.c b/plugins/wiimote.c
index 90d6d7b..12312b6 100644
--- a/plugins/wiimote.c
+++ b/plugins/wiimote.c
@@ -70,12 +70,17 @@ static const char *wii_names[] = {
 };
 
 static ssize_t wii_pincb(struct btd_adapter *adapter, struct btd_device *device,
-						char *pinbuf, gboolean *display)
+			char *pinbuf, gboolean *display, unsigned int attempt)
 {
 	uint16_t vendor, product;
 	char addr[18], name[25];
 	unsigned int i;
 
+	/* Only try the pin code once per device. If it's not correct then it's
+	 * an unknown device. */
+	if (attempt > 1)
+		return 0;
+
 	ba2str(device_get_address(device), addr);
 
 	vendor = btd_device_get_vendor(device);
diff --git a/src/adapter.c b/src/adapter.c
index b317d47..bf10268 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4795,7 +4795,7 @@ static ssize_t btd_adapter_pin_cb_iter_next(
 
 	while (iter->it != NULL) {
 		cb = iter->it->data;
-		ret = cb(adapter, device, pin_buf, display);
+		ret = cb(adapter, device, pin_buf, display, iter->attempt);
 		iter->attempt++;
 		if (ret > 0)
 			return ret;
diff --git a/src/adapter.h b/src/adapter.h
index 425a11f..09d80c2 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -132,7 +132,8 @@ int btd_cancel_authorization(guint id);
 int btd_adapter_restore_powered(struct btd_adapter *adapter);
 
 typedef ssize_t (*btd_adapter_pin_cb_t) (struct btd_adapter *adapter,
-			struct btd_device *dev, char *out, gboolean *display);
+			struct btd_device *dev, char *out, gboolean *display,
+							unsigned int attempt);
 void btd_adapter_register_pin_cb(struct btd_adapter *adapter,
 						btd_adapter_pin_cb_t cb);
 void btd_adapter_unregister_pin_cb(struct btd_adapter *adapter,
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 3/8] core: Add support for retrying a bonding
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 1/8] core: Convert the pincode callback to an interable list Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 2/8] plugins: Extend the pin code callback with the call number Alex Deymo
@ 2013-05-09  0:37 ` Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 4/8] core: retry bonding attempt until the iterator reaches the end Alex Deymo
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

In order to retry a bonding we need a timer that will perform the
retry, we need to stash the status of the bonding request so we
can use it again. In the case of a retrying bonding attempt we
need to not tear down the temporary D-Bus device object on the
adapter.
---
 src/adapter.c |  2 +-
 src/device.c  | 12 ++++++++++++
 src/device.h  |  1 +
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index bf10268..bcf54d5 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4239,7 +4239,7 @@ static void adapter_remove_connection(struct btd_adapter *adapter,
 	if (device_is_authenticating(device))
 		device_cancel_authentication(device, TRUE);
 
-	if (device_is_temporary(device)) {
+	if (device_is_temporary(device) && !device_is_retrying(device)) {
 		const char *path = device_get_path(device);
 
 		DBG("Removing temporary device %s", path);
diff --git a/src/device.c b/src/device.c
index 005acb3..012e150 100644
--- a/src/device.c
+++ b/src/device.c
@@ -88,6 +88,8 @@ struct bonding_req {
 	struct btd_device *device;
 	struct agent *agent;
 	struct btd_adapter_pin_cb_iter *cb_iter;
+	uint8_t status;
+	guint retry_timer;
 };
 
 typedef enum {
@@ -1625,6 +1627,9 @@ static void bonding_request_free(struct bonding_req *bonding)
 		bonding->agent = NULL;
 	}
 
+	if (bonding->retry_timer)
+		g_source_remove(bonding->retry_timer);
+
 	if (bonding->device)
 		bonding->device->bonding = NULL;
 
@@ -3673,6 +3678,13 @@ static void device_auth_req_free(struct btd_device *device)
 	device->authr = NULL;
 }
 
+bool device_is_retrying(struct btd_device *device)
+{
+	struct bonding_req *bonding = device->bonding;
+
+	return bonding && bonding->retry_timer > 0;
+}
+
 void device_bonding_complete(struct btd_device *device, uint8_t status)
 {
 	struct bonding_req *bonding = device->bonding;
diff --git a/src/device.h b/src/device.h
index 0869e22..b7d5c45 100644
--- a/src/device.h
+++ b/src/device.h
@@ -74,6 +74,7 @@ void device_set_bonded(struct btd_device *device, gboolean bonded);
 void device_set_legacy(struct btd_device *device, bool legacy);
 void device_set_rssi(struct btd_device *device, int8_t rssi);
 gboolean device_is_connected(struct btd_device *device);
+bool device_is_retrying(struct btd_device *device);
 void device_bonding_complete(struct btd_device *device, uint8_t status);
 gboolean device_is_bonding(struct btd_device *device, const char *sender);
 void device_bonding_failed(struct btd_device *device, uint8_t status);
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 4/8] core: retry bonding attempt until the iterator reaches the end.
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
                   ` (2 preceding siblings ...)
  2013-05-09  0:37 ` [PATCH v5 3/8] core: Add support for retrying a bonding Alex Deymo
@ 2013-05-09  0:37 ` Alex Deymo
  2013-05-09  0:37 ` [PATCH v5 5/8] core: Add device_get_class to the public interface Alex Deymo
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

This patch splits the bonding process in an interative process consisting
of one or more "bonding attempts". The user/agent starts a new "bonding"
that may involve several rounds of "bonding attempts" with the device
before it gets back to the user/agent.

Some functions were split in two parts to reflect this change. When a
bonding attempt fails with an authentication error and a pin code was
provided, a new bonding attempt is initiated (after a short delay)
to retry with the next function (or next call to the same function)
in the pincode callback list. If no pin code was provided to the device,
no retry is attempted and the authentication error is returned to the
client. This effectively allows a plugin try different pincodes for the
same device during the same bonding.
---
 src/adapter.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 src/adapter.h |  3 ++
 src/device.c  | 47 +++++++++++++++++++++++++++++
 src/device.h  |  2 ++
 4 files changed, 135 insertions(+), 13 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index bcf54d5..bca1515 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -165,6 +165,7 @@ struct btd_adapter {
 	guint pairable_timeout_id;	/* pairable timeout id */
 	guint auth_idle_id;		/* Pending authorization dequeue */
 	GQueue *auths;			/* Ongoing and pending auths */
+	bool pincode_requested;		/* PIN requested during last bonding */
 	GSList *connections;		/* Connected devices */
 	GSList *devices;		/* Devices structure pointers */
 	GSList *connect_list;		/* Devices to connect when found */
@@ -3894,6 +3895,7 @@ static struct btd_adapter *btd_adapter_new(uint16_t index)
 
 	adapter->dev_id = index;
 	adapter->mgmt = mgmt_ref(mgmt_master);
+	adapter->pincode_requested = FALSE;
 
 	/*
 	 * Setup default configuration values. These are either adapter
@@ -4835,6 +4837,9 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
 		return;
 	}
 
+	/* Flag the request of a pincode to allow a bonding retry. */
+	adapter->pincode_requested = TRUE;
+
 	memset(pin, 0, sizeof(pin));
 
 	iter = device_bonding_iter(device);
@@ -4923,6 +4928,42 @@ static void bonding_complete(struct btd_adapter *adapter,
 	check_oob_bonding_complete(adapter, bdaddr, status);
 }
 
+/* bonding_attempt_complete() handles the end of a "bonding attempt" checking if
+ * it should begin a new attempt or complete the bonding.
+ */
+static void bonding_attempt_complete(struct btd_adapter *adapter,
+					const bdaddr_t *bdaddr,
+					uint8_t addr_type, uint8_t status)
+{
+	struct btd_device *device;
+	char addr[18];
+
+	ba2str(bdaddr, addr);
+	DBG("hci%u bdaddr %s type %u status 0x%x", adapter->dev_id, addr,
+							addr_type, status);
+
+	if (status == 0)
+		device = adapter_get_device(adapter, bdaddr, addr_type);
+	else
+		device = adapter_find_device(adapter, bdaddr);
+
+	if (status == MGMT_STATUS_AUTH_FAILED && adapter->pincode_requested) {
+		/* On faliure, issue a bonding_retry if possible. */
+		if (device != NULL) {
+			if (device_bonding_attempt_retry(device) == 0)
+				return;
+		}
+	}
+
+	/* Ignore disconnects during retry. */
+	if (status == MGMT_STATUS_DISCONNECTED &&
+					device && device_is_retrying(device))
+		return;
+
+	/* In any other case, finish the bonding. */
+	bonding_complete(adapter, bdaddr, addr_type, status);
+}
+
 struct pair_device_data {
 	struct btd_adapter *adapter;
 	bdaddr_t bdaddr;
@@ -4976,7 +5017,7 @@ static void pair_device_complete(uint8_t status, uint16_t length,
 		error("Pair device failed: %s (0x%02x)",
 						mgmt_errstr(status), status);
 
-		bonding_complete(adapter, &data->bdaddr,
+		bonding_attempt_complete(adapter, &data->bdaddr,
 						data->addr_type, status);
 		return;
 	}
@@ -4986,17 +5027,13 @@ static void pair_device_complete(uint8_t status, uint16_t length,
 		return;
 	}
 
-	bonding_complete(adapter, &rp->addr.bdaddr, rp->addr.type, status);
+	bonding_attempt_complete(adapter, &rp->addr.bdaddr, rp->addr.type,
+									status);
 }
 
 int adapter_create_bonding(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
 					uint8_t addr_type, uint8_t io_cap)
 {
-	struct mgmt_cp_pair_device cp;
-	char addr[18];
-	struct pair_device_data *data;
-	unsigned int id;
-
 	if (adapter->pair_device_id > 0) {
 		error("Unable pair since another pairing is in progress");
 		return -EBUSY;
@@ -5004,10 +5041,25 @@ int adapter_create_bonding(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
 
 	suspend_discovery(adapter);
 
+	return adapter_bonding_attempt(adapter, bdaddr, addr_type, io_cap);
+}
+
+/* Starts a new bonding attempt in a fresh new bonding_req or a retried one. */
+int adapter_bonding_attempt(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
+					uint8_t addr_type, uint8_t io_cap)
+{
+	struct mgmt_cp_pair_device cp;
+	char addr[18];
+	struct pair_device_data *data;
+	unsigned int id;
+
 	ba2str(bdaddr, addr);
 	DBG("hci%u bdaddr %s type %d io_cap 0x%02x",
 				adapter->dev_id, addr, addr_type, io_cap);
 
+	/* Reset the pincode_requested flag for a new bonding attempt. */
+	adapter->pincode_requested = FALSE;
+
 	memset(&cp, 0, sizeof(cp));
 	bacpy(&cp.addr.bdaddr, bdaddr);
 	cp.addr.type = addr_type;
@@ -5056,7 +5108,7 @@ static void dev_disconnected(struct btd_adapter *adapter,
 	if (device)
 		adapter_remove_connection(adapter, device);
 
-	bonding_complete(adapter, &addr->bdaddr, addr->type,
+	bonding_attempt_complete(adapter, &addr->bdaddr, addr->type,
 						MGMT_STATUS_DISCONNECTED);
 }
 
@@ -5110,7 +5162,8 @@ static void auth_failed_callback(uint16_t index, uint16_t length,
 		return;
 	}
 
-	bonding_complete(adapter, &ev->addr.bdaddr, ev->addr.type, ev->status);
+	bonding_attempt_complete(adapter, &ev->addr.bdaddr, ev->addr.type,
+								ev->status);
 }
 
 static void store_link_key(struct btd_adapter *adapter,
@@ -5708,14 +5761,31 @@ static void connect_failed_callback(uint16_t index, uint16_t length,
 
 	device = adapter_find_device(adapter, &ev->addr.bdaddr);
 	if (device) {
+		/* If the device is in a bonding process cancel any auth request
+		 * sent to the agent before proceeding, but keep the bonding
+		 * request structure. */
 		if (device_is_bonding(device, NULL))
-			device_bonding_failed(device, ev->status);
-		if (device_is_temporary(device))
-			adapter_remove_device(adapter, device, TRUE);
+			device_cancel_authentication(device, FALSE);
 	}
 
 	/* In the case of security mode 3 devices */
-	bonding_complete(adapter, &ev->addr.bdaddr, ev->addr.type, ev->status);
+	bonding_attempt_complete(adapter, &ev->addr.bdaddr, ev->addr.type,
+								ev->status);
+
+	/* If the device is scheduled to retry the bonding wait until the retry
+	 * happens. In other case, proceed with cancel the bondig.
+	 */
+	if (device && device_is_bonding(device, NULL)
+					&& !device_is_retrying(device)) {
+		device_cancel_authentication(device, TRUE);
+		device_bonding_failed(device, ev->status);
+	}
+
+	/* In the case the bonding was canceled or did exists, remove the device
+	 * when it is temporary. */
+	if (device && !device_is_bonding(device, NULL)
+						&& device_is_temporary(device))
+		adapter_remove_device(adapter, device, TRUE);
 }
 
 static void unpaired_callback(uint16_t index, uint16_t length,
diff --git a/src/adapter.h b/src/adapter.h
index 09d80c2..2de8730 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -179,6 +179,9 @@ int btd_adapter_passkey_reply(struct btd_adapter *adapter,
 int adapter_create_bonding(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
 					uint8_t addr_type, uint8_t io_cap);
 
+int adapter_bonding_attempt(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
+					uint8_t addr_type, uint8_t io_cap);
+
 int adapter_cancel_bonding(struct btd_adapter *adapter, const bdaddr_t *bdaddr,
 							uint8_t addr_type);
 
diff --git a/src/device.c b/src/device.c
index 012e150..03325f7 100644
--- a/src/device.c
+++ b/src/device.c
@@ -3818,6 +3818,53 @@ gboolean device_is_bonding(struct btd_device *device, const char *sender)
 	return g_str_equal(sender, dbus_message_get_sender(bonding->msg));
 }
 
+static gboolean device_bonding_retry(gpointer data)
+{
+	struct btd_device *device = data;
+	struct btd_adapter *adapter = device_get_adapter(device);
+	struct bonding_req *bonding = device->bonding;
+	uint8_t io_cap;
+	int err;
+
+	if (!bonding)
+		return FALSE;
+
+	DBG("retrying bonding");
+	bonding->retry_timer = 0;
+
+	if (bonding->agent)
+		io_cap = agent_get_io_capability(bonding->agent);
+	else
+		io_cap = IO_CAPABILITY_NOINPUTNOOUTPUT;
+
+	err = adapter_bonding_attempt(adapter, &device->bdaddr,
+				device->bdaddr_type, io_cap);
+	if (err < 0)
+		device_bonding_complete(device, bonding->status);
+
+	return FALSE;
+}
+
+int device_bonding_attempt_retry(struct btd_device *device)
+{
+	struct bonding_req *bonding = device->bonding;
+
+	/* Ignore other failure events while retrying */
+	if (device_is_retrying(device))
+		return 0;
+
+	if (!bonding)
+		return -EINVAL;
+
+	if (btd_adapter_pin_cb_iter_end(bonding->cb_iter))
+		return -EINVAL;
+
+	DBG("scheduling retry");
+	bonding->retry_timer = g_timeout_add(3000,
+						device_bonding_retry, device);
+	return 0;
+}
+
 void device_bonding_failed(struct btd_device *device, uint8_t status)
 {
 	struct bonding_req *bonding = device->bonding;
diff --git a/src/device.h b/src/device.h
index b7d5c45..5aa0f81 100644
--- a/src/device.h
+++ b/src/device.h
@@ -77,8 +77,10 @@ gboolean device_is_connected(struct btd_device *device);
 bool device_is_retrying(struct btd_device *device);
 void device_bonding_complete(struct btd_device *device, uint8_t status);
 gboolean device_is_bonding(struct btd_device *device, const char *sender);
+void device_bonding_attempt_failed(struct btd_device *device, uint8_t status);
 void device_bonding_failed(struct btd_device *device, uint8_t status);
 struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device);
+int device_bonding_attempt_retry(struct btd_device *device);
 int device_request_pincode(struct btd_device *device, gboolean secure);
 int device_request_passkey(struct btd_device *device);
 int device_confirm_passkey(struct btd_device *device, uint32_t passkey,
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 5/8] core: Add device_get_class to the public interface.
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
                   ` (3 preceding siblings ...)
  2013-05-09  0:37 ` [PATCH v5 4/8] core: retry bonding attempt until the iterator reaches the end Alex Deymo
@ 2013-05-09  0:37 ` Alex Deymo
  2013-05-09  0:38 ` [PATCH v5 6/8] autopair: Add the autopair plugin Alex Deymo
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

Exports the device class to plugins.
---
 src/device.c | 5 +++++
 src/device.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/src/device.c b/src/device.c
index 03325f7..681d0c8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -2206,6 +2206,11 @@ void device_set_class(struct btd_device *device, uint32_t class)
 						DEVICE_INTERFACE, "Class");
 }
 
+uint32_t btd_device_get_class(struct btd_device *device)
+{
+	return device->class;
+}
+
 uint16_t btd_device_get_vendor(struct btd_device *device)
 {
 	return device->vendor;
diff --git a/src/device.h b/src/device.h
index 5aa0f81..07639c5 100644
--- a/src/device.h
+++ b/src/device.h
@@ -38,6 +38,7 @@ void device_store_cached_name(struct btd_device *dev, const char *name);
 void device_get_name(struct btd_device *device, char *name, size_t len);
 bool device_name_known(struct btd_device *device);
 void device_set_class(struct btd_device *device, uint32_t class);
+uint32_t btd_device_get_class(struct btd_device *device);
 uint16_t btd_device_get_vendor(struct btd_device *device);
 uint16_t btd_device_get_vendor_src(struct btd_device *device);
 uint16_t btd_device_get_product(struct btd_device *device);
-- 
1.8.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 6/8] autopair: Add the autopair plugin.
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
                   ` (4 preceding siblings ...)
  2013-05-09  0:37 ` [PATCH v5 5/8] core: Add device_get_class to the public interface Alex Deymo
@ 2013-05-09  0:38 ` Alex Deymo
  2013-05-09  0:38 ` [PATCH v5 7/8] core: Expose the last bonding attempt timeout on retry Alex Deymo
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

The autopair plugin tries standard pincodes for different devices with dumb
pincodes. It also generates a random 6 digit pincode for keyboards that
support any pincode but fallbacks to the agent call in case the random
generated pincode didn't work.
---
 Makefile.plugins   |   3 ++
 plugins/autopair.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 153 insertions(+)
 create mode 100644 plugins/autopair.c

diff --git a/Makefile.plugins b/Makefile.plugins
index 44e6eca..3efe849 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -5,6 +5,9 @@ builtin_sources += plugins/hostname.c
 builtin_modules += wiimote
 builtin_sources += plugins/wiimote.c
 
+builtin_modules += autopair
+builtin_sources += plugins/autopair.c
+
 if MAINTAINER_MODE
 builtin_modules += gatt_example
 builtin_sources += plugins/gatt-example.c
diff --git a/plugins/autopair.c b/plugins/autopair.c
new file mode 100644
index 0000000..4d5e787
--- /dev/null
+++ b/plugins/autopair.c
@@ -0,0 +1,150 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012 Google Inc.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <bluetooth/bluetooth.h>
+#include <glib.h>
+
+#include "plugin.h"
+#include "adapter.h"
+#include "device.h"
+#include "log.h"
+#include "storage.h"
+
+/*
+ * Plugin to handle automatic pairing of devices with reduced user
+ * interaction, including implementing the recommendation of the HID spec
+ * for keyboard devices.
+ *
+ * The plugin works by intercepting the PIN request for devices; if the
+ * device is a keyboard a random six-digit numeric PIN is generated and
+ * returned, flagged for displaying using DisplayPinCode.
+ *
+ */
+
+static ssize_t autopair_pincb(struct btd_adapter *adapter,
+					struct btd_device *device,
+					char *pinbuf, gboolean *display,
+					unsigned int attempt)
+{
+	char addr[18];
+	char pinstr[7];
+	uint32_t class;
+
+	ba2str(device_get_address(device), addr);
+
+	class = btd_device_get_class(device);
+
+	DBG("device %s 0x%x", addr, class);
+
+	/* This is a class-based pincode guesser. Ignore devices with an unknown
+	 * class. */
+	if (class == 0)
+		return 0;
+
+	switch ((class & 0x1f00) >> 8) {
+	case 0x04:		/* Audio/Video */
+		switch ((class & 0xfc) >> 2) {
+		case 0x01:		/* Wearable Headset Device */
+		case 0x02:		/* Hands-free Device */
+		case 0x06:		/* Headphones */
+		case 0x07:		/* Portable Audio */
+		case 0x0a:		/* HiFi Audio Device */
+			if (attempt > 1)
+				return 0;
+			memcpy(pinbuf, "0000", 4);
+			return 4;
+			break;
+		}
+		break;
+	case 0x05:		/* Peripheral */
+		switch ((class & 0xc0) >> 6) {
+		case 0x01:		/* Keyboard */
+		case 0x03:		/* Combo keyboard/pointing device */
+			if (attempt > 1)
+				return 0;
+			snprintf(pinstr, sizeof(pinstr), "%06d",
+						rand() % 1000000);
+			*display = TRUE;
+			memcpy(pinbuf, pinstr, 6);
+			return 6;
+			break;
+		case 0x02: /* Pointing device */
+			if (attempt > 1)
+				return 0;
+			memcpy(pinbuf, "0000", 4);
+			return 4;
+			break;
+		}
+		break;
+	}
+
+	return 0;
+}
+
+
+static int autopair_probe(struct btd_adapter *adapter)
+{
+	btd_adapter_register_pin_cb(adapter, autopair_pincb);
+
+	return 0;
+}
+
+static void autopair_remove(struct btd_adapter *adapter)
+{
+	btd_adapter_unregister_pin_cb(adapter, autopair_pincb);
+}
+
+static struct btd_adapter_driver autopair_driver = {
+	.name = "autopair",
+	.probe = autopair_probe,
+	.remove = autopair_remove,
+};
+
+static int autopair_init(void)
+{
+	/* Initialize the random seed from /dev/urandom */
+	unsigned int seed = time(NULL);
+	FILE *f = fopen("/dev/urandom", "rb");
+	if (f != NULL) {
+		fread(&seed, sizeof(seed), 1, f);
+		fclose(f);
+	}
+	srand(seed);
+
+	return btd_register_adapter_driver(&autopair_driver);
+}
+
+static void autopair_exit(void)
+{
+	btd_unregister_adapter_driver(&autopair_driver);
+}
+
+BLUETOOTH_PLUGIN_DEFINE(autopair, VERSION,
+		BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, autopair_init, autopair_exit)
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 7/8] core: Expose the last bonding attempt timeout on retry
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
                   ` (5 preceding siblings ...)
  2013-05-09  0:38 ` [PATCH v5 6/8] autopair: Add the autopair plugin Alex Deymo
@ 2013-05-09  0:38 ` Alex Deymo
  2013-05-09  0:38 ` [PATCH v5 8/8] autopair: Try a fixed pincode for keyboards rejecting random codes Alex Deymo
  2013-05-10  7:39 ` [PATCH v5 0/8] Autopair Johan Hedberg
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

One of the interesting values for pincode plugins is the timeout of a
bonding attempt. For keyboards supporting any random pincode as long as
it is also typed in the keyboard, the timeout until it fails is in the
order of the seconds to allow the user type the pincode on the bluetooth
keyboard. In the case of a dumb keyboard accepting only a fixed pincode
the timeout before the keyboard fails is in the order of a fraction of
a second.

This patch computes the elapsed time between the pairing started or the
pin code was sent to the device and the device returns with an error.
This measured duration is exposed in milliseconds to the plugins when
retrying the bonding attempt.
---
 src/adapter.c | 19 ++++++++++++++++++-
 src/device.c  | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/device.h  |  2 ++
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/src/adapter.c b/src/adapter.c
index bca1515..2a4084e 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -4558,10 +4558,22 @@ int btd_adapter_remove_bonding(struct btd_adapter *adapter,
 	return -EIO;
 }
 
+static void pincode_reply_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct btd_device *device = user_data;
+
+	/* If the MGMT_OP_PIN_CODE_REPLY command is acknowledged, move the
+	 * starting time to that point. This give a better sense of time
+	 * evaluating the pincode. */
+	device_bonding_restart_timer(device);
+}
+
 int btd_adapter_pincode_reply(struct btd_adapter *adapter,
 					const bdaddr_t *bdaddr,
 					const char *pin, size_t pin_len)
 {
+	struct btd_device *device;
 	unsigned int id;
 	char addr[18];
 
@@ -4590,9 +4602,14 @@ int btd_adapter_pincode_reply(struct btd_adapter *adapter,
 		cp.pin_len = pin_len;
 		memcpy(cp.pin_code, pin, pin_len);
 
+		/* Since a pincode was requested, update the starting time to
+		 * the point where the pincode is provided. */
+		device = adapter_find_device(adapter, bdaddr);
+		device_bonding_restart_timer(device);
+
 		id = mgmt_reply(adapter->mgmt, MGMT_OP_PIN_CODE_REPLY,
 					adapter->dev_id, sizeof(cp), &cp,
-					NULL, NULL, NULL);
+					pincode_reply_complete, device, NULL);
 	}
 
 	if (id == 0)
diff --git a/src/device.c b/src/device.c
index 681d0c8..e373908 100644
--- a/src/device.c
+++ b/src/device.c
@@ -35,6 +35,7 @@
 #include <sys/ioctl.h>
 #include <errno.h>
 #include <dirent.h>
+#include <time.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sdp.h>
@@ -90,6 +91,8 @@ struct bonding_req {
 	struct btd_adapter_pin_cb_iter *cb_iter;
 	uint8_t status;
 	guint retry_timer;
+	struct timespec attempt_start_time;
+	long last_attempt_duration_ms;
 };
 
 typedef enum {
@@ -1493,12 +1496,56 @@ static struct bonding_req *bonding_request_new(DBusMessage *msg,
 
 	bonding->cb_iter = btd_adapter_pin_cb_iter_new(device->adapter);
 
+	/* Marks the bonding start time for the first attempt on request
+	 * construction. The following attempts will be updated on
+	 * device_bonding_retry. */
+	clock_gettime(CLOCK_MONOTONIC, &bonding->attempt_start_time);
+
 	if (agent)
 		bonding->agent = agent_ref(agent);
 
 	return bonding;
 }
 
+void device_bonding_restart_timer(struct btd_device *device)
+{
+	if (!device || !device->bonding)
+		return;
+
+	clock_gettime(CLOCK_MONOTONIC, &device->bonding->attempt_start_time);
+}
+
+static void bonding_request_stop_timer(struct bonding_req *bonding)
+{
+	struct timespec current;
+
+	clock_gettime(CLOCK_MONOTONIC, &current);
+
+	/* Compute the time difference in ms. */
+	bonding->last_attempt_duration_ms =
+		(current.tv_sec - bonding->attempt_start_time.tv_sec) * 1000L +
+		(current.tv_nsec - bonding->attempt_start_time.tv_nsec)
+								/ 1000000L;
+}
+
+/* Returns the duration of the last bonding attempt in milliseconds. The
+ * duration is measured starting from the latest of the following three
+ * events and finishing when the Command complete event is received for the
+ * authentication request:
+ *  - MGMT_OP_PAIR_DEVICE is sent,
+ *  - MGMT_OP_PIN_CODE_REPLY is sent and
+ *  - Command complete event is received for the sent MGMT_OP_PIN_CODE_REPLY.
+ */
+long device_bonding_last_duration(struct btd_device *device)
+{
+	struct bonding_req *bonding = device->bonding;
+
+	if (!bonding)
+		return 0;
+
+	return bonding->last_attempt_duration_ms;
+}
+
 static void create_bond_req_exit(DBusConnection *conn, void *user_data)
 {
 	struct btd_device *device = user_data;
@@ -3837,6 +3884,12 @@ static gboolean device_bonding_retry(gpointer data)
 	DBG("retrying bonding");
 	bonding->retry_timer = 0;
 
+	/* Restart the bonding timer to the begining of the pairing. If not
+	 * pincode request/reply occurs during this retry,
+	 * device_bonding_last_duration() will return a consistent value from
+	 * this point. */
+	device_bonding_restart_timer(device);
+
 	if (bonding->agent)
 		io_cap = agent_get_io_capability(bonding->agent);
 	else
@@ -3861,6 +3914,10 @@ int device_bonding_attempt_retry(struct btd_device *device)
 	if (!bonding)
 		return -EINVAL;
 
+	/* Mark the end of a bonding attempt to compute the delta for the
+	 * retry. */
+	bonding_request_stop_timer(bonding);
+
 	if (btd_adapter_pin_cb_iter_end(bonding->cb_iter))
 		return -EINVAL;
 
diff --git a/src/device.h b/src/device.h
index 07639c5..2a82aa2 100644
--- a/src/device.h
+++ b/src/device.h
@@ -82,6 +82,8 @@ void device_bonding_attempt_failed(struct btd_device *device, uint8_t status);
 void device_bonding_failed(struct btd_device *device, uint8_t status);
 struct btd_adapter_pin_cb_iter *device_bonding_iter(struct btd_device *device);
 int device_bonding_attempt_retry(struct btd_device *device);
+long device_bonding_last_duration(struct btd_device *device);
+void device_bonding_restart_timer(struct btd_device *device);
 int device_request_pincode(struct btd_device *device, gboolean secure);
 int device_request_passkey(struct btd_device *device);
 int device_confirm_passkey(struct btd_device *device, uint32_t passkey,
-- 
1.8.2.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 8/8] autopair: Try a fixed pincode for keyboards rejecting random codes
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
                   ` (6 preceding siblings ...)
  2013-05-09  0:38 ` [PATCH v5 7/8] core: Expose the last bonding attempt timeout on retry Alex Deymo
@ 2013-05-09  0:38 ` Alex Deymo
  2013-05-10  7:39 ` [PATCH v5 0/8] Autopair Johan Hedberg
  8 siblings, 0 replies; 10+ messages in thread
From: Alex Deymo @ 2013-05-09  0:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: marcel, keybuk, Alex Deymo

This patch makes the autopair plugin try a fixed "0000" pincode for
keyboards that reject the pincode too fast (less than 500ms). This
too short delay rejecting the pincode means that the user didn't
have time to type the random pincode in the bluetooth keyboard and
was the keyboard who actually rejected it.
---
 plugins/autopair.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/plugins/autopair.c b/plugins/autopair.c
index 4d5e787..06cae8d 100644
--- a/plugins/autopair.c
+++ b/plugins/autopair.c
@@ -87,8 +87,23 @@ static ssize_t autopair_pincb(struct btd_adapter *adapter,
 		switch ((class & 0xc0) >> 6) {
 		case 0x01:		/* Keyboard */
 		case 0x03:		/* Combo keyboard/pointing device */
-			if (attempt > 1)
+			/* For keyboards rejecting the first random code in less
+			 * than 500ms, try a fixed code. */
+			if (attempt > 1 &&
+				device_bonding_last_duration(device) < 500) {
+				/* Don't try more than one dumb code */
+				if (attempt > 2)
+					return 0;
+				/* Try "0000" as the code for the second
+				 * attempt. */
+				memcpy(pinbuf, "0000", 4);
+				return 4;
+			}
+
+			/* Never try more than 3 random pincodes. */
+			if (attempt >= 4)
 				return 0;
+
 			snprintf(pinstr, sizeof(pinstr), "%06d",
 						rand() % 1000000);
 			*display = TRUE;
-- 
1.8.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 0/8] Autopair
  2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
                   ` (7 preceding siblings ...)
  2013-05-09  0:38 ` [PATCH v5 8/8] autopair: Try a fixed pincode for keyboards rejecting random codes Alex Deymo
@ 2013-05-10  7:39 ` Johan Hedberg
  8 siblings, 0 replies; 10+ messages in thread
From: Johan Hedberg @ 2013-05-10  7:39 UTC (permalink / raw)
  To: Alex Deymo; +Cc: linux-bluetooth, marcel, keybuk

Hi Alex,

On Wed, May 08, 2013, Alex Deymo wrote:
> Changes from the v4 are:
> * uint32_t --> unsigned int for the "attempt" argument. I think that
> restrict that value to unsigned given that -1 is never used for
> attempt is a good practice.
> * "pincb_iter" --> "btd_adapter_pin_cb_iter". The "pin_cb" instead
> of "pincb" is to match the btd_adapter_pin_cb_t callback type
> already used in the code.
> * Added a bool pincode_requested member to btd_adapter (see patch 4/8)
> to signal if the device requested a pincode during the bonding attempt.
> This is basically to fix the case were we keep retrying the bonding
> and the device keeps sending an authentication error without consuming
> a pin code from the pincode callback list. This ensures that either a
> pincode was consumed from the list before retrying. Together with the
> fact that the pin codes provided by the callback list is a finite list,
> this ensures the retry mechanism will finish.
> 
> Please consider this version for bluez. We are actively testing this
> patchset in our last chromiumos release and I don't have any bug reported
> regarding this feature. Thanks!
> Alex.
> 
> Alex Deymo (8):
>   core: Convert the pincode callback to an interable list.
>   plugins: Extend the pin code callback with the call number
>   core: Add support for retrying a bonding
>   core: retry bonding attempt until the iterator reaches the end.
>   core: Add device_get_class to the public interface.
>   autopair: Add the autopair plugin.
>   core: Expose the last bonding attempt timeout on retry
>   autopair: Try a fixed pincode for keyboards rejecting random codes
> 
>  Makefile.plugins   |   3 +
>  plugins/autopair.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  plugins/wiimote.c  |   7 ++-
>  src/adapter.c      | 175 ++++++++++++++++++++++++++++++++++++++++++++++-------
>  src/adapter.h      |  11 +++-
>  src/device.c       | 135 +++++++++++++++++++++++++++++++++++++++++
>  src/device.h       |   7 +++
>  7 files changed, 478 insertions(+), 25 deletions(-)
>  create mode 100644 plugins/autopair.c

All patches in this set have been applied. Thanks!

I did fix one thing in patch 4: for type bool the expected assignments
are true/false and not TRUE/FALSE (which are GLib defines). I also
pushed one small coding style/readability patch on top of this set.

Johan

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-05-10  7:39 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-09  0:37 [PATCH v5 0/8] Autopair Alex Deymo
2013-05-09  0:37 ` [PATCH v5 1/8] core: Convert the pincode callback to an interable list Alex Deymo
2013-05-09  0:37 ` [PATCH v5 2/8] plugins: Extend the pin code callback with the call number Alex Deymo
2013-05-09  0:37 ` [PATCH v5 3/8] core: Add support for retrying a bonding Alex Deymo
2013-05-09  0:37 ` [PATCH v5 4/8] core: retry bonding attempt until the iterator reaches the end Alex Deymo
2013-05-09  0:37 ` [PATCH v5 5/8] core: Add device_get_class to the public interface Alex Deymo
2013-05-09  0:38 ` [PATCH v5 6/8] autopair: Add the autopair plugin Alex Deymo
2013-05-09  0:38 ` [PATCH v5 7/8] core: Expose the last bonding attempt timeout on retry Alex Deymo
2013-05-09  0:38 ` [PATCH v5 8/8] autopair: Try a fixed pincode for keyboards rejecting random codes Alex Deymo
2013-05-10  7:39 ` [PATCH v5 0/8] Autopair Johan Hedberg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.