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

📄 manager.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		break;	case 7:		*ctrl |= CS7;		break;	case 8:		*ctrl |= CS8;		break;	}	return 0;}static int set_stopbits(uint8_t stopbits, tcflag_t *ctrl){	/* 1.5 will not be allowed */	switch (stopbits) {	case 1:		*ctrl &= ~CSTOPB;		return 0;	case 2:		*ctrl |= CSTOPB;		return 0;	}	return -EINVAL;}static DBusMessage *proxy_set_serial_params(DBusConnection *conn,						DBusMessage *msg, void *data){	struct proxy *prx = data;	const char *ratestr, *paritystr;	uint8_t databits, stopbits;	tcflag_t ctrl;		/* Control mode flags */	speed_t speed = B0;	/* In/Out speed */	/* Don't allow change TTY settings if it is open */	if (prx->local_watch)		return failed(msg, "Not allowed");	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &ratestr,				DBUS_TYPE_BYTE, &databits,				DBUS_TYPE_BYTE, &stopbits,				DBUS_TYPE_STRING, &paritystr,				DBUS_TYPE_INVALID))		return NULL;	if (str2speed(ratestr, &speed)  == B0)		return invalid_arguments(msg, "Invalid baud rate");	ctrl = prx->proxy_ti.c_cflag;	if (set_databits(databits, &ctrl) < 0)		return invalid_arguments(msg, "Invalid data bits");	if (set_stopbits(stopbits, &ctrl) < 0)		return invalid_arguments(msg, "Invalid stop bits");	if (set_parity(paritystr, &ctrl) < 0)		return invalid_arguments(msg, "Invalid parity");	prx->proxy_ti.c_cflag = ctrl;	prx->proxy_ti.c_cflag |= (CLOCAL | CREAD);	cfsetispeed(&prx->proxy_ti, speed);	cfsetospeed(&prx->proxy_ti, speed);	proxy_store(&prx->src, prx->uuid128, prx->address, NULL,				prx->channel, 0, &prx->proxy_ti);	return dbus_message_new_method_return(msg);}static GDBusMethodTable proxy_methods[] = {	{ "Enable",			"",	"",	proxy_enable },	{ "Disable",			"",	"",	proxy_disable },	{ "GetInfo",			"",	"a{sv}",proxy_get_info },	{ "SetSerialParameters",	"syys",	"",	proxy_set_serial_params },	{ },};static void proxy_unregister(gpointer data){	struct proxy *prx = data;	int sk;	info("Unregistered proxy: %s", prx->address);	if (prx->type != TTY_PROXY)		goto done;	/* Restore the initial TTY configuration */	sk =  open(prx->address, O_RDWR | O_NOCTTY);	if (sk) {		tcsetattr(sk, TCSAFLUSH, &prx->sys_ti);		close(sk);	}done:	proxy_free(prx);}static int register_proxy_object(struct proxy *prx, char *outpath, size_t size){	char path[MAX_PATH_LENGTH + 1];	snprintf(path, MAX_PATH_LENGTH, "/org/bluez/serial/proxy%d",			sk_counter++);	if (!g_dbus_register_interface(connection, path,					SERIAL_PROXY_INTERFACE,					proxy_methods, NULL, NULL,					prx, proxy_unregister)) {		error("D-Bus failed to register %s path", path);		return -1;	}	prx->path = g_strdup(path);	proxies = g_slist_append(proxies, prx);	if (outpath)		strncpy(outpath, path, size);	info("Registered proxy:%s", path);	return 0;}static int proxy_tty_register(bdaddr_t *src, const char *uuid128,				const char *address, struct termios *ti,				char *outpath, size_t size, gboolean save){	struct termios sys_ti;	struct proxy *prx;	int sk, ret;	sk = open(address, O_RDONLY | O_NOCTTY);	if (sk < 0) {		error("Cant open TTY: %s(%d)", strerror(errno), errno);		return -EINVAL;	}	prx = g_new0(struct proxy, 1);	prx->address = g_strdup(address);	prx->uuid128 = g_strdup(uuid128);	prx->type = TTY_PROXY;	bacpy(&prx->src, src);	/* Current TTY settings */	memset(&sys_ti, 0, sizeof(sys_ti));	tcgetattr(sk, &sys_ti);	memcpy(&prx->sys_ti, &sys_ti, sizeof(sys_ti));	close(sk);	if (!ti) {		/* Use current settings */		memcpy(&prx->proxy_ti, &sys_ti, sizeof(sys_ti));	} else {		/* New TTY settings: user provided */		memcpy(&prx->proxy_ti, ti, sizeof(*ti));	}	ret = register_proxy_object(prx, outpath, size);	if (ret < 0)		proxy_free(prx);	if (save)		proxy_store(src, uuid128, address, NULL,			prx->channel, 0, &prx->proxy_ti);	return ret;}static int proxy_socket_register(bdaddr_t *src, const char *uuid128,				const char *address, char *outpath,				size_t size, gboolean save){	struct proxy *prx;	int ret;	prx = g_new0(struct proxy, 1);	prx->address = g_strdup(address);	prx->uuid128 = g_strdup(uuid128);	prx->type = UNIX_SOCKET_PROXY;	bacpy(&prx->src, src);	ret = register_proxy_object(prx, outpath, size);	if (ret < 0)		proxy_free(prx);	if (save)		proxy_store(src, uuid128, address, NULL,				prx->channel, 0, NULL);	return ret;}static int proxy_tcp_register(bdaddr_t *src, const char *uuid128,				const char *address, char *outpath,				size_t size, gboolean save){	struct proxy *prx;	int ret;	prx = g_new0(struct proxy, 1);	prx->address = g_strdup(address);	prx->uuid128 = g_strdup(uuid128);	prx->type = TCP_SOCKET_PROXY;	bacpy(&prx->src, src);	ret = register_proxy_object(prx, outpath, size);	if (ret < 0)		proxy_free(prx);	if (save)		proxy_store(src, uuid128, address, NULL,				prx->channel, 0, NULL);	return ret;}static proxy_type_t addr2type(const char *address){	struct stat st;	if (stat(address, &st) < 0) {		/*		 * Unix socket: if the sun_path starts with null byte		 * it refers to abstract namespace. 'x00' will be used		 * to represent the null byte.		 */		if (strncmp("localhost:", address, 10) == 0)			return TCP_SOCKET_PROXY;		if (strncmp("x00", address, 3) != 0)			return UNKNOWN_PROXY_TYPE;		else			return UNIX_SOCKET_PROXY;	} else {		/* Filesystem: char device or unix socket */		if (S_ISCHR(st.st_mode) && strncmp("/dev/", address, 4) == 0)			return TTY_PROXY;		else if (S_ISSOCK(st.st_mode))			return UNIX_SOCKET_PROXY;		else			return UNKNOWN_PROXY_TYPE;	}}static int proxy_addrcmp(gconstpointer proxy, gconstpointer addr){	const struct proxy *prx = proxy;	const char *address = addr;	return strcmp(prx->address, address);}static int proxy_pathcmp(gconstpointer proxy, gconstpointer p){	const struct proxy *prx = proxy;	const char *path = p;	return strcmp(prx->path, path);}static DBusMessage *create_proxy(DBusConnection *conn,				DBusMessage *msg, void *data){	char path[MAX_PATH_LENGTH + 1];	const char *uuid128, *address, *ppath = path;	DBusMessage *reply;	proxy_type_t type;	bdaddr_t src;	uuid_t uuid;	int dev_id, ret;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &uuid128,				DBUS_TYPE_STRING, &address,				DBUS_TYPE_INVALID))		return NULL;	if (bt_string2uuid(&uuid, uuid128) < 0)		return invalid_arguments(msg, "Invalid UUID");	type = addr2type(address);	if (type == UNKNOWN_PROXY_TYPE)		return invalid_arguments(msg, "Invalid address");	/* Only one proxy per address(TTY or unix socket) is allowed */	if (g_slist_find_custom(proxies, address, proxy_addrcmp))		return g_dbus_create_error(msg, ERROR_INTERFACE ".AlreadyExist",						"Proxy already exists");	dev_id = hci_get_route(NULL);	if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) {		error("Adapter not available");		return failed(msg, "Adapter no available");	}	reply = dbus_message_new_method_return(msg);	if (!reply)		return NULL;	switch (type) {	case UNIX_SOCKET_PROXY:		ret = proxy_socket_register(&src, uuid128, address,						path, sizeof(path), TRUE);		break;	case TTY_PROXY:		ret = proxy_tty_register(&src, uuid128, address,				NULL, path, sizeof(path), TRUE);		break;	case TCP_SOCKET_PROXY:		ret = proxy_tcp_register(&src, uuid128, address,					path, sizeof(path), TRUE);		break;	default:		ret = -1;	}	if (ret < 0) {		dbus_message_unref(reply);		return failed(msg, "Create object path failed");	}	g_dbus_emit_signal(connection, SERIAL_MANAGER_PATH,			SERIAL_MANAGER_INTERFACE, "ProxyCreated",			DBUS_TYPE_STRING, &ppath,			DBUS_TYPE_INVALID);	dbus_message_append_args(reply,			DBUS_TYPE_STRING, &ppath,			DBUS_TYPE_INVALID);	return reply;}static DBusMessage *list_proxies(DBusConnection *conn,				DBusMessage *msg, void *data){	struct proxy *prx;	const GSList *l;	DBusMessage *reply;	DBusMessageIter iter, iter_array;	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_TYPE_STRING_AS_STRING, &iter_array);	for (l = proxies; l; l = l->next) {		prx = l->data;		dbus_message_iter_append_basic(&iter_array,				DBUS_TYPE_STRING, &prx->path);	}	dbus_message_iter_close_container(&iter, &iter_array);	return reply;}static DBusMessage *remove_proxy(DBusConnection *conn,				DBusMessage *msg, void *data){	struct proxy *prx;	const char *path;	GSList *l;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &path,				DBUS_TYPE_INVALID))		return NULL;	l = g_slist_find_custom(proxies, path, proxy_pathcmp);	if (!l)		return does_not_exist(msg, "Invalid proxy path");	g_dbus_emit_signal(conn, SERIAL_MANAGER_PATH,			SERIAL_MANAGER_INTERFACE, "ProxyRemoved",			DBUS_TYPE_STRING, &path,			DBUS_TYPE_INVALID);	prx = l->data;	proxy_delete(&prx->src, prx->address);	proxies = g_slist_remove(proxies, prx);	g_dbus_unregister_interface(conn, path, SERIAL_PROXY_INTERFACE);	return dbus_message_new_method_return(msg);}static void manager_unregister(void *data){	if (proxies) {		g_slist_foreach(proxies,				(GFunc) proxy_unregister, NULL);		g_slist_free(proxies);		proxies = NULL;	}}static GDBusMethodTable manager_methods[] = {	{ "CreateProxy",		"ss",	"s",	create_proxy },	{ "ListProxies",		"",	"as",	list_proxies },	{ "RemoveProxy",		"s",	"",	remove_proxy },	{ },};static GDBusSignalTable manager_signals[] = {	{ "ProxyCreated",		"s"	},	{ "ProxyRemoved",		"s"	},	{ }};static void parse_proxy(char *key, char *value, void *data){	char uuid128[MAX_LEN_UUID_STR], tmp[3];	char *pvalue, *src_addr = data;	proxy_type_t type;	int ch, opts, pos;	bdaddr_t src;	struct termios ti;	uint8_t *pti;	memset(uuid128, 0, sizeof(uuid128));	ch = opts = pos = 0;	if (sscanf(value,"%s %d 0x%04X %n", uuid128, &ch, &opts, &pos) != 3)		return;	/* Extracting name */	value += pos;	pvalue = strchr(value, ':');	if (!pvalue)		return;	/* FIXME: currently name is not used */	*pvalue = '\0';	str2ba(src_addr, &src);	type = addr2type(key);	switch (type) {	case TTY_PROXY:		/* Extracting termios */		pvalue++;		if (!pvalue || strlen(pvalue) != (2 * sizeof(ti)))			return;		memset(&ti, 0, sizeof(ti));		memset(tmp, 0, sizeof(tmp));		/* Converting to termios struct */		pti = (uint8_t *) &ti;		for (pos = 0; pos < sizeof(ti); pos++, pvalue += 2, pti++) {			memcpy(tmp, pvalue, 2);			*pti = (uint8_t) strtol(tmp, NULL, 16);		}		proxy_tty_register(&src, uuid128, key, &ti, NULL, 0, FALSE);		break;	case UNIX_SOCKET_PROXY:		proxy_socket_register(&src, uuid128, key, NULL, 0, FALSE);		break;	case TCP_SOCKET_PROXY:		proxy_tcp_register(&src, uuid128, key, NULL, 0, FALSE);		break;	default:		return;	}}static void register_stored(void){	char filename[PATH_MAX + 1];	struct dirent *de;	DIR *dir;	snprintf(filename, PATH_MAX, "%s", STORAGEDIR);	dir = opendir(filename);	if (!dir)		return;	while ((de = readdir(dir)) != NULL) {		if (!isdigit(de->d_name[0]))			continue;		snprintf(filename, PATH_MAX, "%s/%s/proxy", STORAGEDIR, de->d_name);		textfile_foreach(filename, parse_proxy, de->d_name);	}	closedir(dir);}static int serial_probe(struct btd_device_driver *driver,			struct btd_device *device, sdp_record_t *rec,			const char *name){	struct adapter *adapter = device_get_adapter(device);	const gchar *path = device_get_path(device);	sdp_list_t *protos;	int ch;	bdaddr_t src, dst;	DBG("path %s", path);	if (sdp_get_access_protos(rec, &protos) < 0)		return -EINVAL;	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);	if (ch < 1 || ch > 30) {		error("Channel out of range: %d", ch);		return -EINVAL;	}	str2ba(adapter->address, &src);	str2ba(device_get_address(device), &dst);	return port_register(connection, path, &src, &dst, name,			driver->uuids[0], ch);}static void serial_remove(struct btd_device_driver *driver,				struct btd_device *device){	const gchar *path = device_get_path(device);	DBG("path %s", path);	port_unregister(path, driver->uuids[0]);}static int port_probe(struct btd_device_driver *driver,			struct btd_device *device, GSList *records){	return serial_probe(driver, device, records->data,			SERIAL_PORT_NAME);}static int dialup_probe(struct btd_device_driver *driver,			struct btd_device *device, GSList *records){	return serial_probe(driver, device, records->data,			DIALUP_NET_NAME);}static struct btd_device_driver serial_port_driver = {	.name	= "serial-port",	.uuids	= BTD_UUIDS(SERIAL_PORT_UUID),	.probe	= port_probe,	.remove	= serial_remove,};static struct btd_device_driver serial_dialup_driver = {	.name	= "serial-dialup",	.uuids	= BTD_UUIDS(DIALUP_NET_UUID),	.probe	= dialup_probe,	.remove	= serial_remove,};int serial_manager_init(DBusConnection *conn){	if (!g_dbus_register_interface(conn, SERIAL_MANAGER_PATH,					SERIAL_MANAGER_INTERFACE,					manager_methods, manager_signals, NULL,					NULL, manager_unregister)) {		error("Failed to register %s interface to %s",				SERIAL_MANAGER_INTERFACE, SERIAL_MANAGER_PATH);		return -1;	}	connection = dbus_connection_ref(conn);	info("Registered manager path:%s", SERIAL_MANAGER_PATH);	register_stored();	btd_register_device_driver(&serial_port_driver);	btd_register_device_driver(&serial_dialup_driver);	return 0;}void serial_manager_exit(void){	btd_unregister_device_driver(&serial_port_driver);	btd_unregister_device_driver(&serial_dialup_driver);	g_dbus_unregister_interface(connection, SERIAL_MANAGER_PATH,						SERIAL_MANAGER_INTERFACE);	dbus_connection_unref(connection);	connection = NULL;	port_release_all();}

⌨️ 快捷键说明

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