⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adapter.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	bdaddr_t bdaddr;	int sk;	str2ba(address, &bdaddr);	/* check if there is a pending discover: requested by D-Bus/non clients */	if (adapter->discov_active)		return in_progress(msg, "Discover in progress");	pending_remote_name_cancel(adapter);	if (adapter->bonding)		return in_progress(msg, "Bonding in progress");	if (adapter_find_auth_request(adapter, &bdaddr))		return in_progress(msg, "Bonding in progress");	/* check if a link key already exists */	create_name(filename, PATH_MAX, STORAGEDIR, adapter->address,			"linkkeys");	str = textfile_caseget(filename, address);	if (str) {		free(str);		return g_dbus_create_error(msg,				ERROR_INTERFACE ".AlreadyExists",				"Bonding already exists");	}	sk = l2raw_connect(adapter->address, &bdaddr);	if (sk < 0)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".ConnectionAttemptFailed",				"Connection attempt failed");	bonding = bonding_request_new(conn, msg, adapter, address, agent_path,					capability);	if (!bonding) {		close(sk);		return NULL;	}	bonding->io = g_io_channel_unix_new(sk);	bonding->io_id = g_io_add_watch(bonding->io,					G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,					(GIOFunc) create_bonding_conn_complete,					adapter);	bonding->listener_id = g_dbus_add_disconnect_watch(conn,						dbus_message_get_sender(msg),						create_bond_req_exit, adapter,						NULL);	adapter->bonding = bonding;	return NULL;}static void periodic_discover_req_exit(void *user_data){	struct adapter *adapter = user_data;	debug("PeriodicDiscovery requestor exited");	/* Cleanup the discovered devices list and send the cmd to exit from	 * periodic inquiry or cancel remote name request. The return value can	 * be ignored. */	cancel_periodic_discovery(adapter);}static DBusMessage *adapter_start_periodic(DBusConnection *conn,						DBusMessage *msg, void *data){	periodic_inquiry_cp cp;	struct hci_request rq;	struct adapter *adapter = data;	uint8_t lap[3] = { 0x33, 0x8b, 0x9e };	uint8_t status;	int dd;	if (!adapter->up)		return adapter_not_ready(msg);	if (dbus_message_is_method_call(msg, ADAPTER_INTERFACE,				"StartPeriodicDiscovery")) {		if (!dbus_message_has_signature(msg,					DBUS_TYPE_INVALID_AS_STRING))			return invalid_args(msg);	}	if (adapter->discov_active || adapter->pdiscov_active)		return in_progress(msg, "Discover in progress");	pending_remote_name_cancel(adapter);	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return no_such_adapter(msg);	memset(&cp, 0, sizeof(cp));	memcpy(&cp.lap, lap, 3);	cp.max_period = htobs(24);	cp.min_period = htobs(16);	cp.length  = 0x08;	cp.num_rsp = 0x00;	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_LINK_CTL;	rq.ocf    = OCF_PERIODIC_INQUIRY;	rq.cparam = &cp;	rq.clen   = PERIODIC_INQUIRY_CP_SIZE;	rq.rparam = &status;	rq.rlen   = sizeof(status);	rq.event  = EVT_CMD_COMPLETE;	if (hci_send_req(dd, &rq, 1000) < 0) {		int err = errno;		error("Unable to start periodic inquiry: %s (%d)",				strerror(errno), errno);		hci_close_dev(dd);		return failed_strerror(msg, err);	}	if (status) {		error("HCI_Periodic_Inquiry_Mode failed with status 0x%02x",				status);		hci_close_dev(dd);		return failed_strerror(msg, bt_error(status));	}	adapter->pdiscov_requestor = g_strdup(dbus_message_get_sender(msg));	if (adapter->pdiscov_resolve_names)		adapter->discov_type = PERIODIC_INQUIRY | RESOLVE_NAME;	else		adapter->discov_type = PERIODIC_INQUIRY;	hci_close_dev(dd);	/* track the request owner to cancel it automatically if the owner	 * exits */	adapter->pdiscov_listener = g_dbus_add_disconnect_watch(conn,						dbus_message_get_sender(msg),						periodic_discover_req_exit,						adapter, NULL);	return dbus_message_new_method_return(msg);}static DBusMessage *adapter_stop_periodic(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter = data;	int err;	if (!adapter->up)		return adapter_not_ready(msg);	if (!adapter->pdiscov_active)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".NotAuthorized",				"Not authorized");	/*	 * Cleanup the discovered devices list and send the cmd to exit	 * from periodic inquiry mode or cancel remote name request.	 */	err = cancel_periodic_discovery(adapter);	if (err < 0) {		if (err == -ENODEV)			return no_such_adapter(msg);		else			return failed_strerror(msg, -err);	}	return dbus_message_new_method_return(msg);}static void discover_devices_req_exit(void *user_data){	struct adapter *adapter = user_data;	debug("DiscoverDevices requestor exited");	/* Cleanup the discovered devices list and send the command to cancel	 * inquiry or cancel remote name request. The return can be ignored. */	cancel_discovery(adapter);}static DBusMessage *adapter_discover_devices(DBusConnection *conn,						DBusMessage *msg, void *data){	inquiry_cp cp;	evt_cmd_status rp;	struct hci_request rq;	struct adapter *adapter = data;	uint8_t lap[3] = { 0x33, 0x8b, 0x9e };	int dd;	if (!adapter->up)		return adapter_not_ready(msg);	if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING))		return invalid_args(msg);	if (adapter->discov_active)		return in_progress(msg, "Discover in progress");	pending_remote_name_cancel(adapter);	if (adapter->bonding)		return in_progress(msg, "Bonding in progress");	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return no_such_adapter(msg);	memset(&cp, 0, sizeof(cp));	memcpy(&cp.lap, lap, 3);	cp.length  = 0x08;	cp.num_rsp = 0x00;	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_LINK_CTL;	rq.ocf    = OCF_INQUIRY;	rq.cparam = &cp;	rq.clen   = INQUIRY_CP_SIZE;	rq.rparam = &rp;	rq.rlen   = EVT_CMD_STATUS_SIZE;	rq.event  = EVT_CMD_STATUS;	if (hci_send_req(dd, &rq, 500) < 0) {		int err = errno;		error("Unable to start inquiry: %s (%d)",				strerror(errno), errno);		hci_close_dev(dd);		return failed_strerror(msg, err);	}	if (rp.status) {		error("HCI_Inquiry command failed with status 0x%02x",				rp.status);		hci_close_dev(dd);		return failed_strerror(msg, bt_error(rp.status));	}	adapter->discov_type |= (STD_INQUIRY | RESOLVE_NAME);	adapter->discov_requestor = g_strdup(dbus_message_get_sender(msg));	hci_close_dev(dd);	/* track the request owner to cancel it automatically if the owner	 * exits */	adapter->discov_listener = g_dbus_add_disconnect_watch(conn,						dbus_message_get_sender(msg),						discover_devices_req_exit,						adapter, NULL);	return dbus_message_new_method_return(msg);}static DBusMessage *adapter_cancel_discovery(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter = data;	int err;	if (!adapter->up)		return adapter_not_ready(msg);	if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING))		return invalid_args(msg);	/* is there discover pending? or discovery cancel was requested	 * previously */	if (!adapter->discov_active || adapter->discovery_cancel)		return g_dbus_create_error(msg,				ERROR_INTERFACE ".NotAuthorized",				"Not Authorized");	/* only the discover requestor can cancel the inquiry process */	if (!adapter->discov_requestor ||			strcmp(adapter->discov_requestor, dbus_message_get_sender(msg)))		return g_dbus_create_error(msg,				ERROR_INTERFACE ".NotAuthorized",				"Not Authorized");	/* Cleanup the discovered devices list and send the cmd to cancel	 * inquiry or cancel remote name request */	err = cancel_discovery(adapter);	if (err < 0) {		if (err == -ENODEV)			return no_such_adapter(msg);		else			return failed_strerror(msg, -err);	}	/* Reply before send DiscoveryCompleted */	adapter->discovery_cancel = dbus_message_ref(msg);	return NULL;}struct remote_device_list_t {	GSList *list;	time_t time;};static DBusMessage *get_properties(DBusConnection *conn,					DBusMessage *msg, void *data){	struct adapter *adapter = data;	const char *property;	DBusMessage *reply;	DBusMessageIter iter;	DBusMessageIter dict;	bdaddr_t ba;	char str[249];	if (check_address(adapter->address) < 0)		return adapter_not_ready(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_DICT_ENTRY_BEGIN_CHAR_AS_STRING			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);	/* Address */	property = adapter->address;	dbus_message_iter_append_dict_entry(&dict, "Address",			DBUS_TYPE_STRING, &property);	/* Name */	memset(str, 0, sizeof(str));	property = str;	str2ba(adapter->address, &ba);	if (!read_local_name(&ba, str))		dbus_message_iter_append_dict_entry(&dict, "Name",			DBUS_TYPE_STRING, &property);	/* Mode */	property = mode2str(adapter->mode);	dbus_message_iter_append_dict_entry(&dict, "Mode",			DBUS_TYPE_STRING, &property);	/* DiscoverableTimeout */	dbus_message_iter_append_dict_entry(&dict, "DiscoverableTimeout",				DBUS_TYPE_UINT32, &adapter->discov_timeout);	/* PeriodicDiscovery */	dbus_message_iter_append_dict_entry(&dict, "PeriodicDiscovery",				DBUS_TYPE_BOOLEAN, &adapter->pdiscov_active);	dbus_message_iter_close_container(&iter, &dict);	return reply;}static DBusMessage *set_property(DBusConnection *conn,					DBusMessage *msg, void *data){	struct adapter *adapter = data;	DBusMessageIter iter;	DBusMessageIter sub;	const char *property;	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("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);	} else if (g_str_equal("PeriodicDiscovery", property)) {		dbus_bool_t value;		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_BOOLEAN)			return invalid_args(msg);		dbus_message_iter_get_basic(&sub, &value);		if (value)			return adapter_start_periodic(conn, msg, data);		else			return adapter_stop_periodic(conn, msg, 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 = str2mode(adapter->address, mode);		if (adapter->global_mode == adapter->mode)			return dbus_message_new_method_return(msg);		if (adapter->sessions && adapter->global_mode < adapter->mode)			return confirm_mode(conn, msg, mode, data);		return set_mode(conn, msg, str2mode(adapter->address, mode),				data);	}	return invalid_args(msg);}static void session_exit(void *data){	struct mode_req *req = data;	struct adapter *adapter = req->adapter;	adapter->sessions = g_slist_remove(adapter->sessions, req);	if (!adapter->sessions) {		debug("Falling back to '%s' mode", mode2str(adapter->global_mode));		/* FIXME: fallback to previous mode		set_mode(req->conn, req->msg, adapter->global_mode, adapter);		*/	}	dbus_connection_unref(req->conn);	dbus_message_unref(req->msg);	g_free(req);}static DBusMessage *request_mode(DBusConnection *conn,					DBusMessage *msg, void *data){	const char *mode;	struct adapter *adapter = data;	struct mode_req *req;	uint8_t new_mode;	int ret;	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &mode,						DBUS_TYPE_INVALID))		return invalid_args(msg);	new_mode = str2mode(adapter->address, 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 (g_slist_find_custom(adapter->sessions, msg,			(GCompareFunc) find_session))		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",				"Mode already requested");	req = g_new0(struct mode_req, 1);	req->adapter = adapter;	req->conn = dbus_connection_ref(conn);	req->msg = dbus_message_ref(msg);	req->mode = new_mode;	req->id = g_dbus_add_disconnect_watch(conn,					dbus_message_get_sender(msg),					session_exit, req, NULL);	if (!adapter->sessions)		adapter->global_mode = adapter->mode;	adapter->sessions = g_slist_append(adapter->sessions, req);	/* 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) {		dbus_message_unref(req->msg);		g_dbus_remove_watch(req->conn, req->id);		dbus_connection_unref(req->conn);		g_free(req);		return invalid_args(msg);	}	return NULL;}static DBusMessage *release_mode(DBusConnection *conn,					DBusMessage *msg, void *data){	struct adapter *adapter = data;	GSList *l;	l = g_slist_find_custom(adapter->sessions, msg,			(GCompareFunc) find_session);	if (!l)		return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",				"No Mode to release");	session_exit(l->data);	return dbus_message_new_method_return(msg);}static DBusMessage *list_devices(DBusConnection *conn,						DBusMessage *msg, void *data){	struct 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -