* [PATCHv3 01/16] android/hal-sock: Add debug flag printing
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 02/16] android/socket: Use static local adapter address Andrei Emeltchenko
` (14 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/hal-sock.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/android/hal-sock.c b/android/hal-sock.c
index b7bc88e..eafa451 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -55,8 +55,8 @@ static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
return BT_STATUS_PARM_INVALID;
}
- DBG("uuid %s chan %d sock %p type %d service_name %s",
- btuuid2str(uuid), chan, sock, type, service_name);
+ DBG("uuid %s chan %d sock %p type %d service_name %s flags 0x%02x",
+ btuuid2str(uuid), chan, sock, type, service_name, flags);
switch (type) {
case BTSOCK_RFCOMM:
@@ -82,8 +82,8 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
return BT_STATUS_PARM_INVALID;
}
- DBG("uuid %s chan %d sock %p type %d", btuuid2str(uuid), chan, sock,
- type);
+ DBG("uuid %s chan %d sock %p type %d flags 0x%02x",
+ btuuid2str(uuid), chan, sock, type, flags);
if (type != BTSOCK_RFCOMM) {
error("Socket type %u not supported", type);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 02/16] android/socket: Use static local adapter address
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 01/16] android/hal-sock: Add debug flag printing Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:46 ` Johan Hedberg
2013-11-18 8:26 ` [PATCHv3 03/16] android/socket: Add connect signal to socket Andrei Emeltchenko
` (13 subsequent siblings)
15 siblings, 1 reply; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
---
android/socket.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index c283c5f..e580036 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -35,6 +35,7 @@
#include "ipc.h"
#include "socket.h"
+static bdaddr_t adapter_addr;
static int handle_listen(void *buf)
{
@@ -81,6 +82,8 @@ bool bt_socket_register(int sk, const bdaddr_t *addr)
{
DBG("");
+ bacpy(&adapter_addr, addr);
+
return true;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 03/16] android/socket: Add connect signal to socket
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 01/16] android/hal-sock: Add debug flag printing Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 02/16] android/socket: Use static local adapter address Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:45 ` Johan Hedberg
2013-11-18 8:26 ` [PATCHv3 04/16] android/socket: Define structs and implement listen Andrei Emeltchenko
` (12 subsequent siblings)
15 siblings, 1 reply; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Connect signal is used to pass information to framework that socket
is accepted.
---
android/hal-msg.h | 2 ++
android/socket.h | 7 +++++++
2 files changed, 9 insertions(+)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 44fd5c8..9e3a81f 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -232,6 +232,8 @@ struct hal_cmd_sock_connect {
uint8_t flags;
} __attribute__((packed));
+/* Bluetooth Hidhost HAL api */
+
#define HAL_OP_HIDHOST_CONNECT 0x01
struct hal_cmd_hidhost_connect {
uint8_t bdaddr[6];
diff --git a/android/socket.h b/android/socket.h
index 7aa5574..ba56c9b 100644
--- a/android/socket.h
+++ b/android/socket.h
@@ -21,6 +21,13 @@
*
*/
+struct hal_sock_connect_signal {
+ short size;
+ uint8_t bdaddr[6];
+ int channel;
+ int status;
+} __attribute__((packed));
+
void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
bool bt_socket_register(int sk, const bdaddr_t *addr);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCHv3 03/16] android/socket: Add connect signal to socket
2013-11-18 8:26 ` [PATCHv3 03/16] android/socket: Add connect signal to socket Andrei Emeltchenko
@ 2013-11-18 8:45 ` Johan Hedberg
0 siblings, 0 replies; 22+ messages in thread
From: Johan Hedberg @ 2013-11-18 8:45 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
Hi Andrei,
On Mon, Nov 18, 2013, Andrei Emeltchenko wrote:
> Connect signal is used to pass information to framework that socket
> is accepted.
> ---
> android/hal-msg.h | 2 ++
> android/socket.h | 7 +++++++
> 2 files changed, 9 insertions(+)
>
> diff --git a/android/hal-msg.h b/android/hal-msg.h
> index 44fd5c8..9e3a81f 100644
> --- a/android/hal-msg.h
> +++ b/android/hal-msg.h
> @@ -232,6 +232,8 @@ struct hal_cmd_sock_connect {
> uint8_t flags;
> } __attribute__((packed));
>
> +/* Bluetooth Hidhost HAL api */
> +
This part seems unrelated to this patch?
Johan
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCHv3 04/16] android/socket: Define structs and implement listen
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (2 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 03/16] android/socket: Add connect signal to socket Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:55 ` Johan Hedberg
2013-11-18 8:26 ` [PATCHv3 05/16] android/socket: Implement socket accepted event Andrei Emeltchenko
` (11 subsequent siblings)
15 siblings, 1 reply; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 116 insertions(+), 2 deletions(-)
diff --git a/android/socket.c b/android/socket.c
index e580036..276c78c 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -27,8 +27,12 @@
#include <glib.h>
#include <stdbool.h>
+#include <unistd.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"
@@ -37,13 +41,123 @@
static bdaddr_t adapter_addr;
-static int handle_listen(void *buf)
+/* Simple list of RFCOMM server sockets */
+GList *rfcomm_srv_list = NULL;
+
+/* Simple list of RFCOMM connected sockets */
+GList *rfcomm_connected_list = NULL;
+
+struct rfcomm_slot {
+ int fd; /* descriptor for communication with Java framework */
+ int real_sock; /* real RFCOMM socket */
+ int channel; /* RFCOMM channel */
+};
+
+static struct rfcomm_slot *create_rfslot(int sock, int *hal_fd)
{
- DBG("Not implemented");
+ int fds[2] = {-1, -1};
+ struct rfcomm_slot *rfslot;
+
+ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds) < 0) {
+ error("socketpair(): %s", strerror(errno));
+ return NULL;
+ }
+
+ rfslot = g_malloc0(sizeof(*rfslot));
+ rfslot->fd = fds[0];
+ *hal_fd = fds[1];
+ rfslot->real_sock = sock;
+
+ return rfslot;
+}
+
+static void cleanup_rfslot(struct rfcomm_slot *rfslot)
+{
+ DBG("Cleanup: rfslot: %p fd %d real_sock %d chan %u",
+ rfslot, rfslot->fd, rfslot->real_sock, rfslot->channel);
+
+ if (rfslot->fd > 0)
+ close(rfslot->fd);
+ if (rfslot->real_sock > 0)
+ close(rfslot->real_sock);
+
+ g_free(rfslot);
+}
+
+static struct {
+ uint8_t uuid[16];
+ uint8_t channel;
+} uuid_to_chan[] = {
+ { .uuid = {
+ 0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+ },
+#define PBAP_DEFAULT_CHANNEL 15
+ .channel = PBAP_DEFAULT_CHANNEL },
+ { .uuid = {
+ 0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+ },
+#define OPP_DEFAULT_CHANNEL 9
+ .channel = OPP_DEFAULT_CHANNEL },
+ { {0} }
+};
+
+static int get_rfcomm_default_chan(const uint8_t *uuid)
+{
+ int i;
+
+ for (i = 0; uuid_to_chan[i].channel; i++) {
+ if (!memcmp(uuid_to_chan[i].uuid, uuid, 16))
+ return uuid_to_chan[i].channel;
+ }
return -1;
}
+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 rfcomm_slot *rfslot;
+ GIOChannel *io;
+ GError *err = NULL;
+ int hal_fd = -1;
+ int chan;
+
+ DBG("");
+
+ chan = get_rfcomm_default_chan(cmd->uuid);
+ if (chan < 0)
+ return -1;
+
+ DBG("rfcomm channel %d", chan);
+
+ rfslot = create_rfslot(-1, &hal_fd);
+
+ io = bt_io_listen(accept_cb, NULL, rfslot, 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_rfslot(rfslot);
+ return -1;
+ }
+
+ rfslot->real_sock = g_io_channel_unix_get_fd(io);
+ rfcomm_srv_list = g_list_append(rfcomm_srv_list, rfslot);
+
+ DBG("real_sock %d fd %d hal_fd %d",
+ rfslot->real_sock, rfslot->fd, hal_fd);
+
+ return hal_fd;
+}
+
static int handle_connect(void *buf)
{
DBG("Not implemented");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCHv3 04/16] android/socket: Define structs and implement listen
2013-11-18 8:26 ` [PATCHv3 04/16] android/socket: Define structs and implement listen Andrei Emeltchenko
@ 2013-11-18 8:55 ` Johan Hedberg
2013-11-18 10:02 ` Andrei Emeltchenko
0 siblings, 1 reply; 22+ messages in thread
From: Johan Hedberg @ 2013-11-18 8:55 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth
Hi Andrei,
On Mon, Nov 18, 2013, Andrei Emeltchenko wrote:
> 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 | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 116 insertions(+), 2 deletions(-)
>
> diff --git a/android/socket.c b/android/socket.c
> index e580036..276c78c 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -27,8 +27,12 @@
>
> #include <glib.h>
> #include <stdbool.h>
> +#include <unistd.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"
> @@ -37,13 +41,123 @@
>
> static bdaddr_t adapter_addr;
>
> -static int handle_listen(void *buf)
> +/* Simple list of RFCOMM server sockets */
> +GList *rfcomm_srv_list = NULL;
> +
> +/* Simple list of RFCOMM connected sockets */
> +GList *rfcomm_connected_list = NULL;
Didn't I suggest "servers" and "connections" as names for these?
> +struct rfcomm_slot {
The term "slot" seems a bit confusing to me. You're using this struct as
context for both server sockets and connected sockets. Would the name
struct rfcomm_socket make more sense? Feel free to suggest something
else too.
> +
> + rfslot = g_malloc0(sizeof(*rfslot));
rfslot = g_new0(struct rfcom_slot, 1);
> +static void cleanup_rfslot(struct rfcomm_slot *rfslot)
> +{
> + DBG("Cleanup: rfslot: %p fd %d real_sock %d chan %u",
> + rfslot, rfslot->fd, rfslot->real_sock, rfslot->channel);
Since DBG() will anyway print the function name having an explicit
"Cleanup:" in the log message seems redundant.
> +static struct {
> + uint8_t uuid[16];
> + uint8_t channel;
> +} uuid_to_chan[] = {
> + { .uuid = {
> + 0x00, 0x00, 0x11, 0x2F, 0x00, 0x00, 0x10, 0x00,
> + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
> + },
Why doesn't this first entry have a channel? Please indent the stuff
between { and } with an extra tab.
> +#define PBAP_DEFAULT_CHANNEL 15
I'd rather have these default channel definitions in a separate place,
probably in the beginning of the C-file where you can quickly see them.
Having them inline like this doesn't really provide any value at all
compared to just hard-coding them in the places where you have
.channel = ...
> + { .uuid = {
> + 0x00, 0x00, 0x11, 0x05, 0x00, 0x00, 0x10, 0x00,
> + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
> + },
> +#define OPP_DEFAULT_CHANNEL 9
> + .channel = OPP_DEFAULT_CHANNEL },
Is this the missing channel from the first entry? Looks misplaced to me.
> +static int get_rfcomm_default_chan(const uint8_t *uuid)
> +{
> + int i;
> +
> + for (i = 0; uuid_to_chan[i].channel; i++) {
> + if (!memcmp(uuid_to_chan[i].uuid, uuid, 16))
> + return uuid_to_chan[i].channel;
> + }
>
> return -1;
Maybe return -ENOENT?
> +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 rfcomm_slot *rfslot;
> + GIOChannel *io;
> + GError *err = NULL;
> + int hal_fd = -1;
Why do you need to pre-initialize hal_fd? If create_rfslot() can fail
can won't you detect that?
> + int chan;
> +
> + DBG("");
> +
> + chan = get_rfcomm_default_chan(cmd->uuid);
> + if (chan < 0)
> + return -1;
Maybe "return chan;"?
Johan
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCHv3 04/16] android/socket: Define structs and implement listen
2013-11-18 8:55 ` Johan Hedberg
@ 2013-11-18 10:02 ` Andrei Emeltchenko
0 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 10:02 UTC (permalink / raw)
To: linux-bluetooth
Hi Johan,
On Mon, Nov 18, 2013 at 10:55:35AM +0200, Johan Hedberg wrote:
> Hi Andrei,
>
> On Mon, Nov 18, 2013, Andrei Emeltchenko wrote:
> > 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 | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 116 insertions(+), 2 deletions(-)
> >
> > diff --git a/android/socket.c b/android/socket.c
> > index e580036..276c78c 100644
> > --- a/android/socket.c
> > +++ b/android/socket.c
> > @@ -27,8 +27,12 @@
> >
> > #include <glib.h>
> > #include <stdbool.h>
> > +#include <unistd.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"
> > @@ -37,13 +41,123 @@
> >
> > static bdaddr_t adapter_addr;
> >
> > -static int handle_listen(void *buf)
> > +/* Simple list of RFCOMM server sockets */
> > +GList *rfcomm_srv_list = NULL;
> > +
> > +/* Simple list of RFCOMM connected sockets */
> > +GList *rfcomm_connected_list = NULL;
>
> Didn't I suggest "servers" and "connections" as names for these?
>
> > +struct rfcomm_slot {
>
> The term "slot" seems a bit confusing to me. You're using this struct as
> context for both server sockets and connected sockets. Would the name
> struct rfcomm_socket make more sense? Feel free to suggest something
> else too.
rfcomm_socket is ok, what is a good name instead of rfslot? rfsock?
Best regards
Andrei Emeltchenko
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCHv3 05/16] android/socket: Implement socket accepted event
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (3 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 04/16] android/socket: Define structs and implement listen Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 06/16] android/socket: Implement Android RFCOMM stack events Andrei Emeltchenko
` (10 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 276c78c..c9ee32f 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -115,8 +115,60 @@ static int get_rfcomm_default_chan(const uint8_t *uuid)
return -1;
}
+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_slot *rfslot = user_data;
+ struct rfcomm_slot *rfslot_acc;
+ GIOChannel *io_stack;
+ bdaddr_t dst;
+ char address[18];
+ int sock_acc;
+ int hal_fd = -1;
+
+ bt_io_get(io, &err,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_io_channel_shutdown(io, TRUE, NULL);
+ return;
+ }
+
+ ba2str(&dst, address);
+ DBG("Incoming connection from %s rfslot %p", address, rfslot);
+
+ DBG("rfslot: fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ sock_acc = g_io_channel_unix_get_fd(io);
+ rfslot_acc = create_rfslot(sock_acc, &hal_fd);
+ rfcomm_connected_list =
+ g_list_append(rfcomm_connected_list, rfslot_acc);
+
+ /* Handle events from Android */
+ io_stack = g_io_channel_unix_new(rfslot_acc->fd);
+ g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ sock_stack_event_cb, rfslot_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, rfslot_acc);
+
+ DBG("rfslot %p rfslot_acc %p", rfslot, rfslot_acc);
}
static int handle_listen(void *buf)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 06/16] android/socket: Implement Android RFCOMM stack events
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (4 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 05/16] android/socket: Implement socket accepted event Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 07/16] android/socket: Implement RFCOMM events Andrei Emeltchenko
` (9 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index c9ee32f..027b519 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -115,9 +115,70 @@ static int get_rfcomm_default_chan(const uint8_t *uuid)
return -1;
}
+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_slot *rfslot = data;
+ unsigned char buf[1024];
+ int len, sent;
+
+ DBG("rfslot: fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ if (!g_list_find(rfcomm_connected_list, rfslot)) {
+ error("rfslot %p not found in the list", rfslot);
+ 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);
+ rfcomm_connected_list = g_list_remove(rfcomm_connected_list,
+ rfslot);
+ cleanup_rfslot(rfslot);
+ return FALSE;
+ }
+
+ len = read(rfslot->fd, buf, sizeof(buf));
+ if (len <= 0) {
+ error("read(): %s", strerror(errno));
+ return FALSE;
+ }
+
+ DBG("read %d bytes write to %d", len, rfslot->real_sock);
+
+ sent = try_write_all(rfslot->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 [flat|nested] 22+ messages in thread* [PATCHv3 07/16] android/socket: Implement RFCOMM events
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (5 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 06/16] android/socket: Implement Android RFCOMM stack events Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 08/16] android/socket: Implement accept signal over Android fd Andrei Emeltchenko
` (8 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Copy data from RFCOMM socket to Android framework. Consider splice
in the future.
---
android/socket.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 027b519..eba50f6 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -185,6 +185,44 @@ static gboolean sock_stack_event_cb(GIOChannel *io, GIOCondition cond,
static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
gpointer data)
{
+ struct rfcomm_slot *rfslot = data;
+ unsigned char buf[1024];
+ int len, sent;
+
+ DBG("rfslot: fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ if (!g_list_find(rfcomm_connected_list, rfslot)) {
+ error("rfslot %p not found in the list", rfslot);
+ 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);
+ rfcomm_connected_list = g_list_remove(rfcomm_connected_list,
+ rfslot);
+ cleanup_rfslot(rfslot);
+ return FALSE;
+ }
+
+ len = read(rfslot->real_sock, buf, sizeof(buf));
+ if (len <= 0) {
+ error("read(): %s", strerror(errno));
+ return FALSE;
+ }
+
+ DBG("read %d bytes, write to fd %d", len, rfslot->fd);
+
+ sent = try_write_all(rfslot->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 [flat|nested] 22+ messages in thread* [PATCHv3 08/16] android/socket: Implement accept signal over Android fd
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (6 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 07/16] android/socket: Implement RFCOMM events Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 09/16] android/socket: Write channel to " Andrei Emeltchenko
` (7 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 eba50f6..4886158 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"
static bdaddr_t adapter_addr;
@@ -103,6 +104,45 @@ static struct {
{ {0} }
};
+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 int get_rfcomm_default_chan(const uint8_t *uuid)
{
int i;
@@ -226,6 +266,21 @@ static gboolean sock_rfcomm_event_cb(GIOChannel *io, GIOCondition cond,
return TRUE;
}
+static void sock_send_accept(struct rfcomm_slot *rfslot, bdaddr_t *bdaddr,
+ int fd_accepted)
+{
+ struct hal_sock_connect_signal cmd;
+
+ DBG("");
+
+ cmd.size = sizeof(cmd);
+ bdaddr2android(bdaddr, cmd.bdaddr);
+ cmd.channel = rfslot->channel;
+ cmd.status = 0;
+
+ bt_sock_send_fd(rfslot->fd, &cmd, sizeof(cmd), fd_accepted);
+}
+
static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
{
struct rfcomm_slot *rfslot = user_data;
@@ -257,6 +312,8 @@ static void accept_cb(GIOChannel *io, GError *err, gpointer user_data)
rfcomm_connected_list =
g_list_append(rfcomm_connected_list, rfslot_acc);
+ sock_send_accept(rfslot, &dst, hal_fd);
+
/* Handle events from Android */
io_stack = g_io_channel_unix_new(rfslot_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 [flat|nested] 22+ messages in thread* [PATCHv3 09/16] android/socket: Write channel to Android fd
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (7 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 08/16] android/socket: Implement accept signal over Android fd Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 10/16] android/socket: Implement socket connect HAL method Andrei Emeltchenko
` (6 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 4886158..a800a77 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -360,6 +360,13 @@ static int handle_listen(void *buf)
rfslot->real_sock = g_io_channel_unix_get_fd(io);
rfcomm_srv_list = g_list_append(rfcomm_srv_list, rfslot);
+ /* TODO: Check this */
+ if (write(rfslot->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+ error("Error sending RFCOMM channel");
+ cleanup_rfslot(rfslot);
+ return -1;
+ }
+
DBG("real_sock %d fd %d hal_fd %d",
rfslot->real_sock, rfslot->fd, hal_fd);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 10/16] android/socket: Implement socket connect HAL method
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (8 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 09/16] android/socket: Write channel to " Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 11/16] android/socket: Parse SDP response and connect Andrei Emeltchenko
` (5 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 a800a77..c22e4ed 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"
@@ -52,6 +55,7 @@ struct rfcomm_slot {
int fd; /* descriptor for communication with Java framework */
int real_sock; /* real RFCOMM socket */
int channel; /* RFCOMM channel */
+ bdaddr_t dst;
};
static struct rfcomm_slot *create_rfslot(int sock, int *hal_fd)
@@ -373,11 +377,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_slot *rfslot;
+ bdaddr_t dst;
+ uuid_t uuid;
+ int hal_fd = -1;
- return -1;
+ DBG("");
+
+ android2bdaddr(cmd->bdaddr, &dst);
+ rfslot = create_rfslot(-1, &hal_fd);
+ bacpy(&rfslot->dst, &dst);
+
+ 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, rfslot,
+ NULL) < 0) {
+ error("Failed to search SDP records");
+ cleanup_rfslot(rfslot);
+ 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 [flat|nested] 22+ messages in thread* [PATCHv3 11/16] android/socket: Parse SDP response and connect
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (9 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 10/16] android/socket: Implement socket connect HAL method Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 12/16] android/socket: Implement HAL connect call Andrei Emeltchenko
` (4 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 c22e4ed..dde000d 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -377,9 +377,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_slot *rfslot = 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, rfslot, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &rfslot->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;
+ }
+
+ rfslot->real_sock = g_io_channel_unix_get_fd(io);
+ rfslot->channel = chan;
+ rfcomm_connected_list = g_list_append(rfcomm_connected_list, rfslot);
+ return;
+
+fail:
+ cleanup_rfslot(rfslot);
}
static int handle_connect(void *buf)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 12/16] android/socket: Implement HAL connect call
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (10 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 11/16] android/socket: Parse SDP response and connect Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 13/16] android/socket: Send RFCOMM channel to framework Andrei Emeltchenko
` (3 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
HAL connect uses similar event handlers like listen call.
---
android/socket.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/android/socket.c b/android/socket.c
index dde000d..063681e 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -377,8 +377,49 @@ static int handle_listen(void *buf)
return hal_fd;
}
-static void connect_cb(GIOChannel *io, GError *err, gpointer user_data)
+static void connect_cb(GIOChannel *io, GError *conn_err, gpointer user_data)
{
+ struct rfcomm_slot *rfslot = user_data;
+ GIOChannel *io_stack;
+ GError *io_err = NULL;
+ bdaddr_t dst;
+ char address[18];
+ int chan = -1;
+
+ bt_io_get(io, &io_err,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_INVALID);
+ if (io_err) {
+ error("%s", io_err->message);
+ g_error_free(io_err);
+ goto fail;
+ }
+
+ if (conn_err) {
+ error("%s", conn_err->message);
+ goto fail;
+ }
+
+ ba2str(&dst, address);
+ DBG("Connected to %s rfslot %p chan %d", address, rfslot, chan);
+
+ DBG("rfslot: fd %d real_sock %d chan %u sock %d",
+ rfslot->fd, rfslot->real_sock, rfslot->channel,
+ g_io_channel_unix_get_fd(io));
+
+ /* Handle events from Android */
+ io_stack = g_io_channel_unix_new(rfslot->fd);
+ g_io_add_watch(io_stack, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ sock_stack_event_cb, rfslot);
+ 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, rfslot);
+
+ return;
+fail:
+ cleanup_rfslot(rfslot);
}
static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 13/16] android/socket: Send RFCOMM channel to framework
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (11 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 12/16] android/socket: Implement HAL connect call Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 14/16] android/socket: Send connect signal on connect Andrei Emeltchenko
` (2 subsequent siblings)
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 063681e..39935e8 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -477,6 +477,11 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
goto fail;
}
+ if (write(rfslot->fd, &chan, sizeof(chan)) != sizeof(chan)) {
+ error("Error sending RFCOMM channel");
+ goto fail;
+ }
+
rfslot->real_sock = g_io_channel_unix_get_fd(io);
rfslot->channel = chan;
rfcomm_connected_list = g_list_append(rfcomm_connected_list, rfslot);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCHv3 14/16] android/socket: Send connect signal on connect
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (12 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 13/16] android/socket: Send RFCOMM channel to framework Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 15/16] android/socket: Close file descriptor after sending Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 16/16] android/socket: Add SDP record for OPP profile Andrei Emeltchenko
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 39935e8..1bcaa23 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -377,6 +377,33 @@ static int handle_listen(void *buf)
return hal_fd;
}
+static ssize_t sock_send_connect(struct rfcomm_slot *rfslot, 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 = rfslot->channel;
+ cmd.status = 0;
+
+ len = write(rfslot->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 *conn_err, gpointer user_data)
{
struct rfcomm_slot *rfslot = user_data;
@@ -407,6 +434,9 @@ static void connect_cb(GIOChannel *io, GError *conn_err, gpointer user_data)
rfslot->fd, rfslot->real_sock, rfslot->channel,
g_io_channel_unix_get_fd(io));
+ if (sock_send_connect(rfslot, &dst) < 0)
+ goto fail;
+
/* Handle events from Android */
io_stack = g_io_channel_unix_new(rfslot->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 [flat|nested] 22+ messages in thread* [PATCHv3 15/16] android/socket: Close file descriptor after sending
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (13 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 14/16] android/socket: Send connect signal on connect Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 8:26 ` [PATCHv3 16/16] android/socket: Add SDP record for OPP profile Andrei Emeltchenko
15 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 1bcaa23..6b50014 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -560,6 +560,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);
@@ -567,6 +568,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 [flat|nested] 22+ messages in thread* [PATCHv3 16/16] android/socket: Add SDP record for OPP profile
2013-11-18 8:26 [PATCHv3 00/16] Socket HAL Andrei Emeltchenko
` (14 preceding siblings ...)
2013-11-18 8:26 ` [PATCHv3 15/16] android/socket: Close file descriptor after sending Andrei Emeltchenko
@ 2013-11-18 8:26 ` Andrei Emeltchenko
2013-11-18 9:28 ` Andrei Emeltchenko
15 siblings, 1 reply; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 8:26 UTC (permalink / raw)
To: linux-bluetooth
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 | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/android/socket.c b/android/socket.c
index 6b50014..989b876 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -36,6 +36,7 @@
#include "lib/sdp_lib.h"
#include "src/sdp-client.h"
+#include "bluetooth.h"
#include "log.h"
#include "hal-msg.h"
#include "hal-ipc.h"
@@ -43,6 +44,9 @@
#include "utils.h"
#include "socket.h"
+/* Use Object Transfer for all services */
+#define SVC_HINT_OBEX 0x10
+
static bdaddr_t adapter_addr;
/* Simple list of RFCOMM server sockets */
@@ -56,6 +60,7 @@ struct rfcomm_slot {
int real_sock; /* real RFCOMM socket */
int channel; /* RFCOMM channel */
bdaddr_t dst;
+ uint32_t service_handle;
};
static struct rfcomm_slot *create_rfslot(int sock, int *hal_fd)
@@ -86,6 +91,9 @@ static void cleanup_rfslot(struct rfcomm_slot *rfslot)
if (rfslot->real_sock > 0)
close(rfslot->real_sock);
+ if (rfslot->service_handle)
+ bt_adapter_remove_record(rfslot->service_handle);
+
g_free(rfslot);
}
@@ -108,6 +116,90 @@ static struct {
{ {0} }
};
+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;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(0, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
+ svclass_id = sdp_list_append(0, &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(0, profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[0] = sdp_list_append(0, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &chan);
+ proto[0] = sdp_list_append(proto[0], channel);
+ apseq = sdp_list_append(apseq, proto[0]);
+
+ sdp_uuid16_create(&obex_uuid, OBEX_UUID);
+ proto[1] = sdp_list_append(0, &obex_uuid);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(0, 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", 0, 0);
+
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], 0);
+ sdp_list_free(proto[1], 0);
+ sdp_list_free(apseq, 0);
+ sdp_list_free(aproto, 0);
+
+ return record;
+}
+
+static uint32_t sdp_service_register(uint8_t chan)
+{
+ sdp_record_t *record;
+
+ switch (chan) {
+ case OPP_DEFAULT_CHANNEL:
+ record = create_opp_record(chan);
+ break;
+ default:
+ DBG("Not implemented");
+ return 0;
+ }
+
+ if (bt_adapter_add_record(record, SVC_HINT_OBEX) < 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;
@@ -371,6 +463,8 @@ static int handle_listen(void *buf)
return -1;
}
+ rfslot->service_handle = sdp_service_register(chan);
+
DBG("real_sock %d fd %d hal_fd %d",
rfslot->real_sock, rfslot->fd, hal_fd);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCHv3 16/16] android/socket: Add SDP record for OPP profile
2013-11-18 8:26 ` [PATCHv3 16/16] android/socket: Add SDP record for OPP profile Andrei Emeltchenko
@ 2013-11-18 9:28 ` Andrei Emeltchenko
0 siblings, 0 replies; 22+ messages in thread
From: Andrei Emeltchenko @ 2013-11-18 9:28 UTC (permalink / raw)
To: linux-bluetooth
Hi,
On Mon, Nov 18, 2013 at 10:26:19AM +0200, Andrei Emeltchenko wrote:
> 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 | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 94 insertions(+)
>
> diff --git a/android/socket.c b/android/socket.c
> index 6b50014..989b876 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -36,6 +36,7 @@
> #include "lib/sdp_lib.h"
> #include "src/sdp-client.h"
>
> +#include "bluetooth.h"
> #include "log.h"
> #include "hal-msg.h"
> #include "hal-ipc.h"
> @@ -43,6 +44,9 @@
> #include "utils.h"
> #include "socket.h"
>
> +/* Use Object Transfer for all services */
> +#define SVC_HINT_OBEX 0x10
> +
> static bdaddr_t adapter_addr;
>
> /* Simple list of RFCOMM server sockets */
> @@ -56,6 +60,7 @@ struct rfcomm_slot {
> int real_sock; /* real RFCOMM socket */
> int channel; /* RFCOMM channel */
> bdaddr_t dst;
> + uint32_t service_handle;
> };
>
> static struct rfcomm_slot *create_rfslot(int sock, int *hal_fd)
> @@ -86,6 +91,9 @@ static void cleanup_rfslot(struct rfcomm_slot *rfslot)
> if (rfslot->real_sock > 0)
> close(rfslot->real_sock);
>
> + if (rfslot->service_handle)
> + bt_adapter_remove_record(rfslot->service_handle);
> +
> g_free(rfslot);
> }
>
> @@ -108,6 +116,90 @@ static struct {
> { {0} }
> };
>
> +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;
> +
> + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
> + root = sdp_list_append(0, &root_uuid);
> + sdp_set_browse_groups(record, root);
> +
> + sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
> + svclass_id = sdp_list_append(0, &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(0, profile);
> + sdp_set_profile_descs(record, pfseq);
> +
> + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
> + proto[0] = sdp_list_append(0, &rfcomm_uuid);
> + channel = sdp_data_alloc(SDP_UINT8, &chan);
> + proto[0] = sdp_list_append(proto[0], channel);
> + apseq = sdp_list_append(apseq, proto[0]);
fixed myself to:
@@ -161,7 +161,7 @@ static sdp_record_t *create_opp_record(uint8_t chan)
proto[0] = sdp_list_append(0, &rfcomm_uuid);
channel = sdp_data_alloc(SDP_UINT8, &chan);
proto[0] = sdp_list_append(proto[0], channel);
- apseq = sdp_list_append(apseq, proto[0]);
+ apseq = sdp_list_append(0, proto[0]);
sdp_uuid16_create(&obex_uuid, OBEX_UUID);
proto[1] = sdp_list_append(0, &obex_uuid);
Best regards
Andrei Emeltchenko
^ permalink raw reply [flat|nested] 22+ messages in thread