📄 dbus-hci.c
字号:
/* If there is a pending reply for discovery cancel */ if (adapter->discovery_cancel) { DBusMessage *reply; reply = dbus_message_new_method_return(adapter->discovery_cancel); send_message_and_unref(connection, reply); dbus_message_unref(adapter->discovery_cancel); adapter->discovery_cancel = NULL; } /* reset the discover type for standard inquiry only */ adapter->discov_type &= ~STD_INQUIRY; }done: /* Proceed with any queued up audits */ process_audits_list(path);}void hcid_dbus_periodic_inquiry_start(bdaddr_t *local, uint8_t status){ struct adapter *adapter; char path[MAX_PATH_LENGTH], local_addr[18]; int id; /* Don't send the signal if the cmd failed */ if (status) return; 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->pdiscov_active = 1; /* Disable name resolution for non D-Bus clients */ if (!adapter->pdiscov_requestor) adapter->discov_type &= ~RESOLVE_NAME; } dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "PeriodicDiscoveryStarted", DBUS_TYPE_INVALID);}void hcid_dbus_periodic_inquiry_exit(bdaddr_t *local, uint8_t status){ struct adapter *adapter; char path[MAX_PATH_LENGTH], local_addr[18]; int id; /* Don't send the signal if the cmd failed */ if (status) return; 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; } /* reset the discover type to be able to handle D-Bus and non D-Bus * requests */ adapter->pdiscov_active = 0; adapter->discov_type &= ~(PERIODIC_INQUIRY | RESOLVE_NAME); /* free discovered devices list */ g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; /* free out of range devices list */ g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL); g_slist_free(adapter->oor_devices); adapter->oor_devices = 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; } /* workaround: inquiry completed is not sent when exiting from * periodic inquiry */ if (adapter->discov_active) { dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "DiscoveryCompleted", DBUS_TYPE_INVALID); adapter->discov_active = 0; } /* Send discovery completed signal if there isn't name to resolve */ dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "PeriodicDiscoveryStopped", DBUS_TYPE_INVALID);}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;}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], path[MAX_PATH_LENGTH]; struct adapter *adapter; GSList *l; char local_addr[18], peer_addr[18], *name, *tmp_name; const char *paddr = peer_addr; struct remote_dev_info match; dbus_int16_t tmp_rssi = rssi; uint8_t name_type = 0x00; name_status_t name_status; 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); if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); 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->discov_active && !adapter->pdiscov_active) adapter->pdiscov_active = 1; /* reset the idle flag when the inquiry complete event arrives */ if (adapter->pdiscov_active) { adapter->pinq_idle = 0; /* Out of range list update */ l = g_slist_find_custom(adapter->oor_devices, peer_addr, (GCompareFunc) strcmp); if (l) { char *dev = l->data; adapter->oor_devices = g_slist_remove(adapter->oor_devices, dev); g_free(dev); } } /* send the device found signal */ dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteDeviceFound", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_UINT32, &class, DBUS_TYPE_INT16, &tmp_rssi, DBUS_TYPE_INVALID); 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 */ l = g_slist_find_custom(adapter->found_devices, &match, (GCompareFunc) found_device_cmp); if (l) return; /* the inquiry result can be triggered by NON D-Bus client */ if (adapter->discov_type & RESOLVE_NAME) name_status = NAME_REQUIRED; else name_status = NAME_NOT_REQUIRED; create_name(filename, PATH_MAX, STORAGEDIR, local_addr, "names"); name = textfile_get(filename, peer_addr); 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; } } if (name) { dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteNameUpdated", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); g_free(name); if (name_type != 0x08) name_status = NAME_SENT; } /* add in the list to track name sent/pending */ found_device_add(&adapter->found_devices, peer, rssi, name_status);}void hcid_dbus_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class){ char local_addr[18], peer_addr[18]; const char *paddr = peer_addr; uint32_t old_class = 0; int id; read_remote_class(local, peer, &old_class); if (old_class == class) return; 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; } send_adapter_signal(connection, id, "RemoteClassUpdated", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_UINT32, &class, DBUS_TYPE_INVALID);}void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name){ struct adapter *adapter; char path[MAX_PATH_LENGTH], local_addr[18], peer_addr[18]; const char *paddr = peer_addr; 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); if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); return; } if (status) dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteNameFailed", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); else dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteNameUpdated", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); /* remove from remote name request list */ found_device_remove(&adapter->found_devices, peer); /* check if there is more devices to request names */ if (!found_device_req_name(adapter)) return; /* skip if a new request has been sent */ /* free discovered devices list */ g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; /* * The discovery completed signal must be sent only for discover * devices request WITH name resolving */ 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 there is a pending reply for discovery cancel */ if (adapter->discovery_cancel) { DBusMessage *reply; reply = dbus_message_new_method_return(adapter->discovery_cancel); send_message_and_unref(connection, reply); dbus_message_unref(adapter->discovery_cancel); adapter->discovery_cancel = NULL; } /* Disable name resolution for non D-Bus clients */ if (!adapter->pdiscov_requestor) adapter->discov_type &= ~RESOLVE_NAME; } if (adapter->discov_active) { dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "DiscoveryCompleted", DBUS_TYPE_INVALID); adapter->discov_active = 0; }}void hcid_dbus_conn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, bdaddr_t *peer){ char path[MAX_PATH_LENGTH], local_addr[18], peer_addr[18]; const char *paddr = peer_addr; struct adapter *adapter; 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); if (!dbus_connection_get_object_user_data(connection, path, (void *) &adapter)) { error("Getting %s path data failed!", path); return; } if (status) { GSList *l; cancel_passkey_agent_requests(adapter->passkey_agents, path, peer); release_passkey_agents(adapter, peer); l = g_slist_find_custom(adapter->pin_reqs, peer, pin_req_cmp); if (l) { struct pending_pin_req *p = l->data; adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, p); g_free(p); } if (adapter->bonding) adapter->bonding->hci_status = status; } else { /* Send the remote device connected signal */ dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteDeviceConnected", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); /* add in the active connetions list */ active_conn_append(&adapter->active_conn, peer, handle); }}void hcid_dbus_disconn_complete(bdaddr_t *local, uint8_t status, uint16_t handle, uint8_t reason){ DBusMessage *reply; char path[MAX_PATH_LENGTH], local_addr[18], peer_addr[18]; const char *paddr = peer_addr; struct adapter *adapter; struct active_conn_info *dev; GSList *l; int id; if (status) { error("Disconnection failed: 0x%02x", status); return; } 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->active_conn, &handle, active_conn_find_by_handle); if (!l) return; dev = l->data; ba2str(&dev->bdaddr, peer_addr); /* clean pending HCI cmds */ hci_req_queue_remove(adapter->dev_id, &dev->bdaddr); /* Cancel D-Bus/non D-Bus requests */ cancel_passkey_agent_requests(adapter->passkey_agents, path, &dev->bdaddr); release_passkey_agents(adapter, &dev->bdaddr); l = g_slist_find_custom(adapter->pin_reqs, &dev->bdaddr, pin_req_cmp); if (l) { struct pending_pin_req *p = l->data; adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, p); g_free(p); } /* Check if there is a pending CreateBonding request */ if (adapter->bonding && (bacmp(&adapter->bonding->bdaddr, &dev->bdaddr) == 0)) { if (adapter->bonding->cancel) { /* reply authentication canceled */ error_authentication_canceled(connection, adapter->bonding->rq); } else { reply = new_authentication_return(adapter->bonding->rq, HCI_AUTHENTICATION_FAILURE); 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; } /* Check if there is a pending RemoteDeviceDisconnect request */ if (adapter->pending_dc) { reply = dbus_message_new_method_return(adapter->pending_dc->msg); if (!reply) error("Failed to allocate disconnect reply"); else send_message_and_unref(adapter->pending_dc->conn, reply); g_source_remove(adapter->pending_dc->timeout_id); dc_pending_timeout_cleanup(adapter); } /* Send the remote device disconnected signal */ dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE, "RemoteDeviceDisconnected", DBUS_TYPE_STRING, &paddr, DBUS_TYPE_INVALID); adapter->active_conn = g_slist_remove(adapter->active_conn, dev); g_free(dev);}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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -