static gboolean check_append_or_replace (MMLocationGpsNmea *self, const gchar *trace) { /* By default, replace */ gboolean append_or_replace = FALSE; GMatchInfo *match_info = NULL; if (G_UNLIKELY (!self->priv->sequence_regex)) self->priv->sequence_regex = g_regex_new ("\\$GPGSV,(\\d),(\\d).*", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); if (g_regex_match (self->priv->sequence_regex, trace, 0, &match_info)) { guint index; /* If we don't have the first element of a sequence, append */ if (mm_get_uint_from_match_info (match_info, 2, &index) && index != 1) append_or_replace = TRUE; } g_match_info_free (match_info); return append_or_replace; }
static void erinfo_received (MMPortSerialAt *port, GMatchInfo *info, MMBroadbandModemMbm *self) { MMModemAccessTechnology act = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN; guint mode; if (mm_get_uint_from_match_info (info, 2, &mode)) { switch (mode) { case 1: act = MM_MODEM_ACCESS_TECHNOLOGY_GPRS; break; case 2: act = MM_MODEM_ACCESS_TECHNOLOGY_EDGE; break; default: break; } } /* 3G modes take precedence */ if (mm_get_uint_from_match_info (info, 3, &mode)) { switch (mode) { case 1: act = MM_MODEM_ACCESS_TECHNOLOGY_UMTS; break; case 2: act = MM_MODEM_ACCESS_TECHNOLOGY_HSDPA; break; case 3: act = MM_MODEM_ACCESS_TECHNOLOGY_HSPA; break; default: break; } } mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self), act, MM_IFACE_MODEM_3GPP_ALL_ACCESS_TECHNOLOGIES_MASK); }
static void e2nap_received (MMPortSerialAt *port, GMatchInfo *info, MMBroadbandModemMbm *self) { MMBearerList *list = NULL; guint state; BearerListReportStatusForeachContext ctx; if (!mm_get_uint_from_match_info (info, 1, &state)) return; ctx.status = MM_BEARER_CONNECTION_STATUS_UNKNOWN; switch (state) { case MBM_E2NAP_DISCONNECTED: mm_dbg ("disconnected"); ctx.status = MM_BEARER_CONNECTION_STATUS_DISCONNECTED; break; case MBM_E2NAP_CONNECTED: mm_dbg ("connected"); ctx.status = MM_BEARER_CONNECTION_STATUS_CONNECTED; break; case MBM_E2NAP_CONNECTING: mm_dbg ("connecting"); break; default: /* Should not happen */ mm_dbg ("unhandled E2NAP state %d", state); } /* If unknown status, don't try to report anything */ if (ctx.status == MM_BEARER_CONNECTION_STATUS_UNKNOWN) return; /* If empty bearer list, nothing else to do */ g_object_get (self, MM_IFACE_MODEM_BEARER_LIST, &list, NULL); if (!list) return; mm_bearer_list_foreach (list, (MMBearerListForeachFunc)bearer_list_report_status_foreach, &ctx); g_object_unref (list); }
static gchar * parse_time (const gchar *response, const gchar *regex, const gchar *tag, GError **error) { GRegex *r; GMatchInfo *match_info = NULL; GError *match_error = NULL; guint year, month, day, hour, minute, second; gchar *result = NULL; r = g_regex_new (regex, 0, 0, NULL); g_assert (r != NULL); if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { if (match_error) { g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse %s results: ", tag); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match %s reply", tag); } } else { if (mm_get_uint_from_match_info (match_info, 1, &year) && mm_get_uint_from_match_info (match_info, 2, &month) && mm_get_uint_from_match_info (match_info, 3, &day) && mm_get_uint_from_match_info (match_info, 4, &hour) && mm_get_uint_from_match_info (match_info, 5, &minute) && mm_get_uint_from_match_info (match_info, 6, &second)) { /* Return ISO-8601 format date/time string */ result = g_strdup_printf ("%04d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, minute, second); } else { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse %s reply", tag); } } if (match_info) g_match_info_free (match_info); g_regex_unref (r); return result; }
static gboolean parse_nwltime_reply (const char *response, gchar **out_iso_8601, MMNetworkTimezone **out_tz, GError **error) { GRegex *r; GMatchInfo *match_info = NULL; GError *match_error = NULL; guint year, month, day, hour, minute, second; gchar *result = NULL; gint utc_offset = 0; gboolean success = FALSE; /* Sample reply: 2013.3.27.15.47.19.2.-5 */ r = g_regex_new ("(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\\.([\\-\\+\\d]+)$", 0, 0, NULL); g_assert (r != NULL); if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { if (match_error) { g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse $NWLTIME results: "); } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match $NWLTIME reply"); } } else { /* Remember that g_match_info_get_match_count() includes match #0 */ g_assert (g_match_info_get_match_count (match_info) >= 9); if (mm_get_uint_from_match_info (match_info, 1, &year) && mm_get_uint_from_match_info (match_info, 2, &month) && mm_get_uint_from_match_info (match_info, 3, &day) && mm_get_uint_from_match_info (match_info, 4, &hour) && mm_get_uint_from_match_info (match_info, 5, &minute) && mm_get_uint_from_match_info (match_info, 6, &second) && mm_get_int_from_match_info (match_info, 8, &utc_offset)) { result = mm_new_iso8601_time (year, month, day, hour, minute, second, TRUE, utc_offset * 60); if (out_tz) { *out_tz = mm_network_timezone_new (); mm_network_timezone_set_offset (*out_tz, utc_offset * 60); } success = TRUE; } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse $NWLTIME reply"); } } if (out_iso_8601) *out_iso_8601 = result; else g_free (result); if (match_info) g_match_info_free (match_info); g_regex_unref (r); return success; }
static gboolean cache_port_mode (MMDevice *device, const gchar *reply) { GRegex *r = NULL; GRegexCompileFlags flags = G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW; GMatchInfo *match_info = NULL; GError *error = NULL; gboolean ret = FALSE; guint portcfg_current; /* #PORTCFG: <requested>,<active> */ r = g_regex_new ("#PORTCFG:\\s*(\\d+),(\\d+)", flags, 0, NULL); g_assert (r != NULL); if (!g_regex_match_full (r, reply, strlen (reply), 0, 0, &match_info, &error)) goto out; if (!mm_get_uint_from_match_info (match_info, 2, &portcfg_current)) { mm_dbg ("telit: unrecognized #PORTCFG <active> value"); goto out; } /* Reference for port configurations: * HE910/UE910/UL865 Families Ports Arrangements User Guide */ switch (portcfg_current) { case 0: case 1: case 4: case 5: case 7: case 9: case 10: case 11: g_object_set_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT, "00"); g_object_set_data (G_OBJECT (device), TAG_TELIT_AUX_PORT, "06"); break; case 2: case 3: case 6: g_object_set_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT, "00"); break; case 8: case 12: g_object_set_data (G_OBJECT (device), TAG_TELIT_MODEM_PORT, "00"); g_object_set_data (G_OBJECT (device), TAG_TELIT_AUX_PORT, "06"); g_object_set_data (G_OBJECT (device), TAG_TELIT_NMEA_PORT, "0a"); break; default: /* portcfg value not supported */ goto out; } ret = TRUE; out: g_match_info_free (match_info); g_regex_unref (r); if (error != NULL) { mm_dbg ("telit: error while matching: %s", error->message); g_error_free (error); } return ret; }
static void wwsm_read_ready (MMBaseModem *self, GAsyncResult *res, GSimpleAsyncResult *simple) { GRegex *r; GMatchInfo *match_info = NULL; LoadAllowedModesResult result; const gchar *response; GError *error = NULL; response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error); if (!response) { g_simple_async_result_take_error (simple, error); g_simple_async_result_complete (simple); g_object_unref (simple); return; } result.allowed = MM_MODEM_MODE_NONE; result.preferred = MM_MODEM_MODE_NONE; /* Possible responses: * +WWSM: 0 (2G only) * +WWSM: 1 (3G only) * +WWSM: 2,0 (Any) * +WWSM: 2,1 (2G preferred) * +WWSM: 2,2 (3G preferred) */ r = g_regex_new ("\\r\\n\\+WWSM: ([0-2])(,([0-2]))?.*$", 0, 0, NULL); g_assert (r != NULL); if (g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) { guint allowed = 0; if (mm_get_uint_from_match_info (match_info, 1, &allowed)) { switch (allowed) { case 0: result.allowed = MM_MODEM_MODE_2G; result.preferred = MM_MODEM_MODE_NONE; break; case 1: result.allowed = MM_MODEM_MODE_3G; result.preferred = MM_MODEM_MODE_NONE; break; case 2: { guint preferred = 0; result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); /* 3, to avoid the comma */ if (mm_get_uint_from_match_info (match_info, 3, &preferred)) { switch (preferred) { case 0: result.preferred = MM_MODEM_MODE_NONE; break; case 1: result.preferred = MM_MODEM_MODE_2G; break; case 2: result.preferred = MM_MODEM_MODE_3G; break; default: g_warn_if_reached (); break; } } break; } default: g_warn_if_reached (); break; } } } if (result.allowed == MM_MODEM_MODE_NONE) g_simple_async_result_set_error (simple, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Unknown wireless data service reply: '%s'", response); else g_simple_async_result_set_op_res_gpointer (simple, &result, NULL); g_simple_async_result_complete (simple); g_object_unref (simple); g_regex_unref (r); if (match_info) g_match_info_free (match_info); }
gboolean mm_huawei_parse_sysinfoex_response (const char *reply, guint *out_srv_status, guint *out_srv_domain, guint *out_roam_status, guint *out_sim_state, guint *out_sys_mode, guint *out_sys_submode, GError **error) { gboolean matched; GRegex *r; GMatchInfo *match_info = NULL; GError *match_error = NULL; g_assert (out_srv_status != NULL); g_assert (out_srv_domain != NULL); g_assert (out_roam_status != NULL); g_assert (out_sim_state != NULL); g_assert (out_sys_mode != NULL); g_assert (out_sys_submode != NULL); /* Format: * * ^SYSINFOEX: <srv_status>,<srv_domain>,<roam_status>,<sim_state>,<reserved>,<sysmode>,<sysmode_name>,<submode>,<submode_name> * * <sysmode_name> and <submode_name> may not be quoted on some Huawei modems (e.g. E303). */ /* ^SYSINFOEX:2,3,0,1,,3,"WCDMA",41,"HSPA+" */ r = g_regex_new ("\\^SYSINFOEX:\\s*(\\d+),(\\d+),(\\d+),(\\d+),?(\\d*),(\\d+),\"?([^\"]*)\"?,(\\d+),\"?([^\"]*)\"?$", 0, 0, NULL); g_assert (r != NULL); matched = g_regex_match_full (r, reply, -1, 0, 0, &match_info, &match_error); if (!matched) { if (match_error) { g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse ^SYSINFOEX results: "); } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match ^SYSINFOEX reply"); } } else { mm_get_uint_from_match_info (match_info, 1, out_srv_status); mm_get_uint_from_match_info (match_info, 2, out_srv_domain); mm_get_uint_from_match_info (match_info, 3, out_roam_status); mm_get_uint_from_match_info (match_info, 4, out_sim_state); /* We just ignore the sysmode and submode name strings */ mm_get_uint_from_match_info (match_info, 6, out_sys_mode); mm_get_uint_from_match_info (match_info, 8, out_sys_submode); } if (match_info) g_match_info_free (match_info); g_regex_unref (r); return matched; }
gboolean mm_huawei_parse_ndisstatqry_response (const gchar *response, gboolean *ipv4_available, gboolean *ipv4_connected, gboolean *ipv6_available, gboolean *ipv6_connected, GError **error) { GRegex *r; GMatchInfo *match_info; GError *inner_error = NULL; if (!response || !(g_ascii_strncasecmp (response, "^NDISSTAT:", strlen ("^NDISSTAT:")) == 0 || g_ascii_strncasecmp (response, "^NDISSTATQRY:", strlen ("^NDISSTATQRY:")) == 0)) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing ^NDISSTAT / ^NDISSTATQRY prefix"); return FALSE; } *ipv4_available = FALSE; *ipv6_available = FALSE; /* The response maybe as: * ^NDISSTAT: 1,,,IPV4 * ^NDISSTAT: 0,33,,IPV6 * ^NDISSTATQRY: 1,,,IPV4 * ^NDISSTATQRY: 0,33,,IPV6 * OK * * Or, in newer firmwares: * ^NDISSTATQRY:0,,,"IPV4",0,,,"IPV6" * OK * * Or, even (handled separately): * ^NDISSTATQry:1 * OK */ /* If multiple fields available, try first parsing method */ if (strchr (response, ',')) { r = g_regex_new ("\\^NDISSTAT(?:QRY)?(?:Qry)?:\\s*(\\d),([^,]*),([^,]*),([^,\\r\\n]*)(?:\\r\\n)?" "(?:\\^NDISSTAT:|\\^NDISSTATQRY:)?\\s*,?(\\d)?,?([^,]*)?,?([^,]*)?,?([^,\\r\\n]*)?(?:\\r\\n)?", G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); g_assert (r != NULL); g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); if (!inner_error && g_match_info_matches (match_info)) { guint ip_type_field = 4; /* IPv4 and IPv6 are fields 4 and (if available) 8 */ while (!inner_error && ip_type_field <= 8) { gchar *ip_type_str; guint connected; ip_type_str = mm_get_string_unquoted_from_match_info (match_info, ip_type_field); if (!ip_type_str) break; if (!mm_get_uint_from_match_info (match_info, (ip_type_field - 3), &connected) || (connected != 0 && connected != 1)) { inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't parse ^NDISSTAT / ^NDISSTATQRY fields"); } else if (g_ascii_strcasecmp (ip_type_str, "IPV4") == 0) { *ipv4_available = TRUE; *ipv4_connected = (gboolean)connected; } else if (g_ascii_strcasecmp (ip_type_str, "IPV6") == 0) { *ipv6_available = TRUE; *ipv6_connected = (gboolean)connected; } g_free (ip_type_str); ip_type_field += 4; } } g_match_info_free (match_info); g_regex_unref (r); } /* No separate IPv4/IPv6 info given just connected/not connected */ else { r = g_regex_new ("\\^NDISSTAT(?:QRY)?(?:Qry)?:\\s*(\\d)(?:\\r\\n)?", G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL); g_assert (r != NULL); g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error); if (!inner_error && g_match_info_matches (match_info)) { guint connected; if (!mm_get_uint_from_match_info (match_info, 1, &connected) || (connected != 0 && connected != 1)) { inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't parse ^NDISSTAT / ^NDISSTATQRY fields"); } else { /* We'll assume IPv4 */ *ipv4_available = TRUE; *ipv4_connected = (gboolean)connected; } } g_match_info_free (match_info); g_regex_unref (r); } if (!ipv4_available && !ipv6_available) { inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't find IPv4 or IPv6 info in ^NDISSTAT / ^NDISSTATQRY response"); } if (inner_error) { g_propagate_error (error, inner_error); return FALSE; } return TRUE; }
gboolean mm_huawei_parse_sysinfo_response (const char *reply, guint *out_srv_status, guint *out_srv_domain, guint *out_roam_status, guint *out_sys_mode, guint *out_sim_state, gboolean *out_sys_submode_valid, guint *out_sys_submode, GError **error) { gboolean matched; GRegex *r; GMatchInfo *match_info = NULL; GError *match_error = NULL; g_assert (out_srv_status != NULL); g_assert (out_srv_domain != NULL); g_assert (out_roam_status != NULL); g_assert (out_sys_mode != NULL); g_assert (out_sim_state != NULL); g_assert (out_sys_submode_valid != NULL); g_assert (out_sys_submode != NULL); /* Format: * * ^SYSINFO: <srv_status>,<srv_domain>,<roam_status>,<sys_mode>,<sim_state>[,<reserved>,<sys_submode>] */ /* Can't just use \d here since sometimes you get "^SYSINFO:2,1,0,3,1,,3" */ r = g_regex_new ("\\^SYSINFO:\\s*(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),?(\\d+)?,?(\\d+)?$", 0, 0, NULL); g_assert (r != NULL); matched = g_regex_match_full (r, reply, -1, 0, 0, &match_info, &match_error); if (!matched) { if (match_error) { g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse ^SYSINFO results: "); } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match ^SYSINFO reply"); } } else { mm_get_uint_from_match_info (match_info, 1, out_srv_status); mm_get_uint_from_match_info (match_info, 2, out_srv_domain); mm_get_uint_from_match_info (match_info, 3, out_roam_status); mm_get_uint_from_match_info (match_info, 4, out_sys_mode); mm_get_uint_from_match_info (match_info, 5, out_sim_state); /* Remember that g_match_info_get_match_count() includes match #0 */ if (g_match_info_get_match_count (match_info) >= 8) { *out_sys_submode_valid = TRUE; mm_get_uint_from_match_info (match_info, 7, out_sys_submode); } } if (match_info) g_match_info_free (match_info); g_regex_unref (r); return matched; }
gboolean mm_huawei_parse_time_response (const gchar *response, gchar **iso8601p, MMNetworkTimezone **tzp, GError **error) { GRegex *r; GMatchInfo *match_info = NULL; GError *match_error = NULL; guint year, month, day, hour, minute, second; gboolean ret = FALSE; g_assert (iso8601p || tzp); /* at least one */ /* TIME response cannot ever provide TZ info */ if (tzp) { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED, "^TIME does not provide timezone information"); return FALSE; } /* Already in ISO-8601 format, but verify just to be sure */ r = g_regex_new ("\\^TIME:\\s*(\\d+)/(\\d+)/(\\d+)\\s*(\\d+):(\\d+):(\\d*)$", 0, 0, NULL); g_assert (r != NULL); if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { if (match_error) { g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse ^TIME results: "); } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match ^TIME reply"); } } else { /* Remember that g_match_info_get_match_count() includes match #0 */ g_assert (g_match_info_get_match_count (match_info) >= 7); if (mm_get_uint_from_match_info (match_info, 1, &year) && mm_get_uint_from_match_info (match_info, 2, &month) && mm_get_uint_from_match_info (match_info, 3, &day) && mm_get_uint_from_match_info (match_info, 4, &hour) && mm_get_uint_from_match_info (match_info, 5, &minute) && mm_get_uint_from_match_info (match_info, 6, &second)) { /* adjust year */ if (year < 100) year += 2000; /* Return ISO-8601 format date/time string */ if (iso8601p) *iso8601p = mm_new_iso8601_time (year, month, day, hour, minute, second, FALSE, 0); ret = TRUE; } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse ^TIME reply"); } } if (match_info) g_match_info_free (match_info); g_regex_unref (r); return ret; }
gboolean mm_huawei_parse_nwtime_response (const gchar *response, gchar **iso8601p, MMNetworkTimezone **tzp, GError **error) { GRegex *r; GMatchInfo *match_info = NULL; GError *match_error = NULL; guint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, dt = 0; gint tz = 0; gboolean ret = FALSE; g_assert (iso8601p || tzp); /* at least one */ r = g_regex_new ("\\^NWTIME:\\s*(\\d+)/(\\d+)/(\\d+),(\\d+):(\\d+):(\\d*)([\\-\\+\\d]+),(\\d+)$", 0, 0, NULL); g_assert (r != NULL); if (!g_regex_match_full (r, response, -1, 0, 0, &match_info, &match_error)) { if (match_error) { g_propagate_error (error, match_error); g_prefix_error (error, "Could not parse ^NWTIME results: "); } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't match ^NWTIME reply"); } } else { /* Remember that g_match_info_get_match_count() includes match #0 */ g_assert (g_match_info_get_match_count (match_info) >= 9); if (mm_get_uint_from_match_info (match_info, 1, &year) && mm_get_uint_from_match_info (match_info, 2, &month) && mm_get_uint_from_match_info (match_info, 3, &day) && mm_get_uint_from_match_info (match_info, 4, &hour) && mm_get_uint_from_match_info (match_info, 5, &minute) && mm_get_uint_from_match_info (match_info, 6, &second) && mm_get_int_from_match_info (match_info, 7, &tz) && mm_get_uint_from_match_info (match_info, 8, &dt)) { /* adjust year */ if (year < 100) year += 2000; /* * tz = timezone offset in 15 minute intervals * dt = daylight adjustment, 0 = none, 1 = 1 hour, 2 = 2 hours * other values are marked reserved. */ if (iso8601p) { /* Return ISO-8601 format date/time string */ *iso8601p = mm_new_iso8601_time (year, month, day, hour, minute, second, TRUE, (tz * 15) + (dt * 60)); } if (tzp) { *tzp = mm_network_timezone_new (); mm_network_timezone_set_offset (*tzp, tz * 15); mm_network_timezone_set_dst_offset (*tzp, dt * 60); } ret = TRUE; } else { g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse ^NWTIME reply"); } } if (match_info) g_match_info_free (match_info); g_regex_unref (r); return ret; }
static void selrat_query_ready (MMBaseModem *self, GAsyncResult *res, GSimpleAsyncResult *simple) { LoadAllowedModesResult result; const gchar *response; GError *error = NULL; GRegex *r = NULL; GMatchInfo *match_info = NULL; response = mm_base_modem_at_command_full_finish (MM_BASE_MODEM (self), res, &error); if (!response) { g_simple_async_result_take_error (simple, error); g_simple_async_result_complete (simple); g_object_unref (simple); return; } /* Example response: !SELRAT: 03, UMTS 3G Preferred */ r = g_regex_new ("!SELRAT:\\s*(\\d+).*$", 0, 0, NULL); g_assert (r != NULL); if (g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &error)) { guint mode; if (mm_get_uint_from_match_info (match_info, 1, &mode) && mode >= 0 && mode <= 7) { switch (mode) { case 0: result.allowed = MM_MODEM_MODE_ANY; result.preferred = MM_MODEM_MODE_NONE; break; case 1: result.allowed = MM_MODEM_MODE_3G; result.preferred = MM_MODEM_MODE_NONE; break; case 2: result.allowed = MM_MODEM_MODE_2G; result.preferred = MM_MODEM_MODE_NONE; break; case 3: /* in Sierra LTE devices, mode 3 is automatic, including LTE, no preference */ if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { result.allowed = MM_MODEM_MODE_ANY; result.preferred = MM_MODEM_MODE_NONE; } else { result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); result.preferred = MM_MODEM_MODE_3G; } break; case 4: /* in Sierra LTE devices, mode 4 is automatic, including LTE, no preference */ if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) { result.allowed = MM_MODEM_MODE_ANY; result.preferred = MM_MODEM_MODE_NONE; } else { result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); result.preferred = MM_MODEM_MODE_2G; } break; case 5: result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G); result.preferred = MM_MODEM_MODE_NONE; break; case 6: result.allowed = MM_MODEM_MODE_4G; result.preferred = MM_MODEM_MODE_NONE; break; case 7: result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G); result.preferred = MM_MODEM_MODE_NONE; break; default: g_assert_not_reached (); break; } } else error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed to parse the allowed mode response: '%s'", response); } if (error) g_simple_async_result_take_error (simple, error); else g_simple_async_result_set_op_res_gpointer (simple, &result, NULL); g_simple_async_result_complete (simple); g_object_unref (simple); }