* [PATCHv2 9/9] unit/avrcp: Add /TP/PAS/BV-11-C test
From: Andrei Emeltchenko @ 2014-02-28 14:18 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393597125-18176-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Test verifies that the set player application setting value command
issued from the Controller.
---
unit/test-avrcp.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
index 0206e19..76fcdaf 100644
--- a/unit/test-avrcp.c
+++ b/unit/test-avrcp.c
@@ -461,6 +461,16 @@ static void test_client(gconstpointer data)
sizeof(attributes), NULL, NULL);
}
+ if (g_str_equal(context->data->test_name, "/TP/PAS/BV-11-C")) {
+ uint8_t attributes[2] = { AVRCP_ATTRIBUTE_EQUALIZER,
+ AVRCP_ATTRIBUTE_REPEAT_MODE };
+ uint8_t values[] = { 0xaa, 0xff };
+
+ avrcp_set_player_value(context->session, attributes,
+ sizeof(attributes), values,
+ NULL, NULL);
+ }
+
execute_context(context);
}
@@ -628,5 +638,13 @@ int main(int argc, char *argv[])
AVRCP_ATTRIBUTE_EQUALIZER, 0x00,
AVRCP_ATTRIBUTE_REPEAT_MODE, 0x00));
+ define_test("/TP/PAS/BV-11-C", test_client,
+ raw_pdu(0x00, 0x11, 0x0e, 0x00, 0x48, 0x00,
+ 0x00, 0x19, 0x58,
+ AVRCP_SET_PLAYER_VALUE,
+ 0x00, 0x00, 0x05, 0x02,
+ AVRCP_ATTRIBUTE_EQUALIZER, 0xaa,
+ AVRCP_ATTRIBUTE_REPEAT_MODE, 0xff));
+
return g_test_run();
}
--
1.8.3.2
^ permalink raw reply related
* Re: [PATCHv2 4/9] avrcp: Fix buffer size check
From: Luiz Augusto von Dentz @ 2014-02-28 14:26 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1393597125-18176-4-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Fri, Feb 28, 2014 at 3:18 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Fix size check taking into account that attributes starts from 1 (0 is
> illegal).
> ---
> profiles/audio/avrcp.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
> index c0e5d07..48c3355 100644
> --- a/profiles/audio/avrcp.c
> +++ b/profiles/audio/avrcp.c
> @@ -1909,7 +1909,7 @@ static void avrcp_get_current_player_value(struct avrcp *session,
> struct avrcp_header *pdu = (void *) buf;
> uint16_t length = AVRCP_HEADER_LENGTH + count + 1;
>
> - if (count > AVRCP_ATTRIBUTE_LAST + 1)
> + if (count > AVRCP_ATTRIBUTE_LAST)
> return;
>
> memset(buf, 0, sizeof(buf));
> --
> 1.8.3.2
This does not apply anymore, there is no check inside
avrcp_get_current_player_value.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCHv2 1/9] unit/avrcp: Add /TP/PAS/BV-06-C test
From: Luiz Augusto von Dentz @ 2014-02-28 14:28 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1393597125-18176-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
Hi Andrei,
On Fri, Feb 28, 2014 at 3:18 PM, Andrei Emeltchenko
<Andrei.Emeltchenko.news@gmail.com> wrote:
> From: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
>
> Test verifies that the list player application setting values response
> issued from the Target.
> ---
> unit/test-avrcp.c | 32 ++++++++++++++++++++++++++++++++
> 1 file changed, 32 insertions(+)
>
> diff --git a/unit/test-avrcp.c b/unit/test-avrcp.c
> index db9cb92..51fe064 100644
> --- a/unit/test-avrcp.c
> +++ b/unit/test-avrcp.c
> @@ -355,6 +355,26 @@ static uint8_t avrcp_handle_get_player_attr_text(struct avrcp *session,
> return AVC_CTYPE_STABLE;
> }
>
> +static uint8_t avrcp_handle_list_player_values(struct avrcp *session,
> + uint8_t transaction, uint16_t *params_len,
> + uint8_t *params, void *user_data)
> +{
> + DBG("params[0] %d params_len %d", params[0], *params_len);
> +
> + if (*params_len != 1)
> + goto fail;
> +
> + *params_len = 1;
> + params[0] = 0;
> + return AVC_CTYPE_STABLE;
> +
> +fail:
> + *params_len = 1;
> + params[0] = AVRCP_STATUS_INVALID_PARAM;
> +
> + return AVC_CTYPE_REJECTED;
> +}
> +
> static const struct avrcp_control_handler control_handlers[] = {
> { AVRCP_GET_CAPABILITIES, AVC_CTYPE_STATUS,
> avrcp_handle_get_capabilities },
> @@ -362,6 +382,8 @@ static const struct avrcp_control_handler control_handlers[] = {
> avrcp_handle_list_attributes },
> { AVRCP_GET_PLAYER_ATTRIBUTE_TEXT, AVC_CTYPE_STATUS,
> avrcp_handle_get_player_attr_text },
> + { AVRCP_LIST_PLAYER_VALUES, AVC_CTYPE_STATUS,
> + avrcp_handle_list_player_values },
> { },
> };
>
> @@ -518,5 +540,15 @@ int main(int argc, char *argv[])
> AVRCP_GET_PLAYER_ATTRIBUTE_TEXT,
> 0x00, 0x00, 0x01, 0x00));
>
> + define_test("/TP/PAS/BV-06-C", test_server,
> + raw_pdu(0x00, 0x11, 0x0e, 0x01, 0x48, 0x00,
> + 0x00, 0x19, 0x58,
> + AVRCP_LIST_PLAYER_VALUES,
> + 0x00, 0x00, 0x01, 0x00),
> + raw_pdu(0x02, 0x11, 0x0e, 0x0c, 0x48, 0x00,
> + 0x00, 0x19, 0x58,
> + AVRCP_LIST_PLAYER_VALUES,
> + 0x00, 0x00, 0x01, 0x00));
> +
> return g_test_run();
> }
> --
> 1.8.3.2
Hold on with the unit tests, we need to add the asynchronous response
support otherwise it wont work with Android.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH 1/6] android: Refactor IPC init
From: Szymon Janc @ 2014-02-28 14:34 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393592969-4451-1-git-send-email-szymon.janc@tieto.com>
On Friday 28 of February 2014 14:09:24 Szymon Janc wrote:
> This allows to pass socket path and max service ID while initializaing
> IPC. This is first step to allow use it both for BT and Audio HALs.
> ---
> android/a2dp.c | 27 +++++++----
> android/a2dp.h | 2 +-
> android/avrcp.c | 52 +++++++++++----------
> android/avrcp.h | 2 +-
> android/bluetooth.c | 113 +++++++++++++++++++++++++-------------------
> android/bluetooth.h | 2 +-
> android/handsfree.c | 65 ++++++++++++++------------
> android/handsfree.h | 2 +-
> android/hidhost.c | 61 +++++++++++++-----------
> android/hidhost.h | 2 +-
> android/ipc.c | 132 +++++++++++++++++++++++++++++++++-------------------
> android/ipc.h | 24 ++++++----
> android/main.c | 41 +++++++++-------
> android/pan.c | 32 +++++++------
> android/pan.h | 2 +-
> android/socket.c | 26 +++++++----
> android/socket.h | 2 +-
> android/test-ipc.c | 44 ++++++++++++------
> 18 files changed, 374 insertions(+), 257 deletions(-)
>
> diff --git a/android/a2dp.c b/android/a2dp.c
> index 5d7dc78..b05d4bd 100644
> --- a/android/a2dp.c
> +++ b/android/a2dp.c
> @@ -39,9 +39,9 @@
> #include "lib/sdp_lib.h"
> #include "profiles/audio/a2dp-codecs.h"
> #include "src/log.h"
> -#include "a2dp.h"
> #include "hal-msg.h"
> #include "ipc.h"
> +#include "a2dp.h"
> #include "utils.h"
> #include "bluetooth.h"
> #include "avdtp.h"
> @@ -63,6 +63,8 @@ static uint32_t record_id = 0;
> static guint audio_retry_id = 0;
> static bool audio_retrying = false;
>
> +static struct ipc *hal_ipc = NULL;
> +
> struct a2dp_preset {
> void *data;
> int8_t len;
> @@ -226,8 +228,8 @@ static void bt_a2dp_notify_state(struct a2dp_device *dev, uint8_t state)
> bdaddr2android(&dev->dst, ev.bdaddr);
> ev.state = state;
>
> - ipc_send_notif(HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_CONN_STATE, sizeof(ev),
> - &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_CONN_STATE,
> + sizeof(ev), &ev);
>
> if (state != HAL_A2DP_STATE_DISCONNECTED)
> return;
> @@ -253,8 +255,8 @@ static void bt_audio_notify_state(struct a2dp_setup *setup, uint8_t state)
> bdaddr2android(&setup->dev->dst, ev.bdaddr);
> ev.state = state;
>
> - ipc_send_notif(HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_AUDIO_STATE, sizeof(ev),
> - &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_EV_A2DP_AUDIO_STATE,
> + sizeof(ev), &ev);
> }
>
> static void disconnect_cb(void *user_data)
> @@ -597,7 +599,7 @@ static void bt_a2dp_connect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_CONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_CONNECT, status);
> }
>
> static void bt_a2dp_disconnect(const void *buf, uint16_t len)
> @@ -631,7 +633,8 @@ static void bt_a2dp_disconnect(const void *buf, uint16_t len)
> bt_a2dp_notify_state(dev, HAL_A2DP_STATE_DISCONNECTING);
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_DISCONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_A2DP, HAL_OP_A2DP_DISCONNECT,
> + status);
> }
>
> static const struct ipc_handler cmd_handlers[] = {
> @@ -1540,7 +1543,7 @@ retry:
> audio_disconnected);
> }
>
> -bool bt_a2dp_register(const bdaddr_t *addr)
> +bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> GError *err = NULL;
> sdp_record_t *rec;
> @@ -1573,7 +1576,9 @@ bool bt_a2dp_register(const bdaddr_t *addr)
> }
> record_id = rec->handle;
>
> - ipc_register(HAL_SERVICE_ID_A2DP, cmd_handlers,
> + hal_ipc = ipc;
> +
> + ipc_register(hal_ipc, HAL_SERVICE_ID_A2DP, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
>
> bt_audio_register(audio_disconnected);
> @@ -1600,7 +1605,9 @@ void bt_a2dp_unregister(void)
> g_slist_free_full(devices, a2dp_device_free);
> devices = NULL;
>
> - ipc_unregister(HAL_SERVICE_ID_A2DP);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_A2DP);
> + hal_ipc = NULL;
> +
> audio_ipc_unregister();
>
> bt_adapter_remove_record(record_id);
> diff --git a/android/a2dp.h b/android/a2dp.h
> index e626e41..b41a178 100644
> --- a/android/a2dp.h
> +++ b/android/a2dp.h
> @@ -21,5 +21,5 @@
> *
> */
>
> -bool bt_a2dp_register(const bdaddr_t *addr);
> +bool bt_a2dp_register(struct ipc *ipc, const bdaddr_t *addr);
> void bt_a2dp_unregister(void);
> diff --git a/android/avrcp.c b/android/avrcp.c
> index 8ff70b4..678c321 100644
> --- a/android/avrcp.c
> +++ b/android/avrcp.c
> @@ -33,12 +33,12 @@
> #include "lib/sdp.h"
> #include "lib/sdp_lib.h"
> #include "src/log.h"
> -#include "bluetooth.h"
> #include "avctp.h"
> -#include "avrcp.h"
> #include "avrcp-lib.h"
> #include "hal-msg.h"
> #include "ipc.h"
> +#include "bluetooth.h"
> +#include "avrcp.h"
>
> #define L2CAP_PSM_AVCTP 0x17
>
> @@ -51,6 +51,7 @@ static bdaddr_t adapter_addr;
> static uint32_t record_id = 0;
> static GSList *devices = NULL;
> static GIOChannel *server = NULL;
> +static struct ipc *hal_ipc = NULL;
>
> struct avrcp_device {
> bdaddr_t dst;
> @@ -62,79 +63,79 @@ static void handle_get_play_status(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAY_STATUS,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_GET_PLAY_STATUS, HAL_STATUS_FAILED);
> }
>
> static void handle_list_player_attrs(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_LIST_PLAYER_ATTRS,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_LIST_PLAYER_ATTRS, HAL_STATUS_FAILED);
> }
>
> static void handle_list_player_values(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_LIST_PLAYER_VALUES,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_LIST_PLAYER_VALUES, HAL_STATUS_FAILED);
> }
>
> static void handle_get_player_attrs(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAYER_ATTRS,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_GET_PLAYER_ATTRS, HAL_STATUS_FAILED);
> }
>
> static void handle_get_player_attrs_text(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_GET_PLAYER_ATTRS_TEXT, HAL_STATUS_FAILED);
> }
>
> static void handle_get_player_values_text(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_GET_PLAYER_VALUES_TEXT, HAL_STATUS_FAILED);
> }
>
> static void handle_get_element_attrs_text(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_GET_ELEMENT_ATTRS_TEXT, HAL_STATUS_FAILED);
> }
>
> static void handle_set_player_attrs_value(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_SET_PLAYER_ATTRS_VALUE, HAL_STATUS_FAILED);
> }
>
> static void handle_register_notification(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_REGISTER_NOTIFICATION,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP,
> + HAL_OP_AVRCP_REGISTER_NOTIFICATION, HAL_STATUS_FAILED);
> }
>
> static void handle_set_volume(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_AVRCP, HAL_OP_AVRCP_SET_VOLUME,
> HAL_STATUS_FAILED);
> }
>
> @@ -363,7 +364,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
> DBG("%s connected", address);
> }
>
> -bool bt_avrcp_register(const bdaddr_t *addr)
> +bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> GError *err = NULL;
> sdp_record_t *rec;
> @@ -396,7 +397,9 @@ bool bt_avrcp_register(const bdaddr_t *addr)
> }
> record_id = rec->handle;
>
> - ipc_register(HAL_SERVICE_ID_AVRCP, cmd_handlers,
> + hal_ipc = ipc;
> +
> + ipc_register(hal_ipc, HAL_SERVICE_ID_AVRCP, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
>
> return true;
> @@ -415,7 +418,8 @@ void bt_avrcp_unregister(void)
> g_slist_free_full(devices, avrcp_device_free);
> devices = NULL;
>
> - ipc_unregister(HAL_SERVICE_ID_AVRCP);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_AVRCP);
> + hal_ipc = NULL;
>
> bt_adapter_remove_record(record_id);
> record_id = 0;
> diff --git a/android/avrcp.h b/android/avrcp.h
> index 1fcd953..3dcffeb 100644
> --- a/android/avrcp.h
> +++ b/android/avrcp.h
> @@ -21,7 +21,7 @@
> *
> */
>
> -bool bt_avrcp_register(const bdaddr_t *addr);
> +bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr);
> void bt_avrcp_unregister(void);
>
> void bt_avrcp_connect(const bdaddr_t *dst);
> diff --git a/android/bluetooth.c b/android/bluetooth.c
> index ac4c213..26493f7 100644
> --- a/android/bluetooth.c
> +++ b/android/bluetooth.c
> @@ -145,6 +145,8 @@ static GSList *cached_devices = NULL;
> /* This list contains addresses which are asked for records */
> static GSList *browse_reqs;
>
> +static struct ipc *hal_ipc = NULL;
> +
> static void store_adapter_config(void)
> {
> GKeyFile *key_file;
> @@ -390,8 +392,8 @@ static void send_adapter_property(uint8_t type, uint16_t len, const void *val)
> ev->props[0].len = len;
> memcpy(ev->props[0].val, val, len);
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
> - sizeof(buf), buf);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), buf);
> }
>
> static void adapter_name_changed(const uint8_t *name)
> @@ -440,8 +442,8 @@ static void powered_changed(void)
>
> DBG("%u", ev.state);
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_STATE_CHANGED,
> - sizeof(ev), &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_ADAPTER_STATE_CHANGED, sizeof(ev), &ev);
> }
>
> static uint8_t settings2scan_mode(void)
> @@ -594,8 +596,8 @@ static void send_bond_state_change(const bdaddr_t *addr, uint8_t status,
> ev.state = state;
> bdaddr2android(addr, ev.bdaddr);
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_BOND_STATE_CHANGED,
> - sizeof(ev), &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_BOND_STATE_CHANGED, sizeof(ev), &ev);
> }
>
> static void set_device_bond_state(const bdaddr_t *addr, uint8_t status,
> @@ -647,8 +649,8 @@ static void send_device_property(const bdaddr_t *bdaddr, uint8_t type,
> ev->props[0].len = len;
> memcpy(ev->props[0].val, val, len);
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_REMOTE_DEVICE_PROPS,
> - sizeof(buf), buf);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_REMOTE_DEVICE_PROPS, sizeof(buf), buf);
> }
>
> static void send_device_uuids_notif(struct device *dev)
> @@ -883,7 +885,7 @@ static void pin_code_request_callback(uint16_t index, uint16_t length,
> bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
> hal_ev.class_of_dev = dev->class;
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_PIN_REQUEST,
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_EV_PIN_REQUEST,
> sizeof(hal_ev), &hal_ev);
> }
>
> @@ -901,7 +903,7 @@ static void send_ssp_request(const bdaddr_t *addr, uint8_t variant,
> ev.pairing_variant = variant;
> ev.passkey = passkey;
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_SSP_REQUEST,
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_EV_SSP_REQUEST,
> sizeof(ev), &ev);
> }
>
> @@ -1010,7 +1012,7 @@ static void mgmt_discovering_event(uint16_t index, uint16_t length,
> cp.state = HAL_DISCOVERY_STATE_STOPPED;
> }
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH,
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> HAL_EV_DISCOVERY_STATE_CHANGED, sizeof(cp), &cp);
> }
>
> @@ -1106,8 +1108,8 @@ static void update_new_device(struct device *dev, int8_t rssi,
> ev->num_props++;
> }
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_DEVICE_FOUND, size,
> - buf);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_EV_DEVICE_FOUND,
> + size, buf);
> }
>
> static void update_device(struct device *dev, int8_t rssi,
> @@ -1147,7 +1149,7 @@ static void update_device(struct device *dev, int8_t rssi,
> }
>
> if (ev->num_props)
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH,
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> HAL_EV_REMOTE_DEVICE_PROPS, size, buf);
> }
>
> @@ -1259,8 +1261,8 @@ static void mgmt_device_connected_event(uint16_t index, uint16_t length,
> hal_ev.state = HAL_ACL_STATE_CONNECTED;
> bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ACL_STATE_CHANGED,
> - sizeof(hal_ev), &hal_ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_ACL_STATE_CHANGED, sizeof(hal_ev), &hal_ev);
> }
>
> static void mgmt_device_disconnected_event(uint16_t index, uint16_t length,
> @@ -1279,8 +1281,8 @@ static void mgmt_device_disconnected_event(uint16_t index, uint16_t length,
> hal_ev.state = HAL_ACL_STATE_DISCONNECTED;
> bdaddr2android(&ev->addr.bdaddr, hal_ev.bdaddr);
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ACL_STATE_CHANGED,
> - sizeof(hal_ev), &hal_ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_ACL_STATE_CHANGED, sizeof(hal_ev), &hal_ev);
> }
>
> static uint8_t status_mgmt2hal(uint8_t mgmt)
> @@ -1502,8 +1504,8 @@ static uint8_t get_adapter_uuids(void)
> p += sizeof(uint128_t);
> }
>
> - ipc_send_notif(HAL_SERVICE_ID_BLUETOOTH, HAL_EV_ADAPTER_PROPS_CHANGED,
> - sizeof(buf), ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_EV_ADAPTER_PROPS_CHANGED, sizeof(buf), ev);
>
> return HAL_STATUS_SUCCESS;
> }
> @@ -2387,7 +2389,8 @@ static void handle_get_adapter_prop_cmd(const void *buf, uint16_t len)
> error("Failed to get adapter property (type %u status %u)",
> cmd->type, status);
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROP,
> + status);
> }
>
> static void get_adapter_properties(void)
> @@ -2538,7 +2541,8 @@ static void handle_set_adapter_prop_cmd(const void *buf, uint16_t len)
> error("Failed to set adapter property (type %u status %u)",
> cmd->type, status);
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_ADAPTER_PROP, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_ADAPTER_PROP,
> + status);
> }
>
> static void pair_device_complete(uint8_t status, uint16_t length,
> @@ -2579,7 +2583,8 @@ static void handle_create_bond_cmd(const void *buf, uint16_t len)
> HAL_BOND_STATE_BONDING);
>
> fail:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CREATE_BOND, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CREATE_BOND,
> + status);
> }
>
> static void handle_cancel_bond_cmd(const void *buf, uint16_t len)
> @@ -2597,7 +2602,8 @@ static void handle_cancel_bond_cmd(const void *buf, uint16_t len)
> else
> status = HAL_STATUS_FAILED;
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_BOND, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_BOND,
> + status);
> }
>
> static void unpair_device_complete(uint8_t status, uint16_t length,
> @@ -2631,7 +2637,8 @@ static void handle_remove_bond_cmd(const void *buf, uint16_t len)
> else
> status = HAL_STATUS_FAILED;
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_REMOVE_BOND, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_REMOVE_BOND,
> + status);
> }
>
> static void handle_pin_reply_cmd(const void *buf, uint16_t len)
> @@ -2682,7 +2689,8 @@ static void handle_pin_reply_cmd(const void *buf, uint16_t len)
>
> status = HAL_STATUS_SUCCESS;
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_PIN_REPLY, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_PIN_REPLY,
> + status);
> }
>
> static uint8_t user_confirm_reply(const bdaddr_t *bdaddr, bool accept)
> @@ -2770,7 +2778,8 @@ static void handle_ssp_reply_cmd(const void *buf, uint16_t len)
> break;
> }
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SSP_REPLY, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SSP_REPLY,
> + status);
> }
>
> static void handle_get_remote_services_cmd(const void *buf, uint16_t len)
> @@ -2783,8 +2792,8 @@ static void handle_get_remote_services_cmd(const void *buf, uint16_t len)
>
> status = browse_remote_sdp(&addr);
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_SERVICES,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_OP_GET_REMOTE_SERVICES, status);
> }
>
> static uint8_t get_device_uuids(struct device *dev)
> @@ -2907,7 +2916,7 @@ static void handle_enable_cmd(const void *buf, uint16_t len)
>
> status = HAL_STATUS_SUCCESS;
> reply:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_ENABLE, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_ENABLE, status);
> }
>
> static void handle_disable_cmd(const void *buf, uint16_t len)
> @@ -2929,15 +2938,15 @@ static void handle_disable_cmd(const void *buf, uint16_t len)
>
> status = HAL_STATUS_SUCCESS;
> reply:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DISABLE, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DISABLE, status);
> }
>
> static void handle_get_adapter_props_cmd(const void *buf, uint16_t len)
> {
> get_adapter_properties();
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_ADAPTER_PROPS,
> - HAL_STATUS_SUCCESS);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_OP_GET_ADAPTER_PROPS, HAL_STATUS_SUCCESS);
> }
>
> static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
> @@ -2960,8 +2969,8 @@ static void handle_get_remote_device_props_cmd(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROPS,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_OP_GET_REMOTE_DEVICE_PROPS, status);
> }
>
> static void handle_get_remote_device_prop_cmd(const void *buf, uint16_t len)
> @@ -3017,8 +3026,8 @@ static void handle_get_remote_device_prop_cmd(const void *buf, uint16_t len)
> cmd->type, status);
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_DEVICE_PROP,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_OP_GET_REMOTE_DEVICE_PROP, status);
> }
>
> static uint8_t set_device_friendly_name(struct device *dev, const uint8_t *val,
> @@ -3088,8 +3097,8 @@ static void handle_set_remote_device_prop_cmd(const void *buf, uint16_t len)
> cmd->type, status);
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_SET_REMOTE_DEVICE_PROP,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_OP_SET_REMOTE_DEVICE_PROP, status);
> }
>
> static void handle_get_remote_service_rec_cmd(const void *buf, uint16_t len)
> @@ -3098,8 +3107,8 @@ static void handle_get_remote_service_rec_cmd(const void *buf, uint16_t len)
>
> error("get_remote_service_record not supported");
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_GET_REMOTE_SERVICE_REC,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH,
> + HAL_OP_GET_REMOTE_SERVICE_REC, HAL_STATUS_FAILED);
> }
>
> static void handle_start_discovery_cmd(const void *buf, uint16_t len)
> @@ -3123,7 +3132,8 @@ static void handle_start_discovery_cmd(const void *buf, uint16_t len)
>
> status = HAL_STATUS_SUCCESS;
> reply:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_START_DISCOVERY, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_START_DISCOVERY,
> + status);
> }
>
> static void handle_cancel_discovery_cmd(const void *buf, uint16_t len)
> @@ -3148,7 +3158,8 @@ static void handle_cancel_discovery_cmd(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> reply:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_DISCOVERY, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_CANCEL_DISCOVERY,
> + status);
> }
>
> static void handle_dut_mode_conf_cmd(const void *buf, uint16_t len)
> @@ -3181,7 +3192,8 @@ static void handle_dut_mode_conf_cmd(const void *buf, uint16_t len)
> close(fd);
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_CONF, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_CONF,
> + status);
> }
>
> static void handle_dut_mode_send_cmd(const void *buf, uint16_t len)
> @@ -3198,7 +3210,7 @@ static void handle_dut_mode_send_cmd(const void *buf, uint16_t len)
>
> /* TODO */
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_SEND,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_DUT_MODE_SEND,
> HAL_STATUS_FAILED);
> }
>
> @@ -3216,7 +3228,7 @@ static void handle_le_test_mode_cmd(const void *buf, uint16_t len)
>
> /* TODO */
>
> - ipc_send_rsp(HAL_SERVICE_ID_BLUETOOTH, HAL_OP_LE_TEST_MODE,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, HAL_OP_LE_TEST_MODE,
> HAL_STATUS_FAILED);
> }
>
> @@ -3272,11 +3284,13 @@ static const struct ipc_handler cmd_handlers[] = {
> { handle_le_test_mode_cmd, true, sizeof(struct hal_cmd_le_test_mode) },
> };
>
> -void bt_bluetooth_register(void)
> +void bt_bluetooth_register(struct ipc *ipc)
> {
> DBG("");
>
> - ipc_register(HAL_SERVICE_ID_BLUETOOTH, cmd_handlers,
> + hal_ipc = ipc;
> +
> + ipc_register(hal_ipc, HAL_SERVICE_ID_BLUETOOTH, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
> }
>
> @@ -3290,5 +3304,6 @@ void bt_bluetooth_unregister(void)
> g_slist_free_full(cached_devices, (GDestroyNotify) free_device);
> cached_devices = NULL;
>
> - ipc_unregister(HAL_SERVICE_ID_CORE);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_CORE);
> + hal_ipc = NULL;
> }
> diff --git a/android/bluetooth.h b/android/bluetooth.h
> index 8ab34f6..fbc850d 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(void);
> +void bt_bluetooth_register(struct ipc *ipc);
> 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 60bff91..ef8c776 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -38,11 +38,11 @@
> #include "src/uuid-helper.h"
> #include "src/shared/hfp.h"
> #include "btio/btio.h"
> +#include "hal-msg.h"
> +#include "ipc.h"
> #include "handsfree.h"
> #include "bluetooth.h"
> #include "src/log.h"
> -#include "hal-msg.h"
> -#include "ipc.h"
> #include "utils.h"
>
> #define HFP_AG_CHANNEL 13
> @@ -56,6 +56,7 @@ static struct {
>
> static bdaddr_t adapter_addr;
> static uint32_t record_id = 0;
> +static struct ipc *hal_ipc = NULL;
>
> static GIOChannel *server = NULL;
>
> @@ -75,8 +76,8 @@ static void device_set_state(uint8_t state)
> bdaddr2android(&device.bdaddr, ev.bdaddr);
> ev.state = state;
>
> - ipc_send_notif(HAL_SERVICE_ID_HANDSFREE, HAL_EV_HANDSFREE_CONN_STATE,
> - sizeof(ev), &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_EV_HANDSFREE_CONN_STATE, sizeof(ev), &ev);
> }
>
> static void device_init(const bdaddr_t *bdaddr)
> @@ -281,8 +282,8 @@ static void handle_connect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_CONNECT, status);
> }
>
> static void handle_disconnect(const void *buf, uint16_t len)
> @@ -317,23 +318,23 @@ static void handle_disconnect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_DISCONNECT,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_DISCONNECT, status);
> }
>
> static void handle_connect_audio(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT_AUDIO,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_CONNECT_AUDIO, HAL_STATUS_FAILED);
> }
>
> static void handle_disconnect_audio(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> HAL_OP_HANDSFREE_DISCONNECT_AUDIO, HAL_STATUS_FAILED);
> }
>
> @@ -341,31 +342,31 @@ static void handle_start_vr(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_START_VR,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_START_VR, HAL_STATUS_FAILED);
> }
>
> static void handle_stop_vr(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_STOP_VR,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_STOP_VR, HAL_STATUS_FAILED);
> }
>
> static void handle_volume_control(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_VOLUME_CONTROL,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_VOLUME_CONTROL, HAL_STATUS_FAILED);
> }
>
> static void handle_device_status_notif(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
> HAL_STATUS_FAILED);
> }
> @@ -374,23 +375,23 @@ static void handle_cops(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_COPS_RESPONSE,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_COPS_RESPONSE, HAL_STATUS_FAILED);
> }
>
> static void handle_cind(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CIND_RESPONSE,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_CIND_RESPONSE, HAL_STATUS_FAILED);
> }
>
> static void handle_formatted_at_resp(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE,
> HAL_STATUS_FAILED);
> }
> @@ -399,23 +400,23 @@ static void handle_at_resp(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_AT_RESPONSE,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_AT_RESPONSE, HAL_STATUS_FAILED);
> }
>
> static void handle_clcc_resp(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CLCC_RESPONSE,
> - HAL_STATUS_FAILED);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> + HAL_OP_HANDSFREE_CLCC_RESPONSE, HAL_STATUS_FAILED);
> }
>
> static void handle_phone_state_change(const void *buf, uint16_t len)
> {
> DBG("");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HANDSFREE,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
> HAL_STATUS_FAILED);
> }
> @@ -530,7 +531,7 @@ static sdp_record_t *handsfree_ag_record(void)
> return record;
> }
>
> -bool bt_handsfree_register(const bdaddr_t *addr)
> +bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> sdp_record_t *rec;
> GError *err = NULL;
> @@ -563,7 +564,8 @@ bool bt_handsfree_register(const bdaddr_t *addr)
> }
> record_id = rec->handle;
>
> - ipc_register(HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
> + hal_ipc = ipc;
> + ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
>
> return true;
> @@ -580,7 +582,8 @@ void bt_handsfree_unregister(void)
> {
> DBG("");
>
> - ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_HANDSFREE);
> + hal_ipc = NULL;
>
> if (server) {
> g_io_channel_shutdown(server, TRUE, NULL);
> diff --git a/android/handsfree.h b/android/handsfree.h
> index e3fdd70..3ede819 100644
> --- a/android/handsfree.h
> +++ b/android/handsfree.h
> @@ -21,5 +21,5 @@
> *
> */
>
> -bool bt_handsfree_register(const bdaddr_t *addr);
> +bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr);
> void bt_handsfree_unregister(void);
> diff --git a/android/hidhost.c b/android/hidhost.c
> index fd5ea4d..0c6eb7d 100644
> --- a/android/hidhost.c
> +++ b/android/hidhost.c
> @@ -81,6 +81,8 @@ static GIOChannel *ctrl_io = NULL;
> static GIOChannel *intr_io = NULL;
> static GSList *devices = NULL;
>
> +static struct ipc *hal_ipc = NULL;
> +
> struct hid_device {
> bdaddr_t dst;
> uint8_t state;
> @@ -303,8 +305,8 @@ static void bt_hid_notify_state(struct hid_device *dev, uint8_t state)
> bdaddr2android(&dev->dst, ev.bdaddr);
> ev.state = state;
>
> - ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_CONN_STATE,
> - sizeof(ev), &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_EV_HIDHOST_CONN_STATE, sizeof(ev), &ev);
> }
>
> static gboolean intr_watch_cb(GIOChannel *chan, GIOCondition cond,
> @@ -362,8 +364,8 @@ static void bt_hid_notify_proto_mode(struct hid_device *dev, uint8_t *buf,
> ev.mode = HAL_HIDHOST_UNSUPPORTED_PROTOCOL;
> }
>
> - ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_PROTO_MODE,
> - sizeof(ev), &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_EV_HIDHOST_PROTO_MODE, sizeof(ev), &ev);
> }
>
> static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
> @@ -405,8 +407,8 @@ static void bt_hid_notify_get_report(struct hid_device *dev, uint8_t *buf,
> }
>
> send:
> - ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_GET_REPORT,
> - ev_len, ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_EV_HIDHOST_GET_REPORT, ev_len, ev);
> g_free(ev);
> }
>
> @@ -430,9 +432,8 @@ static void bt_hid_notify_virtual_unplug(struct hid_device *dev,
> ev.status = HAL_HIDHOST_STATUS_OK;
> }
>
> - ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_VIRTUAL_UNPLUG,
> - sizeof(ev), &ev);
> -
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_EV_HIDHOST_VIRTUAL_UNPLUG, sizeof(ev), &ev);
> }
>
> static gboolean ctrl_io_watch_cb(GIOChannel *chan, gpointer data)
> @@ -515,8 +516,8 @@ static void bt_hid_set_info(struct hid_device *dev)
> memset(ev.descr, 0, sizeof(ev.descr));
> memcpy(ev.descr, dev->rd_data, ev.descr_len);
>
> - ipc_send_notif(HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_INFO, sizeof(ev),
> - &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_EV_HIDHOST_INFO,
> + sizeof(ev), &ev);
> }
>
> static int uhid_create(struct hid_device *dev)
> @@ -806,7 +807,8 @@ static void bt_hid_connect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT,
> + status);
> }
>
> static void bt_hid_disconnect(const void *buf, uint16_t len)
> @@ -841,7 +843,8 @@ static void bt_hid_disconnect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT,
> + status);
> }
>
> static void bt_hid_virtual_unplug(const void *buf, uint16_t len)
> @@ -894,8 +897,8 @@ static void bt_hid_virtual_unplug(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_VIRTUAL_UNPLUG,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_OP_HIDHOST_VIRTUAL_UNPLUG, status);
> }
>
> static void bt_hid_info(const void *buf, uint16_t len)
> @@ -914,7 +917,7 @@ static void bt_hid_info(const void *buf, uint16_t len)
> * once device is created with HID internals. */
> DBG("Not supported");
>
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
> HAL_STATUS_UNSUPPORTED);
> }
>
> @@ -964,8 +967,8 @@ static void bt_hid_get_protocol(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_PROTOCOL,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_OP_HIDHOST_GET_PROTOCOL, status);
> }
>
> static void bt_hid_set_protocol(const void *buf, uint16_t len)
> @@ -1014,8 +1017,8 @@ static void bt_hid_set_protocol(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_PROTOCOL,
> - status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST,
> + HAL_OP_HIDHOST_SET_PROTOCOL, status);
> }
>
> static void bt_hid_get_report(const void *buf, uint16_t len)
> @@ -1081,7 +1084,8 @@ static void bt_hid_get_report(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT,
> + status);
> }
>
> static void bt_hid_set_report(const void *buf, uint16_t len)
> @@ -1158,7 +1162,8 @@ static void bt_hid_set_report(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT,
> + status);
> }
>
> static void bt_hid_send_data(const void *buf, uint16_t len)
> @@ -1224,7 +1229,8 @@ static void bt_hid_send_data(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA,
> + status);
> }
>
> static const struct ipc_handler cmd_handlers[] = {
> @@ -1323,7 +1329,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
> }
> }
>
> -bool bt_hid_register(const bdaddr_t *addr)
> +bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> GError *err = NULL;
>
> @@ -1358,7 +1364,9 @@ bool bt_hid_register(const bdaddr_t *addr)
> return false;
> }
>
> - ipc_register(HAL_SERVICE_ID_HIDHOST, cmd_handlers,
> + hal_ipc = ipc;
> +
> + ipc_register(hal_ipc, HAL_SERVICE_ID_HIDHOST, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
>
> return true;
> @@ -1383,5 +1391,6 @@ void bt_hid_unregister(void)
> intr_io = NULL;
> }
>
> - ipc_unregister(HAL_SERVICE_ID_HIDHOST);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_HIDHOST);
> + hal_ipc = NULL;
> }
> diff --git a/android/hidhost.h b/android/hidhost.h
> index 5c3c801..1017195 100644
> --- a/android/hidhost.h
> +++ b/android/hidhost.h
> @@ -21,5 +21,5 @@
> *
> */
>
> -bool bt_hid_register(const bdaddr_t *addr);
> +bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr);
> void bt_hid_unregister(void);
> diff --git a/android/ipc.c b/android/ipc.c
> index 4a3a60d..3d6e2a3 100644
> --- a/android/ipc.c
> +++ b/android/ipc.c
> @@ -40,13 +40,19 @@
> #include "ipc.h"
> #include "src/log.h"
>
> -static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
> +struct ipc {
> + struct service_handler *services;
> + int service_max;
>
> -static GIOChannel *cmd_io = NULL;
> -static GIOChannel *notif_io = NULL;
> + const char *path;
> + size_t size;
>
> -static guint cmd_watch = 0;
> -static guint notif_watch = 0;
> + GIOChannel *cmd_io;
> + guint cmd_watch;
> +
> + GIOChannel *notif_io;
> + guint notif_watch;
> +};
>
> int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
> const void *buf, ssize_t len)
> @@ -103,6 +109,8 @@ int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
> static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
> gpointer user_data)
> {
> + struct ipc *ipc = user_data;
> +
> char buf[BLUEZ_HAL_MTU];
> ssize_t ret;
> int fd, err;
> @@ -121,7 +129,7 @@ static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
> goto fail;
> }
>
> - err = ipc_handle_msg(services, HAL_SERVICE_ID_MAX, buf, ret);
> + err = ipc_handle_msg(ipc->services, ipc->service_max, buf, ret);
> if (err < 0) {
> error("IPC: failed to handle message, terminating (%s)",
> strerror(-err));
> @@ -181,6 +189,8 @@ GIOChannel *ipc_connect(const char *path, size_t size, GIOFunc connect_cb,
> static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
> gpointer user_data)
> {
> + struct ipc *ipc = user_data;
> +
> DBG("");
>
> if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> @@ -191,11 +201,11 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
>
> cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
>
> - notif_watch = g_io_add_watch(io, cond, notif_watch_cb, NULL);
> + ipc->notif_watch = g_io_add_watch(io, cond, notif_watch_cb, ipc);
>
> cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
>
> - cmd_watch = g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
> + ipc->cmd_watch = g_io_add_watch(ipc->cmd_io, cond, cmd_watch_cb, ipc);
>
> info("IPC: successfully connected");
>
> @@ -205,6 +215,8 @@ static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
> static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
> gpointer user_data)
> {
> + struct ipc *ipc = user_data;
> +
> DBG("");
>
> if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> @@ -213,45 +225,62 @@ static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
> return FALSE;
> }
>
> - notif_io = ipc_connect(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> - notif_connect_cb, NULL);
> - if (!notif_io)
> + ipc->notif_io = ipc_connect(ipc->path, ipc->size, notif_connect_cb,
> + ipc);
> + if (!ipc->notif_io)
> raise(SIGTERM);
>
> return FALSE;
> }
>
> -void ipc_init(void)
> +struct ipc *ipc_init(const char *path, size_t size, int max_service_id)
> {
> - cmd_io = ipc_connect(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> - cmd_connect_cb, NULL);
> - if (!cmd_io)
> - raise(SIGTERM);
> + struct ipc *ipc;
> +
> + ipc = g_new0(struct ipc, 1);
> +
> + ipc->services = g_new0(struct service_handler, max_service_id + 1);
> + ipc->service_max = max_service_id;
> +
> + ipc->path = path;
> + ipc->size = size;
> +
> + ipc->cmd_io = ipc_connect(path, size, cmd_connect_cb, ipc);
> + if (!ipc->cmd_io) {
> + g_free(ipc->services);
> + g_free(ipc);
> + return NULL;
> + }
> +
> + return ipc;
> }
>
> -void ipc_cleanup(void)
> +void ipc_cleanup(struct ipc *ipc)
> {
> - if (cmd_watch) {
> - g_source_remove(cmd_watch);
> - cmd_watch = 0;
> + if (ipc->cmd_watch) {
> + g_source_remove(ipc->cmd_watch);
> + ipc->cmd_watch = 0;
> }
>
> - if (cmd_io) {
> - g_io_channel_shutdown(cmd_io, TRUE, NULL);
> - g_io_channel_unref(cmd_io);
> - cmd_io = NULL;
> + if (ipc->cmd_io) {
> + g_io_channel_shutdown(ipc->cmd_io, TRUE, NULL);
> + g_io_channel_unref(ipc->cmd_io);
> + ipc->cmd_io = NULL;
> }
>
> - if (notif_watch) {
> - g_source_remove(notif_watch);
> - notif_watch = 0;
> + if (ipc->notif_watch) {
> + g_source_remove(ipc->notif_watch);
> + ipc->notif_watch = 0;
> }
>
> - if (notif_io) {
> - g_io_channel_shutdown(notif_io, TRUE, NULL);
> - g_io_channel_unref(notif_io);
> - notif_io = NULL;
> + if (ipc->notif_io) {
> + g_io_channel_shutdown(ipc->notif_io, TRUE, NULL);
> + g_io_channel_unref(ipc->notif_io);
> + ipc->notif_io = NULL;
> }
> +
> + g_free(ipc->services);
> + g_free(ipc);
> }
>
> void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
> @@ -299,12 +328,13 @@ void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
> }
> }
>
> -void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status)
> +void ipc_send_rsp(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
> + uint8_t status)
> {
> struct hal_status s;
> int sk;
>
> - sk = g_io_channel_unix_get_fd(cmd_io);
> + sk = g_io_channel_unix_get_fd(ipc->cmd_io);
>
> if (status == HAL_STATUS_SUCCESS) {
> ipc_send(sk, service_id, opcode, 0, NULL, -1);
> @@ -316,32 +346,38 @@ void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status)
> ipc_send(sk, service_id, HAL_OP_STATUS, sizeof(s), &s, -1);
> }
>
> -void ipc_send_rsp_full(uint8_t service_id, uint8_t opcode, uint16_t len,
> - void *param, int fd)
> +void ipc_send_rsp_full(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
> + uint16_t len, void *param, int fd)
> {
> - ipc_send(g_io_channel_unix_get_fd(cmd_io), service_id, opcode, len,
> + ipc_send(g_io_channel_unix_get_fd(ipc->cmd_io), service_id, opcode, len,
> param, fd);
> }
>
> -void ipc_send_notif(uint8_t service_id, uint8_t opcode, uint16_t len,
> - void *param)
> +void ipc_send_notif(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
> + uint16_t len, void *param)
> {
> - if (!notif_io)
> + if (!ipc || !ipc->notif_io)
> return;
>
> - ipc_send(g_io_channel_unix_get_fd(notif_io), service_id, opcode, len,
> - param, -1);
> + ipc_send(g_io_channel_unix_get_fd(ipc->notif_io), service_id, opcode,
> + len, param, -1);
> }
>
> -void ipc_register(uint8_t service, const struct ipc_handler *handlers,
> - uint8_t size)
> +void ipc_register(struct ipc *ipc, uint8_t service,
> + const struct ipc_handler *handlers, uint8_t size)
> {
> - services[service].handler = handlers;
> - services[service].size = size;
> + if (service > ipc->service_max)
> + return;
> +
> + ipc->services[service].handler = handlers;
> + ipc->services[service].size = size;
> }
>
> -void ipc_unregister(uint8_t service)
> +void ipc_unregister(struct ipc *ipc, uint8_t service)
> {
> - services[service].handler = NULL;
> - services[service].size = 0;
> + if (service > ipc->service_max)
> + return;
> +
> + ipc->services[service].handler = NULL;
> + ipc->services[service].size = 0;
> }
> diff --git a/android/ipc.h b/android/ipc.h
> index cfa4018..601301c 100644
> --- a/android/ipc.h
> +++ b/android/ipc.h
> @@ -32,20 +32,24 @@ struct service_handler {
> uint8_t size;
> };
>
> -void ipc_init(void);
> -void ipc_cleanup(void);
> +struct ipc;
> +
> +struct ipc *ipc_init(const char *path, size_t size, int max_service_id);
> +void ipc_cleanup(struct ipc *ipc);
> +
> GIOChannel *ipc_connect(const char *path, size_t size, GIOFunc connect_cb,
> void *user_data);
> int ipc_handle_msg(struct service_handler *handlers, size_t max_index,
> const void *buf, ssize_t len);
>
> -void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status);
> -void ipc_send_rsp_full(uint8_t service_id, uint8_t opcode, uint16_t len,
> - void *param, int fd);
> -void ipc_send_notif(uint8_t service_id, uint8_t opcode, uint16_t len,
> - void *param);
> +void ipc_send_rsp(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
> + uint8_t status);
> +void ipc_send_rsp_full(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
> + uint16_t len, void *param, int fd);
> +void ipc_send_notif(struct ipc *ipc, uint8_t service_id, uint8_t opcode,
> + uint16_t len, void *param);
> void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
> void *param, int fd);
> -void ipc_register(uint8_t service, const struct ipc_handler *handlers,
> - uint8_t size);
> -void ipc_unregister(uint8_t service);
> +void ipc_register(struct ipc *ipc, uint8_t service,
> + const struct ipc_handler *handlers, uint8_t size);
> +void ipc_unregister(struct ipc *ipc, uint8_t service);
> diff --git a/android/main.c b/android/main.c
> index aca6351..9f22486 100644
> --- a/android/main.c
> +++ b/android/main.c
> @@ -48,11 +48,11 @@
>
> #include "lib/bluetooth.h"
>
> +#include "ipc.h"
> #include "bluetooth.h"
> #include "socket.h"
> #include "hidhost.h"
> #include "hal-msg.h"
> -#include "ipc.h"
> #include "a2dp.h"
> #include "pan.h"
> #include "avrcp.h"
> @@ -67,6 +67,8 @@ static bdaddr_t adapter_bdaddr;
>
> static GMainLoop *event_loop;
>
> +static struct ipc *hal_ipc = NULL;
> +
> static bool services[HAL_SERVICE_ID_MAX + 1] = { false };
>
> static void service_register(const void *buf, uint16_t len)
> @@ -81,43 +83,43 @@ static void service_register(const void *buf, uint16_t len)
>
> switch (m->service_id) {
> case HAL_SERVICE_ID_BLUETOOTH:
> - bt_bluetooth_register();
> + bt_bluetooth_register(hal_ipc);
>
> break;
> case HAL_SERVICE_ID_SOCKET:
> - bt_socket_register(&adapter_bdaddr);
> + bt_socket_register(hal_ipc, &adapter_bdaddr);
>
> break;
> case HAL_SERVICE_ID_HIDHOST:
> - if (!bt_hid_register(&adapter_bdaddr)) {
> + if (!bt_hid_register(hal_ipc, &adapter_bdaddr)) {
> status = HAL_STATUS_FAILED;
> goto failed;
> }
>
> break;
> case HAL_SERVICE_ID_A2DP:
> - if (!bt_a2dp_register(&adapter_bdaddr)) {
> + if (!bt_a2dp_register(hal_ipc, &adapter_bdaddr)) {
> status = HAL_STATUS_FAILED;
> goto failed;
> }
>
> break;
> case HAL_SERVICE_ID_PAN:
> - if (!bt_pan_register(&adapter_bdaddr)) {
> + if (!bt_pan_register(hal_ipc, &adapter_bdaddr)) {
> status = HAL_STATUS_FAILED;
> goto failed;
> }
>
> break;
> case HAL_SERVICE_ID_AVRCP:
> - if (!bt_avrcp_register(&adapter_bdaddr)) {
> + if (!bt_avrcp_register(hal_ipc, &adapter_bdaddr)) {
> status = HAL_STATUS_FAILED;
> goto failed;
> }
>
> break;
> case HAL_SERVICE_ID_HANDSFREE:
> - if (!bt_handsfree_register(&adapter_bdaddr)) {
> + if (!bt_handsfree_register(hal_ipc, &adapter_bdaddr)) {
> status = HAL_STATUS_FAILED;
> goto failed;
> }
> @@ -136,7 +138,8 @@ static void service_register(const void *buf, uint16_t len)
> info("Service ID=%u registered", m->service_id);
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
> + status);
> }
>
> static void service_unregister(const void *buf, uint16_t len)
> @@ -186,7 +189,8 @@ static void service_unregister(const void *buf, uint16_t len)
> info("Service ID=%u unregistered", m->service_id);
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
> + status);
> }
>
> static const struct ipc_handler cmd_handlers[] = {
> @@ -240,7 +244,15 @@ static void adapter_ready(int err, const bdaddr_t *addr)
>
> info("Adapter initialized");
>
> - ipc_init();
> + hal_ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + HAL_SERVICE_ID_MAX);
> + if (!hal_ipc) {
> + error("Failed to initialize IPC");
> + exit(EXIT_FAILURE);
> + }
> +
> + ipc_register(hal_ipc, HAL_SERVICE_ID_CORE, cmd_handlers,
> + G_N_ELEMENTS(cmd_handlers));
> }
>
> static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
> @@ -464,9 +476,6 @@ int main(int argc, char *argv[])
> /* Use params: mtu = 0, flags = 0 */
> start_sdp_server(0, 0);
>
> - ipc_register(HAL_SERVICE_ID_CORE, cmd_handlers,
> - G_N_ELEMENTS(cmd_handlers));
> -
> DBG("Entering main loop");
>
> event_loop = g_main_loop_new(NULL, FALSE);
> @@ -480,12 +489,12 @@ int main(int argc, char *argv[])
>
> cleanup_services();
>
> - ipc_cleanup();
> stop_sdp_server();
> bt_bluetooth_cleanup();
> g_main_loop_unref(event_loop);
>
> - ipc_unregister(HAL_SERVICE_ID_CORE);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_CORE);
> + ipc_cleanup(hal_ipc);
>
> info("Exit");
>
> diff --git a/android/pan.c b/android/pan.c
> index cfc03bc..b4a3494 100644
> --- a/android/pan.c
> +++ b/android/pan.c
> @@ -49,11 +49,11 @@
> #include "profiles/network/bnep.h"
> #include "src/log.h"
>
> -#include "pan.h"
> #include "hal-msg.h"
> #include "ipc.h"
> #include "utils.h"
> #include "bluetooth.h"
> +#include "pan.h"
>
> #define SVC_HINT_NETWORKING 0x02
>
> @@ -64,6 +64,7 @@
> static bdaddr_t adapter_addr;
> GSList *devices = NULL;
> uint8_t local_role = HAL_PAN_ROLE_NONE;
> +static struct ipc *hal_ipc = NULL;
>
> struct pan_device {
> char iface[16];
> @@ -247,8 +248,8 @@ static void bt_pan_notify_conn_state(struct pan_device *dev, uint8_t state)
> ev.remote_role = dev->role;
> ev.status = HAL_STATUS_SUCCESS;
>
> - ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE, sizeof(ev),
> - &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CONN_STATE,
> + sizeof(ev), &ev);
> if (dev->conn_state == HAL_PAN_STATE_DISCONNECTED)
> pan_device_remove(dev);
> }
> @@ -270,8 +271,8 @@ static void bt_pan_notify_ctrl_state(struct pan_device *dev, uint8_t state)
> else
> memcpy(ev.name, dev->iface, sizeof(dev->iface));
>
> - ipc_send_notif(HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE, sizeof(ev),
> - &ev);
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_PAN, HAL_EV_PAN_CTRL_STATE,
> + sizeof(ev), &ev);
> }
>
> static void bnep_disconn_cb(void *data)
> @@ -414,7 +415,7 @@ static void bt_pan_connect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, status);
> }
>
> static void bt_pan_disconnect(const void *buf, uint16_t len)
> @@ -444,7 +445,8 @@ static void bt_pan_disconnect(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT,
> + status);
> }
>
> static gboolean nap_watchdog_cb(GIOChannel *chan, GIOCondition cond,
> @@ -676,7 +678,7 @@ static void bt_pan_enable(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
>
> reply:
> - ipc_send_rsp(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE, status);
> }
>
> static void bt_pan_get_role(const void *buf, uint16_t len)
> @@ -686,8 +688,8 @@ static void bt_pan_get_role(const void *buf, uint16_t len)
> DBG("");
>
> rsp.local_role = local_role;
> - ipc_send_rsp_full(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, sizeof(rsp),
> - &rsp, -1);
> + ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE,
> + sizeof(rsp), &rsp, -1);
> }
>
> static const struct ipc_handler cmd_handlers[] = {
> @@ -776,7 +778,7 @@ static sdp_record_t *pan_record(void)
> return record;
> }
>
> -bool bt_pan_register(const bdaddr_t *addr)
> +bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> sdp_record_t *rec;
> int err;
> @@ -813,7 +815,9 @@ bool bt_pan_register(const bdaddr_t *addr)
> }
>
> nap_dev.record_id = rec->handle;
> - ipc_register(HAL_SERVICE_ID_PAN, cmd_handlers,
> +
> + hal_ipc = ipc;
> + ipc_register(hal_ipc, HAL_SERVICE_ID_PAN, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
>
> return true;
> @@ -829,7 +833,9 @@ void bt_pan_unregister(void)
>
> bnep_cleanup();
>
> - ipc_unregister(HAL_SERVICE_ID_PAN);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_PAN);
> + hal_ipc = NULL;
> +
> bt_adapter_remove_record(nap_dev.record_id);
> nap_dev.record_id = 0;
> destroy_nap_device();
> diff --git a/android/pan.h b/android/pan.h
> index 72a7eab..2045ac5 100644
> --- a/android/pan.h
> +++ b/android/pan.h
> @@ -21,5 +21,5 @@
> *
> */
>
> -bool bt_pan_register(const bdaddr_t *addr);
> +bool bt_pan_register(struct ipc *ipc, const bdaddr_t *addr);
> void bt_pan_unregister(void);
> diff --git a/android/socket.c b/android/socket.c
> index 655ee40..d463255 100644
> --- a/android/socket.c
> +++ b/android/socket.c
> @@ -38,11 +38,11 @@
> #include "src/sdpd.h"
> #include "src/log.h"
>
> -#include "bluetooth.h"
> #include "hal-msg.h"
> #include "hal-ipc.h"
> #include "ipc.h"
> #include "utils.h"
> +#include "bluetooth.h"
> #include "socket.h"
>
> #define RFCOMM_CHANNEL_MAX 30
> @@ -60,6 +60,7 @@
> #define MAP_MSG_TYPE_SMS_CDMA 0x04
> #define DEFAULT_MAS_MSG_TYPE (MAP_MSG_TYPE_SMS_GSM | MAP_MSG_TYPE_SMS_CDMA)
>
> +static struct ipc *hal_ipc = NULL;
> struct rfcomm_sock {
> int channel; /* RFCOMM channel */
> BtIOSecLevel sec_level;
> @@ -862,13 +863,14 @@ static void handle_listen(const void *buf, uint16_t len)
> if (status != HAL_STATUS_SUCCESS)
> goto failed;
>
> - ipc_send_rsp_full(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN, 0, NULL,
> - hal_sock);
> + ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN,
> + 0, NULL, hal_sock);
> close(hal_sock);
> return ;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_LISTEN,
> + status);
> }
>
> static bool sock_send_connect(struct rfcomm_sock *rfsock, bdaddr_t *bdaddr)
> @@ -1106,13 +1108,14 @@ static void handle_connect(const void *buf, uint16_t len)
> if (status != HAL_STATUS_SUCCESS)
> goto failed;
>
> - ipc_send_rsp_full(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT, 0,
> - NULL, hal_sock);
> + ipc_send_rsp_full(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT,
> + 0, NULL, hal_sock);
> close(hal_sock);
> return;
>
> failed:
> - ipc_send_rsp(HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT, status);
> + ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_SOCKET, HAL_OP_SOCKET_CONNECT,
> + status);
>
> }
>
> @@ -1123,7 +1126,7 @@ static const struct ipc_handler cmd_handlers[] = {
> { handle_connect, false, sizeof(struct hal_cmd_socket_connect) },
> };
>
> -void bt_socket_register(const bdaddr_t *addr)
> +void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> size_t i;
>
> @@ -1137,7 +1140,9 @@ void bt_socket_register(const bdaddr_t *addr)
> servers[profiles[i].channel].reserved = true;
>
> bacpy(&adapter_addr, addr);
> - ipc_register(HAL_SERVICE_ID_SOCKET, cmd_handlers,
> +
> + hal_ipc = ipc;
> + ipc_register(hal_ipc, HAL_SERVICE_ID_SOCKET, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
> }
>
> @@ -1155,5 +1160,6 @@ void bt_socket_unregister(void)
>
> memset(servers, 0, sizeof(servers));
>
> - ipc_unregister(HAL_SERVICE_ID_SOCKET);
> + ipc_unregister(hal_ipc, HAL_SERVICE_ID_SOCKET);
> + hal_ipc = NULL;
> }
> diff --git a/android/socket.h b/android/socket.h
> index d41616f..d3ed9b4 100644
> --- a/android/socket.h
> +++ b/android/socket.h
> @@ -30,5 +30,5 @@ struct hal_sock_connect_signal {
>
> void bt_sock_handle_cmd(int sk, uint8_t opcode, void *buf, uint16_t len);
>
> -void bt_socket_register(const bdaddr_t *addr);
> +void bt_socket_register(struct ipc *ipc, const bdaddr_t *addr);
> void bt_socket_unregister(void);
> diff --git a/android/test-ipc.c b/android/test-ipc.c
> index 8dd53a1..054af84 100644
> --- a/android/test-ipc.c
> +++ b/android/test-ipc.c
> @@ -43,6 +43,8 @@
> #include "android/hal-msg.h"
> #include "android/ipc.h"
>
> +static struct ipc *ipc = NULL;
> +
> struct test_data {
> uint32_t expected_signal;
> const void *cmd;
> @@ -283,11 +285,15 @@ static void test_init(gconstpointer data)
> {
> struct context *context = create_context(data);
>
> - ipc_init();
> + ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + HAL_SERVICE_ID_MAX);
> +
> + g_assert(ipc);
>
> execute_context(context);
>
> - ipc_cleanup();
> + ipc_cleanup(ipc);
> + ipc = NULL;
> }
>
> static gboolean send_cmd(gpointer user_data)
> @@ -310,7 +316,7 @@ static gboolean register_service(gpointer user_data)
> struct context *context = user_data;
> const struct test_data *test_data = context->data;
>
> - ipc_register(test_data->service, test_data->handlers,
> + ipc_register(ipc, test_data->service, test_data->handlers,
> test_data->handlers_size);
>
> return FALSE;
> @@ -321,7 +327,7 @@ static gboolean unregister_service(gpointer user_data)
> struct context *context = user_data;
> const struct test_data *test_data = context->data;
>
> - ipc_unregister(test_data->service);
> + ipc_unregister(ipc, test_data->service);
>
> return FALSE;
> }
> @@ -330,13 +336,17 @@ static void test_cmd(gconstpointer data)
> {
> struct context *context = create_context(data);
>
> - ipc_init();
> + ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + HAL_SERVICE_ID_MAX);
> +
> + g_assert(ipc);
>
> g_idle_add(send_cmd, context);
>
> execute_context(context);
>
> - ipc_cleanup();
> + ipc_cleanup(ipc);
> + ipc = NULL;
> }
>
> static void test_cmd_reg(gconstpointer data)
> @@ -344,23 +354,30 @@ static void test_cmd_reg(gconstpointer data)
> struct context *context = create_context(data);
> const struct test_data *test_data = context->data;
>
> - ipc_init();
> + ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + HAL_SERVICE_ID_MAX);
> +
> + g_assert(ipc);
>
> g_idle_add(register_service, context);
> g_idle_add(send_cmd, context);
>
> execute_context(context);
>
> - ipc_unregister(test_data->service);
> + ipc_unregister(ipc, test_data->service);
>
> - ipc_cleanup();
> + ipc_cleanup(ipc);
> + ipc = NULL;
> }
>
> static void test_cmd_reg_1(gconstpointer data)
> {
> struct context *context = create_context(data);
>
> - ipc_init();
> + ipc = ipc_init(BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH),
> + HAL_SERVICE_ID_MAX);
> +
> + g_assert(ipc);
>
> g_idle_add(register_service, context);
> g_idle_add(unregister_service, context);
> @@ -368,17 +385,18 @@ static void test_cmd_reg_1(gconstpointer data)
>
> execute_context(context);
>
> - ipc_cleanup();
> + ipc_cleanup(ipc);
> + ipc = NULL;
> }
>
> static void test_cmd_handler_1(const void *buf, uint16_t len)
> {
> - ipc_send_rsp(0, 1, 0);
> + ipc_send_rsp(ipc, 0, 1, 0);
> }
>
> static void test_cmd_handler_2(const void *buf, uint16_t len)
> {
> - ipc_send_rsp(0, 2, 0);
> + ipc_send_rsp(ipc, 0, 2, 0);
> }
>
> static void test_cmd_handler_invalid(const void *buf, uint16_t len)
>
All patches are now upstream.
--
Best regards,
Szymon Janc
^ permalink raw reply
* [PATCH 1/2] Bluetooth: Re-encrypt link after receiving an LTK
From: johan.hedberg @ 2014-02-28 14:37 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
It's not strictly speaking required to re-encrypt a link once we receive
an LTK since the connection is already encrypted with the STK. However,
re-encrypting with the LTK allows us to verify that we've received an
LTK that actually works.
This patch updates the SMP code to request encrypting with the LTK in
case we're in master role and waits until the key refresh complete event
before notifying user space of the distributed keys.
A new flag is also added for the SMP context to ensure that we
re-encryption only once in case of multiple calls to smp_distribute_keys.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 27 ++++++++++++++++++++++-----
net/bluetooth/smp.h | 3 ++-
2 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 4f4ff36f5f34..79b6c97f8303 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -1178,6 +1178,7 @@ int smp_distribute_keys(struct l2cap_conn *conn)
struct smp_chan *smp = conn->smp_chan;
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
+ bool ltk_encrypt;
__u8 *keydist;
BT_DBG("conn %p", conn);
@@ -1269,12 +1270,28 @@ int smp_distribute_keys(struct l2cap_conn *conn)
if ((smp->remote_key_dist & 0x07))
return 0;
- clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
- cancel_delayed_work_sync(&conn->security_timer);
- set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
- smp_notify_keys(conn);
+ /* Check if we should try to re-encrypt the link with the LTK.
+ * SMP_FLAG_LTK_ENCRYPT flag is used to track whether we've
+ * already tried this (in which case we shouldn't try again).
+ */
+ if (smp->ltk)
+ ltk_encrypt = !test_and_set_bit(SMP_FLAG_LTK_ENCRYPT,
+ &smp->smp_flags);
+ else
+ ltk_encrypt = false;
- smp_chan_destroy(conn);
+ /* Re-encrypt the link with LTK if possible */
+ if (ltk_encrypt && hcon->out) {
+ struct smp_ltk *ltk = smp->ltk;
+ hci_le_start_enc(hcon, ltk->ediv, ltk->rand, ltk->val);
+ hcon->enc_key_size = ltk->enc_size;
+ } else {
+ clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
+ cancel_delayed_work_sync(&conn->security_timer);
+ set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
+ smp_notify_keys(conn);
+ smp_chan_destroy(conn);
+ }
return 0;
}
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index a11d4281542c..676395f93702 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -118,7 +118,8 @@ struct smp_cmd_security_req {
#define SMP_FLAG_TK_VALID 1
#define SMP_FLAG_CFM_PENDING 2
#define SMP_FLAG_MITM_AUTH 3
-#define SMP_FLAG_COMPLETE 4
+#define SMP_FLAG_LTK_ENCRYPT 4
+#define SMP_FLAG_COMPLETE 5
struct smp_chan {
struct l2cap_conn *conn;
--
1.8.5.3
^ permalink raw reply related
* [PATCH 2/2] Bluetooth: Delay LTK encryption to let remote receive all keys
From: johan.hedberg @ 2014-02-28 14:37 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1393598254-9609-1-git-send-email-johan.hedberg@gmail.com>
From: Johan Hedberg <johan.hedberg@intel.com>
Some devices may refuse to re-encrypt with the LTK if they haven't
received all our keys yet. This patch adds a 200ms delay before
attempting re-encryption with the LTK.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
net/bluetooth/smp.c | 22 +++++++++++++++++++---
net/bluetooth/smp.h | 3 +++
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 79b6c97f8303..cba0e0ddf332 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -549,6 +549,20 @@ error:
smp_failure(conn, reason);
}
+static void smp_reencrypt(struct work_struct *work)
+{
+ struct smp_chan *smp = container_of(work, struct smp_chan,
+ reencrypt.work);
+ struct l2cap_conn *conn = smp->conn;
+ struct hci_conn *hcon = conn->hcon;
+ struct smp_ltk *ltk = smp->ltk;
+
+ BT_DBG("");
+
+ hci_le_start_enc(hcon, ltk->ediv, ltk->rand, ltk->val);
+ hcon->enc_key_size = ltk->enc_size;
+}
+
static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
{
struct smp_chan *smp;
@@ -559,6 +573,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn)
INIT_WORK(&smp->confirm, confirm_work);
INIT_WORK(&smp->random, random_work);
+ INIT_DELAYED_WORK(&smp->reencrypt, smp_reencrypt);
smp->conn = conn;
conn->smp_chan = smp;
@@ -576,6 +591,8 @@ void smp_chan_destroy(struct l2cap_conn *conn)
BUG_ON(!smp);
+ cancel_delayed_work_sync(&smp->reencrypt);
+
complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags);
mgmt_smp_complete(conn->hcon, complete);
@@ -1282,9 +1299,8 @@ int smp_distribute_keys(struct l2cap_conn *conn)
/* Re-encrypt the link with LTK if possible */
if (ltk_encrypt && hcon->out) {
- struct smp_ltk *ltk = smp->ltk;
- hci_le_start_enc(hcon, ltk->ediv, ltk->rand, ltk->val);
- hcon->enc_key_size = ltk->enc_size;
+ queue_delayed_work(hdev->req_workqueue, &smp->reencrypt,
+ SMP_REENCRYPT_TIMEOUT);
} else {
clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags);
cancel_delayed_work_sync(&conn->security_timer);
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 676395f93702..f95bf887a9f3 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -121,6 +121,8 @@ struct smp_cmd_security_req {
#define SMP_FLAG_LTK_ENCRYPT 4
#define SMP_FLAG_COMPLETE 5
+#define SMP_REENCRYPT_TIMEOUT msecs_to_jiffies(200)
+
struct smp_chan {
struct l2cap_conn *conn;
u8 preq[7]; /* SMP Pairing Request */
@@ -140,6 +142,7 @@ struct smp_chan {
unsigned long smp_flags;
struct work_struct confirm;
struct work_struct random;
+ struct delayed_work reencrypt;
};
/* SMP Commands */
--
1.8.5.3
^ permalink raw reply related
* Receiving data in BLE non-connectable undirected advertisements
From: Benjamin Adler @ 2014-02-28 15:00 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org
Hello bluez,
as the subject notes, I'm trying to receive non-connectable undirected
advertisements from a bluetooth low energy device, namely TI's
SensorTag. Their SDK contains a sample app named SimpleBLEBroadcaster,
that, supposedly, sends those advertisements including some data. There
is an overview of TI's understanding of this mechanism for download at
http://e2e.ti.com/support/low_power_rf/m/videos__files/653593/download.aspx
Is it possible to receive/display the *data* (up to 31 bytes, I believe)
that can be contained in those advertisements using bluez? I currently
don't care whether it's a commandline tool, C-based API, python, DBUS,
anything.
When I start SimpleBLEBroadcaster, btmon alone doesn't show anything,
but "hcitool lescan" says.
LE Scan ...
90:59:AF:0B:8A:7D (unknown)
The complete output of a btmon during lescan is attached below.
https://github.com/bmpm/bcast-observer-demos and a script named
"test-bluetooth-observer" made me believe that there should be an
org.bluez.Observer interface for this, which I couldn't find using
qdbusviewer.
I asked on #bluez before, but it seems noone knew.
Thanks!
ben
###################################################################
####### start "btmon"
Bluetooth monitor ver 5.14
= New Index: 00:02:72:33:29:55 (BR/EDR,USB,hci0) [hci0] 0.377191
####### start "hcitool lescan" in another shell
< HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 [hci0] 4.457403
Type: Active (0x01)
Interval: 10.000 msec (0x0010)
Window: 10.000 msec (0x0010)
Own address type: Public (0x00)
Filter policy: Accept all advertisement (0x00)
> HCI Event: Command Complete (0x0e) plen 4 [hci0]
4.458949
LE Set Scan Parameters (0x08|0x000b) ncmd 1
Status: Success (0x00)
< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 4.459094
Scanning: Enabled (0x01)
Filter duplicates: Enabled (0x01)
> HCI Event: Command Complete (0x0e) plen 4 [hci0]
4.459957
LE Set Scan Enable (0x08|0x000c) ncmd 1
Status: Success (0x00)
####### Power-on the SensorTag
> HCI Event: LE Meta Event (0x3e) plen 20 [hci0]
9.481376
LE Advertising Report (0x02)
Num reports: 1
Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
Address type: Public (0x00)
Address: 90:59:AF:0B:8A:7D (Texas Instruments)
Data length: 8
Flags: 0x04
BR/EDR Not Supported
Company: not assigned (513)
Data: 03
RSSI: -80 dBm (0xb0)
####### Quit hcitool
< HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 20.647504
Scanning: Disabled (0x00)
Filter duplicates: Enabled (0x01)
> HCI Event: Command Complete (0x0e) plen 4 [hci0]
20.650124
LE Set Scan Enable (0x08|0x000c) ncmd 1
Status: Success (0x00)
#
^ permalink raw reply
* Re: Receiving data in BLE non-connectable undirected advertisements
From: Adam Warski @ 2014-02-28 15:13 UTC (permalink / raw)
To: Benjamin Adler; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <5310A4A9.2000907@gmx.net>
If you want to see the raw advertisement packets, run:
1st terminal: hcidump -R
2nd terminal: hcitool lescan
The raw dump will contain the advertisement data.
Adam
On 28 Feb 2014, at 16:00, Benjamin Adler <benadler@gmx.net> wrote:
> Hello bluez,
>
> as the subject notes, I'm trying to receive non-connectable undirected advertisements from a bluetooth low energy device, namely TI's SensorTag. Their SDK contains a sample app named SimpleBLEBroadcaster, that, supposedly, sends those advertisements including some data. There is an overview of TI's understanding of this mechanism for download at
>
> http://e2e.ti.com/support/low_power_rf/m/videos__files/653593/download.aspx
>
> Is it possible to receive/display the *data* (up to 31 bytes, I believe) that can be contained in those advertisements using bluez? I currently don't care whether it's a commandline tool, C-based API, python, DBUS, anything.
>
> When I start SimpleBLEBroadcaster, btmon alone doesn't show anything, but "hcitool lescan" says.
>
> LE Scan ...
> 90:59:AF:0B:8A:7D (unknown)
>
> The complete output of a btmon during lescan is attached below.
>
> https://github.com/bmpm/bcast-observer-demos and a script named "test-bluetooth-observer" made me believe that there should be an org.bluez.Observer interface for this, which I couldn't find using qdbusviewer.
>
> I asked on #bluez before, but it seems noone knew.
>
> Thanks!
> ben
>
> ###################################################################
>
> ####### start "btmon"
>
> Bluetooth monitor ver 5.14
> = New Index: 00:02:72:33:29:55 (BR/EDR,USB,hci0) [hci0] 0.377191
>
> ####### start "hcitool lescan" in another shell
>
> < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 [hci0] 4.457403
> Type: Active (0x01)
> Interval: 10.000 msec (0x0010)
> Window: 10.000 msec (0x0010)
> Own address type: Public (0x00)
> Filter policy: Accept all advertisement (0x00)
> > HCI Event: Command Complete (0x0e) plen 4 [hci0] 4.458949
> LE Set Scan Parameters (0x08|0x000b) ncmd 1
> Status: Success (0x00)
> < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 4.459094
> Scanning: Enabled (0x01)
> Filter duplicates: Enabled (0x01)
> > HCI Event: Command Complete (0x0e) plen 4 [hci0] 4.459957
> LE Set Scan Enable (0x08|0x000c) ncmd 1
> Status: Success (0x00)
>
> ####### Power-on the SensorTag
>
> > HCI Event: LE Meta Event (0x3e) plen 20 [hci0] 9.481376
> LE Advertising Report (0x02)
> Num reports: 1
> Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
> Address type: Public (0x00)
> Address: 90:59:AF:0B:8A:7D (Texas Instruments)
> Data length: 8
> Flags: 0x04
> BR/EDR Not Supported
> Company: not assigned (513)
> Data: 03
> RSSI: -80 dBm (0xb0)
>
> ####### Quit hcitool
>
> < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 20.647504
> Scanning: Disabled (0x00)
> Filter duplicates: Enabled (0x01)
> > HCI Event: Command Complete (0x0e) plen 4 [hci0] 20.650124
> LE Set Scan Enable (0x08|0x000c) ncmd 1
> Status: Success (0x00)
>
> #
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Adam Warski
http://twitter.com/#!/adamwarski
http://www.softwaremill.com
http://www.warski.org
^ permalink raw reply
* [PATCH] Bluetooth: Add timeout for LE connection attempts
From: johan.hedberg @ 2014-02-28 15:28 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
LE connection attempts do not have a controller side timeout in the same
way as BR/EDR has (in form of the page timeout). Since we always do
scanning before initiating connections the attempts are always expected
to succeed in some reasonable time.
This patch adds a timer which forces a cancellation of the connection
attempt within 20 seconds if it has not been successful by then. This
way we e.g. ensure that mgmt_pair_device times out eventually and gives
an error response.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 1 +
net/bluetooth/hci_conn.c | 20 ++++++++++++++++++++
net/bluetooth/hci_event.c | 2 ++
4 files changed, 24 insertions(+)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0740fee39c73..086d3f83faee 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -183,6 +183,7 @@ enum {
#define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */
+#define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
/* HCI data types */
#define HCI_COMMAND_PKT 0x01
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index edf194679b7d..dbb788e4f265 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -375,6 +375,7 @@ struct hci_conn {
struct delayed_work disc_work;
struct delayed_work auto_accept_work;
struct delayed_work idle_work;
+ struct delayed_work le_conn_timeout;
struct device dev;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 818330c1b2a2..3e3d4a4260c5 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work)
&conn->dst);
}
+static void le_conn_timeout(struct work_struct *work)
+{
+ struct hci_conn *conn = container_of(work, struct hci_conn,
+ le_conn_timeout.work);
+
+ BT_DBG("");
+
+ hci_le_create_connection_cancel(conn);
+}
+
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
{
struct hci_conn *conn;
@@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle);
+ INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);
atomic_set(&conn->refcnt, 0);
@@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn)
/* Unacked frames */
hdev->acl_cnt += conn->sent;
} else if (conn->type == LE_LINK) {
+ cancel_delayed_work_sync(&conn->le_conn_timeout);
+
if (hdev->le_pkts)
hdev->le_cnt += conn->sent;
else
@@ -590,6 +603,13 @@ static void hci_req_add_le_create_conn(struct hci_request *req,
hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
conn->state = BT_CONNECT;
+
+ /* We don't want the connection attempt to stick around
+ * indefinitely since LE doesn't have a page timeout concept
+ * like BR/EDR.
+ */
+ queue_delayed_work(conn->hdev->workqueue, &conn->le_conn_timeout,
+ HCI_LE_CONN_TIMEOUT);
}
static void stop_scan_complete(struct hci_dev *hdev, u8 status)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3ae8ae1a029c..4698dfd8042f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3794,6 +3794,8 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn->init_addr_type = ev->bdaddr_type;
bacpy(&conn->init_addr, &ev->bdaddr);
}
+ } else {
+ cancel_delayed_work(&conn->le_conn_timeout);
}
/* Ensure that the hci_conn contains the identity address type
--
1.8.5.3
^ permalink raw reply related
* Re: Receiving data in BLE non-connectable undirected advertisements
From: Benjamin Adler @ 2014-02-28 15:38 UTC (permalink / raw)
Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <00B030ED-78C3-4C48-B738-4161348CD6E8@warski.org>
Adam,
thanks for your answer!
On 28.02.2014 15:13, Adam Warski wrote:
> If you want to see the raw advertisement packets, run:
> 1st terminal: hcidump -R
> 2nd terminal: hcitool lescan
> The raw dump will contain the advertisement data.
# hcidump -R
HCI sniffer - Bluetooth packet analyzer ver 5.14
device: hci0 snap_len: 1500 filter: 0xffffffffffffffff
### start "hcitool lescan"
< 01 0B 20 07 01 10 00 10 00 00 00
> 04 0E 04 01 0B 20 00
< 01 0C 20 02 01 01
> 04 0E 04 01 0C 20 00
### power-on sensortag
> 04 3E 14 02 01 03 00 7D 8A 0B AF 59 90 08 02 01 04 04 FF 01
02 03 B7
### power-cycle sensortag
<nothing>
So it seems like hcitool must first tell bluez to listen for
advertisement packets. Is there documentation/samples on how to do this
with python or C? Any other programs that do this, so I can read their
source?
Also, only the first advertisement of the SensorTag is shown. While that
probably makes sense for traditional advertisements, my use case
requires that all advertisements are shown, as I'm trying to transmit
low-rate data from the tag's sensors in the advertisements.
Do you have some hints concerning the easiest way to receive and process
those advertisements, preferably without the hassle of user-interaction
and multiple terminals?
Cheers,
ben
^ permalink raw reply
* Re: Receiving data in BLE non-connectable undirected advertisements
From: Marcel Holtmann @ 2014-02-28 15:46 UTC (permalink / raw)
To: Benjamin Adler; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <5310A4A9.2000907@gmx.net>
Hi Benjamin,
> as the subject notes, I'm trying to receive non-connectable undirected advertisements from a bluetooth low energy device, namely TI's SensorTag. Their SDK contains a sample app named SimpleBLEBroadcaster, that, supposedly, sends those advertisements including some data. There is an overview of TI's understanding of this mechanism for download at
>
> http://e2e.ti.com/support/low_power_rf/m/videos__files/653593/download.aspx
>
> Is it possible to receive/display the *data* (up to 31 bytes, I believe) that can be contained in those advertisements using bluez? I currently don't care whether it's a commandline tool, C-based API, python, DBUS, anything.
>
> When I start SimpleBLEBroadcaster, btmon alone doesn't show anything, but "hcitool lescan" says.
>
> LE Scan ...
> 90:59:AF:0B:8A:7D (unknown)
>
> The complete output of a btmon during lescan is attached below.
>
> https://github.com/bmpm/bcast-observer-demos and a script named "test-bluetooth-observer" made me believe that there should be an org.bluez.Observer interface for this, which I couldn't find using qdbusviewer.
>
> I asked on #bluez before, but it seems noone knew.
>
> Thanks!
> ben
>
> ###################################################################
>
> ####### start "btmon"
>
> Bluetooth monitor ver 5.14
> = New Index: 00:02:72:33:29:55 (BR/EDR,USB,hci0) [hci0] 0.377191
>
> ####### start "hcitool lescan" in another shell
>
> < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 [hci0] 4.457403
> Type: Active (0x01)
> Interval: 10.000 msec (0x0010)
> Window: 10.000 msec (0x0010)
> Own address type: Public (0x00)
> Filter policy: Accept all advertisement (0x00)
> > HCI Event: Command Complete (0x0e) plen 4 [hci0] 4.458949
> LE Set Scan Parameters (0x08|0x000b) ncmd 1
> Status: Success (0x00)
> < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 4.459094
> Scanning: Enabled (0x01)
> Filter duplicates: Enabled (0x01)
> > HCI Event: Command Complete (0x0e) plen 4 [hci0] 4.459957
> LE Set Scan Enable (0x08|0x000c) ncmd 1
> Status: Success (0x00)
>
> ####### Power-on the SensorTag
>
> > HCI Event: LE Meta Event (0x3e) plen 20 [hci0] 9.481376
> LE Advertising Report (0x02)
> Num reports: 1
> Event type: Non connectable undirected - ADV_NONCONN_IND (0x03)
> Address type: Public (0x00)
> Address: 90:59:AF:0B:8A:7D (Texas Instruments)
> Data length: 8
> Flags: 0x04
> BR/EDR Not Supported
> Company: not assigned (513)
> Data: 03
seems the TI engineers are as incapable of understanding little endian as the iOS engineers. Company identifiers are little endian, people ;)
> RSSI: -80 dBm (0xb0)
>
> ####### Quit hcitool
>
> < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 [hci0] 20.647504
> Scanning: Disabled (0x00)
> Filter duplicates: Enabled (0x01)
> > HCI Event: Command Complete (0x0e) plen 4 [hci0] 20.650124
> LE Set Scan Enable (0x08|0x000c) ncmd 1
> Status: Success (0x00)
>
> #
You can just write an advertising receiver by using Bluetooth HCI User Channel feature from the 3.13 kernel. With the help of src/shared/hci.c (if that license is acceptable to you), this is trivial. If the license is not acceptable, then you have to write your own HCI handling.
The BlueZ source code contains samples in form of tools/ibeacon.c and others on how to write such small program for direct access of the HCI interface. If you use this sample code, then please comply with the license as well here.
Our bluetoothd itself has zero interest in providing this functionality since we do have to look into the advertising data to make sense out of it.
Regards
Marcel
^ permalink raw reply
* Re: [PATCHv2 3/8] shared/hfp: Add initial implementiation of processing commands
From: Denis Kenzior @ 2014-02-28 15:46 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: Marcin Kraglak, linux-bluetooth
In-Reply-To: <BA9EB144-665E-4A51-81EF-EEEFAB18C822@holtmann.org>
Hi Marcel,
>> + if (data[result.offset] == '+')
>> + return process_extended(hfp, &result);
>> + else
>> + return process_basic(hfp, &result);
>
> Please do not do this. I mentioned this before, this basic vs extended is pointless.
>
> Command matching should be either based on commands like “D” or “+BRSF” and not bother trying to treat the + any special. See how src/emulator.c in oFono registers all the handlers.
>
There is a difference in syntax between basic commands and extended
commands. HFP only uses two basic commands, namely ATD and ATA so they
might be simply handled as a special case. Others are implicit, e.g.
ATE, ATV, etc.
Regards,
-Denis
^ permalink raw reply
* Re: [PATCH v2 0/4] Bluetooth: Fix initiator/responder addresses for SMP
From: Marcel Holtmann @ 2014-02-28 15:54 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1393584857-30375-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> Here's a second attempt to fix the initiator/responder addresses when
> using privacy. The main difference to the previous attempt is an added
> protection to HCI_Set_Random_Address so we don't do that while
> connecting or advertising, and a clarification for the white list corner
> case in aptch 3/4 that we're taking a "best effort" approach while
> lacking full tracking of white list initiated connections.
>
> Johan
>
> ----------------------------------------------------------------
> Johan Hedberg (4):
> Bluetooth: Add protections for updating local random address
> Bluetooth: Fix updating connection state to BT_CONNECT too early
> Bluetooth: Track LE initiator and responder address information
> Bluetooth: Use hdev->init/resp_addr values for smp_c1 function
>
> include/net/bluetooth/hci_core.h | 4 ++
> net/bluetooth/hci_conn.c | 3 +-
> net/bluetooth/hci_core.c | 27 ++++++++++++-
> net/bluetooth/hci_event.c | 78 ++++++++++++++++++++++++++++++++++++
> net/bluetooth/mgmt.c | 7 ++++
> net/bluetooth/smp.c | 22 +++-------
> 6 files changed, 122 insertions(+), 19 deletions(-)
all 4 patches have been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* Re: Receiving data in BLE non-connectable undirected advertisements
From: Adam Warski @ 2014-02-28 15:54 UTC (permalink / raw)
To: Benjamin Adler; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <5310AD83.9030208@gmx.net>
> Also, only the first advertisement of the SensorTag is shown. While that probably makes sense for traditional advertisements, my use case requires that all advertisements are shown, as I'm trying to transmit low-rate data from the tag's sensors in the advertisements.
Try hcitool lescan --duplicates.
By default duplicates are filtered out, so as all the advertisements are the same, you only see the first one after starting scanning.
However, see my post from 3 hours ago, I get into buffer overflows errors when using this option (but maybe it’s only me :) )
Adam
--
Adam Warski
http://twitter.com/#!/adamwarski
http://www.softwaremill.com
http://www.warski.org
^ permalink raw reply
* Re: Passive scanning of iBeacons results in a "Data Buffer Overflow"
From: Anderson Lizardo @ 2014-02-28 16:14 UTC (permalink / raw)
To: Adam Warski; +Cc: BlueZ development
In-Reply-To: <6E6C1573-4744-486B-B2E6-2D3DC45D024B@warski.org>
Hi Adam,
On Fri, Feb 28, 2014 at 8:41 AM, Adam Warski <adam@warski.org> wrote:
> But then I get:
>
>> HCI Event: LE Meta Event (0x3e) plen 42
> LE Advertising Report
> ADV_IND - Connectable undirected advertising (0)
> bdaddr FC:94:A8:6F:A8:10 (Random)
> Flags: 0x06
> Unknown type 0xff with 25 bytes data
> RSSI: -4
>> HCI Event: QoS Violation (0x1e) plen 2
> handle 1537
>> HCI Event: Data Buffer Overflow (0x1a) plen 255
> type Unknown
>> HCI Event: code 0xa8 plen 148
>> HCI Event: code 0xf8 plen 70
>> HCI Event: Physical Link Complete (0x40) plen 127
> status 0x30 phy handle 0xf5
> Error: Parameter out of Mandatory Range
For me looks like something got confused on the HCI packet parsing:
either the kernel, hcidump, or something else. The HCI events after
the LE meta event make no sense (they seem garbage). Did you try with
btmon instead of hcidump ?
Can you save the raw dump using "hcidump -w output.dump" (or using
btmon -w) and send to the list? It is easier to analyze, as the parser
may be bogus.
Best Regards,
--
Anderson Lizardo
http://www.indt.org/?lang=en
INdT - Manaus - Brazil
^ permalink raw reply
* Re: [PATCH v2 1/2] Bluetooth: Re-encrypt link after receiving an LTK
From: Marcel Holtmann @ 2014-02-28 16:19 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1393603803-19006-1-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> It's not strictly speaking required to re-encrypt a link once we receive
> an LTK since the connection is already encrypted with the STK. However,
> re-encrypting with the LTK allows us to verify that we've received an
> LTK that actually works.
>
> This patch updates the SMP code to request encrypting with the LTK in
> case we're in master role and waits until the key refresh complete event
> before notifying user space of the distributed keys.
>
> A new flag is also added for the SMP context to ensure that we
> re-encryption only once in case of multiple calls to smp_distribute_keys.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> net/bluetooth/smp.c | 32 +++++++++++++++++++++++++++-----
> net/bluetooth/smp.h | 3 ++-
> 2 files changed, 29 insertions(+), 6 deletions(-)
patch has been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* [PATCH 1/6] android/ipc: Add command to enable HFP in handsfree HAL
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
* [PATCH 2/6] android/handsfree: Add support for enable HFP command
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393604374-10127-1-git-send-email-szymon.janc@tieto.com>
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
* [PATCH 3/6] android/hal-handsfree: Add support for enable HFP command
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393604374-10127-1-git-send-email-szymon.janc@tieto.com>
---
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
* [PATCH 4/6] android/socket: Reserve channel for HSP AG
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393604374-10127-1-git-send-email-szymon.janc@tieto.com>
---
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
* [PATCH 5/6] android/handsfree: Add support for HSP AG
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393604374-10127-1-git-send-email-szymon.janc@tieto.com>
---
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
* [PATCH 6/6] android/handsfree: Allow to connect to HSP or HFP handsfree unit
From: Szymon Janc @ 2014-02-28 16:19 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1393604374-10127-1-git-send-email-szymon.janc@tieto.com>
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
* Re: [PATCH v2 2/2] Bluetooth: Add timeout for LE connection attempts
From: Marcel Holtmann @ 2014-02-28 16:32 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <1393602346-14676-2-git-send-email-johan.hedberg@gmail.com>
Hi Johan,
> LE connection attempts do not have a controller side timeout in the same
> way as BR/EDR has (in form of the page timeout). Since we always do
> scanning before initiating connections the attempts are always expected
> to succeed in some reasonable time.
>
> This patch adds a timer which forces a cancellation of the connection
> attempt within 20 seconds if it has not been successful by then. This
> way we e.g. ensure that mgmt_pair_device times out eventually and gives
> an error response.
>
> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
> ---
> include/net/bluetooth/hci.h | 1 +
> include/net/bluetooth/hci_core.h | 1 +
> net/bluetooth/hci_conn.c | 13 +++++++++++++
> net/bluetooth/hci_event.c | 12 ++++++++++++
> 4 files changed, 27 insertions(+)
both patches have been applied to bluetooth-next tree.
Regards
Marcel
^ permalink raw reply
* Re: [PATCH 4/6] android/socket: Reserve channel for HSP AG
From: Johan Hedberg @ 2014-02-28 16:44 UTC (permalink / raw)
To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1393604374-10127-4-git-send-email-szymon.janc@tieto.com>
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
* a2dp codec selection
From: tropp @ 2014-02-28 16:45 UTC (permalink / raw)
To: linux-bluetooth
hi,
i am using a2dp to connect my bluetooth headphones to my pc. the headphones are supporting the mandatory sbc codec and additionally the aac and aptX codecs. the following defines in profiles/audio/a2dp-codecs.h let me assume that at least sbc, mp3, aac and atrac are supported audio codecs by bluez:
#define A2DP_CODEC_SBC 0x00
#define A2DP_CODEC_MPEG12 0x01
#define A2DP_CODEC_MPEG24 0x02
#define A2DP_CODEC_ATRAC 0x03
#define A2DP_CODEC_VENDOR 0xFF
i want to use the aac codec for the best audio quality. therefore i added the following lines to my /etc/bluetooth/audio.conf
[A2DP]
SBCSources=0
MPEG24Sources=1
is there any possibility to check which codec is currently used if a a2dp link is established? i want to confirm that aac is really used, or if i am using sbc, which bitrate is selected.
i am using ubuntu 12.10.
regards, tropp
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox