2014-11-12 10:49:23

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 00/14] android/handsfree-clien: Second set of HFP HF

In this set all mising signaling part is implemented.
Tested on UPF 49 as well.

SCO part will come in next set.

Lukasz Rymanowski (14):
android/handsfree-client: Add handle start/stop vr
android/handsfree-client: Add volume control handling
android/handsfree-client: Add handling dial command
android/handsfree-client: Add call action implementation
android/handsfree-client: Implement query current calls
android/handsfree-client: Add handling +CLCC
android/handsfree-client: Add support for +CIEV events
android/handsfree-client: Send indicators val we got during SLC setup
android/handsfree-client: Add support to get operator name
android/handsfree-client: Send to AG that we do support long name
android/handsfree-client: Retrieve subscriber number information
android/handsfree-client: Implement send DTMF codes
android/handsfree-client: Implement handling AT+BIND and +BIND
android/handsfree-client: Implement codec negotiations

android/handsfree-client.c | 832 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 800 insertions(+), 32 deletions(-)

--
1.8.4



2014-11-18 21:58:52

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 14/14] android/handsfree-client: Implement codec negotiations

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:37 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 62
> ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62
> insertions(+)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 4338c11..74d1547 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -116,6 +116,7 @@ struct device {
> struct hfp_hf *hf;
> uint8_t state;
>
> + uint8_t negotiated_codec;
> uint32_t features;
> struct hfp_codec codecs[2];
>
> @@ -1034,6 +1035,66 @@ static void binp_cb(struct hfp_context *context, void
> *user_data) sizeof(*ev) + ev->number_len, ev);
> }
>
> +static bool is_codec_supported_localy(struct device *dev, uint8_t codec)
> +{
> + int i;
> +
> + for (i = 0; i < CODECS_COUNT; i++) {
> + if (dev->codecs[i].type != codec)
> + continue;
> +
> + return dev->codecs[i].local_supported;
> + }
> +
> + return false;
> +}
> +
> +static void bcs_resp(enum hfp_result result, enum hfp_error cme_err,
> + void *user_data)
> +{
> + DBG("%d", result);

Shouldn't we handle error response?

> +}
> +
> +static void bcs_cb(struct hfp_context *context, void *user_data)
> +{
> + struct device *dev = user_data;
> + uint32_t codec;

unsigned int

> + char codecs_string[2 * CODECS_COUNT + 1];
> + char cmd[sizeof(codecs_string) + 7];

Those really deserve some comment.

> +
> + DBG("");
> +
> + if (!context) {
> + error("hf-client: incorrect BCS response");
> + return;
> + }

Not needed.

> +
> + memset(cmd, 0, sizeof(cmd));
> +
> + if (!hfp_context_get_number(context, &codec))
> + goto failed;
> +
> + if (!is_codec_supported_localy(dev, codec))
> + goto failed;
> +
> + sprintf(cmd, "AT+BCS=%d", codec);
> +
> + dev->negotiated_codec = codec;
> +
> + goto done;
> +
> +failed:

I'd avoid this mixed labels jump, those make code hard to read.
I'd make failed label handle only fail case. Just call hfp_hf_send_command
instead of those sprintfs. This will also make cmd not needed.

> + error("hf-client: Could not get codec");
> +
> + strcpy(cmd, "AT+BCS=");
> +
> + get_local_codecs_string(dev, codecs_string, sizeof(codecs_string));
> + strcat(cmd, codecs_string);

maybe this is not really needed since hfp_hf_send_command accepts format
string?

hfp_hf_send_command(dev->hf, bcs_resp, dev, "AT+BCS=%s", codecs_string);

> +
> +done:
> + hfp_hf_send_command(dev->hf, bcs_resp, dev, cmd);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> int i;
> @@ -1064,6 +1125,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
> hfp_hf_register(dev->hf, cnum_cb, "+CNUM", dev, NULL);
> hfp_hf_register(dev->hf, binp_cb, "+BINP", dev, NULL);
> + hfp_hf_register(dev->hf, bcs_cb, "+BCS", dev, NULL);
>
> if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
> info("hf-client: Could not send AT+COPS=3,0");

--
BR
Szymon Janc

2014-11-18 21:09:32

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:36 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 47
> +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44
> insertions(+), 3 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 73898ea..4338c11 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -674,10 +674,23 @@ done:
>
> static void handle_get_last_vc_tag_num(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + struct device *dev;
> + uint8_t status;
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+BINP=1"))
> + status = HAL_STATUS_SUCCESS;
> + else
> + status = HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_GET_LAST_VOICE_TAG_NUM,
> - HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_GET_LAST_VOICE_TAG_NUM, status);
> }
>
> static void disconnect_watch(void *user_data)
> @@ -994,6 +1007,33 @@ static void cops_cb(struct hfp_context *context, void
> *user_data) sizeof(*ev) + ev->name_len, ev);
> }
>
> +static void binp_cb(struct hfp_context *context, void *user_data)
> +{
> + uint8_t buf[IPC_MTU];
> + struct hal_ev_hf_client_last_void_call_tag_num *ev = (void *) buf;
> + char number[255];

Why 255? According to spec it should be 32 digits max.

> +
> + DBG("");
> +
> + if (!context) {
> + error("hf-client: incorrect COPS response");
> + return;
> + }
> +
> + if (!hfp_context_get_string(context, number, sizeof(number))) {
> + error("hf-client: incorrect COPS response");
> + return;
> + }
> +
> + memset(buf, 0, sizeof(buf));
> + ev->number_len = strlen(number) + 1;
> + memcpy(ev->number, number, ev->number_len);

Could extract directly to ev->number.

> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_CLIENT_LAST_VOICE_CALL_TAG_NUM,
> + sizeof(*ev) + ev->number_len, ev);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> int i;
> @@ -1023,6 +1063,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
> hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
> hfp_hf_register(dev->hf, cnum_cb, "+CNUM", dev, NULL);
> + hfp_hf_register(dev->hf, binp_cb, "+BINP", dev, NULL);
>
> if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
> info("hf-client: Could not send AT+COPS=3,0");

--
BR
Szymon Janc

2014-11-18 20:52:47

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:34 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 73
> ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71
> insertions(+), 2 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 6fe5495..bc3e2cd 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -627,10 +627,26 @@ done:
>
> static void handle_retrieve_subscr_info(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + struct device *dev;
> + uint8_t status;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+CNUM"))
> + status = HAL_STATUS_SUCCESS;
> + else
> + status = HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> HAL_OP_HF_CLIENT_RETRIEVE_SUBSCR_INFO,
> - HAL_STATUS_UNSUPPORTED);
> + status);
> }
>
> static void handle_send_dtmf(const void *buf, uint16_t len)
> @@ -873,6 +889,58 @@ static void ciev_cb(struct hfp_context *context, void
> *user_data) }
> }
>
> +static void cnum_cb(struct hfp_context *context, void *user_data)
> +{
> + uint8_t buf[IPC_MTU];
> + struct hal_ev_hf_client_subscriber_service_info *ev = (void *) buf;
> + char number[16];
> + uint32_t service;

unsigned int

> +
> + DBG("");
> +
> + if (!context) {
> + error("hf-client: incorrect CNUM response");
> + return;
> + }

Should not happen.

> +
> + /* Alpha field is empty string, just skip it*/

missing space before */

> + hfp_context_skip_field(context);
> +
> + if (!hfp_context_get_string(context, number, sizeof(number))) {
> + error("hf-client: Could not get number");
> + return;
> + }
> +
> + /* Type is not used in Android */
> + hfp_context_skip_field(context);
> +
> + /* Speed field is empty string, just skip it*/
> + hfp_context_skip_field(context);
> +
> + if (!hfp_context_get_number(context, &service))
> + return;
> +
> + memset(buf, 0, sizeof(buf));
> + ev->name_len = strlen(number) + 1;
> + memcpy(ev->name, number, ev->name_len);

Could avoid memset and memcpy and extract number directly to ev->name.

> +
> + switch (service) {
> + case 4:
> + ev->type = HAL_HF_CLIENT_SUBSCR_TYPE_VOICE;
> + break;
> + case 5:
> + ev->type = HAL_HF_CLIENT_SUBSCR_TYPE_FAX;
> + break;
> + default:
> + ev->type = HAL_HF_CLIENT_SUBSCR_TYPE_UNKNOWN;
> + break;
> + }
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_CLIENT_SUBSCRIBER_SERVICE_INFO,
> + sizeof(*ev) + ev->name_len, ev);
> +}
> +
> static void cops_cb(struct hfp_context *context, void *user_data)
> {
> uint8_t buf[IPC_MTU];
> @@ -938,6 +1006,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
> hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
> hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
> + hfp_hf_register(dev->hf, cnum_cb, "+CNUM", dev, NULL);
>
> if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
> info("hf-client: Could not send AT+COPS=3,0");

--
BR
Szymon Janc

2014-11-18 20:17:34

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 09/14] android/handsfree-client: Add support to get operator name

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:32 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 58
> ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56
> insertions(+), 2 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index c710b48..2931c5c 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -603,10 +603,26 @@ done:
>
> static void handle_query_operator_name(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + struct device *dev;
> + uint8_t status;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS?"))
> + status = HAL_STATUS_SUCCESS;
> + else
> + status = HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> HAL_OP_HF_CLIENT_QUERY_OPERATOR_NAME,
> - HAL_STATUS_UNSUPPORTED);
> + status);
> }
>
> static void handle_retrieve_subscr_info(const void *buf, uint16_t len)
> @@ -857,6 +873,43 @@ static void ciev_cb(struct hfp_context *context, void
> *user_data) }
> }
>
> +static void cops_cb(struct hfp_context *context, void *user_data)
> +{
> + uint8_t buf[IPC_MTU];
> + struct hal_ev_hf_client_operator_name *ev = (void *) buf;
> + char name[17];
> + uint32_t format;

unsigned int

> +
> + DBG("");
> +
> + if (!context) {
> + error("hf-client: incorrect COPS response");
> + return;
> + }

Not needed.

> +
> + /* Not interested in mode */
> + hfp_context_skip_field(context);
> +
> + if (!hfp_context_get_number(context, &format))
> + return;
> +
> + if (format != 0)
> + info("hf-client: Not correct string format in +COSP");
> +
> + if (!hfp_context_get_string(context, name, sizeof(name))) {
> + error("hf-client: incorrect COPS response");
> + return;
> + }
> +
> + memset(buf, 0, sizeof(buf));

This memset is not really needed since all relevant data is later overwritten.
Maybe just extract name directly to ev->name?

> + ev->name_len = strlen(name) + 1;
> + memcpy(ev->name, name, ev->name_len);
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_OPERATOR_NAME,
> + sizeof(*ev) + ev->name_len, ev);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> int i;
> @@ -884,6 +937,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
> hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
> hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
> + hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
> }
>
> static void slc_chld_cb(struct hfp_context *context, void *user_data)

--
BR
Szymon Janc

2014-11-18 19:55:39

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:31 Lukasz Rymanowski wrote:
> Once SLC is done, Android is ready to get indicators values.
> ---
> android/handsfree-client.c | 19 +++++++++++++++----
> 1 file changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 97202d5..c710b48 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -859,14 +859,24 @@ static void ciev_cb(struct hfp_context *context, void
> *user_data)
>
> static void slc_completed(struct device *dev)
> {
> + int i;
> + struct indicator *ag_ind;
> +
> DBG("");
>
> + ag_ind = dev->ag_ind;
> +
> device_set_state(dev, HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED);
>
> - /*
> - * TODO: Notify Android with indicators, register unsolicited result
> - * handlers
> - */
> + /* Notify Android with indicators */
> + for (i = 0; i < HFP_INDICATOR_LAST; i++) {
> + if (!ag_ind[i].cb)
> + continue;
> +
> + ag_ind[i].cb(ag_ind[i].val);
> + }
> +
> + /* TODO: register unsolicited results handlers */
>
> hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
> hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
> @@ -959,6 +969,7 @@ static void set_indicator_value(uint8_t index, unsigned
> int val, continue;
>
> ag_ind[i].val = val;
> + ag_ind[i].cb(val);

Some indentation issue here.

> return;
> }
> }

--
BR
Szymon Janc

2014-11-18 19:54:15

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 07/14] android/handsfree-client: Add support for +CIEV events

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:30 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 133
> ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132
> insertions(+), 1 deletion(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index d5899b0..97202d5 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -95,11 +95,14 @@ enum hfp_indicator {
> HFP_INDICATOR_LAST
> };
>
> +typedef void (*ciev_func_t)(uint8_t val);
> +
> struct indicator {
> uint8_t index;
> uint32_t min;
> uint32_t max;
> uint32_t val;
> + ciev_func_t cb;
> };
>
> struct hfp_codec {
> @@ -819,7 +822,39 @@ static void clcc_cb(struct hfp_context *context, void
> *user_data) }
>
> ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_EV_HF_CLIENT_CURRENT_CALL, sizeof(*ev), ev);
> + HAL_EV_HF_CLIENT_CURRENT_CALL,
> + sizeof(*ev) + ev->number_len, ev);
> +}

Shouldn't this be part of 06/14 ?

> +
> +static void ciev_cb(struct hfp_context *context, void *user_data)
> +{
> + struct device *dev = user_data;
> + uint32_t index, val;

unsigned int

> + int i;
> +
> + DBG("");
> +
> + if (!context) {
> + error("hf-client: incorrect CLCC response");
> + return;
> + }

Callbacks are guaranteed to be called with valid context, so there is no need
to check that (I think this affects multiple callbacks in other patches as
well).

> +
> + if (!hfp_context_get_number(context, &index))
> + return;
> +
> + if (!hfp_context_get_number(context, &val))
> + return;
> +
> + for (i = 0; i < HFP_INDICATOR_LAST; i++) {
> + if (dev->ag_ind[i].index != index)
> + continue;
> +
> + if (dev->ag_ind[i].cb) {
> + dev->ag_ind[i].val = val;
> + dev->ag_ind[i].cb(val);
> + return;
> + }
> + }
> }
>
> static void slc_completed(struct device *dev)
> @@ -838,6 +873,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
> hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
> hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
> + hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
> }
>
> static void slc_chld_cb(struct hfp_context *context, void *user_data)
> @@ -1008,6 +1044,94 @@ failed:
> slc_error(dev);
> }
>
> +static void ciev_service_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_net_state ev;
> +
> + DBG("");
> +
> + ev.state = val;

This maps to enum so should be sanitized to IPC defines.
(those below as well)

> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_NET_STATE, sizeof(ev), &ev);
> +}
> +
> +static void ciev_call_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_call_indicator ev;
> +
> + DBG("");
> +
> + ev.call = val;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_CALL_INDICATOR, sizeof(ev), &ev);
> +}
> +
> +static void ciev_callsetup_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_call_setup_indicator ev;
> +
> + DBG("");
> +
> + ev.call_setup = val;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_CALL_SETUP_INDICATOR,
> + sizeof(ev), &ev);
> +}
> +
> +static void ciev_callheld_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_call_held_indicator ev;
> +
> + DBG("");
> +
> + ev.call_held = val;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_CALL_HELD_INDICATOR,
> + sizeof(ev), &ev);
> +}
> +
> +static void ciev_signal_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_net_signal_strength ev;
> +
> + DBG("");
> +
> + ev.signal_strength = val;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_NET_SIGNAL_STRENGTH,
> + sizeof(ev), &ev);
> +}
> +
> +static void ciev_roam_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_net_roaming_type ev;
> +
> + DBG("");
> +
> + ev.state = val;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_NET_ROAMING_TYPE,
> + sizeof(ev), &ev);
> +}
> +
> +static void ciev_battchg_cb(uint8_t val)
> +{
> + struct hal_ev_hf_client_battery_level ev;
> +
> + DBG("");
> +
> + ev.battery_level = val;
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_BATTERY_LEVEL, sizeof(ev), &ev);
> +}
> +
> static void set_indicator_parameters(uint8_t index, const char *indicator,
> unsigned int min,
> unsigned int max,
> @@ -1021,6 +1145,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_SERVICE].index = index;
> ag_ind[HFP_INDICATOR_SERVICE].min = min;
> ag_ind[HFP_INDICATOR_SERVICE].max = max;
> + ag_ind[HFP_INDICATOR_SERVICE].cb = ciev_service_cb;
> return;
> }
>
> @@ -1028,6 +1153,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_CALL].index = index;
> ag_ind[HFP_INDICATOR_CALL].min = min;
> ag_ind[HFP_INDICATOR_CALL].max = max;
> + ag_ind[HFP_INDICATOR_CALL].cb = ciev_call_cb;
> return;
> }
>
> @@ -1035,6 +1161,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_CALLSETUP].index = index;
> ag_ind[HFP_INDICATOR_CALLSETUP].min = min;
> ag_ind[HFP_INDICATOR_CALLSETUP].max = max;
> + ag_ind[HFP_INDICATOR_CALLSETUP].cb = ciev_callsetup_cb;
> return;
> }
>
> @@ -1042,6 +1169,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_CALLHELD].index = index;
> ag_ind[HFP_INDICATOR_CALLHELD].min = min;
> ag_ind[HFP_INDICATOR_CALLHELD].max = max;
> + ag_ind[HFP_INDICATOR_CALLHELD].cb = ciev_callheld_cb;
> return;
> }
>
> @@ -1049,6 +1177,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_SIGNAL].index = index;
> ag_ind[HFP_INDICATOR_SIGNAL].min = min;
> ag_ind[HFP_INDICATOR_SIGNAL].max = max;
> + ag_ind[HFP_INDICATOR_SIGNAL].cb = ciev_signal_cb;
> return;
> }
>
> @@ -1056,6 +1185,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_ROAM].index = index;
> ag_ind[HFP_INDICATOR_ROAM].min = min;
> ag_ind[HFP_INDICATOR_ROAM].max = max;
> + ag_ind[HFP_INDICATOR_ROAM].cb = ciev_roam_cb;
> return;
> }
>
> @@ -1063,6 +1193,7 @@ static void set_indicator_parameters(uint8_t index,
> const char *indicator, ag_ind[HFP_INDICATOR_BATTCHG].index = index;
> ag_ind[HFP_INDICATOR_BATTCHG].min = min;
> ag_ind[HFP_INDICATOR_BATTCHG].max = max;
> + ag_ind[HFP_INDICATOR_BATTCHG].cb = ciev_battchg_cb;
> return;
> }

--
BR
Szymon Janc

2014-11-18 16:29:57

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 06/14] android/handsfree-client: Add handling +CLCC

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:29 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 64 insertions(+)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index b058a39..d5899b0 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -591,6 +591,7 @@ static void handle_query_current_calls(const void *buf, uint16_t len)
> status = HAL_STATUS_SUCCESS;
> else
> status = HAL_STATUS_FAILED;
> +


unrelated

> done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> HAL_OP_HF_CLIENT_QUERY_CURRENT_CALLS,
> @@ -759,6 +760,68 @@ static void brth_cb(struct hfp_context *context, void *user_data)
> sizeof(ev), &ev);
> }
>
> +static void clcc_cb(struct hfp_context *context, void *user_data)
> +{
> + uint8_t buf[IPC_MTU];
> + struct hal_ev_hf_client_current_call *ev = (void *) buf;
> + uint32_t val;

unsigned int

> + char number[20];
> +
> + DBG("");
> +
> + memset(buf, 0, sizeof(buf));
> +
> + /*TODO: Shall we verify received values? */
> +
> + if (!context) {
> + error("hf-client: incorrect CLCC response");
> + return;
> + }
> +
> + if (!hfp_context_get_number(context, &val)) {
> + error("hf-client: Could not get index");
> + return;
> + }
> +
> + ev->index = (uint8_t)val;

If cast is really needed then there should be space after )

> +
> + if (!hfp_context_get_number(context, &val)) {
> + error("hf-client: Could not get direction");
> + return;
> + }
> +
> + ev->direction = val;

Those maps to enums so should be sanitized.

> +
> + if (!hfp_context_get_number(context, &val)) {
> + error("hf-client: Could not get callstate");
> + return;
> + }
> +
> + ev->call_state = val;

ditto.

> +
> + /* Next field is MODE but Android is not interested in this. Skip it */
> + if (!hfp_context_get_number(context, &val)) {
> + error("hf-client: Could not get mode");
> + return;
> + }
> +
> + if (!hfp_context_get_number(context, &val)) {
> + error("hf-client: Could not get multiparty");
> + return;
> + }
> +
> + ev->multiparty = val;

ditto.

> +
> + if (hfp_context_get_string(context, number,
> + (uint8_t) sizeof(number))) {

Why this cast?

> + ev->number_len = strlen(number) + 1;
> + memcpy(ev->number, number, ev->number_len);
> + }
> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_CURRENT_CALL, sizeof(*ev), ev);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> DBG("");
> @@ -774,6 +837,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
> hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
> hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
> + hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
> }
>
> static void slc_chld_cb(struct hfp_context *context, void *user_data)
>

--
Best regards,
Szymon Janc

2014-11-18 16:24:30

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 04/14] android/handsfree-client: Add call action implementation

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:27 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 99 +++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 97 insertions(+), 2 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index 4dfe9fb..97ff228 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -499,9 +499,79 @@ done:
>
> static void handle_call_action(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + const struct hal_cmd_hf_client_call_action *cmd = buf;
> + struct device *dev;
> + uint8_t status;
> + bool ret;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + switch (cmd->action) {
> + case HAL_HF_CLIENT_ACTION_CHLD_0:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHLD=0");
> + break;
> + case HAL_HF_CLIENT_ACTION_CHLD_1:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHLD=1");
> + break;
> + case HAL_HF_CLIENT_ACTION_CHLD_2:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb,
> + NULL, "AT+CHLD=2");
> + break;
> + case HAL_HF_CLIENT_ACTION_CHLD_3:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHLD=3");
> + break;
> + case HAL_HF_CLIENT_ACTION_CHLD_4:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHLD=4");
> + break;
> + case HAL_HF_CLIENT_ACTION_CHLD_1x:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHLD=1%d", cmd->index);

cmd->index is unsigned type. (BTW it seems to be int on HAL API, should
we update IPC to match this..?)

> + break;
> + case HAL_HF_CLIENT_ACTION_CHLD_2x:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHLD=2%d", cmd->index);
> + break;
> + case HAL_HF_CLIENT_ACTION_ATA:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "ATA");
> + break;
> + case HAL_HF_CLIENT_ACTION_CHUP:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+CHUP");
> + break;
> + case HAL_HF_CLIENT_ACTION_BRTH_0:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+BTRH=0");
> + break;
> + case HAL_HF_CLIENT_ACTION_BRTH_1:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+BTRH=1");
> + break;
> + case HAL_HF_CLIENT_ACTION_BRTH_2:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+BTRH=2");
> + break;
> + default:
> + error("hf-client: Unknown action %d", cmd->action);
> + ret = false;
> + break;
> + }
> +
> + status = ret ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_CALL_ACTION, HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_CALL_ACTION, status);
> }
>
> static void handle_query_current_calls(const void *buf, uint16_t len)
> @@ -650,6 +720,30 @@ static void vgs_cb(struct hfp_context *context, void *user_data)
> HAL_EV_CLIENT_VOLUME_CHANGED, sizeof(ev), &ev);
> }
>
> +static void brth_cb(struct hfp_context *context, void *user_data)
> +{
> + struct hal_ev_hf_client_response_and_hold_status ev;
> + uint32_t val;

unsigned int

> +
> + DBG("");
> +
> + if (!context) {
> + error("hf-client: incorrect BTRH response");
> + return;
> + }
> +
> + if (!hfp_context_get_number(context, &val)) {
> + error("hf-client: incorrect BTRH response. Can not get val");
> + return;
> + }
> +
> + ev.status = val;

Value should be verified with IPC type cause it is later mapped to enum.

> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_RESPONSE_AND_HOLD_STATUS,
> + sizeof(ev), &ev);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> DBG("");
> @@ -664,6 +758,7 @@ static void slc_completed(struct device *dev)
> hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
> hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
> hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
> + hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
> }
>
> static void slc_chld_cb(struct hfp_context *context, void *user_data)
>

--
Best regards,
Szymon Janc

2014-11-18 16:18:57

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 03/14] android/handsfree-client: Add handling dial command

On Wednesday 12 of November 2014 11:49:26 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 66 +++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 57 insertions(+), 9 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index e498f89..4dfe9fb 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -429,24 +429,72 @@ done:
> static void handle_dial(const void *buf, uint16_t len)
> {
> const struct hal_cmd_hf_client_dial *cmd = buf;
> + struct device *dev;
> + uint8_t status;
> + bool ret;
>
> - if (len != sizeof(*cmd) + cmd->number_len) {
> - error("Malformed number data, size (%u bytes), terminating",
> - len);
> - raise(SIGTERM);
> - return;
> + DBG("");
> +
> + if (len != sizeof(*cmd) + cmd->number_len)
> + goto failed;
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> }
>
> - DBG("Not Implemented");
> + if (cmd->number_len > 0) {
> + if (cmd->number[cmd->number_len - 1] != '\0')
> + goto failed;
> +
> + DBG("Dialing %s", cmd->number);
> +
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "ATD%s;", cmd->number);
> + } else {
> + DBG("Redialing");
> +
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+BLDN");
> + }
> +
> + status = ret ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_DIAL, HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_DIAL, status);
> +
> + return;
> +
> +failed:
> + error("Malformed number data, size (%u bytes), terminating", len);
> + raise(SIGTERM);
> }
>
> static void handle_dial_memory(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + const struct hal_cmd_hf_client_dial_memory *cmd = buf;
> + struct device *dev;
> + uint8_t status;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }

Check if cmd->location is not < 0 (just in case).

> +
> + if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL , "ATD>%d;",
> + cmd->location))
> + status = HAL_STATUS_SUCCESS;
> + else
> + status = HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_DIAL_MEMORY, HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_DIAL_MEMORY, status);
> }
>
> static void handle_call_action(const void *buf, uint16_t len)
>

--
Best regards,
Szymon Janc

2014-11-18 16:12:51

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 02/14] android/handsfree-client: Add volume control handling

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:25 Lukasz Rymanowski wrote:
> ---
> android/handsfree-client.c | 65 ++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 63 insertions(+), 2 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index d8b0bb1..e498f89 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -391,10 +391,39 @@ done:
>
> static void handle_volume_control(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + const struct hal_cmd_hf_client_volume_control *cmd = buf;
> + struct device *dev;
> + uint8_t status;
> + bool ret;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }

Clip value to 15 here (just in case).

> +
> + switch (cmd->type) {
> + case HF_CLIENT_VOLUME_TYPE_SPEAKER:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+VGS=%d", cmd->volume);

Please use %u for printing unsigned types.

> + break;
> + case HF_CLIENT_VOLUME_TYPE_MIC:
> + ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
> + "AT+VGM=%d", cmd->volume);
> + break;
> + default:
> + ret = false;
> + break;
> + }
> +
> + status = ret ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> HAL_OP_HF_CLIENT_VOLUME_CONTROL,
> - HAL_STATUS_UNSUPPORTED);
> + status);
> }
>
> static void handle_dial(const void *buf, uint16_t len)
> @@ -543,6 +572,36 @@ static void bvra_cb(struct hfp_context *context, void *user_data)
> HAL_EV_HF_CLIENT_VR_STATE, sizeof(ev), &ev);
> }
>
> +static void vgm_cb(struct hfp_context *context, void *user_data)
> +{
> + struct hal_ev_hf_client_volume_changed ev;
> + uint32_t val;

Unsigned int here.

> +
> + if (!hfp_context_get_number(context, &val))
> + return;
> +
> + ev.type = HF_CLIENT_VOLUME_TYPE_MIC;
> + ev.volume = val;

Consider clipping this to 15.

> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_VR_STATE, sizeof(ev), &ev);
> +}
> +
> +static void vgs_cb(struct hfp_context *context, void *user_data)
> +{
> + struct hal_ev_hf_client_volume_changed ev;
> + uint32_t val;

Unsigned int here.

> +
> + if (!hfp_context_get_number(context, &val))
> + return;
> +
> + ev.type = HF_CLIENT_VOLUME_TYPE_SPEAKER;
> + ev.volume = val;

Consider clipping this to 15.

> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_CLIENT_VOLUME_CHANGED, sizeof(ev), &ev);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> DBG("");
> @@ -555,6 +614,8 @@ static void slc_completed(struct device *dev)
> */
>
> hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
> + hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
> + hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
> }
>
> static void slc_chld_cb(struct hfp_context *context, void *user_data)
>

--
Best regards,
Szymon Janc

2014-11-18 16:04:57

by Szymon Janc

[permalink] [raw]
Subject: Re: [PATCH 01/14] android/handsfree-client: Add handle start/stop vr

Hi Łukasz,

On Wednesday 12 of November 2014 11:49:24 Lukasz Rymanowski wrote:
> This patch implements start/stop voice recogniction command handling.
> It also introduce find_default_device which returns connected device.
>
> Note that for now we support only one device as this is HAL limitation
> ---
> android/handsfree-client.c | 106 +++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 102 insertions(+), 4 deletions(-)
>
> diff --git a/android/handsfree-client.c b/android/handsfree-client.c
> index c576ae8..d8b0bb1 100644
> --- a/android/handsfree-client.c
> +++ b/android/handsfree-client.c
> @@ -135,6 +135,11 @@ static uint32_t hfp_hf_record_id = 0;
> static struct queue *devices = NULL;
> static GIOChannel *hfp_hf_server = NULL;
>
> +static struct device *find_default_device(void)
> +{
> + return queue_peek_head(devices);
> +}
> +
> static bool match_by_bdaddr(const void *data, const void *user_data)
> {
> const bdaddr_t *addr1 = data;
> @@ -293,18 +298,95 @@ static void handle_disconnect_audio(const void *buf, uint16_t len)
> HAL_STATUS_UNSUPPORTED);
> }
>
> +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)
> {
> - DBG("Not Implemented");
> + struct device *dev;
> + uint8_t status;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+BVRA=1"))
> + status = HAL_STATUS_SUCCESS;
> + else
> + status = HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_START_VR, HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_START_VR, status);
> }
>
> static void handle_stop_vr(const void *buf, uint16_t len)
> {
> - DBG("Not Implemented");
> + struct device *dev;
> + uint8_t status;
> +
> + DBG("");
> +
> + dev = find_default_device();
> + if (!dev) {
> + status = HAL_STATUS_FAILED;
> + goto done;
> + }
> +
> + if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+BVRA=0"))
> + status = HAL_STATUS_SUCCESS;
> + else
> + status = HAL_STATUS_FAILED;
> +
> +done:
> ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> - HAL_OP_HF_CLIENT_STOP_VR, HAL_STATUS_UNSUPPORTED);
> + HAL_OP_HF_CLIENT_STOP_VR, status);
> }
>
> static void handle_volume_control(const void *buf, uint16_t len)
> @@ -447,6 +529,20 @@ static void get_local_codecs_string(struct device *dev, char *buf,
> }
> }
>
> +static void bvra_cb(struct hfp_context *context, void *user_data)
> +{
> + struct hal_ev_hf_client_vr_state ev;
> + uint32_t val;

Should be unsigned int.

> +
> + if (!hfp_context_get_number(context, &val))
> + return;
> +
> + ev.state = val ? HAL_HF_CLIENT_VR_STARTED : HAL_HF_CLIENT_VR_STOPPED;

We should verify if val is valid ie.
if (!hfp_context_get_number(context, &val) || val > 1)
return;


> +
> + ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
> + HAL_EV_HF_CLIENT_VR_STATE, sizeof(ev), &ev);
> +}
> +
> static void slc_completed(struct device *dev)
> {
> DBG("");
> @@ -457,6 +553,8 @@ static void slc_completed(struct device *dev)
> * TODO: Notify Android with indicators, register unsolicited result
> * handlers
> */
> +
> + hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
> }
>
> static void slc_chld_cb(struct hfp_context *context, void *user_data)
>

--
Best regards,
Szymon Janc

2014-11-12 10:49:37

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 14/14] android/handsfree-client: Implement codec negotiations

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 4338c11..74d1547 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -116,6 +116,7 @@ struct device {
struct hfp_hf *hf;
uint8_t state;

+ uint8_t negotiated_codec;
uint32_t features;
struct hfp_codec codecs[2];

@@ -1034,6 +1035,66 @@ static void binp_cb(struct hfp_context *context, void *user_data)
sizeof(*ev) + ev->number_len, ev);
}

+static bool is_codec_supported_localy(struct device *dev, uint8_t codec)
+{
+ int i;
+
+ for (i = 0; i < CODECS_COUNT; i++) {
+ if (dev->codecs[i].type != codec)
+ continue;
+
+ return dev->codecs[i].local_supported;
+ }
+
+ return false;
+}
+
+static void bcs_resp(enum hfp_result result, enum hfp_error cme_err,
+ void *user_data)
+{
+ DBG("%d", result);
+}
+
+static void bcs_cb(struct hfp_context *context, void *user_data)
+{
+ struct device *dev = user_data;
+ uint32_t codec;
+ char codecs_string[2 * CODECS_COUNT + 1];
+ char cmd[sizeof(codecs_string) + 7];
+
+ DBG("");
+
+ if (!context) {
+ error("hf-client: incorrect BCS response");
+ return;
+ }
+
+ memset(cmd, 0, sizeof(cmd));
+
+ if (!hfp_context_get_number(context, &codec))
+ goto failed;
+
+ if (!is_codec_supported_localy(dev, codec))
+ goto failed;
+
+ sprintf(cmd, "AT+BCS=%d", codec);
+
+ dev->negotiated_codec = codec;
+
+ goto done;
+
+failed:
+ error("hf-client: Could not get codec");
+
+ strcpy(cmd, "AT+BCS=");
+
+ get_local_codecs_string(dev, codecs_string, sizeof(codecs_string));
+ strcat(cmd, codecs_string);
+
+done:
+ hfp_hf_send_command(dev->hf, bcs_resp, dev, cmd);
+}
+
static void slc_completed(struct device *dev)
{
int i;
@@ -1064,6 +1125,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
hfp_hf_register(dev->hf, cnum_cb, "+CNUM", dev, NULL);
hfp_hf_register(dev->hf, binp_cb, "+BINP", dev, NULL);
+ hfp_hf_register(dev->hf, bcs_cb, "+BCS", dev, NULL);

if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
info("hf-client: Could not send AT+COPS=3,0");
--
1.8.4


2014-11-12 10:49:25

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 02/14] android/handsfree-client: Add volume control handling

---
android/handsfree-client.c | 65 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 63 insertions(+), 2 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index d8b0bb1..e498f89 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -391,10 +391,39 @@ done:

static void handle_volume_control(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ const struct hal_cmd_hf_client_volume_control *cmd = buf;
+ struct device *dev;
+ uint8_t status;
+ bool ret;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ switch (cmd->type) {
+ case HF_CLIENT_VOLUME_TYPE_SPEAKER:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+VGS=%d", cmd->volume);
+ break;
+ case HF_CLIENT_VOLUME_TYPE_MIC:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+VGM=%d", cmd->volume);
+ break;
+ default:
+ ret = false;
+ break;
+ }
+
+ status = ret ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
HAL_OP_HF_CLIENT_VOLUME_CONTROL,
- HAL_STATUS_UNSUPPORTED);
+ status);
}

static void handle_dial(const void *buf, uint16_t len)
@@ -543,6 +572,36 @@ static void bvra_cb(struct hfp_context *context, void *user_data)
HAL_EV_HF_CLIENT_VR_STATE, sizeof(ev), &ev);
}

+static void vgm_cb(struct hfp_context *context, void *user_data)
+{
+ struct hal_ev_hf_client_volume_changed ev;
+ uint32_t val;
+
+ if (!hfp_context_get_number(context, &val))
+ return;
+
+ ev.type = HF_CLIENT_VOLUME_TYPE_MIC;
+ ev.volume = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_VR_STATE, sizeof(ev), &ev);
+}
+
+static void vgs_cb(struct hfp_context *context, void *user_data)
+{
+ struct hal_ev_hf_client_volume_changed ev;
+ uint32_t val;
+
+ if (!hfp_context_get_number(context, &val))
+ return;
+
+ ev.type = HF_CLIENT_VOLUME_TYPE_SPEAKER;
+ ev.volume = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_CLIENT_VOLUME_CHANGED, sizeof(ev), &ev);
+}
+
static void slc_completed(struct device *dev)
{
DBG("");
@@ -555,6 +614,8 @@ static void slc_completed(struct device *dev)
*/

hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
+ hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
+ hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
--
1.8.4


2014-11-12 10:49:24

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 01/14] android/handsfree-client: Add handle start/stop vr

This patch implements start/stop voice recogniction command handling.
It also introduce find_default_device which returns connected device.

Note that for now we support only one device as this is HAL limitation
---
android/handsfree-client.c | 106 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 102 insertions(+), 4 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index c576ae8..d8b0bb1 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -135,6 +135,11 @@ static uint32_t hfp_hf_record_id = 0;
static struct queue *devices = NULL;
static GIOChannel *hfp_hf_server = NULL;

+static struct device *find_default_device(void)
+{
+ return queue_peek_head(devices);
+}
+
static bool match_by_bdaddr(const void *data, const void *user_data)
{
const bdaddr_t *addr1 = data;
@@ -293,18 +298,95 @@ static void handle_disconnect_audio(const void *buf, uint16_t len)
HAL_STATUS_UNSUPPORTED);
}

+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)
{
- DBG("Not Implemented");
+ struct device *dev;
+ uint8_t status;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+BVRA=1"))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_START_VR, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_START_VR, status);
}

static void handle_stop_vr(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ struct device *dev;
+ uint8_t status;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+BVRA=0"))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_STOP_VR, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_STOP_VR, status);
}

static void handle_volume_control(const void *buf, uint16_t len)
@@ -447,6 +529,20 @@ static void get_local_codecs_string(struct device *dev, char *buf,
}
}

+static void bvra_cb(struct hfp_context *context, void *user_data)
+{
+ struct hal_ev_hf_client_vr_state ev;
+ uint32_t val;
+
+ if (!hfp_context_get_number(context, &val))
+ return;
+
+ ev.state = val ? HAL_HF_CLIENT_VR_STARTED : HAL_HF_CLIENT_VR_STOPPED;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_VR_STATE, sizeof(ev), &ev);
+}
+
static void slc_completed(struct device *dev)
{
DBG("");
@@ -457,6 +553,8 @@ static void slc_completed(struct device *dev)
* TODO: Notify Android with indicators, register unsolicited result
* handlers
*/
+
+ hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
--
1.8.4


2014-11-12 10:49:26

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 03/14] android/handsfree-client: Add handling dial command

---
android/handsfree-client.c | 66 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 57 insertions(+), 9 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index e498f89..4dfe9fb 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -429,24 +429,72 @@ done:
static void handle_dial(const void *buf, uint16_t len)
{
const struct hal_cmd_hf_client_dial *cmd = buf;
+ struct device *dev;
+ uint8_t status;
+ bool ret;

- if (len != sizeof(*cmd) + cmd->number_len) {
- error("Malformed number data, size (%u bytes), terminating",
- len);
- raise(SIGTERM);
- return;
+ DBG("");
+
+ if (len != sizeof(*cmd) + cmd->number_len)
+ goto failed;
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
}

- DBG("Not Implemented");
+ if (cmd->number_len > 0) {
+ if (cmd->number[cmd->number_len - 1] != '\0')
+ goto failed;
+
+ DBG("Dialing %s", cmd->number);
+
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "ATD%s;", cmd->number);
+ } else {
+ DBG("Redialing");
+
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+BLDN");
+ }
+
+ status = ret ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_DIAL, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_DIAL, status);
+
+ return;
+
+failed:
+ error("Malformed number data, size (%u bytes), terminating", len);
+ raise(SIGTERM);
}

static void handle_dial_memory(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ const struct hal_cmd_hf_client_dial_memory *cmd = buf;
+ struct device *dev;
+ uint8_t status;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL , "ATD>%d;",
+ cmd->location))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_DIAL_MEMORY, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_DIAL_MEMORY, status);
}

static void handle_call_action(const void *buf, uint16_t len)
--
1.8.4


2014-11-12 10:49:27

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 04/14] android/handsfree-client: Add call action implementation

---
android/handsfree-client.c | 99 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 4dfe9fb..97ff228 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -499,9 +499,79 @@ done:

static void handle_call_action(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ const struct hal_cmd_hf_client_call_action *cmd = buf;
+ struct device *dev;
+ uint8_t status;
+ bool ret;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ switch (cmd->action) {
+ case HAL_HF_CLIENT_ACTION_CHLD_0:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHLD=0");
+ break;
+ case HAL_HF_CLIENT_ACTION_CHLD_1:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHLD=1");
+ break;
+ case HAL_HF_CLIENT_ACTION_CHLD_2:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb,
+ NULL, "AT+CHLD=2");
+ break;
+ case HAL_HF_CLIENT_ACTION_CHLD_3:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHLD=3");
+ break;
+ case HAL_HF_CLIENT_ACTION_CHLD_4:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHLD=4");
+ break;
+ case HAL_HF_CLIENT_ACTION_CHLD_1x:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHLD=1%d", cmd->index);
+ break;
+ case HAL_HF_CLIENT_ACTION_CHLD_2x:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHLD=2%d", cmd->index);
+ break;
+ case HAL_HF_CLIENT_ACTION_ATA:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "ATA");
+ break;
+ case HAL_HF_CLIENT_ACTION_CHUP:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+CHUP");
+ break;
+ case HAL_HF_CLIENT_ACTION_BRTH_0:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+BTRH=0");
+ break;
+ case HAL_HF_CLIENT_ACTION_BRTH_1:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+BTRH=1");
+ break;
+ case HAL_HF_CLIENT_ACTION_BRTH_2:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+BTRH=2");
+ break;
+ default:
+ error("hf-client: Unknown action %d", cmd->action);
+ ret = false;
+ break;
+ }
+
+ status = ret ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_CALL_ACTION, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_CALL_ACTION, status);
}

static void handle_query_current_calls(const void *buf, uint16_t len)
@@ -650,6 +720,30 @@ static void vgs_cb(struct hfp_context *context, void *user_data)
HAL_EV_CLIENT_VOLUME_CHANGED, sizeof(ev), &ev);
}

+static void brth_cb(struct hfp_context *context, void *user_data)
+{
+ struct hal_ev_hf_client_response_and_hold_status ev;
+ uint32_t val;
+
+ DBG("");
+
+ if (!context) {
+ error("hf-client: incorrect BTRH response");
+ return;
+ }
+
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: incorrect BTRH response. Can not get val");
+ return;
+ }
+
+ ev.status = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_RESPONSE_AND_HOLD_STATUS,
+ sizeof(ev), &ev);
+}
+
static void slc_completed(struct device *dev)
{
DBG("");
@@ -664,6 +758,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
+ hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
--
1.8.4


2014-11-12 10:49:35

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 12/14] android/handsfree-client: Implement send DTMF codes

---
android/handsfree-client.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index bc3e2cd..73898ea 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -651,9 +651,25 @@ done:

static void handle_send_dtmf(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ const struct hal_cmd_hf_client_send_dtmf *cmd = buf;
+ struct device *dev;
+ uint8_t status;
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+VTS=%c",
+ (char) cmd->tone))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_SEND_DTMF, HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_SEND_DTMF, status);
}

static void handle_get_last_vc_tag_num(const void *buf, uint16_t len)
--
1.8.4


2014-11-12 10:49:31

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup

Once SLC is done, Android is ready to get indicators values.
---
android/handsfree-client.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 97202d5..c710b48 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -859,14 +859,24 @@ static void ciev_cb(struct hfp_context *context, void *user_data)

static void slc_completed(struct device *dev)
{
+ int i;
+ struct indicator *ag_ind;
+
DBG("");

+ ag_ind = dev->ag_ind;
+
device_set_state(dev, HAL_HF_CLIENT_CONN_STATE_SLC_CONNECTED);

- /*
- * TODO: Notify Android with indicators, register unsolicited result
- * handlers
- */
+ /* Notify Android with indicators */
+ for (i = 0; i < HFP_INDICATOR_LAST; i++) {
+ if (!ag_ind[i].cb)
+ continue;
+
+ ag_ind[i].cb(ag_ind[i].val);
+ }
+
+ /* TODO: register unsolicited results handlers */

hfp_hf_register(dev->hf, bvra_cb, "+BRVA", dev, NULL);
hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
@@ -959,6 +969,7 @@ static void set_indicator_value(uint8_t index, unsigned int val,
continue;

ag_ind[i].val = val;
+ ag_ind[i].cb(val);
return;
}
}
--
1.8.4


2014-11-12 10:49:29

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 06/14] android/handsfree-client: Add handling +CLCC

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index b058a39..d5899b0 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -591,6 +591,7 @@ static void handle_query_current_calls(const void *buf, uint16_t len)
status = HAL_STATUS_SUCCESS;
else
status = HAL_STATUS_FAILED;
+
done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
HAL_OP_HF_CLIENT_QUERY_CURRENT_CALLS,
@@ -759,6 +760,68 @@ static void brth_cb(struct hfp_context *context, void *user_data)
sizeof(ev), &ev);
}

+static void clcc_cb(struct hfp_context *context, void *user_data)
+{
+ uint8_t buf[IPC_MTU];
+ struct hal_ev_hf_client_current_call *ev = (void *) buf;
+ uint32_t val;
+ char number[20];
+
+ DBG("");
+
+ memset(buf, 0, sizeof(buf));
+
+ /*TODO: Shall we verify received values? */
+
+ if (!context) {
+ error("hf-client: incorrect CLCC response");
+ return;
+ }
+
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: Could not get index");
+ return;
+ }
+
+ ev->index = (uint8_t)val;
+
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: Could not get direction");
+ return;
+ }
+
+ ev->direction = val;
+
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: Could not get callstate");
+ return;
+ }
+
+ ev->call_state = val;
+
+ /* Next field is MODE but Android is not interested in this. Skip it */
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: Could not get mode");
+ return;
+ }
+
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: Could not get multiparty");
+ return;
+ }
+
+ ev->multiparty = val;
+
+ if (hfp_context_get_string(context, number,
+ (uint8_t) sizeof(number))) {
+ ev->number_len = strlen(number) + 1;
+ memcpy(ev->number, number, ev->number_len);
+ }
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_CURRENT_CALL, sizeof(*ev), ev);
+}
+
static void slc_completed(struct device *dev)
{
DBG("");
@@ -774,6 +837,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, vgm_cb, "+VGM", dev, NULL);
hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
+ hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
--
1.8.4


2014-11-12 10:49:34

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information

---
android/handsfree-client.c | 73 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 6fe5495..bc3e2cd 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -627,10 +627,26 @@ done:

static void handle_retrieve_subscr_info(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ struct device *dev;
+ uint8_t status;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+CNUM"))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
HAL_OP_HF_CLIENT_RETRIEVE_SUBSCR_INFO,
- HAL_STATUS_UNSUPPORTED);
+ status);
}

static void handle_send_dtmf(const void *buf, uint16_t len)
@@ -873,6 +889,58 @@ static void ciev_cb(struct hfp_context *context, void *user_data)
}
}

+static void cnum_cb(struct hfp_context *context, void *user_data)
+{
+ uint8_t buf[IPC_MTU];
+ struct hal_ev_hf_client_subscriber_service_info *ev = (void *) buf;
+ char number[16];
+ uint32_t service;
+
+ DBG("");
+
+ if (!context) {
+ error("hf-client: incorrect CNUM response");
+ return;
+ }
+
+ /* Alpha field is empty string, just skip it*/
+ hfp_context_skip_field(context);
+
+ if (!hfp_context_get_string(context, number, sizeof(number))) {
+ error("hf-client: Could not get number");
+ return;
+ }
+
+ /* Type is not used in Android */
+ hfp_context_skip_field(context);
+
+ /* Speed field is empty string, just skip it*/
+ hfp_context_skip_field(context);
+
+ if (!hfp_context_get_number(context, &service))
+ return;
+
+ memset(buf, 0, sizeof(buf));
+ ev->name_len = strlen(number) + 1;
+ memcpy(ev->name, number, ev->name_len);
+
+ switch (service) {
+ case 4:
+ ev->type = HAL_HF_CLIENT_SUBSCR_TYPE_VOICE;
+ break;
+ case 5:
+ ev->type = HAL_HF_CLIENT_SUBSCR_TYPE_FAX;
+ break;
+ default:
+ ev->type = HAL_HF_CLIENT_SUBSCR_TYPE_UNKNOWN;
+ break;
+ }
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_CLIENT_SUBSCRIBER_SERVICE_INFO,
+ sizeof(*ev) + ev->name_len, ev);
+}
+
static void cops_cb(struct hfp_context *context, void *user_data)
{
uint8_t buf[IPC_MTU];
@@ -938,6 +1006,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
+ hfp_hf_register(dev->hf, cnum_cb, "+CNUM", dev, NULL);

if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
info("hf-client: Could not send AT+COPS=3,0");
--
1.8.4


2014-11-12 10:49:36

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND

---
android/handsfree-client.c | 47 +++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 73898ea..4338c11 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -674,10 +674,23 @@ done:

static void handle_get_last_vc_tag_num(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ struct device *dev;
+ uint8_t status;
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+BINP=1"))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_OP_HF_CLIENT_GET_LAST_VOICE_TAG_NUM,
- HAL_STATUS_UNSUPPORTED);
+ HAL_OP_HF_CLIENT_GET_LAST_VOICE_TAG_NUM, status);
}

static void disconnect_watch(void *user_data)
@@ -994,6 +1007,33 @@ static void cops_cb(struct hfp_context *context, void *user_data)
sizeof(*ev) + ev->name_len, ev);
}

+static void binp_cb(struct hfp_context *context, void *user_data)
+{
+ uint8_t buf[IPC_MTU];
+ struct hal_ev_hf_client_last_void_call_tag_num *ev = (void *) buf;
+ char number[255];
+
+ DBG("");
+
+ if (!context) {
+ error("hf-client: incorrect COPS response");
+ return;
+ }
+
+ if (!hfp_context_get_string(context, number, sizeof(number))) {
+ error("hf-client: incorrect COPS response");
+ return;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ ev->number_len = strlen(number) + 1;
+ memcpy(ev->number, number, ev->number_len);
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_CLIENT_LAST_VOICE_CALL_TAG_NUM,
+ sizeof(*ev) + ev->number_len, ev);
+}
+
static void slc_completed(struct device *dev)
{
int i;
@@ -1023,6 +1063,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
hfp_hf_register(dev->hf, cnum_cb, "+CNUM", dev, NULL);
+ hfp_hf_register(dev->hf, binp_cb, "+BINP", dev, NULL);

if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
info("hf-client: Could not send AT+COPS=3,0");
--
1.8.4


2014-11-12 10:49:32

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 09/14] android/handsfree-client: Add support to get operator name

---
android/handsfree-client.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 56 insertions(+), 2 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index c710b48..2931c5c 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -603,10 +603,26 @@ done:

static void handle_query_operator_name(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ struct device *dev;
+ uint8_t status;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS?"))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
HAL_OP_HF_CLIENT_QUERY_OPERATOR_NAME,
- HAL_STATUS_UNSUPPORTED);
+ status);
}

static void handle_retrieve_subscr_info(const void *buf, uint16_t len)
@@ -857,6 +873,43 @@ static void ciev_cb(struct hfp_context *context, void *user_data)
}
}

+static void cops_cb(struct hfp_context *context, void *user_data)
+{
+ uint8_t buf[IPC_MTU];
+ struct hal_ev_hf_client_operator_name *ev = (void *) buf;
+ char name[17];
+ uint32_t format;
+
+ DBG("");
+
+ if (!context) {
+ error("hf-client: incorrect COPS response");
+ return;
+ }
+
+ /* Not interested in mode */
+ hfp_context_skip_field(context);
+
+ if (!hfp_context_get_number(context, &format))
+ return;
+
+ if (format != 0)
+ info("hf-client: Not correct string format in +COSP");
+
+ if (!hfp_context_get_string(context, name, sizeof(name))) {
+ error("hf-client: incorrect COPS response");
+ return;
+ }
+
+ memset(buf, 0, sizeof(buf));
+ ev->name_len = strlen(name) + 1;
+ memcpy(ev->name, name, ev->name_len);
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_OPERATOR_NAME,
+ sizeof(*ev) + ev->name_len, ev);
+}
+
static void slc_completed(struct device *dev)
{
int i;
@@ -884,6 +937,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
+ hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
--
1.8.4


2014-11-12 10:49:33

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 10/14] android/handsfree-client: Send to AG that we do support long name

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 2931c5c..6fe5495 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -938,6 +938,9 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
hfp_hf_register(dev->hf, cops_cb, "+COPS", dev, NULL);
+
+ if (!hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+COPS=3,0"))
+ info("hf-client: Could not send AT+COPS=3,0");
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
--
1.8.4


2014-11-12 10:49:30

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 07/14] android/handsfree-client: Add support for +CIEV events

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index d5899b0..97202d5 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -95,11 +95,14 @@ enum hfp_indicator {
HFP_INDICATOR_LAST
};

+typedef void (*ciev_func_t)(uint8_t val);
+
struct indicator {
uint8_t index;
uint32_t min;
uint32_t max;
uint32_t val;
+ ciev_func_t cb;
};

struct hfp_codec {
@@ -819,7 +822,39 @@ static void clcc_cb(struct hfp_context *context, void *user_data)
}

ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
- HAL_EV_HF_CLIENT_CURRENT_CALL, sizeof(*ev), ev);
+ HAL_EV_HF_CLIENT_CURRENT_CALL,
+ sizeof(*ev) + ev->number_len, ev);
+}
+
+static void ciev_cb(struct hfp_context *context, void *user_data)
+{
+ struct device *dev = user_data;
+ uint32_t index, val;
+ int i;
+
+ DBG("");
+
+ if (!context) {
+ error("hf-client: incorrect CLCC response");
+ return;
+ }
+
+ if (!hfp_context_get_number(context, &index))
+ return;
+
+ if (!hfp_context_get_number(context, &val))
+ return;
+
+ for (i = 0; i < HFP_INDICATOR_LAST; i++) {
+ if (dev->ag_ind[i].index != index)
+ continue;
+
+ if (dev->ag_ind[i].cb) {
+ dev->ag_ind[i].val = val;
+ dev->ag_ind[i].cb(val);
+ return;
+ }
+ }
}

static void slc_completed(struct device *dev)
@@ -838,6 +873,7 @@ static void slc_completed(struct device *dev)
hfp_hf_register(dev->hf, vgs_cb, "+VGS", dev, NULL);
hfp_hf_register(dev->hf, brth_cb, "+BTRH", dev, NULL);
hfp_hf_register(dev->hf, clcc_cb, "+CLCC", dev, NULL);
+ hfp_hf_register(dev->hf, ciev_cb, "+CIEV", dev, NULL);
}

static void slc_chld_cb(struct hfp_context *context, void *user_data)
@@ -1008,6 +1044,94 @@ failed:
slc_error(dev);
}

+static void ciev_service_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_net_state ev;
+
+ DBG("");
+
+ ev.state = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_NET_STATE, sizeof(ev), &ev);
+}
+
+static void ciev_call_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_call_indicator ev;
+
+ DBG("");
+
+ ev.call = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_CALL_INDICATOR, sizeof(ev), &ev);
+}
+
+static void ciev_callsetup_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_call_setup_indicator ev;
+
+ DBG("");
+
+ ev.call_setup = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_CALL_SETUP_INDICATOR,
+ sizeof(ev), &ev);
+}
+
+static void ciev_callheld_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_call_held_indicator ev;
+
+ DBG("");
+
+ ev.call_held = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_CALL_HELD_INDICATOR,
+ sizeof(ev), &ev);
+}
+
+static void ciev_signal_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_net_signal_strength ev;
+
+ DBG("");
+
+ ev.signal_strength = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_NET_SIGNAL_STRENGTH,
+ sizeof(ev), &ev);
+}
+
+static void ciev_roam_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_net_roaming_type ev;
+
+ DBG("");
+
+ ev.state = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_NET_ROAMING_TYPE,
+ sizeof(ev), &ev);
+}
+
+static void ciev_battchg_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_battery_level ev;
+
+ DBG("");
+
+ ev.battery_level = val;
+
+ ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
+ HAL_EV_HF_CLIENT_BATTERY_LEVEL, sizeof(ev), &ev);
+}
+
static void set_indicator_parameters(uint8_t index, const char *indicator,
unsigned int min,
unsigned int max,
@@ -1021,6 +1145,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_SERVICE].index = index;
ag_ind[HFP_INDICATOR_SERVICE].min = min;
ag_ind[HFP_INDICATOR_SERVICE].max = max;
+ ag_ind[HFP_INDICATOR_SERVICE].cb = ciev_service_cb;
return;
}

@@ -1028,6 +1153,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_CALL].index = index;
ag_ind[HFP_INDICATOR_CALL].min = min;
ag_ind[HFP_INDICATOR_CALL].max = max;
+ ag_ind[HFP_INDICATOR_CALL].cb = ciev_call_cb;
return;
}

@@ -1035,6 +1161,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_CALLSETUP].index = index;
ag_ind[HFP_INDICATOR_CALLSETUP].min = min;
ag_ind[HFP_INDICATOR_CALLSETUP].max = max;
+ ag_ind[HFP_INDICATOR_CALLSETUP].cb = ciev_callsetup_cb;
return;
}

@@ -1042,6 +1169,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_CALLHELD].index = index;
ag_ind[HFP_INDICATOR_CALLHELD].min = min;
ag_ind[HFP_INDICATOR_CALLHELD].max = max;
+ ag_ind[HFP_INDICATOR_CALLHELD].cb = ciev_callheld_cb;
return;
}

@@ -1049,6 +1177,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_SIGNAL].index = index;
ag_ind[HFP_INDICATOR_SIGNAL].min = min;
ag_ind[HFP_INDICATOR_SIGNAL].max = max;
+ ag_ind[HFP_INDICATOR_SIGNAL].cb = ciev_signal_cb;
return;
}

@@ -1056,6 +1185,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_ROAM].index = index;
ag_ind[HFP_INDICATOR_ROAM].min = min;
ag_ind[HFP_INDICATOR_ROAM].max = max;
+ ag_ind[HFP_INDICATOR_ROAM].cb = ciev_roam_cb;
return;
}

@@ -1063,6 +1193,7 @@ static void set_indicator_parameters(uint8_t index, const char *indicator,
ag_ind[HFP_INDICATOR_BATTCHG].index = index;
ag_ind[HFP_INDICATOR_BATTCHG].min = min;
ag_ind[HFP_INDICATOR_BATTCHG].max = max;
+ ag_ind[HFP_INDICATOR_BATTCHG].cb = ciev_battchg_cb;
return;
}

--
1.8.4


2014-11-12 10:49:28

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH 05/14] android/handsfree-client: Implement query current calls

---
android/handsfree-client.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 97ff228..b058a39 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -576,10 +576,25 @@ done:

static void handle_query_current_calls(const void *buf, uint16_t len)
{
- DBG("Not Implemented");
+ struct device *dev;
+ uint8_t status;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ if (hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL, "AT+CLCC"))
+ status = HAL_STATUS_SUCCESS;
+ else
+ status = HAL_STATUS_FAILED;
+done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE_CLIENT,
HAL_OP_HF_CLIENT_QUERY_CURRENT_CALLS,
- HAL_STATUS_UNSUPPORTED);
+ status);
}

static void handle_query_operator_name(const void *buf, uint16_t len)
--
1.8.4