From fa105c4ba6dbb7acce585ab6e00f71f2aba9db8f Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Sun, 19 Jan 2014 21:39:26 -0600 Subject: [PATCH] hfp: Add initial SLC negotiation for HFP 1.7 --- drivers/hfpmodem/slc.c | 95 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/hfpmodem/slc.c b/drivers/hfpmodem/slc.c index 34f2d5c0..5e1fa28b 100644 --- a/drivers/hfpmodem/slc.c +++ b/drivers/hfpmodem/slc.c @@ -41,10 +41,12 @@ #include "hfp.h" #include "slc.h" +static const char *none_prefix[] = { NULL }; static const char *brsf_prefix[] = { "+BRSF:", NULL }; static const char *cind_prefix[] = { "+CIND:", NULL }; static const char *cmer_prefix[] = { "+CMER:", NULL }; static const char *chld_prefix[] = { "+CHLD:", NULL }; +static const char *bind_prefix[] = { "+BIND:", NULL }; struct slc_establish_data { gint ref_count; @@ -107,6 +109,90 @@ static void slc_established(struct slc_establish_data *sed) sed->connect_cb(sed->userdata); } +static void bind_query_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct slc_establish_data *sed = user_data; + GAtResultIter iter; + int hf_indicator; + int enabled; + + if (!ok) + goto error; + + g_at_result_iter_init(&iter, result); + + while (g_at_result_iter_next(&iter, "+BIND:")) { + if (!g_at_result_iter_next_number(&iter, &hf_indicator)) + goto error; + + if (!g_at_result_iter_next_number(&iter, &enabled)) + goto error; + + ofono_info("AG wants indicator %d %s", + hf_indicator, enabled ? "enabled" : "disabled"); + } + + slc_established(sed); + return; + +error: + slc_failed(sed); +} + +static void bind_support_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct slc_establish_data *sed = user_data; + struct hfp_slc_info *info = sed->info; + GAtResultIter iter; + int hf_indicator; + + if (!ok) + goto error; + + g_at_result_iter_init(&iter, result); + + if (!g_at_result_iter_next(&iter, "+BIND:")) + goto error; + + if (!g_at_result_iter_open_list(&iter)) + goto error; + + while (g_at_result_iter_next_number(&iter, &hf_indicator)) { + ofono_info("AG supports the following indicator: %d", + hf_indicator); + + if (hf_indicator == HFP_HF_INDICATOR_ENHANCED_SAFETY) + ofono_info("Distracted Driving Reduction"); + } + + if (!g_at_result_iter_close_list(&iter)) + goto error; + + slc_establish_data_ref(sed); + g_at_chat_send(info->chat, "AT+BIND?", bind_prefix, + bind_query_cb, sed, slc_establish_data_unref); + + return; + +error: + slc_failed(sed); +} + +static void bind_set_cb(gboolean ok, GAtResult *result, gpointer user_data) +{ + struct slc_establish_data *sed = user_data; + struct hfp_slc_info *info = sed->info; + + if (!ok) { + slc_failed(sed); + return; + } + + slc_establish_data_ref(sed); + g_at_chat_send(info->chat, "AT+BIND=?", bind_prefix, + bind_support_cb, sed, slc_establish_data_unref); +} + static void chld_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct slc_establish_data *sed = user_data; @@ -148,7 +234,14 @@ static void chld_cb(gboolean ok, GAtResult *result, gpointer user_data) info->ag_mpty_features = ag_mpty_feature; - slc_established(sed); + if (info->ag_features & HFP_AG_FEATURE_HF_INDICATORS && + info->hf_features & HFP_HF_FEATURE_HF_INDICATORS) { + slc_establish_data_ref(sed); + g_at_chat_send(info->chat, "AT+BIND=1", none_prefix, + bind_set_cb, sed, slc_establish_data_unref); + } else + slc_established(sed); + return; error: