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

📄 adapter.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
					const char *mode, void *data){	struct adapter *adapter = data;	struct mode_req *req;	int ret;	if (!adapter->agent)		return dbus_message_new_method_return(msg);	req = g_new0(struct mode_req, 1);	req->adapter = adapter;	req->conn = dbus_connection_ref(conn);	req->msg = dbus_message_ref(msg);	req->mode = str2mode(adapter->address, mode);	ret = agent_confirm_mode_change(adapter->agent, mode, confirm_mode_cb,					req);	if (ret < 0) {		dbus_connection_unref(req->conn);		dbus_message_unref(req->msg);		g_free(req);		return invalid_args(msg);	}	return NULL;}static DBusMessage *set_discoverable_timeout(DBusConnection *conn,							DBusMessage *msg,							uint32_t timeout,							void *data){	struct adapter *adapter = data;	bdaddr_t bdaddr;	const char *path;	if (adapter->discov_timeout_id) {		g_source_remove(adapter->discov_timeout_id);		adapter->discov_timeout_id = 0;	}	if ((timeout != 0) && (adapter->scan_mode & SCAN_INQUIRY))		adapter->discov_timeout_id = g_timeout_add(timeout * 1000,						discov_timeout_handler,						adapter);	adapter->discov_timeout = timeout;	str2ba(adapter->address, &bdaddr);	write_discoverable_timeout(&bdaddr, timeout);	path = dbus_message_get_path(msg);	dbus_connection_emit_property_changed(conn, path,					ADAPTER_INTERFACE,					"DiscoverableTimeout",					DBUS_TYPE_UINT32, &timeout);	return dbus_message_new_method_return(msg);}static void update_ext_inquiry_response(int dd, struct hci_dev *dev){	uint8_t fec = 0, data[240];	if (!(dev->features[6] & LMP_EXT_INQ))		return;	memset(data, 0, sizeof(data));	if (dev->ssp_mode > 0)		create_ext_inquiry_response((char *) dev->name, data);	if (hci_write_ext_inquiry_response(dd, fec, data, 2000) < 0)		error("Can't write extended inquiry response: %s (%d)",						strerror(errno), errno);}static int adapter_set_name(struct adapter *adapter, const char *name){	struct hci_dev *dev = &adapter->dev;	int dd, err;	bdaddr_t bdaddr;	str2ba(adapter->address, &bdaddr);	write_local_name(&bdaddr, (char *) name);	if (!adapter->up)		return 0;	dd = hci_open_dev(adapter->dev_id);	if (dd < 0) {		err = errno;		error("Can't open device hci%d: %s (%d)",					adapter->dev_id, strerror(err), err);		return -err;	}	if (hci_write_local_name(dd, name, 5000) < 0) {		err = errno;		error("Can't write name for hci%d: %s (%d)",					adapter->dev_id, strerror(err), err);		hci_close_dev(dd);		return -err;	}	strncpy((char *) dev->name, name, 248);	update_ext_inquiry_response(dd, dev);	hci_close_dev(dd);	return 0;}static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,					const char *name, void *data){	struct adapter *adapter = data;	int ecode;	const char *path;	if (!g_utf8_validate(name, -1, NULL)) {		error("Name change failed: the supplied name isn't valid UTF-8");		return invalid_args(msg);	}	ecode = adapter_set_name(adapter, name);	if (ecode < 0)		return failed_strerror(msg, -ecode);	path = dbus_message_get_path(msg);	dbus_connection_emit_property_changed(conn, path,					ADAPTER_INTERFACE,					"Name", DBUS_TYPE_STRING,					&name);	return dbus_message_new_method_return(msg);}static void reply_authentication_failure(struct bonding_request_info *bonding){	DBusMessage *reply;	int status;	status = bonding->hci_status ?			bonding->hci_status : HCI_AUTHENTICATION_FAILURE;	reply = new_authentication_return(bonding->msg, status);	if (reply) {		dbus_connection_send(bonding->conn, reply, NULL);		dbus_message_unref(reply);	}}struct btd_device *adapter_find_device(struct adapter *adapter, const char *dest){	struct btd_device *device;	GSList *l;	if (!adapter)		return NULL;	l = g_slist_find_custom(adapter->devices,				dest, (GCompareFunc) device_address_cmp);	if (!l)		return NULL;	device = l->data;	return device;}struct btd_device *adapter_create_device(DBusConnection *conn,				struct adapter *adapter, const char *address){	struct btd_device *device;	debug("adapter_create_device(%s)", address);	device = device_create(conn, adapter, address);	if (!device)		return NULL;	device_set_temporary(device, TRUE);	adapter->devices = g_slist_append(adapter->devices, device);	return device;}static DBusMessage *remove_bonding(DBusConnection *conn, DBusMessage *msg,					const char *address, void *data){	struct adapter *adapter = data;	struct btd_device *device;	char filename[PATH_MAX + 1];	char *str;	bdaddr_t src, dst;	GSList *l;	int dev, err;	gboolean paired;	str2ba(adapter->address, &src);	str2ba(address, &dst);	dev = hci_open_dev(adapter->dev_id);	if (dev < 0 && msg)		return no_such_adapter(msg);	create_name(filename, PATH_MAX, STORAGEDIR, adapter->address,			"linkkeys");	/* textfile_del doesn't return an error when the key is not found */	str = textfile_caseget(filename, address);	paired = str ? TRUE : FALSE;	g_free(str);	if (!paired && msg) {		hci_close_dev(dev);		return g_dbus_create_error(msg,				ERROR_INTERFACE ".DoesNotExist",				"Bonding does not exist");	}	/* Delete the link key from storage */	if (textfile_casedel(filename, address) < 0 && msg) {		hci_close_dev(dev);		err = errno;		return failed_strerror(msg, err);	}	/* Delete the link key from the Bluetooth chip */	hci_delete_stored_link_key(dev, &dst, 0, 1000);	/* find the connection */	l = g_slist_find_custom(adapter->active_conn, &dst,				active_conn_find_by_bdaddr);	if (l) {		struct active_conn_info *con = l->data;		/* Send the HCI disconnect command */		if ((hci_disconnect(dev, htobs(con->handle),					HCI_OE_USER_ENDED_CONNECTION, 500) < 0)					&& msg){			int err = errno;			error("Disconnect failed");			hci_close_dev(dev);			return failed_strerror(msg, err);		}	}	hci_close_dev(dev);	device = adapter_find_device(adapter, address);	if (!device)		goto proceed;	if (paired) {		gboolean paired = FALSE;		const gchar *dev_path = device_get_path(device);		dbus_connection_emit_property_changed(conn, dev_path,					DEVICE_INTERFACE, "Paired",					DBUS_TYPE_BOOLEAN, &paired);	}proceed:	if(!msg)		goto done;	return dbus_message_new_method_return(msg);done:	return NULL;}void adapter_remove_device(DBusConnection *conn, struct adapter *adapter,				struct btd_device *device){	bdaddr_t src;	const gchar *destination = device_get_address(device);	const gchar *dev_path = device_get_path(device);	struct agent *agent;	str2ba(adapter->address, &src);	delete_entry(&src, "profiles", destination);	remove_bonding(conn, NULL, destination, adapter);	if (!device_is_temporary(device)) {		g_dbus_emit_signal(conn, adapter->path,				ADAPTER_INTERFACE,				"DeviceRemoved",				DBUS_TYPE_OBJECT_PATH, &dev_path,				DBUS_TYPE_INVALID);	}	agent = device_get_agent(device);	if (agent) {		agent_destroy(agent, FALSE);		device_set_agent(device, NULL);	}	adapter->devices = g_slist_remove(adapter->devices, device);	device_remove(conn, device);}struct btd_device *adapter_get_device(DBusConnection *conn,				struct adapter *adapter, const gchar *address){	struct btd_device *device;	debug("adapter_get_device(%s)", address);	if (!adapter)		return NULL;	device = adapter_find_device(adapter, address);	if (device)		return device;	return adapter_create_device(conn, adapter, address);}void remove_pending_device(struct adapter *adapter){	struct btd_device *device;	char address[18];	ba2str(&adapter->bonding->bdaddr, address);	device = adapter_find_device(adapter, address);	if (!device)		return;	if (device_is_temporary(device))		adapter_remove_device(adapter->bonding->conn, adapter, device);}static gboolean create_bonding_conn_complete(GIOChannel *io, GIOCondition cond,						struct adapter *adapter){	struct hci_request rq;	auth_requested_cp cp;	evt_cmd_status rp;	struct l2cap_conninfo cinfo;	socklen_t len;	int sk, dd, ret;	if (!adapter->bonding) {		/* If we come here it implies a bug somewhere */		debug("create_bonding_conn_complete: no pending bonding!");		g_io_channel_close(io);		g_io_channel_unref(io);		return FALSE;	}	if (cond & G_IO_NVAL) {		DBusMessage *reply;		reply = new_authentication_return(adapter->bonding->msg, 0x09);		g_dbus_send_message(adapter->bonding->conn, reply);		goto cleanup;	}	if (cond & (G_IO_HUP | G_IO_ERR)) {		debug("Hangup or error on bonding IO channel");		if (!adapter->bonding->auth_active)			error_connection_attempt_failed(adapter->bonding->conn,							adapter->bonding->msg,							ENETDOWN);		else			reply_authentication_failure(adapter->bonding);		goto failed;	}	sk = g_io_channel_unix_get_fd(io);	len = sizeof(ret);	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {		error("Can't get socket error: %s (%d)",				strerror(errno), errno);		error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,				errno);		goto failed;	}	if (ret != 0) {		if (adapter->bonding->auth_active)			reply_authentication_failure(adapter->bonding);		else			error_connection_attempt_failed(adapter->bonding->conn,							adapter->bonding->msg,							ret);		goto failed;	}	len = sizeof(cinfo);	if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {		error("Can't get connection info: %s (%d)",				strerror(errno), errno);		error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,				errno);		goto failed;	}	dd = hci_open_dev(adapter->dev_id);	if (dd < 0) {		DBusMessage *reply = no_such_adapter(adapter->bonding->msg);		g_dbus_send_message(adapter->bonding->conn, reply);		goto failed;	}	memset(&rp, 0, sizeof(rp));	memset(&cp, 0, sizeof(cp));	cp.handle = htobs(cinfo.hci_handle);	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_LINK_CTL;	rq.ocf    = OCF_AUTH_REQUESTED;	rq.cparam = &cp;	rq.clen   = AUTH_REQUESTED_CP_SIZE;	rq.rparam = &rp;	rq.rlen   = EVT_CMD_STATUS_SIZE;	rq.event  = EVT_CMD_STATUS;	if (hci_send_req(dd, &rq, 500) < 0) {		error("Unable to send HCI request: %s (%d)",					strerror(errno), errno);		error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,				errno);		hci_close_dev(dd);		goto failed;	}	if (rp.status) {		error("HCI_Authentication_Requested failed with status 0x%02x",				rp.status);		error_failed_errno(adapter->bonding->conn, adapter->bonding->msg,				bt_error(rp.status));		hci_close_dev(dd);		goto failed;	}	hci_close_dev(dd);	adapter->bonding->auth_active = 1;	adapter->bonding->io_id = g_io_add_watch(io,						G_IO_NVAL | G_IO_HUP | G_IO_ERR,						(GIOFunc) create_bonding_conn_complete,						adapter);	return FALSE;failed:	g_io_channel_close(io);	remove_pending_device(adapter);cleanup:	g_dbus_remove_watch(adapter->bonding->conn,				adapter->bonding->listener_id);	bonding_request_free(adapter->bonding);	adapter->bonding = NULL;	return FALSE;}static void cancel_auth_request(struct pending_auth_info *auth, int dev_id){	int dd;	if (auth->replied)		return;	dd = hci_open_dev(dev_id);	if (dd < 0) {		error("hci_open_dev: %s (%d)", strerror(errno), errno);		return;	}	switch (auth->type) {	case AUTH_TYPE_PINCODE:		hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY,				6, &auth->bdaddr);		break;	case AUTH_TYPE_CONFIRM:		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_CONFIRM_NEG_REPLY,				6, &auth->bdaddr);		break;	case AUTH_TYPE_PASSKEY:		hci_send_cmd(dd, OGF_LINK_CTL, OCF_USER_PASSKEY_NEG_REPLY,				6, &auth->bdaddr);		break;	case AUTH_TYPE_NOTIFY:		/* User Notify doesn't require any reply */		break;	}	auth->replied = TRUE;	hci_close_dev(dd);}static void create_bond_req_exit(void *user_data){	struct adapter *adapter = user_data;	struct pending_auth_info *auth;	debug("CreateConnection requestor exited before bonding was completed");	auth = adapter_find_auth_request(adapter, &adapter->bonding->bdaddr);	if (auth) {		cancel_auth_request(auth, adapter->dev_id);		if (auth->agent)			agent_cancel(auth->agent);		adapter_remove_auth_request(adapter, &adapter->bonding->bdaddr);	}	remove_pending_device(adapter);	g_io_channel_close(adapter->bonding->io);	if (adapter->bonding->io_id)		g_source_remove(adapter->bonding->io_id);	bonding_request_free(adapter->bonding);	adapter->bonding = NULL;}static DBusMessage *create_bonding(DBusConnection *conn, DBusMessage *msg,				const char *address, const char *agent_path,				uint8_t capability, void *data){	char filename[PATH_MAX + 1];	char *str;	struct adapter *adapter = data;	struct bonding_request_info *bonding;

⌨️ 快捷键说明

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