Re: [PATCH 1/3] android/handsfree: Add initial implementation of Codec Negotiation feature

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

 



hi Marcin,

On Thursday 13 March 2014 15:04:35 Marcin Kraglak wrote:
> It will handle AT+BAC command and update list of available codecs.
> It will check if mandatory codec CVSD is present on list and, if
> Wide Band Speech supported, MSBC codec is on next place. Other codecs
> can be also used after extending codecs_defaults array.
> It will also handle incorrect SLC establishment, when HF supports
> Codec Negotiation, but didn't send AT+BAC.
> ---
>  android/handsfree.c | 94
> +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92
> insertions(+), 2 deletions(-)
> 
> diff --git a/android/handsfree.c b/android/handsfree.c
> index b71c28e..44d1f32 100644
> --- a/android/handsfree.c
> +++ b/android/handsfree.c
> @@ -71,7 +71,8 @@
> 
>  #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_ECS | HFP_AG_FEAT_EXT_ERR |\
> +			HFP_AG_FEAT_CODEC )
> 
>  #define HFP_AG_CHLD "0,1,2,3"
> 
> @@ -87,6 +88,13 @@
> 
>  #define RING_TIMEOUT 2
> 
> +#define CVSD_OFFSET 0
> +#define MSBC_OFFSET 1
> +#define CODECS_COUNT (MSBC_OFFSET + 1)
> +
> +#define CODEC_ID_CVSD 0x01
> +#define CODEC_ID_MSBC 0x02
> +
>  struct indicator {
>  	const char *name;
>  	int min;
> @@ -96,6 +104,12 @@ struct indicator {
>  	bool active;
>  };
> 
> +struct hfp_codec {
> +	uint8_t type;
> +	bool local_supported;
> +	bool remote_supported;
> +};
> +
>  static const struct indicator inds_defaults[] = {
>  		{ "service",   0, 1, 0, false, true },
>  		{ "call",      0, 1, 0, true, true },
> @@ -106,6 +120,11 @@ static const struct indicator inds_defaults[] = {
>  		{ "battchg",   0, 5, 0, false, true },
>  };
> 
> +static const struct hfp_codec codecs_defaults[] = {
> +	{ CODEC_ID_CVSD, true, false},
> +	{ CODEC_ID_MSBC, false, false},
> +};
> +
>  static struct {
>  	bdaddr_t bdaddr;
>  	uint8_t state;
> @@ -116,6 +135,9 @@ static struct {
>  	bool ccwa_enabled;
>  	bool indicators_enabled;
>  	struct indicator inds[IND_COUNT];
> +	uint8_t negotiated_codec;
> +	uint8_t proposed_codec;
> +	struct hfp_codec codecs[CODECS_COUNT];
>  	guint ring;
>  	bool hsp;
>  	struct hfp_gw *gw;
> @@ -180,6 +202,8 @@ static void device_init(const bdaddr_t *bdaddr)
> 
>  	memcpy(device.inds, inds_defaults, sizeof(device.inds));
> 
> +	memcpy(device.codecs, codecs_defaults, sizeof(device.codecs));
> +
>  	device_set_state(HAL_EV_HANDSFREE_CONN_STATE_CONNECTING);
>  }
> 
> @@ -924,6 +948,13 @@ static void at_cmd_cind(struct hfp_gw_result *result,
> enum hfp_gw_cmd_type type, switch (type) {
>  	case HFP_GW_CMD_TYPE_TEST:
> 
> +		/* If device supports Codec Negotiation, AT+BAC should be
> +		 * received first
> +		 */
> +		if ((device.features & HFP_HF_FEAT_CODEC))
> +			if (!device.codecs[CVSD_OFFSET].remote_supported)
> +				break;
> +
>  		len = strlen("+CIND:") + 1;
> 
>  		for (i = 0; i < IND_COUNT; i++) {
> @@ -1032,13 +1063,72 @@ static void at_cmd_chld(struct hfp_gw_result
> *result, enum hfp_gw_cmd_type type, hfp_gw_send_result(device.gw,
> HFP_RESULT_ERROR);
>  }
> 
> +static struct hfp_codec *find_codec_by_type(uint8_t type)
> +{
> +	int i;
> +
> +	for (i = 0; i < CODECS_COUNT; i++)
> +		if (type == device.codecs[i].type)
> +			return &device.codecs[i];
> +
> +	return NULL;
> +}
> +
>  static void at_cmd_bac(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 (!(device.features & HFP_HF_FEAT_CODEC))
> +			goto failed;
> +
> +		/* Clear list of codecs */
> +		memcpy(device.codecs, codecs_defaults, sizeof(device.codecs));
> +		device.negotiated_codec = 0;
> +
> +		/* At least CVSD mandatory codec must exist
> +		 * HFP V1.6 4.34.1
> +		 */
> +		if (!hfp_gw_result_get_number(result, &val)
> +				|| val != CODEC_ID_CVSD)
> +			goto failed;
> 
> +		device.codecs[CVSD_OFFSET].remote_supported = true;
> +
> +		if (hfp_gw_result_get_number(result, &val)) {
> +			if (val != CODEC_ID_MSBC)
> +				goto failed;
> +
> +			device.codecs[MSBC_OFFSET].remote_supported = true;
> +		}
> +
> +		while (hfp_gw_result_has_next(result)) {
> +			struct hfp_codec *codec;
> +
> +			if (!hfp_gw_result_get_number(result, &val))
> +				goto failed;
> +
> +			codec = find_codec_by_type(val);
> +			if (!codec)
> +				continue;
> +
> +			codec->remote_supported = true;
> +		}
> +
> +		hfp_gw_send_result(device.gw, HFP_RESULT_OK);
> +
> +		return;
> +	case HFP_GW_CMD_TYPE_TEST:
> +	case HFP_GW_CMD_TYPE_READ:
> +	case HFP_GW_CMD_TYPE_COMMAND:
> +		break;
> +	}
> +
> +failed:
>  	hfp_gw_send_result(device.gw, HFP_RESULT_ERROR);
>  }

All patches applied, thanks.

I had to fix some coding style issues though, so please pay attention on that 
in future.

-- 
Szymon K. Janc
szymon.janc@xxxxxxxxx
--
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