📄 dbus-hci.c
字号:
{ char peer_addr[18]; struct btd_adapter *adapter; struct bonding_request_info *bonding; struct btd_device *device; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(peer, peer_addr); device = adapter_get_device(connection, adapter, peer_addr); if (status) { struct pending_auth_info *auth; auth = adapter_find_auth_request(adapter, peer); if (auth && auth->agent) agent_cancel(auth->agent); adapter_remove_auth_request(adapter, peer); if (device) device_set_secmode3_conn(device, FALSE); bonding = adapter_get_bonding_info(adapter); if (bonding) bonding->hci_status = status; } else { if (device) device_set_connected(connection, device, TRUE); /* add in the active connetions list */ adapter_add_active_conn(adapter, peer, handle); }}void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason){ DBusMessage *reply; char peer_addr[18]; struct btd_adapter *adapter; struct btd_device *device; struct active_conn_info *dev; struct pending_auth_info *auth; uint16_t dev_id; struct bonding_request_info *bonding; if (status) { error("Disconnection failed: 0x%02x", status); return; } adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } dev = adapter_search_active_conn_by_handle(adapter, handle); if (!dev) { error("No matching connection for handle %u", handle); return; } ba2str(&dev->bdaddr, peer_addr); dev_id = adapter_get_dev_id(adapter); /* clean pending HCI cmds */ hci_req_queue_remove(dev_id, &dev->bdaddr); /* Cancel D-Bus/non D-Bus requests */ auth = adapter_find_auth_request(adapter, &dev->bdaddr); if (auth && auth->agent) agent_cancel(auth->agent); adapter_remove_auth_request(adapter, &dev->bdaddr); bonding = adapter_get_bonding_info(adapter); /* Check if there is a pending Bonding request */ if (bonding && (bacmp(&bonding->bdaddr, &dev->bdaddr) == 0)) { if (bonding->cancel) { /* reply authentication canceled */ reply = new_authentication_return(bonding->msg, HCI_OE_USER_ENDED_CONNECTION); g_dbus_send_message(connection, reply); } else { reply = new_authentication_return(bonding->msg, HCI_AUTHENTICATION_FAILURE); g_dbus_send_message(connection, reply); } adapter_free_bonding_request(adapter); } adapter_remove_active_conn(adapter, dev); device = adapter_find_device(adapter, peer_addr); if (device) { device_set_connected(connection, device, FALSE); if (device_is_temporary(device)) { debug("Removing temporary device %s", peer_addr); adapter_remove_device(connection, adapter, device); } }}int set_service_classes(int dd, const uint8_t *cls, uint8_t value){ uint32_t dev_class; 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, HCI_REQ_TIMEOUT) < 0) { int err = -errno; error("Can't write class of device: %s (%d)", strerror(err), err); return err; } return 0;}int set_major_and_minor_class(int dd, const uint8_t *cls, uint8_t major, uint8_t minor){ uint32_t dev_class; dev_class = (cls[2] << 16) | ((cls[1] & 0x20) << 8) | ((major & 0xdf) << 8) | minor; if (hci_write_class_of_dev(dd, dev_class, HCI_REQ_TIMEOUT) < 0) { int 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, HCI_REQ_TIMEOUT) < 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 btd_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, HCI_REQ_TIMEOUT) < 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_mode_changed(adapter, rp.enable);failed: if (dd >= 0) hci_close_dev(dd);}void hcid_dbus_write_class_complete(bdaddr_t *local){ struct btd_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, HCI_REQ_TIMEOUT) < 0) { error("Can't read class of device on hci%d: %s (%d)", dev_id, strerror(errno), errno); hci_close_dev(dd); return; } adapter_set_class(adapter, cls); write_local_class(local, cls); hci_close_dev(dd);}void hcid_dbus_write_simple_pairing_mode_complete(bdaddr_t *local){ struct btd_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, HCI_REQ_TIMEOUT) < 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 btd_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; if (!adapter_pairing_initiator(adapter, remote) && !adapter_is_pairable(adapter)) return -EPERM; ba2str(remote, addr); /* For CreatePairedDevice use dedicated bonding */ device = adapter_find_device(adapter, addr); if (device) { agent = device_get_agent(device); if (agent) *auth = 0x03; } if (!agent) agent = adapter_get_agent(adapter); if (!agent) { /* This is the non bondable mode case */ if (device && device_get_auth(device) > 0x01) { debug("Bonding request, but no agent present"); return -1; } /* No agent available, and no bonding case */ if (*auth < 0x02) { debug("Allowing no bonding without agent"); /* No input, no output */ *cap = 0x03; return 0; } error("No agent available for IO capability"); return -1; } if (device && *auth < 0x02) { /* If remote requests dedicated bonding follow that lead */ if (device_get_auth(device) == 0x02 || device_get_auth(device) == 0x03) *auth = 0x02; } *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 btd_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 btd_adapter *adapter){ struct remote_dev_info *dev, match; int dd, err = 0; uint16_t dev_id = adapter_get_dev_id(adapter); dd = hci_open_dev(dev_id); if (dd < 0) return -ENODEV; /* * 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; dev = adapter_search_found_devices(adapter, &match); if (dev) { if (remote_name_cancel(dd, &dev->bdaddr, HCI_REQ_TIMEOUT) < 0) { error("Read remote name cancel failed: %s, (%d)", strerror(errno), errno); err = -errno; } } else { if (inquiry_cancel(dd, HCI_REQ_TIMEOUT) < 0) { error("Inquiry cancel failed:%s (%d)", strerror(errno), errno); err = -errno; } } hci_close_dev(dd); 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 btd_adapter *adapter){ struct remote_dev_info *dev, match; int dd, err = 0; uint16_t dev_id = adapter_get_dev_id(adapter); dd = hci_open_dev(dev_id); if (dd < 0) return -ENODEV; /* find the pending remote name request */ memset(&match, 0, sizeof(struct remote_dev_info)); bacpy(&match.bdaddr, BDADDR_ANY); match.name_status = NAME_REQUESTED; dev = adapter_search_found_devices(adapter, &match); if (dev) { if (remote_name_cancel(dd, &dev->bdaddr, HCI_REQ_TIMEOUT) < 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, HCI_REQ_TIMEOUT) < 0) { error("Periodic Inquiry exit failed:%s (%d)", strerror(errno), errno); err = -errno; } hci_close_dev(dd); 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 + -