[PATCH 2/2] android/handsfree: Add support for WBS mode

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for WBS mode in handsfree HAl as well as
redefining current modes.

"persist.sys.bluetooth.handsfree" property can be used to tune
handsfree HAL. Setting it to "hfp" or "hfp_wbs" values enables HFP
profile with narrowband only or with both narrowband and wideband
speech support. Any other value or lack of property defaults to
HSP only mode.
---

The open point is the name of property used to control mode. If it should be
persist.sys or maybe just ro. ? Do we want to allow priviledged user to be
able to runtime control which mode is enabled?

Note: property name must be <32 characters.

 android/hal-handsfree.c | 14 ++++++++++----
 android/hal-msg.h       |  4 +++-
 android/handsfree.c     | 51 +++++++++++++++++++++++++++++++++++--------------
 3 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/android/hal-handsfree.c b/android/hal-handsfree.c
index 31793b0..5a05975 100644
--- a/android/hal-handsfree.c
+++ b/android/hal-handsfree.c
@@ -28,6 +28,8 @@
 #include "ipc-common.h"
 #include "hal-ipc.h"
 
+#define MODE_PROPERTY_NAME "persist.sys.bluetooth.handsfree"
+
 static const bthf_callbacks_t *cbs = NULL;
 
 static bool interface_ready(void)
@@ -210,11 +212,15 @@ static uint8_t get_mode(void)
 {
 	char value[PROPERTY_VALUE_MAX];
 
-	if (property_get("bluetooth.handsfree_mode", value, "") > 0 &&
-					(!strcasecmp(value, "hsp_only")))
-		return HAL_MODE_HANDSFREE_HSP_ONLY;
+	if (property_get(MODE_PROPERTY_NAME, value, "") > 0 &&
+					(!strcasecmp(value, "hfp")))
+		return HAL_MODE_HANDSFREE_HFP;
+
+	if (property_get(MODE_PROPERTY_NAME, value, "") > 0 &&
+					(!strcasecmp(value, "hfp_wbs")))
+		return HAL_MODE_HANDSFREE_HFP_WBS;
 
-	return HAL_MODE_DEFAULT;
+	return HAL_MODE_HANDSFREE_HSP_ONLY;
 }
 
 static bt_status_t init(bthf_callbacks_t *callbacks)
diff --git a/android/hal-msg.h b/android/hal-msg.h
index e325f21..4c1f42b 100644
--- a/android/hal-msg.h
+++ b/android/hal-msg.h
@@ -426,7 +426,9 @@ struct hal_cmd_health_destroy_channel {
 
 /* Handsfree HAL API */
 
-#define HAL_MODE_HANDSFREE_HSP_ONLY		0x01
+#define HAL_MODE_HANDSFREE_HSP_ONLY		HAL_MODE_DEFAULT
+#define HAL_MODE_HANDSFREE_HFP			0x01
+#define HAL_MODE_HANDSFREE_HFP_WBS		0x02
 
 #define HAL_OP_HANDSFREE_CONNECT		0x01
 struct hal_cmd_handsfree_connect {
diff --git a/android/handsfree.c b/android/handsfree.c
index c8e5f8a..1afe011 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
@@ -71,8 +71,7 @@
 
 #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 |\
-			HFP_AG_FEAT_CODEC )
+			HFP_AG_FEAT_ECS | HFP_AG_FEAT_EXT_ERR )
 
 #define HFP_AG_CHLD "0,1,2,3"
 
@@ -153,6 +152,8 @@ static struct {
 	guint sco_watch;
 } device;
 
+static uint32_t hfp_ag_features = 0;
+
 static bdaddr_t adapter_addr;
 static struct ipc *hal_ipc = NULL;
 
@@ -204,6 +205,14 @@ static void device_set_audio_state(uint8_t state)
 				HAL_EV_HANDSFREE_AUDIO_STATE, sizeof(ev), &ev);
 }
 
+static void init_codecs(void)
+{
+	memcpy(device.codecs, codecs_defaults, sizeof(device.codecs));
+
+	if (hfp_ag_features & HFP_AG_FEAT_CODEC)
+		device.codecs[MSBC_OFFSET].local_supported = true;
+}
+
 static void device_init(const bdaddr_t *bdaddr)
 {
 	bacpy(&device.bdaddr, bdaddr);
@@ -212,7 +221,7 @@ static void device_init(const bdaddr_t *bdaddr)
 
 	memcpy(device.inds, inds_defaults, sizeof(device.inds));
 
-	memcpy(device.codecs, codecs_defaults, sizeof(device.codecs));
+	init_codecs();
 
 	device_set_state(HAL_EV_HANDSFREE_CONN_STATE_CONNECTING);
 }
@@ -1182,7 +1191,7 @@ static void at_cmd_brsf(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 		/* TODO verify features */
 		device.features = feat;
 
-		hfp_gw_send_info(device.gw, "+BRSF: %u", HFP_AG_FEATURES);
+		hfp_gw_send_info(device.gw, "+BRSF: %u", hfp_ag_features);
 		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
 		return;
 	case HFP_GW_CMD_TYPE_READ:
@@ -1257,8 +1266,8 @@ static void at_cmd_bac(struct hfp_gw_result *result, enum hfp_gw_cmd_type type,
 		if (!(device.features & HFP_HF_FEAT_CODEC))
 			goto failed;
 
-		/* Clear list of codecs */
-		memcpy(device.codecs, codecs_defaults, sizeof(device.codecs));
+		/* set codecs to defaults */
+		init_codecs();
 		device.negotiated_codec = 0;
 
 		/* At least CVSD mandatory codec must exist
@@ -2411,8 +2420,8 @@ static sdp_record_t *hfp_ag_record(void)
 	apseq = sdp_list_append(apseq, proto[1]);
 
 	/* 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 = hfp_ag_features & 0x0000003F;
+	if (hfp_ag_features & HFP_AG_FEAT_CODEC)
 		sdpfeat |= 0x00000020;
 	else
 		sdpfeat &= ~0x00000020;
@@ -2535,17 +2544,29 @@ bool bt_handsfree_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
 	if (!enable_hsp_ag())
 		return false;
 
-	if (mode != HAL_MODE_HANDSFREE_HSP_ONLY && !enable_hfp_ag()) {
-		cleanup_hsp_ag();
-		return false;
-	}
-
 	if (!enable_sco_server()) {
 		cleanup_hsp_ag();
-		cleanup_hfp_ag();
 		return false;
 	}
 
+	if (mode == HAL_MODE_HANDSFREE_HSP_ONLY)
+		goto done;
+
+	hfp_ag_features = HFP_AG_FEATURES;
+
+	if (mode == HAL_MODE_HANDSFREE_HFP_WBS)
+		hfp_ag_features |= HFP_AG_FEAT_CODEC;
+
+	if (enable_hfp_ag())
+		goto done;
+
+	cleanup_hsp_ag();
+	disable_sco_server();
+	hfp_ag_features = 0;
+
+	return false;
+
+done:
 	hal_ipc = ipc;
 	ipc_register(hal_ipc, HAL_SERVICE_ID_HANDSFREE, cmd_handlers,
 						G_N_ELEMENTS(cmd_handlers));
@@ -2563,4 +2584,6 @@ void bt_handsfree_unregister(void)
 	cleanup_hfp_ag();
 	cleanup_hsp_ag();
 	disable_sco_server();
+
+	hfp_ag_features = 0;
 }
-- 
1.8.5.3

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux