diff --git a/android/handsfree.c b/android/handsfree.c
index 9af3a2b..ac26af4 100644
--- a/android/handsfree.c
+++ b/android/handsfree.c
return FALSE;
}
+static void select_codec(uint8_t codec_type)
+{
+ uint8_t type = CODEC_ID_CVSD;
+ int i;
+
+ if (codec_type > 0) {
+ type = codec_type;
+ goto done;
+ }
+
+ for (i = CODECS_COUNT - 1; i >= CVSD_OFFSET; i--) {
+ if (!device.codecs[i].local_supported)
+ continue;
+
+ if (!device.codecs[i].remote_supported)
+ continue;
+
+ type = device.codecs[i].type;
+ break;
+ }
+
+done:
+ device.proposed_codec = type;
+
+ hfp_gw_send_info(device.gw, "+BCS: %u", type);
+}
+
static void connect_sco_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
if (err) {
status = HAL_EV_HANDSFREE_AUDIO_STATE_DISCONNECTED;
device_set_audio_state(status);
+ if (!(device.features & HFP_HF_FEAT_CODEC))
+ return;
+
+ if (device.negotiated_codec != CODEC_ID_CVSD)
+ /* If other failed, try connect CVSD */
+ select_codec(CODEC_ID_CVSD);
+
return;
}
{
GIOChannel *io;
GError *gerr = NULL;
+ uint16_t voice_settings;
if (device.sco)
return false;
+ if ((device.features & HFP_HF_FEAT_CODEC) && device.negotiated_codec
+ != CODEC_ID_CVSD)
+ voice_settings = BT_VOICE_TRANSPARENT;
+ else
+ voice_settings = BT_VOICE_CVSD_16BIT;
+
io = bt_io_connect(connect_sco_cb, NULL, NULL, &gerr,
BT_IO_OPT_SOURCE_BDADDR, &adapter_addr,
BT_IO_OPT_DEST_BDADDR, &device.bdaddr,
+ BT_IO_OPT_VOICE, voice_settings,
BT_IO_OPT_INVALID);
if (!io) {
{
DBG("");
- /* TODO */
+ switch (type) {
+ case HFP_GW_CMD_TYPE_COMMAND:
+ if (!(device.features & HFP_HF_FEAT_CODEC))
+ break;
+
+ if (hfp_gw_result_has_next(result))
+ break;
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+ /* we haven't negotiated codec, start selection */
+ if (!device.negotiated_codec) {
+ select_codec(0);
+ return;
+ }
+ /* we try connect to negotiated codec. If it fails, and it isn't
+ * CVSD codec, try connect CVSD
+ */
+ if (!connect_sco() && device.negotiated_codec != CODEC_ID_CVSD)
+ select_codec(CODEC_ID_CVSD);
+
+ 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);
}
static void at_cmd_bcs(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))
+ break;
+
+ if (hfp_gw_result_has_next(result))
+ break;
+
+ /* Remote replied with other codec. Reply with error */
+ if (device.proposed_codec != val) {
+ device.proposed_codec = 0;
+ break;
+ }
+
+ device.proposed_codec = 0;
+ device.negotiated_codec = val;
+
+ hfp_gw_send_result(device.gw, HFP_RESULT_OK);
+
+ /* Connect sco with negotiated parameters */
+ connect_sco();
+
+ 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);
}
return true;
}
+static bool connect_audio(void)
+{
+ if ((device.features & HFP_HF_FEAT_CODEC) && !device.negotiated_codec) {
+ /* It's probably first connection, select best codec
+ * and try connect
+ */
+ select_codec(0);
+ return true;
+ }
+
+ return connect_sco();
+}
+
static void handle_connect_audio(const void *buf, uint16_t len)
{
const struct hal_cmd_handsfree_connect_audio *cmd = buf;
goto done;
}
- status = connect_sco() ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
+ status = connect_audio() ? HAL_STATUS_SUCCESS : HAL_STATUS_FAILED;
done:
ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HANDSFREE,