📄 dbus-hci.c
字号:
}int set_service_classes(int dd, const uint8_t *cls, uint8_t value){ uint32_t dev_class; int err; if (cls[2] == value) return 0; /* Already set */ dev_class = (value << 16) | (cls[1] << 8) | cls[0]; if (hci_write_class_of_dev(dd, dev_class, 1000) < 0) { err = errno; error("Can't write class of device: %s (%d)", strerror(err), err); return -err; } return 0;}gboolean discov_timeout_handler(void *data){ struct adapter *adapter = data; struct hci_request rq; int dd; uint8_t scan_enable = adapter->scan_enable; uint8_t status = 0; gboolean retval = TRUE; scan_enable &= ~SCAN_INQUIRY; dd = hci_open_dev(adapter->dev_id); if (dd < 0) { error("HCI device open failed: hci%d", adapter->dev_id); return TRUE; } memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_WRITE_SCAN_ENABLE; rq.cparam = &scan_enable; rq.clen = sizeof(scan_enable); rq.rparam = &status; rq.rlen = sizeof(status); rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, 1000) < 0) { error("Sending write scan enable command to hci%d failed: %s (%d)", adapter->dev_id, strerror(errno), errno); goto failed; } if (status) { error("Setting scan enable failed with status 0x%02x", status); goto failed; } set_limited_discoverable(dd, adapter->class, FALSE); adapter->timeout_id = 0; retval = FALSE;failed: if (dd >= 0) hci_close_dev(dd); return retval;}/* Section reserved to device HCI callbacks */void hcid_dbus_setname_complete(bdaddr_t *local){ int id, dd = -1; read_local_name_rp rp; struct hci_request rq; const char *pname = (char *) rp.name; char local_addr[18], name[249]; ba2str(local, local_addr); id = hci_devid(local_addr); if (id < 0) { error("No matching device id for %s", local_addr); return; } dd = hci_open_dev(id); if (dd < 0) { error("HCI device open failed: hci%d", id); memset(&rp, 0, sizeof(rp)); } else { memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_READ_LOCAL_NAME; rq.rparam = &rp; rq.rlen = READ_LOCAL_NAME_RP_SIZE; rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, 1000) < 0) { error("Sending getting name command failed: %s (%d)", strerror(errno), errno); rp.name[0] = '\0'; } if (rp.status) { error("Getting name failed with status 0x%02x", rp.status); rp.name[0] = '\0'; } hci_close_dev(dd); } strncpy(name, pname, sizeof(name) - 1); name[248] = '\0'; pname = name; send_adapter_signal(connection, id, "NameChanged", DBUS_TYPE_STRING, &pname, DBUS_TYPE_INVALID);}void hcid_dbus_setscan_enable_complete(bdaddr_t *local){ struct adapter *adapter; char path[MAX_PATH_LENGTH], local_addr[18]; read_scan_enable_rp rp; struct hci_request rq; int id, dd = -1; 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); dd = hci_open_dev(id); if (dd < 0) { error("HCI device open failed: hci%d", id); return; } memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_READ_SCAN_ENABLE; rq.rparam = &rp; rq.rlen = READ_SCAN_ENABLE_RP_SIZE; rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, 1000) < 0) { error("Sending read scan enable command failed: %s (%d)", strerror(errno), errno); goto failed; } if (rp.status) { error("Getting scan enable failed with status 0x%02x", rp.status); goto failed; } if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); goto failed; } if (adapter->timeout_id) { g_source_remove(adapter->timeout_id); adapter->timeout_id = 0; } if (adapter->scan_enable != rp.enable) adapter_mode_changed(adapter, path, rp.enable);failed: if (dd >= 0) hci_close_dev(dd);}void hcid_dbus_write_class_complete(bdaddr_t *local){ struct adapter *adapter; char path[MAX_PATH_LENGTH], local_addr[18]; int id, dd; uint8_t cls[3]; 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); return; } dd = hci_open_dev(id); if (dd < 0) { error("HCI device open failed: hci%d", id); return; } if (hci_read_class_of_dev(dd, cls, 1000) < 0) { error("Can't read class of device on hci%d: %s (%d)", id, strerror(errno), errno); hci_close_dev(dd); return; } write_local_class(local, cls); set_device_class(adapter->dev_id, cls); memcpy(adapter->class, cls, 3); hci_close_dev(dd);}void hcid_dbus_write_simple_pairing_mode_complete(bdaddr_t *local){ char addr[18]; int dev_id, dd; uint8_t mode; ba2str(local, addr); dev_id = hci_devid(addr); if (dev_id < 0) { error("No matching device id for %s", addr); return; } dd = hci_open_dev(dev_id); if (dd < 0) { error("HCI device open failed: hci%d", dev_id); return; } if (hci_read_simple_pairing_mode(dd, &mode, 1000) < 0) { error("Can't read class of device on hci%d: %s(%d)", dev_id, strerror(errno), errno); hci_close_dev(dd); return; } set_simple_pairing_mode(dev_id, mode); hci_close_dev(dd);}void hcid_dbus_pin_code_reply(bdaddr_t *local, void *ptr){ typedef struct { uint8_t status; bdaddr_t bdaddr; } __attribute__ ((packed)) ret_pin_code_req_reply; struct adapter *adapter; ret_pin_code_req_reply *ret = ptr + EVT_CMD_COMPLETE_SIZE; GSList *l; 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)) { error("Getting %s path data failed!", path); return; } l = g_slist_find_custom(adapter->pin_reqs, &ret->bdaddr, pin_req_cmp); if (l) { struct pending_pin_info *p = l->data; p->replied = 1; }}void create_bond_req_exit(const char *name, struct adapter *adapter){ char path[MAX_PATH_LENGTH]; GSList *l; snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, adapter->dev_id); debug("CreateConnection requestor (%s) exited before bonding was completed", name); cancel_passkey_agent_requests(adapter->passkey_agents, path, &adapter->bonding->bdaddr); release_passkey_agents(adapter, &adapter->bonding->bdaddr); l = g_slist_find_custom(adapter->pin_reqs, &adapter->bonding->bdaddr, pin_req_cmp); if (l) { struct pending_pin_info *p = l->data; if (!p->replied) { int dd; dd = hci_open_dev(adapter->dev_id); if (dd >= 0) { hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &adapter->bonding->bdaddr); hci_close_dev(dd); } } adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, p); g_free(p); } g_io_channel_close(adapter->bonding->io); if (adapter->bonding->io_id) g_source_remove(adapter->bonding->io_id); bonding_request_free(adapter->bonding); adapter->bonding = NULL;}void discover_devices_req_exit(const char *name, struct adapter *adapter){ debug("DiscoverDevices requestor (%s) exited", name); /* * Cleanup the discovered devices list and send the command to * cancel inquiry or cancel remote name request. The return * can be ignored. */ cancel_discovery(adapter);}static int inquiry_cancel(int dd, int to){ struct hci_request rq; uint8_t status; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_INQUIRY_CANCEL; rq.rparam = &status; rq.rlen = sizeof(status); rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, to) < 0) return -1; if (status) { errno = bt_error(status); return -1; } return 0;}static int remote_name_cancel(int dd, bdaddr_t *dba, int to){ remote_name_req_cancel_cp cp; struct hci_request rq; uint8_t status; memset(&rq, 0, sizeof(rq)); memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, dba); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_REMOTE_NAME_REQ_CANCEL; rq.cparam = &cp; rq.clen = REMOTE_NAME_REQ_CANCEL_CP_SIZE; rq.rparam = &status; rq.rlen = sizeof(status); rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, to) < 0) return -1; if (status) { errno = bt_error(status); return -1; } return 0;}int cancel_discovery(struct adapter *adapter){ struct remote_dev_info *dev, match; GSList *l; int dd, err = 0; if (!adapter->discov_active) goto cleanup; dd = hci_open_dev(adapter->dev_id); if (dd < 0) { err = -ENODEV; goto cleanup; } /* * If there is a pending read remote name request means * that the inquiry complete event was already received */ memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, BDADDR_ANY); match.name_status = NAME_REQUESTED; l = g_slist_find_custom(adapter->found_devices, &match, (GCompareFunc) found_device_cmp); if (l) { dev = l->data; if (remote_name_cancel(dd, &dev->bdaddr, 1000) < 0) { error("Read remote name cancel failed: %s, (%d)", strerror(errno), errno); err = -errno; } } else { if (inquiry_cancel(dd, 1000) < 0) { error("Inquiry cancel failed:%s (%d)", strerror(errno), errno); err = -errno; } } hci_close_dev(dd);cleanup: /* * Reset discov_requestor and discover_state in the remote name * request event handler or in the inquiry complete handler. */ g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; /* Disable name resolution for non D-Bus clients */ if (!adapter->pdiscov_requestor) adapter->discov_type &= ~RESOLVE_NAME; return err;}void periodic_discover_req_exit(const char *name, struct adapter *adapter){ debug("PeriodicDiscovery requestor (%s) exited", name); /* * Cleanup the discovered devices list and send the cmd to exit from * periodic inquiry or cancel remote name request. The return value can * be ignored. */ cancel_periodic_discovery(adapter);}static int periodic_inquiry_exit(int dd, int to){ struct hci_request rq; uint8_t status; memset(&rq, 0, sizeof(rq)); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_EXIT_PERIODIC_INQUIRY; rq.rparam = &status; rq.rlen = sizeof(status); rq.event = EVT_CMD_COMPLETE; if (hci_send_req(dd, &rq, to) < 0) return -1; if (status) { errno = status; return -1; } return 0;}int cancel_periodic_discovery(struct adapter *adapter){ struct remote_dev_info *dev, match; GSList *l; int dd, err = 0; if (!adapter->pdiscov_active) goto cleanup; dd = hci_open_dev(adapter->dev_id); if (dd < 0) { err = -ENODEV; goto cleanup; } /* find the pending remote name request */ memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, BDADDR_ANY); match.name_status = NAME_REQUESTED; l = g_slist_find_custom(adapter->found_devices, &match, (GCompareFunc) found_device_cmp); if (l) { dev = l->data; if (remote_name_cancel(dd, &dev->bdaddr, 1000) < 0) { error("Read remote name cancel failed: %s, (%d)", strerror(errno), errno); err = -errno; } } /* ovewrite err if necessary: stop periodic inquiry has higher * priority */ if (periodic_inquiry_exit(dd, 1000) < 0) { error("Periodic Inquiry exit failed:%s (%d)", strerror(errno), errno); err = -errno; } hci_close_dev(dd);cleanup: /* * Reset pdiscov_requestor and pdiscov_active is done when the * cmd complete event for exit periodic inquiry mode cmd arrives. */ g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; return err;}/* Most of the functions in this module require easy access to a connection so * we keep it global here and provide these access functions the other (few) * modules that require access to it */void set_dbus_connection(DBusConnection *conn){ connection = conn;}DBusConnection *get_dbus_connection(void){ return connection;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -