aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/mm-modem-huawei-gsm.c147
-rw-r--r--plugins/mm-modem-mbm.c150
-rw-r--r--plugins/mm-plugin-huawei.c2
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);