diff options
| author | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-05-09 21:00:02 +0000 | 
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.dentz@openbossa.org> | 2008-05-09 21:00:02 +0000 | 
| commit | 8cf2f361bf51ee608db71057843cd9dbdf66ff70 (patch) | |
| tree | 3517c6f66db96858c76eba4a34997b3ac70bbf2d | |
| parent | a59f82bd8a01e83bd7724beccfe2a0383982650c (diff) | |
Cleanup and removal of dbus internal calls.
| -rw-r--r-- | serial/manager.c | 629 | 
1 files changed, 218 insertions, 411 deletions
| diff --git a/serial/manager.c b/serial/manager.c index aa05b8f3..2ad0655c 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -70,10 +70,9 @@  struct pending_connect {  	DBusConnection	*conn;  	DBusMessage	*msg; -	char		*bda;		/* Destination address  */ -	char		*adapter_path;	/* Adapter D-Bus path   */ +	char		*adapter;	/* Adapter address */ +	char		*address;	/* Destination address  */  	char		*pattern;	/* Connection request pattern */ -	bdaddr_t	src;  	uint8_t		channel;  	char		*dev;		/* tty device name */  	int		id;		/* RFCOMM device id */ @@ -143,12 +142,12 @@ static void pending_connect_free(struct pending_connect *pc)  		dbus_connection_unref(pc->conn);  	if (pc->msg)  		dbus_message_unref(pc->msg); -	if (pc->bda) -		g_free(pc->bda); +	if (pc->adapter) +		g_free(pc->adapter); +	if (pc->address) +		g_free(pc->address);  	if (pc->pattern)  		g_free(pc->pattern); -	if (pc->adapter_path) -		g_free(pc->adapter_path);  	if (pc->dev)  		g_free(pc->dev);  	g_free(pc); @@ -162,7 +161,7 @@ static struct pending_connect *find_pending_connect_by_pattern(const char *bda,  	/* Pattern can be friendly name, uuid128, record handle or channel */  	for (l = pending_connects; l != NULL; l = l->next) {  		struct pending_connect *pending = l->data; -		if (!strcasecmp(pending->bda, bda) && +		if (!strcasecmp(pending->address, bda) &&  				!strcasecmp(pending->pattern, pattern))  			return pending;  	} @@ -234,7 +233,7 @@ static void open_notify(int fd, int err, struct pending_connect *pc)  			DBUS_TYPE_STRING, &pc->dev,  			DBUS_TYPE_INVALID); -	str2ba(pc->bda, &dst); +	str2ba(pc->address, &dst);  	/* Add the RFCOMM connection listener */  	port_add_listener(pc->conn, pc->id, &dst, fd, @@ -364,8 +363,8 @@ static void rfcomm_connect_cb(GIOChannel *chan, int err_cb, gpointer user_data)  	memset(&req, 0, sizeof(req));  	req.dev_id = -1;  	req.flags = (1 << RFCOMM_REUSE_DLC); -	bacpy(&req.src, &pc->src); -	str2ba(pc->bda, &req.dst); +	str2ba(pc->adapter, &req.src); +	str2ba(pc->address, &req.dst);  	req.channel = pc->channel;  	sk = g_io_channel_unix_get_fd(chan); @@ -392,22 +391,87 @@ fail:  	pending_connect_remove(pc);  } -static void record_reply(DBusPendingCall *call, void *data) +static DBusHandlerResult create_channel_port(DBusConnection *conn, +				DBusMessage *msg, const char *adapter, +				const char *address, const char *name, +				long channel, void *data) +{ +	char path[MAX_PATH_LENGTH], port_name[16]; +	const char *ppath = path; +	DBusMessage *reply; +	int err; +	bdaddr_t src, dst; + +	if (channel < 1 || channel > 30) +		return error_invalid_arguments(conn, msg, +				"invalid RFCOMM channel"); + +	str2ba(adapter, &src); +	str2ba(address, &dst); +	err = rfcomm_bind(&src, &dst, -1, channel); +	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, channel, name); +	port_register(conn, err, &src, &dst, port_name, path, name); +	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 DBusHandlerResult connect_pending(DBusConnection *conn, DBusMessage *msg, +					struct pending_connect *pc) +{ +	int err; +	bdaddr_t src, dst; + +	if (!g_slist_find(pending_connects, pc)) { +		pending_connects = g_slist_append(pending_connects, pc); +		name_listener_add(conn, dbus_message_get_sender(msg), +				(name_cb_t) transaction_owner_exited, NULL); +	} + +	str2ba(pc->adapter, &src); +	str2ba(pc->address, &dst); + +	err = bt_rfcomm_connect(&src, &dst, pc->channel, rfcomm_connect_cb, pc); +	if (err < 0) { +		const char *strerr = strerror(-err); +		error("RFCOMM connect failed: %s(%d)", strerr, -err); +		pending_connects = g_slist_remove(pending_connects, pc); +		pending_connect_free(pc); +		return error_connection_attempt_failed(conn, msg, -err); +	} + +	return DBUS_HANDLER_RESULT_HANDLED; +} + +static void record_cb(sdp_list_t *recs, int err, gpointer data)  {  	struct pending_connect *pc; -	DBusMessage *reply = dbus_pending_call_steal_reply(call);  	sdp_record_t *rec = NULL; -	const uint8_t *rec_bin;  	sdp_list_t *protos; -	DBusError derr; -	int len, scanned, ch, err; +	int ch;  	bdaddr_t dst;  	/* Owner exited? */ -	if (!g_slist_find(pending_connects, data)) { -		dbus_message_unref(reply); +	if (!g_slist_find(pending_connects, data))  		return; -	}  	pc = data;  	if (pc->canceled) { @@ -415,45 +479,19 @@ static void record_reply(DBusPendingCall *call, void *data)  		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("GetRemoteServiceRecord: %s(%s)", -					derr.name, derr.message); -		dbus_error_free(&derr); -		goto fail; -	} - -	if (!dbus_message_get_args(reply, &derr, -				DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &rec_bin, &len, -				DBUS_TYPE_INVALID)) { -		error_not_supported(pc->conn, pc->msg); -		error("%s: %s", derr.name, derr.message); -		dbus_error_free(&derr); +	if (err < 0) { +		error_connection_attempt_failed(pc->conn, pc->msg, -err);  		goto fail;  	} -	if (len == 0) { +	if (!recs || !recs->data) {  		error_not_supported(pc->conn, pc->msg);  		error("Invalid service record length");  		goto fail;  	} -	rec = sdp_extract_pdu(rec_bin, &scanned); -	if (!rec) { -		error("Can't extract SDP record."); -		error_not_supported(pc->conn, pc->msg); -		goto fail; -	} - -	if (len != scanned || (sdp_get_access_protos(rec, &protos) < 0)) { +	rec = recs->data; +	if (sdp_get_access_protos(rec, &protos) < 0) {  		error_not_supported(pc->conn, pc->msg);  		goto fail;  	} @@ -468,21 +506,11 @@ static void record_reply(DBusPendingCall *call, void *data)  		goto fail;  	} -	str2ba(pc->bda, &dst); +	str2ba(pc->address, &dst);  	if (dbus_message_has_member(pc->msg, "CreatePort")) { -		char path[MAX_PATH_LENGTH], port_name[16]; -		const char *ppath = path;  		sdp_data_t *d;  		char *svcname = NULL; -		DBusMessage *reply; - -		err = rfcomm_bind(&pc->src, &dst, -1, ch); -		if (err < 0) { -			error_failed_errno(pc->conn, pc->msg, -err); -			goto fail; -		} -		snprintf(port_name, sizeof(port_name), "/dev/rfcomm%d", err);  		d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY);  		if (d) { @@ -491,36 +519,16 @@ static void record_reply(DBusPendingCall *call, void *data)  					d->unitSize, d->val.str);  		} -		port_store(&pc->src, &dst, err, ch, svcname); +		create_channel_port(pc->conn, pc->msg, pc->adapter, +				pc->address, svcname, ch, data); -		port_register(pc->conn, err, &pc->src, &dst, port_name, -			      path, svcname);  		if (svcname)  			g_free(svcname); - -		ports_paths = g_slist_append(ports_paths, g_strdup(path)); - -		reply = dbus_message_new_method_return(pc->msg); -		dbus_message_append_args(reply, -				DBUS_TYPE_STRING, &ppath, -				DBUS_TYPE_INVALID); -		send_message_and_unref(pc->conn, reply); - -		dbus_connection_emit_signal(pc->conn, SERIAL_MANAGER_PATH, -				SERIAL_MANAGER_INTERFACE, "PortCreated" , -				DBUS_TYPE_STRING, &ppath, -				DBUS_TYPE_INVALID);  	} else {  		/* ConnectService */  		pc->channel = ch; -		err = bt_rfcomm_connect(&pc->src, &dst, ch, rfcomm_connect_cb, pc); -		if (err < 0) { -			error("RFCOMM connection failed"); -			error_connection_attempt_failed(pc->conn, -					pc->msg, -err); -			goto fail; -		} +		connect_pending(pc->conn, pc->msg, pc);  		/* Wait the connect callback */  		goto done; @@ -529,132 +537,47 @@ static void record_reply(DBusPendingCall *call, void *data)  fail:  	pending_connect_remove(pc);  done: -	if (rec) -		sdp_record_free(rec); -	dbus_message_unref(reply); +	if (recs) +		sdp_list_free(recs, (sdp_free_func_t) sdp_record_free);  } -static int get_record(struct pending_connect *pc, uint32_t handle, -					DBusPendingCallNotifyFunction cb) -{ -	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) +static int str2uuid(uuid_t *uuid, const char *string)  { -	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; -	} +	uint16_t data1, data2, data3, data5; +	uint32_t data0, data4; -	dbus_message_unref(reply); -	return; -fail: -	dbus_message_unref(reply); -	pending_connect_remove(pc); -} +	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]; -static int get_handles(struct pending_connect *pc, const char *uuid, -					DBusPendingCallNotifyFunction cb) -{ -	DBusMessage *msg; -	DBusPendingCall *call; +		data0 = htonl(data0); +		data1 = htons(data1); +		data2 = htons(data2); +		data3 = htons(data3); +		data4 = htonl(data4); +		data5 = htons(data5); -	msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, -				"org.bluez.Adapter", "GetRemoteServiceHandles"); -	if (!msg) -		return -1; +		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); -	dbus_message_append_args(msg, -			DBUS_TYPE_STRING, &pc->bda, -			DBUS_TYPE_STRING, &uuid, -			DBUS_TYPE_INVALID); +		sdp_uuid128_create(uuid, val); -	if (!dbus_connection_send_with_reply(pc->conn, msg, &call, -1)) { -		error("Can't send D-Bus message."); -		dbus_message_unref(msg); -		return -1; +		return 0;  	} -	dbus_pending_call_set_notify(call, cb, pc, NULL); -	dbus_pending_call_unref(call); -	dbus_message_unref(msg); - -	return 0; +	return -1;  } -static int pattern2uuid128(const char *pattern, char *uuid, size_t size) +static int pattern2uuid(const char *pattern, uuid_t *uuid)  {  	uint16_t cls;  	int i; @@ -662,11 +585,7 @@ static int pattern2uuid128(const char *pattern, char *uuid, size_t size)  	/* 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); +		sdp_uuid16_create(uuid, cls);  		return 0;  	} @@ -683,7 +602,7 @@ static int pattern2uuid128(const char *pattern, char *uuid, size_t size)  			return -EINVAL;  	} -	strncpy(uuid, pattern, size); +	str2uuid(uuid, pattern);  	return 0;  } @@ -704,21 +623,53 @@ static int pattern2long(const char *pattern, long *pval)  	return 0;  } +static DBusHandlerResult search_uuid(DBusConnection *conn, DBusMessage *msg, +				const char *adapter, const char *address, +				const char *pattern, uuid_t *uuid, void *data) +{ +	struct pending_connect *pc; +	int err; +	bdaddr_t src, dst; + +	pc = g_new0(struct pending_connect, 1); +	pc->conn = dbus_connection_ref(conn); +	pc->msg = dbus_message_ref(msg); +	pc->adapter = g_strdup(adapter); +	pc->address = g_strdup(address); +	pc->id = -1; +	pc->pattern = g_strdup(pattern); + +	str2ba(adapter, &src); +	str2ba(address, &dst); + +	err = bt_search_service(&src, &dst, uuid, record_cb, pc, NULL); +	if (err < 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; +} +  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; +	const char *address, *pattern; +	struct pending_connect *pending;  	DBusError derr; -	bdaddr_t src, dst;  	long val; -	int dev_id, err; +	uuid_t uuid; +	char adp[18]; +	int dev_id; +	bdaddr_t src;  	dbus_error_init(&derr);  	if (!dbus_message_get_args(msg, &derr, -				DBUS_TYPE_STRING, &bda, +				DBUS_TYPE_STRING, &address,  				DBUS_TYPE_STRING, &pattern,  				DBUS_TYPE_INVALID)) {  		error_invalid_arguments(conn, msg, derr.message); @@ -726,92 +677,27 @@ static DBusHandlerResult create_port(DBusConnection *conn,  		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)) +	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); +	pending = find_pending_connect_by_pattern(address, pattern); +	if (pending) +		return error_in_progress(conn, msg, "Connection in progress"); -	memset(uuid, 0, sizeof(uuid)); +	ba2str(&src, adp);  	/* 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; -	} +	if (pattern2uuid(pattern, &uuid) == 0) +		return search_uuid(conn, msg, adp, address, pattern, &uuid, +				data); -	/* 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"); -		} +	/* RFCOMM Channel */ +	if (pattern2long(pattern, &val) == 0) +		return create_channel_port(conn, msg, adp, address, pattern, +				val, data); -		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; +	return error_invalid_arguments(conn, msg, "invalid pattern");  }  static void message_append_paths(DBusMessage *msg, const GSList *list) @@ -951,42 +837,6 @@ static void add_lang_attr(sdp_record_t *r)  	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 sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel)  {  	sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; @@ -1847,108 +1697,70 @@ static DBusHandlerResult remove_proxy(DBusConnection *conn,  			dbus_message_new_method_return(msg));  } -static DBusHandlerResult connect_service_from_devid(DBusConnection *conn, -				DBusMessage *msg, void *data, int dev_id, -				const char *bda, const char *pattern) +static DBusHandlerResult connect_channel(DBusConnection *conn, DBusMessage *msg, +				const char *adapter, const char *address, +				const char *pattern, long channel, void *data)  { -	struct pending_connect *pending, *pc; -	bdaddr_t src, dst; -	long val; -	int err; -	char uuid[MAX_LEN_UUID_STR]; - -	pending = find_pending_connect_by_pattern(bda, pattern); -	if (pending) -		return error_in_progress(conn, msg, "Connection in progress"); +	struct pending_connect *pc; -	if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) -		return error_failed(conn, msg, "Adapter not available"); +	if (channel < 1 || channel > 30) +		return error_invalid_arguments(conn, msg, +				"invalid RFCOMM channel");  	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->adapter = g_strdup(adapter); +	pc->address = g_strdup(address);  	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); -		goto done; -	} - -	/* Record handle or channel */ -	err = pattern2long(pattern, &val); -	if (err < 0) { -		pending_connect_free(pc); -		return error_invalid_arguments(conn, msg, "invalid pattern"); -	} +	pc->channel = channel; -	/* 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); -		goto done; -	} +	return connect_pending(conn, msg, pc); +} -	/* RFCOMM Channel range: 1 - 30 */ -	if (val < 1 || val > 30) { -		pending_connect_free(pc); -		return error_invalid_arguments(conn, msg, -				"invalid RFCOMM channel"); -	} +static DBusHandlerResult service_connect(DBusConnection *conn, DBusMessage *msg, +					const char *adapter, const char *address, +					const char *pattern, void *data) +{ +	int dev_id; +	bdaddr_t src; +	char adp[18]; +	uuid_t uuid; +	long val; -	/* Add here since connect() in the first try can happen */ -	pending_connects = g_slist_append(pending_connects, pc); +	if (!adapter) +		dev_id = hci_get_route(NULL); +	else +		dev_id = hci_devid(adapter); -	pc->channel = val; +	if ((dev_id < 0) || (hci_devba(dev_id, &src) < 0)) +		return error_failed(conn, msg, "Adapter not available"); -	str2ba(pc->bda, &dst); +	ba2str(&src, adp); -	err = bt_rfcomm_connect(&pc->src, &dst, val, rfcomm_connect_cb, pc); +	/* Friendly name or uuid128 */ +	if (pattern2uuid(pattern, &uuid) == 0) +		return search_uuid(conn, msg, adp, address, pattern, &uuid, +				data); -	if (err < 0) { -		const char *strerr = strerror(-err); -		error("RFCOMM connect failed: %s(%d)", strerr, -err); -		pending_connects = g_slist_remove(pending_connects, pc); -		pending_connect_free(pc); -		return error_connection_attempt_failed(conn, msg, -err); -	} -done: -	name_listener_add(conn, dbus_message_get_sender(msg), -			(name_cb_t) transaction_owner_exited, NULL); +	/* RFCOMM Channel */ +	if (pattern2long(pattern, &val) == 0) +		return connect_channel(conn, msg, adp, address, pattern, +					val, data); -	return DBUS_HANDLER_RESULT_HANDLED; +	return error_invalid_arguments(conn, msg, "invalid pattern");  }  static DBusHandlerResult connect_service(DBusConnection *conn,  					DBusMessage *msg, void *data)  {  	DBusError derr; -	const char *bda, *pattern; -	int devid; +	const char *address, *pattern;  	dbus_error_init(&derr);  	if (!dbus_message_get_args(msg, &derr, -				DBUS_TYPE_STRING, &bda, +				DBUS_TYPE_STRING, &address,  				DBUS_TYPE_STRING, &pattern,  				DBUS_TYPE_INVALID)) {  		error_invalid_arguments(conn, msg, derr.message); @@ -1956,22 +1768,19 @@ static DBusHandlerResult connect_service(DBusConnection *conn,  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	devid = hci_get_route(NULL); - -	return connect_service_from_devid(conn, msg, data, devid, bda, pattern); +	return service_connect(conn, msg, NULL, address, pattern, data);  }  static DBusHandlerResult connect_service_from_adapter(DBusConnection *conn,  						DBusMessage *msg, void *data)  {  	DBusError derr; -	const char *adapter, *bda, *pattern; -	int devid; +	const char *adapter, *address, *pattern;  	dbus_error_init(&derr);  	if (!dbus_message_get_args(msg, &derr,  				DBUS_TYPE_STRING, &adapter, -				DBUS_TYPE_STRING, &bda, +				DBUS_TYPE_STRING, &address,  				DBUS_TYPE_STRING, &pattern,  				DBUS_TYPE_INVALID)) {  		error_invalid_arguments(conn, msg, derr.message); @@ -1979,9 +1788,7 @@ static DBusHandlerResult connect_service_from_adapter(DBusConnection *conn,  		return DBUS_HANDLER_RESULT_HANDLED;  	} -	devid = hci_devid(adapter); - -	return connect_service_from_devid(conn, msg, data, devid, bda, pattern); +	return service_connect(conn, msg, adapter, address, pattern, data);  }  static DBusHandlerResult disconnect_service(DBusConnection *conn, | 
