📄 dbus-hci.c
字号:
if (dev_id < 0) return dev_id; dd = hci_open_dev(dev_id); if (dd < 0) return dd; memset(&req, 0, sizeof(req)); bacpy(&req.bdaddr, remote); err = ioctl(dd, HCIGETAUTHINFO, (unsigned long) &req); if (err < 0) { debug("HCIGETAUTHINFO failed: %s (%d)", strerror(errno), errno); hci_close_dev(dd); return err; } hci_close_dev(dd); if (auth) *auth = req.type; return 0;}int hcid_dbus_user_confirm(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey){ struct adapter *adapter; struct btd_device *device; struct agent *agent; char addr[18]; uint8_t type; struct pending_auth_info *auth; uint16_t dev_id; adapter = manager_find_adapter(sba); if (!adapter) { error("No matching adapter found"); return -1; } dev_id = adapter_get_dev_id(adapter); if (get_auth_requirements(sba, dba, &type) < 0) { int dd; dd = hci_open_dev(dev_id); if (dd < 0) { error("Unable to open hci%d", dev_id); return -1; } hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY, 6, dba); hci_close_dev(dd); return 0; } ba2str(dba, addr); device = adapter_get_device(connection, adapter, addr); if (!device) { error("Device creation failed"); return -1; } /* If no MITM protection required, auto-accept */ if (!(device_get_auth(device) & 0x01) && !(type & 0x01)) { int dd; dd = hci_open_dev(dev_id); if (dd < 0) { error("Unable to open hci%d", dev_id); return -1; } hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_REPLY, 6, dba); hci_close_dev(dd); return 0; } agent = device_get_agent(device); if (!agent) agent = adapter->agent; if (!agent) { error("No agent available for user confirm request"); return -1; } if (agent_request_confirmation(agent, device, passkey, confirm_cb, device) < 0) { error("Requesting passkey failed"); return -1; } auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_CONFIRM); auth->agent = agent; return 0;}int hcid_dbus_user_passkey(bdaddr_t *sba, bdaddr_t *dba){ struct adapter *adapter; struct btd_device *device; struct agent *agent = NULL; char addr[18]; struct pending_auth_info *auth; adapter = manager_find_adapter(sba); if (!adapter) { error("No matching adapter found"); return -1; } ba2str(dba, addr); device = adapter_get_device(connection, adapter, addr); if (device) agent = device_get_agent(device); if (!agent) agent = adapter->agent; if (!agent) { error("No agent available for user confirm request"); return -1; } if (agent_request_passkey(agent, device, passkey_cb, device) < 0) { error("Requesting passkey failed"); return -1; } auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_PASSKEY); auth->agent = agent; return 0;}int hcid_dbus_user_notify(bdaddr_t *sba, bdaddr_t *dba, uint32_t passkey){ struct adapter *adapter; struct btd_device *device; struct agent *agent = NULL; char addr[18]; struct pending_auth_info *auth; adapter = manager_find_adapter(sba); if (!adapter) { error("No matching adapter found"); return -1; } ba2str(dba, addr); device = adapter_get_device(connection, adapter, addr); if (device) agent = device_get_agent(device); if (!agent) agent = adapter->agent; if (!agent) { error("No agent available for user confirm request"); return -1; } if (agent_display_passkey(agent, device, passkey) < 0) { error("Displaying passkey failed"); return -1; } auth = adapter_new_auth_request(adapter, dba, AUTH_TYPE_NOTIFY); auth->agent = agent; return 0;}void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t status){ struct adapter *adapter; char peer_addr[18]; const char *paddr = peer_addr; DBusMessage *reply; struct btd_device *device; struct bonding_request_info *bonding; gboolean paired = TRUE; struct pending_auth_info *auth; const gchar *dev_path; const gchar *path; debug("hcid_dbus_bonding_process_complete: status=%02x", status); ba2str(peer, peer_addr); adapter = manager_find_adapter(local); if (!adapter) { error("Unable to find matching adapter"); return; } if (status) { if (adapter->bonding) adapter->bonding->hci_status = status; } auth = adapter_find_auth_request(adapter, peer); if (!auth) { debug("hcid_dbus_bonding_process_complete: no pending auth request"); goto proceed; } if (auth->agent) agent_cancel(auth->agent); adapter_remove_auth_request(adapter, peer); if (status) goto proceed; device = adapter_get_device(connection, adapter, paddr); if (device) { debug("hcid_dbus_bonding_process_complete: removing temporary flag"); device_set_temporary(device, FALSE); dev_path = device_get_path(device); path = adapter_get_path(adapter); g_dbus_emit_signal(connection, path, ADAPTER_INTERFACE, "DeviceCreated", DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_INVALID); dbus_connection_emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Paired", DBUS_TYPE_BOOLEAN, &paired); }proceed: bonding = adapter->bonding; if (!bonding || bacmp(&bonding->bdaddr, peer)) return; /* skip: no bonding req pending */ if (bonding->cancel) { /* reply authentication canceled */ reply = new_authentication_return(bonding->msg, HCI_OE_USER_ENDED_CONNECTION); g_dbus_send_message(connection, reply); goto cleanup; } /* reply authentication success or an error */ if (dbus_message_is_method_call(bonding->msg, ADAPTER_INTERFACE, "CreateBonding")) { reply = new_authentication_return(bonding->msg, status); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); } else if ((device = adapter_find_device(adapter, paddr))) { if (status) { reply = new_authentication_return(bonding->msg, status); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); } else { device_set_temporary(device, FALSE); device_browse(device, bonding->conn, bonding->msg, NULL); } }cleanup: g_dbus_remove_watch(connection, adapter->bonding->listener_id); if (adapter->bonding->io_id) g_source_remove(adapter->bonding->io_id); g_io_channel_close(adapter->bonding->io); bonding_request_free(adapter->bonding); adapter->bonding = NULL;}void hcid_dbus_inquiry_start(bdaddr_t *local){ struct adapter *adapter; const gchar *path; adapter = manager_find_adapter(local); if (!adapter) { error("Unable to find matching adapter"); return; } adapter->discov_active = 1; /* * Cancel pending remote name request and clean the device list * when inquiry is supported in periodic inquiry idle state. */ if (adapter->pdiscov_active) pending_remote_name_cancel(adapter); /* Disable name resolution for non D-Bus clients */ if (!adapter->discov_requestor) adapter->discov_type &= ~RESOLVE_NAME; path = adapter_get_path(adapter); dbus_connection_emit_property_changed(connection, path, ADAPTER_INTERFACE, "PeriodicDiscovery", DBUS_TYPE_BOOLEAN, &adapter->discov_active); g_dbus_emit_signal(connection, path, ADAPTER_INTERFACE, "DiscoveryStarted", DBUS_TYPE_INVALID);}int found_device_req_name(struct adapter *adapter){ struct hci_request rq; evt_cmd_status rp; remote_name_req_cp cp; struct remote_dev_info match; GSList *l; int dd, req_sent = 0; uint16_t dev_id = adapter_get_dev_id(adapter); /* get the next remote address */ if (!adapter->found_devices) return -ENODATA; memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, BDADDR_ANY); match.name_status = NAME_REQUIRED; l = g_slist_find_custom(adapter->found_devices, &match, (GCompareFunc) found_device_cmp); if (!l) return -ENODATA; dd = hci_open_dev(dev_id); if (dd < 0) return -errno; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_REMOTE_NAME_REQ; rq.cparam = &cp; rq.clen = REMOTE_NAME_REQ_CP_SIZE; rq.rparam = &rp; rq.rlen = EVT_CMD_STATUS_SIZE; rq.event = EVT_CMD_STATUS; /* send at least one request or return failed if the list is empty */ do { struct remote_dev_info *dev = l->data; /* flag to indicate the current remote name requested */ dev->name_status = NAME_REQUESTED; memset(&rp, 0, sizeof(rp)); memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &dev->bdaddr); cp.pscan_rep_mode = 0x02; if (hci_send_req(dd, &rq, 500) < 0) error("Unable to send the HCI remote name request: %s (%d)", strerror(errno), errno); if (!rp.status) { req_sent = 1; break; } error("Remote name request failed with status 0x%02x", rp.status); /* if failed, request the next element */ /* remove the element from the list */ adapter->found_devices = g_slist_remove(adapter->found_devices, dev); g_free(dev); /* get the next element */ l = g_slist_find_custom(adapter->found_devices, &match, (GCompareFunc) found_device_cmp); } while (l); hci_close_dev(dd); if (!req_sent) return -ENODATA; return 0;}static void send_out_of_range(const char *path, GSList *l){ while (l) { const char *peer_addr = l->data; g_dbus_emit_signal(connection, path, ADAPTER_INTERFACE, "DeviceDisappeared", DBUS_TYPE_STRING, &peer_addr, DBUS_TYPE_INVALID); l = l->next; }}void hcid_dbus_inquiry_complete(bdaddr_t *local){ struct adapter *adapter; struct remote_dev_info *dev; bdaddr_t tmp; const gchar *path; adapter = manager_find_adapter(local); if (!adapter) { error("Unable to find matching adapter"); return; } path = adapter_get_path(adapter); /* Out of range verification */ if (adapter->pdiscov_active && !adapter->discov_active) { GSList *l; send_out_of_range(path, adapter->oor_devices); g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL); g_slist_free(adapter->oor_devices); adapter->oor_devices = NULL; l = adapter->found_devices; while (l) { dev = l->data; baswap(&tmp, &dev->bdaddr); adapter->oor_devices = g_slist_append(adapter->oor_devices, batostr(&tmp)); l = l->next; } } adapter->pinq_idle = 1; /* * Enable resolution again: standard inquiry can be * received in the periodic inquiry idle state. */ if (adapter->pdiscov_requestor && adapter->pdiscov_resolve_names) adapter->discov_type |= RESOLVE_NAME; /* * The following scenarios can happen: * 1. standard inquiry: always send discovery completed signal * 2. standard inquiry + name resolving: send discovery completed * after name resolving * 3. periodic inquiry: skip discovery completed signal * 4. periodic inquiry + standard inquiry: always send discovery * completed signal * * Keep in mind that non D-Bus requests can arrive. */ if (!found_device_req_name(adapter)) return; /* skip - there is name to resolve */ if (adapter->discov_active) { g_dbus_emit_signal(connection, path, ADAPTER_INTERFACE, "DiscoveryCompleted", DBUS_TYPE_INVALID); adapter->discov_active = 0; } /* free discovered devices list */ g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; if (adapter->discov_requestor) { g_dbus_remove_watch(connection, adapter->discov_listener); adapter->discov_listener = 0; g_free(adapter->discov_requestor); adapter->discov_requestor = NULL; /* If there is a pending reply for discovery cancel */ if (adapter->discovery_cancel) { DBusMessage *reply; reply = dbus_message_new_method_return(adapter->discovery_cancel); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); dbus_message_unref(adapter->discovery_cancel); adapter->discovery_cancel = NULL; } /* reset the discover type for standard inquiry only */ adapter->discov_type &= ~STD_INQUIRY; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -