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

📄 device.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	iconn->intr_sk = g_io_channel_unix_get_fd(chan);	err = hidp_connadd(&idev->src, &idev->dst,				iconn->ctrl_sk, iconn->intr_sk,					iconn->timeout, idev->name);	if (err < 0)		goto failed;	iconn->intr_watch = create_watch(iconn->intr_sk, intr_watch_cb, iconn);	iconn->ctrl_watch = create_watch(iconn->ctrl_sk, ctrl_watch_cb, iconn);	g_dbus_emit_signal(idev->conn, idev->path,			INPUT_DEVICE_INTERFACE, "Connected",			DBUS_TYPE_STRING, &iconn->uuid,			DBUS_TYPE_INVALID);	/* Replying to the requestor */	g_dbus_send_reply(idev->conn, iconn->pending_connect, DBUS_TYPE_INVALID);	goto cleanup;failed:	reply = connection_attempt_failed(iconn->pending_connect, -err);	g_dbus_send_message(idev->conn, reply);	iconn->intr_sk = -1;	iconn->ctrl_sk = -1;cleanup:	dbus_message_unref(iconn->pending_connect);	iconn->pending_connect = NULL;}static void control_connect_cb(GIOChannel *chan, int err, const bdaddr_t *src,			const bdaddr_t *dst, gpointer user_data){	struct input_conn *iconn = user_data;	struct input_device *idev = iconn->idev;	if (err < 0) {		error("connect(): %s (%d)", strerror(-err), -err);		goto failed;	}	/* Set HID control channel */	iconn->ctrl_sk = g_io_channel_unix_get_fd(chan);	/* Connect to the HID interrupt channel */	err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_INTR, 0,			interrupt_connect_cb, iconn);	if (err < 0) {		error("L2CAP connect failed:%s (%d)", strerror(-err), -err);		goto failed;	}	return;failed:	iconn->ctrl_sk = -1;	connection_attempt_failed(iconn->pending_connect, -err);	dbus_message_unref(iconn->pending_connect);	iconn->pending_connect = NULL;}static int fake_disconnect(struct input_conn *iconn){	struct fake_input *fake = iconn->fake;	if (!fake->io)		return -ENOTCONN;	g_io_channel_close(fake->io);	g_io_channel_unref(fake->io);	fake->io = NULL;	if (fake->uinput >= 0) {		ioctl(fake->uinput, UI_DEV_DESTROY);		close(fake->uinput);		fake->uinput = -1;	}	return 0;}static int is_connected(struct input_conn *iconn){	struct input_device *idev = iconn->idev;	struct fake_input *fake = iconn->fake;	struct hidp_conninfo ci;	int ctl;	/* Fake input */	if (fake)		return fake->flags & FI_FLAG_CONNECTED;	/* Standard HID */	ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);	if (ctl < 0)		return 0;	memset(&ci, 0, sizeof(ci));	bacpy(&ci.bdaddr, &idev->dst);	if (ioctl(ctl, HIDPGETCONNINFO, &ci) < 0) {		close(ctl);		return 0;	}	close(ctl);	if (ci.state != BT_CONNECTED)		return 0;	else		return 1;}static int connection_disconnect(struct input_conn *iconn, uint32_t flags){	struct input_device *idev = iconn->idev;	struct fake_input *fake = iconn->fake;	struct hidp_conndel_req req;	struct hidp_conninfo ci;	int ctl, err;	/* Fake input disconnect */	if (fake) {		err = fake->disconnect(iconn);		if (err == 0)			fake->flags &= ~FI_FLAG_CONNECTED;		return err;	}	/* Standard HID disconnect */	if (iconn->ctrl_sk >= 0) {		close(iconn->ctrl_sk);		iconn->ctrl_sk = -1;	}	if (iconn->intr_sk >= 0) {		close(iconn->intr_sk);		iconn->intr_sk = -1;	}	ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HIDP);	if (ctl < 0) {		error("Can't open HIDP control socket");		return -errno;	}	memset(&ci, 0, sizeof(ci));	bacpy(&ci.bdaddr, &idev->dst);	if ((ioctl(ctl, HIDPGETCONNINFO, &ci) < 0) ||				(ci.state != BT_CONNECTED)) {		errno = ENOTCONN;		goto fail;	}	memset(&req, 0, sizeof(req));	bacpy(&req.bdaddr, &idev->dst);	req.flags = flags;	if (ioctl(ctl, HIDPCONNDEL, &req) < 0) {		error("Can't delete the HID device: %s(%d)",				strerror(errno), errno);		goto fail;	}	close(ctl);	return 0;fail:	err = errno;	close(ctl);	errno = err;	return -err;}static int disconnect(struct input_device *idev, uint32_t flags){	struct input_conn *iconn = NULL;	GSList *l;	for (l = idev->connections; l; l = l->next) {		iconn = l->data;		if (is_connected(iconn))			break;	}	if (!iconn)		return ENOTCONN;	return connection_disconnect(iconn, flags);}/* * Input Device methods */static DBusMessage *device_connect(DBusConnection *conn,					DBusMessage *msg, void *data){	struct input_device *idev = data;	struct input_conn *iconn;	struct fake_input *fake;	const char *svc;	int err;	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc,						DBUS_TYPE_INVALID) == FALSE)		return NULL;	iconn = find_connection(idev->connections, svc);	if (!iconn)		return not_supported(msg);	if (iconn->pending_connect)		return in_progress(msg);	if (is_connected(iconn))		return already_connected(msg);	iconn->pending_connect = dbus_message_ref(msg);	fake = iconn->fake;	/* Fake input device */	if (fake) {		if (fake->connect(iconn) < 0) {			int err = errno;			const char *str = strerror(err);			error("Connect failed: %s(%d)", str, err);			dbus_message_unref(iconn->pending_connect);			iconn->pending_connect = NULL;			return connection_attempt_failed(msg, err);		}		fake->flags |= FI_FLAG_CONNECTED;		return NULL;	}	/* HID devices */	err = bt_l2cap_connect(&idev->src, &idev->dst, L2CAP_PSM_HIDP_CTRL,						0, control_connect_cb, iconn);	if (err < 0) {		error("L2CAP connect failed: %s(%d)", strerror(-err), -err);		dbus_message_unref(iconn->pending_connect);		iconn->pending_connect = NULL;		return connection_attempt_failed(msg, -err);	}	return NULL;}static DBusMessage *create_errno_message(DBusMessage *msg, int err){	return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",							strerror(err));}static DBusMessage *device_disconnect(DBusConnection *conn,						DBusMessage *msg, void *data){	struct input_device *idev = data;	int err;	err = disconnect(idev, 0);	if (err < 0)		return create_errno_message(msg, -err);	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);}static DBusMessage *device_is_connected(DBusConnection *conn,						DBusMessage *msg, void *data){	struct input_device *idev = data;	dbus_bool_t connected = FALSE;	GSList *l;	for (l = idev->connections; l; l = l->next) {		struct input_conn *iconn = l->data;		if (!is_connected(iconn))			continue;		connected = TRUE;		break;	}	return g_dbus_create_reply(msg, DBUS_TYPE_BOOLEAN, &connected,							DBUS_TYPE_INVALID);}static void device_unregister(void *data){	struct input_device *idev = data;	info("Unregistered interface %s on path %s", INPUT_DEVICE_INTERFACE, idev->path);	/* Disconnect if applied */	disconnect(idev, (1 << HIDP_VIRTUAL_CABLE_UNPLUG));	devices = g_slist_remove(devices, idev);	input_device_free(idev);}static GDBusMethodTable device_methods[] = {	{ "Connect",		"s",	"",	device_connect,						G_DBUS_METHOD_FLAG_ASYNC },	{ "Disconnect",		"",	"",	device_disconnect	},	{ "IsConnected",	"",	"b",	device_is_connected	},	{ }};static GDBusSignalTable device_signals[] = {	{ "Connected",		"ss"	},	{ "Disconnected",	"s"	},	{ }};static struct input_device *input_device_new(DBusConnection *conn,					const char *path, bdaddr_t *src,					bdaddr_t *dst){	struct input_device *idev;	idev = g_new0(struct input_device, 1);	bacpy(&idev->src, src);	bacpy(&idev->dst, dst);	idev->path = g_strdup(path);	read_device_name(src, dst, &idev->name);	idev->conn = dbus_connection_ref(conn);	if (g_dbus_register_interface(conn, idev->path, INPUT_DEVICE_INTERFACE,					device_methods, device_signals, NULL,					idev, device_unregister) == FALSE) {		error("Failed to register interface %s on path %s",			INPUT_DEVICE_INTERFACE, path);		input_device_free(idev);		return NULL;	}	info("Registered interface %s on path %s", INPUT_DEVICE_INTERFACE,		idev->path);	return idev;}static struct input_conn *input_conn_new(struct input_device *idev,					const char *uuid, const char *alias,					int timeout){	struct input_conn *iconn;	iconn = g_new0(struct input_conn, 1);	iconn->ctrl_sk = -1;	iconn->intr_sk = -1;	iconn->timeout = timeout;	iconn->uuid = g_strdup(uuid);	iconn->alias = g_strdup(alias);	iconn->idev = idev;	return iconn;}int input_device_register(DBusConnection *conn, const char *path,			bdaddr_t *src, bdaddr_t *dst, const char *uuid,			int timeout){	struct input_device *idev;	struct input_conn *iconn;	idev = find_device_by_path(devices, path);	if (!idev) {		idev = input_device_new(conn, path, src, dst);		if (!idev)			return -EINVAL;		devices = g_slist_append(devices, idev);	}	iconn = input_conn_new(idev, uuid, "hid", timeout);	if (!iconn)		return -EINVAL;	idev->connections = g_slist_append(idev->connections, iconn);	return 0;}int fake_input_register(DBusConnection *conn, const char *path, bdaddr_t *src,			bdaddr_t *dst, const char *uuid, uint8_t channel){	struct input_device *idev;	struct input_conn *iconn;	idev = find_device_by_path(devices, path);	if (!idev) {		idev = input_device_new(conn, path, src, dst);		if (!idev)			return -EINVAL;		devices = g_slist_append(devices, idev);	}	iconn = input_conn_new(idev, uuid, "hsp", 0);	if (!iconn)		return -EINVAL;	iconn->fake = g_new0(struct fake_input, 1);	iconn->fake->ch = channel;	iconn->fake->connect = rfcomm_connect;	iconn->fake->disconnect = fake_disconnect;	idev->connections = g_slist_append(idev->connections, iconn);	return 0;}static struct input_device *find_device(const bdaddr_t *src,					const bdaddr_t *dst){	GSList *list;	for (list = devices; list != NULL; list = list->next) {		struct input_device *idev = list->data;		if (!bacmp(&idev->src, src) && !bacmp(&idev->dst, dst))			return idev;	}	return NULL;}int input_device_unregister(const char *path, const char *uuid){	struct input_device *idev;	struct input_conn *iconn;	idev = find_device_by_path(devices, path);	if (idev == NULL)		return -EINVAL;	iconn = find_connection(idev->connections, uuid);	if (iconn == NULL)		return -EINVAL;	if (iconn->pending_connect) {		/* Pending connection running */		return -EBUSY;	}	del_stored_device_info(&idev->src, &idev->dst);	idev->connections = g_slist_remove(idev->connections, iconn);	input_conn_free(iconn);	if (idev->connections)		return 0;	g_dbus_unregister_interface(idev->conn, path, INPUT_DEVICE_INTERFACE);	return 0;}gboolean input_device_is_registered(bdaddr_t *src, bdaddr_t *dst){	struct input_device *idev = find_device(src, dst);	return idev ? TRUE : FALSE;}int input_device_set_channel(const bdaddr_t *src, const bdaddr_t *dst, int psm, int nsk){	struct input_device *idev = find_device(src, dst);	struct input_conn *iconn;	if (!idev)		return -ENOENT;	iconn = find_connection(idev->connections, "hid");	if (!iconn)		return -ENOENT;	switch (psm) {	case L2CAP_PSM_HIDP_CTRL:		iconn->ctrl_sk = nsk;		break;	case L2CAP_PSM_HIDP_INTR:		iconn->intr_sk = nsk;		break;	}	return 0;}int input_device_close_channels(const bdaddr_t *src, const bdaddr_t *dst){	struct input_device *idev = find_device(src, dst);	struct input_conn *iconn;	if (!idev)		return -ENOENT;	iconn = find_connection(idev->connections, "hid");	if (!iconn)		return -ENOENT;	if (iconn->ctrl_sk >= 0) {		close(iconn->ctrl_sk);		iconn->ctrl_sk = -1;	}	if (iconn->intr_sk >= 0) {		close(iconn->intr_sk);		iconn->intr_sk = -1;	}	return 0;}int input_device_connadd(bdaddr_t *src, bdaddr_t *dst){	struct input_device *idev;	struct input_conn *iconn;	int err;	idev = find_device(src, dst);	if (!idev)		return -ENOENT;	iconn = find_connection(idev->connections, "hid");	if (!iconn)		return -ENOENT;	err = hidp_connadd(src, dst, iconn->ctrl_sk, iconn->intr_sk,				iconn->timeout, idev->name);	if (err < 0)		goto error;	iconn->intr_watch = create_watch(iconn->intr_sk, intr_watch_cb, iconn);	iconn->ctrl_watch = create_watch(iconn->ctrl_sk, ctrl_watch_cb, iconn);	g_dbus_emit_signal(idev->conn, idev->path,			INPUT_DEVICE_INTERFACE, "Connected",			DBUS_TYPE_STRING, &iconn->uuid,			DBUS_TYPE_INVALID);	return 0;error:	close(iconn->ctrl_sk);	close(iconn->intr_sk);	iconn->ctrl_sk = -1;	iconn->intr_sk = -1;	return err;}

⌨️ 快捷键说明

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