📄 adapter.c
字号:
reply = dbus_message_new_method_return(msg); if (!reply) return NULL; dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter); for (l = adapter->devices; l; l = l->next) { struct btd_device *device = l->data; if (device_is_temporary(device)) continue; dev_path = device_get_path(device); dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_OBJECT_PATH, &dev_path); } dbus_message_iter_close_container(&iter, &array_iter); return reply;}static DBusMessage *create_device(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; struct btd_device *device; const gchar *address; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID) == FALSE) return invalid_args(msg); if (check_address(address) < 0) return invalid_args(msg); if (adapter_find_device(adapter, address)) return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExists", "Device already exists"); debug("create_device(%s)", address); device = device_create(conn, adapter, address); if (!device) return NULL; device_set_temporary(device, FALSE); device_browse(device, conn, msg, NULL); adapter->devices = g_slist_append(adapter->devices, device); return NULL;}static uint8_t parse_io_capability(const char *capability){ if (g_str_equal(capability, "")) return IO_CAPABILITY_DISPLAYYESNO; if (g_str_equal(capability, "DisplayOnly")) return IO_CAPABILITY_DISPLAYONLY; if (g_str_equal(capability, "DisplayYesNo")) return IO_CAPABILITY_DISPLAYYESNO; if (g_str_equal(capability, "KeyboardOnly")) return IO_CAPABILITY_KEYBOARDONLY; if (g_str_equal(capability, "NoInputOutput")) return IO_CAPABILITY_NOINPUTOUTPUT; return IO_CAPABILITY_INVALID;}static DBusMessage *create_paired_device(DBusConnection *conn, DBusMessage *msg, void *data){ const gchar *address, *agent_path, *capability; uint8_t cap; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_OBJECT_PATH, &agent_path, DBUS_TYPE_STRING, &capability, DBUS_TYPE_INVALID) == FALSE) return invalid_args(msg); if (check_address(address) < 0) return invalid_args(msg); cap = parse_io_capability(capability); if (cap == IO_CAPABILITY_INVALID) return invalid_args(msg); return create_bonding(conn, msg, address, agent_path, cap, data);}static gint device_path_cmp(struct btd_device *device, const gchar *path){ const gchar *dev_path = device_get_path(device); return strcasecmp(dev_path, path);}static DBusMessage *remove_device(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; struct btd_device *device; const char *path; GSList *l; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) == FALSE) return invalid_args(msg); l = g_slist_find_custom(adapter->devices, path, (GCompareFunc) device_path_cmp); if (!l) return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", "Device does not exist"); device = l->data; if (device_is_temporary(device) || device_is_busy(device)) return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", "Device creation in progress"); adapter_remove_device(conn, adapter, device); return dbus_message_new_method_return(msg);}static DBusMessage *find_device(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; struct btd_device *device; DBusMessage *reply; const gchar *address; GSList *l; const gchar *dev_path; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) return invalid_args(msg); l = g_slist_find_custom(adapter->devices, address, (GCompareFunc) device_address_cmp); if (!l) return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", "Device does not exist"); device = l->data; if (device_is_temporary(device)) return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", "Device creation in progress"); reply = dbus_message_new_method_return(msg); if (!reply) return NULL; dev_path = device_get_path(device); dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_INVALID); return reply;}static void agent_removed(struct agent *agent, struct adapter *adapter){ struct pending_auth_info *auth; GSList *l; adapter->agent = NULL; l = g_slist_find_custom(adapter->auth_reqs, agent, auth_info_agent_cmp); if (!l) return; auth = l->data; auth->agent = NULL;}static DBusMessage *register_agent(DBusConnection *conn, DBusMessage *msg, void *data){ const char *path, *name, *capability; struct agent *agent; struct adapter *adapter = data; uint8_t cap; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_STRING, &capability, DBUS_TYPE_INVALID)) return NULL; if (adapter->agent) return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExists", "Agent already exists"); cap = parse_io_capability(capability); if (cap == IO_CAPABILITY_INVALID) return invalid_args(msg); name = dbus_message_get_sender(msg); agent = agent_create(adapter, name, path, cap, (agent_remove_cb) agent_removed, adapter); if (!agent) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed to create a new agent"); adapter->agent = agent; debug("Agent registered for hci%d at %s:%s", adapter->dev_id, name, path); return dbus_message_new_method_return(msg);}static DBusMessage *unregister_agent(DBusConnection *conn, DBusMessage *msg, void *data){ const char *path, *name; struct adapter *adapter = data; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) return NULL; name = dbus_message_get_sender(msg); if (!adapter->agent || !agent_matches(adapter->agent, name, path)) return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist", "No such agent"); agent_destroy(adapter->agent, FALSE); adapter->agent = NULL; return dbus_message_new_method_return(msg);}static DBusMessage *add_service_record(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; DBusMessage *reply; const char *sender, *record; dbus_uint32_t handle; bdaddr_t src; int err; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE) return NULL; sender = dbus_message_get_sender(msg); str2ba(adapter->address, &src); err = add_xml_record(conn, sender, &src, record, &handle); if (err < 0) return failed_strerror(msg, err); reply = dbus_message_new_method_return(msg); if (!reply) return NULL; dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID); return reply;}static DBusMessage *update_service_record(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; bdaddr_t src; str2ba(adapter->address, &src); return update_xml_record(conn, msg, &src);}static DBusMessage *remove_service_record(DBusConnection *conn, DBusMessage *msg, void *data){ dbus_uint32_t handle; const char *sender; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID) == FALSE) return NULL; sender = dbus_message_get_sender(msg); if (remove_record(conn, sender, handle) < 0) return not_available(msg); return dbus_message_new_method_return(msg);}static DBusMessage *request_authorization(DBusConnection *conn, DBusMessage *msg, void *data){ /* FIXME implement the request */ return NULL;}static DBusMessage *cancel_authorization(DBusConnection *conn, DBusMessage *msg, void *data){ /* FIXME implement cancel request */ return dbus_message_new_method_return(msg);}/* BlueZ 4.0 API */static GDBusMethodTable adapter_methods[] = { { "GetProperties", "", "a{sv}",get_properties }, { "SetProperty", "sv", "", set_property, G_DBUS_METHOD_FLAG_ASYNC}, { "RequestMode", "s", "", request_mode, G_DBUS_METHOD_FLAG_ASYNC}, { "ReleaseMode", "", "", release_mode }, { "DiscoverDevices", "", "", adapter_discover_devices}, { "CancelDiscovery", "", "", adapter_cancel_discovery, G_DBUS_METHOD_FLAG_ASYNC}, { "ListDevices", "", "ao", list_devices }, { "CreateDevice", "s", "o", create_device, G_DBUS_METHOD_FLAG_ASYNC}, { "CreatePairedDevice", "sos", "o", create_paired_device, G_DBUS_METHOD_FLAG_ASYNC}, { "RemoveDevice", "o", "", remove_device }, { "FindDevice", "s", "o", find_device }, { "RegisterAgent", "os", "", register_agent }, { "UnregisterAgent", "o", "", unregister_agent }, { "AddServiceRecord", "s", "u", add_service_record }, { "UpdateServiceRecord","us", "", update_service_record }, { "RemoveServiceRecord","u", "", remove_service_record }, { "RequestAuthorization","su", "", request_authorization, G_DBUS_METHOD_FLAG_ASYNC}, { "CancelAuthorization","", "", cancel_authorization }, { }};static GDBusSignalTable adapter_signals[] = { { "DiscoveryStarted", "" }, { "DiscoveryCompleted", "" }, { "DeviceCreated", "o" }, { "DeviceRemoved", "o" }, { "DeviceFound", "sa{sv}" }, { "PropertyChanged", "sv" }, { "DeviceDisappeared", "s" }, { }};static inline uint8_t get_inquiry_mode(struct hci_dev *dev){ if (dev->features[6] & LMP_EXT_INQ) return 2; if (dev->features[3] & LMP_RSSI_INQ) return 1; if (dev->manufacturer == 11 && dev->hci_rev == 0x00 && dev->lmp_subver == 0x0757) return 1; if (dev->manufacturer == 15) { if (dev->hci_rev == 0x03 && dev->lmp_subver == 0x6963) return 1; if (dev->hci_rev == 0x09 && dev->lmp_subver == 0x6963) return 1; if (dev->hci_rev == 0x00 && dev->lmp_subver == 0x6965) return 1; } if (dev->manufacturer == 31 && dev->hci_rev == 0x2005 && dev->lmp_subver == 0x1805) return 1; return 0;}static int device_read_bdaddr(uint16_t dev_id, const char *address){ int dd, err; bdaddr_t bdaddr; dd = hci_open_dev(dev_id); if (dd < 0) { err = errno; error("Can't open device hci%d: %s (%d)", dev_id, strerror(err), err); return -err; } str2ba(address, &bdaddr); if (hci_read_bd_addr(dd, &bdaddr, 2000) < 0) { err = errno; error("Can't read address for hci%d: %s (%d)", dev_id, strerror(err), err); hci_close_dev(dd); return -err; } hci_close_dev(dd); return 0;}static int adapter_setup(struct adapter *adapter, int dd){ struct hci_dev *dev = &adapter->dev; uint8_t events[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00 }; uint8_t inqmode; bdaddr_t bdaddr; int err; char name[249]; if (dev->hci_rev > 1) { if (dev->features[5] & LMP_SNIFF_SUBR) events[5] |= 0x20; if (dev->features[5] & LMP_PAUSE_ENC) events[5] |= 0x80; if (dev->features[6] & LMP_EXT_INQ) events[5] |= 0x40; if (dev->features[6] & LMP_NFLUSH_PKTS) events[7] |= 0x01; if (dev->features[7] & LMP_LSTO) events[6] |= 0x80; if (dev->features[6] & LMP_SIMPLE_PAIR) { events[6] |= 0x01; /* IO Capability Request */ events[6] |= 0x02; /* IO Capability Response */ events[6] |= 0x04; /* User Confirmation Request */ events[6] |= 0x08; /* User Passkey Request */ events[6] |= 0x10; /* Remote OOB Data Request */ events[6] |= 0x20; /* Simple Pairing Complete */ events[7] |= 0x04; /* User Passkey Notification */ events[7] |= 0x08; /* Keypress Notification */ events[7] |= 0x10; /* Remote Host Supported Features Notification */ } hci_send_cmd(dd, OGF_HOST_CTL, OCF_SET_EVENT_MASK, sizeof(events), events); } str2ba(adapter->address, &bdaddr); if (read_local_name(&bdaddr, name) == 0) { memcpy(dev->name, name, 248); hci_write_local_name(dd, name, 5000); } update_ext_inquiry_response(dd, dev); inqmode = get_inquiry_mode(dev); if (inqmode < 1) return 0; if (hci_write_inquiry_mode(dd, inqmode, 2000) < 0) { err = errno; error("Can't write inquiry mode for %s: %s (%d)", adapter->path, strerror(err), err); hci_close_dev(dd); return -err; } return 0;}static int active_conn_append(GSList **list, bdaddr_t *bdaddr, uint16_t handle){ struct active_conn_info *dev; dev = g_new0(struct active_conn_info, 1); bacpy(&dev->bdaddr, bdaddr); dev->handle = handle; *list = g_slist_append(*list, dev); return 0;}static void create_stored_records_from_keys(char *key, char *value, void *user_data){ struct record_list *rec_list = user_data; const gchar *addr = rec_list->addr; sdp_record_t *rec; int size, i, len; uint8_t *pdata; char tmp[3] = ""; if (strstr(key, addr) == NULL) return; size = strlen(value)/2; pdata = g_malloc0(size); for (i = 0; i < size; i++) { memcpy(tmp, value + (i * 2), 2); pdata[i] = (uint8_t) strtol(tmp, NULL, 16); } rec = sdp_extract_pdu(pdata, size, &len); free(pdata); rec_list->recs = sdp_list_append(rec_list->recs, rec);}static void create_stored_device_from_profiles(char *key, char *value, void *user_data){ char filename[PATH_MAX + 1]; struct adapter *adapter = user_data; GSList *uuids = bt_string2list(value); struct btd_device *device; const gchar *src; struct record_list rec_list; if (g_slist_find_custom(adapter->devices, key, (GCompareFunc) device_address_cmp)) return; device = device_create(connection, adapter, key); if (!device) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -