Diff between 940428c4145591c54744bea3f42856a6deb11e52 and 8a7c267e36a83245999dc374b627a889acd694f0

Changed Files

File Additions Deletions Status
src/adapter.c +50 -8 modified
src/adapter.h +5 -0 modified
src/device.c +14 -0 modified
src/device.h +1 -0 modified

Full Patch

diff --git a/src/adapter.c b/src/adapter.c
index b952ea1..d6c865c 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;
 
@@ -4759,22 +4765,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,
@@ -4788,6 +4822,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");
@@ -4805,7 +4840,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 14c3e81..26df0d8 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 70e1502..f6ca79b 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,