hfp: Add initial SLC negotiation for HFP 1.7
authorDenis Kenzior <denkenz@gmail.com>
Mon, 20 Jan 2014 03:39:26 +0000 (21:39 -0600)
committerDenis Kenzior <denkenz@gmail.com>
Mon, 20 Oct 2014 18:40:28 +0000 (13:40 -0500)
drivers/hfpmodem/slc.c

index 34f2d5c..5e1fa28 100644 (file)
 #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: