linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/14] android/handsfree-clien: Second set of HFP HF
@ 2014-11-12 10:49 Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 01/14] android/handsfree-client: Add handle start/stop vr Lukasz Rymanowski
                   ` (13 more replies)
  0 siblings, 14 replies; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

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


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/14] android/handsfree-client: Add handle start/stop vr
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 16:04   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 02/14] android/handsfree-client: Add volume control handling Lukasz Rymanowski
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/14] android/handsfree-client: Add volume control handling
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 01/14] android/handsfree-client: Add handle start/stop vr Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 16:12   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 03/14] android/handsfree-client: Add handling dial command Lukasz Rymanowski
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/14] android/handsfree-client: Add handling dial command
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 01/14] android/handsfree-client: Add handle start/stop vr Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 02/14] android/handsfree-client: Add volume control handling Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 16:18   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 04/14] android/handsfree-client: Add call action implementation Lukasz Rymanowski
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/14] android/handsfree-client: Add call action implementation
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (2 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 03/14] android/handsfree-client: Add handling dial command Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 16:24   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 05/14] android/handsfree-client: Implement query current calls Lukasz Rymanowski
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/14] android/handsfree-client: Implement query current calls
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (3 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 04/14] android/handsfree-client: Add call action implementation Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 06/14] android/handsfree-client: Add handling +CLCC Lukasz Rymanowski
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/14] android/handsfree-client: Add handling +CLCC
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (4 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 05/14] android/handsfree-client: Implement query current calls Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 16:29   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 07/14] android/handsfree-client: Add support for +CIEV events Lukasz Rymanowski
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/14] android/handsfree-client: Add support for +CIEV events
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (5 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 06/14] android/handsfree-client: Add handling +CLCC Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 19:54   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup Lukasz Rymanowski
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (6 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 07/14] android/handsfree-client: Add support for +CIEV events Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 19:55   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 09/14] android/handsfree-client: Add support to get operator name Lukasz Rymanowski
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/14] android/handsfree-client: Add support to get operator name
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (7 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 20:17   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 10/14] android/handsfree-client: Send to AG that we do support long name Lukasz Rymanowski
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/14] android/handsfree-client: Send to AG that we do support long name
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (8 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 09/14] android/handsfree-client: Add support to get operator name Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information Lukasz Rymanowski
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (9 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 10/14] android/handsfree-client: Send to AG that we do support long name Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 20:52   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 12/14] android/handsfree-client: Implement send DTMF codes Lukasz Rymanowski
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/14] android/handsfree-client: Implement send DTMF codes
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (10 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND Lukasz Rymanowski
  2014-11-12 10:49 ` [PATCH 14/14] android/handsfree-client: Implement codec negotiations Lukasz Rymanowski
  13 siblings, 0 replies; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (11 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 12/14] android/handsfree-client: Implement send DTMF codes Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 21:09   ` Szymon Janc
  2014-11-12 10:49 ` [PATCH 14/14] android/handsfree-client: Implement codec negotiations Lukasz Rymanowski
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 14/14] android/handsfree-client: Implement codec negotiations
  2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
                   ` (12 preceding siblings ...)
  2014-11-12 10:49 ` [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND Lukasz Rymanowski
@ 2014-11-12 10:49 ` Lukasz Rymanowski
  2014-11-18 21:58   ` Szymon Janc
  13 siblings, 1 reply; 26+ messages in thread
From: Lukasz Rymanowski @ 2014-11-12 10:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Lukasz Rymanowski

---
 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


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/14] android/handsfree-client: Add handle start/stop vr
  2014-11-12 10:49 ` [PATCH 01/14] android/handsfree-client: Add handle start/stop vr Lukasz Rymanowski
@ 2014-11-18 16:04   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 16:04 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 02/14] android/handsfree-client: Add volume control handling
  2014-11-12 10:49 ` [PATCH 02/14] android/handsfree-client: Add volume control handling Lukasz Rymanowski
@ 2014-11-18 16:12   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 16:12 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 03/14] android/handsfree-client: Add handling dial command
  2014-11-12 10:49 ` [PATCH 03/14] android/handsfree-client: Add handling dial command Lukasz Rymanowski
@ 2014-11-18 16:18   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 16:18 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 04/14] android/handsfree-client: Add call action implementation
  2014-11-12 10:49 ` [PATCH 04/14] android/handsfree-client: Add call action implementation Lukasz Rymanowski
@ 2014-11-18 16:24   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 16:24 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 06/14] android/handsfree-client: Add handling +CLCC
  2014-11-12 10:49 ` [PATCH 06/14] android/handsfree-client: Add handling +CLCC Lukasz Rymanowski
@ 2014-11-18 16:29   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 16:29 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 07/14] android/handsfree-client: Add support for +CIEV events
  2014-11-12 10:49 ` [PATCH 07/14] android/handsfree-client: Add support for +CIEV events Lukasz Rymanowski
@ 2014-11-18 19:54   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 19:54 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup
  2014-11-12 10:49 ` [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup Lukasz Rymanowski
@ 2014-11-18 19:55   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 19:55 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 09/14] android/handsfree-client: Add support to get operator name
  2014-11-12 10:49 ` [PATCH 09/14] android/handsfree-client: Add support to get operator name Lukasz Rymanowski
@ 2014-11-18 20:17   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 20:17 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information
  2014-11-12 10:49 ` [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information Lukasz Rymanowski
@ 2014-11-18 20:52   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 20:52 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND
  2014-11-12 10:49 ` [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND Lukasz Rymanowski
@ 2014-11-18 21:09   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 21:09 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 14/14] android/handsfree-client: Implement codec negotiations
  2014-11-12 10:49 ` [PATCH 14/14] android/handsfree-client: Implement codec negotiations Lukasz Rymanowski
@ 2014-11-18 21:58   ` Szymon Janc
  0 siblings, 0 replies; 26+ messages in thread
From: Szymon Janc @ 2014-11-18 21:58 UTC (permalink / raw)
  To: Lukasz Rymanowski; +Cc: linux-bluetooth

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

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2014-11-18 21:58 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-12 10:49 [PATCH 00/14] android/handsfree-clien: Second set of HFP HF Lukasz Rymanowski
2014-11-12 10:49 ` [PATCH 01/14] android/handsfree-client: Add handle start/stop vr Lukasz Rymanowski
2014-11-18 16:04   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 02/14] android/handsfree-client: Add volume control handling Lukasz Rymanowski
2014-11-18 16:12   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 03/14] android/handsfree-client: Add handling dial command Lukasz Rymanowski
2014-11-18 16:18   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 04/14] android/handsfree-client: Add call action implementation Lukasz Rymanowski
2014-11-18 16:24   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 05/14] android/handsfree-client: Implement query current calls Lukasz Rymanowski
2014-11-12 10:49 ` [PATCH 06/14] android/handsfree-client: Add handling +CLCC Lukasz Rymanowski
2014-11-18 16:29   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 07/14] android/handsfree-client: Add support for +CIEV events Lukasz Rymanowski
2014-11-18 19:54   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 08/14] android/handsfree-client: Send indicators val we got during SLC setup Lukasz Rymanowski
2014-11-18 19:55   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 09/14] android/handsfree-client: Add support to get operator name Lukasz Rymanowski
2014-11-18 20:17   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 10/14] android/handsfree-client: Send to AG that we do support long name Lukasz Rymanowski
2014-11-12 10:49 ` [PATCH 11/14] android/handsfree-client: Retrieve subscriber number information Lukasz Rymanowski
2014-11-18 20:52   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 12/14] android/handsfree-client: Implement send DTMF codes Lukasz Rymanowski
2014-11-12 10:49 ` [PATCH 13/14] android/handsfree-client: Implement handling AT+BIND and +BIND Lukasz Rymanowski
2014-11-18 21:09   ` Szymon Janc
2014-11-12 10:49 ` [PATCH 14/14] android/handsfree-client: Implement codec negotiations Lukasz Rymanowski
2014-11-18 21:58   ` Szymon Janc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).