2013-10-28 12:30:05

by Marcin Kraglak

[permalink] [raw]
Subject: [PATCH 1/5] android/hal: Add initial socket implementation

Added socket api opcodes and structures and its implementation
in hal-sock.c.
---
android/hal-msg.h | 20 ++++++++++++++++++++
android/hal-sock.c | 28 ++++++++++++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 677b00b..ec7d181 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -213,6 +213,26 @@ struct hal_cmd_le_test_mode {
uint8_t data[0];
} __attribute__((packed));

+/* Bluetooth Socket HAL api */
+
+#define HAL_OP_SOCK_LISTEN 0x01
+struct hal_op_sock_listen {
+ uint8_t type;
+ uint8_t name[256];
+ uint8_t uuid[16];
+ uint16_t channel;
+ uint8_t flags;
+} __attribute__((packed));
+
+#define HAL_OP_SOCK_CONNECT 0x02
+struct hal_op_sock_connect {
+ uint8_t bdaddr[6];
+ uint8_t type;
+ uint8_t uuid[16];
+ uint16_t channel;
+ uint8_t flags;
+} __attribute__((packed));
+
#define HAL_OP_HID_CONNECT 0x01
struct hal_cmd_hid_connect {
uint8_t bdaddr[6];
diff --git a/android/hal-sock.c b/android/hal-sock.c
index 7642ee3..131877a 100644
--- a/android/hal-sock.c
+++ b/android/hal-sock.c
@@ -15,18 +15,33 @@
*
*/

+#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>

+#include "hal-ipc.h"
#include "hal-log.h"
+#include "hal-msg.h"
#include "hal.h"

static bt_status_t sock_listen_rfcomm(const char *service_name,
const uint8_t *uuid, int chan,
int *sock, int flags)
{
+ struct hal_op_sock_listen cmd;
+
DBG("");

- return BT_STATUS_UNSUPPORTED;
+ cmd.flags = flags;
+ cmd.type = BTSOCK_RFCOMM;
+ cmd.channel = chan;
+ memcpy(cmd.uuid, uuid, sizeof(cmd.uuid));
+ memset(cmd.name, 0, sizeof(cmd.name));
+ memcpy(cmd.name, service_name, strlen(service_name));
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_LISTEN,
+ sizeof(cmd), &cmd, NULL, NULL, sock);
}

static bt_status_t sock_listen(btsock_type_t type, const char *service_name,
@@ -58,6 +73,8 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,
const uint8_t *uuid, int chan,
int *sock, int flags)
{
+ struct hal_op_sock_connect cmd;
+
if ((!uuid && chan <= 0) || !bdaddr || !sock) {
error("invalid params: bd_addr %p, uuid %p, chan %d, sock %p",
bdaddr, uuid, chan, sock);
@@ -66,7 +83,14 @@ static bt_status_t sock_connect(const bt_bdaddr_t *bdaddr, btsock_type_t type,

DBG("uuid %p chan %d sock %p type %d", uuid, chan, sock, type);

- return BT_STATUS_UNSUPPORTED;
+ cmd.flags = flags;
+ cmd.type = type;
+ cmd.channel = chan;
+ memcpy(cmd.uuid, uuid, sizeof(cmd.uuid));
+ memcpy(cmd.bdaddr, bdaddr, sizeof(cmd.bdaddr));
+
+ return hal_ipc_cmd(HAL_SERVICE_ID_SOCK, HAL_OP_SOCK_CONNECT,
+ sizeof(cmd), &cmd, NULL, NULL, sock);
}

static btsock_interface_t sock_if = {
--
1.8.2.2



2013-10-28 13:47:00

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface

Hi Johan,

>> +static int uuid_cmp(const void *a, const void *b)
>> +{
>> + const sdp_record_t *rec = a;
>> + const uuid_t *uuid = b;
>> +
>> + return sdp_uuid_cmp(&rec->svclass, uuid);
>> +}
>> +
>> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
>> +{
>> + if (uuid->type == SDP_UUID16)
>> + sdp_uuid16_to_uuid128(uuid128, uuid);
>> + else if (uuid->type == SDP_UUID32)
>> + sdp_uuid32_to_uuid128(uuid128, uuid);
>> + else
>> + memcpy(uuid128, uuid, sizeof(*uuid));
>> +}
>> +
>> +static uint8_t get_uuid_mask(const uuid_t *uuid)
>> +{
>> + if (uuid->type != SDP_UUID16)
>> + return 0;
>> +
>> + switch (uuid->value.uuid16) {
>> + case DIALUP_NET_SVCLASS_ID:
>> + case CIP_SVCLASS_ID:
>> + return 0x42; /* Telephony & Networking */
>> + case IRMC_SYNC_SVCLASS_ID:
>> + case OBEX_OBJPUSH_SVCLASS_ID:
>> + case OBEX_FILETRANS_SVCLASS_ID:
>> + case IRMC_SYNC_CMD_SVCLASS_ID:
>> + case PBAP_PSE_SVCLASS_ID:
>> + return 0x10; /* Object Transfer */
>> + case HEADSET_SVCLASS_ID:
>> + case HANDSFREE_SVCLASS_ID:
>> + return 0x20; /* Audio */
>> + case CORDLESS_TELEPHONY_SVCLASS_ID:
>> + case INTERCOM_SVCLASS_ID:
>> + case FAX_SVCLASS_ID:
>> + case SAP_SVCLASS_ID:
>> + /*
>> + * Setting the telephony bit for the handsfree audio gateway
>> + * role is not required by the HFP specification, but the
>> + * Nokia 616 carkit is just plain broken! It will refuse
>> + * pairing without this bit set.
>> + */
>> + case HANDSFREE_AGW_SVCLASS_ID:
>> + return 0x40; /* Telephony */
>> + case AUDIO_SOURCE_SVCLASS_ID:
>> + case VIDEO_SOURCE_SVCLASS_ID:
>> + return 0x08; /* Capturing */
>> + case AUDIO_SINK_SVCLASS_ID:
>> + case VIDEO_SINK_SVCLASS_ID:
>> + return 0x04; /* Rendering */
>> + case PANU_SVCLASS_ID:
>> + case NAP_SVCLASS_ID:
>> + case GN_SVCLASS_ID:
>> + return 0x02; /* Networking */
>> + default:
>> + return 0;
>> + }
>> +}
>
> I don't think it makes sense to duplicate this code in bluez.git,
> especially not the last function. Instead, I think it should be
> refactored to the appropriate common place (lib/sdp.c maybe? Or maybe
> not if we don't want to pollute the already deprecated libbluetooth - in
> which case I'd expect a proposal where to put this).

I was actually thinking that we just make this static. In Android all SDP records are normally registered ahead of time. They even did this when they used BlueZ. It was essentially a sdptool add for all the records they needed.

This is also means we can just use the service class hint as a static value.

>> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
>> +{
>> + struct mgmt_cp_add_uuid cp;
>> + uuid_t uuid128;
>> + uint128_t uint128;
>> +
>> + uuid_to_uuid128(&uuid128, uuid);
>> +
>> + ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
>> + htob128(&uint128, (uint128_t *) cp.uuid);
>> + cp.svc_hint = svc_hint;
>> +
>> + if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
>> + 0, sizeof(cp), &cp,
>> + add_uuid_complete, adapter, NULL) > 0)
>> + return 0;
>
> Since you're skipping the "is_supported_uuid" check that we're doing in
> the normal bluetoothd I suppose we at least have a proper check for a
> minimum mgmt version when initializing the android bluetoothd? Otherwise
> your patch is broken.

We should require a minimum mgmt version for Android. One that has all the bugs fixed. There is no point in planning on supporting older kernels anyway.

Regards

Marcel


2013-10-28 13:24:23

by Andrei Emeltchenko

[permalink] [raw]
Subject: Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface

Hi Marcin,

On Mon, Oct 28, 2013 at 01:30:09PM +0100, Marcin Kraglak wrote:
> Use mgmt interface for adding and removing uuids to adapter.
> This is needed for proper changing adapter's class of device.
> ---
> android/adapter.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 141 insertions(+)
>
> diff --git a/android/adapter.c b/android/adapter.c
> index b1cb5f8..bed0423 100644
> --- a/android/adapter.c
> +++ b/android/adapter.c
> @@ -532,10 +532,105 @@ error:
> ipc_send_rsp(io, HAL_SERVICE_ID_BLUETOOTH, status);
> }
>
> +static int uuid_cmp(const void *a, const void *b)
> +{
> + const sdp_record_t *rec = a;
> + const uuid_t *uuid = b;
> +
> + return sdp_uuid_cmp(&rec->svclass, uuid);
> +}
> +
> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
> +{
> + if (uuid->type == SDP_UUID16)
> + sdp_uuid16_to_uuid128(uuid128, uuid);
> + else if (uuid->type == SDP_UUID32)
> + sdp_uuid32_to_uuid128(uuid128, uuid);
> + else
> + memcpy(uuid128, uuid, sizeof(*uuid));
> +}
> +
> +static uint8_t get_uuid_mask(const uuid_t *uuid)
> +{
> + if (uuid->type != SDP_UUID16)
> + return 0;
> +
> + switch (uuid->value.uuid16) {
> + case DIALUP_NET_SVCLASS_ID:
> + case CIP_SVCLASS_ID:
> + return 0x42; /* Telephony & Networking */
> + case IRMC_SYNC_SVCLASS_ID:
> + case OBEX_OBJPUSH_SVCLASS_ID:
> + case OBEX_FILETRANS_SVCLASS_ID:
> + case IRMC_SYNC_CMD_SVCLASS_ID:
> + case PBAP_PSE_SVCLASS_ID:
> + return 0x10; /* Object Transfer */
> + case HEADSET_SVCLASS_ID:
> + case HANDSFREE_SVCLASS_ID:
> + return 0x20; /* Audio */
> + case CORDLESS_TELEPHONY_SVCLASS_ID:
> + case INTERCOM_SVCLASS_ID:
> + case FAX_SVCLASS_ID:
> + case SAP_SVCLASS_ID:
> + /*
> + * Setting the telephony bit for the handsfree audio gateway
> + * role is not required by the HFP specification, but the
> + * Nokia 616 carkit is just plain broken! It will refuse
> + * pairing without this bit set.
> + */
> + case HANDSFREE_AGW_SVCLASS_ID:
> + return 0x40; /* Telephony */
> + case AUDIO_SOURCE_SVCLASS_ID:
> + case VIDEO_SOURCE_SVCLASS_ID:
> + return 0x08; /* Capturing */
> + case AUDIO_SINK_SVCLASS_ID:
> + case VIDEO_SINK_SVCLASS_ID:
> + return 0x04; /* Rendering */
> + case PANU_SVCLASS_ID:
> + case NAP_SVCLASS_ID:
> + case GN_SVCLASS_ID:
> + return 0x02; /* Networking */
> + default:
> + return 0;
> + }
> +}

Can those functions be reused between our android/adapter and src/adapter?

Best regards
Andrei Emeltchenko


> +
> +static void add_uuid_complete(uint8_t status, uint16_t length,
> + const void *param, void *user_data)
> +{
> + if (status != MGMT_STATUS_SUCCESS) {
> + error("Failed to add UUID: %s (0x%02x)",
> + mgmt_errstr(status), status);
> + return;
> + }
> + /*TODO inform that adapter uuids has been changed*/
> +}
> +
> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
> +{
> + struct mgmt_cp_add_uuid cp;
> + uuid_t uuid128;
> + uint128_t uint128;
> +
> + uuid_to_uuid128(&uuid128, uuid);
> +
> + ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> + htob128(&uint128, (uint128_t *) cp.uuid);
> + cp.svc_hint = svc_hint;
> +
> + if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
> + 0, sizeof(cp), &cp,
> + add_uuid_complete, adapter, NULL) > 0)
> + return 0;
> +
> + return -EIO;
> +}
> +
> static void adapter_service_insert(sdp_record_t *rec)
> {
> sdp_list_t *browse_list = NULL;
> uuid_t browse_uuid;
> + bool new_uuid;
>
> /* skip record without a browse group */
> if (sdp_get_browse_groups(rec, &browse_list) < 0) {
> @@ -552,6 +647,19 @@ static void adapter_service_insert(sdp_record_t *rec)
> adapter->services = sdp_list_insert_sorted(
> adapter->services, rec, record_sort);
>
> + if (!sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
> + new_uuid = true;
> + else
> + new_uuid = false;
> +
> + adapter->services = sdp_list_insert_sorted(adapter->services, rec,
> + record_sort);
> +
> + if (new_uuid) {
> + uint8_t svc_hint = get_uuid_mask(&rec->svclass);
> + add_uuid(&rec->svclass, svc_hint);
> + }
> +
> done:
> sdp_list_free(browse_list, free);
> }
> @@ -569,6 +677,36 @@ int bt_adapter_service_add(sdp_record_t *rec)
> return ret;
> }
>
> +static void remove_uuid_complete(uint8_t status, uint16_t length,
> + const void *param, void *user_data)
> +{
> + if (status != MGMT_STATUS_SUCCESS) {
> + error("Failed to remove UUID: %s (0x%02x)",
> + mgmt_errstr(status), status);
> + return;
> + }
> + /*TODO inform that adapter uuids has been changed*/
> +}
> +
> +static int remove_uuid(uuid_t *uuid)
> +{
> + struct mgmt_cp_remove_uuid cp;
> + uuid_t uuid128;
> + uint128_t uint128;
> +
> + uuid_to_uuid128(&uuid128, uuid);
> +
> + ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> + htob128(&uint128, (uint128_t *) cp.uuid);
> +
> + if (mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_UUID,
> + 0, sizeof(cp), &cp,
> + remove_uuid_complete, adapter, NULL) > 0)
> + return 0;
> +
> + return -EIO;
> +}
> +
> void bt_adapter_service_remove(uint32_t handle)
> {
> sdp_record_t *rec = sdp_record_find(handle);
> @@ -578,6 +716,9 @@ void bt_adapter_service_remove(uint32_t handle)
>
> adapter->services = sdp_list_remove(adapter->services, rec);
>
> + if (!sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
> + remove_uuid(&rec->svclass);
> +
> remove_record_from_server(rec->handle);
> }
>
> --
> 1.8.2.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2013-10-28 13:23:54

by Johan Hedberg

[permalink] [raw]
Subject: Re: [PATCH 5/5] android: Add and remove uuids in mgmt interface

Hi Marcin,

On Mon, Oct 28, 2013, Marcin Kraglak wrote:
> +static int uuid_cmp(const void *a, const void *b)
> +{
> + const sdp_record_t *rec = a;
> + const uuid_t *uuid = b;
> +
> + return sdp_uuid_cmp(&rec->svclass, uuid);
> +}
> +
> +static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
> +{
> + if (uuid->type == SDP_UUID16)
> + sdp_uuid16_to_uuid128(uuid128, uuid);
> + else if (uuid->type == SDP_UUID32)
> + sdp_uuid32_to_uuid128(uuid128, uuid);
> + else
> + memcpy(uuid128, uuid, sizeof(*uuid));
> +}
> +
> +static uint8_t get_uuid_mask(const uuid_t *uuid)
> +{
> + if (uuid->type != SDP_UUID16)
> + return 0;
> +
> + switch (uuid->value.uuid16) {
> + case DIALUP_NET_SVCLASS_ID:
> + case CIP_SVCLASS_ID:
> + return 0x42; /* Telephony & Networking */
> + case IRMC_SYNC_SVCLASS_ID:
> + case OBEX_OBJPUSH_SVCLASS_ID:
> + case OBEX_FILETRANS_SVCLASS_ID:
> + case IRMC_SYNC_CMD_SVCLASS_ID:
> + case PBAP_PSE_SVCLASS_ID:
> + return 0x10; /* Object Transfer */
> + case HEADSET_SVCLASS_ID:
> + case HANDSFREE_SVCLASS_ID:
> + return 0x20; /* Audio */
> + case CORDLESS_TELEPHONY_SVCLASS_ID:
> + case INTERCOM_SVCLASS_ID:
> + case FAX_SVCLASS_ID:
> + case SAP_SVCLASS_ID:
> + /*
> + * Setting the telephony bit for the handsfree audio gateway
> + * role is not required by the HFP specification, but the
> + * Nokia 616 carkit is just plain broken! It will refuse
> + * pairing without this bit set.
> + */
> + case HANDSFREE_AGW_SVCLASS_ID:
> + return 0x40; /* Telephony */
> + case AUDIO_SOURCE_SVCLASS_ID:
> + case VIDEO_SOURCE_SVCLASS_ID:
> + return 0x08; /* Capturing */
> + case AUDIO_SINK_SVCLASS_ID:
> + case VIDEO_SINK_SVCLASS_ID:
> + return 0x04; /* Rendering */
> + case PANU_SVCLASS_ID:
> + case NAP_SVCLASS_ID:
> + case GN_SVCLASS_ID:
> + return 0x02; /* Networking */
> + default:
> + return 0;
> + }
> +}

I don't think it makes sense to duplicate this code in bluez.git,
especially not the last function. Instead, I think it should be
refactored to the appropriate common place (lib/sdp.c maybe? Or maybe
not if we don't want to pollute the already deprecated libbluetooth - in
which case I'd expect a proposal where to put this).

> +static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
> +{
> + struct mgmt_cp_add_uuid cp;
> + uuid_t uuid128;
> + uint128_t uint128;
> +
> + uuid_to_uuid128(&uuid128, uuid);
> +
> + ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
> + htob128(&uint128, (uint128_t *) cp.uuid);
> + cp.svc_hint = svc_hint;
> +
> + if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
> + 0, sizeof(cp), &cp,
> + add_uuid_complete, adapter, NULL) > 0)
> + return 0;

Since you're skipping the "is_supported_uuid" check that we're doing in
the normal bluetoothd I suppose we at least have a proper check for a
minimum mgmt version when initializing the android bluetoothd? Otherwise
your patch is broken.

Johan

2013-10-28 12:30:09

by Marcin Kraglak

[permalink] [raw]
Subject: [PATCH 5/5] android: Add and remove uuids in mgmt interface

Use mgmt interface for adding and removing uuids to adapter.
This is needed for proper changing adapter's class of device.
---
android/adapter.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+)

diff --git a/android/adapter.c b/android/adapter.c
index b1cb5f8..bed0423 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -532,10 +532,105 @@ error:
ipc_send_rsp(io, HAL_SERVICE_ID_BLUETOOTH, status);
}

+static int uuid_cmp(const void *a, const void *b)
+{
+ const sdp_record_t *rec = a;
+ const uuid_t *uuid = b;
+
+ return sdp_uuid_cmp(&rec->svclass, uuid);
+}
+
+static void uuid_to_uuid128(uuid_t *uuid128, const uuid_t *uuid)
+{
+ if (uuid->type == SDP_UUID16)
+ sdp_uuid16_to_uuid128(uuid128, uuid);
+ else if (uuid->type == SDP_UUID32)
+ sdp_uuid32_to_uuid128(uuid128, uuid);
+ else
+ memcpy(uuid128, uuid, sizeof(*uuid));
+}
+
+static uint8_t get_uuid_mask(const uuid_t *uuid)
+{
+ if (uuid->type != SDP_UUID16)
+ return 0;
+
+ switch (uuid->value.uuid16) {
+ case DIALUP_NET_SVCLASS_ID:
+ case CIP_SVCLASS_ID:
+ return 0x42; /* Telephony & Networking */
+ case IRMC_SYNC_SVCLASS_ID:
+ case OBEX_OBJPUSH_SVCLASS_ID:
+ case OBEX_FILETRANS_SVCLASS_ID:
+ case IRMC_SYNC_CMD_SVCLASS_ID:
+ case PBAP_PSE_SVCLASS_ID:
+ return 0x10; /* Object Transfer */
+ case HEADSET_SVCLASS_ID:
+ case HANDSFREE_SVCLASS_ID:
+ return 0x20; /* Audio */
+ case CORDLESS_TELEPHONY_SVCLASS_ID:
+ case INTERCOM_SVCLASS_ID:
+ case FAX_SVCLASS_ID:
+ case SAP_SVCLASS_ID:
+ /*
+ * Setting the telephony bit for the handsfree audio gateway
+ * role is not required by the HFP specification, but the
+ * Nokia 616 carkit is just plain broken! It will refuse
+ * pairing without this bit set.
+ */
+ case HANDSFREE_AGW_SVCLASS_ID:
+ return 0x40; /* Telephony */
+ case AUDIO_SOURCE_SVCLASS_ID:
+ case VIDEO_SOURCE_SVCLASS_ID:
+ return 0x08; /* Capturing */
+ case AUDIO_SINK_SVCLASS_ID:
+ case VIDEO_SINK_SVCLASS_ID:
+ return 0x04; /* Rendering */
+ case PANU_SVCLASS_ID:
+ case NAP_SVCLASS_ID:
+ case GN_SVCLASS_ID:
+ return 0x02; /* Networking */
+ default:
+ return 0;
+ }
+}
+
+static void add_uuid_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to add UUID: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ return;
+ }
+ /*TODO inform that adapter uuids has been changed*/
+}
+
+static int add_uuid(uuid_t *uuid, uint8_t svc_hint)
+{
+ struct mgmt_cp_add_uuid cp;
+ uuid_t uuid128;
+ uint128_t uint128;
+
+ uuid_to_uuid128(&uuid128, uuid);
+
+ ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
+ htob128(&uint128, (uint128_t *) cp.uuid);
+ cp.svc_hint = svc_hint;
+
+ if (mgmt_send(adapter->mgmt, MGMT_OP_ADD_UUID,
+ 0, sizeof(cp), &cp,
+ add_uuid_complete, adapter, NULL) > 0)
+ return 0;
+
+ return -EIO;
+}
+
static void adapter_service_insert(sdp_record_t *rec)
{
sdp_list_t *browse_list = NULL;
uuid_t browse_uuid;
+ bool new_uuid;

/* skip record without a browse group */
if (sdp_get_browse_groups(rec, &browse_list) < 0) {
@@ -552,6 +647,19 @@ static void adapter_service_insert(sdp_record_t *rec)
adapter->services = sdp_list_insert_sorted(
adapter->services, rec, record_sort);

+ if (!sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
+ new_uuid = true;
+ else
+ new_uuid = false;
+
+ adapter->services = sdp_list_insert_sorted(adapter->services, rec,
+ record_sort);
+
+ if (new_uuid) {
+ uint8_t svc_hint = get_uuid_mask(&rec->svclass);
+ add_uuid(&rec->svclass, svc_hint);
+ }
+
done:
sdp_list_free(browse_list, free);
}
@@ -569,6 +677,36 @@ int bt_adapter_service_add(sdp_record_t *rec)
return ret;
}

+static void remove_uuid_complete(uint8_t status, uint16_t length,
+ const void *param, void *user_data)
+{
+ if (status != MGMT_STATUS_SUCCESS) {
+ error("Failed to remove UUID: %s (0x%02x)",
+ mgmt_errstr(status), status);
+ return;
+ }
+ /*TODO inform that adapter uuids has been changed*/
+}
+
+static int remove_uuid(uuid_t *uuid)
+{
+ struct mgmt_cp_remove_uuid cp;
+ uuid_t uuid128;
+ uint128_t uint128;
+
+ uuid_to_uuid128(&uuid128, uuid);
+
+ ntoh128((uint128_t *) uuid128.value.uuid128.data, &uint128);
+ htob128(&uint128, (uint128_t *) cp.uuid);
+
+ if (mgmt_send(adapter->mgmt, MGMT_OP_REMOVE_UUID,
+ 0, sizeof(cp), &cp,
+ remove_uuid_complete, adapter, NULL) > 0)
+ return 0;
+
+ return -EIO;
+}
+
void bt_adapter_service_remove(uint32_t handle)
{
sdp_record_t *rec = sdp_record_find(handle);
@@ -578,6 +716,9 @@ void bt_adapter_service_remove(uint32_t handle)

adapter->services = sdp_list_remove(adapter->services, rec);

+ if (!sdp_list_find(adapter->services, &rec->svclass, uuid_cmp))
+ remove_uuid(&rec->svclass);
+
remove_record_from_server(rec->handle);
}

--
1.8.2.2


2013-10-28 12:30:08

by Marcin Kraglak

[permalink] [raw]
Subject: [PATCH 4/5] android: Cache adapter services in bt_adapter struct

We need to cache list of sdp records to add/remove uuids
in mgmt interface properly.
---
android/adapter.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/android/adapter.c b/android/adapter.c
index a14c2a4..b1cb5f8 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -30,6 +30,7 @@
#include "src/shared/mgmt.h"
#include "lib/mgmt.h"
#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
#include "log.h"
#include "hal-msg.h"
#include "ipc.h"
@@ -50,6 +51,8 @@ struct bt_adapter {

uint32_t supported_settings;
uint32_t current_settings;
+
+ sdp_list_t *services;
};

static struct bt_adapter *adapter;
@@ -529,14 +532,53 @@ error:
ipc_send_rsp(io, HAL_SERVICE_ID_BLUETOOTH, status);
}

