📄 device.c
字号:
return FALSE; dd = hci_open_dev(dev_id); if (dd < 0) goto fail; memset(&cp, 0, sizeof(cp)); cp.handle = htobs(ci->handle); cp.reason = HCI_OE_USER_ENDED_CONNECTION; hci_send_cmd(dd, OGF_LINK_CTL, OCF_DISCONNECT, DISCONNECT_CP_SIZE, &cp); close(dd);fail: return FALSE;}static DBusMessage *disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data){ struct btd_device *device = user_data; struct active_conn_info *dev; dev = adapter_search_active_conn_by_bdaddr(device->adapter, &device->bdaddr); if (!dev) return g_dbus_create_error(msg, ERROR_INTERFACE ".NotConnected", "Device is not connected"); g_dbus_emit_signal(conn, device->path, DEVICE_INTERFACE, "DisconnectRequested", DBUS_TYPE_INVALID); device->disconn_timer = g_timeout_add_seconds(DISCONNECT_TIMER, disconnect_timeout, device); return dbus_message_new_method_return(msg);}static GDBusMethodTable device_methods[] = { { "GetProperties", "", "a{sv}", get_properties }, { "SetProperty", "sv", "", set_property }, { "DiscoverServices", "s", "a{us}", discover_services, G_DBUS_METHOD_FLAG_ASYNC}, { "CancelDiscovery", "", "", cancel_discover }, { "Disconnect", "", "", disconnect }, { }};static GDBusSignalTable device_signals[] = { { "PropertyChanged", "sv" }, { "DisconnectRequested", "" }, { }};gboolean device_get_connected(struct btd_device *device){ return device->connected;}void device_set_connected(DBusConnection *conn, struct btd_device *device, gboolean connected){ device->connected = connected; emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Connected", DBUS_TYPE_BOOLEAN, &connected); if (connected && device->secmode3) { struct btd_adapter *adapter = device_get_adapter(device); bdaddr_t sba; adapter_get_address(adapter, &sba); device->secmode3 = FALSE; hcid_dbus_bonding_process_complete(&sba, &device->bdaddr, 0); }}void device_set_secmode3_conn(struct btd_device *device, gboolean enable){ device->secmode3 = enable;}struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter, const gchar *address){ gchar *address_up; struct btd_device *device; const gchar *adapter_path = adapter_get_path(adapter); device = g_try_malloc0(sizeof(struct btd_device)); if (device == NULL) return NULL; address_up = g_ascii_strup(address, -1); device->path = g_strdup_printf("%s/dev_%s", adapter_path, address_up); g_strdelimit(device->path, ":", '_'); g_free(address_up); debug("Creating device %s", device->path); if (g_dbus_register_interface(conn, device->path, DEVICE_INTERFACE, device_methods, device_signals, NULL, device, device_free) == FALSE) { device_free(device); return NULL; } str2ba(address, &device->bdaddr); device->adapter = adapter; return device;}void device_remove(DBusConnection *conn, struct btd_device *device){ GSList *list; struct btd_device_driver *driver; gchar *path = g_strdup(device->path); debug("Removing device %s", path); for (list = device->drivers; list; list = list->next) { struct btd_driver_data *driver_data = list->data; driver = driver_data->driver; driver->remove(device); g_free(driver_data); } g_dbus_unregister_interface(conn, path, DEVICE_INTERFACE); g_free(path);}gint device_address_cmp(struct btd_device *device, const gchar *address){ char addr[18]; ba2str(&device->bdaddr, addr); return strcasecmp(addr, address);}static gboolean record_has_uuid(const sdp_record_t *rec, const char *profile_uuid){ sdp_list_t *pat; for (pat = rec->pattern; pat != NULL; pat = pat->next) { char *uuid; int ret; uuid = bt_uuid2string(pat->data); if (!uuid) continue; ret = strcasecmp(uuid, profile_uuid); g_free(uuid); if (ret == 0) return TRUE; } return FALSE;}static GSList *device_match_pattern(struct btd_device *device, const char *match_uuid, GSList *profiles){ GSList *l, *uuids = NULL; for (l = profiles; l; l = l->next) { char *profile_uuid = l->data; const sdp_record_t *rec; rec = btd_device_get_record(device, profile_uuid); if (!rec) continue; if (record_has_uuid(rec, match_uuid)) uuids = g_slist_append(uuids, profile_uuid); } return uuids;}static GSList *device_match_driver(struct btd_device *device, struct btd_device_driver *driver, GSList *profiles){ const char **uuid; GSList *uuids = NULL; for (uuid = driver->uuids; *uuid; uuid++) { GSList *match; /* skip duplicated uuids */ if (g_slist_find_custom(uuids, *uuid, (GCompareFunc) strcasecmp)) continue; /* match profile driver */ match = g_slist_find_custom(profiles, *uuid, (GCompareFunc) strcasecmp); if (match) { uuids = g_slist_append(uuids, match->data); continue; } /* match pattern driver */ match = device_match_pattern(device, *uuid, profiles); for (; match; match = match->next) uuids = g_slist_append(uuids, match->data); } return uuids;}void device_probe_drivers(struct btd_device *device, GSList *profiles){ GSList *list; int err; debug("Probe drivers for %s", device->path); for (list = device_drivers; list; list = list->next) { struct btd_device_driver *driver = list->data; GSList *probe_uuids; struct btd_driver_data *driver_data; probe_uuids = device_match_driver(device, driver, profiles); if (!probe_uuids) continue; driver_data = g_new0(struct btd_driver_data, 1); err = driver->probe(device, probe_uuids); if (err < 0) { error("probe failed with driver %s for device %s", driver->name, device->path); g_free(driver_data); g_slist_free(probe_uuids); continue; } driver_data->driver = driver; device->drivers = g_slist_append(device->drivers, driver_data); g_slist_free(probe_uuids); } for (list = profiles; list; list = list->next) { GSList *l = g_slist_find_custom(device->uuids, list->data, (GCompareFunc) strcasecmp); if (l) continue; device->uuids = g_slist_insert_sorted(device->uuids, g_strdup(list->data), (GCompareFunc) strcasecmp); } if (device->tmp_records) { sdp_list_free(device->tmp_records, (sdp_free_func_t) sdp_record_free); device->tmp_records = NULL; }}void device_remove_drivers(struct btd_device *device, GSList *uuids){ struct btd_adapter *adapter = device_get_adapter(device); GSList *list, *next; char srcaddr[18], dstaddr[18]; bdaddr_t src; sdp_list_t *records; adapter_get_address(adapter, &src); ba2str(&src, srcaddr); ba2str(&device->bdaddr, dstaddr); records = read_records(&src, &device->bdaddr); debug("Remove drivers for %s", device->path); for (list = device->drivers; list; list = next) { struct btd_driver_data *driver_data = list->data; struct btd_device_driver *driver = driver_data->driver; const char **uuid; next = list->next; for (uuid = driver->uuids; *uuid; uuid++) { sdp_record_t *rec; if (!g_slist_find_custom(uuids, *uuid, (GCompareFunc) strcasecmp)) continue; debug("UUID %s was removed from device %s", *uuid, dstaddr); driver->remove(device); device->drivers = g_slist_remove(device->drivers, driver_data); g_free(driver_data); rec = find_record_in_list(records, *uuid); if (!rec) break; delete_record(srcaddr, dstaddr, rec->handle); records = sdp_list_remove(records, rec); sdp_record_free(rec); break; } } if (records) sdp_list_free(records, (sdp_free_func_t) sdp_record_free); for (list = uuids; list; list = list->next) device->uuids = g_slist_remove(device->uuids, list->data);}static void iter_append_record(DBusMessageIter *dict, uint32_t handle, const char *record){ DBusMessageIter entry; dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); dbus_message_iter_append_basic(&entry, DBUS_TYPE_UINT32, &handle); dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &record); dbus_message_iter_close_container(dict, &entry);}static void append_and_grow_string(void *data, const char *str){ sdp_buf_t *buff = data; int len; len = strlen(str); if (!buff->data) { buff->data = malloc(DEFAULT_XML_BUF_SIZE); if (!buff->data) return; buff->buf_size = DEFAULT_XML_BUF_SIZE; } /* Grow string */ while (buff->buf_size < (buff->data_size + len + 1)) { void *tmp; uint32_t new_size; /* Grow buffer by a factor of 2 */ new_size = (buff->buf_size << 1); tmp = realloc(buff->data, new_size); if (!tmp) return; buff->data = tmp; buff->buf_size = new_size; } /* Include the NULL character */ memcpy(buff->data + buff->data_size, str, len + 1); buff->data_size += len;}static void discover_device_reply(struct browse_req *req, sdp_list_t *recs){ DBusMessage *reply; DBusMessageIter iter, dict; sdp_list_t *seq; reply = dbus_message_new_method_return(req->msg); if (!reply) return; dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_UINT32_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); for (seq = recs; seq; seq = seq->next) { sdp_record_t *rec = (sdp_record_t *) seq->data; sdp_buf_t result; if (!rec) break; memset(&result, 0, sizeof(sdp_buf_t)); convert_sdp_record_to_xml(rec, &result, append_and_grow_string); if (result.data) { const char *val = (char *) result.data; iter_append_record(&dict, rec->handle, val); free(result.data); } } dbus_message_iter_close_container(&iter, &dict); g_dbus_send_message(req->conn, reply);}static void services_changed(struct btd_device *device){ DBusConnection *conn = get_dbus_connection(); char **uuids; GSList *l; int i; uuids = g_new0(char *, g_slist_length(device->uuids) + 1); for (i = 0, l = device->uuids; l; l = l->next, i++) uuids[i] = l->data; emit_array_property_changed(conn, device->path, DEVICE_INTERFACE, "UUIDs", DBUS_TYPE_STRING, &uuids); g_free(uuids);}static int rec_cmp(const void *a, const void *b){ const sdp_record_t *r1 = a; const sdp_record_t *r2 = b; return r1->handle - r2->handle;}static void update_services(struct browse_req *req, sdp_list_t *recs){ struct btd_device *device = req->device;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -