Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH] bdaddr: Remove *_CP_SIZE defines
From: Petri Gynther @ 2014-03-07 22:55 UTC (permalink / raw)
  To: linux-bluetooth

Remove *_CP_SIZE defines and use sizeof(cp) instead.
---
 tools/bdaddr.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/tools/bdaddr.c b/tools/bdaddr.c
index ee9c01c..8356a8d 100644
--- a/tools/bdaddr.c
+++ b/tools/bdaddr.c
@@ -57,7 +57,6 @@ static int generic_reset_device(int dd)
 typedef struct {
 	bdaddr_t	bdaddr;
 } __attribute__ ((packed)) ericsson_write_bd_addr_cp;
-#define ERICSSON_WRITE_BD_ADDR_CP_SIZE 6
 
 static int ericsson_write_bd_addr(int dd, bdaddr_t *bdaddr)
 {
@@ -71,7 +70,7 @@ static int ericsson_write_bd_addr(int dd, bdaddr_t *bdaddr)
 	rq.ogf    = OGF_VENDOR_CMD;
 	rq.ocf    = OCF_ERICSSON_WRITE_BD_ADDR;
 	rq.cparam = &cp;
-	rq.clen   = ERICSSON_WRITE_BD_ADDR_CP_SIZE;
+	rq.clen   = sizeof(cp);
 	rq.rparam = NULL;
 	rq.rlen   = 0;
 
@@ -87,7 +86,6 @@ typedef struct {
 	uint8_t		flash_length;
 	uint8_t		flash_data[253];
 } __attribute__ ((packed)) ericsson_store_in_flash_cp;
-#define ERICSSON_STORE_IN_FLASH_CP_SIZE 255
 
 static int ericsson_store_in_flash(int dd, uint8_t user_id, uint8_t flash_length, uint8_t *flash_data)
 {
@@ -104,7 +102,7 @@ static int ericsson_store_in_flash(int dd, uint8_t user_id, uint8_t flash_length
 	rq.ogf    = OGF_VENDOR_CMD;
 	rq.ocf    = OCF_ERICSSON_STORE_IN_FLASH;
 	rq.cparam = &cp;
-	rq.clen   = ERICSSON_STORE_IN_FLASH_CP_SIZE;
+	rq.clen   = sizeof(cp);
 	rq.rparam = NULL;
 	rq.rlen   = 0;
 
@@ -199,7 +197,6 @@ static int csr_reset_device(int dd)
 typedef struct {
 	bdaddr_t	bdaddr;
 } __attribute__ ((packed)) ti_write_bd_addr_cp;
-#define TI_WRITE_BD_ADDR_CP_SIZE 6
 
 static int ti_write_bd_addr(int dd, bdaddr_t *bdaddr)
 {
@@ -213,7 +210,7 @@ static int ti_write_bd_addr(int dd, bdaddr_t *bdaddr)
 	rq.ogf    = OGF_VENDOR_CMD;
 	rq.ocf    = OCF_TI_WRITE_BD_ADDR;
 	rq.cparam = &cp;
-	rq.clen   = TI_WRITE_BD_ADDR_CP_SIZE;
+	rq.clen   = sizeof(cp);
 	rq.rparam = NULL;
 	rq.rlen   = 0;
 
@@ -227,7 +224,6 @@ static int ti_write_bd_addr(int dd, bdaddr_t *bdaddr)
 typedef struct {
 	bdaddr_t	bdaddr;
 } __attribute__ ((packed)) bcm_write_bd_addr_cp;
-#define BCM_WRITE_BD_ADDR_CP_SIZE 6
 
 static int bcm_write_bd_addr(int dd, bdaddr_t *bdaddr)
 {
@@ -241,7 +237,7 @@ static int bcm_write_bd_addr(int dd, bdaddr_t *bdaddr)
 	rq.ogf    = OGF_VENDOR_CMD;
 	rq.ocf    = OCF_BCM_WRITE_BD_ADDR;
 	rq.cparam = &cp;
-	rq.clen   = BCM_WRITE_BD_ADDR_CP_SIZE;
+	rq.clen   = sizeof(cp);
 	rq.rparam = NULL;
 	rq.rlen   = 0;
 
@@ -255,7 +251,6 @@ static int bcm_write_bd_addr(int dd, bdaddr_t *bdaddr)
 typedef struct {
 	bdaddr_t	bdaddr;
 } __attribute__ ((packed)) zeevo_write_bd_addr_cp;
-#define ZEEVO_WRITE_BD_ADDR_CP_SIZE 6
 
 static int zeevo_write_bd_addr(int dd, bdaddr_t *bdaddr)
 {
@@ -269,7 +264,7 @@ static int zeevo_write_bd_addr(int dd, bdaddr_t *bdaddr)
 	rq.ogf    = OGF_VENDOR_CMD;
 	rq.ocf    = OCF_ZEEVO_WRITE_BD_ADDR;
 	rq.cparam = &cp;
-	rq.clen   = ZEEVO_WRITE_BD_ADDR_CP_SIZE;
+	rq.clen   = sizeof(cp);
 	rq.rparam = NULL;
 	rq.rlen   = 0;
 
-- 
1.9.0.279.gdc9e3eb


^ permalink raw reply related

* [PATCH 00/20] More Android Handsfree work
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

* [PATCH 01/20] android/handsfree: Add AG and HF features masks
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 03/20] android/handsfree: Add support for unknown AT commands
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 04/20] android/handsfree: Add support for voice recognition function
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 05/20] android/handsfree: Add support for AT+NREC command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 06/20] android/handsfree: Add support for AT+CLCC command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 07/20] android/handsfree: Add support for AT+CHLD command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 08/20] android/handsfree: Add support for AT+CMEE command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 09/20] android/handsfree: Add support for AT+CKPD command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 10/20] android/handsfree: Add support fot AT+CNUM command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 11/20] android/handsfree: Add support for AT+VTS command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 12/20] android/handsfree: Add support for ATA command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 13/20] android/handsfree: Fix checking AT+COPS parameters
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 14/20] android/handsfree: Add support for ATD command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 15/20] android/handsfree: Add support for AT+BLDN command
From: Szymon Janc @ 2014-03-08  0:19 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 16/20] android/handsfree: Add support for AT+CHUP command
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 17/20] android/hal-handsfree: Fix handling of dial notification
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 18/20] android/handsfree: Add support for phone state change command
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 19/20] android/handsfree: Add support for AT+CLIP command
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* [PATCH 20/20] android/handsfree: Add comment for AT+VGS/AT+VGM result code
From: Szymon Janc @ 2014-03-08  0:20 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Szymon Janc
In-Reply-To: <1394238004-15691-1-git-send-email-szymon.janc@tieto.com>

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

* Re: [PATCH 03/20] android/handsfree: Add support for unknown AT commands
From: Marcel Holtmann @ 2014-03-08  3:37 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1394238004-15691-4-git-send-email-szymon.janc@tieto.com>

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

* Re: [PATCH 02/20] android/handsfree: Add stubs for all AT commands defines by spec
From: Marcel Holtmann @ 2014-03-08  3:39 UTC (permalink / raw)
  To: Szymon Janc; +Cc: linux-bluetooth
In-Reply-To: <1394238004-15691-3-git-send-email-szymon.janc@tieto.com>

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

* Re: Passive scanning of iBeacons results in a "Data Buffer Overflow"
From: Terry Hardie @ 2014-03-08  7:19 UTC (permalink / raw)
  To: linux-bluetooth
In-Reply-To: <6E6C1573-4744-486B-B2E6-2D3DC45D024B@warski.org>

Hi guys,

I'm having something similar to what Adam is reporting. I'm running on a 
BeagleBone Black, which uses a TI MUSB controller (I think it's different 
to the Raspberry Pi USB controller?).

I have 2 vendor's USB bluetooth receivers.

One is a Cambridge Silicon Radio (0a12:0001) and the other is a Broadcom 
BCM20702A1 (0a5c:21e8). The Broadcom needs a RAM patch to behave slightly 
better, but it outside the scope of this problem. BOTH exhibit the same 
problem (so I seriously doubt it's a problem with the Bluetooth receivers)

Both devices are operating in HCI mode. I'm running Ubuntu on my 
BeagleBone Black.

I've also built the latest version of Bluez (5.15)

The problem is when running a lescan (hcitool lescan) with a LE device in 
paring mode, which is transmitting a lot of LE Advertising report packets, 
the HCI drivers eventually loses sync. I've traced it down to a duplicate 
USB fragment.

I've tested these USB receivers under Ubuntu on an Intel machine with the 
same Bluez 5.15, and the problem is not present.

hcidump shows when things go crazy:

2014-03-08 06:32:12.111970 > HCI Event: LE Meta Event (0x3e) plen 33
     LE Advertising Report
       ADV_IND - Connectable undirected advertising (0)
       bdaddr E1:F9:7C:05:30:3C (Random)
       Flags: 0x05
       Complete local name: 'Scosche PROX'
       Unknown type 0x19 with 2 bytes data
       RSSI: -62
2014-03-08 06:32:12.163087 > HCI Event: Unknown (0x00) plen 2
   C7 3E
2014-03-08 06:32:12.163136 > HCI Event: Flow Specification Complete (0x21) 
plen 2
     status 0x01 handle 0x0000 flags 1 incoming
     Error: Unknown HCI Command
2014-03-08 06:32:12.192009 > HCI Event: Inquiry Complete (0x01) plen 60
     status 0x30
     Error: Parameter out of Mandatory Range
     05 7C F9 E1 15 02 01 05 0D 09 53 63 6F 73 63 68 65 20 50 52
     4F 58 03 19 00 02 C5 3E 21 02 01 00 01 3C 30 05 7C F9 E1 15
     02 01 05 0D 09 53 63 6F 73 63 68 65 20 50 52 4F 58 03 19
2014-03-08 06:32:12.218055 > HCI Event: Unknown (0x00) plen 2
   C5 3E

I added some code to btusb_intr_complete to print each urb as it comes up 
from the USB stack. Here's the output for the above problem. Note the 
extra "00 02 c7" -- Should not be there...

Mar  8 06:32:12 arm kernel: [  122.915094] hci1 urb df4a8540 status 0 count 16 flags 768
Mar  8 06:32:12 arm kernel: [  122.915176] hci1 urb contents:  3e 21 02 01 00 01 3c 30 05 7c f9 e1 15 02 01 05
Mar  8 06:32:12 arm kernel: [  122.916004] hci1 urb df4a8540 status 0 count 16 flags 768
Mar  8 06:32:12 arm kernel: [  122.916085] hci1 urb contents:  0d 09 53 63 6f 73 63 68 65 20 50 52 4f 58 03 19
Mar  8 06:32:12 arm kernel: [  122.916985] hci1 urb df4a8540 status 0 count 3 flags 768
Mar  8 06:32:12 arm kernel: [  122.917018] hci1 urb contents:  00 02 c2
Mar  8 06:32:12 arm kernel: [  122.942995] hci1 urb df4a8540 status 0 count 3 flags 768
Mar  8 06:32:12 arm kernel: [  122.943028] hci1 urb contents:  00 02 c7

I used usbmon to do a "sniff" of the USB traffic. Here's a snippet of a 
correct HCI LE Advertising report event, followed by one where the middle 
fragment is repeated (frame 1300 is a repeat) This is a different capture 
from the above example. I can provide the pcap somewhere if needed

No.     Time                       Source                Destination           Protocol Length Info
    1291 2014-03-07 02:40:16.942573 host                  3.1                   USB      64     URB_INTERRUPT in
    1292 2014-03-07 02:40:16.959480 3.1                   host                  HCI_USB  80     Rcvd Fragment
3e21020100013c30057cf9e115020105
    1293 2014-03-07 02:40:16.959624 host                  3.1                   USB      64     URB_INTERRUPT in
    1294 2014-03-07 02:40:16.960449 3.1                   host                  HCI_USB  80     Rcvd Fragment
0d0953636f736368652050524f580319
    1295 2014-03-07 02:40:16.960546 host                  3.1                   USB      64     URB_INTERRUPT in
    1296 2014-03-07 02:40:16.961455 3.1                   host                  HCI_EVT  67     Rcvd LE Meta (LE Advertising Report)
0002ae
    1297 2014-03-07 02:40:16.961560 host                  3.1                   USB      64     URB_INTERRUPT in
    1298 2014-03-07 02:40:16.981627 3.1                   host                  HCI_USB  80     Rcvd Fragment
3e21020100013c30057cf9e115020105
    1299 2014-03-07 02:40:16.981696 host                  3.1                   USB      64     URB_INTERRUPT in
    1300 2014-03-07 02:40:17.002651 3.1                   host                  HCI_USB  80     Rcvd Fragment
3e21020100013c30057cf9e115020105
    1301 2014-03-07 02:40:17.002720 host                  3.1                   USB      64     URB_INTERRUPT in
    1302 2014-03-07 02:40:17.003560 3.1                   host                  HCI_USB  80     Rcvd Fragment
0d0953636f736368652050524f580319
    1303 2014-03-07 02:40:17.003649 host                  3.1                   USB      64     URB_INTERRUPT in
    1304 2014-03-07 02:40:17.004567 3.1                   host                  HCI_USB  67     Rcvd Fragment
0002b5



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox