Diff between 1d5cf84f49fefc5388945ffd842d02bf2d639158 and b6b29c9aaef0bb5fa45c335c60f0e910c63feca8

Changed Files

File Additions Deletions Status
android/hal-handsfree.c +10 -4 modified
android/hal-msg.h +3 -1 modified
android/handsfree.c +37 -14 modified

Full Patch

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