diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/mm-modem-huawei-gsm.c | 147 | ||||
-rw-r--r-- | plugins/mm-modem-mbm.c | 150 | ||||
-rw-r--r-- | plugins/mm-plugin-huawei.c | 2 |
3 files changed, 296 insertions, 3 deletions
diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index 6637bd02..5123e7f0 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -17,12 +17,14 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <errno.h> #define G_UDEV_API_IS_SUBJECT_TO_CHANGE #include <gudev/gudev.h> #include "mm-modem-huawei-gsm.h" #include "mm-modem-gsm-network.h" +#include "mm-modem-gsm-card.h" #include "mm-errors.h" #include "mm-callback-info.h" #include "mm-at-serial-port.h" @@ -30,10 +32,12 @@ static void modem_init (MMModem *modem_class); static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class); +static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); G_DEFINE_TYPE_EXTENDED (MMModemHuaweiGsm, mm_modem_huawei_gsm, MM_TYPE_GENERIC_GSM, 0, G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init)) + G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_init)) #define MM_MODEM_HUAWEI_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_HUAWEI_GSM, MMModemHuaweiGsmPrivate)) @@ -448,6 +452,141 @@ get_access_technology (MMGenericGsm *modem, } /*****************************************************************************/ + +static gboolean +parse_num (const char *str, guint32 *out_num, guint32 min, guint32 max) +{ + unsigned long int tmp; + + if (!str || !strlen (str)) + return FALSE; + + errno = 0; + tmp = strtoul (str, NULL, 10); + if (errno != 0 || tmp < min || tmp > max) + return FALSE; + *out_num = (guint32) tmp; + return TRUE; +} + +static void +send_huawei_cpin_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + GRegex *r = NULL; + GMatchInfo *match_info = NULL; + const char *pin_type; + guint32 attempts_left = 0; + char *str = NULL; + guint32 num = 0; + + if (error) { + info->error = g_error_copy (error); + goto done; + } + + pin_type = mm_callback_info_get_data (info, "pin_type"); + + r = g_regex_new ("\\^CPIN:\\s*([^,]+),[^,]*,(\\d+),(\\d+),(\\d+),(\\d+)", G_REGEX_UNGREEDY, 0, NULL); + if (!r) { + g_set_error_literal (&info->error, + MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Could not parse ^CPIN results (error creating regex)."); + goto done; + } + + if (!g_regex_match_full (r, response->str, response->len, 0, 0, &match_info, &info->error)) { + g_set_error_literal (&info->error, + MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Could not parse ^CPIN results (match failed)."); + goto done; + } + + if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK)) + num = 2; + else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN)) + num = 3; + else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2)) + num = 4; + else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2)) + num = 5; + else { + g_debug ("%s: unhandled pin type '%s'", __func__, pin_type); + + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type"); + } + + if (num > 0) { + gboolean success = FALSE; + + str = g_match_info_fetch (match_info, num); + if (str) { + success = parse_num (str, &attempts_left, 0, 10); + g_free (str); + } + + if (!success) { + info->error = g_error_new_literal (MM_MODEM_ERROR, + MM_MODEM_ERROR_GENERAL, + "Could not parse ^CPIN results (missing or invalid match info)."); + } + } + + mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL); + + g_match_info_free (match_info); + +done: + if (r) + g_regex_unref (r); + mm_serial_port_close (MM_SERIAL_PORT (port)); + mm_callback_info_schedule (info); +} + +static void +get_unlock_retries (MMModemGsmCard *modem, + const char *pin_type, + MMModemUIntFn callback, + gpointer user_data) +{ + MMAtSerialPort *port; + char *command; + MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); + + g_debug ("%s: pin type '%s'", __func__, pin_type); + + /* Ensure we have a usable port to use for the command */ + port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error); + if (!port) { + mm_callback_info_schedule (info); + return; + } + + /* Modem may not be enabled yet, which sometimes can't be done until + * the device has been unlocked. In this case we have to open the port + * ourselves. + */ + if (!mm_serial_port_open (MM_SERIAL_PORT (port), &info->error)) { + mm_callback_info_schedule (info); + return; + } + + /* if the modem have not yet been enabled we need to make sure echoing is turned off */ + command = g_strdup_printf ("E0"); + mm_at_serial_port_queue_command (port, command, 3, NULL, NULL); + g_free (command); + + mm_callback_info_set_data (info, "pin_type", g_strdup (pin_type), g_free); + + command = g_strdup_printf ("^CPIN?"); + mm_at_serial_port_queue_command (port, command, 3, send_huawei_cpin_done, info); + g_free (command); +} + +/*****************************************************************************/ /* Unsolicited message handlers */ static void @@ -627,6 +766,12 @@ modem_gsm_network_init (MMModemGsmNetwork *class) } static void +modem_gsm_card_init (MMModemGsmCard *class) +{ + class->get_unlock_retries = get_unlock_retries; +} + +static void mm_modem_huawei_gsm_init (MMModemHuaweiGsm *self) { } diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index 10be0be8..7f6bc9c8 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -28,17 +28,20 @@ #include "mm-modem-mbm.h" #include "mm-modem-simple.h" +#include "mm-modem-gsm-card.h" #include "mm-errors.h" #include "mm-callback-info.h" static void modem_init (MMModem *modem_class); static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class); static void modem_simple_init (MMModemSimple *class); +static void modem_gsm_card_init (MMModemGsmCard *class); G_DEFINE_TYPE_EXTENDED (MMModemMbm, mm_modem_mbm, MM_TYPE_GENERIC_GSM, 0, G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init) G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init) - G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init)) + G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_SIMPLE, modem_simple_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_CARD, modem_gsm_card_init)) #define MM_MODEM_MBM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_MBM, MMModemMbmPrivate)) @@ -505,6 +508,59 @@ do_disconnect (MMGenericGsm *gsm, MM_GENERIC_GSM_CLASS (mm_modem_mbm_parent_class)->do_disconnect (gsm, cid, callback, user_data); } +static void +factory_reset_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + + mm_serial_port_close (MM_SERIAL_PORT (port)); + mm_callback_info_schedule (info); +} + +static void +factory_reset (MMModem *self, + const char *code, + MMModemFn callback, + gpointer user_data) +{ + MMAtSerialPort *port; + MMCallbackInfo *info; + + info = mm_callback_info_new (self, callback, user_data); + + /* Ensure we have a usable port to use for the command */ + port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (self), &info->error); + if (!port) { + mm_callback_info_schedule (info); + return; + } + + /* Modem may not be enabled yet, which sometimes can't be done until + * the device has been unlocked. In this case we have to open the port + * ourselves. + */ + if (!mm_serial_port_open (MM_SERIAL_PORT (port), &info->error)) { + mm_callback_info_schedule (info); + return; + } + + mm_at_serial_port_queue_command (port, "&F +CMEE=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+COPS=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CR=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CRC=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CREG=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CMER=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "*EPEE=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CNMI=2, 0, 0, 0, 0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CGREG=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "*EIAD=0", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CGSMS=3", 3, NULL, NULL); + mm_at_serial_port_queue_command (port, "+CSCA=\"\",129", 3, factory_reset_done, info); +} + /*****************************************************************************/ static void @@ -736,6 +792,91 @@ mbm_modem_authenticate (MMModemMbm *self, /*****************************************************************************/ +static void +send_epin_done (MMAtSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + const char *pin_type; + int attempts_left = 0; + + if (error) { + info->error = g_error_copy (error); + goto done; + } + + pin_type = mm_callback_info_get_data (info, "pin_type"); + + if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN)) + sscanf (response->str, "*EPIN: %d", &attempts_left); + else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK)) + sscanf (response->str, "*EPIN: %*d, %d", &attempts_left); + else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PIN2)) + sscanf (response->str, "*EPIN: %*d, %*d, %d", &attempts_left); + else if (strstr (pin_type, MM_MODEM_GSM_CARD_SIM_PUK2)) + sscanf (response->str, "*EPIN: %*d, %*d, %*d, %d", &attempts_left); + else { + g_debug ("%s: unhandled pin type '%s'", __func__, pin_type); + + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unhandled PIN type"); + } + + if (attempts_left < 0 || attempts_left > 998) { + info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid PIN attempts left %d", attempts_left); + attempts_left = 0; + } + + mm_callback_info_set_result (info, GUINT_TO_POINTER (attempts_left), NULL); + +done: + mm_serial_port_close (MM_SERIAL_PORT (port)); + mm_callback_info_schedule (info); +} + +static void +mbm_get_unlock_retries (MMModemGsmCard *modem, + const char *pin_type, + MMModemUIntFn callback, + gpointer user_data) +{ + MMAtSerialPort *port; + char *command; + MMCallbackInfo *info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); + + g_debug ("%s: pin type '%s'", __func__, pin_type); + + /* Ensure we have a usable port to use for the command */ + port = mm_generic_gsm_get_best_at_port (MM_GENERIC_GSM (modem), &info->error); + if (!port) { + mm_callback_info_schedule (info); + return; + } + + /* Modem may not be enabled yet, which sometimes can't be done until + * the device has been unlocked. In this case we have to open the port + * ourselves. + */ + if (!mm_serial_port_open (MM_SERIAL_PORT (port), &info->error)) { + mm_callback_info_schedule (info); + return; + } + + /* if the modem have not yet been enabled we need to make sure echoing is turned off */ + command = g_strdup_printf ("E0"); + mm_at_serial_port_queue_command (port, command, 3, NULL, NULL); + g_free (command); + + mm_callback_info_set_data (info, "pin_type", g_strdup (pin_type), g_free); + + command = g_strdup_printf ("*EPIN?"); + mm_at_serial_port_queue_command (port, command, 3, send_epin_done, info); + g_free (command); +} + +/*****************************************************************************/ + static gboolean grab_port (MMModem *modem, const char *subsys, @@ -805,6 +946,12 @@ grab_port (MMModem *modem, /*****************************************************************************/ static void +modem_gsm_card_init (MMModemGsmCard *class) +{ + class->get_unlock_retries = mbm_get_unlock_retries; +} + +static void modem_gsm_network_init (MMModemGsmNetwork *class) { class->do_register = do_register; @@ -822,6 +969,7 @@ modem_init (MMModem *modem_class) modem_class->grab_port = grab_port; modem_class->disable = disable; modem_class->connect = do_connect; + modem_class->factory_reset = factory_reset; } static void diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c index b4c97d6e..2993689d 100644 --- a/plugins/mm-plugin-huawei.c +++ b/plugins/mm-plugin-huawei.c @@ -237,7 +237,7 @@ supports_port (MMPluginBase *base, add_regex (info->serial, "\\r\\n\\^BOOT:.+\\r\\n", task); add_regex (info->serial, "\\r\\r\\^BOOT:.+\\r\\r", task); - info->id = g_timeout_add (5000, probe_secondary_timeout, task); + info->id = g_timeout_add_seconds (7, probe_secondary_timeout, task); g_object_set_data_full (G_OBJECT (task), TAG_SUPPORTS_INFO, info, huawei_supports_info_destroy); |