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