📄 dbus-hci.c
字号:
snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); if (hci_devinfo(id, &di) < 0) { error("Getting device info failed: hci%d", id); return -1; } if (hci_test_bit(HCI_RAW, &di.flags)) return -1; if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); return -1; } if (hci_test_bit(HCI_INQUIRY, &di.flags)) adapter->discov_active = 1; else adapter->discov_active = 0; adapter->up = 1; adapter->discov_timeout = get_discoverable_timeout(id); adapter->discov_type = DISCOVER_TYPE_NONE; dd = hci_open_dev(id); if (dd < 0) goto failed; adapter->scan_enable = get_startup_scan(id); hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &adapter->scan_enable); /* * Get the adapter Bluetooth address */ err = get_device_address(adapter->dev_id, adapter->address, sizeof(adapter->address)); if (err < 0) goto failed; err = get_device_class(adapter->dev_id, adapter->class); if (err < 0) goto failed; adapter->mode = get_startup_mode(id); if (adapter->mode == MODE_LIMITED) set_limited_discoverable(dd, adapter->class, TRUE); /* * retrieve the active connections: address the scenario where * the are active connections before the daemon've started */ cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); cl->dev_id = id; cl->conn_num = 10; ci = cl->conn_info; if (ioctl(dd, HCIGETCONNLIST, cl) < 0) goto failed; for (i = 0; i < cl->conn_num; i++, ci++) active_conn_append(&adapter->active_conn, &ci->bdaddr, ci->handle); ret = 0; mode = mode2str(adapter->mode); dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "ModeChanged", DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID);failed: if (ret == 0 && get_default_adapter() < 0) set_default_adapter(id); if (dd >= 0) hci_close_dev(dd); g_free(cl); return ret;}static void send_dc_signal(struct active_conn_info *dev, const char *path){ char addr[18]; const char *paddr = addr; ba2str(&dev->bdaddr, addr); dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteDeviceDisconnected", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID);}int hcid_dbus_stop_device(uint16_t id){ char path[MAX_PATH_LENGTH]; struct adapter *adapter; const char *mode = "off"; snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); return -1; } /* cancel pending timeout */ if (adapter->timeout_id) { g_source_remove(adapter->timeout_id); adapter->timeout_id = 0; } /* check pending requests */ reply_pending_requests(path, adapter); cancel_passkey_agent_requests(adapter->passkey_agents, path, NULL); release_passkey_agents(adapter, NULL); if (adapter->discov_requestor) { name_listener_remove(connection, adapter->discov_requestor, (name_cb_t) discover_devices_req_exit, adapter); g_free(adapter->discov_requestor); adapter->discov_requestor = NULL; } if (adapter->pdiscov_requestor) { name_listener_remove(connection, adapter->pdiscov_requestor, (name_cb_t) periodic_discover_req_exit, adapter); g_free(adapter->pdiscov_requestor); adapter->pdiscov_requestor = NULL; } if (adapter->found_devices) { g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; } if (adapter->oor_devices) { g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL); g_slist_free(adapter->oor_devices); adapter->oor_devices = NULL; } if (adapter->pin_reqs) { g_slist_foreach(adapter->pin_reqs, (GFunc) g_free, NULL); g_slist_free(adapter->pin_reqs); adapter->pin_reqs = NULL; } if (adapter->active_conn) { g_slist_foreach(adapter->active_conn, (GFunc) send_dc_signal, path); g_slist_foreach(adapter->active_conn, (GFunc) g_free, NULL); g_slist_free(adapter->active_conn); adapter->active_conn = NULL; } send_adapter_signal(connection, adapter->dev_id, "ModeChanged", DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); adapter->up = 0; adapter->scan_enable = SCAN_DISABLED; adapter->mode = MODE_OFF; adapter->discov_active = 0; adapter->pdiscov_active = 0; adapter->pinq_idle = 0; adapter->discov_type = DISCOVER_TYPE_NONE; return 0;}int pin_req_cmp(const void *p1, const void *p2){ const struct pending_pin_info *pb1 = p1; const struct pending_pin_info *pb2 = p2; return p2 ? bacmp(&pb1->bdaddr, &pb2->bdaddr) : -1;}void hcid_dbus_pending_pin_req_add(bdaddr_t *sba, bdaddr_t *dba){ char path[MAX_PATH_LENGTH], addr[18]; struct adapter *adapter; struct pending_pin_info *info; int id; ba2str(sba, addr); id = hci_devid(addr); if (id < 0) { error("No matching device id for %s", addr); return; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); return; } info = g_new0(struct pending_pin_info, 1); bacpy(&info->bdaddr, dba); adapter->pin_reqs = g_slist_append(adapter->pin_reqs, info); if (adapter->bonding && !bacmp(dba, &adapter->bonding->bdaddr)) adapter->bonding->auth_active = 1;}int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci){ char path[MAX_PATH_LENGTH], addr[18]; int id; ba2str(sba, addr); id = hci_devid(addr); if (id < 0) { error("No matching device id for %s", addr); return -1; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); return handle_passkey_request(connection, dev, path, sba, &ci->bdaddr);}int hcid_dbus_confirm_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci, char *pin){ char path[MAX_PATH_LENGTH], addr[18]; int id; ba2str(sba, addr); id = hci_devid(addr); if (id < 0) { error("No matching device id for %s", addr); return -1; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); return handle_confirm_request(connection, dev, path, sba, &ci->bdaddr, pin);}void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer, uint8_t status){ struct adapter *adapter; char path[MAX_PATH_LENGTH], local_addr[18], peer_addr[18]; const char *paddr = peer_addr; GSList *l; int id; ba2str(local, local_addr); ba2str(peer, peer_addr); id = hci_devid(local_addr); if (id < 0) { error("No matching device id for %s", local_addr); return; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); /* create the authentication reply */ if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); return; } if (status) cancel_passkey_agent_requests(adapter->passkey_agents, path, peer); l = g_slist_find_custom(adapter->pin_reqs, peer, pin_req_cmp); if (l) { void *d = l->data; adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, l->data); g_free(d); if (!status) send_adapter_signal(connection, adapter->dev_id, "BondingCreated", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); } release_passkey_agents(adapter, peer); if (!adapter->bonding || bacmp(&adapter->bonding->bdaddr, peer)) return; /* skip: no bonding req pending */ if (adapter->bonding->cancel) { /* reply authentication canceled */ error_authentication_canceled(connection, adapter->bonding->rq); } else { DBusMessage *reply; /* reply authentication success or an error */ reply = new_authentication_return(adapter->bonding->rq, status); send_message_and_unref(connection, reply); } name_listener_remove(connection, dbus_message_get_sender(adapter->bonding->rq), (name_cb_t) create_bond_req_exit, adapter); 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; char path[MAX_PATH_LENGTH], local_addr[18]; int id; ba2str(local, local_addr); id = hci_devid(local_addr); if (id < 0) { error("No matching device id for %s", local_addr); return; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); if (dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { 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; } send_adapter_signal(connection, adapter->dev_id, "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; /* 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(adapter->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; char peer_addr[18]; const char *signal = NULL, *paddr = peer_addr; /* 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; ba2str(&dev->bdaddr, peer_addr); if (hci_send_req(dd, &rq, 500) < 0) { error("Unable to send the HCI remote name request: %s (%d)", strerror(errno), errno); signal = "RemoteNameFailed"; } if (rp.status) { error("Remote name request failed with status 0x%02x", rp.status); signal = "RemoteNameFailed"; } if (!signal) { req_sent = 1; /* if we are in discovery, inform application of getting name */ if (adapter->discov_type & (STD_INQUIRY | PERIODIC_INQUIRY)) signal = "RemoteNameRequested"; } if (signal) send_adapter_signal(connection, adapter->dev_id, signal, DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); if (req_sent) break; /* 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; dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteDeviceDisappeared", DBUS_TYPE_STRING, &peer_addr, DBUS_TYPE_INVALID); l = l->next; }}void hcid_dbus_inquiry_complete(bdaddr_t *local){ struct adapter *adapter; GSList *l; char path[MAX_PATH_LENGTH], local_addr[18]; struct remote_dev_info *dev; bdaddr_t tmp; int id; ba2str(local, local_addr); id = hci_devid(local_addr); if (id < 0) { error("No matching device id for %s", local_addr); return; } snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); goto done; } /* Out of range verification */ if (adapter->pdiscov_active && !adapter->discov_active) { 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)) goto done; /* skip - there is name to resolve */ if (adapter->discov_active) { dbus_connection_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) { name_listener_remove(connection, adapter->discov_requestor, (name_cb_t) discover_devices_req_exit, adapter); g_free(adapter->discov_requestor); adapter->discov_requestor = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -