public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Matthew Garrett <mjg59@srcf.ucam.org>
To: BlueZ development <bluez-devel@lists.sourceforge.net>
Subject: Re: [Bluez-devel] [PATCH] implement RFCOMM Connect and Disconnect	methods
Date: Sat, 19 Aug 2006 15:36:08 +0100	[thread overview]
Message-ID: <20060819143608.GA31812@srcf.ucam.org> (raw)
In-Reply-To: <20060817115912.GA24906@localhost.localdomain>

Right. How about this (not heavily tested, more proof of concept) - it 
removes the unimplemented Connect and CancelConnect methods, and 
replaces them with ConnectByUUID, ConnectByService and ConnectByHandle 
methods with the appropriate CancelConnect methods.

Index: dbus-api.txt
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-api.txt,v
retrieving revision 1.41
diff -u -r1.41 dbus-api.txt
--- dbus-api.txt	18 Aug 2006 19:50:27 -0000	1.41
+++ dbus-api.txt	19 Aug 2006 14:34:32 -0000
@@ -901,11 +901,11 @@
 Interface	org.bluez.RFCOMM
 Object path	/org/bluez/{hci0,hci1,...}
 
-Methods		string Connect(string address, string service)
+Methods		string ConnectByService(string address, string service)
 
 			This creates a connection to a remote RFCOMM based
-			service. The service string can either be a UUID-16,
-			a UUID-32, a UUID-128 or a service abbreviation.
+			service. The service string must be a service 
+			abbreviation.
 
 			The return value will be the path of the newly
 			created RFCOMM TTY device (for example /dev/rfcomm0).
@@ -917,9 +917,46 @@
 			                      "ftp", "bpp", "bip", "synch",
 			                      "dun", "opp", "fax", "spp"
 
-		void CancelConnect(string address, string service)
+		void CancelConnectByService(string address, string service)
 
-			This method cancels a previous Connect method call.
+			This method cancels a previous ConnectByService method
+			 call.
+
+		string ConnectByUUID(string address, string uuid)
+
+			This creates a connection to a remote RFCOMM based
+			service. The uuid string must be a UUID-128.
+
+			The return value will be the path of the newly
+			created RFCOMM TTY device (for example /dev/rfcomm0).
+
+			If the application disconnects from the D-Bus this
+			connection will be terminated.
+
+		void CancelConnectByUUID(string address, string uuid)
+
+			This method cancels a previous ConnectByUUID method 
+			call.
+
+		string ConnectByHandle(string address, uint32 handle)
+
+			This creates a connection to a remote RFCOMM based
+			service. The handle must be a servicerecord handle.
+
+			The return value will be the path of the newly
+			created RFCOMM TTY device (for example /dev/rfcomm0).
+
+			If the application disconnects from the D-Bus this
+			connection will be terminated.
+
+			Valid service values: "vcp", "map", "pbap", "sap",
+			                      "ftp", "bpp", "bip", "synch",
+			                      "dun", "opp", "fax", "spp"
+
+		void CancelConnectByHandle(string address, string uuid)
+
+			This method cancels a previous ConnectByHandle method 
+			call.
 
 		string ConnectByChannel(string address, byte channel)
 
Index: dbus-rfcomm.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-rfcomm.c,v
retrieving revision 1.10
diff -u -r1.10 dbus-rfcomm.c
--- dbus-rfcomm.c	18 Aug 2006 18:29:40 -0000	1.10
+++ dbus-rfcomm.c	19 Aug 2006 14:34:32 -0000
@@ -33,11 +33,14 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <arpa/inet.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/rfcomm.h>
 #include <bluetooth/hci.h>
 #include <bluetooth/hci_lib.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
 
 #include <dbus/dbus.h>
 
@@ -452,18 +455,308 @@
 	return node;
 }
 
-static DBusHandlerResult rfcomm_connect_req(DBusConnection *conn,
-						DBusMessage *msg, void *data)
+static DBusHandlerResult rfcomm_get_ch_from_uuid_t(DBusConnection *conn,
+						   DBusMessage *msg,
+						   const char *dst, 
+						   uuid_t *uuid,
+						   int *ch,
+						   void *data)
+{
+	sdp_record_t *rec;
+	sdp_list_t *protos;
+
+	rec = find_record_by_uuid (dst, uuid);
+	if (!rec)
+		return error_record_does_not_exist (conn, msg);
+	
+	if (sdp_get_access_protos(rec, &protos) == 0)
+		*ch = sdp_get_proto_port (protos, RFCOMM_UUID);
+
+	if (*ch == -1)
+		return error_record_does_not_exist (conn, msg);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult rfcomm_get_ch_from_handle(DBusConnection *conn,
+						   DBusMessage *msg,
+						   const char *dst, 
+						   int handle,
+						   int *ch,
+						   void *data)
 {
-	error("RFCOMM.Connect not implemented");
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	bdaddr_t bdaddr;
+	sdp_record_t *rec;
+	sdp_list_t *protos;
+	struct hci_dbus_data *dbus_data = data;
+
+	hci_devba(dbus_data->dev_id, &bdaddr);
+
+	rec = find_record_by_handle (dst, handle);
+	if (!rec)
+		return error_record_does_not_exist (conn, msg);
+	
+	if (sdp_get_access_protos(rec, &protos) == 0)
+		*ch = sdp_get_proto_port (protos, RFCOMM_UUID);
+
+	if (*ch == -1)
+		return error_record_does_not_exist (conn, msg);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-static DBusHandlerResult rfcomm_cancel_connect_req(DBusConnection *conn,
-						DBusMessage *msg, void *data)
+static DBusHandlerResult rfcomm_connect_uuid_t(DBusConnection *conn, 
+					       DBusMessage *msg, 
+					       const char *dst, uuid_t *uuid,
+					       void *data)
 {
-	error("RFCOMM.CancelConnect not implemented");
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	int ch = -1;
+	DBusHandlerResult ret;
+	struct hci_dbus_data *dbus_data = data;
+	bdaddr_t bdaddr;
+	int err;
+
+	hci_devba(dbus_data->dev_id, &bdaddr);
+	
+	ret = rfcomm_get_ch_from_uuid_t(conn, msg, dst, uuid, &ch, data);
+
+	if (ret != DBUS_HANDLER_RESULT_HANDLED)
+		return ret;
+
+	if (find_pending_connect(dst, ch))
+		return error_connect_in_progress(conn, msg);
+	
+	if (rfcomm_connect(conn, msg, &bdaddr, dst, NULL, ch, &err) < 0)
+		return error_failed(conn, msg, err);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult rfcomm_cancel_connect_uuid_t(DBusConnection *conn, 
+						      DBusMessage *msg, 
+						      const char *dst, 
+						      uuid_t *uuid,
+						      void *data)
+{
+	int ch = -1;
+	DBusHandlerResult ret;
+	DBusMessage *reply;
+	struct hci_dbus_data *dbus_data = data;
+	struct pending_connect *pending;
+	bdaddr_t bdaddr;
+
+	hci_devba(dbus_data->dev_id, &bdaddr);
+	
+	ret = rfcomm_get_ch_from_uuid_t(conn, msg, dst, uuid, &ch, data);
+
+	if (ret != DBUS_HANDLER_RESULT_HANDLED)
+		return ret;
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return DBUS_HANDLER_RESULT_NEED_MEMORY;
+	
+	pending = find_pending_connect(dst, ch);
+	if (!pending)
+		return error_connect_in_progress(conn, msg);
+	
+	pending->canceled = 1;
+
+	return send_reply_and_unref(conn, reply);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult rfcomm_connect_uuid_req(DBusConnection *conn,
+						 DBusMessage *msg, void *data)
+{
+	uuid_t uuid;
+	const char *dst;
+	const char *string_uuid;
+	unsigned int data0, data4;
+	unsigned short data1, data2, data3, data5;
+
+	if (!dbus_message_get_args(msg, NULL,
+				   DBUS_TYPE_STRING, &dst,
+				   DBUS_TYPE_STRING, &string_uuid,
+				   DBUS_TYPE_INVALID))
+		return error_invalid_arguments(conn, msg);
+
+	sscanf (string_uuid, "%8x-%4hx-%4hx-%4hx-%8x%4hx", &data0, &data1, 
+		&data2, &data3,	&data4, &data5);
+
+	data0 = htonl(data0);
+	data1 = htons(data1);
+	data2 = htons(data2);
+	data3 = htons(data3);
+	data4 = htonl(data4);
+	data5 = htons(data5);
+
+	uuid.type = SDP_UUID128;
+	memcpy (&uuid.value.uuid128.data[0], &data0, 4);
+	memcpy (&uuid.value.uuid128.data[4], &data1, 2);
+	memcpy (&uuid.value.uuid128.data[6], &data2, 2);
+	memcpy (&uuid.value.uuid128.data[8], &data3, 2);
+	memcpy (&uuid.value.uuid128.data[10], &data4, 4);
+	memcpy (&uuid.value.uuid128.data[14], &data5, 2);
+
+	return rfcomm_connect_uuid_t(conn, msg, dst, &uuid, data);
+}
+
+static DBusHandlerResult rfcomm_cancel_connect_uuid_req(DBusConnection *conn,
+							DBusMessage *msg, 
+							void *data)
+{
+	uuid_t uuid;
+	const char *dst;
+	const char *string_uuid;
+	unsigned int data0, data4;
+	unsigned short data1, data2, data3, data5;
+
+	if (!dbus_message_get_args(msg, NULL,
+				   DBUS_TYPE_STRING, &dst,
+				   DBUS_TYPE_STRING, &string_uuid,
+				   DBUS_TYPE_INVALID))
+		return error_invalid_arguments(conn, msg);
+
+	sscanf (string_uuid, "%8x-%4hx-%4hx-%4hx-%8x%4hx", &data0, &data1, 
+		&data2, &data3,	&data4, &data5);
+
+	data0 = htonl(data0);
+	data1 = htons(data1);
+	data2 = htons(data2);
+	data3 = htons(data3);
+	data4 = htonl(data4);
+	data5 = htons(data5);
+
+	uuid.type = SDP_UUID128;
+	memcpy (&uuid.value.uuid128.data[0], &data0, 4);
+	memcpy (&uuid.value.uuid128.data[4], &data1, 2);
+	memcpy (&uuid.value.uuid128.data[6], &data2, 2);
+	memcpy (&uuid.value.uuid128.data[8], &data3, 2);
+	memcpy (&uuid.value.uuid128.data[10], &data4, 4);
+	memcpy (&uuid.value.uuid128.data[14], &data5, 2);
+
+	return rfcomm_cancel_connect_uuid_t(conn, msg, dst, &uuid, data);
+}
+
+static DBusHandlerResult rfcomm_connect_service_req(DBusConnection *conn,
+						    DBusMessage *msg, 
+						    void *data)
+{
+	char *dst;
+	char *service;
+	uuid_t short_uuid;
+	uuid_t *uuid;
+
+	if (!dbus_message_get_args(msg, NULL,
+				   DBUS_TYPE_STRING, &dst,
+				   DBUS_TYPE_STRING, &service,
+				   DBUS_TYPE_INVALID))
+		return error_invalid_arguments(conn, msg);
+	
+	short_uuid.type = SDP_UUID16;
+	short_uuid.value.uuid16 = sdp_str2svclass (service);
+
+	uuid = sdp_uuid_to_uuid128 (&short_uuid);
+
+	return rfcomm_connect_uuid_t(conn, msg, dst, uuid, data);
+}
+
+static DBusHandlerResult rfcomm_cancel_connect_service_req(DBusConnection *conn,
+							   DBusMessage *msg, 
+							   void *data)
+{
+	char *dst;
+	char *service;
+	uuid_t short_uuid;
+	uuid_t *uuid;
+
+	if (!dbus_message_get_args(msg, NULL,
+				   DBUS_TYPE_STRING, &dst,
+				   DBUS_TYPE_STRING, &service,
+				   DBUS_TYPE_INVALID))
+		return error_invalid_arguments(conn, msg);
+	
+	short_uuid.type = SDP_UUID16;
+	short_uuid.value.uuid16 = sdp_str2svclass (service);
+
+	uuid = sdp_uuid_to_uuid128 (&short_uuid);
+
+	return rfcomm_cancel_connect_uuid_t(conn, msg, dst, uuid, data);
+}
+
+static DBusHandlerResult rfcomm_connect_handle_req (DBusConnection *conn,
+						    DBusMessage *msg,
+						    void *data)
+{
+	int ch = -1;
+	const char *dst;
+	DBusHandlerResult ret;
+	int handle;
+	struct hci_dbus_data *dbus_data = data;
+	bdaddr_t bdaddr;
+	int err;
+
+	hci_devba(dbus_data->dev_id, &bdaddr);
+
+	if (!dbus_message_get_args(msg, NULL,
+				   DBUS_TYPE_STRING, &dst,
+				   DBUS_TYPE_UINT32, &handle,
+				   DBUS_TYPE_INVALID))
+		return error_invalid_arguments(conn, msg);
+
+	ret = rfcomm_get_ch_from_handle(conn, msg, dst, handle, &ch, data);
+
+	if (ret != DBUS_HANDLER_RESULT_HANDLED)
+		return ret;
+
+	if (find_pending_connect(dst, ch))
+		return error_connect_in_progress(conn, msg);
+	
+	if (rfcomm_connect(conn, msg, &bdaddr, dst, NULL, ch, &err) < 0)
+		return error_failed(conn, msg, err);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult rfcomm_cancel_connect_handle_req (DBusConnection *conn,
+							   DBusMessage *msg,
+							   void *data)
+{
+	int ch = -1;
+	const char *dst;
+	DBusHandlerResult ret;
+	DBusMessage *reply;
+	int handle;
+	struct hci_dbus_data *dbus_data = data;
+	bdaddr_t bdaddr;
+	struct pending_connect *pending;
+
+	hci_devba(dbus_data->dev_id, &bdaddr);
+
+	if (!dbus_message_get_args(msg, NULL,
+				   DBUS_TYPE_STRING, &dst,
+				   DBUS_TYPE_UINT32, &handle,
+				   DBUS_TYPE_INVALID))
+		return error_invalid_arguments(conn, msg);
+
+	ret = rfcomm_get_ch_from_handle(conn, msg, dst, handle, &ch, data);
+
+	if (ret != DBUS_HANDLER_RESULT_HANDLED)
+		return ret;
+
+	reply = dbus_message_new_method_return(msg);
+	if (!reply)
+		return DBUS_HANDLER_RESULT_NEED_MEMORY;
+	
+	pending = find_pending_connect(dst, ch);
+	if (!pending)
+		return error_connect_in_progress(conn, msg);
+	
+	pending->canceled = 1;
+
+	return send_reply_and_unref(conn, reply);
 }
 
 static DBusHandlerResult rfcomm_connect_by_ch_req(DBusConnection *conn,
@@ -685,8 +978,12 @@
 }
 
 static struct service_data rfcomm_services[] = {
-	{ "Connect",			rfcomm_connect_req,			},
-	{ "CancelConnect",		rfcomm_cancel_connect_req,		},
+	{ "ConnectByUUID",			rfcomm_connect_uuid_req,	},
+	{ "ConnectByService",			rfcomm_connect_service_req,	},
+	{ "ConnectByHandle",			rfcomm_connect_handle_req,	},
+	{ "CancelConnectByUUID",		rfcomm_cancel_connect_uuid_req,	},
+	{ "CancelConnectByService",		rfcomm_cancel_connect_service_req,	},
+	{ "CancelConnectByHandle",		rfcomm_cancel_connect_handle_req,	},
 	{ "ConnectByChannel",		rfcomm_connect_by_ch_req,		},
 	{ "CancelConnectByChannel",	rfcomm_cancel_connect_by_ch_req,	},
 	{ "Disconnect",			rfcomm_disconnect_req,			},
Index: dbus-sdp.c
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus-sdp.c,v
retrieving revision 1.9
diff -u -r1.9 dbus-sdp.c
--- dbus-sdp.c	18 Aug 2006 18:29:40 -0000	1.9
+++ dbus-sdp.c	19 Aug 2006 14:34:33 -0000
@@ -855,6 +855,77 @@
 
 }
 
+static int sdp_uuid_comp_func(const void *key1, const void *key2)
+{	
+	const uuid_t *a = (const uuid_t *)key1;
+	const uuid_t *b = (const uuid_t *)key2;
+
+	if (a->type != b->type)
+		return 1;
+	
+	switch (a->type) {
+	case SDP_UUID16:		
+		return !(a->value.uuid16 == b->value.uuid16);
+		break;
+        case SDP_UUID32:
+		return !(a->value.uuid32 == b->value.uuid32);
+		break;
+        case SDP_UUID128:
+		return !memcmp(&a->value.uuid128, &b->value.uuid128, 
+			       sizeof(uint128_t));
+		break;
+	}
+	return 1;
+}
+
+sdp_record_t *find_record_by_uuid(const char *address, uuid_t *uuid)
+{
+	struct slist *lp, *lr;
+	struct service_provider *p;
+	struct service_record *r;
+	sdp_list_t *list = 0;
+	
+
+	for (lp = sdp_cache; lp; lp = lp->next) {
+		p = lp->data;
+		if (strcmp(p->prov, address))
+			continue;
+
+		for (lr = p->lrec; lr; lr = lr->next) {
+			r = lr->data;
+			/* Check whether the record has the correct uuid */
+			if (sdp_get_service_classes(r->record, &list) !=0)
+				continue;
+			
+			if (sdp_list_find (list, &uuid, sdp_uuid_comp_func))
+				return r->record;
+		}
+	}
+
+	return NULL;
+}	
+
+sdp_record_t *find_record_by_handle(const char *address, int handle)
+{
+	struct slist *lp, *lr;
+	struct service_provider *p;
+	struct service_record *r;
+
+	for (lp = sdp_cache; lp; lp = lp->next) {
+		p = lp->data;
+		if (strcmp(p->prov, address))
+			continue;
+
+		for (lr = p->lrec; lr; lr = lr->next) {
+			r = lr->data;
+			if (r->record->handle == handle)
+				return r->record;
+		}
+	}
+
+	return NULL;
+}
+
 static sdp_record_t *find_record(const char *address, int id)
 {
 	struct slist *lp, *lr;
Index: dbus.h
===================================================================
RCS file: /cvsroot/bluez/utils/hcid/dbus.h,v
retrieving revision 1.98
diff -u -r1.98 dbus.h
--- dbus.h	19 Aug 2006 00:30:46 -0000	1.98
+++ dbus.h	19 Aug 2006 14:34:33 -0000
@@ -214,4 +214,8 @@
 
 int discoverable_timeout_handler(void *data);
 
+sdp_record_t *find_record_by_uuid(const char *address, uuid_t *uuid);
+sdp_record_t *find_record_by_handle(const char *address, int handle);
+uint16_t sdp_str2svclass(const char *str);
+
 #endif /* __H_BLUEZ_DBUS_H__ */

-- 
Matthew Garrett | mjg59@srcf.ucam.org

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

  parent reply	other threads:[~2006-08-19 14:36 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-08-17 10:06 [Bluez-devel] [PATCH] implement RFCOMM Connect and Disconnect methods Matthew Garrett
2006-08-17 13:04 ` Marcel Holtmann
2006-08-17 11:41   ` Matthew Garrett
2006-08-17 11:59     ` Johan Hedberg
2006-08-17 12:01       ` Matthew Garrett
2006-08-19 14:36       ` Matthew Garrett [this message]
2006-08-20  1:39         ` Marcel Holtmann
2006-08-19 23:53           ` Matthew Garrett
2006-08-20  2:13             ` Marcel Holtmann
2006-08-20  0:31               ` Matthew Garrett
2006-08-20  3:15                 ` Marcel Holtmann
2006-08-20 17:59                   ` Matthew Garrett
2006-08-23  6:21                     ` [Bluez-devel] RFComm auth/encrypt Denis KENZIOR
2006-08-23 20:13                     ` [Bluez-devel] [PATCH] implement RFCOMM Connect and Disconnect methods Johan Hedberg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060819143608.GA31812@srcf.ucam.org \
    --to=mjg59@srcf.ucam.org \
    --cc=bluez-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox