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

📄 manager.c

📁 基于LINUX内核驱动的开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	sdp_data = g_new0(struct audio_sdp_data, 1);	if (msg)		sdp_data->msg = dbus_message_ref(msg);	sdp_data->device = device;	sdp_data->cb = cb;	sdp_data->cb_data = user_data;	return get_handles(GENERIC_AUDIO_UUID, sdp_data);}struct device *manager_device_connected(bdaddr_t *bda, const char *uuid){	struct device *device;	const char *path;	gboolean headset = FALSE, created = FALSE;	device = manager_find_device(bda, NULL, FALSE);	if (!device) {		device = create_device(bda);		if (!device)			return NULL;		if (!add_device(device, TRUE)) {			destroy_device(device);			return NULL;		}		created = TRUE;	}	if (!strcmp(uuid, HSP_AG_UUID) || !strcmp(uuid, HFP_AG_UUID)) {		if (device->headset)			return device;		device->headset = headset_init(device, NULL, 0);		if (!device->headset)			return NULL;		headset = TRUE;	} else if (!strcmp(uuid, A2DP_SOURCE_UUID)) {		if (device->sink)			return device;		device->sink = sink_init(device);		if (!device->sink)			return NULL;	} else if (!strcmp(uuid, AVRCP_TARGET_UUID)) {		if (device->control)			return device;		device->control = control_init(device);		if (!device->control)			return NULL;	} else		return NULL;	path = device->path;	if (created) {		dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DeviceCreated",						DBUS_TYPE_STRING, &path,						DBUS_TYPE_INVALID);		resolve_services(NULL, device, NULL, NULL);	}	if (headset)		dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"HeadsetCreated",						DBUS_TYPE_STRING, &path,						DBUS_TYPE_INVALID);	if (headset && !default_hs) {		default_hs = device;		dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DefaultHeadsetChanged",						DBUS_TYPE_STRING, &path,						DBUS_TYPE_INVALID);	}	if (!default_dev) {		default_dev = device;		dbus_connection_emit_signal(connection, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DefaultDeviceChanged",						DBUS_TYPE_STRING, &path,						DBUS_TYPE_INVALID);	}	return device;}gboolean manager_create_device(bdaddr_t *bda, create_dev_cb_t cb,				void *user_data){	struct device *dev;	dev = create_device(bda);	if (!dev)		return FALSE;	resolve_services(NULL, dev, cb, user_data);	return TRUE;}static DBusHandlerResult am_create_device(DBusConnection *conn,						DBusMessage *msg,						void *data){	const char *address, *path;	bdaddr_t bda;	struct device *device;	DBusMessage *reply;	DBusError derr;	dbus_error_init(&derr);	dbus_message_get_args(msg, &derr,				DBUS_TYPE_STRING, &address,				DBUS_TYPE_INVALID);	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(connection, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	str2ba(address, &bda);	device = manager_find_device(&bda, NULL, FALSE);	if (!device) {		device = create_device(&bda);		return resolve_services(msg, device, NULL, NULL);	}	path = device->path;	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply, DBUS_TYPE_STRING, &path,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult am_list_devices(DBusConnection *conn,						DBusMessage *msg,						void *data){	DBusMessageIter iter, array_iter;	DBusMessage *reply;	DBusError derr;	GSList *l;	gboolean hs_only = FALSE;	dbus_error_init(&derr);	if (dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,					"ListHeadsets"))		hs_only = TRUE;	else		hs_only = FALSE;	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, &array_iter);	for (l = devices; l != NULL; l = l->next) {		struct device *device = l->data;		if (hs_only && !device->headset)			continue;		dbus_message_iter_append_basic(&array_iter,						DBUS_TYPE_STRING, &device->path);	}	dbus_message_iter_close_container(&iter, &array_iter);	return send_message_and_unref(connection, reply);}static gint device_path_cmp(gconstpointer a, gconstpointer b){	const struct device *device = a;	const char *path = b;	return strcmp(device->path, path);}static DBusHandlerResult am_remove_device(DBusConnection *conn,						DBusMessage *msg,						void *data){	DBusError derr;	DBusMessage *reply;	GSList *match;	const char *path;	struct device *device;	dbus_error_init(&derr);	if (!dbus_message_get_args(msg, &derr,					DBUS_TYPE_STRING, &path,					DBUS_TYPE_INVALID)) {		error_invalid_arguments(connection, msg, derr.message);		return DBUS_HANDLER_RESULT_HANDLED;	}	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(connection, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	match = g_slist_find_custom(devices, path, device_path_cmp);	if (!match)		return error_device_does_not_exist(connection, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	device = match->data;	device_remove_stored(device);	remove_device(device);	/* Fallback to a valid default */	if (default_dev == NULL) {		const char *param;		GSList *l;		default_dev = manager_find_device(BDADDR_ANY, NULL, TRUE);		if (!default_dev && devices) {			l = devices;			default_dev = (g_slist_last(l))->data;		}		param = default_dev ? default_dev->path : "";		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DefaultHeadsetChanged",						DBUS_TYPE_STRING, &param,						DBUS_TYPE_INVALID);		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DefaultDeviceChanged",						DBUS_TYPE_STRING, &param,						DBUS_TYPE_INVALID);		if (default_dev)			device_store(default_dev, TRUE);	}	dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,					AUDIO_MANAGER_INTERFACE,					"HeadsetRemoved",					DBUS_TYPE_STRING, &path,					DBUS_TYPE_INVALID);	dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,					AUDIO_MANAGER_INTERFACE,					"DeviceRemoved",					DBUS_TYPE_STRING, &path,					DBUS_TYPE_INVALID);	return send_message_and_unref(connection, reply);}static DBusHandlerResult am_find_by_addr(DBusConnection *conn,						DBusMessage *msg,						void *data){	const char *address;	DBusMessage *reply;	DBusError derr;	struct device *device;	bdaddr_t bda;	dbus_error_init(&derr);	dbus_message_get_args(msg, &derr,				DBUS_TYPE_STRING, &address,				DBUS_TYPE_INVALID);	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(connection, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	str2ba(address, &bda);	device = manager_find_device(&bda, NULL, FALSE);	if (!device)		return error_device_does_not_exist(conn, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply, DBUS_TYPE_STRING, &device->path,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult am_default_device(DBusConnection *conn,						DBusMessage *msg,						void *data){	DBusMessage *reply;	if (!default_dev)		return error_device_does_not_exist(connection, msg);	if (default_dev->headset == NULL &&		dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,							"DefaultHeadset"))		return error_device_does_not_exist(connection, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_dev->path,					DBUS_TYPE_INVALID);	return send_message_and_unref(connection, reply);}static DBusHandlerResult am_change_default_device(DBusConnection *conn,							DBusMessage *msg,							void *data){	DBusError derr;	DBusMessage *reply;	GSList *match;	const char *path;	struct device *device;	dbus_error_init(&derr);	if (!dbus_message_get_args(msg, &derr,					DBUS_TYPE_STRING, &path,					DBUS_TYPE_INVALID)) {		error_invalid_arguments(connection, msg, derr.message);		return DBUS_HANDLER_RESULT_HANDLED;	}	if (dbus_error_is_set(&derr)) {		error_invalid_arguments(connection, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	match = g_slist_find_custom(devices, path, device_path_cmp);	if (!match)		return error_device_does_not_exist(connection, msg);	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	device = match->data;	if (!dbus_message_is_method_call(msg, AUDIO_MANAGER_INTERFACE,		"ChangeDefaultHeadset"))		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DefaultDeviceChanged",						DBUS_TYPE_STRING, &device->path,						DBUS_TYPE_INVALID);	else if (device->headset)		dbus_connection_emit_signal(conn, AUDIO_MANAGER_PATH,						AUDIO_MANAGER_INTERFACE,						"DefaultHeadsetChanged",						DBUS_TYPE_STRING, &device->path,						DBUS_TYPE_INVALID);	else		return error_device_does_not_exist(connection, msg);	default_dev = device;	device_store(device, TRUE);	return send_message_and_unref(connection, reply);}static DBusMethodVTable manager_methods[] = {	{ "CreateDevice",		am_create_device,		"s",	"s"		},	{ "RemoveDevice",		am_remove_device,		"s",	""		},	{ "ListDevices",		am_list_devices,		"",	"as"		},	{ "DefaultDevice",		am_default_device,		"",	"s"		},	{ "ChangeDefaultDevice",	am_change_default_device,		"s",	""		},	{ "CreateHeadset",		am_create_device,		"s",	"s"		},	{ "RemoveHeadset",		am_remove_device,		"s",	""		},	{ "ListHeadsets",		am_list_devices,		"",	"as"		},	{ "FindDeviceByAddress",	am_find_by_addr,		"s",	"s"		},	{ "DefaultHeadset",		am_default_device,		"",	"s"		},	{ "ChangeDefaultHeadset",	am_change_default_device,		"s",	""		},	{ NULL, NULL, NULL, NULL },};static DBusSignalVTable manager_signals[] = {	{ "DeviceCreated",		"s"	},	{ "DeviceRemoved",		"s"	},	{ "HeadsetCreated",		"s"	},	{ "HeadsetRemoved",		"s"	},	{ "DefaultDeviceChanged",	"s"	},	{ "DefaultHeadsetChanged",	"s"	},	{ NULL, NULL }};static void parse_stored_devices(char *key, char *value, void *data){	bdaddr_t *src = data;	struct device *device;	bdaddr_t dst;	if (!key || !value || strcmp(key, "default") == 0)		return;	str2ba(key, &dst);	device = manager_find_device(&dst, NULL, FALSE);	if (device)		return;	info("Loading device %s (%s)", key, value);	device = create_device(&dst);	if (!device)		return;	/* Change storage to source adapter */	bacpy(&device->store, src);	if (enabled.headset && strstr(value, "headset"))		device->headset = headset_init(device, NULL, 0);	if (enabled.sink && strstr(value, "sink"))		device->sink = sink_init(device);	if (enabled.control && strstr(value, "control"))		device->control = control_init(device);	add_device(device, FALSE);}static void register_devices_stored(const char *adapter){	char filename[PATH_MAX + 1];	struct stat st;	struct device *device;	bdaddr_t default_src;	bdaddr_t dst;	bdaddr_t src;	char *addr;	int dev_id;	create_name(filename, PATH_MAX, STORAGEDIR, adapter, "audio");	str2ba(adapter, &src);	if (stat(filename, &st) < 0)		return;	if (!(st.st_mode & __S_IFREG))		return;	textfile_foreach(filename, parse_stored_devices, &src);	bacpy(&default_src, BDADDR_ANY);	dev_id = hci_get_route(&default_src);	if (dev_id < 0 || hci_devba(dev_id, &default_src) < 0)		return;	if (bacmp(&default_src, &src) != 0)		return;	addr = textfile_get(filename, "default");	if (!addr)		return;	str2ba(addr, &dst);	device = manager_find_device(&dst, NULL, FALSE);	if (device) {		info("Setting %s as default device", addr);		default_dev = device;	}	free(addr);}static void register_stored(void){	char dirname[PATH_MAX + 1];	struct dirent *de;	DIR *dir;	snprintf(dirname, PATH_MAX, "%s", STORAGEDIR);	dir = opendir(dirname);	if (!dir)		return;	while ((de = readdir(dir)) != NULL) {		if (!isdigit(de->d_name[0]))			continue;		/* Device objects */		register_devices_stored(de->d_name);	}	closedir(dir);}static void manager_unregister(DBusConnection *conn, void *data){	info("Unregistered manager path");	if (devices) {		g_slist_foreach(devices, (GFunc) remove_device, NULL);		g_slist_free(devices);		devices = NULL;	}}static int hsp_ag_record(sdp_buf_t *buf, uint8_t ch){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;	uuid_t l2cap_uuid, rfcomm_uuid;	sdp_profile_desc_t profile;	sdp_list_t *aproto, *proto[2];	sdp_record_t record;	sdp_data_t *channel;	int ret;	memset(&record, 0, sizeof(sdp_record_t));	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);	root = sdp_list_append(0, &root_uuid);	sdp_set_browse_groups(&record, root);	sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);	svclass_id = sdp_list_append(0, &svclass_uuid);	sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);	svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);	sdp_set_service_classes(&record, svclass_id);	sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);	profile.version = 0x0100;	pfseq = sdp_list_append(0, &profile);	sdp_set_profile_descs(&record, pfseq);	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);	proto[0] = sdp_list_append(0, &l2cap_uuid);	apseq = sdp_list_append(0, proto[0]);	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);	proto[1] = sdp_list_append(0, &rfcomm_uuid);	channel = sdp_data_alloc(SDP_UINT8, &ch);	proto[1] = sdp_list_append(proto[1], channel);	apseq = sdp_list_append(apseq, proto[1]);	aproto = sdp_list_append(0, apseq);	sdp_set_access_protos(&record, aproto);	sdp_set_info_attr(&record, "Headset Audio Gateway", 0, 0);	if (sdp_gen_record_pdu(&record, buf) < 0)		ret = -1;	else		ret = 0;	sdp_data_free(channel);	sdp_list_free(proto[0], 0);	sdp_list_free(proto[1], 0);	sdp_list_free(apseq, 0);	sdp_list_free(pfseq, 0);	sdp_list_free(aproto, 0);	sdp_list_free(root, 0);	sdp_list_free(svclass_id, 0);	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);	sdp_list_free(record.pattern, free);	return ret;}static int hfp_ag_record(sdp_buf_t *buf, uint8_t ch, uint32_t feat){	sdp_list_t *svclass_id, *pfseq, *apseq, *root;	uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;	uuid_t l2cap_uuid, rfcomm_uuid;	sdp_profile_desc_t profile;	sdp_list_t *aproto, *proto[2];	sdp_record_t record;	sdp_data_t *channel, *features;	uint8_t netid = 0x01;	uint16_t sdpfeat;	sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid);	int ret;

⌨️ 快捷键说明

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