* [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL
@ 2014-02-28 16:19 Szymon Janc
2014-02-28 16:19 ` [PATCH 2/6] android/handsfree: Add support for enable HFP command Szymon Janc
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This command will be used to enable HFP support in handsfree HAL.
---
android/hal-ipc-api.txt | 2 ++
android/hal-msg.h | 2 ++
2 files changed, 4 insertions(+)
diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
index 1a19c80..54f6783 100644
--- a/android/hal-ipc-api.txt
+++ b/android/hal-ipc-api.txt
@@ -935,6 +935,8 @@ Android HAL name: "handsfree" (BT_PROFILE_HANDSFREE_ID)
In case of an error, the error response will be returned.
+ Opcode 0x0f - Enable Handsfree Profile command/response
+
Notifications:
Opcode 0x81 - Connection State notification
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 1e12868..cbb0f14 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -783,6 +783,8 @@ struct hal_cmd_gatt_server_send_response {
uint8_t data[0];
} __attribute__((packed));
+#define HAL_OP_HANDSFREE_ENABLE_HFP 0x0F
+
/* Notifications and confirmations */
#define HAL_POWER_OFF 0x00
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/6] android/handsfree: Add support for enable HFP command
2014-02-28 16:19 [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL Szymon Janc
@ 2014-02-28 16:19 ` Szymon Janc
2014-02-28 16:19 ` [PATCH 3/6] android/hal-handsfree: " Szymon Janc
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This allows to not enable HFP AG when initializing HAL.
---
android/handsfree.c | 246 ++++++++++++++++++++++++++++------------------------
1 file changed, 132 insertions(+), 114 deletions(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 81ddcc7..e9478ad 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -56,10 +56,82 @@ static struct {
} device;
static bdaddr_t adapter_addr;
-static uint32_t record_id = 0;
+static uint32_t hfp_record_id = 0;
static struct ipc *hal_ipc = NULL;
-static GIOChannel *server = NULL;
+static GIOChannel *hfp_server = NULL;
+
+static sdp_record_t *handsfree_ag_record(void)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
+ uuid_t l2cap_uuid, rfcomm_uuid;
+ sdp_profile_desc_t profile;
+ sdp_list_t *aproto, *proto[2];
+ sdp_record_t *record;
+ sdp_data_t *channel, *features;
+ uint8_t netid = 0x01;
+ uint16_t sdpfeat;
+ sdp_data_t *network;
+ uint8_t ch = HFP_AG_CHANNEL;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ network = sdp_data_alloc(SDP_UINT8, &netid);
+ if (!network) {
+ sdp_record_free(record);
+ return NULL;
+ }
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(record, root);
+
+ sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
+ svclass_id = sdp_list_append(NULL, &svclass_uuid);
+ sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
+ svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
+ profile.version = 0x0106;
+ pfseq = sdp_list_append(NULL, &profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto[0] = sdp_list_append(0, &l2cap_uuid);
+ apseq = sdp_list_append(NULL, proto[0]);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[1] = sdp_list_append(NULL, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &ch);
+ proto[1] = sdp_list_append(proto[1], channel);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ sdpfeat = HFP_AG_FEATURES;
+ features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
+ sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
+
+ aproto = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sdp_set_info_attr(record, "Hands-Free Audio Gateway", NULL, NULL);
+
+ sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
+
+ 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 void device_set_state(uint8_t state)
{
@@ -422,6 +494,54 @@ static void handle_phone_state_change(const void *buf, uint16_t len)
HAL_STATUS_FAILED);
}
+static void handle_enable_hfp(const void *buf, uint16_t len)
+{
+ sdp_record_t *rec;
+ GError *err = NULL;
+
+ DBG("");
+
+ if (hfp_server)
+ goto failed;
+
+ hfp_server = bt_io_listen(NULL, confirm_cb, NULL, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_CHANNEL, HFP_AG_CHANNEL,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_INVALID);
+ if (!hfp_server) {
+ error("Failed to listen on Handsfree rfcomm: %s", err->message);
+ g_error_free(err);
+ goto failed;
+ }
+
+ rec = handsfree_ag_record();
+ if (!rec) {
+ error("Failed to allocate Handsfree record");
+ goto failed_io;
+ }
+
+ if (bt_adapter_add_record(rec, 0) < 0) {
+ error("Failed to register Handsfree record");
+ sdp_record_free(rec);
+ goto failed_io;
+ }
+ hfp_record_id = rec->handle;
+
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_ENABLE_HFP, HAL_STATUS_SUCCESS);
+ return;
+
+failed_io:
+ g_io_channel_shutdown(hfp_server, TRUE, NULL);
+ g_io_channel_unref(hfp_server);
+ hfp_server = NULL;
+
+failed:
+ ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+ HAL_OP_HANDSFREE_ENABLE_HFP, HAL_STATUS_FAILED);
+}
+
static const struct ipc_handler cmd_handlers[] = {
/* HAL_OP_HANDSFREE_CONNECT */
{ handle_connect, false, sizeof(struct hal_cmd_handsfree_connect)},
@@ -458,125 +578,21 @@ static const struct ipc_handler cmd_handlers[] = {
/* HAL_OP_HANDSFREE_PHONE_STATE_CHANGE */
{handle_phone_state_change, true,
sizeof(struct hal_cmd_handsfree_phone_state_change)},
+ /* HAL_OP_HANDSFREE_ENABLE_HFP */
+ {handle_enable_hfp, false, 0 },
};
-static sdp_record_t *handsfree_ag_record(void)
-{
- sdp_list_t *svclass_id, *pfseq, *apseq, *root;
- uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
- uuid_t l2cap_uuid, rfcomm_uuid;
- sdp_profile_desc_t profile;
- sdp_list_t *aproto, *proto[2];
- sdp_record_t *record;
- sdp_data_t *channel, *features;
- uint8_t netid = 0x01;
- uint16_t sdpfeat;
- sdp_data_t *network;
- uint8_t ch = HFP_AG_CHANNEL;
-
- record = sdp_record_alloc();
- if (!record)
- return NULL;
-
- network = sdp_data_alloc(SDP_UINT8, &netid);
- if (!network) {
- sdp_record_free(record);
- return NULL;
- }
-
- sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
- root = sdp_list_append(NULL, &root_uuid);
- sdp_set_browse_groups(record, root);
-
- sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID);
- svclass_id = sdp_list_append(NULL, &svclass_uuid);
- sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
- svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
- sdp_set_service_classes(record, svclass_id);
-
- sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID);
- profile.version = 0x0106;
- pfseq = sdp_list_append(NULL, &profile);
- sdp_set_profile_descs(record, pfseq);
-
- sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
- proto[0] = sdp_list_append(0, &l2cap_uuid);
- apseq = sdp_list_append(NULL, proto[0]);
-
- sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
- proto[1] = sdp_list_append(NULL, &rfcomm_uuid);
- channel = sdp_data_alloc(SDP_UINT8, &ch);
- proto[1] = sdp_list_append(proto[1], channel);
- apseq = sdp_list_append(apseq, proto[1]);
-
- sdpfeat = HFP_AG_FEATURES;
- features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
- sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
-
- aproto = sdp_list_append(NULL, apseq);
- sdp_set_access_protos(record, aproto);
-
- sdp_set_info_attr(record, "Hands-Free Audio Gateway", NULL, NULL);
-
- sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
-
- 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;
-}
-
bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr)
{
- sdp_record_t *rec;
- GError *err = NULL;
-
DBG("");
bacpy(&adapter_addr, addr);
- server = bt_io_listen( NULL, confirm_cb, NULL, NULL, &err,
- BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
- BT_IO_OPT_CHANNEL, HFP_AG_CHANNEL,
- BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
- BT_IO_OPT_INVALID);
- if (!server) {
- error("Failed to listen on Handsfree rfcomm: %s", err->message);
- g_error_free(err);
- return false;
- }
-
- rec = handsfree_ag_record();
- if (!rec) {
- error("Failed to allocate Handsfree record");
- goto failed;
- }
-
- if (bt_adapter_add_record(rec, 0) < 0) {
- error("Failed to register Handsfree record");
- sdp_record_free(rec);
- goto failed;
- }
- record_id = rec->handle;
-
hal_ipc = ipc;
ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
return true;
-
-failed:
- g_io_channel_shutdown(server, TRUE, NULL);
- g_io_channel_unref(server);
- server = NULL;
-
- return false;
}
void bt_handsfree_unregister(void)
@@ -586,12 +602,14 @@ void bt_handsfree_unregister(void)
ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
hal_ipc = NULL;
- if (server) {
- g_io_channel_shutdown(server, TRUE, NULL);
- g_io_channel_unref(server);
- server = NULL;
+ if (hfp_server) {
+ g_io_channel_shutdown(hfp_server, TRUE, NULL);
+ g_io_channel_unref(hfp_server);
+ hfp_server = NULL;
}
- bt_adapter_remove_record(record_id);
- record_id = 0;
+ if (hfp_record_id > 0) {
+ bt_adapter_remove_record(hfp_record_id);
+ hfp_record_id = 0;
+ }
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/6] android/hal-handsfree: Add support for enable HFP command
2014-02-28 16:19 [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL Szymon Janc
2014-02-28 16:19 ` [PATCH 2/6] android/handsfree: Add support for enable HFP command Szymon Janc
@ 2014-02-28 16:19 ` Szymon Janc
2014-02-28 16:19 ` [PATCH 4/6] android/socket: Reserve channel for HSP AG Szymon Janc
` (2 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/hal-handsfree.c | 45 ++++++++++++++++++++++++++-------------------
1 file changed, 26 insertions(+), 19 deletions(-)
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 1b150c3..790d7a5 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -196,6 +196,25 @@ static const struct hal_ipc_handler ev_handlers[] = {
{handle_hsp_key_press, false, 0},
};
+static void cleanup(void)
+{
+ struct hal_cmd_unregister_module cmd;
+
+ DBG("");
+
+ if (!interface_ready())
+ return;
+
+ cbs = NULL;
+
+ cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+
+ hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
+ sizeof(cmd), &cmd, 0, NULL, NULL);
+
+ hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+}
+
static bt_status_t init(bthf_callbacks_t *callbacks)
{
struct hal_cmd_register_module cmd;
@@ -219,8 +238,15 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
if (ret != BT_STATUS_SUCCESS) {
cbs = NULL;
hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
+ return ret;
}
+ /* TODO should be based on some property value */
+ ret = hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_ENABLE_HFP,
+ 0, NULL, 0, NULL, NULL);
+ if (ret != BT_STATUS_SUCCESS)
+ cleanup();
+
return ret;
}
@@ -518,25 +544,6 @@ static bt_status_t phone_state_change(int num_active, int num_held,
len, cmd, 0, NULL, NULL);
}
-static void cleanup(void)
-{
- struct hal_cmd_unregister_module cmd;
-
- DBG("");
-
- if (!interface_ready())
- return;
-
- cbs = NULL;
-
- cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
-
- hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
- sizeof(cmd), &cmd, 0, NULL, NULL);
-
- hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
-}
-
static bthf_interface_t iface = {
.size = sizeof(iface),
.init = init,
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/6] android/socket: Reserve channel for HSP AG
2014-02-28 16:19 [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL Szymon Janc
2014-02-28 16:19 ` [PATCH 2/6] android/handsfree: Add support for enable HFP command Szymon Janc
2014-02-28 16:19 ` [PATCH 3/6] android/hal-handsfree: " Szymon Janc
@ 2014-02-28 16:19 ` Szymon Janc
2014-02-28 16:44 ` Johan Hedberg
2014-02-28 16:19 ` [PATCH 5/6] android/handsfree: Add support " Szymon Janc
2014-02-28 16:19 ` [PATCH 6/6] android/handsfree: Allow to connect to HSP or HFP handsfree unit Szymon Janc
4 siblings, 1 reply; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/socket.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/android/socket.c b/android/socket.c
index ee98b54..f6863c8 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -47,8 +47,9 @@
#define RFCOMM_CHANNEL_MAX 30
+#define HSP_AG_DEFAULT_CHANNEL 11
#define OPP_DEFAULT_CHANNEL 12
-#define HFAG_DEFAULT_CHANNEL 13
+#define HFP_AG_DEFAULT_CHANNEL 13
#define PBAP_DEFAULT_CHANNEL 19
#define SVC_HINT_OBEX 0x10
@@ -373,10 +374,19 @@ static const struct profile_info {
} profiles[] = {
{
.uuid = {
+ 0x00, 0x00, 0x11, 0x08, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+ },
+ .channel = HSP_AG_DEFAULT_CHANNEL,
+ .svc_hint = 0,
+ .sec_level = BT_IO_SEC_MEDIUM,
+ .create_record = NULL
+ }, {
+ .uuid = {
0x00, 0x00, 0x11, 0x1F, 0x00, 0x00, 0x10, 0x00,
0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
},
- .channel = HFAG_DEFAULT_CHANNEL,
+ .channel = HFP_AG_DEFAULT_CHANNEL,
.svc_hint = 0,
.sec_level = BT_IO_SEC_MEDIUM,
.create_record = NULL
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/6] android/handsfree: Add support for HSP AG
2014-02-28 16:19 [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL Szymon Janc
` (2 preceding siblings ...)
2014-02-28 16:19 ` [PATCH 4/6] android/socket: Reserve channel for HSP AG Szymon Janc
@ 2014-02-28 16:19 ` Szymon Janc
2014-02-28 16:19 ` [PATCH 6/6] android/handsfree: Allow to connect to HSP or HFP handsfree unit Szymon Janc
4 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/handsfree.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 118 insertions(+), 3 deletions(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index e9478ad..6052d5d 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -47,6 +47,8 @@
#include "utils.h"
#define HFP_AG_CHANNEL 13
+#define HSP_AG_CHANNEL 11
+
#define HFP_AG_FEATURES 0
static struct {
@@ -56,11 +58,78 @@ static struct {
} device;
static bdaddr_t adapter_addr;
-static uint32_t hfp_record_id = 0;
static struct ipc *hal_ipc = NULL;
+static uint32_t hfp_record_id = 0;
static GIOChannel *hfp_server = NULL;
+static uint32_t hsp_record_id = 0;
+static GIOChannel *hsp_server = NULL;
+
+static sdp_record_t *headset_ag_record(void)
+{
+ sdp_list_t *svclass_id, *pfseq, *apseq, *root;
+ uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
+ uuid_t l2cap_uuid, rfcomm_uuid;
+ sdp_profile_desc_t profile;
+ sdp_list_t *aproto, *proto[2];
+ sdp_record_t *record;
+ sdp_data_t *channel;
+ uint8_t netid = 0x01;
+ sdp_data_t *network;
+ uint8_t ch = HSP_AG_CHANNEL;
+
+ record = sdp_record_alloc();
+ if (!record)
+ return NULL;
+
+ network = sdp_data_alloc(SDP_UINT8, &netid);
+ if (!network) {
+ sdp_record_free(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(&svclass_uuid, HEADSET_AGW_SVCLASS_ID);
+ svclass_id = sdp_list_append(0, &svclass_uuid);
+ sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID);
+ svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid);
+ sdp_set_service_classes(record, svclass_id);
+
+ sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID);
+ profile.version = 0x0100;
+ pfseq = sdp_list_append(0, &profile);
+ sdp_set_profile_descs(record, pfseq);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto[0] = sdp_list_append(0, &l2cap_uuid);
+ apseq = sdp_list_append(0, proto[0]);
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto[1] = sdp_list_append(0, &rfcomm_uuid);
+ channel = sdp_data_alloc(SDP_UINT8, &ch);
+ proto[1] = sdp_list_append(proto[1], channel);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(0, apseq);
+ sdp_set_access_protos(record, aproto);
+
+ sdp_set_info_attr(record, "Voice Gateway", 0, 0);
+
+ sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network);
+
+ 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 sdp_record_t *handsfree_ag_record(void)
{
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
@@ -584,23 +653,66 @@ static const struct ipc_handler cmd_handlers[] = {
bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr)
{
+ sdp_record_t *rec;
+ GError *err = NULL;
+
DBG("");
bacpy(&adapter_addr, addr);
+ hsp_server = bt_io_listen(NULL, confirm_cb, NULL, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_CHANNEL, HSP_AG_CHANNEL,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_INVALID);
+ if (!hsp_server) {
+ error("Failed to listen on Headset rfcomm: %s", err->message);
+ g_error_free(err);
+ return false;
+ }
+
+ rec = headset_ag_record();
+ if (!rec) {
+ error("Failed to allocate Headset record");
+ goto failed;
+ }
+
+ if (bt_adapter_add_record(rec, 0) < 0) {
+ error("Failed to register Headset record");
+ sdp_record_free(rec);
+ goto failed;
+ }
+ hsp_record_id = rec->handle;
+
hal_ipc = ipc;
+
ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
return true;
+
+failed:
+ g_io_channel_shutdown(hsp_server, TRUE, NULL);
+ g_io_channel_unref(hsp_server);
+ hsp_server = NULL;
+
+ return false;
}
void bt_handsfree_unregister(void)
{
DBG("");
- ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
- hal_ipc = NULL;
+ if (hsp_server) {
+ g_io_channel_shutdown(hsp_server, TRUE, NULL);
+ g_io_channel_unref(hsp_server);
+ hsp_server = NULL;
+ }
+
+ if (hsp_record_id > 0) {
+ bt_adapter_remove_record(hsp_record_id);
+ hsp_record_id = 0;
+ }
if (hfp_server) {
g_io_channel_shutdown(hfp_server, TRUE, NULL);
@@ -612,4 +724,7 @@ void bt_handsfree_unregister(void)
bt_adapter_remove_record(hfp_record_id);
hfp_record_id = 0;
}
+
+ ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
+ hal_ipc = NULL;
}
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/6] android/handsfree: Allow to connect to HSP or HFP handsfree unit
2014-02-28 16:19 [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL Szymon Janc
` (3 preceding siblings ...)
2014-02-28 16:19 ` [PATCH 5/6] android/handsfree: Add support " Szymon Janc
@ 2014-02-28 16:19 ` Szymon Janc
4 siblings, 0 replies; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This allows to connect to HSP (it HFP is not enabled) or fallback to
HSP if HFP is not supported by remote device.
---
android/handsfree.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 106 insertions(+), 7 deletions(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 6052d5d..b73bc19 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -320,7 +320,7 @@ drop:
g_io_channel_shutdown(chan, TRUE, NULL);
}
-static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
+static void sdp_hsp_search_cb(sdp_list_t *recs, int err, gpointer data)
{
sdp_list_t *protos, *classes;
GError *gerr = NULL;
@@ -331,12 +331,13 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
DBG("");
if (err < 0) {
- error("handsfree: unable to get SDP record: %s", strerror(-err));
+ error("handsfree: unable to get SDP record: %s",
+ strerror(-err));
goto fail;
}
if (!recs || !recs->data) {
- error("handsfree: no SDP records found");
+ info("handsfree: no HSP SDP records found");
goto fail;
}
@@ -352,6 +353,94 @@ static void sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
}
/* TODO read remote version? */
+ /* TODO read volume control support */
+
+ memcpy(&uuid, classes->data, sizeof(uuid));
+ sdp_list_free(classes, free);
+
+ if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
+ uuid.value.uuid16 != HEADSET_SVCLASS_ID) {
+ sdp_list_free(protos, NULL);
+ error("handsfree: invalid service record or not HSP");
+ goto fail;
+ }
+
+ channel = 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 (channel <= 0) {
+ error("handsfree: unable to get RFCOMM channel from record");
+ goto fail;
+ }
+
+ io = bt_io_connect(connect_cb, NULL, NULL, &gerr,
+ BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
+ BT_IO_OPT_DEST_BDADDR, &device.bdaddr,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
+ BT_IO_OPT_CHANNEL, channel,
+ BT_IO_OPT_INVALID);
+ if (!io) {
+ error("handsfree: unable to connect: %s", gerr->message);
+ g_error_free(gerr);
+ goto fail;
+ }
+
+ g_io_channel_unref(io);
+ return;
+
+fail:
+ device_cleanup();
+}
+
+static int sdp_search_hsp(void)
+{
+ uuid_t uuid;
+
+ sdp_uuid16_create(&uuid, HEADSET_SVCLASS_ID);
+
+ return bt_search_service(&adapter_addr, &device.bdaddr, &uuid,
+ sdp_hsp_search_cb, NULL, NULL, 0);
+}
+
+static void sdp_hfp_search_cb(sdp_list_t *recs, int err, gpointer data)
+{
+ sdp_list_t *protos, *classes;
+ GError *gerr = NULL;
+ GIOChannel *io;
+ uuid_t uuid;
+ int channel;
+
+ DBG("");
+
+ if (err < 0) {
+ error("handsfree: unable to get SDP record: %s",
+ strerror(-err));
+ goto fail;
+ }
+
+ if (!recs || !recs->data) {
+ info("handsfree: no HFP SDP records found, trying HSP");
+
+ if (sdp_search_hsp() < 0) {
+ error("handsfree: HSP SDP search failed");
+ goto fail;
+ }
+
+ return;
+ }
+
+ if (sdp_get_service_classes(recs->data, &classes) < 0) {
+ error("handsfree: unable to get service classes from record");
+ goto fail;
+ }
+
+ if (sdp_get_access_protos(recs->data, &protos) < 0) {
+ error("handsfree: unable to get access protocols from record");
+ sdp_list_free(classes, free);
+ goto fail;
+ }
+
+ /* TODO read remote version? */
memcpy(&uuid, classes->data, sizeof(uuid));
sdp_list_free(classes, free);
@@ -390,13 +479,23 @@ fail:
device_cleanup();
}
+static int sdp_search_hfp(void)
+{
+ uuid_t uuid;
+
+ sdp_uuid16_create(&uuid, HANDSFREE_SVCLASS_ID);
+
+ return bt_search_service(&adapter_addr, &device.bdaddr, &uuid,
+ sdp_hfp_search_cb, NULL, NULL, 0);
+}
+
static void handle_connect(const void *buf, uint16_t len)
{
const struct hal_cmd_handsfree_connect *cmd = buf;
char addr[18];
uint8_t status;
- uuid_t uuid;
bdaddr_t bdaddr;
+ int ret;
DBG("");
@@ -412,9 +511,9 @@ static void handle_connect(const void *buf, uint16_t len)
device_init(&bdaddr);
- sdp_uuid16_create(&uuid, HANDSFREE_SVCLASS_ID);
- if (bt_search_service(&adapter_addr, &device.bdaddr, &uuid,
- sdp_search_cb, NULL, NULL, 0) < 0) {
+ /* prefer HFP over HSP */
+ ret = hfp_server ? sdp_search_hfp() : sdp_search_hsp();
+ if (ret < 0) {
error("handsfree: SDP search failed");
device_cleanup();
status = HAL_STATUS_FAILED;
--
1.8.3.2
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 4/6] android/socket: Reserve channel for HSP AG
2014-02-28 16:19 ` [PATCH 4/6] android/socket: Reserve channel for HSP AG Szymon Janc
@ 2014-02-28 16:44 ` Johan Hedberg
2014-02-28 17:06 ` Szymon Janc
0 siblings, 1 reply; 11+ messages in thread
From: Johan Hedberg @ 2014-02-28 16:44 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
Hi Szymon,
On Fri, Feb 28, 2014, Szymon Janc wrote:
> ---
> android/socket.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/android/socket.c b/android/socket.c
> index ee98b54..f6863c8 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -47,8 +47,9 @@
>
> #define RFCOMM_CHANNEL_MAX 30
>
> +#define HSP_AG_DEFAULT_CHANNEL 11
> #define OPP_DEFAULT_CHANNEL 12
> -#define HFAG_DEFAULT_CHANNEL 13
> +#define HFP_AG_DEFAULT_CHANNEL 13
> #define PBAP_DEFAULT_CHANNEL 19
Wasn't our plan to mirror the BlueZ doc/assigned-numbers.txt here? At
least the OPP and HSP channels don't match up with that.
Johan
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/6] android/socket: Reserve channel for HSP AG
2014-02-28 16:44 ` Johan Hedberg
@ 2014-02-28 17:06 ` Szymon Janc
2014-02-28 17:19 ` Marcel Holtmann
0 siblings, 1 reply; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 17:06 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
Hi Johan,
On Friday 28 of February 2014 18:44:59 Johan Hedberg wrote:
> Hi Szymon,
>
> On Fri, Feb 28, 2014, Szymon Janc wrote:
> > ---
> > android/socket.c | 14 ++++++++++++--
> > 1 file changed, 12 insertions(+), 2 deletions(-)
> >
> > diff --git a/android/socket.c b/android/socket.c
> > index ee98b54..f6863c8 100644
> > --- a/android/socket.c
> > +++ b/android/socket.c
> > @@ -47,8 +47,9 @@
> >
> > #define RFCOMM_CHANNEL_MAX 30
> >
> > +#define HSP_AG_DEFAULT_CHANNEL 11
> > #define OPP_DEFAULT_CHANNEL 12
> > -#define HFAG_DEFAULT_CHANNEL 13
> > +#define HFP_AG_DEFAULT_CHANNEL 13
> > #define PBAP_DEFAULT_CHANNEL 19
>
> Wasn't our plan to mirror the BlueZ doc/assigned-numbers.txt here? At
> least the OPP and HSP channels don't match up with that.
We followed Bluedroid channels (although for HSP I did check which one is
used:), but we could go with BlueZ assigned-numbers.txt. That would require
fixed channels numbers for MAP, but that shouldn't be a problem.
Will send a patch for that.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/6] android/socket: Reserve channel for HSP AG
2014-02-28 17:06 ` Szymon Janc
@ 2014-02-28 17:19 ` Marcel Holtmann
2014-02-28 17:45 ` Szymon Janc
0 siblings, 1 reply; 11+ messages in thread
From: Marcel Holtmann @ 2014-02-28 17:19 UTC (permalink / raw)
To: Szymon Janc; +Cc: Johan Hedberg, linux-bluetooth
Hi Szymon,
>>> ---
>>> android/socket.c | 14 ++++++++++++--
>>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/android/socket.c b/android/socket.c
>>> index ee98b54..f6863c8 100644
>>> --- a/android/socket.c
>>> +++ b/android/socket.c
>>> @@ -47,8 +47,9 @@
>>>
>>> #define RFCOMM_CHANNEL_MAX 30
>>>
>>> +#define HSP_AG_DEFAULT_CHANNEL 11
>>> #define OPP_DEFAULT_CHANNEL 12
>>> -#define HFAG_DEFAULT_CHANNEL 13
>>> +#define HFP_AG_DEFAULT_CHANNEL 13
>>> #define PBAP_DEFAULT_CHANNEL 19
>>
>> Wasn't our plan to mirror the BlueZ doc/assigned-numbers.txt here? At
>> least the OPP and HSP channels don't match up with that.
>
> We followed Bluedroid channels (although for HSP I did check which one is
> used:), but we could go with BlueZ assigned-numbers.txt. That would require
> fixed channels numbers for MAP, but that shouldn't be a problem.
lets go with the Bluedroid ones, but make sure we document it somewhere which ones are used for what. I do not want to have to dig that out of the code.
Regards
Marcel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/6] android/socket: Reserve channel for HSP AG
2014-02-28 17:19 ` Marcel Holtmann
@ 2014-02-28 17:45 ` Szymon Janc
2014-02-28 17:54 ` Marcel Holtmann
0 siblings, 1 reply; 11+ messages in thread
From: Szymon Janc @ 2014-02-28 17:45 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: Johan Hedberg, linux-bluetooth
Hi Marcel,
On Friday 28 of February 2014 09:19:53 Marcel Holtmann wrote:
> Hi Szymon,
>
> >>> ---
> >>> android/socket.c | 14 ++++++++++++--
> >>> 1 file changed, 12 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/android/socket.c b/android/socket.c
> >>> index ee98b54..f6863c8 100644
> >>> --- a/android/socket.c
> >>> +++ b/android/socket.c
> >>> @@ -47,8 +47,9 @@
> >>>
> >>> #define RFCOMM_CHANNEL_MAX 30
> >>>
> >>> +#define HSP_AG_DEFAULT_CHANNEL 11
> >>> #define OPP_DEFAULT_CHANNEL 12
> >>> -#define HFAG_DEFAULT_CHANNEL 13
> >>> +#define HFP_AG_DEFAULT_CHANNEL 13
> >>> #define PBAP_DEFAULT_CHANNEL 19
> >>
> >> Wasn't our plan to mirror the BlueZ doc/assigned-numbers.txt here? At
> >> least the OPP and HSP channels don't match up with that.
> >
> > We followed Bluedroid channels (although for HSP I did check which one is
> > used:), but we could go with BlueZ assigned-numbers.txt. That would require
> > fixed channels numbers for MAP, but that shouldn't be a problem.
>
> lets go with the Bluedroid ones, but make sure we document it somewhere which ones are used for what. I do not want to have to dig that out of the code.
With Bluedroid there is bit awkward situation. Only PBAP and OPP channels are
explicitly reserved.
There is also comment that channel 1 is reserved for HFP AG but... when HFP AG
record is registered it skips channel 1 (due to it being already 'reserved' :)).
This results in HSP AG using channel 2, and HFP using channel 3 when both are
enabled. If one would disable HSP, then HFP would have channel 2. So those are
kind of dynamic :)
Opinions?:)
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/6] android/socket: Reserve channel for HSP AG
2014-02-28 17:45 ` Szymon Janc
@ 2014-02-28 17:54 ` Marcel Holtmann
0 siblings, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2014-02-28 17:54 UTC (permalink / raw)
To: Szymon Janc; +Cc: Johan Hedberg, linux-bluetooth
Hi Szymon,
>>>>> ---
>>>>> android/socket.c | 14 ++++++++++++--
>>>>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/android/socket.c b/android/socket.c
>>>>> index ee98b54..f6863c8 100644
>>>>> --- a/android/socket.c
>>>>> +++ b/android/socket.c
>>>>> @@ -47,8 +47,9 @@
>>>>>
>>>>> #define RFCOMM_CHANNEL_MAX 30
>>>>>
>>>>> +#define HSP_AG_DEFAULT_CHANNEL 11
>>>>> #define OPP_DEFAULT_CHANNEL 12
>>>>> -#define HFAG_DEFAULT_CHANNEL 13
>>>>> +#define HFP_AG_DEFAULT_CHANNEL 13
>>>>> #define PBAP_DEFAULT_CHANNEL 19
>>>>
>>>> Wasn't our plan to mirror the BlueZ doc/assigned-numbers.txt here? At
>>>> least the OPP and HSP channels don't match up with that.
>>>
>>> We followed Bluedroid channels (although for HSP I did check which one is
>>> used:), but we could go with BlueZ assigned-numbers.txt. That would require
>>> fixed channels numbers for MAP, but that shouldn't be a problem.
>>
>> lets go with the Bluedroid ones, but make sure we document it somewhere which ones are used for what. I do not want to have to dig that out of the code.
>
> With Bluedroid there is bit awkward situation. Only PBAP and OPP channels are
> explicitly reserved.
>
> There is also comment that channel 1 is reserved for HFP AG but... when HFP AG
> record is registered it skips channel 1 (due to it being already 'reserved' :)).
>
> This results in HSP AG using channel 2, and HFP using channel 3 when both are
> enabled. If one would disable HSP, then HFP would have channel 2. So those are
> kind of dynamic :)
that is funny indeed. Then lets just go with our assigned numbers where we want to use fixed ones. And do them dynamic for the ones where we need to be dynamic if at all.
Regards
Marcel
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2014-02-28 17:54 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-02-28 16:19 [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL Szymon Janc
2014-02-28 16:19 ` [PATCH 2/6] android/handsfree: Add support for enable HFP command Szymon Janc
2014-02-28 16:19 ` [PATCH 3/6] android/hal-handsfree: " Szymon Janc
2014-02-28 16:19 ` [PATCH 4/6] android/socket: Reserve channel for HSP AG Szymon Janc
2014-02-28 16:44 ` Johan Hedberg
2014-02-28 17:06 ` Szymon Janc
2014-02-28 17:19 ` Marcel Holtmann
2014-02-28 17:45 ` Szymon Janc
2014-02-28 17:54 ` Marcel Holtmann
2014-02-28 16:19 ` [PATCH 5/6] android/handsfree: Add support " Szymon Janc
2014-02-28 16:19 ` [PATCH 6/6] android/handsfree: Allow to connect to HSP or HFP handsfree unit Szymon Janc
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox