static void confirm_agent_reply(DBusPendingCall *call, void *user_data) { struct pending_agent_request *req = user_data; struct passkey_agent *agent = req->agent; pin_code_reply_cp pr; DBusMessage *message; DBusError err; int len; /* steal_reply will always return non-NULL since the callback * is only called after a reply has been received */ message = dbus_pending_call_steal_reply(call); dbus_error_init(&err); if (dbus_set_error_from_message(&err, message)) { error("Passkey agent replied with an error: %s, %s", err.name, err.message); dbus_error_free(&err); goto fail; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_INVALID)) { error("Wrong confirm reply signature: %s", err.message); dbus_error_free(&err); goto fail; } len = strlen(req->pin); set_pin_length(&req->sba, len); memset(&pr, 0, sizeof(pr)); bacpy(&pr.bdaddr, &req->bda); memcpy(pr.pin_code, req->pin, len); pr.pin_len = len; hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); goto done; fail: hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &req->bda); done: if (message) dbus_message_unref(message); agent->pending_requests = g_slist_remove(agent->pending_requests, req); dbus_pending_call_cancel(req->call); if (req->call) dbus_pending_call_unref(req->call); g_free(req->pin); g_free(req->path); g_free(req); if (agent != default_agent) { agent->adapter->passkey_agents = g_slist_remove(agent->adapter->passkey_agents, agent); passkey_agent_free(agent); } }
static void passkey_agent_reply(DBusPendingCall *call, void *user_data) { struct pending_agent_request *req = user_data; struct passkey_agent *agent = req->agent; pin_code_reply_cp pr; DBusMessage *message; DBusError err; size_t len; char *pin; /* steal_reply will always return non-NULL since the callback * is only called after a reply has been received */ message = dbus_pending_call_steal_reply(call); dbus_error_init(&err); if (dbus_set_error_from_message(&err, message)) { if (!req->old_if && !strcmp(err.name, DBUS_ERROR_UNKNOWN_METHOD)) { debug("New Request API failed, trying old one"); req->old_if = 1; dbus_error_free(&err); dbus_pending_call_unref(req->call); req->call = agent_request(req->path, &req->bda, agent, FALSE, 1); if (!req->call) goto fail; dbus_message_unref(message); dbus_pending_call_set_notify(req->call, passkey_agent_reply, req, NULL); return; } error("Passkey agent replied with an error: %s, %s", err.name, err.message); dbus_error_free(&err); goto fail; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID)) { error("Wrong passkey reply signature: %s", err.message); dbus_error_free(&err); goto fail; } len = strlen(pin); if (len > 16 || len < 1) { error("Invalid passkey length from handler"); goto fail; } set_pin_length(&req->sba, len); memset(&pr, 0, sizeof(pr)); bacpy(&pr.bdaddr, &req->bda); memcpy(pr.pin_code, pin, len); pr.pin_len = len; hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY, PIN_CODE_REPLY_CP_SIZE, &pr); goto done; fail: hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &req->bda); done: if (message) dbus_message_unref(message); agent->pending_requests = g_slist_remove(agent->pending_requests, req); dbus_pending_call_cancel(req->call); if (req->call) dbus_pending_call_unref(req->call); g_free(req->path); g_free(req); if (agent != default_agent) { agent->adapter->passkey_agents = g_slist_remove(agent->adapter->passkey_agents, agent); passkey_agent_free(agent); } }
static void pincode_reply(DBusPendingCall *call, void *user_data) { struct agent_request *req = user_data; struct agent *agent = req->agent; struct btd_adapter *adapter = agent->adapter; agent_pincode_cb cb = req->cb; DBusMessage *message; DBusError err; bdaddr_t sba; size_t len; char *pin; adapter_get_address(adapter, &sba); /* steal_reply will always return non-NULL since the callback * is only called after a reply has been received */ message = dbus_pending_call_steal_reply(call); dbus_error_init(&err); if (dbus_set_error_from_message(&err, message)) { if ((g_str_equal(DBUS_ERROR_UNKNOWN_METHOD, err.name) || g_str_equal(DBUS_ERROR_NO_REPLY, err.name)) && request_fallback(req, pincode_reply) == 0) { dbus_error_free(&err); return; } error("Agent replied with an error: %s, %s", err.name, err.message); cb(agent, &err, NULL, req->user_data); dbus_error_free(&err); goto done; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID)) { error("Wrong passkey reply signature: %s", err.message); cb(agent, &err, NULL, req->user_data); dbus_error_free(&err); goto done; } len = strlen(pin); dbus_error_init(&err); if (len > 16 || len < 1) { error("Invalid passkey length from handler"); dbus_set_error_const(&err, "org.bluez.Error.InvalidArgs", "Invalid passkey length"); cb(agent, &err, NULL, req->user_data); dbus_error_free(&err); goto done; } set_pin_length(&sba, len); cb(agent, NULL, pin, req->user_data); done: if (message) dbus_message_unref(message); dbus_pending_call_cancel(req->call); agent->request = NULL; agent_request_free(req, TRUE); }