📄 dbus-hci.c
字号:
}void hcid_dbus_periodic_inquiry_start(bdaddr_t *local, uint8_t status){ struct adapter *adapter; const gchar *path; /* Don't send the signal if the cmd failed */ if (status) return; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } adapter->pdiscov_active = 1; /* Disable name resolution for non D-Bus clients */ if (!adapter->pdiscov_requestor) adapter->discov_type &= ~RESOLVE_NAME; path = adapter_get_path(adapter); dbus_connection_emit_property_changed(connection, path, ADAPTER_INTERFACE, "PeriodicDiscovery", DBUS_TYPE_BOOLEAN, &adapter->pdiscov_active);}void hcid_dbus_periodic_inquiry_exit(bdaddr_t *local, uint8_t status){ struct adapter *adapter; const gchar *path; /* Don't send the signal if the cmd failed */ if (status) return; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); 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) { g_dbus_remove_watch(connection, adapter->pdiscov_listener); adapter->pdiscov_listener = 0; g_free(adapter->pdiscov_requestor); adapter->pdiscov_requestor = NULL; } path = adapter_get_path(adapter); /* workaround: inquiry completed is not sent when exiting from * periodic inquiry */ if (adapter->discov_active) { g_dbus_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_property_changed(connection, path, ADAPTER_INTERFACE, "PeriodicDiscovery", DBUS_TYPE_BOOLEAN, &adapter->discov_active);}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;}static void append_dict_valist(DBusMessageIter *iter, const char *first_key, va_list var_args){ DBusMessageIter dict; const char *key; int type; void *val; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); key = first_key; while (key) { type = va_arg(var_args, int); val = va_arg(var_args, void *); dbus_message_iter_append_dict_entry(&dict, key, type, val); key = va_arg(var_args, char *); } dbus_message_iter_close_container(iter, &dict);}static void emit_device_found(const char *path, const char *address, const char *first_key, ...){ DBusMessage *signal; DBusMessageIter iter; va_list var_args; signal = dbus_message_new_signal(path, ADAPTER_INTERFACE, "DeviceFound"); if (!signal) { error("Unable to allocate new %s.DeviceFound signal", ADAPTER_INTERFACE); return; } dbus_message_iter_init_append(signal, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &address); va_start(var_args, first_key); append_dict_valist(&iter, first_key, var_args); va_end(var_args); dbus_connection_send(connection, signal, NULL); dbus_message_unref(signal);}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]; 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; const gchar *path; ba2str(local, local_addr); ba2str(peer, peer_addr); adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); 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); } } 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; } } path = adapter_get_path(adapter); if (name) { if (name_type != 0x08) name_status = NAME_SENT; emit_device_found(path, paddr, "Address", DBUS_TYPE_STRING, &paddr, "Class", DBUS_TYPE_UINT32, &class, "RSSI", DBUS_TYPE_INT16, &tmp_rssi, "Name", DBUS_TYPE_STRING, &name, NULL); g_free(name); } else { emit_device_found(path, paddr, "Address", DBUS_TYPE_STRING, &paddr, "Class", DBUS_TYPE_UINT32, &class, "RSSI", DBUS_TYPE_INT16, &tmp_rssi, NULL); } /* 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 peer_addr[18]; const char *paddr = peer_addr; uint32_t old_class = 0; struct adapter *adapter; GSList *l; struct btd_device *device; const gchar *dev_path; read_remote_class(local, peer, &old_class); if (old_class == class) return; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(peer, peer_addr); l = g_slist_find_custom(adapter->devices, paddr, (GCompareFunc) device_address_cmp); if (!l) return; device = l->data; dev_path = device_get_path(device); dbus_connection_emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Class", DBUS_TYPE_UINT32, &class);}void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, uint8_t status, char *name){ struct adapter *adapter; char peer_addr[18]; const char *paddr = peer_addr; const gchar *dev_path; const gchar *path; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(peer, peer_addr); if (!status) { struct btd_device *device; device = adapter_find_device(adapter, paddr); if (device) { dev_path = device_get_path(device); dbus_connection_emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Name", DBUS_TYPE_STRING, &name); } } /* 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) { g_dbus_remove_watch(connection, adapter->discov_listener); adapter->discov_listener = 0; 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); dbus_connection_send(connection, reply, NULL); dbus_message_unref(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; } path = adapter_get_path(adapter); if (adapter->discov_active) { g_dbus_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 peer_addr[18]; const char *paddr = peer_addr; struct adapter *adapter; const gchar *dev_path; adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); return; } ba2str(peer, 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 (adapter->bonding) adapter->bonding->hci_status = status; } else { struct btd_device *device; gboolean connected = TRUE; device = adapter_find_device(adapter, paddr); if (device) { dev_path = device_get_path(device); dbus_connection_emit_property_changed(connection, dev_path, DEVICE_INTERFACE, "Connected", DBUS_TYPE_BOOLEAN, &connected); } /* 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 peer_addr[18]; const char *paddr = peer_addr; struct adapter *adapter; struct btd_device *device; struct active_conn_info *dev; GSList *l; gboolean connected = FALSE; struct pending_auth_info *auth; const gchar *destination; const gchar *dev_path; uint16_t dev_id; if (status) { error("Disconnection failed: 0x%02x", status); return; } adapter = manager_find_adapter(local); if (!adapter) { error("No matching adapter found"); 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); 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); /* 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 */ reply = new_authentication_return(adapter->bonding->msg, HCI_OE_USER_ENDED_CONNECTION); g_dbus_send_message(connection, reply); } else { reply = new_authentication_return(adapter->bonding->msg, HCI_AUTHENTICATION_FAILURE); dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); } g_dbus_remove_watch(adapter->bonding->conn, adapter->bonding->listener_id); 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; } adapter->active_conn = g_slist_remove(adapter->active_conn, dev); g_free(dev); device = adapter_find_device(adapter, paddr); if (device) { destination = device_get_address(device); dev_path = device_get_path(device);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -