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

📄 manager.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 2 页
字号:
	dbus_error_init(&derr);	if (dbus_set_error_from_message(&derr, reply)) {		/* FIXME : to not try to be clever about		   hcid error but forward as is to the user */		if (dbus_error_has_name(&derr,			"org.bluez.Error.ConnectionAttemptFailed"))			error_connection_attempt_failed(pr->conn,					pr->msg, EIO);		else			error_not_supported(pr->conn, pr->msg);		error("GetRemoteServiceHandles: %s(%s)",					derr.name, derr.message);		goto fail;	}	if (!dbus_message_get_args(reply, &derr,				DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len,				DBUS_TYPE_INVALID)) {		error_not_supported(pr->conn, pr->msg);		error("%s: %s", derr.name, derr.message);		goto fail;	}	if (len == 0) {		error_not_supported(pr->conn, pr->msg);		error("HID record handle not found");		goto fail;	}	if (get_record(pr, *phandle, hid_record_reply) < 0) {		error_not_supported(pr->conn, pr->msg);		error("HID service attribute request failed");		goto fail;	} else {		/* Wait record reply */		goto done;	}fail:	dbus_error_free(&derr);	pending_req_free(pr);done:	dbus_message_unref(reply);}static void pnp_record_reply(DBusPendingCall *call, void *data){	DBusMessage *reply = dbus_pending_call_steal_reply(call);	struct pending_req *pr = data;	DBusError derr;	uint8_t *rec_bin;	int len, scanned;	dbus_error_init(&derr);	if (dbus_set_error_from_message(&derr, reply)) {		/* FIXME : to not try to be clever about		   hcid error but forward as is to the user */		if (dbus_error_has_name(&derr,			"org.bluez.Error.ConnectionAttemptFailed"))			error_connection_attempt_failed(pr->conn, pr->msg,					EIO);		else			error_not_supported(pr->conn, pr->msg);		error("GetRemoteServiceRecord: %s(%s)",				derr.name, derr.message);		goto fail;	}	if (!dbus_message_get_args(reply, &derr,				DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len,				DBUS_TYPE_INVALID)) {		error_not_supported(pr->conn, pr->msg);		error("%s: %s", derr.name, derr.message);		goto fail;	}	if (len == 0) {		error_not_supported(pr->conn, pr->msg);		error("Invalid PnP service record length");		goto fail;	}	pr->pnp_rec = sdp_extract_pdu(rec_bin, &scanned);	if (get_handles(pr, hid_uuid, hid_handle_reply) < 0) {		error_not_supported(pr->conn, pr->msg);		error("HID service search request failed");		goto fail;	} else {		/* Wait handle reply */		goto done;	}fail:	dbus_error_free(&derr);	pending_req_free(pr);done:	dbus_message_unref(reply);}static void pnp_handle_reply(DBusPendingCall *call, void *data){	DBusMessage *reply = dbus_pending_call_steal_reply(call);	struct pending_req *pr = data;	DBusError derr;	uint32_t *phandle;	int len;	dbus_error_init(&derr);	if (dbus_set_error_from_message(&derr, reply)) {		/* FIXME : to not try to be clever about		   hcid error but forward as is to the user */		if (dbus_error_has_name(&derr,			"org.bluez.Error.ConnectionAttemptFailed"))			error_connection_attempt_failed(pr->conn, pr->msg,					 EIO);		else			error_not_supported(pr->conn, pr->msg);		error("GetRemoteServiceHandles: %s(%s)",				derr.name, derr.message);		goto fail;	}	if (!dbus_message_get_args(reply, &derr,				DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len,				DBUS_TYPE_INVALID)) {		error_not_supported(pr->conn, pr->msg);		error("%s: %s", derr.name, derr.message);		goto fail;	}	if (len == 0) {		/* PnP is optional: Ignore it and request the HID handle  */		if (get_handles(pr, hid_uuid, hid_handle_reply) < 0) {			error_not_supported(pr->conn, pr->msg);			error("HID service search request failed");			goto fail;		}	} else {		/* Request PnP record */		if (get_record(pr, *phandle, pnp_record_reply) < 0) {			error_not_supported(pr->conn, pr->msg);			error("PnP service attribute request failed");			goto fail;		}	}	/* Wait HID handle reply or PnP record reply */	goto done;fail:	dbus_error_free(&derr);	pending_req_free(pr);done:	dbus_message_unref(reply);}static void headset_record_reply(DBusPendingCall *call, void *data){	DBusMessage *reply = dbus_pending_call_steal_reply(call);	DBusMessage *pr_reply;	DBusError derr;	struct pending_req *pr = data;	uint8_t *rec_bin;	sdp_record_t *rec;	sdp_list_t *protos;	const char *path;	int len, scanned;	uint8_t ch;	dbus_error_init(&derr);	if (dbus_set_error_from_message(&derr, reply)) {		/* FIXME : to not try to be clever about		   hcid error but forward as is to the user */		if (dbus_error_has_name(&derr,			"org.bluez.Error.ConnectionAttemptFailed"))			error_connection_attempt_failed(pr->conn, pr->msg,					EIO);		else			error_not_supported(pr->conn, pr->msg);		error("GetRemoteServiceRecord: %s(%s)",				derr.name, derr.message);		goto fail;	}	if (!dbus_message_get_args(reply, &derr,				DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len,				DBUS_TYPE_INVALID)) {		error_not_supported(pr->conn, pr->msg);		error("%s: %s", derr.name, derr.message);		goto fail;	}	if (len == 0) {		error_not_supported(pr->conn, pr->msg);		error("Invalid headset service record length");		goto fail;	}	rec = sdp_extract_pdu(rec_bin, &scanned);	if (!rec) {		error_not_supported(pr->conn, pr->msg);		goto fail;	}	if (sdp_get_access_protos(rec, &protos) < 0) {		error_not_supported(pr->conn, pr->msg);		goto fail;	}	ch = sdp_get_proto_port(protos, RFCOMM_UUID);	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);	sdp_list_free(protos, NULL);	sdp_record_free(rec);	if (ch <= 0) {		error_not_supported(pr->conn, pr->msg);		error("Invalid RFCOMM channel");		goto fail;	}	/* FIXME: Store the fake input data */	if (fake_input_register(pr->conn, &pr->src, &pr->dst, ch, &path) < 0) {		error("D-Bus path registration failed:%s", path);		error_failed(pr->conn, pr->msg, "Path registration failed");		goto fail;	}	dbus_connection_emit_signal(pr->conn, INPUT_PATH,			INPUT_MANAGER_INTERFACE, "DeviceCreated",			DBUS_TYPE_STRING, &path,			DBUS_TYPE_INVALID);	device_paths = g_slist_append(device_paths, g_strdup(path));	pr_reply = dbus_message_new_method_return(pr->msg);	dbus_message_append_args(pr_reply,			DBUS_TYPE_STRING, &path,			DBUS_TYPE_INVALID);	send_message_and_unref(pr->conn, pr_reply);fail:	dbus_error_free(&derr);	pending_req_free(pr);	dbus_message_unref(reply);}static void headset_handle_reply(DBusPendingCall *call, void *data){	DBusMessage *reply = dbus_pending_call_steal_reply(call);	struct pending_req *pr = data;	DBusError derr;	uint32_t *phandle;	int len;	dbus_error_init(&derr);	if (dbus_set_error_from_message(&derr, reply)) {		/* FIXME : to not try to be clever about		   hcid error but forward as is to the user */		if (dbus_error_has_name(&derr,			"org.bluez.Error.ConnectionAttemptFailed"))			error_connection_attempt_failed(pr->conn, pr->msg, 					EIO);		else			error_not_supported(pr->conn, pr->msg);		error("GetRemoteServiceHandles: %s(%s)",				derr.name, derr.message);		goto fail;	}	if (!dbus_message_get_args(reply, &derr,				DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, &len,				DBUS_TYPE_INVALID)) {		error_not_supported(pr->conn, pr->msg);		error("%s: %s", derr.name, derr.message);		goto fail;	}	if (len == 0) {		error_not_supported(pr->conn, pr->msg);		error("Headset record handle not found");		goto fail;	}	if (get_record(pr, *phandle, headset_record_reply) < 0) {		error_not_supported(pr->conn, pr->msg);		error("Headset service attribute request failed");		goto fail;	} else {		/* Wait record reply */		goto done;	}fail:	dbus_error_free(&derr);	pending_req_free(pr);done:	dbus_message_unref(reply);}static DBusHandlerResult create_device(DBusConnection *conn,					DBusMessage *msg, void *data){	struct pending_req *pr;	DBusError derr;	const char *addr;	bdaddr_t src, dst;	uint32_t cls = 0;	int dev_id;	dbus_error_init(&derr);	if (!dbus_message_get_args(msg, &derr,				DBUS_TYPE_STRING, &addr,				DBUS_TYPE_INVALID)) {		error_invalid_arguments(conn, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	/* Get the default adapter */	dev_id = hci_get_route(NULL);	if (dev_id < 0) {		error("Bluetooth adapter not available");		return error_failed(conn, msg, "Adapter not available");	}	if (hci_devba(dev_id, &src) < 0) {		error("Can't get local adapter device info");		return error_failed(conn, msg, "Adapter not available");	}	str2ba(addr, &dst);	if (input_device_is_registered(&src, &dst))		return error_already_exists(conn, msg, "Input Already exists");	if (read_device_class(&src, &dst, &cls) < 0) {		error("Device class not available");		return error_not_supported(conn, msg);	}	pr = pending_req_new(conn, msg, &src, &dst);	if (!pr)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	switch (cls & 0x1f00) {		case 0x0500: /* Peripheral */		case 0x0200: /* Phone */			if (get_handles(pr, pnp_uuid, pnp_handle_reply) < 0) {				pending_req_free(pr);				return error_not_supported(conn, msg);			}			break;		case 0x0400: /* Fake input */			if (get_handles(pr, headset_uuid,						headset_handle_reply) < 0) {				pending_req_free(pr);				return error_not_supported(conn, msg);			}			break;		default:			pending_req_free(pr);			return error_not_supported(conn, msg);	}	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult remove_device(DBusConnection *conn,					DBusMessage *msg, void *data){	DBusMessage *reply;	DBusError derr;	GSList *l;	const char *path;	int err;	dbus_error_init(&derr);	if (!dbus_message_get_args(msg, &derr,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_INVALID)) {		error_invalid_arguments(conn, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	l = g_slist_find_custom(device_paths, path, (GCompareFunc) strcmp);	if (!l)		return error_does_not_exist(conn, msg, "Input doesn't exist");	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	err = input_device_unregister(conn, path);	if (err < 0) {		dbus_message_unref(reply);		return error_failed_errno(conn, msg, -err);	}	g_free(l->data);	device_paths = g_slist_remove(device_paths, l->data);	return send_message_and_unref(conn, reply);}static DBusHandlerResult list_devices(DBusConnection *conn,					DBusMessage *msg, void *data){	DBusMessageIter iter, iter_array;	DBusMessage *reply;	GSList *paths;	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_TYPE_STRING_AS_STRING, &iter_array);	for (paths = device_paths; paths != NULL; paths = paths->next) {		const char *ppath = paths->data;		dbus_message_iter_append_basic(&iter_array,					DBUS_TYPE_STRING, &ppath);	}	dbus_message_iter_close_container(&iter, &iter_array);	return send_message_and_unref(conn, reply);}static void manager_unregister(DBusConnection *conn, void *data){	info("Unregistered manager path");	g_slist_foreach(device_paths, (GFunc) free, NULL);	g_slist_free(device_paths);}/* * Stored inputs registration functions */static void stored_input(char *key, char *value, void *data){	const char *path;	struct hidp_connadd_req hidp;	bdaddr_t dst, *src = data;	str2ba(key, &dst);	memset(&hidp, 0, sizeof(hidp));	if (parse_stored_device_info(value, &hidp) < 0)		return;	/*	 * Repeated entries for the same remote device are	 * acceptable since the source is different.	 */	if (input_device_register(connection, src, &dst, &hidp, &path) < 0)		goto cleanup;	device_paths = g_slist_append(device_paths, g_strdup(path));cleanup:	if (hidp.rd_data)		g_free(hidp.rd_data);}/* hidd to input transition function */static void stored_hidd(char *key, char *value, void *data){	struct hidp_connadd_req hidp;	char *str, filename[PATH_MAX + 1], addr[18];	bdaddr_t dst, *src = data;	ba2str(src, addr);	create_name(filename, PATH_MAX, STORAGEDIR, addr, "input");	str = textfile_get(filename, key);	if (str) {		/* Skip: entry found in input file */		free(str);		return;	}	memset(&hidp, 0, sizeof(hidp));	if (parse_stored_hidd(value, &hidp) < 0)		return;	str2ba(key, &dst);	store_device_info(src, &dst, &hidp);	if (hidp.rd_data)		g_free(hidp.rd_data);}static void register_stored_inputs(void){	char dirname[PATH_MAX + 1];	char filename[PATH_MAX + 1];	struct dirent *de;	DIR *dir;	bdaddr_t src;	snprintf(dirname, PATH_MAX, "%s", STORAGEDIR);	dir = opendir(dirname);	if (!dir)		return;	while ((de = readdir(dir)) != NULL) {		if (!isdigit(de->d_name[0]))			continue;		str2ba(de->d_name, &src);		/* move the hidd entries to the input storage */		create_name(filename, PATH_MAX, STORAGEDIR,						de->d_name, "hidd");		textfile_foreach(filename, stored_hidd, &src);		/* load the input stored devices */		create_name(filename, PATH_MAX, STORAGEDIR,						de->d_name, "input");		textfile_foreach(filename, stored_input, &src);	}	closedir(dir);}static DBusMethodVTable manager_methods[] = {	{ "ListDevices",		list_devices,	"",	"as"	},	{ "CreateDevice",		create_device,	"s",	"s"	},	{ "CreateSecureDevice",		create_device,	"s",	"s"	},	{ "RemoveDevice",		remove_device,	"s",	""	},	{ NULL, NULL, NULL, NULL },};static DBusSignalVTable manager_signals[] = {	{ "DeviceCreated",	"s"	},	{ "DeviceRemoved",	"s"	},	{ NULL, NULL }};int input_init(DBusConnection *conn){	dbus_connection_set_exit_on_disconnect(conn, TRUE);	if (!dbus_connection_create_object_path(conn, INPUT_PATH,						NULL, manager_unregister)) {		error("D-Bus failed to register %s path", INPUT_PATH);		return -1;	}	if (!dbus_connection_register_interface(conn, INPUT_PATH,						INPUT_MANAGER_INTERFACE,						manager_methods,						manager_signals, NULL)) {		error("Failed to register %s interface to %s",				INPUT_MANAGER_INTERFACE, INPUT_PATH);		dbus_connection_destroy_object_path(connection, INPUT_PATH);		return -1;	}	connection = dbus_connection_ref(conn);	info("Registered input manager path:%s", INPUT_PATH);	/* Register well known HID devices */	register_stored_inputs();	server_start(connection);	return 0;}void input_exit(void){	dbus_connection_destroy_object_path(connection, INPUT_PATH);	server_stop();	dbus_connection_unref(connection);	connection = NULL;}

⌨️ 快捷键说明

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