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

📄 manager.c

📁 基于LINUX内核驱动的开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	DBusMessage *msg;	DBusPendingCall *call;	msg = dbus_message_new_method_call("org.bluez", pc->adapter_path,			"org.bluez.Adapter", "GetRemoteServiceRecord");	if (!msg)		return -1;	dbus_message_append_args(msg,			DBUS_TYPE_STRING, &pc->bda,			DBUS_TYPE_UINT32, &handle,			DBUS_TYPE_INVALID);	if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) {		error("Can't send D-Bus message.");		dbus_message_unref(msg);		return -1;	}	dbus_pending_call_set_notify(call, cb, pc, NULL);	dbus_pending_call_unref(call);	dbus_message_unref(msg);	return 0;}static void handles_reply(DBusPendingCall *call, void *data){	struct pending_connect *pc;	DBusMessage *reply = dbus_pending_call_steal_reply(call);	DBusError derr;	uint32_t *phandle;	int len;	/* Owner exited? */	if (!g_slist_find(pending_connects, data)) {		dbus_message_unref(reply);		return;	}	pc = data;	if (pc->canceled) {		error_canceled(pc->conn, pc->msg, "Connection canceled");		goto fail;	}	dbus_error_init(&derr);	if (dbus_set_error_from_message(&derr, reply)) {		/* FIXME : forward error as is */		if (dbus_error_has_name(&derr,				"org.bluez.Error.ConnectionAttemptFailed"))			error_connection_attempt_failed(pc->conn,					pc->msg, EIO);		else			error_not_supported(pc->conn, pc->msg);		error("GetRemoteServiceHandles: %s(%s)",					derr.name, derr.message);		dbus_error_free(&derr);		goto fail;	}	if (!dbus_message_get_args(reply, &derr,				DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle,				&len, DBUS_TYPE_INVALID)) {		error_not_supported(pc->conn, pc->msg);		error("%s: %s", derr.name, derr.message);		dbus_error_free(&derr);		goto fail;	}	if (len == 0) {		error_not_supported(pc->conn, pc->msg);		goto fail;	}	if (get_record(pc, *phandle, record_reply) < 0) {		error_not_supported(pc->conn, pc->msg);		goto fail;	}	dbus_message_unref(reply);	return;fail:	dbus_message_unref(reply);	pending_connect_remove(pc);}static int get_handles(struct pending_connect *pc, const char *uuid,					DBusPendingCallNotifyFunction cb){	DBusMessage *msg;	DBusPendingCall *call;	msg = dbus_message_new_method_call("org.bluez", pc->adapter_path,				"org.bluez.Adapter", "GetRemoteServiceHandles");	if (!msg)		return -1;	dbus_message_append_args(msg,			DBUS_TYPE_STRING, &pc->bda,			DBUS_TYPE_STRING, &uuid,			DBUS_TYPE_INVALID);	if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) {		error("Can't send D-Bus message.");		dbus_message_unref(msg);		return -1;	}	dbus_pending_call_set_notify(call, cb, pc, NULL);	dbus_pending_call_unref(call);	dbus_message_unref(msg);	return 0;}static int pattern2uuid128(const char *pattern, char *uuid, size_t size){	uint16_t cls;	/* Friendly name */	cls = str2class(pattern);	if (cls) {		uuid_t uuid16, uuid128;		sdp_uuid16_create(&uuid16, cls);		sdp_uuid16_to_uuid128(&uuid128, &uuid16);		sdp_uuid2strn(&uuid128, uuid, size);		return 0;	}	/* UUID 128*/	if ((strlen(pattern) == 36) &&		(strncasecmp(BASE_UUID, pattern, 3) == 0) &&		(strncasecmp(BASE_UUID + 8, pattern + 8, 28) == 0)) {		strncpy(uuid, pattern, size);		return 0;	}	return -EINVAL;}static int pattern2long(const char *pattern, long *pval){	char *endptr;	long val;	errno = 0;	val = strtol(pattern, &endptr, 0);	if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||			(errno != 0 && val == 0) || (pattern == endptr)) {		return -EINVAL;	}	*pval = val;	return 0;}static DBusHandlerResult create_port(DBusConnection *conn,				DBusMessage *msg, void *data){	char path[MAX_PATH_LENGTH], port_name[16], uuid[MAX_LEN_UUID_STR];	const char *bda, *pattern, *ppath = path;	struct pending_connect *pending, *pc;	DBusMessage *reply;	DBusError derr;	bdaddr_t src, dst;	long val;	int dev_id, err;	dbus_error_init(&derr);	if (!dbus_message_get_args(msg, &derr,				DBUS_TYPE_STRING, &bda,				DBUS_TYPE_STRING, &pattern,				DBUS_TYPE_INVALID)) {		error_invalid_arguments(conn, msg, derr.message);		dbus_error_free(&derr);		return DBUS_HANDLER_RESULT_HANDLED;	}	pending = find_pending_connect_by_pattern(bda, pattern);	if (pending)		return error_in_progress(conn, msg, "Connection in progress");	dev_id = hci_get_route(NULL);	if ((dev_id < 0) ||  (hci_devba(dev_id, &src) < 0))		return error_failed(conn, msg, "Adapter not available");	pc = g_new0(struct pending_connect, 1);	bacpy(&pc->src, &src);	pc->conn = dbus_connection_ref(conn);	pc->msg = dbus_message_ref(msg);	pc->bda = g_strdup(bda);	pc->id = -1;	pc->pattern = g_strdup(pattern);	pc->adapter_path = g_malloc0(16);	snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id);	memset(uuid, 0, sizeof(uuid));	/* Friendly name or uuid128 */	if (pattern2uuid128(pattern, uuid, sizeof(uuid)) == 0) {		if (get_handles(pc, uuid, handles_reply) < 0) {			pending_connect_free(pc);			return error_not_supported(conn, msg);		}		pending_connects = g_slist_append(pending_connects, pc);		name_listener_add(conn, dbus_message_get_sender(msg),				(name_cb_t) transaction_owner_exited, NULL);		return DBUS_HANDLER_RESULT_HANDLED;	}	/* Record handle or channel */	err = pattern2long(pattern, &val);	if (err < 0) {		pending_connect_free(pc);		return error_invalid_arguments(conn, msg, "invalid pattern");	}	/* Record handle: starts at 0x10000 */	if (strncasecmp("0x", pattern, 2) == 0) {		if (val < 0x10000) {			pending_connect_free(pc);			return error_invalid_arguments(conn, msg,					"invalid record handle");		}		if (get_record(pc, val, record_reply) < 0) {			pending_connect_free(pc);			return error_not_supported(conn, msg);		}		pending_connects = g_slist_append(pending_connects, pc);		name_listener_add(conn, dbus_message_get_sender(msg),				(name_cb_t) transaction_owner_exited, NULL);		return DBUS_HANDLER_RESULT_HANDLED;	}	pending_connect_free(pc);	/* RFCOMM Channel range: 1 - 30 */	if (val < 1 || val > 30)		return error_invalid_arguments(conn, msg,				"invalid RFCOMM channel");	str2ba(bda, &dst);	err = rfcomm_bind(&src, &dst, -1, val);	if (err < 0)		return error_failed_errno(conn, msg, -err);	snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err);	port_store(&src, &dst, err, val, NULL);	port_register(conn, err, &src, &dst, port_name, path, NULL);	ports_paths = g_slist_append(ports_paths, g_strdup(path));	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	dbus_message_append_args(reply,			DBUS_TYPE_STRING, &ppath,			DBUS_TYPE_INVALID);	send_message_and_unref(conn, reply);	dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH,			SERIAL_MANAGER_INTERFACE, "PortCreated" ,			DBUS_TYPE_STRING, &ppath,			DBUS_TYPE_INVALID);	return DBUS_HANDLER_RESULT_HANDLED;}static void message_append_paths(DBusMessage *msg, const GSList *list){	const GSList *l;	const char *path;	DBusMessageIter iter, iter_array;	dbus_message_iter_init_append(msg, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,			DBUS_TYPE_STRING_AS_STRING, &iter_array);	for (l = list; l; l = l->next) {		path = l->data;		dbus_message_iter_append_basic(&iter_array,				DBUS_TYPE_STRING, &path);	}	dbus_message_iter_close_container(&iter, &iter_array);}static DBusHandlerResult list_ports(DBusConnection *conn,				DBusMessage *msg, void *data){	DBusMessage *reply;	reply = dbus_message_new_method_return(msg);	if (!reply)		return DBUS_HANDLER_RESULT_NEED_MEMORY;	message_append_paths(reply, ports_paths);	return send_message_and_unref(conn, reply);}static DBusHandlerResult remove_port(DBusConnection *conn,				DBusMessage *msg, void *data){	struct rfcomm_dev_info di;	DBusError derr;	const char *path;	GSList *l;	int16_t id;	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;	}	if (sscanf(path, SERIAL_MANAGER_PATH"/rfcomm%hd", &id) != 1)		return error_does_not_exist(conn, msg, "Invalid RFCOMM node");	di.id = id;	if (ioctl(rfcomm_ctl, RFCOMMGETDEVINFO, &di) < 0)		return error_does_not_exist(conn, msg, "Invalid RFCOMM node");	port_delete(&di.src, &di.dst, id);	if (port_unregister(path) < 0)		return error_does_not_exist(conn, msg, "Invalid RFCOMM node");	send_message_and_unref(conn,			dbus_message_new_method_return(msg));	dbus_connection_emit_signal(conn, SERIAL_MANAGER_PATH,			SERIAL_MANAGER_INTERFACE, "PortRemoved" ,			DBUS_TYPE_STRING, &path,			DBUS_TYPE_INVALID);	l = g_slist_find_custom(ports_paths, path, (GCompareFunc) strcmp);	if (l) {		g_free(l->data);		ports_paths = g_slist_remove(ports_paths, l->data);	}	return DBUS_HANDLER_RESULT_HANDLED;}static int rfcomm_listen(bdaddr_t *src, uint8_t *channel, int opts){	struct sockaddr_rc laddr;	socklen_t alen;	int err, sk;	sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);	if (sk < 0)		return -errno;	if (setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &opts, sizeof(opts)) < 0)		goto fail;	memset(&laddr, 0, sizeof(laddr));	laddr.rc_family = AF_BLUETOOTH;	bacpy(&laddr.rc_bdaddr, src);	laddr.rc_channel = (channel ? *channel : 0);	alen = sizeof(laddr);	if (bind(sk, (struct sockaddr *) &laddr, alen) < 0)		goto fail;	if (listen(sk, 1) < 0)		goto fail;	if (!channel)		return sk;	memset(&laddr, 0, sizeof(laddr));	if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0)		goto fail;	*channel = laddr.rc_channel;	return sk;fail:	err = errno;	close(sk);	errno = err;	return -err;}static void add_lang_attr(sdp_record_t *r){	sdp_lang_attr_t base_lang;	sdp_list_t *langs = 0;	/* UTF-8 MIBenum (http://www.iana.org/assignments/character-sets) */	base_lang.code_ISO639 = (0x65 << 8) | 0x6e;	base_lang.encoding = 106;	base_lang.base_offset = SDP_PRIMARY_LANG_BASE;	langs = sdp_list_append(0, &base_lang);	sdp_set_lang_attr(r, langs);	sdp_list_free(langs, 0);}static int str2uuid(uuid_t *uuid, const char *string){	uint16_t data1, data2, data3, data5;	uint32_t data0, data4;	if (strlen(string) == 36 &&			string[8] == '-' &&			string[13] == '-' &&			string[18] == '-' &&			string[23] == '-' &&			sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",				&data0, &data1, &data2, &data3, &data4, &data5) == 6) {		uint8_t val[16];		data0 = htonl(data0);		data1 = htons(data1);		data2 = htons(data2);		data3 = htons(data3);		data4 = htonl(data4);		data5 = htons(data5);		memcpy(&val[0], &data0, 4);		memcpy(&val[4], &data1, 2);		memcpy(&val[6], &data2, 2);		memcpy(&val[8], &data3, 2);		memcpy(&val[10], &data4, 4);		memcpy(&val[14], &data5, 2);		sdp_uuid128_create(uuid, val);		return 0;	}	return -1;}static int create_proxy_record(sdp_buf_t *buf, const char *uuid128, uint8_t channel){	sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id;	uuid_t uuid, root_uuid, l2cap, rfcomm;	sdp_profile_desc_t profile;	sdp_record_t record;	sdp_data_t *ch;	int ret;	memset(&record, 0, sizeof(sdp_record_t));	record.handle = 0xffffffff;	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);	root = sdp_list_append(NULL, &root_uuid);	sdp_set_browse_groups(&record, root);	sdp_list_free(root, NULL);	str2uuid(&uuid, uuid128);	svclass_id = sdp_list_append(NULL, &uuid);	sdp_set_service_classes(&record, svclass_id);	sdp_list_free(svclass_id, NULL);	sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);	profile.version = 0x0100;	profiles = sdp_list_append(NULL, &profile);	sdp_set_profile_descs(&record, profiles);	sdp_list_free(profiles, NULL);	sdp_uuid16_create(&l2cap, L2CAP_UUID);	proto[0] = sdp_list_append(NULL, &l2cap);	apseq = sdp_list_append(NULL, proto[0]);	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);	proto[1] = sdp_list_append(NULL, &rfcomm);	ch = sdp_data_alloc(SDP_UINT8, &channel);	proto[1] = sdp_list_append(proto[1], ch);	apseq = sdp_list_append(apseq, proto[1]);	aproto = sdp_list_append(NULL, apseq);	sdp_set_access_protos(&record, aproto);	add_lang_attr(&record);	sdp_set_info_attr(&record, "Port Proxy Entity",				NULL, "Port Proxy Entity");	ret = sdp_gen_record_pdu(&record, buf);	sdp_data_free(ch);	sdp_list_free(proto[0], NULL);	sdp_list_free(proto[1], NULL);	sdp_list_free(apseq, NULL);	sdp_list_free(aproto, NULL);	sdp_list_free(record.attrlist, (sdp_free_func_t) sdp_data_free);	sdp_list_free(record.pattern, free);	return ret;}static GIOError channel_write(GIOChannel *chan, char *buf, size_t size){	GIOError err = G_IO_ERROR_NONE;	gsize wbytes, written;	wbytes = written = 0;	while (wbytes < size) {		err = g_io_channel_write(chan,				buf + wbytes,				size - wbytes,				&written);		if (err != G_IO_ERROR_NONE)			return err;		wbytes += written;	}	return err;}static gboolean forward_data(GIOChannel *chan, GIOCondition cond, gpointer data){	char buf[BUF_SIZE];	GIOChannel *dest = data;	GIOError err;	size_t rbytes;	if (cond & G_IO_NVAL)		return FALSE;	if (cond & (G_IO_HUP | G_IO_ERR)) {		/* Try forward remaining data */		do {			rbytes = 0;			err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes);			if (err != G_IO_ERROR_NONE || rbytes == 0)				break;			err = channel_write(dest, buf, rbytes);		} while (err == G_IO_ERROR_NONE);		g_io_channel_close(dest);		return FALSE;	}	rbytes = 0;	err = g_io_channel_read(chan, buf, sizeof(buf), &rbytes);	if (err != G_IO_ERROR_NONE)		return FALSE;	err = channel_write(dest, buf, rbytes);	if (err != G_IO_ERROR_NONE)		return FALSE;	return TRUE;}static uint32_t add_proxy_record(DBusConnection *conn, sdp_buf_t *buf){	DBusMessage *msg, *reply;	DBusError derr;	dbus_uint32_t rec_id;	msg = dbus_message_new_method_call("org.bluez", "/org/bluez",			"org.bluez.Database", "AddServiceRecord");	if (!msg) {		error("Can't allocate new method call");		return 0;	}	dbus_message_append_args(msg,			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,			&buf->data, buf->data_size,			DBUS_TYPE_INVALID);	dbus_error_init(&derr);	reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &derr);	free(buf->data);	dbus_message_unref(msg);	if (dbus_error_is_set(&derr) ||			dbus_set_error_from_message(&derr, reply)) {		error("Adding service record failed: %s", derr.message);		dbus_error_free(&derr);		return 0;	}	dbus_message_get_args(reply, &derr,			DBUS_TYPE_UINT32, &rec_id,			DBUS_TYPE_INVALID);	if (dbus_error_is_set(&derr)) {		error("Invalid arguments to AddServiceRecord reply: %s",				derr.message);		dbus_message_unref(reply);		dbus_error_free(&derr);		return 0;	}	dbus_message_unref(reply);	return rec_id;}static int remove_proxy_record(DBusConnection *conn, uint32_t rec_id){

⌨️ 快捷键说明

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