📄 adapter.c
字号:
device_set_temporary(device, FALSE); adapter->devices = g_slist_append(adapter->devices, device); src = adapter->address; rec_list.addr = device_get_address(device); rec_list.recs = NULL; create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp"); textfile_foreach(filename, create_stored_records_from_keys, &rec_list); device_probe_drivers(device, uuids, rec_list.recs); if (rec_list.recs != NULL) sdp_list_free(rec_list.recs, (sdp_free_func_t) sdp_record_free); g_slist_free(uuids);}static void create_stored_device_from_linkkeys(char *key, char *value, void *user_data){ struct adapter *adapter = user_data; struct btd_device *device; if (g_slist_find_custom(adapter->devices, key, (GCompareFunc) device_address_cmp)) return; device = device_create(connection, adapter, key); if (device) { device_set_temporary(device, FALSE); adapter->devices = g_slist_append(adapter->devices, device); }}static void load_devices(struct adapter *adapter){ char filename[PATH_MAX + 1]; create_name(filename, PATH_MAX, STORAGEDIR, adapter->address, "profiles"); textfile_foreach(filename, create_stored_device_from_profiles, adapter); create_name(filename, PATH_MAX, STORAGEDIR, adapter->address, "linkkeys"); textfile_foreach(filename, create_stored_device_from_linkkeys, adapter);}static void adapter_up(struct adapter *adapter, int dd){ struct hci_conn_list_req *cl = NULL; struct hci_conn_info *ci; const char *mode; int i; adapter->up = 1; adapter->discov_timeout = get_discoverable_timeout(adapter->dev_id); adapter->discov_type = DISCOVER_TYPE_NONE; adapter->scan_mode = get_startup_scan(adapter->dev_id); hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &adapter->scan_mode); adapter->mode = get_startup_mode(adapter->dev_id); if (adapter->mode == MODE_LIMITED) set_limited_discoverable(dd, adapter->dev.class, TRUE); /* * retrieve the active connections: address the scenario where * the are active connections before the daemon've started */ cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl)); cl->dev_id = adapter->dev_id; cl->conn_num = 10; ci = cl->conn_info; if (ioctl(dd, HCIGETCONNLIST, cl) == 0) { for (i = 0; i < cl->conn_num; i++, ci++) active_conn_append(&adapter->active_conn, &ci->bdaddr, ci->handle); } g_free(cl); mode = mode2str(adapter->mode); dbus_connection_emit_property_changed(connection, adapter->path, ADAPTER_INTERFACE, "Mode", DBUS_TYPE_STRING, &mode); load_devices(adapter);}int adapter_start(struct adapter *adapter){ struct hci_dev *dev = &adapter->dev; struct hci_dev_info di; struct hci_version ver; uint8_t features[8]; int dd, err; char name[249]; if (hci_devinfo(adapter->dev_id, &di) < 0) return -errno; if (hci_test_bit(HCI_RAW, &di.flags)) { dev->ignore = 1; return -1; } if (bacmp(&di.bdaddr, BDADDR_ANY)) ba2str(&di.bdaddr, adapter->address); else { int err = device_read_bdaddr(adapter->dev_id, adapter->address); if (err < 0) return err; } memcpy(dev->features, di.features, 8); dd = hci_open_dev(adapter->dev_id); if (dd < 0) { err = errno; error("Can't open adapter %s: %s (%d)", adapter->path, strerror(err), err); return -err; } if (hci_read_local_version(dd, &ver, 1000) < 0) { err = errno; error("Can't read version info for %s: %s (%d)", adapter->path, strerror(err), err); hci_close_dev(dd); return -err; } dev->hci_rev = ver.hci_rev; dev->lmp_ver = ver.lmp_ver; dev->lmp_subver = ver.lmp_subver; dev->manufacturer = ver.manufacturer; if (hci_read_local_features(dd, features, 1000) < 0) { err = errno; error("Can't read features for %s: %s (%d)", adapter->path, strerror(err), err); hci_close_dev(dd); return -err; } memcpy(dev->features, features, 8); if (hci_read_class_of_dev(dd, dev->class, 1000) < 0) { err = errno; error("Can't read class of adapter on %s: %s (%d)", adapter->path, strerror(err), err); hci_close_dev(dd); return -err; } if (hci_read_local_name(dd, sizeof(name), name, 2000) < 0) { err = errno; error("Can't read local name on %s: %s (%d)", adapter->path, strerror(err), err); hci_close_dev(dd); return -err; } memcpy(dev->name, name, 248); if (!(features[6] & LMP_SIMPLE_PAIR)) goto setup; if (ioctl(dd, HCIGETAUTHINFO, NULL) < 0 && errno != EINVAL) hci_write_simple_pairing_mode(dd, 0x01, 2000); if (hci_read_simple_pairing_mode(dd, &dev->ssp_mode, 1000) < 0) { err = errno; error("Can't read simple pairing mode on %s: %s (%d)", adapter->path, strerror(err), err); hci_close_dev(dd); return -err; }setup: if (hci_test_bit(HCI_INQUIRY, &di.flags)) adapter->discov_active = 1; else adapter->discov_active = 0; adapter_setup(adapter, dd); adapter_up(adapter, dd); hci_close_dev(dd); info("Adapter %s has been enabled", adapter->path); return 0;}static void reply_pending_requests(struct adapter *adapter){ DBusMessage *reply; if (!adapter) return; /* pending bonding */ if (adapter->bonding) { reply = new_authentication_return(adapter->bonding->msg, HCI_OE_USER_ENDED_CONNECTION); g_dbus_send_message(connection, reply); remove_pending_device(adapter); 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; } /* If there is a pending reply for discovery cancel */ if (adapter->discovery_cancel) { 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; } if (adapter->discov_active) { /* Send discovery completed signal if there isn't name * to resolve */ g_dbus_emit_signal(connection, adapter->path, ADAPTER_INTERFACE, "DiscoveryCompleted", DBUS_TYPE_INVALID); /* Cancel inquiry initiated by D-Bus client */ if (adapter->discov_requestor) cancel_discovery(adapter); } if (adapter->pdiscov_active) { /* Stop periodic inquiry initiated by D-Bus client */ if (adapter->pdiscov_requestor) cancel_periodic_discovery(adapter); }}int adapter_stop(struct adapter *adapter){ const char *mode = "off"; /* cancel pending timeout */ if (adapter->discov_timeout_id) { g_source_remove(adapter->discov_timeout_id); adapter->discov_timeout_id = 0; } /* check pending requests */ reply_pending_requests(adapter); 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 (adapter->pdiscov_requestor) { g_dbus_remove_watch(connection, adapter->pdiscov_listener); adapter->pdiscov_listener = 0; g_free(adapter->pdiscov_requestor); adapter->pdiscov_requestor = NULL; } if (adapter->found_devices) { g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL); g_slist_free(adapter->found_devices); adapter->found_devices = NULL; } if (adapter->oor_devices) { g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL); g_slist_free(adapter->oor_devices); adapter->oor_devices = NULL; } if (adapter->auth_reqs) { g_slist_foreach(adapter->auth_reqs, (GFunc) g_free, NULL); g_slist_free(adapter->auth_reqs); adapter->auth_reqs = NULL; } if (adapter->active_conn) { g_slist_foreach(adapter->active_conn, (GFunc) g_free, NULL); g_slist_free(adapter->active_conn); adapter->active_conn = NULL; } dbus_connection_emit_property_changed(connection, adapter->path, ADAPTER_INTERFACE, "Mode", DBUS_TYPE_STRING, &mode); adapter->up = 0; adapter->scan_mode = SCAN_DISABLED; adapter->mode = MODE_OFF; adapter->discov_active = 0; adapter->pdiscov_active = 0; adapter->pinq_idle = 0; adapter->discov_type = DISCOVER_TYPE_NONE; info("Adapter %s has been disabled", adapter->path); return 0;}int adapter_update(struct adapter *adapter){ struct hci_dev *dev = &adapter->dev; int dd; if (dev->ignore) return 0; dd = hci_open_dev(adapter->dev_id); if (dd < 0) { int err = errno; error("Can't open adapter %s: %s (%d)", adapter->path, strerror(err), err); return -err; } update_ext_inquiry_response(dd, dev); hci_close_dev(dd); return 0;}int adapter_get_class(struct adapter *adapter, uint8_t *cls){ struct hci_dev *dev = &adapter->dev; memcpy(cls, dev->class, 3); return 0;}int adapter_set_class(struct adapter *adapter, uint8_t *cls){ struct hci_dev *dev = &adapter->dev; memcpy(dev->class, cls, 3); return 0;}int adapter_update_ssp_mode(struct adapter *adapter, int dd, uint8_t mode){ struct hci_dev *dev = &adapter->dev; dev->ssp_mode = mode; update_ext_inquiry_response(dd, dev); hci_close_dev(dd); return 0;}static void adapter_free(gpointer user_data){ struct adapter *adapter = user_data; g_free(adapter->path); g_free(adapter); return;}struct adapter *adapter_create(DBusConnection *conn, int id){ char path[MAX_PATH_LENGTH]; struct adapter *adapter; if (!connection) connection = conn; snprintf(path, sizeof(path), "%s/hci%d", "/org/bluez", id); adapter = g_try_new0(struct adapter, 1); if (!adapter) { error("Failed to alloc memory to D-Bus path register data (%s)", path); return NULL; } adapter->dev_id = id; adapter->pdiscov_resolve_names = 1; adapter->path = g_strdup(path); if (!g_dbus_register_interface(conn, path, ADAPTER_INTERFACE, adapter_methods, adapter_signals, NULL, adapter, adapter_free)) { error("Adapter interface init failed on path %s", path); adapter_free(adapter); return NULL; } return adapter;}void adapter_remove(struct adapter *adapter){ GSList *l; char *path = g_strdup(adapter->path); debug("Removing adapter %s", path); for (l = adapter->devices; l; l = l->next) device_remove(connection, l->data); g_slist_free(adapter->devices); g_dbus_unregister_interface(connection, path, ADAPTER_INTERFACE); g_free(path);}uint16_t adapter_get_dev_id(struct adapter *adapter){ return adapter->dev_id;}const gchar *adapter_get_path(struct adapter *adapter){ if (!adapter) return NULL; return adapter->path;}const gchar *adapter_get_address(struct adapter *adapter){ if (!adapter) return NULL; return adapter->address;}gboolean discov_timeout_handler(void *data){ struct adapter *adapter = data; struct hci_request rq; int dd; uint8_t scan_enable = adapter->scan_mode; uint8_t status = 0; gboolean retval = TRUE; uint16_t dev_id = adapter->dev_id; scan_enable &= ~SCAN_INQUIRY; dd = hci_open_dev(dev_id); if (dd < 0) { error("HCI device open failed: hci%d", 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)", 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->dev.class, FALSE); adapter_remove_discov_timeout(adapter); retval = FALSE;failed: if (dd >= 0) hci_close_dev(dd); return retval;}void adapter_set_discov_timeout(struct adapter *adapter, guint interval){ if (!adapter) return; if (adapter->discov_timeout_id) { error("Timeout already added for adapter %s", adapter->path); return; } adapter->discov_timeout_id = g_timeout_add(interval, discov_timeout_handler, adapter);}void adapter_remove_discov_timeout(struct adapter *adapter){ if (!adapter) return; if(adapter->discov_timeout_id == 0) return; g_source_remove(adapter->discov_timeout_id); adapter->discov_timeout_id = 0;}void adapter_set_scan_mode(struct adapter *adapter, uint8_t scan_mode){ if (!adapter) return; adapter->scan_mode = scan_mode;}uint8_t adapter_get_scan_mode(struct adapter *adapter){ return adapter->scan_mode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -