From: Daniel Wagner <daniel.wag...@bmw-carit.de>

---
 drivers/atmodem/gprs.c |  170 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 170 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/gprs.c b/drivers/atmodem/gprs.c
index bf82d06..9988217 100644
--- a/drivers/atmodem/gprs.c
+++ b/drivers/atmodem/gprs.c
@@ -48,8 +48,84 @@ static const char *none_prefix[] = { NULL };
 struct gprs_data {
        GAtChat *chat;
        unsigned int vendor;
+       int ossysi; /* option hso 2G/3G info */
+       int octi; /* option hso 2G info details */
+       int ouwcti; /* otpion hso 3G info details */
 };
 
+static int option_octi_to_tech(struct gprs_data *gd)
+{
+       int tech = -1;
+       switch (gd->octi) {
+       case 1: /* GSM */
+               tech = 0;
+               break;
+       case 2: /* GPRS */
+               tech = 1;
+               break;
+       case 3: /* EDGE */
+               tech = 3;
+       }
+
+       return tech;
+}
+
+static int option_ouwcti_to_tech(struct gprs_data *gd)
+{
+       int tech = -1;
+
+       switch (gd->ouwcti) {
+       case 1: /* UMTS */
+               tech = 2;
+               break;
+       case 2: /* HSDPA */
+               tech = 4;
+               break;
+       case 3: /* HSUPA */
+               tech = 5;
+               break;
+       case 4: /* HSPA */
+               tech = 6;
+       }
+
+       return tech;
+}
+
+static int option_get_tech(struct gprs_data *gd)
+{
+       int tech = -1;
+       int tech_2g, tech_3g;
+
+       switch (gd->ossysi) {
+       case -1:
+               tech_2g = option_octi_to_tech(gd);
+               tech_3g = option_ouwcti_to_tech(gd);
+
+               /* 3G tech takes precedence over 2G tech */
+               if (tech_3g == -1)
+                       tech = tech_2g;
+               else
+                       tech = tech_3g;
+               break;
+       case 0: /* 2G */
+               tech = option_octi_to_tech(gd);
+               break;
+       case 2: /* 3G */
+               tech = option_ouwcti_to_tech(gd);
+               break;
+       case 3: /* Unknown */
+               /* reset all ossysi and octi */
+               gd->octi = -1;
+               gd->ossysi = -1;
+               break;
+       }
+
+       DBG("ossysi %d octi %d ouwcti %d tech %d",
+               gd->ossysi, gd->octi, gd->ouwcti, tech);
+
+       return tech;
+}
+
 static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
        struct cb_data *cbd = user_data;
@@ -142,6 +218,67 @@ error:
        CALLBACK_WITH_FAILURE(cb, -1, data);
 }
 
+static void option_ossysi_notify(GAtResult *result, gpointer user_data)
+{
+       struct ofono_gprs *gprs = user_data;
+       struct gprs_data *gd = ofono_gprs_get_data(gprs);
+       GAtResultIter iter;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "_OSSYSI:"))
+               return;
+
+       if (!g_at_result_iter_next_number(&iter, &gd->ossysi))
+               return;
+
+       ofono_gprs_technology_notify(gprs, option_get_tech(gd));
+}
+
+static void option_octi_notify(GAtResult *result, gpointer user_data)
+{
+       struct ofono_gprs *gprs = user_data;
+       struct gprs_data *gd = ofono_gprs_get_data(gprs);
+       GAtResultIter iter;
+       int mode;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "_OCTI:"))
+               return;
+
+       if (!g_at_result_iter_next_number(&iter, &gd->octi))
+               return;
+
+       /* Handle query responses too */
+       if (!g_at_result_iter_next_number(&iter, &mode) == FALSE)
+               gd->octi = mode;
+
+       ofono_gprs_technology_notify(gprs, option_get_tech(gd));
+}
+
+static void option_ouwcti_notify(GAtResult *result, gpointer user_data)
+{
+       struct ofono_gprs *gprs = user_data;
+       struct gprs_data *gd = ofono_gprs_get_data(gprs);
+       GAtResultIter iter;
+       int mode;
+
+       g_at_result_iter_init(&iter, result);
+
+       if (!g_at_result_iter_next(&iter, "_OUWCTI:"))
+               return;
+
+       if (!g_at_result_iter_next_number(&iter, &gd->ouwcti))
+               return;
+
+       /* Handle query responses too */
+       if (!g_at_result_iter_next_number(&iter, &mode) == FALSE)
+               gd->ouwcti = mode;
+
+       ofono_gprs_technology_notify(gprs, option_get_tech(gd));
+}
+
 static void cgreg_notify(GAtResult *result, gpointer user_data)
 {
        struct ofono_gprs *gprs = user_data;
@@ -153,6 +290,20 @@ static void cgreg_notify(GAtResult *result, gpointer 
user_data)
                return;
 
        ofono_gprs_status_notify(gprs, status);
+
+       switch (gd->vendor) {
+       case OFONO_VENDOR_OPTION_HSO:
+               /*
+                * After attaching Option modems will send an unsolicited
+                * CGREG. Unfortunalty, the technology messages
+                * appear before we are attached. So we need to update the core
+                * about the current technology after we tell the core we are
+                * attached. Otherwise, the CurrentTechnology property wont be
+                * updated until a technology change happends.
+                */
+               ofono_gprs_technology_notify(gprs, option_get_tech(gd));
+               break;
+       }
 }
 
 static void cgev_notify(GAtResult *result, gpointer user_data)
@@ -181,6 +332,25 @@ static void gprs_initialized(gboolean ok, GAtResult 
*result, gpointer user_data)
        struct ofono_gprs *gprs = user_data;
        struct gprs_data *gd = ofono_gprs_get_data(gprs);
 
+       switch (gd->vendor) {
+       case OFONO_VENDOR_OPTION_HSO:
+               g_at_chat_register(gd->chat, "_OSSYSI:", option_ossysi_notify,
+                                       FALSE, gprs, NULL);
+               g_at_chat_register(gd->chat, "_OCTI:", option_octi_notify,
+                                       FALSE, gprs, NULL);
+               g_at_chat_register(gd->chat, "_OUWCTI:", option_ouwcti_notify,
+                                       FALSE, gprs, NULL);
+               g_at_chat_send(gd->chat, "AT_OCTI=1", none_prefix,
+                               NULL, NULL, NULL);
+               g_at_chat_send(gd->chat, "AT_OUWCTI=1", none_prefix,
+                               NULL, NULL, NULL);
+               g_at_chat_send(gd->chat, "AT_OCTI?", none_prefix,
+                               NULL, NULL, NULL);
+               g_at_chat_send(gd->chat, "AT_OUWCTI?", none_prefix,
+                               NULL, NULL, NULL);
+               break;
+       }
+
        g_at_chat_register(gd->chat, "+CGEV:", cgev_notify, FALSE, gprs, NULL);
        g_at_chat_register(gd->chat, "+CGREG:", cgreg_notify,
                                FALSE, gprs, NULL);
-- 
1.6.6.1

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to