All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/20] More Android Handsfree work
@ 2014-03-08  0:19 Szymon Janc
  2014-03-08  0:19 ` [PATCH 01/20] android/handsfree: Add AG and HF features masks Szymon Janc
                   ` (20 more replies)
  0 siblings, 21 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Hi,

This patchset adds support for basic handsfree functionality.

What is done:
 - indicators (without callheld)
 - placing, accepting, cancelling calls etc.
 - vendor (unknown) AT command handling
 - extended error codes
 - DTMF codes
 - query current calls
 - voice recognition on/off
 - disabling echo cancellation
 - subscriber and operator identification

Missing features:
 - proper three way calling support (AT+CHLD is supported but callheld
   and CCWA are missing).
 - WBS and codec negotiation
 - audio

-- 
BR
Szymon Janc

Szymon Janc (20):
  android/handsfree: Add AG and HF features masks
  android/handsfree: Add stubs for all AT commands defines by spec
  android/handsfree: Add support for unknown AT commands
  android/handsfree: Add support for voice recognition function
  android/handsfree: Add support for AT+NREC command
  android/handsfree: Add support for AT+CLCC command
  android/handsfree: Add support for AT+CHLD command
  android/handsfree: Add support for AT+CMEE command
  android/handsfree: Add support for AT+CKPD command
  android/handsfree: Add support fot AT+CNUM command
  android/handsfree: Add support for AT+VTS command
  android/handsfree: Add support for ATA command
  android/handsfree: Fix checking AT+COPS parameters
  android/handsfree: Add support for ATD command
  android/handsfree: Add support for AT+BLDN command
  android/handsfree: Add support for AT+CHUP command
  android/hal-handsfree: Fix handling of dial notification
  android/handsfree: Add support for phone state change command
  android/handsfree: Add support for AT+CLIP command
  android/handsfree: Add comment for AT+VGS/AT+VGM result code

 android/hal-handsfree.c |   7 +-
 android/hal-msg.h       |   5 +-
 android/handsfree.c     | 889 ++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 838 insertions(+), 63 deletions(-)

-- 
1.8.5.3


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

* [PATCH 01/20] android/handsfree: Add AG and HF features masks
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec Szymon Janc
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index dc5c73d..3fc4487 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -49,7 +49,28 @@
 #define HSP_AG_CHANNEL 12
 #define HFP_AG_CHANNEL 13
 
-#define HFP_AG_FEATURES 0
+#define HFP_AG_FEAT_3WAY	0x00000001
+#define HFP_AG_FEAT_ECNR	0x00000002
+#define HFP_AG_FEAT_VR		0x00000004
+#define HFP_AG_FEAT_INBAND	0x00000008
+#define HFP_AG_FEAT_VTAG	0x00000010
+#define HFP_AG_FEAT_REJ_CALL	0x00000020
+#define HFP_AG_FEAT_ECS		0x00000040
+#define HFP_AG_FEAT_ECC		0x00000080
+#define HFP_AG_FEAT_EXT_ERR	0x00000100
+#define HFP_AG_FEAT_CODEC	0x00000200
+
+#define HFP_HF_FEAT_ECNR	0x00000001
+#define HFP_HF_FEAT_3WAY	0x00000002
+#define HFP_HF_FEAT_CLI		0x00000004
+#define HFP_HF_FEAT_VR		0x00000008
+#define HFP_HF_FEAT_ECS		0x00000010
+#define HFP_HF_FEAT_ECC		0x00000020
+#define HFP_HF_FEAT_CODEC	0x00000040
+
+#define HFP_AG_FEATURES ( HFP_AG_FEAT_3WAY | HFP_AG_FEAT_ECNR |\
+			HFP_AG_FEAT_VR | HFP_AG_FEAT_REJ_CALL |\
+			HFP_AG_FEAT_ECS | HFP_AG_FEAT_EXT_ERR )
 
 /* offsets in indicators table, should be incremented when sending CIEV */
 #define IND_SERVICE	0
@@ -1150,7 +1171,13 @@ static sdp_record_t *hfp_ag_record(void)
 	proto[1] = sdp_list_append(proto[1], channel);
 	apseq = sdp_list_append(apseq, proto[1]);
 
-	sdpfeat = HFP_AG_FEATURES;
+	/* Codec Negotiation bit in SDP feature is different then in BRSF */
+	sdpfeat = HFP_AG_FEATURES & 0x0000003F;
+	if (HFP_AG_FEATURES & HFP_AG_FEAT_CODEC)
+		sdpfeat |= 0x00000020;
+	else
+		sdpfeat &= ~0x00000020;
+
 	features = sdp_data_alloc(SDP_UINT16, &sdpfeat);
 	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);
 
-- 
1.8.5.3


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

