* [PATCH v3 2/8] android/hal: Update services register commands with mode parameter
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-02 23:50 ` [PATCH v3 3/8] android: Pass mode parameter to registered services Szymon Janc
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/hal-a2dp.c | 1 +
android/hal-avrcp.c | 1 +
android/hal-bluetooth.c | 1 +
android/hal-handsfree.c | 1 +
android/hal-hidhost.c | 1 +
android/hal-msg.h | 3 +++
android/hal-pan.c | 1 +
7 files changed, 9 insertions(+)
diff --git a/android/hal-a2dp.c b/android/hal-a2dp.c
index c898995..ac495a1 100644
--- a/android/hal-a2dp.c
+++ b/android/hal-a2dp.c
@@ -109,6 +109,7 @@ static bt_status_t init(btav_callbacks_t *callbacks)
sizeof(ev_handlers)/sizeof(ev_handlers[0]));
cmd.service_id = HAL_SERVICE_ID_A2DP;
+ cmd.mode = HAL_MODE_DEFAULT;
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-avrcp.c b/android/hal-avrcp.c
index 46e25a0..a720a1e 100644
--- a/android/hal-avrcp.c
+++ b/android/hal-avrcp.c
@@ -220,6 +220,7 @@ static bt_status_t init(btrc_callbacks_t *callbacks)
sizeof(ev_handlers) / sizeof(ev_handlers[0]));
cmd.service_id = HAL_SERVICE_ID_AVRCP;
+ cmd.mode = HAL_MODE_DEFAULT;
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-bluetooth.c b/android/hal-bluetooth.c
index 6871f5d..832183e 100644
--- a/android/hal-bluetooth.c
+++ b/android/hal-bluetooth.c
@@ -442,6 +442,7 @@ static int init(bt_callbacks_t *callbacks)
}
cmd.service_id = HAL_SERVICE_ID_SOCKET;
+ cmd.mode = HAL_MODE_DEFAULT;
status = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, NULL, NULL, NULL);
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 1b150c3..7a28e0f 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -212,6 +212,7 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
sizeof(ev_handlers)/sizeof(ev_handlers[0]));
cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
+ cmd.mode = HAL_MODE_DEFAULT;
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-hidhost.c b/android/hal-hidhost.c
index c758d2a..16253e3 100644
--- a/android/hal-hidhost.c
+++ b/android/hal-hidhost.c
@@ -354,6 +354,7 @@ static bt_status_t init(bthh_callbacks_t *callbacks)
sizeof(ev_handlers)/sizeof(ev_handlers[0]));
cmd.service_id = HAL_SERVICE_ID_HIDHOST;
+ cmd.mode = HAL_MODE_DEFAULT;
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 7b6e46d..8eb97c3 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -54,9 +54,12 @@ static const char BLUEZ_HAL_SK_PATH[] = "\0bluez_hal_socket";
#define HAL_OP_STATUS IPC_OP_STATUS
+#define HAL_MODE_DEFAULT 0x00
+
#define HAL_OP_REGISTER_MODULE 0x01
struct hal_cmd_register_module {
uint8_t service_id;
+ uint8_t mode;
} __attribute__((packed));
#define HAL_OP_UNREGISTER_MODULE 0x02
diff --git a/android/hal-pan.c b/android/hal-pan.c
index 5ee49ef..f383081 100644
--- a/android/hal-pan.c
+++ b/android/hal-pan.c
@@ -157,6 +157,7 @@ static bt_status_t pan_init(const btpan_callbacks_t *callbacks)
sizeof(ev_handlers)/sizeof(ev_handlers[0]));
cmd.service_id = HAL_SERVICE_ID_PAN;
+ cmd.mode = HAL_MODE_DEFAULT;
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 3/8] android: Pass mode parameter to registered services
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
2014-03-02 23:50 ` [PATCH v3 2/8] android/hal: Update services register commands with mode parameter Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-02 23:50 ` [PATCH v3 4/8] android/handsfree: Factor out HFP AG enable code Szymon Janc
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/a2dp.c | 2 +-
android/a2dp.h | 2 +-
android/avrcp.c | 2 +-
android/avrcp.h | 2 +-
android/bluetooth.c | 2 +-
android/bluetooth.h | 2 +-
android/handsfree.c | 2 +-
android/handsfree.h | 2 +-
android/hidhost.c | 2 +-
android/hidhost.h | 2 +-
android/main.c | 14 +++++++-------
android/pan.c | 2 +-
android/pan.h | 2 +-
android/socket.c | 2 +-
android/socket.h | 2 +-
15 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/android/a2dp.c b/android/a2dp.c
index 180d015..4ea16e2 100644
--- a/android/a2dp.c
+++ b/android/a2dp.c
@@ -1564,7 +1564,7 @@ retry:
audio_disconnected);
}
-bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
GError *err = NULL;
sdp_record_t *rec;
diff --git a/android/a2dp.h b/android/a2dp.h
index b41a178..8a70407 100644
--- a/android/a2dp.h
+++ b/android/a2dp.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
void bt_a2dp_unregister(void);
diff --git a/android/avrcp.c b/android/avrcp.c
index 678c321..b65f35c 100644
--- a/android/avrcp.c
+++ b/android/avrcp.c
@@ -364,7 +364,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
DBG("%s connected", address);
}
-bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
GError *err = NULL;
sdp_record_t *rec;
diff --git a/android/avrcp.h b/android/avrcp.h
index 3dcffeb..11e79b7 100644
--- a/android/avrcp.h
+++ b/android/avrcp.h
@@ -21,7 +21,7 @@
*
*/
-bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
void bt_avrcp_unregister(void);
void bt_avrcp_connect(const bdaddr_t *dst);
diff --git a/android/bluetooth.c b/android/bluetooth.c
index 8ad7d5d..6d94904 100644
--- a/android/bluetooth.c
+++ b/android/bluetooth.c
@@ -3285,7 +3285,7 @@ static const struct ipc_handler cmd_handlers[] = {
{ handle_le_test_mode_cmd, true, sizeof(struct hal_cmd_le_test_mode) },
};
-void bt_bluetooth_register(struct ipc *ipc)
+void bt_bluetooth_register(struct ipc *ipc, uint8_t mode)
{
DBG("");
diff --git a/android/bluetooth.h b/android/bluetooth.h
index fbc850d..1c177be 100644
--- a/android/bluetooth.h
+++ b/android/bluetooth.h
@@ -31,7 +31,7 @@ void bt_bluetooth_cleanup(void);
void bt_bluetooth_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
-void bt_bluetooth_register(struct ipc *ipc);
+void bt_bluetooth_register(struct ipc *ipc, uint8_t mode);
void bt_bluetooth_unregister(void);
int bt_adapter_add_record(sdp_record_t *rec, uint8_t svc_hint);
diff --git a/android/handsfree.c b/android/handsfree.c
index 81ddcc7..cfdcc1a 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -532,7 +532,7 @@ static sdp_record_t *handsfree_ag_record(void)
return record;
}
-bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
sdp_record_t *rec;
GError *err = NULL;
diff --git a/android/handsfree.h b/android/handsfree.h
index 3ede819..e5eff47 100644
--- a/android/handsfree.h
+++ b/android/handsfree.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
void bt_handsfree_unregister(void);
diff --git a/android/hidhost.c b/android/hidhost.c
index e469210..4226f69 100644
--- a/android/hidhost.c
+++ b/android/hidhost.c
@@ -1330,7 +1330,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
}
}
-bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
GError *err = NULL;
diff --git a/android/hidhost.h b/android/hidhost.h
index 1017195..e6b87ed 100644
--- a/android/hidhost.h
+++ b/android/hidhost.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
void bt_hid_unregister(void);
diff --git a/android/main.c b/android/main.c
index f7fe9c8..c6e08eb 100644
--- a/android/main.c
+++ b/android/main.c
@@ -84,43 +84,43 @@ static void service_register(const void *buf, uint16_t len)
switch (m->service_id) {
case HAL_SERVICE_ID_BLUETOOTH:
- bt_bluetooth_register(hal_ipc);
+ bt_bluetooth_register(hal_ipc, m->mode);
break;
case HAL_SERVICE_ID_SOCKET:
- bt_socket_register(hal_ipc, &adapter_bdaddr);
+ bt_socket_register(hal_ipc, &adapter_bdaddr, m->mode);
break;
case HAL_SERVICE_ID_HIDHOST:
- if (!bt_hid_register(hal_ipc, &adapter_bdaddr)) {
+ if (!bt_hid_register(hal_ipc, &adapter_bdaddr, m->mode)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_A2DP:
- if (!bt_a2dp_register(hal_ipc, &adapter_bdaddr)) {
+ if (!bt_a2dp_register(hal_ipc, &adapter_bdaddr, m->mode)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_PAN:
- if (!bt_pan_register(hal_ipc, &adapter_bdaddr)) {
+ if (!bt_pan_register(hal_ipc, &adapter_bdaddr, m->mode)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_AVRCP:
- if (!bt_avrcp_register(hal_ipc, &adapter_bdaddr)) {
+ if (!bt_avrcp_register(hal_ipc, &adapter_bdaddr, m->mode)) {
status = HAL_STATUS_FAILED;
goto failed;
}
break;
case HAL_SERVICE_ID_HANDSFREE:
- if (!bt_handsfree_register(hal_ipc, &adapter_bdaddr)) {
+ if (!bt_handsfree_register(hal_ipc, &adapter_bdaddr, m->mode)) {
status = HAL_STATUS_FAILED;
goto failed;
}
diff --git a/android/pan.c b/android/pan.c
index 1e404ab..ce1f677 100644
--- a/android/pan.c
+++ b/android/pan.c
@@ -779,7 +779,7 @@ static sdp_record_t *pan_record(void)
return record;
}
-bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr)
+bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
sdp_record_t *rec;
int err;
diff --git a/android/pan.h b/android/pan.h
index 2045ac5..cfbea96 100644
--- a/android/pan.h
+++ b/android/pan.h
@@ -21,5 +21,5 @@
*
*/
-bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr);
+bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
void bt_pan_unregister(void);
diff --git a/android/socket.c b/android/socket.c
index afa2008..7bc77ed 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -1129,7 +1129,7 @@ static const struct ipc_handler cmd_handlers[] = {
{ handle_connect, false, sizeof(struct hal_cmd_socket_connect) },
};
-void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr)
+void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
size_t i;
diff --git a/android/socket.h b/android/socket.h
index a1eca5a..b0e78c6 100644
--- a/android/socket.h
+++ b/android/socket.h
@@ -28,5 +28,5 @@ struct hal_sock_connect_signal {
int status;
} __attribute__((packed));
-void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr);
+void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode);
void bt_socket_unregister(void);
--
1.8.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/8] android/handsfree: Factor out HFP AG enable code
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
2014-03-02 23:50 ` [PATCH v3 2/8] android/hal: Update services register commands with mode parameter Szymon Janc
2014-03-02 23:50 ` [PATCH v3 3/8] android: Pass mode parameter to registered services Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-02 23:50 ` [PATCH v3 5/8] android/socket: Reserve channel for HSP AG Szymon Janc
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This is in preparation for support to not enable HFP AG when
initializing HAL.
---
android/handsfree.c | 77 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 28 deletions(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index cfdcc1a..7a1d697 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -56,10 +56,10 @@ static struct {
} device;
static bdaddr_t adapter_addr;
-static uint32_t record_id = 0;
static struct ipc *hal_ipc = NULL;
-static GIOChannel *server = NULL;
+static uint32_t hfp_record_id = 0;
+static GIOChannel *hfp_server = NULL;
static void device_set_state(uint8_t state)
{
@@ -460,7 +460,7 @@ static const struct ipc_handler cmd_handlers[] = {
sizeof(struct hal_cmd_handsfree_phone_state_change)},
};
-static sdp_record_t *handsfree_ag_record(void)
+static sdp_record_t *hfp_ag_record(void)
{
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
uuid_t root_uuid, svclass_uuid, ga_svclass_uuid;
@@ -532,27 +532,28 @@ static sdp_record_t *handsfree_ag_record(void)
return record;
}
-bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
+static bool enable_hfp_ag(void)
{
sdp_record_t *rec;
GError *err = NULL;
DBG("");
- bacpy(&adapter_addr, addr);
+ if (hfp_server)
+ return false;
- 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) {
+ 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);
- return false;
+ goto failed;
}
- rec = handsfree_ag_record();
+ rec = hfp_ag_record();
if (!rec) {
error("Failed to allocate Handsfree record");
goto failed;
@@ -563,22 +564,49 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
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));
+ hfp_record_id = rec->handle;
return true;
failed:
- g_io_channel_shutdown(server, TRUE, NULL);
- g_io_channel_unref(server);
- server = NULL;
+ g_io_channel_shutdown(hfp_server, TRUE, NULL);
+ g_io_channel_unref(hfp_server);
+ hfp_server = NULL;
return false;
}
+static void cleanup_hfp_ag(void)
+{
+ if (hfp_server) {
+ g_io_channel_shutdown(hfp_server, TRUE, NULL);
+ g_io_channel_unref(hfp_server);
+ hfp_server = NULL;
+ }
+
+ if (hfp_record_id > 0) {
+ bt_adapter_remove_record(hfp_record_id);
+ hfp_record_id = 0;
+ }
+}
+
+bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
+{
+ DBG("");
+
+ bacpy(&adapter_addr, addr);
+
+ if (!enable_hfp_ag())
+ return false;
+
+ hal_ipc = ipc;
+ ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
+ G_N_ELEMENTS(cmd_handlers));
+
+ return true;
+}
+
void bt_handsfree_unregister(void)
{
DBG("");
@@ -586,12 +614,5 @@ 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;
- }
-
- bt_adapter_remove_record(record_id);
- record_id = 0;
+ cleanup_hfp_ag();
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 5/8] android/socket: Reserve channel for HSP AG
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
` (2 preceding siblings ...)
2014-03-02 23:50 ` [PATCH v3 4/8] android/handsfree: Factor out HFP AG enable code Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-02 23:50 ` [PATCH v3 6/8] android/handsfree: Add support " Szymon Janc
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 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 7bc77ed..e9c7675 100644
--- a/android/socket.c
+++ b/android/socket.c
@@ -48,7 +48,8 @@
#define RFCOMM_CHANNEL_MAX 30
#define OPP_DEFAULT_CHANNEL 9
-#define HFAG_DEFAULT_CHANNEL 13
+#define HSP_AG_DEFAULT_CHANNEL 12
+#define HFP_AG_DEFAULT_CHANNEL 13
#define PBAP_DEFAULT_CHANNEL 15
#define MAP_MAS_DEFAULT_CHANNEL 16
@@ -376,10 +377,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.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 6/8] android/handsfree: Add support for HSP AG
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
` (3 preceding siblings ...)
2014-03-02 23:50 ` [PATCH v3 5/8] android/socket: Reserve channel for HSP AG Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-02 23:50 ` [PATCH v3 7/8] android/handsfree: Allow to connect to HSP or HFP handsfree unit Szymon Janc
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
---
android/handsfree.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 135 insertions(+), 1 deletion(-)
diff --git a/android/handsfree.c b/android/handsfree.c
index 7a1d697..0b97a5d 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -46,7 +46,9 @@
#include "src/log.h"
#include "utils.h"
+#define HSP_AG_CHANNEL 12
#define HFP_AG_CHANNEL 13
+
#define HFP_AG_FEATURES 0
static struct {
@@ -61,6 +63,9 @@ 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 void device_set_state(uint8_t state)
{
struct hal_ev_handsfree_conn_state ev;
@@ -460,6 +465,129 @@ static const struct ipc_handler cmd_handlers[] = {
sizeof(struct hal_cmd_handsfree_phone_state_change)},
};
+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 = 0x0102;
+ 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], 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 bool enable_hsp_ag(void)
+{
+ sdp_record_t *rec;
+ GError *err = NULL;
+
+ DBG("");
+
+ 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;
+
+ return true;
+
+failed:
+ g_io_channel_shutdown(hsp_server, TRUE, NULL);
+ g_io_channel_unref(hsp_server);
+ hsp_server = NULL;
+
+ return false;
+}
+
+static void cleanup_hsp_ag(void)
+{
+ 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;
+ }
+}
+
static sdp_record_t *hfp_ag_record(void)
{
sdp_list_t *svclass_id, *pfseq, *apseq, *root;
@@ -597,9 +725,14 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
bacpy(&adapter_addr, addr);
- if (!enable_hfp_ag())
+ if (!enable_hsp_ag())
return false;
+ if (!enable_hfp_ag()) {
+ cleanup_hsp_ag();
+ return false;
+ }
+
hal_ipc = ipc;
ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
@@ -615,4 +748,5 @@ void bt_handsfree_unregister(void)
hal_ipc = NULL;
cleanup_hfp_ag();
+ cleanup_hsp_ag();
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 7/8] android/handsfree: Allow to connect to HSP or HFP handsfree unit
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
` (4 preceding siblings ...)
2014-03-02 23:50 ` [PATCH v3 6/8] android/handsfree: Add support " Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-02 23:50 ` [PATCH v3 8/8] android/handsfree: Add support for disabling HSP or HFP AGs Szymon Janc
2014-03-04 9:20 ` [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 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 0b97a5d..6149c62 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -184,7 +184,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;
@@ -195,12 +195,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;
}
@@ -216,6 +217,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);
@@ -254,13 +343,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("");
@@ -276,9 +375,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.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 8/8] android/handsfree: Add support for disabling HSP or HFP AGs
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
` (5 preceding siblings ...)
2014-03-02 23:50 ` [PATCH v3 7/8] android/handsfree: Allow to connect to HSP or HFP handsfree unit Szymon Janc
@ 2014-03-02 23:50 ` Szymon Janc
2014-03-04 9:20 ` [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-02 23:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
This allows to tune what profiles are supported by handsfree HAL.
---
android/cutils/properties.h | 8 ++++++++
android/hal-handsfree.c | 15 ++++++++++++++-
android/hal-msg.h | 2 ++
android/handsfree.c | 4 ++--
4 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/android/cutils/properties.h b/android/cutils/properties.h
index dff812f..66a4a84 100644
--- a/android/cutils/properties.h
+++ b/android/cutils/properties.h
@@ -27,6 +27,14 @@
#include <sys/socket.h>
#include <sys/un.h>
+#define PROPERTY_VALUE_MAX 32
+
+static inline int property_get(const char *key, char *value,
+ const char *default_value)
+{
+ return 0;
+}
+
/* property_set: returns 0 on success, < 0 on failure
*/
static inline int property_set(const char *key, const char *value)
diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 7a28e0f..4117ed0 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -20,6 +20,8 @@
#include <string.h>
#include <stdlib.h>
+#include <cutils/properties.h>
+
#include "hal-log.h"
#include "hal.h"
#include "hal-msg.h"
@@ -196,6 +198,17 @@ static const struct hal_ipc_handler ev_handlers[] = {
{handle_hsp_key_press, false, 0},
};
+static uint8_t get_mode(void)
+{
+ char value[PROPERTY_VALUE_MAX];
+
+ if (property_get("bluetooth.handsfree_mode", value, "") > 0 &&
+ (!strcasecmp(value, "hsp_only")))
+ return HAL_MODE_HANDSFREE_HSP_ONLY;
+
+ return HAL_MODE_DEFAULT;
+}
+
static bt_status_t init(bthf_callbacks_t *callbacks)
{
struct hal_cmd_register_module cmd;
@@ -212,7 +225,7 @@ static bt_status_t init(bthf_callbacks_t *callbacks)
sizeof(ev_handlers)/sizeof(ev_handlers[0]));
cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
- cmd.mode = HAL_MODE_DEFAULT;
+ cmd.mode = get_mode();
ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
sizeof(cmd), &cmd, 0, NULL, NULL);
diff --git a/android/hal-msg.h b/android/hal-msg.h
index 8eb97c3..dd25f6e 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -385,6 +385,8 @@ struct hal_cmd_pan_disconnect {
/* Handsfree HAL API */
+#define HAL_MODE_HANDSFREE_HSP_ONLY 0x01
+
#define HAL_OP_HANDSFREE_CONNECT 0x01
struct hal_cmd_handsfree_connect {
uint8_t bdaddr[6];
diff --git a/android/handsfree.c b/android/handsfree.c
index 6149c62..4f69e68 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -820,14 +820,14 @@ static void cleanup_hfp_ag(void)
bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
{
- DBG("");
+ DBG("mode 0x%x", mode);
bacpy(&adapter_addr, addr);
if (!enable_hsp_ag())
return false;
- if (!enable_hfp_ag()) {
+ if (mode != HAL_MODE_HANDSFREE_HSP_ONLY && !enable_hfp_ag()) {
cleanup_hsp_ag();
return false;
}
--
1.8.5.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command
2014-03-02 23:50 [PATCH v3 1/8] android/ipc: Add Mode parameter to register service command Szymon Janc
` (6 preceding siblings ...)
2014-03-02 23:50 ` [PATCH v3 8/8] android/handsfree: Add support for disabling HSP or HFP AGs Szymon Janc
@ 2014-03-04 9:20 ` Szymon Janc
7 siblings, 0 replies; 9+ messages in thread
From: Szymon Janc @ 2014-03-04 9:20 UTC (permalink / raw)
To: linux-bluetooth
On Monday 03 of March 2014 00:50:42 Szymon Janc wrote:
> This will allow to run daemon services in non-default mode.
> ---
> android/hal-ipc-api.txt | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/android/hal-ipc-api.txt b/android/hal-ipc-api.txt
> index 0518c2f..6bf9af3 100644
> --- a/android/hal-ipc-api.txt
> +++ b/android/hal-ipc-api.txt
> @@ -124,12 +124,16 @@ Core Service (ID 0)
> Opcode 0x01 - Register module command/response
>
> Command parameters: Service id (1 octet)
> + Mode (1 octet)
> Response parameters: <none>
>
> In case a command is sent for an undeclared service ID, it will
> be rejected. Also there will be no notifications for undeclared
> service ID.
>
> + Valid Mode values: 0x00 = Default Mode
> + 0xXX = as defined by service
> +
> In case of an error, the error response will be returned.
>
> Opcode 0x02 - Unregister module command/response
> @@ -749,6 +753,8 @@ Bluetooth Handsfree HAL (ID 5)
>
> Android HAL name: "handsfree" (BT_PROFILE_HANDSFREE_ID)
>
> + Service modes: 0x01 = Headset Profile only mode
> +
> Opcode 0x00 - Error response
>
> Response parameters: Status (1 octet)
>
Pushed.
--
Best regards,
Szymon Janc
^ permalink raw reply [flat|nested] 9+ messages in thread