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;
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,
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");
}
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);
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. */
guint listener_id;
struct btd_device *device;
struct agent *agent;
+ struct btd_adapter_pin_cb_iter *cb_iter;
};
typedef enum {
bonding->msg = dbus_message_ref(msg);
+ bonding->cb_iter = btd_adapter_pin_cb_iter_new(device->adapter);
+
if (agent)
bonding->agent = agent_ref(agent);
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);
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)
{
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,