+static void adapter_service_insert(sdp_record_t *rec)
+{
+ sdp_list_t *browse_list = NULL;
+ uuid_t browse_uuid;
+
+ /* skip record without a browse group */
+ if (sdp_get_browse_groups(rec, &browse_list) < 0) {
+ DBG("skipping record without browse group");
+ return;
+ }
+
+ sdp_uuid16_create(&browse_uuid, PUBLIC_BROWSE_GROUP);
+
+ /* skip record without public browse group */
+ if (!sdp_list_find(browse_list, &browse_uuid, sdp_uuid_cmp))
+ goto done;
+
+ adapter->services = sdp_list_insert_sorted(
+ adapter->services, rec, record_sort);
+
+done:
+ sdp_list_free(browse_list, free);
+}
+
int bt_adapter_service_add(sdp_record_t *rec)
{
- return add_record_to_server(&adapter->bdaddr, rec);
+ int ret;
+
+ ret = add_record_to_server(&adapter->bdaddr, rec);
+ if (ret < 0)
+ return ret;
+
+ adapter_service_insert(rec);
+
+ return ret;
}

void bt_adapter_service_remove(uint32_t handle)
{
- remove_record_from_server(handle);
+ sdp_record_t *rec = sdp_record_find(handle);
+
+ if (!rec)
+ return;
+
+ adapter->services = sdp_list_remove(adapter->services, rec);
+
+ remove_record_from_server(rec->handle);
}

const bdaddr_t *bt_adapter_get_address(void)
--
1.8.2.2


2013-10-28 12:30:07

by Marcin Kraglak

[permalink] [raw]
Subject: [PATCH 3/5] android: Add initial sdp implementation

Add and remove records to sdp server. This api will
be used in android's profiles implementations.
---
android/adapter.c | 12 ++++++++++++
android/adapter.h | 3 +++
2 files changed, 15 insertions(+)

diff --git a/android/adapter.c b/android/adapter.c
index 80a9e6d..a14c2a4 100644
--- a/android/adapter.c
+++ b/android/adapter.c
@@ -26,8 +26,10 @@
#include <glib.h>

#include "lib/bluetooth.h"
+#include "src/sdpd.h"
#include "src/shared/mgmt.h"
#include "lib/mgmt.h"
+#include "lib/sdp.h"
#include "log.h"
#include "hal-msg.h"
#include "ipc.h"
@@ -527,6 +529,16 @@ error:
ipc_send_rsp(io, HAL_SERVICE_ID_BLUETOOTH, status);
}

+int bt_adapter_service_add(sdp_record_t *rec)
+{
+ return add_record_to_server(&adapter->bdaddr, rec);
+}
+
+void bt_adapter_service_remove(uint32_t handle)
+{
+ remove_record_from_server(handle);
+}
+
const bdaddr_t *bt_adapter_get_address(void)
{
return &adapter->bdaddr;
diff --git a/android/adapter.h b/android/adapter.h
index 2afc67a..1726f18 100644
--- a/android/adapter.h
+++ b/android/adapter.h
@@ -38,5 +38,8 @@ void bt_adapter_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,

const bdaddr_t *bt_adapter_get_address(void);

+int bt_adapter_service_add(sdp_record_t *rec);
+void bt_adapter_service_remove(uint32_t handle);
+
bool bt_adapter_register(GIOChannel *io);
void bt_adapter_unregister(void);
--
1.8.2.2


2013-10-28 12:30:06

by Marcin Kraglak

[permalink] [raw]
Subject: [PATCH 2/5] android: Initial implementation of socket interface

Add stub implementation of socket interace on daemon side.
---
android/main.c | 4 ++++
android/socket.c | 42 ++++++++++++++++++++++++++++++++++++++++++
android/socket.h | 3 +++
3 files changed, 49 insertions(+)

diff --git a/android/main.c b/android/main.c
index 6ff30a9..2b40621 100644
--- a/android/main.c
+++ b/android/main.c
@@ -213,6 +213,10 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
bt_hid_handle_cmd(hal_cmd_io, msg->opcode, msg->payload,
msg->len);
break;
+ case HAL_SERVICE_ID_SOCK:
+ bt_sock_handle_cmd(hal_cmd_io, msg->opcode, msg->payload,
+ msg->len);
+ break;
default:
ipc_send_rsp(hal_cmd_io, msg->service_id, HAL_STATUS_FAILED);
break;
diff --git a/android/socket.c b/android/socket.c
index 22d2acb..39709cd 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -26,8 +26,50 @@

#include "lib/bluetooth.h"
#include "log.h"
+#include "hal-msg.h"
+#include "hal-ipc.h"
+#include "ipc.h"
#include "socket.h"

+
+static int handle_listen(void *buf)
+{
+ return -1;
+}
+
+static int handle_connect(void *buf)
+{
+ return -1;
+}
+
+void bt_sock_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
+ uint16_t len)
+{
+ int fd;
+
+ switch (opcode) {
+ case HAL_OP_SOCK_LISTEN:
+ fd = handle_listen(buf);
+ if (fd < 0)
+ break;
+
+ ipc_send(io, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ return;
+ case HAL_OP_SOCK_CONNECT:
+ fd = handle_connect(buf);
+ if (fd < 0)
+ break;
+
+ ipc_send(io, HAL_SERVICE_ID_SOCK, opcode, 0, NULL, fd);
+ return;
+ default:
+ DBG("Unhandled command, opcode 0x%x", opcode);
+ break;
+ }
+
+ ipc_send_rsp(io, HAL_SERVICE_ID_SOCK, HAL_STATUS_FAILED);
+}
+
bool bt_socket_register(GIOChannel *io, const bdaddr_t *addr)
{
DBG("");
diff --git a/android/socket.h b/android/socket.h
index b13e84c..2b3b940 100644
--- a/android/socket.h
+++ b/android/socket.h
@@ -21,5 +21,8 @@
*
*/

+void bt_sock_handle_cmd(GIOChannel *io, uint8_t opcode, void *buf,
+ uint16_t len);
+
bool bt_socket_register(GIOChannel *io, const bdaddr_t *addr);
void bt_socket_unregister(void);
--
1.8.2.2