* [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
  2014-03-08  0:19 ` [PATCH 01/20] android/handsfree: Add AG and HF features masks Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  3:39   ` Marcel Holtmann
  2014-03-08  0:19 ` [PATCH 03/20] android/handsfree: Add support for unknown AT commands Szymon Janc
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 221 insertions(+), 2 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 3fc4487..c49a35b 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -287,10 +287,190 @@ failed:
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
 
+static void at_cmd_a(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_d(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_ccwa(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_chup(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_clcc(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_cmee(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_clip(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_vts(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_cnum(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_binp(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_bldn(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_bvra(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_nrec(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_bsir(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_btrh(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_bcc(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_bcs(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_ckpd(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
 static void register_post_slc_at(void)
 {
 	if (device.hsp) {
-		/* TODO CKPD */
+		hfp_gw_register(device.gw, at_cmd_ckpd, "+CKPD", NULL, NULL);
 		hfp_gw_register(device.gw, at_cmd_vgs_vgm, "+VGS",
 				GUINT_TO_POINTER(HAL_HANDSFREE_VOLUME_TYPE_SPEAKER),
 				NULL);
@@ -300,14 +480,31 @@ static void register_post_slc_at(void)
 		return;
 	}
 
-	hfp_gw_register(device.gw, at_cmd_bia, "+BIA", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_a, "A", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_d, "D", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_ccwa, "+CCWA", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_chup, "+CHUP", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_clcc, "+CLCC", NULL, NULL);
 	hfp_gw_register(device.gw, at_cmd_cops, "+COPS", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_cmee, "+CMEE", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_clip, "+CLIP", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_vts, "+VTS", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_cnum, "+CNUM", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_bia, "+BIA", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_binp, "+BINP", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_bldn, "+BLDN", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_bvra, "+BVRA", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_nrec, "+NREC", NULL, NULL);
 	hfp_gw_register(device.gw, at_cmd_vgs_vgm, "+VGS",
 			GUINT_TO_POINTER(HAL_HANDSFREE_VOLUME_TYPE_SPEAKER),
 			NULL);
 	hfp_gw_register(device.gw, at_cmd_vgs_vgm, "+VGM",
 			GUINT_TO_POINTER(HAL_HANDSFREE_VOLUME_TYPE_MIC),
 			NULL);
+	hfp_gw_register(device.gw, at_cmd_bsir, "+BSIR", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_btrh, "+BTRH", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_bcc, "+BCC", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_bcs, "+BCS", NULL, NULL);
 }
 
 static void at_cmd_cmer(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
@@ -432,11 +629,33 @@ static void at_cmd_brsf(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
 
+static void at_cmd_chld(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
+static void at_cmd_bac(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
+							void *user_data)
+{
+	DBG("");
+
+	/* TODO */
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
+
 static void register_slc_at(void)
 {
 	hfp_gw_register(device.gw, at_cmd_brsf, "+BRSF", NULL, NULL);
 	hfp_gw_register(device.gw, at_cmd_cind, "+CIND", NULL, NULL);
 	hfp_gw_register(device.gw, at_cmd_cmer, "+CMER", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_chld, "+CHLD", NULL, NULL);
+	hfp_gw_register(device.gw, at_cmd_bac, "+BAC", NULL, NULL);
 }
 
 static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
-- 
1.8.5.3


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

* [PATCH 03/20] android/handsfree: Add support for unknown AT commands
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
  2014-03-08  0:19 ` [PATCH 01/20] android/handsfree: Add AG and HF features masks Szymon Janc
  2014-03-08  0:19 ` [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  3:37   ` Marcel Holtmann
  2014-03-08  0:19 ` [PATCH 04/20] android/handsfree: Add support for voice recognition function Szymon Janc
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Those commands are passed to Framework without parsing.
---
 android/handsfree.c | 64 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 54 insertions(+), 10 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index c49a35b..e104c4a 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -161,19 +161,35 @@ static void device_cleanup(void)
 	memset(&device, 0, sizeof(device));
 }
 
-static void at_command_handler(const char *command, void *user_data)
+static void disconnect_watch(void *user_data)
 {
-	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+	DBG("");
 
-	if (device.state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED)
-		hfp_gw_disconnect(device.gw);
+	device_cleanup();
 }
 
-static void disconnect_watch(void *user_data)
+static void at_cmd_unknown(const char *command, void *user_data)
 {
-	DBG("");
+	uint8_t buf[IPC_MTU];
+	struct hal_ev_handsfree_unknown_at *ev = (void *) buf;
 
-	device_cleanup();
+	if (device.state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+		hfp_gw_disconnect(device.gw);
+		return;
+	}
+
+	/* copy while string including terminating NULL */
+	ev->len = strlen(command) + 1;
+	memcpy(ev->buf, command, ev->len);
+
+	if (ev->len > IPC_MTU - sizeof(*ev)) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+		return;
+	}
+
+	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+			HAL_EV_HANDSFREE_UNKNOWN_AT, sizeof(*ev) + ev->len, ev);
 }
 
 static void at_cmd_vgs_vgm(struct hfp_gw_result *result,
@@ -674,7 +690,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
 	g_io_channel_set_close_on_unref(chan, FALSE);
 
 	hfp_gw_set_close_on_unref(device.gw, true);
-	hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
+	hfp_gw_set_command_handler(device.gw, at_cmd_unknown, NULL, NULL);
 	hfp_gw_set_disconnect_handler(device.gw, disconnect_watch, NULL, NULL);
 
 
@@ -1147,19 +1163,47 @@ static void handle_cind(const void *buf, uint16_t len)
 
 static void handle_formatted_at_resp(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_formatted_at_response *cmd = buf;
+	char *at;
+
 	DBG("");
 
+	if (len != sizeof(*cmd) + cmd->len) {
+		error("Invalid formatted AT response command, terminating");
+		raise(SIGTERM);
+		return;
+	}
+
+	DBG("");
+
+	at = g_malloc0(cmd->len + 1);
+
+	memcpy(at, cmd->buf, cmd->len);
+
+	hfp_gw_send_info(device.gw, "%s", at);
+
+	g_free(at);
+
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
 					HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE,
-					HAL_STATUS_FAILED);
+					HAL_STATUS_SUCCESS);
 }
 
 static void handle_at_resp(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_at_response *cmd = buf;
+
 	DBG("");
 
+	/* TODO handle +CME ERROR when AT+CMEE support is added */
+
+	if (cmd->response == HAL_HANDSFREE_AT_RESPONSE_OK)
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+	else
+		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-			HAL_OP_HANDSFREE_AT_RESPONSE, HAL_STATUS_FAILED);
+			HAL_OP_HANDSFREE_AT_RESPONSE, HAL_STATUS_SUCCESS);
 }
 
 static void handle_clcc_resp(const void *buf, uint16_t len)
-- 
1.8.5.3


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

* [PATCH 04/20] android/handsfree: Add support for voice recognition function
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (2 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 03/20] android/handsfree: Add support for unknown AT commands Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 05/20] android/handsfree: Add support for AT+NREC command Szymon Janc
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/hal-msg.h   |  3 +++
 android/handsfree.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 1b2b31a..8859454 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -999,6 +999,9 @@ struct hal_ev_handsfree_audio_state {
 	uint8_t bdaddr[6];
 } __attribute__((packed));
 
+#define HAL_HANDSFREE_VR_STOPPED	0x00
+#define HAL_HANDSFREE_VR_STARTED	0x01
+
 #define HAL_EV_HANDSFREE_VR		0x83
 struct hal_ev_handsfree_vr_state {
 	uint8_t state;
diff --git a/android/handsfree.c b/android/handsfree.c
index e104c4a..b0226e8 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -416,9 +416,33 @@ static void at_cmd_bldn(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_bvra(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	struct hal_ev_handsfree_vr_state ev;
+	unsigned int val;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_number(result, &val) || val > 1)
+			break;
+
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		if (val)
+			ev.state = HAL_HANDSFREE_VR_STARTED;
+		else
+			ev.state = HAL_HANDSFREE_VR_STOPPED;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_VR, sizeof(ev), &ev);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
@@ -1013,18 +1037,36 @@ static void handle_disconnect_audio(const void *buf, uint16_t len)
 
 static void handle_start_vr(const void *buf, uint16_t len)
 {
+	uint8_t status;
+
 	DBG("");
 
+	if (device.features & HFP_HF_FEAT_VR) {
+		hfp_gw_send_info(device.gw, "+BVRA: 1");
+		status = HAL_STATUS_SUCCESS;
+	} else {
+		status = HAL_STATUS_FAILED;
+	}
+
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-				HAL_OP_HANDSFREE_START_VR, HAL_STATUS_FAILED);
+					HAL_OP_HANDSFREE_START_VR, status);
 }
 
 static void handle_stop_vr(const void *buf, uint16_t len)
 {
+	uint8_t status;
+
 	DBG("");
 
+	if (device.features & HFP_HF_FEAT_VR) {
+		hfp_gw_send_info(device.gw, "+BVRA: 0");
+		status = HAL_STATUS_SUCCESS;
+	} else {
+		status = HAL_STATUS_FAILED;
+	}
+
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-				HAL_OP_HANDSFREE_STOP_VR, HAL_STATUS_FAILED);
+				HAL_OP_HANDSFREE_STOP_VR, status);
 }
 
 static void handle_volume_control(const void *buf, uint16_t len)
-- 
1.8.5.3


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

* [PATCH 05/20] android/handsfree: Add support for AT+NREC command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (3 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 04/20] android/handsfree: Add support for voice recognition function Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 06/20] android/handsfree: Add support for AT+CLCC command Szymon Janc
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/hal-msg.h   |  2 +-
 android/handsfree.c | 30 +++++++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/android/hal-msg.h b/android/hal-msg.h
index 8859454..0abbbe6 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -1029,7 +1029,7 @@ struct hal_ev_handsfree_dtmf {
 } __attribute__((packed));
 
 #define HAL_HANDSFREE_NREC_STOP		0x00
-#define HAL_HANDSFREE_NREC_STart	0x01
+#define HAL_HANDSFREE_NREC_START	0x01
 
 #define HAL_EV_HANDSFREE_NREC		0x89
 struct hal_ev_handsfree_nrec {
diff --git a/android/handsfree.c b/android/handsfree.c
index b0226e8..31eaabe 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -450,9 +450,37 @@ static void at_cmd_bvra(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_nrec(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	struct hal_ev_handsfree_nrec ev;
+	unsigned int val;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		/* Android HAL defines start and stop parameter for NREC
+		 * callback, but spec allows HF to only disable AG's NREC
+		 * feature for SLC duration. Follow spec here.
+		 */
+		if (!hfp_gw_result_get_number(result, &val) || val != 0)
+			break;
+
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ev.nrec = HAL_HANDSFREE_NREC_STOP;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_NREC, sizeof(ev), &ev);
+
+		/* Framework is not replying with result for AT+NREC */
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
-- 
1.8.5.3


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

* [PATCH 06/20] android/handsfree: Add support for AT+CLCC command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (4 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 05/20] android/handsfree: Add support for AT+NREC command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 07/20] android/handsfree: Add support for AT+CHLD command Szymon Janc
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 31eaabe..a2991b6 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -348,7 +348,20 @@ static void at_cmd_clcc(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 {
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_COMMAND:
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_CLCC, 0, NULL);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_SET:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
@@ -1278,10 +1291,65 @@ static void handle_at_resp(const void *buf, uint16_t len)
 
 static void handle_clcc_resp(const void *buf, uint16_t len)
 {
+	const struct hal_cmd_handsfree_clcc_response *cmd = buf;
+	uint8_t status;
+
+	if (len != sizeof(*cmd) + cmd->number_len) {
+		error("Invalid CLCC response command, terminating");
+		raise(SIGTERM);
+		return;
+	}
+
 	DBG("");
 
+	if (!cmd->index) {
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		status = HAL_STATUS_SUCCESS;
+		goto done;
+	}
+
+	switch (cmd->state) {
+	/* according to comment in HAL only those can have number and type */
+	case HAL_HANDSFREE_CALL_STATE_INCOMING:
+	case HAL_HANDSFREE_CALL_STATE_WAITING:
+		if (cmd->number_len) {
+			char *number = g_malloc0(cmd->number_len + 1);
+
+			memcpy(number, cmd->number, cmd->number_len);
+
+			hfp_gw_send_info(device.gw,
+						"+CLCC: %u,%u,%u,%u,%u,%s,%u",
+						cmd->index, cmd->dir,
+						cmd->state, cmd->mode,
+						cmd->mpty, number, cmd->type);
+
+			g_free(number);
+
+			status = HAL_STATUS_SUCCESS;
+			break;
+		}
+
+		/* fall through */
+	case HAL_HANDSFREE_CALL_STATE_ACTIVE:
+	case HAL_HANDSFREE_CALL_STATE_HELD:
+	case HAL_HANDSFREE_CALL_STATE_DIALING:
+	case HAL_HANDSFREE_CALL_STATE_ALERTING:
+		hfp_gw_send_info(device.gw, "+CLCC: %u,%u,%u,%u,%u",
+					cmd->index, cmd->dir, cmd->state,
+					cmd->mode, cmd->mpty);
+
+		status = HAL_STATUS_SUCCESS;
+		break;
+	case HAL_HANDSFREE_CALL_STATE_IDLE:
+	default:
+		status = HAL_STATUS_FAILED;
+		break;
+	}
+
+done:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-			HAL_OP_HANDSFREE_CLCC_RESPONSE, HAL_STATUS_FAILED);
+				HAL_OP_HANDSFREE_CLCC_RESPONSE, status);
 }
 
 static void handle_phone_state_change(const void *buf, uint16_t len)
-- 
1.8.5.3


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

* [PATCH 07/20] android/handsfree: Add support for AT+CHLD command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (5 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 06/20] android/handsfree: Add support for AT+CLCC command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 08/20] android/handsfree: Add support for AT+CMEE command Szymon Janc
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 42 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index a2991b6..76fd82c 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -72,6 +72,8 @@
 			HFP_AG_FEAT_VR | HFP_AG_FEAT_REJ_CALL |\
 			HFP_AG_FEAT_ECS | HFP_AG_FEAT_EXT_ERR )
 
+#define HFP_AG_CHLD_STR "0,1,2,3"
+
 /* offsets in indicators table, should be incremented when sending CIEV */
 #define IND_SERVICE	0
 #define IND_CALL	1
@@ -616,12 +618,14 @@ static void at_cmd_cmer(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 
 		device.indicators_enabled = val;
 
-		/* TODO Check for 3-way calling support */
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		if (device.features & HFP_HF_FEAT_3WAY)
+			return;
+
 		register_post_slc_at();
 		device_set_state(HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED);
 
-		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
-
 		return;
 	case HFP_GW_CMD_TYPE_TEST:
 	case HFP_GW_CMD_TYPE_READ:
@@ -713,9 +717,39 @@ static void at_cmd_brsf(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_chld(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	struct hal_ev_handsfree_chld ev;
+	unsigned int val;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_number(result, &val) || val > 3)
+			break;
+
+		/* No ECC support */
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		/* value match HAL type */
+		ev.chld = val;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_CHLD, sizeof(ev), &ev);
+
+		return;
+	case HFP_GW_CMD_TYPE_TEST:
+		hfp_gw_send_info(device.gw, "+CHLD=%s", HFP_AG_CHLD_STR);
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		register_post_slc_at();
+		device_set_state(HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
-- 
1.8.5.3


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

* [PATCH 08/20] android/handsfree: Add support for AT+CMEE command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (6 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 07/20] android/handsfree: Add support for AT+CHLD command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 09/20] android/handsfree: Add support for AT+CKPD command Szymon Janc
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

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

diff --git a/android/handsfree.c b/android/handsfree.c
index 76fd82c..f4c78aa 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -107,6 +107,7 @@ static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
 	uint32_t features;
+	bool cmee_enabled;
 	bool indicators_enabled;
 	struct indicator inds[IND_COUNT];
 	bool hsp;
@@ -371,9 +372,28 @@ static void at_cmd_clcc(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_cmee(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	unsigned int val;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_number(result, &val) || val > 1)
+			break;
+
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		device.cmee_enabled = val;
+
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
@@ -1312,10 +1332,10 @@ static void handle_at_resp(const void *buf, uint16_t len)
 
 	DBG("");
 
-	/* TODO handle +CME ERROR when AT+CMEE support is added */
-
 	if (cmd->response == HAL_HANDSFREE_AT_RESPONSE_OK)
 		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+	else if (device.cmee_enabled)
+		hfp_gw_send_error(device.gw, cmd->error);
 	else
 		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 
-- 
1.8.5.3


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

* [PATCH 09/20] android/handsfree: Add support for AT+CKPD command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (7 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 08/20] android/handsfree: Add support for AT+CMEE command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 10/20] android/handsfree: Add support fot AT+CNUM command Szymon Janc
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index f4c78aa..e59a229 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -563,9 +563,29 @@ static void at_cmd_bcs(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_ckpd(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	unsigned int val;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_number(result, &val) || val != 200)
+			break;
+
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+				HAL_EV_HANDSFREE_HSP_KEY_PRESS, 0, NULL);
+
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
-- 
1.8.5.3


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

* [PATCH 10/20] android/handsfree: Add support fot AT+CNUM command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (8 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 09/20] android/handsfree: Add support for AT+CKPD command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 11/20] android/handsfree: Add support for AT+VTS command Szymon Janc
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

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

diff --git a/android/handsfree.c b/android/handsfree.c
index e59a229..123cff0 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -423,7 +423,20 @@ static void at_cmd_cnum(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 {
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_COMMAND:
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+						HAL_EV_HANDSFREE_CNUM, 0, NULL);
+
+		return;
+	case HFP_GW_CMD_TYPE_SET:
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
-- 
1.8.5.3


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

* [PATCH 11/20] android/handsfree: Add support for AT+VTS command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (9 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 10/20] android/handsfree: Add support fot AT+CNUM command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 12/20] android/handsfree: Add support for ATA command Szymon Janc
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

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

diff --git a/android/handsfree.c b/android/handsfree.c
index 123cff0..e7d3975 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -411,12 +411,40 @@ static void at_cmd_clip(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_vts(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	struct hal_ev_handsfree_dtmf ev;
+	char str[2];
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_unquoted_string(result, str, 2))
+			break;
 
-	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
-}
+		if (!((str[0] >= '0' && str[0] <='9') ||
+				(str[0] >= 'A' && str[0] <= 'D') ||
+				str[0] == '*' || str[0] == '#'))
+			break;
+
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ev.tone = str[0];
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_DTMF, sizeof(ev), &ev);
+
+		/* Framework is not replying with result for AT+VTS */
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
+
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);}
 
 static void at_cmd_cnum(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
-- 
1.8.5.3


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

* [PATCH 12/20] android/handsfree: Add support for ATA command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (10 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 11/20] android/handsfree: Add support for AT+VTS command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 13/20] android/handsfree: Fix checking AT+COPS parameters Szymon Janc
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index e7d3975..e88b06a 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -311,7 +311,23 @@ static void at_cmd_a(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 {
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_COMMAND:
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_ANSWER, 0, NULL);
+
+		/* Framework is not replying with result for ATA */
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_SET:
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
-- 
1.8.5.3


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

* [PATCH 13/20] android/handsfree: Fix checking AT+COPS parameters
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (11 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 12/20] android/handsfree: Add support for ATA command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 14/20] android/handsfree: Add support for ATD command Szymon Janc
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index e88b06a..8a5a6cf 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -239,7 +239,7 @@ static void at_cmd_cops(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 		if (!hfp_gw_result_get_number(result, &val) || val != 3)
 			break;
 
-		if (!hfp_gw_result_get_number(result, &val) || val != 1)
+		if (!hfp_gw_result_get_number(result, &val) || val != 0)
 			break;
 
 		if (hfp_gw_result_has_next(result))
-- 
1.8.5.3


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

* [PATCH 14/20] android/handsfree: Add support for ATD command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (12 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 13/20] android/handsfree: Fix checking AT+COPS parameters Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:19 ` [PATCH 15/20] android/handsfree: Add support for AT+BLDN command Szymon Janc
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 8a5a6cf..ad033be 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -335,9 +335,41 @@ static void at_cmd_a(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_d(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	char buf[IPC_MTU];
+	struct hal_ev_handsfree_dial *ev = (void*) buf;
+	int cnt;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_unquoted_string(result,
+						(char *) ev->number, 255))
+			break;
+
+		ev->number_len = strlen((char *) ev->number);
+
+		if (ev->number[ev->number_len - 1] != ';')
+			break;
+
+		if (ev->number[0] == '>')
+			cnt = strspn((char *) ev->number + 1, "0123456789") + 1;
+		else
+			cnt = strspn((char *) ev->number, "0123456789ABC*#+");
+
+		if (cnt != ev->number_len - 1)
+			break;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_DIAL,
+					sizeof(*ev) + ev->number_len, ev);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
@@ -460,7 +492,8 @@ static void at_cmd_vts(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 		break;
 	}
 
-	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);}
+	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+}
 
 static void at_cmd_cnum(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
-- 
1.8.5.3


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

* [PATCH 15/20] android/handsfree: Add support for AT+BLDN command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (13 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 14/20] android/handsfree: Add support for ATD command Szymon Janc
@ 2014-03-08  0:19 ` Szymon Janc
  2014-03-08  0:20 ` [PATCH 16/20] android/handsfree: Add support for AT+CHUP command Szymon Janc
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

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

diff --git a/android/handsfree.c b/android/handsfree.c
index ad033be..16f079f 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -531,11 +531,26 @@ static void at_cmd_binp(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_bldn(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	struct hal_ev_handsfree_dial ev;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_COMMAND:
+		if (hfp_gw_result_has_next(result))
+			break;
 
-	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
+		ev.number_len = 0;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_DIAL, sizeof(ev), &ev);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_SET:
+		break;
+	}
 }
 
 static void at_cmd_bvra(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
-- 
1.8.5.3


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

* [PATCH 16/20] android/handsfree: Add support for AT+CHUP command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (14 preceding siblings ...)
  2014-03-08  0:19 ` [PATCH 15/20] android/handsfree: Add support for AT+BLDN command Szymon Janc
@ 2014-03-08  0:20 ` Szymon Janc
  2014-03-08  0:20 ` [PATCH 17/20] android/hal-handsfree: Fix handling of dial notification Szymon Janc
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index 16f079f..c1ae359 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -389,7 +389,23 @@ static void at_cmd_chup(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 {
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_COMMAND:
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
+					HAL_EV_HANDSFREE_HANGUP, 0, NULL);
+
+		/* Framework is not replying with result for AT+CHUP */
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_SET:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
-- 
1.8.5.3


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

* [PATCH 17/20] android/hal-handsfree: Fix handling of dial notification
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (15 preceding siblings ...)
  2014-03-08  0:20 ` [PATCH 16/20] android/handsfree: Add support for AT+CHUP command Szymon Janc
@ 2014-03-08  0:20 ` Szymon Janc
  2014-03-08  0:20 ` [PATCH 18/20] android/handsfree: Add support for phone state change command Szymon Janc
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Empty number means re-dial and should be passed as NULL.
---
 android/hal-handsfree.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 4117ed0..196b046 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -89,8 +89,13 @@ static void handle_dial(void *buf, uint16_t len)
 		exit(EXIT_FAILURE);
 	}
 
-	if (cbs->dial_call_cmd_cb)
+	if (!cbs->dial_call_cmd_cb)
+		return;
+
+	if (ev->number_len)
 		cbs->dial_call_cmd_cb((char *) ev->number);
+	else
+		cbs->dial_call_cmd_cb(NULL);
 }
 
 static void handle_dtmf(void *buf, uint16_t len)
-- 
1.8.5.3


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

* [PATCH 18/20] android/handsfree: Add support for phone state change command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (16 preceding siblings ...)
  2014-03-08  0:20 ` [PATCH 17/20] android/hal-handsfree: Fix handling of dial notification Szymon Janc
@ 2014-03-08  0:20 ` Szymon Janc
  2014-03-08  0:20 ` [PATCH 19/20] android/handsfree: Add support for AT+CLIP command Szymon Janc
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

Unfortunately HAL is not getting call, callsetup and callheld
indicators values directly from Android Framework and those need to be
chosen based on number of active/hold calls and call state that
triggered phone state change.

This patch adds only basic call state handling (no three way call).
---
 android/handsfree.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 103 insertions(+), 3 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index c1ae359..e07278c 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -84,6 +84,8 @@
 #define IND_BATTCHG	6
 #define IND_COUNT	(IND_BATTCHG + 1)
 
+#define RING_TIMEOUT 2
+
 struct indicator {
 	const char *name;
 	int min;
@@ -110,6 +112,7 @@ static struct {
 	bool cmee_enabled;
 	bool indicators_enabled;
 	struct indicator inds[IND_COUNT];
+	guint ring;
 	bool hsp;
 	struct hfp_gw *gw;
 } device;
@@ -1547,13 +1550,110 @@ done:
 				HAL_OP_HANDSFREE_CLCC_RESPONSE, status);
 }
 
+static gboolean ring_cb(gpointer user_data)
+{
+	hfp_gw_send_info(device.gw, "+RING");
+
+	return TRUE;
+}
+
+static void phone_state_active(int num_active, int num_held)
+{
+
+}
+
+static void phone_state_held(int num_active, int num_held)
+{
+
+}
+
+static void phone_state_dialing(int num_active, int num_held)
+{
+	update_indicator(IND_CALLSETUP, 2);
+}
+
+static void phone_state_alerting(int num_active, int num_held)
+{
+	update_indicator(IND_CALLSETUP, 3);
+}
+
+static void phone_state_incoming(int num_active, int num_held, uint8_t type,
+					const uint8_t *number, uint16_t len)
+{
+	update_indicator(IND_CALLSETUP, 1);
+
+	device.ring = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
+							RING_TIMEOUT, ring_cb,
+							NULL, NULL);
+}
+
+static void phone_state_waiting(int num_active, int num_held, uint8_t type,
+					const uint8_t *number, uint16_t len)
+{
+
+}
+
+static void phone_state_idle(int num_active, int num_held)
+{
+
+	update_indicator(IND_CALL, !!num_active);
+
+	if (device.ring) {
+		g_source_remove(device.ring);
+		device.ring = 0;
+	}
+
+	update_indicator(IND_CALLSETUP, 0);
+}
+
 static void handle_phone_state_change(const void *buf, uint16_t len)
 {
-	DBG("");
+	const struct hal_cmd_handsfree_phone_state_change *cmd = buf;
+	uint8_t status;
+
+	if (len != sizeof(*cmd) + cmd->number_len) {
+		error("Invalid phone state change command, terminating");
+		raise(SIGTERM);
+		return;
+	}
+
+	DBG("active=%u hold=%u state=%u", cmd->num_active, cmd->num_held,
+								cmd->state);
+
+	switch (cmd->state) {
+	case HAL_HANDSFREE_CALL_STATE_ACTIVE:
+		phone_state_active(cmd->num_active, cmd->num_held);
+		break;
+	case HAL_HANDSFREE_CALL_STATE_HELD:
+		phone_state_held(cmd->num_active, cmd->num_held);
+		break;
+	case HAL_HANDSFREE_CALL_STATE_DIALING:
+		phone_state_dialing(cmd->num_active, cmd->num_held);
+		break;
+	case HAL_HANDSFREE_CALL_STATE_ALERTING:
+		phone_state_alerting(cmd->num_active, cmd->num_held);
+		break;
+	case HAL_HANDSFREE_CALL_STATE_INCOMING:
+		phone_state_incoming(cmd->num_active, cmd->num_held, cmd->type,
+						cmd->number, cmd->number_len);
+		break;
+	case HAL_HANDSFREE_CALL_STATE_WAITING:
+		phone_state_waiting(cmd->num_active, cmd->num_held, cmd->type,
+						cmd->number, cmd->number_len);
+		break;
+	case HAL_HANDSFREE_CALL_STATE_IDLE:
+		phone_state_idle(cmd->num_active, cmd->num_held);
+		break;
+	default:
+		status = HAL_STATUS_FAILED;
+		goto failed;
+	}
+
+	status = HAL_STATUS_SUCCESS;
 
+failed:
 	ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
-					HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
-					HAL_STATUS_FAILED);
+				HAL_OP_HANDSFREE_PHONE_STATE_CHANGE, status);
 }
 
 static const struct ipc_handler cmd_handlers[] = {
-- 
1.8.5.3


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

* [PATCH 19/20] android/handsfree: Add support for AT+CLIP command
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (17 preceding siblings ...)
  2014-03-08  0:20 ` [PATCH 18/20] android/handsfree: Add support for phone state change command Szymon Janc
@ 2014-03-08  0:20 ` Szymon Janc
  2014-03-08  0:20 ` [PATCH 20/20] android/handsfree: Add comment for AT+VGS/AT+VGM result code Szymon Janc
  2014-03-10 11:50 ` [PATCH 00/20] More Android Handsfree work Szymon Janc
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/android/handsfree.c b/android/handsfree.c
index e07278c..2a081ef 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -109,6 +109,7 @@ static struct {
 	bdaddr_t bdaddr;
 	uint8_t state;
 	uint32_t features;
+	bool clip_enabled;
 	bool cmee_enabled;
 	bool indicators_enabled;
 	struct indicator inds[IND_COUNT];
@@ -468,9 +469,28 @@ static void at_cmd_cmee(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 static void at_cmd_clip(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 							void *user_data)
 {
+	unsigned int val;
+
 	DBG("");
 
-	/* TODO */
+	switch (type) {
+	case HFP_GW_CMD_TYPE_SET:
+		if (!hfp_gw_result_get_number(result, &val) || val > 1)
+			break;
+
+		if (hfp_gw_result_has_next(result))
+			break;
+
+		device.clip_enabled = val;
+
+		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+		return;
+	case HFP_GW_CMD_TYPE_READ:
+	case HFP_GW_CMD_TYPE_TEST:
+	case HFP_GW_CMD_TYPE_COMMAND:
+		break;
+	}
 
 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
 }
@@ -1552,8 +1572,13 @@ done:
 
 static gboolean ring_cb(gpointer user_data)
 {
+	char *clip = user_data;
+
 	hfp_gw_send_info(device.gw, "+RING");
 
+	if (device.clip_enabled && clip)
+		hfp_gw_send_info(device.gw, "%s", clip);
+
 	return TRUE;
 }
 
@@ -1580,11 +1605,29 @@ static void phone_state_alerting(int num_active, int num_held)
 static void phone_state_incoming(int num_active, int num_held, uint8_t type,
 					const uint8_t *number, uint16_t len)
 {
+	char *clip = NULL;
+
 	update_indicator(IND_CALLSETUP, 1);
 
+	if (len) {
+		if (type == HAL_HANDSFREE_CALL_ADDRTYPE_INTERNATIONAL &&
+							number[0] != '+')
+			clip = g_strdup_printf("+CLIP: \"+%.*s\",%u",
+							len, number, type );
+		else
+			clip = g_strdup_printf("+CLIP: \"%.*s\",%u",
+							len, number, type );
+	}
+
+	/* send first +RING */
+	ring_cb(clip);
+
 	device.ring = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
 							RING_TIMEOUT, ring_cb,
-							NULL, NULL);
+							clip, g_free);
+
+	if (!device.ring)
+		g_free(clip);
 }
 
 static void phone_state_waiting(int num_active, int num_held, uint8_t type,
-- 
1.8.5.3


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

* [PATCH 20/20] android/handsfree: Add comment for AT+VGS/AT+VGM result code
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (18 preceding siblings ...)
  2014-03-08  0:20 ` [PATCH 19/20] android/handsfree: Add support for AT+CLIP command Szymon Janc
@ 2014-03-08  0:20 ` Szymon Janc
  2014-03-10 11:50 ` [PATCH 00/20] More Android Handsfree work Szymon Janc
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc

---
 android/handsfree.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/android/handsfree.c b/android/handsfree.c
index 2a081ef..6b414d3 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -221,6 +221,7 @@ static void at_cmd_vgs_vgm(struct hfp_gw_result *result,
 		ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
 				HAL_EV_HANDSFREE_VOLUME, sizeof(ev), &ev);
 
+		/* Framework is not replying with result for AT+VGS/AT+VGM */
 		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
 
 		return;
-- 
1.8.5.3


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

* Re: [PATCH 03/20] android/handsfree: Add support for unknown AT commands
  2014-03-08  0:19 ` [PATCH 03/20] android/handsfree: Add support for unknown AT commands Szymon Janc
@ 2014-03-08  3:37   ` Marcel Holtmann
  2014-03-08 12:29     ` Szymon Janc
  0 siblings, 1 reply; 25+ messages in thread
From: Marcel Holtmann @ 2014-03-08  3:37 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth

Hi Szymon,

> Those commands are passed to Framework without parsing.
> ---
> android/handsfree.c | 64 ++++++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 54 insertions(+), 10 deletions(-)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index c49a35b..e104c4a 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -161,19 +161,35 @@ static void device_cleanup(void)
> 	memset(&device, 0, sizeof(device));
> }
> 
> -static void at_command_handler(const char *command, void *user_data)
> +static void disconnect_watch(void *user_data)
> {
> -	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +	DBG("");
> 
> -	if (device.state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED)
> -		hfp_gw_disconnect(device.gw);
> +	device_cleanup();
> }
> 
> -static void disconnect_watch(void *user_data)
> +static void at_cmd_unknown(const char *command, void *user_data)
> {
> -	DBG("");
> +	uint8_t buf[IPC_MTU];
> +	struct hal_ev_handsfree_unknown_at *ev = (void *) buf;
> 
> -	device_cleanup();
> +	if (device.state != HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED) {
> +		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +		hfp_gw_disconnect(device.gw);
> +		return;
> +	}
> +
> +	/* copy while string including terminating NULL */
> +	ev->len = strlen(command) + 1;
> +	memcpy(ev->buf, command, ev->len);
> +
> +	if (ev->len > IPC_MTU - sizeof(*ev)) {
> +		hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +		return;
> +	}
> +
> +	ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> +			HAL_EV_HANDSFREE_UNKNOWN_AT, sizeof(*ev) + ev->len, ev);
> }
> 
> static void at_cmd_vgs_vgm(struct hfp_gw_result *result,
> @@ -674,7 +690,7 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
> 	g_io_channel_set_close_on_unref(chan, FALSE);
> 
> 	hfp_gw_set_close_on_unref(device.gw, true);
> -	hfp_gw_set_command_handler(device.gw, at_command_handler, NULL, NULL);
> +	hfp_gw_set_command_handler(device.gw, at_cmd_unknown, NULL, NULL);
> 	hfp_gw_set_disconnect_handler(device.gw, disconnect_watch, NULL, NULL);
> 
> 
> @@ -1147,19 +1163,47 @@ static void handle_cind(const void *buf, uint16_t len)
> 
> static void handle_formatted_at_resp(const void *buf, uint16_t len)
> {
> +	const struct hal_cmd_handsfree_formatted_at_response *cmd = buf;
> +	char *at;
> +
> 	DBG("");
> 
> +	if (len != sizeof(*cmd) + cmd->len) {
> +		error("Invalid formatted AT response command, terminating");
> +		raise(SIGTERM);
> +		return;
> +	}
> +
> +	DBG("");
> +
> +	at = g_malloc0(cmd->len + 1);
> +
> +	memcpy(at, cmd->buf, cmd->len);
> +
> +	hfp_gw_send_info(device.gw, "%s", at);
> +
> +	g_free(at);
> +

is Android really passing AT commands around without \0 terminating them. That OS is really just plain silly.

Anyway, using strndupa seems more appropriate here.

I also wonder why not just using (.., “%.*s”, cmd->len, cmd->buf) here.

Regards

Marcel


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

* Re: [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec
  2014-03-08  0:19 ` [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec Szymon Janc
@ 2014-03-08  3:39   ` Marcel Holtmann
  0 siblings, 0 replies; 25+ messages in thread
From: Marcel Holtmann @ 2014-03-08  3:39 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth

Hi Szymon,

> ---
> android/handsfree.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 221 insertions(+), 2 deletions(-)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index 3fc4487..c49a35b 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -287,10 +287,190 @@ failed:
> 	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> }
> 
> +static void at_cmd_a(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_d(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_ccwa(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_chup(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_clcc(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_cmee(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_clip(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_vts(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_cnum(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_binp(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_bldn(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_bvra(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_nrec(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_bsir(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_btrh(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_bcc(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_bcs(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> +static void at_cmd_ckpd(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
> +							void *user_data)
> +{
> +	DBG("");
> +
> +	/* TODO */
> +
> +	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> +}
> +
> static void register_post_slc_at(void)
> {
> 	if (device.hsp) {
> -		/* TODO CKPD */
> +		hfp_gw_register(device.gw, at_cmd_ckpd, "+CKPD", NULL, NULL);
> 		hfp_gw_register(device.gw, at_cmd_vgs_vgm, "+VGS",
> 				GUINT_TO_POINTER(HAL_HANDSFREE_VOLUME_TYPE_SPEAKER),
> 				NULL);
> @@ -300,14 +480,31 @@ static void register_post_slc_at(void)
> 		return;
> 	}
> 
> -	hfp_gw_register(device.gw, at_cmd_bia, "+BIA", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_a, "A", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_d, "D", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_ccwa, "+CCWA", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_chup, "+CHUP", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_clcc, "+CLCC", NULL, NULL);
> 	hfp_gw_register(device.gw, at_cmd_cops, "+COPS", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_cmee, "+CMEE", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_clip, "+CLIP", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_vts, "+VTS", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_cnum, "+CNUM", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_bia, "+BIA", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_binp, "+BINP", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_bldn, "+BLDN", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_bvra, "+BVRA", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_nrec, "+NREC", NULL, NULL);
> 	hfp_gw_register(device.gw, at_cmd_vgs_vgm, "+VGS",
> 			GUINT_TO_POINTER(HAL_HANDSFREE_VOLUME_TYPE_SPEAKER),
> 			NULL);
> 	hfp_gw_register(device.gw, at_cmd_vgs_vgm, "+VGM",
> 			GUINT_TO_POINTER(HAL_HANDSFREE_VOLUME_TYPE_MIC),
> 			NULL);

can we start using the UINT_TO_PTR from src/shared/util.h please. However I get the feeling that using two separate callbacks is better here. Even if they in the end call the same helper function.

> +	hfp_gw_register(device.gw, at_cmd_bsir, "+BSIR", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_btrh, "+BTRH", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_bcc, "+BCC", NULL, NULL);
> +	hfp_gw_register(device.gw, at_cmd_bcs, "+BCS", NULL, NULL);
> }

Regards

Marcel


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

* Re: [PATCH 03/20] android/handsfree: Add support for unknown AT commands
  2014-03-08  3:37   ` Marcel Holtmann
@ 2014-03-08 12:29     ` Szymon Janc
  0 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-08 12:29 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: linux-bluetooth

Hi Marcel,

On Friday 07 of March 2014 19:37:00 Marcel Holtmann wrote:
> Hi Szymon,
>=20
> > Those commands are passed to Framework without parsing.
> > ---
> > android/handsfree.c | 64
> > ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file change=
d, 54
> > insertions(+), 10 deletions(-)
> >=20
> > diff --git a/android/handsfree.c b/android/handsfree.c
> > index c49a35b..e104c4a 100644
> > --- a/android/handsfree.c
> > +++ b/android/handsfree.c
> > @@ -161,19 +161,35 @@ static void device_cleanup(void)
> >=20
> > =09memset(&device, 0, sizeof(device));
> >=20
> > }
> >=20
> > -static void at_command_handler(const char *command, void *user_dat=
a)
> > +static void disconnect_watch(void *user_data)
> > {
> > -=09hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> > +=09DBG("");
> >=20
> > -=09if (device.state !=3D HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED=
)
> > -=09=09hfp_gw_disconnect(device.gw);
> > +=09device_cleanup();
> > }
> >=20
> > -static void disconnect_watch(void *user_data)
> > +static void at_cmd_unknown(const char *command, void *user_data)
> > {
> > -=09DBG("");
> > +=09uint8_t buf[IPC_MTU];
> > +=09struct hal_ev_handsfree_unknown_at *ev =3D (void *) buf;
> >=20
> > -=09device_cleanup();
> > +=09if (device.state !=3D HAL_EV_HANDSFREE_CONN_STATE_SLC_CONNECTED=
) {
> > +=09=09hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> > +=09=09hfp_gw_disconnect(device.gw);
> > +=09=09return;
> > +=09}
> > +
> > +=09/* copy while string including terminating NULL */
> > +=09ev->len =3D strlen(command) + 1;
> > +=09memcpy(ev->buf, command, ev->len);
> > +
> > +=09if (ev->len > IPC_MTU - sizeof(*ev)) {
> > +=09=09hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
> > +=09=09return;
> > +=09}
> > +
> > +=09ipc_send_notif(hal_ipc, HAL_SERVICE_ID_HANDSFREE,
> > +=09=09=09HAL_EV_HANDSFREE_UNKNOWN_AT, sizeof(*ev) + ev->len, ev);
> > }
> >=20
> > static void at_cmd_vgs_vgm(struct hfp_gw_result *result,
> > @@ -674,7 +690,7 @@ static void connect_cb(GIOChannel *chan, GError=
 *err,
> > gpointer user_data)>=20
> > =09g_io_channel_set_close_on_unref(chan, FALSE);
> > =09
> > =09hfp_gw_set_close_on_unref(device.gw, true);
> >=20
> > -=09hfp_gw_set_command_handler(device.gw, at_command_handler, NULL,=
 NULL);
> > +=09hfp_gw_set_command_handler(device.gw, at_cmd_unknown, NULL, NUL=
L);
> >=20
> > =09hfp_gw_set_disconnect_handler(device.gw, disconnect_watch, NULL,=
=20
NULL);
> >=20
> > @@ -1147,19 +1163,47 @@ static void handle_cind(const void *buf, ui=
nt16_t
> > len)
> >=20
> > static void handle_formatted_at_resp(const void *buf, uint16_t len)=

> > {
> > +=09const struct hal_cmd_handsfree_formatted_at_response *cmd =3D b=
uf;
> > +=09char *at;
> > +
> >=20
> > =09DBG("");
> >=20
> > +=09if (len !=3D sizeof(*cmd) + cmd->len) {
> > +=09=09error("Invalid formatted AT response command, terminating");=

> > +=09=09raise(SIGTERM);
> > +=09=09return;
> > +=09}
> > +
> > +=09DBG("");
> > +
> > +=09at =3D g_malloc0(cmd->len + 1);
> > +
> > +=09memcpy(at, cmd->buf, cmd->len);
> > +
> > +=09hfp_gw_send_info(device.gw, "%s", at);
> > +
> > +=09g_free(at);
> > +
>=20
> is Android really passing AT commands around without \0 terminating t=
hem.
> That OS is really just plain silly.

This is due to how we currently send strings overs IPC. There is string=
 type=20
in our IPC doc, but not in hal-msg.h. I'll fix that.

>=20
> Anyway, using strndupa seems more appropriate here.
>=20
> I also wonder why not just using (.., =E2=80=9C%.*s=E2=80=9D, cmd->le=
n, cmd->buf) here.

I'll use that.

> Regards
>=20
> Marcel

--=20
BR
Szymon Janc

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

* Re: [PATCH 00/20] More Android Handsfree work
  2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
                   ` (19 preceding siblings ...)
  2014-03-08  0:20 ` [PATCH 20/20] android/handsfree: Add comment for AT+VGS/AT+VGM result code Szymon Janc
@ 2014-03-10 11:50 ` Szymon Janc
  20 siblings, 0 replies; 25+ messages in thread
From: Szymon Janc @ 2014-03-10 11:50 UTC (permalink / raw)
  To: linux-bluetooth

On Saturday 08 of March 2014 01:19:44 Szymon Janc wrote:
> Hi,
> 
> This patchset adds support for basic handsfree functionality.
> 
> What is done:
>  - indicators (without callheld)
>  - placing, accepting, cancelling calls etc.
>  - vendor (unknown) AT command handling
>  - extended error codes
>  - DTMF codes
>  - query current calls
>  - voice recognition on/off
>  - disabling echo cancellation
>  - subscriber and operator identification
> 
> Missing features:
>  - proper three way calling support (AT+CHLD is supported but callheld
>    and CCWA are missing).
>  - WBS and codec negotiation
>  - audio
> 
> 

Updated version of this patchset (fixing comments from Marcel) is now upstream.

-- 
Best regards, 
Szymon Janc

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

end of thread, other threads:[~2014-03-10 11:50 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-08  0:19 [PATCH 00/20] More Android Handsfree work Szymon Janc
2014-03-08  0:19 ` [PATCH 01/20] android/handsfree: Add AG and HF features masks Szymon Janc
2014-03-08  0:19 ` [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec Szymon Janc
2014-03-08  3:39   ` Marcel Holtmann
2014-03-08  0:19 ` [PATCH 03/20] android/handsfree: Add support for unknown AT commands Szymon Janc
2014-03-08  3:37   ` Marcel Holtmann
2014-03-08 12:29     ` Szymon Janc
2014-03-08  0:19 ` [PATCH 04/20] android/handsfree: Add support for voice recognition function Szymon Janc
2014-03-08  0:19 ` [PATCH 05/20] android/handsfree: Add support for AT+NREC command Szymon Janc
2014-03-08  0:19 ` [PATCH 06/20] android/handsfree: Add support for AT+CLCC command Szymon Janc
2014-03-08  0:19 ` [PATCH 07/20] android/handsfree: Add support for AT+CHLD command Szymon Janc
2014-03-08  0:19 ` [PATCH 08/20] android/handsfree: Add support for AT+CMEE command Szymon Janc
2014-03-08  0:19 ` [PATCH 09/20] android/handsfree: Add support for AT+CKPD command Szymon Janc
2014-03-08  0:19 ` [PATCH 10/20] android/handsfree: Add support fot AT+CNUM command Szymon Janc
2014-03-08  0:19 ` [PATCH 11/20] android/handsfree: Add support for AT+VTS command Szymon Janc
2014-03-08  0:19 ` [PATCH 12/20] android/handsfree: Add support for ATA command Szymon Janc
2014-03-08  0:19 ` [PATCH 13/20] android/handsfree: Fix checking AT+COPS parameters Szymon Janc
2014-03-08  0:19 ` [PATCH 14/20] android/handsfree: Add support for ATD command Szymon Janc
2014-03-08  0:19 ` [PATCH 15/20] android/handsfree: Add support for AT+BLDN command Szymon Janc
2014-03-08  0:20 ` [PATCH 16/20] android/handsfree: Add support for AT+CHUP command Szymon Janc
2014-03-08  0:20 ` [PATCH 17/20] android/hal-handsfree: Fix handling of dial notification Szymon Janc
2014-03-08  0:20 ` [PATCH 18/20] android/handsfree: Add support for phone state change command Szymon Janc
2014-03-08  0:20 ` [PATCH 19/20] android/handsfree: Add support for AT+CLIP command Szymon Janc
2014-03-08  0:20 ` [PATCH 20/20] android/handsfree: Add comment for AT+VGS/AT+VGM result code Szymon Janc
2014-03-10 11:50 ` [PATCH 00/20] More Android Handsfree work Szymon Janc

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.