Linux bluetooth development
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox