2014-11-25 10:47:23

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 0/5] android/handsfree-client: Add SCO to HFP HF

Last missing piece to HFP HF implementation.

Lukasz Rymanowski (5):
android/handsfree-client: Add SCO to handsfree client
android/handsfree-client: Add handle incoming SCO connection
android/handsfree-client: Implement audio connect/disconnect
android/handsfree-client: Send AT+BCC to start codec negotiation
android/README: Update status of HAL HFP HF implementation

android/README | 2 +-
android/handsfree-client.c | 203 ++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 182 insertions(+), 23 deletions(-)

--
1.8.4



2014-11-28 08:56:12

by Lukasz Rymanowski

[permalink] [raw]
Subject: Re: [PATCH 4/5] android/handsfree-client: Send AT+BCC to start codec negotiation

Hi Szymon,

On Thu, Nov 27, 2014 at 9:50 PM, Szymon Janc <[email protected]> wrote:
> Hi Łukasz,
>
> On Tuesday 25 November 2014 11:47:27 Lukasz Rymanowski wrote:
>> With this patch we start codec negotation on audio connect if both sides
>> does support it.
>>
>> This patch also moves cmd_complete_cb and codec_negotiation_supported
>> functions up in the file
>> ---
>> android/handsfree-client.c | 107
>> +++++++++++++++++++++++---------------------- 1 file changed, 54
>> insertions(+), 53 deletions(-)
>>
>> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
>> index 4118b7e..d942a21 100644
>> --- a/android/handsfree-client.c
>> +++ b/android/handsfree-client.c
>> @@ -292,11 +292,63 @@ done:
>> HAL_OP_HF_CLIENT_DISCONNECT, status);
>> }
>>
>> +static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
>> + void *user_data)
>> +{
>> + struct hal_ev_hf_client_command_complete ev;
>> +
>> + DBG("");
>> + memset(&ev, 0, sizeof(ev));
>> +
>> + switch (result) {
>> + case HFP_RESULT_OK:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_OK;
>> + break;
>> + case HFP_RESULT_NO_CARRIER:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_CARRIER;
>> + break;
>> + case HFP_RESULT_ERROR:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
>> + break;
>> + case HFP_RESULT_BUSY:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BUSY;
>> + break;
>> + case HFP_RESULT_NO_ANSWER:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_ANSWER;
>> + break;
>> + case HFP_RESULT_DELAYED:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_DELAYED;
>> + break;
>> + case HFP_RESULT_BLACKLISTED:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BACKLISTED;
>> + break;
>> + case HFP_RESULT_CME_ERROR:
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_CME;
>> + ev.cme = cme_err;
>> + break;
>> + default:
>> + error("hf-client: Unknown error code %d", result);
>> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
>> + break;
>> + }
>> +
>> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
>> + HAL_EV_CLIENT_COMMAND_COMPLETE, sizeof(ev), &ev);
>> +}
>> +
>> +static bool codec_negotiation_supported(struct device *dev)
>> +{
>> + return (dev->features & HFP_AG_FEAT_CODEC) &&
>> + (hfp_hf_features & HFP_HF_FEAT_CODEC);
>> +}
>> +
>> static bool connect_sco(struct device *dev)
>> {
>> - /* TODO: handle codec negotiation */
>> + if (codec_negotiation_supported(dev))
>> + return hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
>> + "AT+BCC");
>
> This looks strange. It would result in calling command complete callback
> without pending AT command from framework. Shouldn't this be dedicated cb that
> would handle (unlikely, but still..) error and set audio state back to
> disconnected?

You are right. Somehow I missed that.

Also we should handle case when AG replied OK but didn't open
> SCO eg with timeout. This is to avoid getting stuck in connecting audio state.

I wouldn't be paranoid on that unless you have seen such IOT issue? If
not I would not complicate here.

\Lukasz
>
>>
>> - return bt_sco_connect(sco, &dev->bdaddr, 0);
>> + return bt_sco_connect(sco, &dev->bdaddr, BT_VOICE_CVSD_16BIT);
>> }
>>
>> static void set_audio_state(struct device *dev, uint8_t state)
>> @@ -377,51 +429,6 @@ done:
>> HAL_OP_HF_CLIENT_DISCONNECT_AUDIO, status);
>> }
>>
>> -static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
>> - void *user_data)
>> -{
>> - struct hal_ev_hf_client_command_complete ev;
>> -
>> - DBG("");
>> -
>> - memset(&ev, 0, sizeof(ev));
>> -
>> - switch (result) {
>> - case HFP_RESULT_OK:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_OK;
>> - break;
>> - case HFP_RESULT_NO_CARRIER:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_CARRIER;
>> - break;
>> - case HFP_RESULT_ERROR:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
>> - break;
>> - case HFP_RESULT_BUSY:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BUSY;
>> - break;
>> - case HFP_RESULT_NO_ANSWER:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_ANSWER;
>> - break;
>> - case HFP_RESULT_DELAYED:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_DELAYED;
>> - break;
>> - case HFP_RESULT_BLACKLISTED:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BACKLISTED;
>> - break;
>> - case HFP_RESULT_CME_ERROR:
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_CME;
>> - ev.cme = cme_err;
>> - break;
>> - default:
>> - error("hf-client: Unknown error code %d", result);
>> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
>> - break;
>> - }
>> -
>> - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
>> - HAL_EV_CLIENT_COMMAND_COMPLETE, sizeof(ev), &ev);
>> -}
>> -
>> static void handle_start_vr(const void *buf, uint16_t len)
>> {
>> struct device *dev;
>> @@ -1653,12 +1660,6 @@ static void slc_brsf_cb(struct hfp_context *context,
>> void *user_data) dev->features = feat;
>> }
>>
>> -static bool codec_negotiation_supported(struct device *dev)
>> -{
>> - return (dev->features & HFP_AG_FEAT_CODEC) &&
>> - (hfp_hf_features & HFP_HF_FEAT_CODEC);
>> -}
>> -
>> static void slc_brsf_resp(enum hfp_result result, enum hfp_error cme_err,
>> void *user_data)
>> {
>
> --
> Szymon K. Janc
> [email protected]
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-11-27 20:51:12

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 3/5] android/handsfree-client: Implement audio connect/disconnect

Hi Łukasz,

On Tuesday 25 November 2014 11:47:26 Lukasz Rymanowski wrote:
> In this patch also set_audio_state function has been moved

One more thing: set_audio_state() was introduced in PATCH 2/5. Why not put it
in right place from beginning?

> ---
> android/handsfree-client.c | 100
> +++++++++++++++++++++++++++++++++------------ 1 file changed, 75
> insertions(+), 25 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 432b9a1..4118b7e 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -292,19 +292,89 @@ done:
> HAL_OP_HF_CLIENT_DISCONNECT, status);
> }
>
> +static bool connect_sco(struct device *dev)
> +{
> + /* TODO: handle codec negotiation */
> +
> + return bt_sco_connect(sco, &dev->bdaddr, 0);
> +}
> +
> +static void set_audio_state(struct device *dev, uint8_t state)
> +{
> + struct hal_ev_hf_client_audio_state ev;
> + char address[18];
> +
> + if (dev->audio_state == state)
> + return;
> +
> + dev->audio_state = state;
> +
> + ba2str(&dev->bdaddr, address);
> + DBG("device %s audio state %u", address, state);
> +
> + bdaddr2android(&dev->bdaddr, ev.bdaddr);
> + ev.state = state;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
> +}
> +
> static void handle_connect_audio(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + const struct hal_cmd_hf_client_connect_audio *cmd = (void *) buf;
> + struct device *dev;
> + uint8_t status;
> + bdaddr_t bdaddr;
> +
> + DBG("");
> +
> + android2bdaddr(&cmd->bdaddr, &bdaddr);
> +
> + dev = find_device(&bdaddr);
> + if (!dev || dev->state != HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED ||
> + dev->audio_state != HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED) {
> + error("hf-client: Cannot create SCO, check SLC or audio state");
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + if (connect_sco(dev)) {
> + status = HAL_STATUS_SUCCESS;
> + set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_CONNECTING);
> + } else {
> + status = HAL_STATUS_FAILED;
> + }
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_CONNECT_AUDIO, HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_CONNECT_AUDIO, status);
> }
>
> static void handle_disconnect_audio(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + const struct hal_cmd_hf_client_disconnect_audio *cmd = (void *) buf;
> + struct device *dev;
> + uint8_t status;
> + bdaddr_t bdaddr;
> +
> + DBG("");
> +
> + android2bdaddr(&cmd->bdaddr, &bdaddr);
> +
> + dev = find_device(&bdaddr);
> + if (!dev ||
> + dev->audio_state == HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED) {
> + error("hf-client: Device not found or audio not connected");
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + bt_sco_disconnect(sco);
> + status = HAL_STATUS_SUCCESS;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_DISCONNECT_AUDIO,
> - HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_DISCONNECT_AUDIO, status);
> }
>
> static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
> @@ -2011,26 +2081,6 @@ static void cleanup_hfp_hf(void)
> }
> }
>
> -static void set_audio_state(struct device *dev, uint8_t state)
> -{
> - struct hal_ev_hf_client_audio_state ev;
> - char address[18];
> -
> - if (dev->audio_state == state)
> - return;
> -
> - dev->audio_state = state;
> -
> - ba2str(&dev->bdaddr, address);
> - DBG("device %s audio state %u", address, state);
> -
> - bdaddr2android(&dev->bdaddr, ev.bdaddr);
> - ev.state = state;
> -
> - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
> -}
> -
> static bool confirm_sco_cb(const bdaddr_t *addr, uint16_t *voice_settings)
> {
> struct device *dev;

--
Szymon K. Janc
[email protected]

2014-11-27 20:50:20

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 4/5] android/handsfree-client: Send AT+BCC to start codec negotiation

Hi Łukasz,

On Tuesday 25 November 2014 11:47:27 Lukasz Rymanowski wrote:
> With this patch we start codec negotation on audio connect if both sides
> does support it.
>
> This patch also moves cmd_complete_cb and codec_negotiation_supported
> functions up in the file
> ---
> android/handsfree-client.c | 107
> +++++++++++++++++++++++---------------------- 1 file changed, 54
> insertions(+), 53 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 4118b7e..d942a21 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -292,11 +292,63 @@ done:
> HAL_OP_HF_CLIENT_DISCONNECT, status);
> }
>
> +static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
> + void *user_data)
> +{
> + struct hal_ev_hf_client_command_complete ev;
> +
> + DBG("");
> + memset(&ev, 0, sizeof(ev));
> +
> + switch (result) {
> + case HFP_RESULT_OK:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_OK;
> + break;
> + case HFP_RESULT_NO_CARRIER:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_CARRIER;
> + break;
> + case HFP_RESULT_ERROR:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
> + break;
> + case HFP_RESULT_BUSY:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BUSY;
> + break;
> + case HFP_RESULT_NO_ANSWER:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_ANSWER;
> + break;
> + case HFP_RESULT_DELAYED:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_DELAYED;
> + break;
> + case HFP_RESULT_BLACKLISTED:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BACKLISTED;
> + break;
> + case HFP_RESULT_CME_ERROR:
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_CME;
> + ev.cme = cme_err;
> + break;
> + default:
> + error("hf-client: Unknown error code %d", result);
> + ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
> + break;
> + }
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_CLIENT_COMMAND_COMPLETE, sizeof(ev), &ev);
> +}
> +
> +static bool codec_negotiation_supported(struct device *dev)
> +{
> + return (dev->features & HFP_AG_FEAT_CODEC) &&
> + (hfp_hf_features & HFP_HF_FEAT_CODEC);
> +}
> +
> static bool connect_sco(struct device *dev)
> {
> - /* TODO: handle codec negotiation */
> + if (codec_negotiation_supported(dev))
> + return hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+BCC");

This looks strange. It would result in calling command complete callback
without pending AT command from framework. Shouldn't this be dedicated cb that
would handle (unlikely, but still..) error and set audio state back to
disconnected? Also we should handle case when AG replied OK but didn't open
SCO eg with timeout. This is to avoid getting stuck in connecting audio state.

>
> - return bt_sco_connect(sco, &dev->bdaddr, 0);
> + return bt_sco_connect(sco, &dev->bdaddr, BT_VOICE_CVSD_16BIT);
> }
>
> static void set_audio_state(struct device *dev, uint8_t state)
> @@ -377,51 +429,6 @@ done:
> HAL_OP_HF_CLIENT_DISCONNECT_AUDIO, status);
> }
>
> -static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
> - void *user_data)
> -{
> - struct hal_ev_hf_client_command_complete ev;
> -
> - DBG("");
> -
> - memset(&ev, 0, sizeof(ev));
> -
> - switch (result) {
> - case HFP_RESULT_OK:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_OK;
> - break;
> - case HFP_RESULT_NO_CARRIER:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_CARRIER;
> - break;
> - case HFP_RESULT_ERROR:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
> - break;
> - case HFP_RESULT_BUSY:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BUSY;
> - break;
> - case HFP_RESULT_NO_ANSWER:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_ANSWER;
> - break;
> - case HFP_RESULT_DELAYED:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_DELAYED;
> - break;
> - case HFP_RESULT_BLACKLISTED:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BACKLISTED;
> - break;
> - case HFP_RESULT_CME_ERROR:
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_CME;
> - ev.cme = cme_err;
> - break;
> - default:
> - error("hf-client: Unknown error code %d", result);
> - ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
> - break;
> - }
> -
> - ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_EV_CLIENT_COMMAND_COMPLETE, sizeof(ev), &ev);
> -}
> -
> static void handle_start_vr(const void *buf, uint16_t len)
> {
> struct device *dev;
> @@ -1653,12 +1660,6 @@ static void slc_brsf_cb(struct hfp_context *context,
> void *user_data) dev->features = feat;
> }
>
> -static bool codec_negotiation_supported(struct device *dev)
> -{
> - return (dev->features & HFP_AG_FEAT_CODEC) &&
> - (hfp_hf_features & HFP_HF_FEAT_CODEC);
> -}
> -
> static void slc_brsf_resp(enum hfp_result result, enum hfp_error cme_err,
> void *user_data)
> {

--
Szymon K. Janc
[email protected]

2014-11-27 20:50:08

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 2/5] android/handsfree-client: Add handle incoming SCO connection

Hi Łukasz,

On Tuesday 25 November 2014 11:47:25 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 93
> ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93
> insertions(+)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 9e67c7f..432b9a1 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -116,6 +116,7 @@ struct device {
> bdaddr_t bdaddr;
> struct hfp_hf *hf;
> uint8_t state;
> + uint8_t audio_state;
>
> uint8_t negotiated_codec;
> uint32_t features;
> @@ -184,6 +185,7 @@ static struct device *device_create(const bdaddr_t
> *bdaddr)
>
> bacpy(&dev->bdaddr, bdaddr);
> dev->state = HAL_HF_CLIENT_CONN_STATE_DISCONNECTED;
> + dev->audio_state = HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
>
> init_codecs(dev);
>
> @@ -2009,6 +2011,93 @@ static void cleanup_hfp_hf(void)
> }
> }
>
> +static void set_audio_state(struct device *dev, uint8_t state)
> +{
> + struct hal_ev_hf_client_audio_state ev;
> + char address[18];
> +
> + if (dev->audio_state == state)
> + return;
> +
> + dev->audio_state = state;
> +
> + ba2str(&dev->bdaddr, address);
> + DBG("device %s audio state %u", address, state);
> +
> + bdaddr2android(&dev->bdaddr, ev.bdaddr);
> + ev.state = state;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
> +}
> +
> +static bool confirm_sco_cb(const bdaddr_t *addr, uint16_t *voice_settings)
> +{
> + struct device *dev;
> +
> + DBG("");
> +
> + dev = find_device(addr);
> + if (!dev || dev->state != HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED) {
> + error("hf-client: No device or SLC not ready");
> + return false;
> + }
> +
> + set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_CONNECTING);
> +
> + if (!(codec_negotiation_supported(dev)))

Those extra brackets are not needed.

> + *voice_settings = 0;
> + else if (dev->negotiated_codec != CODEC_ID_CVSD)
> + *voice_settings = BT_VOICE_TRANSPARENT;
> + else
> + *voice_settings = BT_VOICE_CVSD_16BIT;
> +
> + return true;
> +}
> +
> +static void connect_sco_cb(enum sco_status status, const bdaddr_t *addr)
> +{
> + struct device *dev;
> + uint8_t audio_state;
> +
> + DBG("SCO Status %u", status);
> +
> + /* Device shall be there, just sanity check */
> + dev = find_device(addr);
> + if (!dev) {
> + error("hf-client: There is no device?");
> + return;
> + }
> +
> + if (status != SCO_STATUS_OK) {
> + audio_state = HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
> + goto done;
> + }
> +
> + if (dev->negotiated_codec == CODEC_ID_MSBC)
> + audio_state = HAL_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC;
> + else
> + audio_state = HAL_HF_CLIENT_AUDIO_STATE_CONNECTED;
> +
> +done:
> + set_audio_state(dev, audio_state);
> +}
> +
> +static void disconnect_sco_cb(const bdaddr_t *addr)
> +{
> + struct device *dev;
> +
> + DBG("");
> +
> + dev = get_device(addr);
> + if (!dev) {
> + error("hf-client: No device");
> + return;
> + }
> +
> + set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED);
> +}
> +
> bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> DBG("");
> @@ -2030,6 +2119,10 @@ bool bt_hf_client_register(struct ipc *ipc, const
> bdaddr_t *addr) goto failed;
> }
>
> + bt_sco_set_confirm_cb(sco, confirm_sco_cb);
> + bt_sco_set_connect_cb(sco, connect_sco_cb);
> + bt_sco_set_disconnect_cb(sco, disconnect_sco_cb);
> +
> hal_ipc = ipc;
> ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));

--
Szymon K. Janc
[email protected]

2014-11-27 20:49:58

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 5/5] android/README: Update status of HAL HFP HF implementation

Hi Łukasz,

On Tuesday 25 November 2014 11:47:28 Lukasz Rymanowski wrote:
> ---
> android/README | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/android/README b/android/README
> index b1ac886..760c2ec 100644
> --- a/android/README
> +++ b/android/README
> @@ -276,7 +276,7 @@ health bt_hl.h complete
> pan bt_pan.h complete
> avrcp bt_rc.h complete
> socket bt_sock.h complete
> -hf_client bt_hf_client.h initial
> +hf_client bt_hf_client.h complete
> map_client bt_mce.h complete

Since I've updated documentation with L information this patch would need to
be rebased.

--
Szymon K. Janc
[email protected]

2014-11-27 20:04:38

by Lukasz Rymanowski

[permalink] [raw]
Subject: Re: [PATCH 0/5] android/handsfree-client: Add SCO to HFP HF

On Tue, Nov 25, 2014 at 11:47 AM, Lukasz Rymanowski
<[email protected]> wrote:
> Last missing piece to HFP HF implementation.
>
> Lukasz Rymanowski (5):
> android/handsfree-client: Add SCO to handsfree client
> android/handsfree-client: Add handle incoming SCO connection
> android/handsfree-client: Implement audio connect/disconnect
> android/handsfree-client: Send AT+BCC to start codec negotiation
> android/README: Update status of HAL HFP HF implementation
>

ping

> android/README | 2 +-
> android/handsfree-client.c | 203 ++++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 182 insertions(+), 23 deletions(-)
>
> --
> 1.8.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-11-25 11:30:43

by Lukasz Rymanowski

[permalink] [raw]
Subject: Re: [PATCH 2/5] android/handsfree-client: Add handle incoming SCO connection

Hi,

On Tue, Nov 25, 2014 at 11:47 AM, Lukasz Rymanowski
<[email protected]> wrote:
> ---
> android/handsfree-client.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 93 insertions(+)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 9e67c7f..432b9a1 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -116,6 +116,7 @@ struct device {
> bdaddr_t bdaddr;
> struct hfp_hf *hf;
> uint8_t state;
> + uint8_t audio_state;
>
> uint8_t negotiated_codec;
> uint32_t features;
> @@ -184,6 +185,7 @@ static struct device *device_create(const bdaddr_t *bdaddr)
>
> bacpy(&dev->bdaddr, bdaddr);
> dev->state = HAL_HF_CLIENT_CONN_STATE_DISCONNECTED;
> + dev->audio_state = HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
>
> init_codecs(dev);
>
> @@ -2009,6 +2011,93 @@ static void cleanup_hfp_hf(void)
> }
> }
>
> +static void set_audio_state(struct device *dev, uint8_t state)
> +{
> + struct hal_ev_hf_client_audio_state ev;
> + char address[18];
> +
> + if (dev->audio_state == state)
> + return;
> +
> + dev->audio_state = state;
> +
> + ba2str(&dev->bdaddr, address);
> + DBG("device %s audio state %u", address, state);
> +
> + bdaddr2android(&dev->bdaddr, ev.bdaddr);
> + ev.state = state;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
> +}
> +
> +static bool confirm_sco_cb(const bdaddr_t *addr, uint16_t *voice_settings)
> +{
> + struct device *dev;
> +
> + DBG("");
> +
> + dev = find_device(addr);
> + if (!dev || dev->state != HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED) {
> + error("hf-client: No device or SLC not ready");
> + return false;
> + }
> +
> + set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_CONNECTING);
> +
> + if (!(codec_negotiation_supported(dev)))
> + *voice_settings = 0;
> + else if (dev->negotiated_codec != CODEC_ID_CVSD)
> + *voice_settings = BT_VOICE_TRANSPARENT;
> + else
> + *voice_settings = BT_VOICE_CVSD_16BIT;
> +
> + return true;
> +}
> +
> +static void connect_sco_cb(enum sco_status status, const bdaddr_t *addr)
> +{
> + struct device *dev;
> + uint8_t audio_state;
> +
> + DBG("SCO Status %u", status);
> +
> + /* Device shall be there, just sanity check */
> + dev = find_device(addr);
> + if (!dev) {
> + error("hf-client: There is no device?");
> + return;
> + }
> +
> + if (status != SCO_STATUS_OK) {
> + audio_state = HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
> + goto done;
> + }
> +
> + if (dev->negotiated_codec == CODEC_ID_MSBC)
> + audio_state = HAL_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC;
> + else
> + audio_state = HAL_HF_CLIENT_AUDIO_STATE_CONNECTED;
> +
> +done:
> + set_audio_state(dev, audio_state);
> +}
> +
> +static void disconnect_sco_cb(const bdaddr_t *addr)
> +{
> + struct device *dev;
> +
> + DBG("");
> +
> + dev = get_device(addr);

Just noticed that It should be find_device() here. Will fix it in v2
but I'm waiting for other comments.

\Lukasz
> + if (!dev) {
> + error("hf-client: No device");
> + return;
> + }
> +
> + set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED);
> +}
> +
> bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
> {
> DBG("");
> @@ -2030,6 +2119,10 @@ bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
> goto failed;
> }
>
> + bt_sco_set_confirm_cb(sco, confirm_sco_cb);
> + bt_sco_set_connect_cb(sco, connect_sco_cb);
> + bt_sco_set_disconnect_cb(sco, disconnect_sco_cb);
> +
> hal_ipc = ipc;
> ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT, cmd_handlers,
> G_N_ELEMENTS(cmd_handlers));
> --
> 1.8.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2014-11-25 10:47:24

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 1/5] android/handsfree-client: Add SCO to handsfree client

---
android/handsfree-client.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 283519f..9e67c7f 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -47,6 +47,7 @@
#include "bluetooth.h"
#include "hal-msg.h"
#include "handsfree-client.h"
+#include "sco.h"

#define HFP_HF_CHANNEL 7

@@ -139,6 +140,8 @@ static uint32_t hfp_hf_record_id = 0;
static struct queue *devices = NULL;
static GIOChannel *hfp_hf_server = NULL;

+static struct bt_sco *sco = NULL;
+
static struct device *find_default_device(void)
{
return queue_peek_head(devices);
@@ -1999,6 +2002,11 @@ static void cleanup_hfp_hf(void)
bt_adapter_remove_record(hfp_hf_record_id);
hfp_hf_record_id = 0;
}
+
+ if (sco) {
+ bt_sco_unref(sco);
+ sco = NULL;
+ }
}

bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
@@ -2016,6 +2024,12 @@ bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
if (!enable_hf_client())
goto failed;

+ sco = bt_sco_new(addr);
+ if (!sco) {
+ error("hf-client: Cannot create SCO. HFP AG is in use ?");
+ goto failed;
+ }
+
hal_ipc = ipc;
ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
@@ -2023,6 +2037,7 @@ bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
return true;

failed:
+ cleanup_hfp_hf();
queue_destroy(devices, free);
devices = NULL;

--
1.8.4


2014-11-25 10:47:25

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 2/5] android/handsfree-client: Add handle incoming SCO connection

---
android/handsfree-client.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 9e67c7f..432b9a1 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -116,6 +116,7 @@ struct device {
bdaddr_t bdaddr;
struct hfp_hf *hf;
uint8_t state;
+ uint8_t audio_state;

uint8_t negotiated_codec;
uint32_t features;
@@ -184,6 +185,7 @@ static struct device *device_create(const bdaddr_t *bdaddr)

bacpy(&dev->bdaddr, bdaddr);
dev->state = HAL_HF_CLIENT_CONN_STATE_DISCONNECTED;
+ dev->audio_state = HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED;

init_codecs(dev);

@@ -2009,6 +2011,93 @@ static void cleanup_hfp_hf(void)
}
}

+static void set_audio_state(struct device *dev, uint8_t state)
+{
+ struct hal_ev_hf_client_audio_state ev;
+ char address[18];
+
+ if (dev->audio_state == state)
+ return;
+
+ dev->audio_state = state;
+
+ ba2str(&dev->bdaddr, address);
+ DBG("device %s audio state %u", address, state);
+
+ bdaddr2android(&dev->bdaddr, ev.bdaddr);
+ ev.state = state;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
+}
+
+static bool confirm_sco_cb(const bdaddr_t *addr, uint16_t *voice_settings)
+{
+ struct device *dev;
+
+ DBG("");
+
+ dev = find_device(addr);
+ if (!dev || dev->state != HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED) {
+ error("hf-client: No device or SLC not ready");
+ return false;
+ }
+
+ set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_CONNECTING);
+
+ if (!(codec_negotiation_supported(dev)))
+ *voice_settings = 0;
+ else if (dev->negotiated_codec != CODEC_ID_CVSD)
+ *voice_settings = BT_VOICE_TRANSPARENT;
+ else
+ *voice_settings = BT_VOICE_CVSD_16BIT;
+
+ return true;
+}
+
+static void connect_sco_cb(enum sco_status status, const bdaddr_t *addr)
+{
+ struct device *dev;
+ uint8_t audio_state;
+
+ DBG("SCO Status %u", status);
+
+ /* Device shall be there, just sanity check */
+ dev = find_device(addr);
+ if (!dev) {
+ error("hf-client: There is no device?");
+ return;
+ }
+
+ if (status != SCO_STATUS_OK) {
+ audio_state = HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
+ goto done;
+ }
+
+ if (dev->negotiated_codec == CODEC_ID_MSBC)
+ audio_state = HAL_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC;
+ else
+ audio_state = HAL_HF_CLIENT_AUDIO_STATE_CONNECTED;
+
+done:
+ set_audio_state(dev, audio_state);
+}
+
+static void disconnect_sco_cb(const bdaddr_t *addr)
+{
+ struct device *dev;
+
+ DBG("");
+
+ dev = get_device(addr);
+ if (!dev) {
+ error("hf-client: No device");
+ return;
+ }
+
+ set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED);
+}
+
bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
{
DBG("");
@@ -2030,6 +2119,10 @@ bool bt_hf_client_register(struct ipc *ipc, const bdaddr_t *addr)
goto failed;
}

+ bt_sco_set_confirm_cb(sco, confirm_sco_cb);
+ bt_sco_set_connect_cb(sco, connect_sco_cb);
+ bt_sco_set_disconnect_cb(sco, disconnect_sco_cb);
+
hal_ipc = ipc;
ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT, cmd_handlers,
G_N_ELEMENTS(cmd_handlers));
--
1.8.4


2014-11-25 10:47:27

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 4/5] android/handsfree-client: Send AT+BCC to start codec negotiation

With this patch we start codec negotation on audio connect if both sides
does support it.

This patch also moves cmd_complete_cb and codec_negotiation_supported
functions up in the file
---
android/handsfree-client.c | 107 +++++++++++++++++++++++----------------------
1 file changed, 54 insertions(+), 53 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 4118b7e..d942a21 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -292,11 +292,63 @@ done:
HAL_OP_HF_CLIENT_DISCONNECT, status);
}

+static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
+ void *user_data)
+{
+ struct hal_ev_hf_client_command_complete ev;
+
+ DBG("");
+ memset(&ev, 0, sizeof(ev));
+
+ switch (result) {
+ case HFP_RESULT_OK:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_OK;
+ break;
+ case HFP_RESULT_NO_CARRIER:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_CARRIER;
+ break;
+ case HFP_RESULT_ERROR:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
+ break;
+ case HFP_RESULT_BUSY:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BUSY;
+ break;
+ case HFP_RESULT_NO_ANSWER:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_ANSWER;
+ break;
+ case HFP_RESULT_DELAYED:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_DELAYED;
+ break;
+ case HFP_RESULT_BLACKLISTED:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BACKLISTED;
+ break;
+ case HFP_RESULT_CME_ERROR:
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_CME;
+ ev.cme = cme_err;
+ break;
+ default:
+ error("hf-client: Unknown error code %d", result);
+ ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
+ break;
+ }
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_CLIENT_COMMAND_COMPLETE, sizeof(ev), &ev);
+}
+
+static bool codec_negotiation_supported(struct device *dev)
+{
+ return (dev->features & HFP_AG_FEAT_CODEC) &&
+ (hfp_hf_features & HFP_HF_FEAT_CODEC);
+}
+
static bool connect_sco(struct device *dev)
{
- /* TODO: handle codec negotiation */
+ if (codec_negotiation_supported(dev))
+ return hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+BCC");

- return bt_sco_connect(sco, &dev->bdaddr, 0);
+ return bt_sco_connect(sco, &dev->bdaddr, BT_VOICE_CVSD_16BIT);
}

static void set_audio_state(struct device *dev, uint8_t state)
@@ -377,51 +429,6 @@ done:
HAL_OP_HF_CLIENT_DISCONNECT_AUDIO, status);
}

-static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
- void *user_data)
-{
- struct hal_ev_hf_client_command_complete ev;
-
- DBG("");
-
- memset(&ev, 0, sizeof(ev));
-
- switch (result) {
- case HFP_RESULT_OK:
- ev.type = HAL_HF_CLIENT_CMD_COMP_OK;
- break;
- case HFP_RESULT_NO_CARRIER:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_CARRIER;
- break;
- case HFP_RESULT_ERROR:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
- break;
- case HFP_RESULT_BUSY:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BUSY;
- break;
- case HFP_RESULT_NO_ANSWER:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_NO_ANSWER;
- break;
- case HFP_RESULT_DELAYED:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_DELAYED;
- break;
- case HFP_RESULT_BLACKLISTED:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_BACKLISTED;
- break;
- case HFP_RESULT_CME_ERROR:
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR_CME;
- ev.cme = cme_err;
- break;
- default:
- error("hf-client: Unknown error code %d", result);
- ev.type = HAL_HF_CLIENT_CMD_COMP_ERR;
- break;
- }
-
- ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_EV_CLIENT_COMMAND_COMPLETE, sizeof(ev), &ev);
-}
-
static void handle_start_vr(const void *buf, uint16_t len)
{
struct device *dev;
@@ -1653,12 +1660,6 @@ static void slc_brsf_cb(struct hfp_context *context, void *user_data)
dev->features = feat;
}

-static bool codec_negotiation_supported(struct device *dev)
-{
- return (dev->features & HFP_AG_FEAT_CODEC) &&
- (hfp_hf_features & HFP_HF_FEAT_CODEC);
-}
-
static void slc_brsf_resp(enum hfp_result result, enum hfp_error cme_err,
void *user_data)
{
--
1.8.4


2014-11-25 10:47:28

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 5/5] android/README: Update status of HAL HFP HF implementation

---
android/README | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/README b/android/README
index b1ac886..760c2ec 100644
--- a/android/README
+++ b/android/README
@@ -276,7 +276,7 @@ health bt_hl.h complete
pan bt_pan.h complete
avrcp bt_rc.h complete
socket bt_sock.h complete
-hf_client bt_hf_client.h initial
+hf_client bt_hf_client.h complete
map_client bt_mce.h complete


--
1.8.4


2014-11-25 10:47:26

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 3/5] android/handsfree-client: Implement audio connect/disconnect

In this patch also set_audio_state function has been moved
---
android/handsfree-client.c | 100 +++++++++++++++++++++++++++++++++------------
1 file changed, 75 insertions(+), 25 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 432b9a1..4118b7e 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -292,19 +292,89 @@ done:
HAL_OP_HF_CLIENT_DISCONNECT, status);
}

+static bool connect_sco(struct device *dev)
+{
+ /* TODO: handle codec negotiation */
+
+ return bt_sco_connect(sco, &dev->bdaddr, 0);
+}
+
+static void set_audio_state(struct device *dev, uint8_t state)
+{
+ struct hal_ev_hf_client_audio_state ev;
+ char address[18];
+
+ if (dev->audio_state == state)
+ return;
+
+ dev->audio_state = state;
+
+ ba2str(&dev->bdaddr, address);
+ DBG("device %s audio state %u", address, state);
+
+ bdaddr2android(&dev->bdaddr, ev.bdaddr);
+ ev.state = state;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
+}
+
static void handle_connect_audio(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ const struct hal_cmd_hf_client_connect_audio *cmd = (void *) buf;
+ struct device *dev;
+ uint8_t status;
+ bdaddr_t bdaddr;
+
+ DBG("");
+
+ android2bdaddr(&cmd->bdaddr, &bdaddr);
+
+ dev = find_device(&bdaddr);
+ if (!dev || dev->state != HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED ||
+ dev->audio_state != HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED) {
+ error("hf-client: Cannot create SCO, check SLC or audio state");
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (connect_sco(dev)) {
+ status = HAL_STATUS_SUCCESS;
+ set_audio_state(dev, HAL_HF_CLIENT_AUDIO_STATE_CONNECTING);
+ } else {
+ status = HAL_STATUS_FAILED;
+ }
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_CONNECT_AUDIO, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_CONNECT_AUDIO, status);
}

static void handle_disconnect_audio(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ const struct hal_cmd_hf_client_disconnect_audio *cmd = (void *) buf;
+ struct device *dev;
+ uint8_t status;
+ bdaddr_t bdaddr;
+
+ DBG("");
+
+ android2bdaddr(&cmd->bdaddr, &bdaddr);
+
+ dev = find_device(&bdaddr);
+ if (!dev ||
+ dev->audio_state == HAL_HF_CLIENT_AUDIO_STATE_DISCONNECTED) {
+ error("hf-client: Device not found or audio not connected");
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ bt_sco_disconnect(sco);
+ status = HAL_STATUS_SUCCESS;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_DISCONNECT_AUDIO,
- HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_DISCONNECT_AUDIO, status);
}

static void cmd_complete_cb(enum hfp_result result, enum hfp_error cme_err,
@@ -2011,26 +2081,6 @@ static void cleanup_hfp_hf(void)
}
}

-static void set_audio_state(struct device *dev, uint8_t state)
-{
- struct hal_ev_hf_client_audio_state ev;
- char address[18];
-
- if (dev->audio_state == state)
- return;
-
- dev->audio_state = state;
-
- ba2str(&dev->bdaddr, address);
- DBG("device %s audio state %u", address, state);
-
- bdaddr2android(&dev->bdaddr, ev.bdaddr);
- ev.state = state;
-
- ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_EV_HF_CLIENT_AUDIO_STATE, sizeof(ev), &ev);
-}
-
static bool confirm_sco_cb(const bdaddr_t *addr, uint16_t *voice_settings)
{
struct device *dev;
--
1.8.4