📄 dbus-hci.c
字号:
struct btd_device *device; struct bonding_request_info *bonding; struct pending_auth_info *auth; 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; } bonding = adapter_get_bonding_info(adapter); if (bonding && bacmp(&bonding->bdaddr, peer)) bonding = NULL; if (status == 0) { device = adapter_get_device(connection, adapter, peer_addr); if (!device) { /* This should really only happen if we run out of * memory */ error("Unable to get device object!"); status = HCI_REJECTED_LIMITED_RESOURCES; } } if (status && bonding) bonding->hci_status = status; auth = adapter_find_auth_request(adapter, peer); if (!auth) { /* This means that there was no pending PIN or SSP token request * from the controller, i.e. this is not a new pairing */ 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 this is a new pairing send the appropriate signal for it * and proceed with service discovery */ if (status == 0) { device_set_paired(connection, device, bonding); if (bonding) adapter_free_bonding_request(adapter); return; }proceed: if (!bonding) return; /* skip: no bonding req pending */ if (bonding->cancel) reply = new_authentication_return(bonding->msg, HCI_OE_USER_ENDED_CONNECTION); else reply = new_authentication_return(bonding->msg, status); g_dbus_send_message(connection, reply); adapter_free_bonding_request(adapter);}void hcid_dbus_inquiry_start(bdaddr_t *local){ struct btd_adapter *adapter; int state; adapter = manager_find_adapter(local); if (!adapter) { error("Unable to find matching adapter"); return; } state = adapter_get_state(adapter); state |= STD_INQUIRY; adapter_set_state(adapter, state); /* * Cancel pending remote name request and clean the device list * when inquiry is supported in periodic inquiry idle state. */ if (adapter_get_state(adapter) & PERIODIC_INQUIRY) pending_remote_name_cancel(adapter); /* Disable name resolution for non D-Bus clients */ if (!adapter_has_discov_sessions(adapter)) { state = adapter_get_state(adapter); state &= ~RESOLVE_NAME; adapter_set_state(adapter, state); }}static int found_device_req_name(struct btd_adapter *adapter){ struct hci_request rq; evt_cmd_status rp; remote_name_req_cp cp; struct remote_dev_info *dev, match; int dd, req_sent = 0; uint16_t dev_id = adapter_get_dev_id(adapter); memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, BDADDR_ANY); match.name_status = NAME_REQUIRED; dev = adapter_search_found_devices(adapter, &match); if (!dev) 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 { /* 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, HCI_REQ_TIMEOUT) < 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_remove_found_device(adapter, &dev->bdaddr); /* get the next element */ dev = adapter_search_found_devices(adapter, &match); } while (dev); hci_close_dev(dd); if (!req_sent) return -ENODATA; return 0;}void hcid_dbus_inquiry_complete(bdaddr_t *local){ struct btd_adapter *adapter; const gchar *path; int state; 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_get_state(adapter) & PERIODIC_INQUIRY) && !(adapter_get_state(adapter) & STD_INQUIRY)) adapter_update_oor_devices(adapter); /* * 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) == 0) return; /* reset the discover type to be able to handle D-Bus and non D-Bus * requests */ state = adapter_get_state(adapter); state &= ~STD_INQUIRY; state &= ~PERIODIC_INQUIRY; adapter_set_state(adapter, state);}void hcid_dbus_periodic_inquiry_start(bdaddr_t *local, uint8_t status){ struct btd_adapter *adapter; int state; /* Don't send the signal if the cmd failed */ if (status) return; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } state = adapter_get_state(adapter); state |= PERIODIC_INQUIRY; adapter_set_state(adapter, state);}void hcid_dbus_periodic_inquiry_exit(bdaddr_t *local, uint8_t status){ struct btd_adapter *adapter; int state; /* Don't send the signal if the cmd failed */ if (status) return; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } /* reset the discover type to be able to handle D-Bus and non D-Bus * requests */ state = adapter_get_state(adapter); state &= ~PERIODIC_INQUIRY; adapter_set_state(adapter, state);}static char *extract_eir_name(uint8_t *data, uint8_t *type){ if (!data || !type) return NULL; if (data[0] == 0) return NULL; *type = data[1]; switch (*type) { case 0x08: case 0x09: return strndup((char *) (data + 2), data[0] - 1); } return NULL;}static void append_dict_valist(DBusMessageIter *iter, const char *first_key, va_list var_args){ DBusMessageIter dict; const char *key; int type; void *val; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); key = first_key; while (key) { type = va_arg(var_args, int); val = va_arg(var_args, void *); dict_append_entry(&dict, key, type, val); key = va_arg(var_args, char *); } dbus_message_iter_close_container(iter, &dict);}static void emit_device_found(const char *path, const char *address, const char *first_key, ...){ DBusMessage *signal; DBusMessageIter iter; va_list var_args; signal = dbus_message_new_signal(path, ADAPTER_INTERFACE, "DeviceFound"); if (!signal) { error("Unable to allocate new %s.DeviceFound signal", ADAPTER_INTERFACE); return; } dbus_message_iter_init_append(signal, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &address); va_start(var_args, first_key); append_dict_valist(&iter, first_key, var_args); va_end(var_args); g_dbus_send_message(connection, signal);}void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, int8_t rssi, uint8_t *data){ char filename[PATH_MAX + 1]; struct btd_adapter *adapter; char local_addr[18], peer_addr[18], *alias, *name, *tmp_name; const char *real_alias; const char *path, *icon, *paddr = peer_addr; struct remote_dev_info *dev, match; dbus_int16_t tmp_rssi = rssi; uint8_t name_type = 0x00; name_status_t name_status; int state; ba2str(local, local_addr); ba2str(peer, peer_addr); adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } write_remote_class(local, peer, class); if (data) write_remote_eir(local, peer, data); /* * workaround to identify situation when the daemon started and * a standard inquiry or periodic inquiry was already running */ if (!(adapter_get_state(adapter) & STD_INQUIRY) && !(adapter_get_state(adapter) & PERIODIC_INQUIRY)) { state = adapter_get_state(adapter); state |= PERIODIC_INQUIRY; adapter_set_state(adapter, state); } /* Out of range list update */ if (adapter_get_state(adapter) & PERIODIC_INQUIRY) adapter_remove_oor_device(adapter, peer_addr); memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, peer); match.name_status = NAME_SENT; /* if found: don't send the name again */ dev = adapter_search_found_devices(adapter, &match); if (dev) return; /* the inquiry result can be triggered by NON D-Bus client */ if (adapter_get_state(adapter) & RESOLVE_NAME) name_status = NAME_REQUIRED; else name_status = NAME_NOT_REQUIRED; create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "aliases"); alias = textfile_get(filename, peer_addr); create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names"); name = textfile_get(filename, peer_addr); if (!alias) { real_alias = NULL; if (!name) { alias = g_strdup(peer_addr); g_strdelimit(alias, ":", '-'); } else alias = g_strdup(name); } else real_alias = alias; tmp_name = extract_eir_name(data, &name_type); if (tmp_name) { if (name_type == 0x09) { write_device_name(local, peer, tmp_name); name_status = NAME_NOT_REQUIRED; if (name) g_free(name); name = tmp_name; } else { if (name) free(tmp_name); else name = tmp_name; } } path = adapter_get_path(adapter); icon = class_to_icon(class); emit_device_found(path, paddr, "Address", DBUS_TYPE_STRING, &paddr, "Class", DBUS_TYPE_UINT32, &class, "Icon", DBUS_TYPE_STRING, &icon, "RSSI", DBUS_TYPE_INT16, &tmp_rssi, "Name", DBUS_TYPE_STRING, &name, "Alias", DBUS_TYPE_STRING, &alias, NULL); if (name && name_type != 0x08) name_status = NAME_SENT; /* add in the list to track name sent/pending */ adapter_add_found_device(adapter, peer, rssi, class, real_alias, name_status); g_free(name); g_free(alias);}void hcid_dbus_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class){ char peer_addr[18]; const char *paddr = peer_addr; uint32_t old_class = 0; struct btd_adapter *adapter; struct btd_device *device; const gchar *dev_path; read_remote_class(local, peer, &old_class); if (old_class == class) return; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(peer, peer_addr); device = adapter_find_device(adapter, paddr); if (!device) return; dev_path = device_get_path(device); emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Class", DBUS_TYPE_UINT32, &class);}void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name){ struct btd_adapter *adapter; char srcaddr[18], dstaddr[18]; int state; struct btd_device *device; struct remote_dev_info match, *dev_info; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(local, srcaddr); ba2str(peer, dstaddr); if (status != 0) goto proceed; bacpy(&match.bdaddr, peer); match.name_status = NAME_ANY; dev_info = adapter_search_found_devices(adapter, &match); if (dev_info) { const char *adapter_path = adapter_get_path(adapter); const char *icon = class_to_icon(dev_info->class); const char *alias, *paddr = dstaddr; dbus_int16_t rssi = dev_info->rssi; if (dev_info->alias) alias = dev_info->alias; else alias = name; emit_device_found(adapter_path, dstaddr, "Address", DBUS_TYPE_STRING, &paddr, "Class", DBUS_TYPE_UINT32, &dev_info->class, "Icon", DBUS_TYPE_STRING, &icon, "RSSI", DBUS_TYPE_INT16, &rssi, "Name", DBUS_TYPE_STRING, &name, "Alias", DBUS_TYPE_STRING, &alias, NULL); } device = adapter_find_device(adapter, dstaddr); if (device) { char alias[248]; const char *dev_path = device_get_path(device); emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Name", DBUS_TYPE_STRING, &name); if (read_device_alias(srcaddr, dstaddr, alias, sizeof(alias)) < 1) emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Alias", DBUS_TYPE_STRING, &name); }proceed: /* remove from remote name request list */ adapter_remove_found_device(adapter, peer); /* check if there is more devices to request names */ if (found_device_req_name(adapter) == 0) return; state = adapter_get_state(adapter); state &= ~PERIODIC_INQUIRY; state &= ~STD_INQUIRY; adapter_set_state(adapter, state);}void hcid_dbus_link_key_notify(bdaddr_t *local, bdaddr_t *peer){ char peer_addr[18]; struct btd_device *device; struct btd_adapter *adapter; struct bonding_request_info *bonding; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(peer, peer_addr); device = adapter_find_device(adapter, peer_addr); if (!device) { error("link_key_notify: device %s was removed!", peer_addr); return; } bonding = adapter_get_bonding_info(adapter); if (!device_get_connected(device)) device_set_secmode3_conn(device, TRUE); else if (!bonding) hcid_dbus_bonding_process_complete(local, peer, 0);}void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -