Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCHv5 17/19] android/socket: Add SPP uuid to profile table
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/socket.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index e3241c9..9358d4a 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -45,6 +45,7 @@
 #include "utils.h"
 #include "socket.h"
 
+#define SPP_DEFAULT_CHANNEL	3
 #define OPP_DEFAULT_CHANNEL	9
 #define PBAP_DEFAULT_CHANNEL	15
 #define MAS_DEFAULT_CHANNEL	16
@@ -197,7 +198,13 @@ static struct profile_info {
 			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
 		},
 		.channel = MAS_DEFAULT_CHANNEL
-	}
+	}, {
+		.uuid = {
+			0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
+			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+		},
+		.channel = SPP_DEFAULT_CHANNEL
+	},
 };
 
 static uint32_t sdp_service_register(struct profile_info *profile)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 16/19] android/socket: Add MAS uuid to profile table
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/socket.c |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 9890739..e3241c9 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -47,6 +47,7 @@
 
 #define OPP_DEFAULT_CHANNEL	9
 #define PBAP_DEFAULT_CHANNEL	15
+#define MAS_DEFAULT_CHANNEL	16
 
 /* Use Object Transfer for all services */
 #define SVC_HINT_OBEX 0x10
@@ -190,6 +191,12 @@ static struct profile_info {
 		.channel = OPP_DEFAULT_CHANNEL,
 		.svc_hint = SVC_HINT_OBEX,
 		.create_record = create_opp_record
+	}, {
+		.uuid = {
+			0x00, 0x00, 0x11, 0x32, 0x00, 0x00, 0x10, 0x00,
+			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+		},
+		.channel = MAS_DEFAULT_CHANNEL
 	}
 };
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 15/19] android/socket: Add SDP record for OPP profile
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

This adds SDP record for OPP shown below:

Service Name: OBEX Object Push
Service RecHandle: 0x10002
Service Class ID List:
  "OBEX Object Push" (0x1105)
Protocol Descriptor List:
  "RFCOMM" (0x0003)
    Channel: 9
  "OBEX" (0x0008)
Profile Descriptor List:
  "OBEX Object Push" (0x1105)
    Version: 0x0100
---
 android/socket.c |   99 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 98 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index d2588cc..9890739 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -35,7 +35,9 @@
 #include "lib/sdp.h"
 #include "lib/sdp_lib.h"
 #include "src/sdp-client.h"
+#include "src/sdpd.h"
 
+#include "bluetooth.h"
 #include "log.h"
 #include "hal-msg.h"
 #include "hal-ipc.h"
@@ -46,6 +48,9 @@
 #define OPP_DEFAULT_CHANNEL	9
 #define PBAP_DEFAULT_CHANNEL	15
 
+/* Use Object Transfer for all services */
+#define SVC_HINT_OBEX 0x10
+
 static bdaddr_t adapter_addr;
 
 /* Simple list of RFCOMM server sockets */
@@ -59,6 +64,7 @@ struct rfcomm_sock {
 	int real_sock;	/* real RFCOMM socket */
 	int channel;	/* RFCOMM channel */
 	bdaddr_t dst;
+	uint32_t service_handle;
 };
 
 static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
@@ -90,9 +96,79 @@ static void cleanup_rfsock(struct rfcomm_sock *rfsock)
 	if (rfsock->real_sock > 0)
 		close(rfsock->real_sock);
 
+	if (rfsock->service_handle)
+		bt_adapter_remove_record(rfsock->service_handle);
+
 	g_free(rfsock);
 }
 
+static sdp_record_t *create_opp_record(uint8_t chan)
+{
+	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+	uuid_t root_uuid, opush_uuid, rfcomm_uuid, obex_uuid;
+	sdp_profile_desc_t profile[1];
+	sdp_list_t *aproto, *proto[2];
+	uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xff };
+	void *dtds[sizeof(formats)], *values[sizeof(formats)];
+	unsigned int i;
+	uint8_t dtd = SDP_UINT8;
+	sdp_data_t *sflist;
+	sdp_data_t *channel;
+	sdp_record_t *record;
+
+	record = sdp_record_alloc();
+	if (!record)
+		return NULL;
+
+	record->handle =  sdp_next_handle();
+
+	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+	root = sdp_list_append(NULL, &root_uuid);
+	sdp_set_browse_groups(record, root);
+
+	sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
+	svclass_id = sdp_list_append(NULL, &opush_uuid);
+	sdp_set_service_classes(record, svclass_id);
+
+	sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
+	profile[0].version = 0x0100;
+	pfseq = sdp_list_append(NULL, profile);
+	sdp_set_profile_descs(record, pfseq);
+
+	sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+	proto[0] = sdp_list_append(NULL, &rfcomm_uuid);
+	channel = sdp_data_alloc(SDP_UINT8, &chan);
+	proto[0] = sdp_list_append(proto[0], channel);
+	apseq = sdp_list_append(NULL, proto[0]);
+
+	sdp_uuid16_create(&obex_uuid, OBEX_UUID);
+	proto[1] = sdp_list_append(NULL, &obex_uuid);
+	apseq = sdp_list_append(apseq, proto[1]);
+
+	aproto = sdp_list_append(NULL, apseq);
+	sdp_set_access_protos(record, aproto);
+
+	for (i = 0; i < sizeof(formats); i++) {
+		dtds[i] = &dtd;
+		values[i] = &formats[i];
+	}
+	sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
+	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
+
+	sdp_set_info_attr(record, "OBEX Object Push", NULL, NULL);
+
+	sdp_data_free(channel);
+	sdp_list_free(proto[0], NULL);
+	sdp_list_free(proto[1], NULL);
+	sdp_list_free(apseq, NULL);
+	sdp_list_free(pfseq, NULL);
+	sdp_list_free(aproto, NULL);
+	sdp_list_free(root, NULL);
+	sdp_list_free(svclass_id, NULL);
+
+	return record;
+}
+
 static struct profile_info {
 	uint8_t		uuid[16];
 	uint8_t		channel;
@@ -111,10 +187,29 @@ static struct profile_info {
 			0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
 			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
 		  },
-		.channel = OPP_DEFAULT_CHANNEL
+		.channel = OPP_DEFAULT_CHANNEL,
+		.svc_hint = SVC_HINT_OBEX,
+		.create_record = create_opp_record
 	}
 };
 
+static uint32_t sdp_service_register(struct profile_info *profile)
+{
+	sdp_record_t *record;
+
+	record = profile->create_record(profile->channel);
+	if (!record)
+		return 0;
+
+	if (bt_adapter_add_record(record, profile->svc_hint) < 0) {
+		error("Failed to register on SDP record");
+		sdp_record_free(record);
+		return 0;
+	}
+
+	return record->handle;
+}
+
 static int bt_sock_send_fd(int sock_fd, const void *buf, int len, int send_fd)
 {
 	ssize_t ret;
@@ -387,6 +482,8 @@ static int handle_listen(void *buf)
 		return -1;
 	}
 
+	rfsock->service_handle = sdp_service_register(profile);
+
 	DBG("real_sock %d fd %d hal_fd %d",
 				rfsock->real_sock, rfsock->fd, hal_fd);
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 14/19] android/socket: Close file descriptor after sending
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/socket.c |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index ee2df1b..d2588cc 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -576,6 +576,7 @@ void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
 			break;
 
 		ipc_send(sk, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+		close(fd);
 		return;
 	case HAL_OP_SOCK_CONNECT:
 		fd = handle_connect(buf);
@@ -583,6 +584,7 @@ void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
 			break;
 
 		ipc_send(sk, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+		close(fd);
 		return;
 	default:
 		DBG("Unhandled command, opcode 0x%x", opcode);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 13/19] android/socket: Send connect signal on connect
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Android framework expects connect signal to be sent when
remote device is connected.
---
 android/socket.c |   30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index e620d10..ee2df1b 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -393,6 +393,33 @@ static int handle_listen(void *buf)
 	return hal_fd;
 }
 
+static ssize_t sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
+{
+	struct hal_sock_connect_signal cmd;
+	ssize_t len;
+
+	DBG("");
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.size = sizeof(cmd);
+	bdaddr2android(bdaddr, cmd.bdaddr);
+	cmd.channel = rfsock->channel;
+	cmd.status = 0;
+
+	len = write(rfsock->fd, &cmd, sizeof(cmd));
+	if (len < 0) {
+		error("%s", strerror(errno));
+		return len;
+	}
+
+	if (len != (ssize_t) sizeof(cmd)) {
+		error("Error sending connect signal");
+		return -1;
+	}
+
+	return len;
+}
+
 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	struct rfcomm_sock *rfsock = user_data;
@@ -423,6 +450,9 @@ static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 		rfsock->fd, rfsock->real_sock, rfsock->channel,
 		g_io_channel_unix_get_fd(io));
 
+	if (sock_send_connect(rfsock, &dst) < 0)
+		goto fail;
+
 	/* Handle events from Android */
 	io_stack = g_io_channel_unix_new(rfsock->fd);
 	g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 12/19] android/socket: Send RFCOMM channel to framework
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Framework expects channel to be send.
---
 android/socket.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index ad09a2c..e620d10 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -493,6 +493,11 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
 		goto fail;
 	}
 
+	if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+		error("Error sending RFCOMM channel");
+		goto fail;
+	}
+
 	rfsock->real_sock = g_io_channel_unix_get_fd(io);
 	rfsock->channel = chan;
 	connections = g_list_append(connections, rfsock);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 11/19] android/socket: Implement HAL connect call
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

HAL connect uses similar event handlers like listen call.
---
 android/socket.c |   41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 6d9c69e..ad09a2c 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -395,6 +395,47 @@ static int handle_listen(void *buf)
 
 static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
+	struct rfcomm_sock *rfsock = user_data;
+	GIOChannel *io_stack;
+	GError *gerr = NULL;
+	bdaddr_t dst;
+	char address[18];
+	int chan = -1;
+
+	if (err) {
+		error("%s", err->message);
+		goto fail;
+	}
+
+	bt_io_get(io, &gerr,
+			BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		goto fail;
+	}
+
+	ba2str(&dst, address);
+	DBG("Connected to %s rfsock %p chan %d", address, rfsock, chan);
+
+	DBG("rfsock: fd %d real_sock %d chan %u sock %d",
+		rfsock->fd, rfsock->real_sock, rfsock->channel,
+		g_io_channel_unix_get_fd(io));
+
+	/* Handle events from Android */
+	io_stack = g_io_channel_unix_new(rfsock->fd);
+	g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+						sock_stack_event_cb, rfsock);
+	g_io_channel_unref(io_stack);
+
+	/* Handle rfcomm events */
+	g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+				sock_rfcomm_event_cb, rfsock);
+
+	return;
+fail:
+	cleanup_rfsock(rfsock);
 }
 
 static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
-- 
1.7.10.4


^ permalink raw reply related

* Re: [PATCH 3/5] android: Handle multiple init(register) and cleanup(unregister) calls properly
From: Johan Hedberg @ 2013-11-19 13:30 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384863676-12358-3-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
> @@ -2275,6 +2275,9 @@ bool bt_bluetooth_register(int sk)
>  {
>  	DBG("");
>  
> +	if (notification_sk > 0)

0 is a valid file descriptor value so the check should be >= 0

> @@ -1190,6 +1190,9 @@ bool bt_hid_register(int sk, const bdaddr_t *addr)
>  
>  	DBG("");
>  
> +	if (notification_sk > 0)
> +		return false;

Same here.

> @@ -95,6 +95,9 @@ bool bt_pan_register(int sk, const bdaddr_t *addr)
>  {
>  	DBG("");
>  
> +	if (notification_sk > 0)
> +		return false;

And here.

Johan

^ permalink raw reply

* [PATCHv5 10/19] android/socket: Parse SDP response and connect
From: Andrei Emeltchenko @ 2013-11-19 13:30 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Parse SDP response, find RFCOMM channel and connect.
---
 android/socket.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 843fba8..6d9c69e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -393,9 +393,72 @@ static int handle_listen(void *buf)
 	return hal_fd;
 }
 
+static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+}
+
 static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
 {
+	struct rfcomm_sock *rfsock = data;
+	GError *gerr = NULL;
+	sdp_list_t *list;
+	GIOChannel *io;
+	int chan;
+
 	DBG("");
+
+	if (err < 0) {
+		error("Unable to get SDP record: %s", strerror(-err));
+		goto fail;
+	}
+
+	if (!recs || !recs->data) {
+		error("No SDP records found");
+		goto fail;
+	}
+
+	for (list = recs; list != NULL; list = list->next) {
+		sdp_record_t *rec = list->data;
+		sdp_list_t *protos;
+
+		if (sdp_get_access_protos(rec, &protos) < 0) {
+			error("Unable to get proto list");
+			goto fail;
+		}
+
+		chan = 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 (chan <= 0) {
+		error("Could not get RFCOMM channel %d", chan);
+		goto fail;
+	}
+
+	DBG("Got RFCOMM channel %d", chan);
+
+	io = bt_io_connect(connect_cb, rfsock, NULL, &gerr,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_DEST_BDADDR, &rfsock->dst,
+				BT_IO_OPT_CHANNEL, chan,
+				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+				BT_IO_OPT_INVALID);
+	if (!io) {
+		error("Failed connect: %s", gerr->message);
+		g_error_free(gerr);
+		goto fail;
+	}
+
+	rfsock->real_sock = g_io_channel_unix_get_fd(io);
+	rfsock->channel = chan;
+	connections = g_list_append(connections, rfsock);
+	return;
+
+fail:
+	cleanup_rfsock(rfsock);
 }
 
 static int handle_connect(void *buf)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 09/19] android/socket: Implement socket connect HAL method
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

First step is to query remote device for RFCOMM channel.
---
 android/socket.c |   34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/android/socket.c b/android/socket.c
index e4479e5..843fba8 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -33,6 +33,9 @@
 #include "lib/bluetooth.h"
 #include "btio/btio.h"
 #include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+#include "src/sdp-client.h"
+
 #include "log.h"
 #include "hal-msg.h"
 #include "hal-ipc.h"
@@ -55,6 +58,7 @@ struct rfcomm_sock {
 	int fd;		/* descriptor for communication with Java framework */
 	int real_sock;	/* real RFCOMM socket */
 	int channel;	/* RFCOMM channel */
+	bdaddr_t dst;
 };
 
 static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
@@ -389,11 +393,37 @@ static int handle_listen(void *buf)
 	return hal_fd;
 }
 
+static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+{
+	DBG("");
+}
+
 static int handle_connect(void *buf)
 {
-	DBG("Not implemented");
+	struct hal_cmd_sock_connect *cmd = buf;
+	struct rfcomm_sock *rfsock;
+	bdaddr_t dst;
+	uuid_t uuid;
+	int hal_fd = -1;
+
+	DBG("");
+
+	android2bdaddr(cmd->bdaddr, &dst);
+	rfsock = create_rfsock(-1, &hal_fd);
+	bacpy(&rfsock->dst, &dst);
 
-	return -1;
+	memset(&uuid, 0, sizeof(uuid));
+	uuid.type = SDP_UUID128;
+	memcpy(&uuid.value.uuid128, cmd->uuid, sizeof(uint128_t));
+
+	if (bt_search_service(&adapter_addr, &dst, &uuid, sdp_search_cb, rfsock,
+								NULL) < 0) {
+		error("Failed to search SDP records");
+		cleanup_rfsock(rfsock);
+		return -1;
+	}
+
+	return hal_fd;
 }
 
 void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 08/19] android/socket: Write channel to Android fd
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Android framework expects to receive channel number as int.
---
 android/socket.c |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 936b70e..e4479e5 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -376,6 +376,13 @@ static int handle_listen(void *buf)
 	rfsock->real_sock = g_io_channel_unix_get_fd(io);
 	servers = g_list_append(servers, rfsock);
 
+	/* TODO: Check this */
+	if (write(rfsock->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+		error("Error sending RFCOMM channel");
+		cleanup_rfsock(rfsock);
+		return -1;
+	}
+
 	DBG("real_sock %d fd %d hal_fd %d",
 				rfsock->real_sock, rfsock->fd, hal_fd);
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 07/19] android/socket: Send accept signal to Android through hal_fd
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Android expects to get accept signal over file descriptor which was
set during listen HAL call.
---
 android/socket.c |   57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 5e77c66..936b70e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -37,6 +37,7 @@
 #include "hal-msg.h"
 #include "hal-ipc.h"
 #include "ipc.h"
+#include "utils.h"
 #include "socket.h"
 
 #define OPP_DEFAULT_CHANNEL	9
@@ -110,6 +111,45 @@ static struct profile_info {
 	}
 };
 
+static int bt_sock_send_fd(int sock_fd, const void *buf, int len, int send_fd)
+{
+	ssize_t ret;
+	struct msghdr msg;
+	struct cmsghdr *cmsg;
+	struct iovec iv;
+	char msgbuf[CMSG_SPACE(1)];
+
+	DBG("len %d sock_fd %d send_fd %d", len, sock_fd, send_fd);
+
+	if (sock_fd == -1 || send_fd == -1)
+		return -1;
+
+	memset(&msg, 0, sizeof(msg));
+
+	msg.msg_control = msgbuf;
+	msg.msg_controllen = sizeof(msgbuf);
+	cmsg = CMSG_FIRSTHDR(&msg);
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	cmsg->cmsg_len = CMSG_LEN(sizeof(send_fd));
+	memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(send_fd));
+
+	iv.iov_base = (unsigned char *) buf;
+	iv.iov_len = len;
+
+	msg.msg_iov = &iv;
+	msg.msg_iovlen = 1;
+
+	ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL);
+	if (ret < 0) {
+		error("sendmsg(): sock_fd %d send_fd %d: %s",
+					sock_fd, send_fd, strerror(errno));
+		return ret;
+	}
+
+	return ret;
+}
+
 static struct profile_info *get_profile_by_uuid(const uint8_t *uuid)
 {
 	unsigned int i;
@@ -231,6 +271,21 @@ static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
 	return TRUE;
 }
 
+static void sock_send_accept(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr,
+							int fd_accepted)
+{
+	struct hal_sock_connect_signal cmd;
+
+	DBG("");
+
+	cmd.size = sizeof(cmd);
+	bdaddr2android(bdaddr, cmd.bdaddr);
+	cmd.channel = rfsock->channel;
+	cmd.status = 0;
+
+	bt_sock_send_fd(rfsock->fd, &cmd, sizeof(cmd), fd_accepted);
+}
+
 static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
 	struct rfcomm_sock *rfsock = user_data;
@@ -268,6 +323,8 @@ static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
 		rfsock->fd, rfsock->real_sock, rfsock->channel,
 		sock_acc);
 
+	sock_send_accept(rfsock, &dst, hal_fd);
+
 	/* Handle events from Android */
 	io_stack = g_io_channel_unix_new(rfsock_acc->fd);
 	g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 06/19] android/socket: Implement RFCOMM events
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Copy data from RFCOMM socket to Android framework. Consider splice
in the future.
---
 android/socket.c |   37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 45f6e5c..5e77c66 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -191,6 +191,43 @@ static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
 static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
 								gpointer data)
 {
+	struct rfcomm_sock *rfsock = data;
+	unsigned char buf[1024];
+	int len, sent;
+
+	DBG("rfsock: fd %d real_sock %d chan %u sock %d",
+		rfsock->fd, rfsock->real_sock, rfsock->channel,
+		g_io_channel_unix_get_fd(io));
+
+	if (!g_list_find(connections, rfsock)) {
+		error("rfsock %p not found in the list", rfsock);
+		return FALSE;
+	}
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		error("Socket error: sock %d cond %d",
+					g_io_channel_unix_get_fd(io), cond);
+		connections = g_list_remove(connections, rfsock);
+		cleanup_rfsock(rfsock);
+		return FALSE;
+	}
+
+	len = read(rfsock->real_sock, buf, sizeof(buf));
+	if (len <= 0) {
+		error("read(): %s", strerror(errno));
+		return FALSE;
+	}
+
+	DBG("read %d bytes, write to fd %d", len, rfsock->fd);
+
+	sent = try_write_all(rfsock->fd, buf, len);
+	if (sent < 0) {
+		error("write(): %s", strerror(errno));
+		return FALSE;
+	}
+
+	DBG("Written %d bytes", sent);
+
 	return TRUE;
 }
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 05/19] android/socket: Implement Android RFCOMM stack events
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

Handle events from Android framework. Write everything to real RFCOMM
socket. Consider splice() in the future.
---
 android/socket.c |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 04f0a7b..45f6e5c 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -122,9 +122,69 @@ static struct profile_info *get_profile_by_uuid(const uint8_t *uuid)
 	return NULL;
 }
 
+static int try_write_all(int fd, unsigned char *buf, int len)
+{
+	int sent = 0;
+
+	while (len > 0) {
+		int written;
+
+		written = write(fd, buf, len);
+		if (written < 0) {
+			if (errno == EINTR || errno == EAGAIN)
+				continue;
+			return -1;
+		}
+
+		if (!written)
+			return 0;
+
+		len -= written; buf += written; sent += written;
+	}
+
+	return sent;
+}
+
 static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
 								gpointer data)
 {
+	struct rfcomm_sock *rfsock = data;
+	unsigned char buf[1024];
+	int len, sent;
+
+	DBG("rfsock: fd %d real_sock %d chan %u sock %d",
+		rfsock->fd, rfsock->real_sock, rfsock->channel,
+		g_io_channel_unix_get_fd(io));
+
+	if (!g_list_find(connections, rfsock)) {
+		error("rfsock %p not found in the list", rfsock);
+		return FALSE;
+	}
+
+	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
+		error("Socket error: sock %d cond %d",
+					g_io_channel_unix_get_fd(io), cond);
+		connections = g_list_remove(connections, rfsock);
+		cleanup_rfsock(rfsock);
+		return FALSE;
+	}
+
+	len = read(rfsock->fd, buf, sizeof(buf));
+	if (len <= 0) {
+		error("read(): %s", strerror(errno));
+		return FALSE;
+	}
+
+	DBG("read %d bytes write to %d", len, rfsock->real_sock);
+
+	sent = try_write_all(rfsock->real_sock, buf, len);
+	if (sent < 0) {
+		error("write(): %s", strerror(errno));
+		return FALSE;
+	}
+
+	DBG("Written %d bytes", sent);
+
 	return TRUE;
 }
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 04/19] android/socket: Implement socket accepted event
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

When we get accepted event we create rfcomm slot and start listening
for events from Android framework and from RFCOMM real socket.
---
 android/socket.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/android/socket.c b/android/socket.c
index 9e9acc9..04f0a7b 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -122,8 +122,66 @@ static struct profile_info *get_profile_by_uuid(const uint8_t *uuid)
 	return NULL;
 }
 
+static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
+								gpointer data)
+{
+	return TRUE;
+}
+
+static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
+								gpointer data)
+{
+	return TRUE;
+}
+
 static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
 {
+	struct rfcomm_sock *rfsock = user_data;
+	struct rfcomm_sock *rfsock_acc;
+	GIOChannel *io_stack;
+	GError *gerr = NULL;
+	bdaddr_t dst;
+	char address[18];
+	int sock_acc;
+	int hal_fd;
+
+	if (err) {
+		error("%s", err->message);
+		return;
+	}
+
+	bt_io_get(io, &gerr,
+			BT_IO_OPT_DEST_BDADDR, &dst,
+			BT_IO_OPT_INVALID);
+	if (gerr) {
+		error("%s", gerr->message);
+		g_error_free(gerr);
+		g_io_channel_shutdown(io, TRUE, NULL);
+		return;
+	}
+
+	ba2str(&dst, address);
+	DBG("Incoming connection from %s rfsock %p", address, rfsock);
+
+	sock_acc = g_io_channel_unix_get_fd(io);
+	rfsock_acc = create_rfsock(sock_acc, &hal_fd);
+	connections = g_list_append(connections, rfsock_acc);
+
+	DBG("rfsock: fd %d real_sock %d chan %u sock %d",
+		rfsock->fd, rfsock->real_sock, rfsock->channel,
+		sock_acc);
+
+	/* Handle events from Android */
+	io_stack = g_io_channel_unix_new(rfsock_acc->fd);
+	g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+					sock_stack_event_cb, rfsock_acc);
+	g_io_channel_unref(io_stack);
+
+	/* Handle rfcomm events */
+	g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+				sock_rfcomm_event_cb, rfsock_acc);
+
+	DBG("rfsock %p rfsock_acc %p", rfsock, rfsock_acc);
 }
 
 static int handle_listen(void *buf)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 03/19] android/socket: Define structs and implement listen
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

This defines structures for socket HAL. We need to emulate Android
sockets by sending connect/accept signals over file descriptor.
Handle HAL socket listen call. Create RFCOMM socket and wait for events.
---
 android/socket.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index d4c7674..9e9acc9 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -27,6 +27,7 @@
 
 #include <glib.h>
 #include <stdbool.h>
+#include <unistd.h>
 #include <errno.h>
 
 #include "lib/bluetooth.h"
@@ -43,6 +44,50 @@
 
 static bdaddr_t adapter_addr;
 
+/* Simple list of RFCOMM server sockets */
+GList *servers = NULL;
+
+/* Simple list of RFCOMM connected sockets */
+GList *connections = NULL;
+
+struct rfcomm_sock {
+	int fd;		/* descriptor for communication with Java framework */
+	int real_sock;	/* real RFCOMM socket */
+	int channel;	/* RFCOMM channel */
+};
+
+static struct rfcomm_sock *create_rfsock(int sock, int *hal_fd)
+{
+	int fds[2] = {-1, -1};
+	struct rfcomm_sock *rfsock;
+
+	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
+		error("socketpair(): %s", strerror(errno));
+		*hal_fd = -1;
+		return NULL;
+	}
+
+	rfsock = g_new0(struct rfcomm_sock, 1);
+	rfsock->fd = fds[0];
+	*hal_fd = fds[1];
+	rfsock->real_sock = sock;
+
+	return rfsock;
+}
+
+static void cleanup_rfsock(struct rfcomm_sock *rfsock)
+{
+	DBG("rfsock: %p fd %d real_sock %d chan %u",
+		rfsock, rfsock->fd, rfsock->real_sock, rfsock->channel);
+
+	if (rfsock->fd > 0)
+		close(rfsock->fd);
+	if (rfsock->real_sock > 0)
+		close(rfsock->real_sock);
+
+	g_free(rfsock);
+}
+
 static struct profile_info {
 	uint8_t		uuid[16];
 	uint8_t		channel;
@@ -77,10 +122,18 @@ static struct profile_info *get_profile_by_uuid(const uint8_t *uuid)
 	return NULL;
 }
 
+static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
+{
+}
+
 static int handle_listen(void *buf)
 {
 	struct hal_cmd_sock_listen *cmd = buf;
 	struct profile_info *profile;
+	struct rfcomm_sock *rfsock;
+	GIOChannel *io;
+	GError *err = NULL;
+	int hal_fd;
 	int chan;
 
 	DBG("");
@@ -93,7 +146,28 @@ static int handle_listen(void *buf)
 
 	DBG("rfcomm channel %d", chan);
 
-	return -1;
+	rfsock = create_rfsock(-1, &hal_fd);
+	if (!rfsock)
+		return -1;
+
+	io = bt_io_listen(accept_cb, NULL, rfsock, NULL, &err,
+				BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+				BT_IO_OPT_CHANNEL, chan,
+				BT_IO_OPT_INVALID);
+	if (!io) {
+		error("Failed listen: %s", err->message);
+		g_error_free(err);
+		cleanup_rfsock(rfsock);
+		return -1;
+	}
+
+	rfsock->real_sock = g_io_channel_unix_get_fd(io);
+	servers = g_list_append(servers, rfsock);
+
+	DBG("real_sock %d fd %d hal_fd %d",
+				rfsock->real_sock, rfsock->fd, hal_fd);
+
+	return hal_fd;
 }
 
 static int handle_connect(void *buf)
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 02/19] android/socket: Add get RFCOMM default channel
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

RFCOMM default channel is the same like in other BlueZ code, it is
defined in src/profile.c
---
 android/socket.c |   54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/android/socket.c b/android/socket.c
index 04bb7d1..d4c7674 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -27,19 +27,71 @@
 
 #include <glib.h>
 #include <stdbool.h>
+#include <errno.h>
 
 #include "lib/bluetooth.h"
+#include "btio/btio.h"
+#include "lib/sdp.h"
 #include "log.h"
 #include "hal-msg.h"
 #include "hal-ipc.h"
 #include "ipc.h"
 #include "socket.h"
 
+#define OPP_DEFAULT_CHANNEL	9
+#define PBAP_DEFAULT_CHANNEL	15
+
 static bdaddr_t adapter_addr;
 
+static struct profile_info {
+	uint8_t		uuid[16];
+	uint8_t		channel;
+	uint8_t		svc_hint;
+	BtIOSecLevel	sec_level;
+	sdp_record_t *	(*create_record)(uint8_t chan);
+} profiles[] = {
+	{
+		.uuid = {
+			0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
+			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+		},
+		.channel = PBAP_DEFAULT_CHANNEL
+	}, {
+		.uuid = {
+			0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
+			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+		  },
+		.channel = OPP_DEFAULT_CHANNEL
+	}
+};
+
+static struct profile_info *get_profile_by_uuid(const uint8_t *uuid)
+{
+	unsigned int i;
+
+	for (i = 0; i < G_N_ELEMENTS(profiles); i++) {
+		if (!memcmp(profiles[i].uuid, uuid, 16))
+			return &profiles[i];
+	}
+
+	return NULL;
+}
+
 static int handle_listen(void *buf)
 {
-	DBG("Not implemented");
+	struct hal_cmd_sock_listen *cmd = buf;
+	struct profile_info *profile;
+	int chan;
+
+	DBG("");
+
+	profile = get_profile_by_uuid(cmd->uuid);
+	if (!profile)
+		return -1;
+
+	chan = profile->channel;
+
+	DBG("rfcomm channel %d", chan);
 
 	return -1;
 }
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 01/19] android/hal-sock: Print bdaddr string instead of pointer
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <1384867809-18135-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

---
 android/hal-sock.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/android/hal-sock.c b/android/hal-sock.c
index eafa451..bd88ad8 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -77,8 +77,8 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
 	struct hal_cmd_sock_connect cmd;
 
 	if ((!uuid && chan <= 0) || !bdaddr || !sock) {
-		error("Invalid params: bd_addr %p, uuid %s, chan %d, sock %p",
-					bdaddr, btuuid2str(uuid), chan, sock);
+		error("Invalid params: bd_addr %s, uuid %s, chan %d, sock %p",
+			bdaddr2str(bdaddr), btuuid2str(uuid), chan, sock);
 		return BT_STATUS_PARM_INVALID;
 	}
 
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv5 00/19] Socket HAL
From: Andrei Emeltchenko @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth

From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>

This is initial code implementing socket HAL. OPP currently works with send/receive files. Probaly
other profiles works as well, not tested yet.

Changes:
	* v5: Changed uuid_to_chan table to profile table keeping information about profile like: channel, create_record,
	svc_hint and sec_level.
	* v4: Changed name rfslot -> rfsock following Johan's comment and other cosmetic changes, fixed one bug in SDP
	record, use NULL instead of 0 for sdp functions.
	* v3: Fixed coding style with write/send between file descriptors.
	* v2: Following Marcel comments changed way copying between file descriptors works, added SDP record
	for OPP and now it is possible to send files through GUI. Merged one patch with structures with actual user.
	* v1: Rebased and use static src address, hal_fd removed from structure and closed after sent to framework,
	added connect calls and SDP parsing, added cleanup_rfcomm function, minor fixes.
	* RFC Initial

TODO:
	* Use sec_level / check what to do with Android supplied security flags.
	* Use splice() (requires bionic change first)

For tracking rfcomm sockets I use structure rfslot which has following
fields:
 - real_sock - real RFCOMM socket
 - fd - fd to communicate with Android framework

create_rfslot sets hal_fd which is fd passed to Android framework with CMSG

Andrei Emeltchenko (19):
  android/hal-sock: Print bdaddr string instead of pointer
  android/socket: Add get RFCOMM default channel
  android/socket: Define structs and implement listen
  android/socket: Implement socket accepted event
  android/socket: Implement Android RFCOMM stack events
  android/socket: Implement RFCOMM events
  android/socket: Send accept signal to Android through hal_fd
  android/socket: Write channel to Android fd
  android/socket: Implement socket connect HAL method
  android/socket: Parse SDP response and connect
  android/socket: Implement HAL connect call
  android/socket: Send RFCOMM channel to framework
  android/socket: Send connect signal on connect
  android/socket: Close file descriptor after sending
  android/socket: Add SDP record for OPP profile
  android/socket: Add MAS uuid to profile table
  android/socket: Add SPP uuid to profile table
  android/socket: Add PBAP SDP record
  android/socket: Add SPP SDP record

 android/hal-sock.c |    4 +-
 android/socket.c   |  760 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 758 insertions(+), 6 deletions(-)

-- 
1.7.10.4


^ permalink raw reply

* Re: autopair corner cases
From: Bastien Nocera @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: deymo, Scott James Remnant
In-Reply-To: <1384864264.2027.22.camel@nuvo>

On Tue, 2013-11-19 at 13:31 +0100, Bastien Nocera wrote:
> Heya,
> 
> There's a bunch of corner cases that the autopair plugin doesn't handle
> and that we used to handle in gnome-bluetooth with BlueZ 4.x.
> 
> 1) First is the case of the PS3 BD Remote that will reject
> authentication when you try to pair to it. gnome-bluetooth knows not to
> pair with it.
> 
> >        <!-- Sony PlayStation 3 Remote Control -->
> >         <device oui="00:19:C1:" name="BD Remote Control" pin="NULL"/>
> >         <device oui="00:1E:3D:" name="BD Remote Control" pin="NULL"/>
> >         <device oui="00:06:F5:" name="BD Remote Control" pin="NULL"/>
> 
> Is there a way to say "we can't actually pair" when the client requested
> pairing already? Or is that considered a security problem?

I've left the handling in gnome-bluetooth for this one.

> 2) The second case is pairing this "funny" keyboard that's the iCade
> controller. In gnome-bluetooth, we had special code to generate only
> joystick movements for the pairing, rather than hard to determine
> buttons, so we'd end up with a 6-digit pin using only 1 through 4.
> 
> >         <!-- ION iCade Game Controller -->
> >         <device name="iCade" type="keyboard" pin="ICADE"/>

I've sent a patch for that one.

> 3) We have a whole list of GPS that don't use present themselves as
> anything special apart from the name. Most use "0000", but some use
> things like "NAVMAN" or "12345678"
> 
> >         <!-- http://bugzilla.gnome.org/show_bug.cgi?id=560315#c20 -->
> >         <device oui="00:02:5B:" name="Pharos iGPS-BT" pin="12345678"/>
> > 
> >         <!-- https://bugzilla.gnome.org/show_bug.cgi?id=613698 -->
> >         <device oui="00:0C:A5:" name="NAVMAN GPS ONE" pin="NAVMAN"/>

I will leave those in gnome-bluetooth as well, as autopair will not
handle those.

> 4) Audio devices will mostly already be supported by the autopair code
> (yay!), though we have a few stragglers, most notably this speaker that
> can use random pincode, as long as they're only 4 digits in length:
> 
> >         <!-- http://bugzilla.gnome.org/show_bug.cgi?id=583651 -->
> >         <device type="audio" oui="00:1A:80:" name="CMT-DH5BT" pin="max:4"/>

I will carry on handling this in gnome-bluetooth, as the pincodes aren't
displayed for audio devices. So it will try "0000" which will fail, and
bluetoothd should fall back to asking us for the pincode, which we'll
generate according to this rule.

> 5) Printers are missing from the list, that should be an easy fix.

Sent a patch for that.

There's one case left for me to handle.

6) I have a "TomTom Remote" that shows up as a keyboard and uses "0000"
as its PIN. The problem is that, as per the code in autopair.c we'll
first show a random pincode then quickly fall back to using "0000":
> /* For keyboards rejecting the first random code
>  * in less than 500ms, try a fixed code. */

How does ChromeOS present this? Does it wait half a second before
showing the pincode to enter? Because flashing an unusable pincode on
the screen before succeeding pairing is pretty rubbish in my opinion...

Cheers


^ permalink raw reply

* [PATCH] autopair: Generate a specific pincode for the iCade
From: Bastien Nocera @ 2013-11-19 13:29 UTC (permalink / raw)
  To: linux-bluetooth


We can't easily enter digits other than 1 through 4 (inclusive)
so generate a random pincode that it will be possible to enter.
---
 plugins/autopair.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/plugins/autopair.c b/plugins/autopair.c
index 8c98c12..168a873 100644
--- a/plugins/autopair.c
+++ b/plugins/autopair.c
@@ -57,13 +57,32 @@ static ssize_t autopair_pincb(struct btd_adapter *adapter,
 {
 	char addr[18];
 	char pinstr[7];
+	char name[25];
 	uint32_t class;
 
 	ba2str(device_get_address(device), addr);
 
 	class = btd_device_get_class(device);
 
-	DBG("device %s 0x%x", addr, class);
+	device_get_name(device, name, sizeof(name));
+	name[sizeof(name) - 1] = 0;
+
+	DBG("device %s (%s) 0x%x", addr, name, class);
+
+	/* Only try this special PIN for the first attempt */
+	if (attempt == 0) {
+		if (g_str_equal(name, "iCade")) {
+			guint i;
+
+			for (i = 0; i < 6; i++) {
+				/* '1', '2', '3' or '4' */
+				pinbuf[i] = g_random_int_range('1', '5');
+			}
+			pinbuf[6] = 0;
+			*display = true;
+			return 6;
+		}
+	}
 
 	/* This is a class-based pincode guesser. Ignore devices with an
 	 * unknown class.
-- 
1.8.4.2



^ permalink raw reply related

* Re: [PATCH 2/5] android/hal-pan: Return error in case of unsupported PAN roles
From: Johan Hedberg @ 2013-11-19 13:27 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384863676-12358-2-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
> ---
>  android/hal-pan.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/android/hal-pan.c b/android/hal-pan.c
> index 2bc560e..30facd4 100644
> --- a/android/hal-pan.c
> +++ b/android/hal-pan.c
> @@ -77,6 +77,9 @@ static bt_status_t pan_enable(int local_role)
>  	if (!interface_ready())
>  		return BT_STATUS_NOT_READY;
>  
> +	if (!(local_role == BTPAN_ROLE_PANU || local_role == BTPAN_ROLE_PANNAP))
> +		return BT_STATUS_UNSUPPORTED;
> +
>  	cmd.local_role = local_role;
>  
>  	return hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE,
> @@ -112,6 +115,14 @@ static bt_status_t pan_connect(const bt_bdaddr_t *bd_addr, int local_role,
>  	if (!interface_ready())
>  		return BT_STATUS_NOT_READY;
>  
> +	if (!((local_role == BTPAN_ROLE_PANNAP &&
> +			remote_role == BTPAN_ROLE_PANU) ||
> +		(local_role == BTPAN_ROLE_PANU &&
> +			remote_role == BTPAN_ROLE_PANNAP) ||
> +		(local_role == BTPAN_ROLE_PANU &&
> +			remote_role == BTPAN_ROLE_PANU)))
> +		return BT_STATUS_UNSUPPORTED;

First of all you've got incorrect indentation here which make this hard
to read (the return statement being on the same column as parts of the
if-statement. When you break lines indent at least by two tabs to make
a clear separation from the actual branch code.

Secondly, shouldn't we be checking that the given local role has been
enabled (through pan_enable)? Or does the daemon do that checking? In
fact is there a clear reason not to let the daemon do all the
verification checks and return an error status over IPC?

Thirdly, this if-statement takes a while to parse, so I'm wondering
whether it'd be clearer to format it in a bit more readable way, e.g.:

        switch (local_role) {
        case BTPAN_ROLE_PANNAP:
                if (remote_role != BTPAN_ROLE_PANU)
                        return BT_STATUS_UNSUPPORTED;
                break;
        case BTPAN_ROLE_PANU:
                if (remote_role != BTPAN_ROLE_PANNAP &&
                                                remote_role != BTPAN_ROLE_PANU)
                        return BT_STATUS_UNSUPPORTED;
                break;
        default:
                return BT_STATUS_UNSUPPORTED;
        }

Thoughts?

Johan

^ permalink raw reply

* Re: [PATCH 1/5] android/pan: Fix wrong struct parameter in disconnect function call
From: Johan Hedberg @ 2013-11-19 13:23 UTC (permalink / raw)
  To: Ravi kumar Veeramally; +Cc: linux-bluetooth
In-Reply-To: <1384863676-12358-1-git-send-email-ravikumar.veeramally@linux.intel.com>

Hi Ravi,

On Tue, Nov 19, 2013, Ravi kumar Veeramally wrote:
> ---
>  android/pan.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

This patch has been applied. Thanks.

Johan

^ permalink raw reply

* [PATCH] autopair: Add special handling for printers
From: Bastien Nocera @ 2013-11-19 13:15 UTC (permalink / raw)
  To: linux-bluetooth


As was done in gnome-bluetooth since 2009:
https://git.gnome.org/browse/gnome-bluetooth/commit/?id=7a472c151d44a3378ecbd3c2a75c763f5c577fe9
---
 plugins/autopair.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/plugins/autopair.c b/plugins/autopair.c
index e6e5035..8c98c12 100644
--- a/plugins/autopair.c
+++ b/plugins/autopair.c
@@ -121,6 +121,14 @@ static ssize_t autopair_pincb(struct btd_adapter *adapter,
 		}
 
 		break;
+	case 0x06:		/* Imaging */
+		if (class & 0x80) {	/* Printer */
+			if (attempt > 1)
+				return 0;
+			memcpy(pinbuf, "0000", 4);
+			return 4;
+		}
+		break;
 	}
 
 	return 0;
-- 
1.8.4.2



^ permalink raw reply related

* autopair corner cases
From: Bastien Nocera @ 2013-11-19 12:31 UTC (permalink / raw)
  To: linux-bluetooth

Heya,

There's a bunch of corner cases that the autopair plugin doesn't handle
and that we used to handle in gnome-bluetooth with BlueZ 4.x.

1) First is the case of the PS3 BD Remote that will reject
authentication when you try to pair to it. gnome-bluetooth knows not to
pair with it.

>        <!-- Sony PlayStation 3 Remote Control -->
>         <device oui="00:19:C1:" name="BD Remote Control" pin="NULL"/>
>         <device oui="00:1E:3D:" name="BD Remote Control" pin="NULL"/>
>         <device oui="00:06:F5:" name="BD Remote Control" pin="NULL"/>

Is there a way to say "we can't actually pair" when the client requested
pairing already? Or is that considered a security problem?

2) The second case is pairing this "funny" keyboard that's the iCade
controller. In gnome-bluetooth, we had special code to generate only
joystick movements for the pairing, rather than hard to determine
buttons, so we'd end up with a 6-digit pin using only 1 through 4.

>         <!-- ION iCade Game Controller -->
>         <device name="iCade" type="keyboard" pin="ICADE"/>

3) We have a whole list of GPS that don't use present themselves as
anything special apart from the name. Most use "0000", but some use
things like "NAVMAN" or "12345678"

>         <!-- http://bugzilla.gnome.org/show_bug.cgi?id=560315#c20 -->
>         <device oui="00:02:5B:" name="Pharos iGPS-BT" pin="12345678"/>
> 
>         <!-- https://bugzilla.gnome.org/show_bug.cgi?id=613698 -->
>         <device oui="00:0C:A5:" name="NAVMAN GPS ONE" pin="NAVMAN"/>

4) Audio devices will mostly already be supported by the autopair code
(yay!), though we have a few stragglers, most notably this speaker that
can use random pincode, as long as they're only 4 digits in length:

>         <!-- http://bugzilla.gnome.org/show_bug.cgi?id=583651 -->
>         <device type="audio" oui="00:1A:80:" name="CMT-DH5BT" pin="max:4"/>

5) Printers are missing from the list, that should be an easy fix.

I'll try and send patches for cases 2 through 4, using a static table in
the autopair plugin. If that's not acceptable, I'll create a new
higher-priority plugin that handles those corner cases.

Cheers


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox