2014-11-19 09:43:33

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 00/15] 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.

v2:
* Addressed Szymon comments
* Added patch fixing index type in IPC call action command (01/15)

Lukasz Rymanowski (15):
android/handsfree-client: Fix index type in call action command
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+BINP and +BINP
android/handsfree-client: Implement codec negotiations

android/hal-msg.h | 2 +-
android/handsfree-client.c | 833 +++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 802 insertions(+), 33 deletions(-)

--
1.8.4



2014-11-19 14:09:12

by Szymon Janc

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

Hi Ɓukasz,

On Wednesday 19 of November 2014 10:43:33 Lukasz Rymanowski wrote:
> In this set all mising signaling part is implemented.
> Tested on UPF 49 as well.
>
> SCO part will come in next set.
>
> v2:
> * Addressed Szymon comments
> * Added patch fixing index type in IPC call action command (01/15)
>
> Lukasz Rymanowski (15):
> android/handsfree-client: Fix index type in call action command
> 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+BINP and +BINP
> android/handsfree-client: Implement codec negotiations
>
> android/hal-msg.h | 2 +-
> android/handsfree-client.c | 833 +++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 802 insertions(+), 33 deletions(-)
>

Patch-set applied (with some small fixes), thanks.

--
Best regards,
Szymon Janc

2014-11-19 09:43:43

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 10/15] android/handsfree-client: Add support to get operator name

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index d3a3bd1..6c318fc 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -623,10 +623,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)
@@ -862,6 +878,37 @@ 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];
+ unsigned int format;
+
+ DBG("");
+
+ /* 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;
+ }
+
+ 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;
@@ -889,6 +936,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-19 09:43:48

by Lukasz Rymanowski

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

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index fbee44e..c3d955e 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];

@@ -1021,6 +1022,55 @@ 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)
+{
+ if (result != HFP_RESULT_OK)
+ error("hf-client: Error on AT+BCS (err=%u)", result);
+}
+
+static void bcs_cb(struct hfp_context *context, void *user_data)
+{
+ struct device *dev = user_data;
+ unsigned int codec;
+ char codecs_string[8];
+
+ DBG("");
+
+ if (!hfp_context_get_number(context, &codec))
+ goto failed;
+
+ if (!is_codec_supported_localy(dev, codec))
+ goto failed;
+
+ dev->negotiated_codec = codec;
+
+ hfp_hf_send_command(dev->hf, bcs_resp, dev, "AT+BCS=%d", codec);
+
+ return;
+
+failed:
+ error("hf-client: Could not get codec");
+
+ get_local_codecs_string(dev, codecs_string, sizeof(codecs_string));
+
+ hfp_hf_send_command(dev->hf, bcs_resp, dev, "AT+BCS=%s", codecs_string);
+}
+
static void slc_completed(struct device *dev)
{
int i;
@@ -1051,6 +1101,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-19 09:43:46

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 13/15] 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 eb3e7c3..79e96a1 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -671,9 +671,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-19 09:43:47

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 14/15] android/handsfree-client: Implement handling AT+BINP and +BINP

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 79e96a1..fbee44e 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -694,10 +694,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)
@@ -987,6 +1000,27 @@ 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[33];
+
+ DBG("");
+
+ if (!hfp_context_get_string(context, number, sizeof(number))) {
+ error("hf-client: incorrect COPS response");
+ return;
+ }
+
+ 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;
@@ -1016,6 +1050,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-19 09:43:45

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 12/15] android/handsfree-client: Retrieve subscriber number information

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index b78294a..eb3e7c3 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -647,10 +647,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)
@@ -878,6 +894,52 @@ 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[33];
+ unsigned int service;
+
+ DBG("");
+
+ /* 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;
+
+ 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];
@@ -937,6 +999,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-19 09:43:40

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 07/15] android/handsfree-client: Add handling +CLCC

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 6860bed..79779c2 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -776,6 +776,63 @@ 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;
+ unsigned int val;
+ char number[33];
+
+ DBG("");
+
+ memset(buf, 0, sizeof(buf));
+
+ if (!hfp_context_get_number(context, &val)) {
+ error("hf-client: Could not get index");
+ return;
+ }
+
+ ev->index = val;
+
+ if (!hfp_context_get_number(context, &val) ||
+ val > HAL_HF_CLIENT_DIRECTION_INCOMIGN) {
+ error("hf-client: Could not get direction");
+ return;
+ }
+
+ ev->direction = val;
+
+ if (!hfp_context_get_number(context, &val) ||
+ val > HAL_HF_CLIENT_CALL_STATE_HELD_BY_RESP_AND_HOLD) {
+ 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) || val > 1) {
+ error("hf-client: Could not get multiparty");
+ return;
+ }
+
+ ev->multiparty = val;
+
+ if (hfp_context_get_string(context, number, 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->number_len, ev);
+}
+
static void slc_completed(struct device *dev)
{
DBG("");
@@ -791,6 +848,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-19 09:43:44

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 11/15] 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 6c318fc..b78294a 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -937,6 +937,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-19 09:43:42

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 09/15] 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 50c5821..d3a3bd1 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -864,14 +864,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);
@@ -964,6 +974,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-19 09:43:41

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 08/15] android/handsfree-client: Add support for +CIEV events

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 79779c2..50c5821 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 {
@@ -833,6 +836,32 @@ static void clcc_cb(struct hfp_context *context, void *user_data)
sizeof(*ev) + ev->number_len, ev);
}

+static void ciev_cb(struct hfp_context *context, void *user_data)
+{
+ struct device *dev = user_data;
+ unsigned int index, val;
+ int i;
+
+ DBG("");
+
+ 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)
{
DBG("");
@@ -849,6 +878,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)
@@ -1019,6 +1049,119 @@ failed:
slc_error(dev);
}

+static void ciev_service_cb(uint8_t val)
+{
+ struct hal_ev_hf_client_net_state ev;
+
+ DBG("");
+
+ if (val > HAL_HF_CLIENT_NET_ROAMING_TYPE_ROAMING) {
+ error("hf-client: Incorrect state %u:", val);
+ return;
+ }
+
+ 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("");
+
+ if (val > HAL_HF_CLIENT_CALL_IND_CALL_IN_PROGERSS) {
+ error("hf-client: Incorrect call state %u:", val);
+ return;
+ }
+
+ 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("");
+
+ if (val > HAL_HF_CLIENT_CALL_SETUP_ALERTING) {
+ error("hf-client: Incorrect call setup state %u:", val);
+ return;
+ }
+
+ 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("");
+
+ if (val > HAL_HF_CLIENT_CALL_SETUP_IND_HOLD) {
+ error("hf-client: Incorrect call held state %u:", val);
+ return;
+ }
+
+ 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("");
+
+ if (val > HAL_HF_CLIENT_NET_ROAMING_TYPE_ROAMING) {
+ error("hf-client: Incorrect roaming state %u:", val);
+ return;
+ }
+
+ 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,
@@ -1032,6 +1175,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;
}

@@ -1039,6 +1183,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;
}

@@ -1046,6 +1191,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;
}

@@ -1053,6 +1199,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;
}

@@ -1060,6 +1207,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;
}

@@ -1067,6 +1215,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;
}

@@ -1074,6 +1223,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-19 09:43:39

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 06/15] android/handsfree-client: Implement query current calls

---
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 c6812ec..6860bed 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -596,10 +596,26 @@ 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


2014-11-19 09:43:38

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 05/15] android/handsfree-client: Add call action implementation

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 2b9a3ac..c6812ec 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -511,9 +511,87 @@ 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:
+ /* Index is int in BT HAL. Let's be paranoid here */
+ if (cmd->index < 0)
+ ret = false;
+ else
+ 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:
+ /* Index is int in BT HAL. Let's be paranoid here */
+ if (cmd->index < 0)
+ ret = false;
+ else
+ 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)
@@ -662,6 +740,26 @@ 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;
+ unsigned int val;
+
+ DBG("");
+
+ if (!hfp_context_get_number(context, &val) ||
+ val > HAL_HF_CLIENT_RESP_AND_HOLD_STATUS_REJECT) {
+ error("hf-client: incorrect BTRH response ");
+ 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("");
@@ -676,6 +774,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-19 09:43:37

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 04/15] android/handsfree-client: Add handling dial command

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 9e856e3..2b9a3ac 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -435,24 +435,78 @@ 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;
+ }
+
+ /* For some reason location in BT HAL is int. Therefore that check */
+ if (cmd->location < 0) {
+ 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-19 09:43:36

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 03/15] android/handsfree-client: Add volume control handling

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

diff --git a/android/handsfree-client.c b/android/handsfree-client.c
index 8b016c6..9e856e3 100644
--- a/android/handsfree-client.c
+++ b/android/handsfree-client.c
@@ -391,10 +391,45 @@ 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;
+ uint8_t vol;
+ bool ret;
+
+ DBG("");
+
+ dev = find_default_device();
+ if (!dev) {
+ status = HAL_STATUS_FAILED;
+ goto done;
+ }
+
+ /* Volume is in the range 0-15. Make sure we send correct value
+ * to remote device
+ */
+ vol = cmd->volume > 15 ? 15 : cmd->volume;
+
+ switch (cmd->type) {
+ case HF_CLIENT_VOLUME_TYPE_SPEAKER:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+VGS=%u", vol);
+ break;
+ case HF_CLIENT_VOLUME_TYPE_MIC:
+ ret = hfp_hf_send_command(dev->hf, cmd_complete_cb, NULL,
+ "AT+VGM=%u", vol);
+ 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 +578,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;
+ unsigned int val;
+
+ if (!hfp_context_get_number(context, &val) || val > 15)
+ 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;
+ unsigned int val;
+
+ if (!hfp_context_get_number(context, &val) || val > 15)
+ 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 +620,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-19 09:43:35

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 02/15] 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..8b016c6 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;
+ unsigned int val;
+
+ if (!hfp_context_get_number(context, &val) || val > 1)
+ 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-19 09:43:34

by Lukasz Rymanowski

[permalink] [raw]
Subject: [PATCH v2 01/15] android/handsfree-client: Fix index type in call action command

According to BT HAL API index should be int.
---
android/hal-msg.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index c86b0a6..c2c659c 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -1089,7 +1089,7 @@ struct hal_cmd_hf_client_dial_memory {
#define HAL_OP_HF_CLIENT_CALL_ACTION 0x0a
struct hal_cmd_hf_client_call_action {
uint8_t action;
- uint8_t index;
+ int32_t index;
} __attribute__((packed));

#define HAL_OP_HF_CLIENT_QUERY_CURRENT_CALLS 0x0b
--
1.8.4