📄 adapter.c
字号:
}static DBusMessage *set_property(DBusConnection *conn, DBusMessage *msg, void *data){ struct btd_adapter *adapter = data; DBusMessageIter iter; DBusMessageIter sub; const char *property; char srcaddr[18]; ba2str(&adapter->bdaddr, srcaddr); if (!dbus_message_iter_init(msg, &iter)) return invalid_args(msg); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return invalid_args(msg); dbus_message_iter_get_basic(&iter, &property); dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) return invalid_args(msg); dbus_message_iter_recurse(&iter, &sub); if (g_str_equal("Name", property)) { const char *name; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) return invalid_args(msg); dbus_message_iter_get_basic(&sub, &name); return set_name(conn, msg, name, data); } else if (g_str_equal("Mode", property)) { const char *mode; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) return invalid_args(msg); dbus_message_iter_get_basic(&sub, &mode); adapter->global_mode = get_mode(&adapter->bdaddr, mode); if (adapter->global_mode == adapter->mode) return dbus_message_new_method_return(msg); if (adapter->mode_sessions && adapter->global_mode < adapter->mode) return confirm_mode(conn, msg, mode, data); return set_mode(conn, msg, get_mode(&adapter->bdaddr, mode), data); } else if (g_str_equal("Powered", property)) { gboolean powered; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN) return invalid_args(msg); dbus_message_iter_get_basic(&sub, &powered); return set_powered(conn, msg, powered, data); } else if (g_str_equal("Discoverable", property)) { gboolean discoverable; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN) return invalid_args(msg); dbus_message_iter_get_basic(&sub, &discoverable); return set_discoverable(conn, msg, discoverable, data); } else if (g_str_equal("DiscoverableTimeout", property)) { uint32_t timeout; if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_UINT32) return invalid_args(msg); dbus_message_iter_get_basic(&sub, &timeout); return set_discoverable_timeout(conn, msg, timeout, data); } return invalid_args(msg);}static DBusMessage *mode_request(DBusConnection *conn, DBusMessage *msg, const char *mode, void *data){ struct btd_adapter *adapter = data; struct session_req *req; uint8_t new_mode; int ret; char srcaddr[18]; ba2str(&adapter->bdaddr, srcaddr); new_mode = get_mode(&adapter->bdaddr, mode); if (new_mode != MODE_CONNECTABLE && new_mode != MODE_DISCOVERABLE) return invalid_args(msg); if (!adapter->agent) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "No agent registered"); if (!adapter->mode_sessions) adapter->global_mode = adapter->mode; req = find_session(adapter->mode_sessions, msg); if (!req) { req = create_session(adapter, conn, msg, new_mode, (GDBusWatchFunction) session_free); adapter->mode_sessions = g_slist_append(adapter->mode_sessions, req); } else { req->mode = new_mode; adapter->mode_sessions = g_slist_append(adapter->mode_sessions, req); session_remove(req); return dbus_message_new_method_return(msg); } /* No need to change mode */ if (adapter->mode >= new_mode) return dbus_message_new_method_return(msg); ret = agent_confirm_mode_change(adapter->agent, mode, confirm_mode_cb, req); if (ret < 0) { session_unref(req); return invalid_args(msg); } return NULL;}static DBusMessage *request_mode(DBusConnection *conn, DBusMessage *msg, void *data){ const char *mode; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID)) return invalid_args(msg); return mode_request(conn, msg, mode, data);}static DBusMessage *request_session(DBusConnection *conn, DBusMessage *msg, void *data){ return mode_request(conn, msg, "connectable", data);}static DBusMessage *release_session(DBusConnection *conn, DBusMessage *msg, void *data){ struct btd_adapter *adapter = data; struct session_req *req; req = find_session(adapter->mode_sessions, msg); if (!req) return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "No Mode to release"); session_unref(req); return dbus_message_new_method_return(msg);}static DBusMessage *list_devices(DBusConnection *conn, DBusMessage *msg, void *data){ struct btd_adapter *adapter = data; DBusMessage *reply; GSList *l; DBusMessageIter iter; DBusMessageIter array_iter; const gchar *dev_path; if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) return invalid_args(msg); 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 *cancel_device_creation(DBusConnection *conn, DBusMessage *msg, void *data){ struct btd_adapter *adapter = data; struct bonding_request_info *bonding = adapter->bonding; const gchar *address; bdaddr_t bda; 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); str2ba(address, &bda); if (bonding && !bacmp(&bonding->bdaddr, &bda)) { if (!g_str_equal(dbus_message_get_sender(msg), dbus_message_get_sender(bonding->msg))) return not_authorized(msg); debug("Canceling device creation for %s", address); cancel_bonding(adapter, FALSE); } return dbus_message_new_method_return(msg);}static DBusMessage *create_device(DBusConnection *conn, DBusMessage *msg, void *data){ struct btd_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, FALSE); 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 btd_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 btd_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 btd_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 btd_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 btd_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);}/* 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 | G_DBUS_METHOD_FLAG_DEPRECATED}, { "ReleaseMode", "", "", release_session, G_DBUS_METHOD_FLAG_DEPRECATED}, { "RequestSession", "", "", request_session, G_DBUS_METHOD_FLAG_ASYNC}, { "ReleaseSession", "", "", release_session }, { "StartDiscovery", "", "", adapter_start_discovery }, { "StopDiscovery", "", "", adapter_stop_discovery, G_DBUS_METHOD_FLAG_ASYNC}, { "ListDevices", "", "ao", list_devices, G_DBUS_METHOD_FLAG_DEPRECATED}, { "CreateDevice", "s", "o", create_device, G_DBUS_METHOD_FLAG_ASYNC}, { "CreatePairedDevice", "sos", "o", create_paired_device, G_DBUS_METHOD_FLAG_ASYNC}, { "CancelDeviceCreation","s", "", cancel_device_creation }, { "RemoveDevice", "o", "", remove_device }, { "FindDevice", "s", "o", find_device }, { "RegisterAgent", "os", "", register_agent }, { "UnregisterAgent", "o", "", unregister_agent }, { }};static GDBusSignalTable adapter_signals[] = { { "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 adapter_read_bdaddr(uint16_t dev_id, bdaddr_t *bdaddr){ int dd, err; 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; } if (hci_read_bd_addr(dd, bdaddr, HCI_REQ_TIMEOUT) < 0) { err = errno;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -