📄 dbus-hci.c
字号:
dbus_connection_emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Connected", DBUS_TYPE_BOOLEAN, &connected); if (device_is_temporary(device)) { debug("Removing temporary device %s", destination); adapter_remove_device(connection, adapter, device); } }}int set_limited_discoverable(int dd, const uint8_t *cls, gboolean limited){ uint32_t dev_class; int err; int num = (limited ? 2 : 1); uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e }; /* * 1: giac * 2: giac + liac */ if (hci_write_current_iac_lap(dd, num, lap, 1000) < 0) { err = errno; error("Can't write current IAC LAP: %s(%d)", strerror(err), err); return -err; } if (limited) { if (cls[1] & 0x20) return 0; /* Already limited */ dev_class = (cls[2] << 16) | ((cls[1] | 0x20) << 8) | cls[0]; } else { if (!(cls[1] & 0x20)) return 0; /* Already clear */ dev_class = (cls[2] << 16) | ((cls[1] & 0xdf) << 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;}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;}/* 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'; } else 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;}void hcid_dbus_setscan_enable_complete(bdaddr_t *local){ struct adapter *adapter; read_scan_enable_rp rp; struct hci_request rq; int dd = -1; uint16_t dev_id; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } dev_id = adapter_get_dev_id(adapter); dd = hci_open_dev(dev_id); if (dd < 0) { error("HCI device open failed: hci%d", dev_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; } adapter_remove_discov_timeout(adapter); if (adapter_get_scan_mode(adapter) != rp.enable) adapter_mode_changed(adapter, rp.enable);failed: if (dd >= 0) hci_close_dev(dd);}void hcid_dbus_write_class_complete(bdaddr_t *local){ struct adapter *adapter; int dd; uint8_t cls[3]; uint16_t dev_id; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } dev_id = adapter_get_dev_id(adapter); dd = hci_open_dev(dev_id); if (dd < 0) { error("HCI device open failed: hci%d", dev_id); return; } if (hci_read_class_of_dev(dd, cls, 1000) < 0) { error("Can't read class of device on hci%d: %s (%d)", dev_id, strerror(errno), errno); hci_close_dev(dd); return; } write_local_class(local, cls); adapter_set_class(adapter, cls); hci_close_dev(dd);}void hcid_dbus_write_simple_pairing_mode_complete(bdaddr_t *local){ struct adapter *adapter; int dd; uint8_t mode; uint16_t dev_id; const gchar *path; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } dev_id = adapter_get_dev_id(adapter); path = adapter_get_path(adapter); dd = hci_open_dev(dev_id); if (dd < 0) { error("HCI adapter open failed: %s", path); return; } if (hci_read_simple_pairing_mode(dd, &mode, 1000) < 0) { error("Can't read class of adapter on %s: %s(%d)", path, strerror(errno), errno); hci_close_dev(dd); return; } adapter_update_ssp_mode(adapter, dd, mode); hci_close_dev(dd);}int hcid_dbus_get_io_cap(bdaddr_t *local, bdaddr_t *remote, uint8_t *cap, uint8_t *auth){ struct adapter *adapter; struct btd_device *device; struct agent *agent = NULL; char addr[18]; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return -1; } if (get_auth_requirements(local, remote, auth) < 0) return -1; ba2str(remote, addr); device = adapter_find_device(adapter, addr); if (device) { agent = device_get_agent(device); if (agent) *auth = 0x03; } if (!agent) agent = adapter->agent; if (!agent) { if (!(*auth & 0x01)) { /* No input, no output */ *cap = 0x03; return 0; } error("No agent available for IO capability"); return -1; } *cap = agent_get_io_capability(agent); return 0;}int hcid_dbus_set_io_cap(bdaddr_t *local, bdaddr_t *remote, uint8_t cap, uint8_t auth){ struct adapter *adapter; struct btd_device *device; char addr[18]; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return -1; } ba2str(remote, addr); device = adapter_get_device(connection, adapter, addr); if (device) { device_set_cap(device, cap); device_set_auth(device, auth); } return 0;}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; uint16_t dev_id = adapter_get_dev_id(adapter); if (!adapter->discov_active) goto cleanup; dd = hci_open_dev(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;}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; uint16_t dev_id = adapter_get_dev_id(adapter); if (!adapter->pdiscov_active) goto cleanup; dd = hci_open_dev(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 + -