diff options
Diffstat (limited to 'src/mm-generic-gsm.c')
-rw-r--r-- | src/mm-generic-gsm.c | 457 |
1 files changed, 325 insertions, 132 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index a566fb6e..3cf8ab8c 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -18,10 +18,14 @@ static gpointer mm_generic_gsm_parent_class = NULL; typedef struct { char *driver; + char *plugin; + char *device; + + gboolean valid; + char *data_device; char *oper_code; char *oper_name; - guint32 modem_type; guint32 ip_method; gboolean unsolicited_registration; @@ -30,24 +34,39 @@ typedef struct { guint32 signal_quality; guint32 cid; + + MMSerialPort *primary; + MMSerialPort *secondary; } MMGenericGsmPrivate; -static void get_registration_status (MMSerial *serial, MMCallbackInfo *info); -static void read_operator_done (MMSerial *serial, - GString *response, - GError *error, - gpointer user_data); +static void get_registration_status (MMSerialPort *port, MMCallbackInfo *info); +static void read_operator_code_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data); + +static void read_operator_name_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data); + +static void reg_state_changed (MMSerialPort *port, + GMatchInfo *match_info, + gpointer user_data); MMModem * -mm_generic_gsm_new (const char *serial_device, const char *driver) +mm_generic_gsm_new (const char *device, + const char *driver, + const char *plugin) { - g_return_val_if_fail (serial_device != NULL, NULL); + g_return_val_if_fail (device != NULL, NULL); g_return_val_if_fail (driver != NULL, NULL); + g_return_val_if_fail (plugin != NULL, NULL); return MM_MODEM (g_object_new (MM_TYPE_GENERIC_GSM, - MM_SERIAL_DEVICE, serial_device, + MM_MODEM_MASTER_DEVICE, device, MM_MODEM_DRIVER, driver, - MM_MODEM_TYPE, MM_MODEM_TYPE_GSM, + MM_MODEM_PLUGIN, plugin, NULL)); } @@ -101,8 +120,8 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem, if (status == MM_MODEM_GSM_NETWORK_REG_STATUS_HOME || status == MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING) { - mm_serial_queue_command (MM_SERIAL (modem), "+COPS=3,2;+COPS?", 3, read_operator_done, GINT_TO_POINTER (0)); - mm_serial_queue_command (MM_SERIAL (modem), "+COPS=3,0;+COPS?", 3, read_operator_done, GINT_TO_POINTER (1)); + mm_serial_port_queue_command (priv->primary, "+COPS=3,2;+COPS?", 3, read_operator_code_done, modem); + mm_serial_port_queue_command (priv->primary, "+COPS=3,0;+COPS?", 3, read_operator_name_done, modem); mm_modem_gsm_network_get_signal_quality (MM_MODEM_GSM_NETWORK (modem), got_signal_quality, NULL); } else { g_free (priv->oper_code); @@ -116,7 +135,7 @@ mm_generic_gsm_set_reg_status (MMGenericGsm *modem, } static void -pin_check_done (MMSerial *serial, +pin_check_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -150,18 +169,113 @@ mm_generic_gsm_check_pin (MMGenericGsm *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv; MMCallbackInfo *info; g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - mm_serial_queue_command (MM_SERIAL (modem), "+CPIN?", 3, pin_check_done, info); + mm_serial_port_queue_command (priv->primary, "+CPIN?", 3, pin_check_done, info); } /*****************************************************************************/ static void -enable_done (MMSerial *serial, +check_valid (MMGenericGsm *self) +{ + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + gboolean new_valid = FALSE; + + if (priv->primary) + new_valid = TRUE; + + if (priv->valid != new_valid) { + priv->valid = new_valid; + g_object_notify (G_OBJECT (self), MM_MODEM_VALID); + } +} + +static gboolean +owns_port (MMModem *modem, const char *subsys, const char *name) +{ + MMGenericGsm *self = MM_GENERIC_GSM (modem); + + if (strcmp (subsys, "tty")) + return FALSE; + + return !!mm_serial_get_port (MM_SERIAL (self), name); +} + +static gboolean +grab_port (MMModem *modem, + const char *subsys, + const char *name, + GError **error) +{ + MMGenericGsm *self = MM_GENERIC_GSM (modem); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + MMSerialPortType ptype = MM_SERIAL_PORT_TYPE_IGNORED; + MMSerialPort *port; + GRegex *regex; + + if (strcmp (subsys, "tty")) + return FALSE; + + if (!priv->primary) + ptype = MM_SERIAL_PORT_TYPE_PRIMARY; + else if (!priv->secondary) + ptype = MM_SERIAL_PORT_TYPE_SECONDARY; + + port = mm_serial_add_port (MM_SERIAL (self), name, ptype); + mm_serial_port_set_response_parser (port, + mm_serial_parser_v1_parse, + mm_serial_parser_v1_new (), + mm_serial_parser_v1_destroy); + + regex = g_regex_new ("\\r\\n\\+CREG: (\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + mm_serial_port_add_unsolicited_msg_handler (port, regex, reg_state_changed, self, NULL); + g_regex_unref (regex); + + + if (ptype == MM_SERIAL_PORT_TYPE_PRIMARY) { + priv->primary = port; + g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); + check_valid (self); + } else if (ptype == MM_SERIAL_PORT_TYPE_SECONDARY) + priv->secondary = port; + + return TRUE; +} + +static void +release_port (MMModem *modem, const char *subsys, const char *name) +{ + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + MMSerialPort *port; + + if (strcmp (subsys, "tty")) + return; + + port = mm_serial_get_port (MM_SERIAL (modem), name); + if (!port) + return; + + if (port == priv->primary) { + mm_serial_remove_port (MM_SERIAL (modem), port); + priv->primary = NULL; + check_valid (MM_GENERIC_GSM (modem)); + } + + if (port == priv->secondary) { + mm_serial_remove_port (MM_SERIAL (modem), port); + priv->secondary = NULL; + check_valid (MM_GENERIC_GSM (modem)); + } +} + +static void +enable_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -175,7 +289,7 @@ enable_done (MMSerial *serial, } static void -init_done (MMSerial *serial, +init_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -186,35 +300,35 @@ init_done (MMSerial *serial, info->error = g_error_copy (error); mm_callback_info_schedule (info); } else { - if (MM_GENERIC_GSM_GET_PRIVATE (serial)->unsolicited_registration) - mm_serial_queue_command (serial, "+CREG=1", 5, NULL, NULL); + if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->unsolicited_registration) + mm_serial_port_queue_command (port, "+CREG=1", 5, NULL, NULL); else - mm_serial_queue_command (serial, "+CREG=0", 5, NULL, NULL); + mm_serial_port_queue_command (port, "+CREG=0", 5, NULL, NULL); - mm_serial_queue_command (serial, "+CFUN=1", 5, enable_done, user_data); + mm_serial_port_queue_command (port, "+CFUN=1", 5, enable_done, user_data); } } static void -enable_flash_done (MMSerial *serial, gpointer user_data) +enable_flash_done (MMSerialPort *port, gpointer user_data) { - mm_serial_queue_command (serial, "Z E0 V1 X4 &C1 +CMEE=1", 3, init_done, user_data); + mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1", 3, init_done, user_data); } static void -disable_done (MMSerial *serial, +disable_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { - mm_serial_close (serial); + mm_serial_port_close (port); mm_callback_info_schedule ((MMCallbackInfo *) user_data); } static void -disable_flash_done (MMSerial *serial, gpointer user_data) +disable_flash_done (MMSerialPort *port, gpointer user_data) { - mm_serial_queue_command (serial, "+CFUN=0", 5, disable_done, user_data); + mm_serial_port_queue_command (port, "+CFUN=0", 5, disable_done, user_data); } static void @@ -223,6 +337,7 @@ enable (MMModem *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; /* First, reset the previously used CID */ @@ -233,13 +348,13 @@ enable (MMModem *modem, if (!do_enable) { mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem)); - if (mm_serial_is_connected (MM_SERIAL (modem))) - mm_serial_flash (MM_SERIAL (modem), 1000, disable_flash_done, info); + if (mm_serial_port_is_connected (priv->primary)) + mm_serial_port_flash (priv->primary, 1000, disable_flash_done, info); else - disable_flash_done (MM_SERIAL (modem), info); + disable_flash_done (priv->primary, info); } else { - if (mm_serial_open (MM_SERIAL (modem), &info->error)) - mm_serial_flash (MM_SERIAL (modem), 100, enable_flash_done, info); + if (mm_serial_port_open (priv->primary, &info->error)) + mm_serial_port_flash (priv->primary, 100, enable_flash_done, info); if (info->error) mm_callback_info_schedule (info); @@ -247,7 +362,7 @@ enable (MMModem *modem, } static void -get_string_done (MMSerial *serial, +get_string_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -267,10 +382,11 @@ get_imei (MMModemGsmCard *modem, MMModemStringFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); - mm_serial_queue_command_cached (MM_SERIAL (modem), "+CGSN", 3, get_string_done, info); + mm_serial_port_queue_command_cached (priv->primary, "+CGSN", 3, get_string_done, info); } static void @@ -278,10 +394,11 @@ get_imsi (MMModemGsmCard *modem, MMModemStringFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; info = mm_callback_info_string_new (MM_MODEM (modem), callback, user_data); - mm_serial_queue_command_cached (MM_SERIAL (modem), "+CIMI", 3, get_string_done, info); + mm_serial_port_queue_command_cached (priv->primary, "+CIMI", 3, get_string_done, info); } static void @@ -297,7 +414,7 @@ gsm_card_info_invoke (MMCallbackInfo *info) } static void -get_version_done (MMSerial *serial, +get_version_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -313,7 +430,7 @@ get_version_done (MMSerial *serial, } static void -get_model_done (MMSerial *serial, +get_model_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -327,7 +444,7 @@ get_model_done (MMSerial *serial, } static void -get_manufacturer_done (MMSerial *serial, +get_manufacturer_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -345,21 +462,21 @@ get_card_info (MMModemGsmCard *modem, MMModemGsmCardInfoFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; - MMSerial *serial = MM_SERIAL (modem); info = mm_callback_info_new_full (MM_MODEM (modem), gsm_card_info_invoke, G_CALLBACK (callback), user_data); - mm_serial_queue_command_cached (serial, "+CGMI", 3, get_manufacturer_done, info); - mm_serial_queue_command_cached (serial, "+CGMM", 3, get_model_done, info); - mm_serial_queue_command_cached (serial, "+CGMR", 3, get_version_done, info); + mm_serial_port_queue_command_cached (priv->primary, "+CGMI", 3, get_manufacturer_done, info); + mm_serial_port_queue_command_cached (priv->primary, "+CGMM", 3, get_model_done, info); + mm_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info); } static void -send_puk_done (MMSerial *serial, +send_puk_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -378,17 +495,18 @@ send_puk (MMModemGsmCard *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; char *command; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); command = g_strdup_printf ("+CPIN=\"%s\",\"%s\"", puk, pin); - mm_serial_queue_command (MM_SERIAL (modem), command, 3, send_puk_done, info); + mm_serial_port_queue_command (priv->primary, command, 3, send_puk_done, info); g_free (command); } static void -send_pin_done (MMSerial *serial, +send_pin_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -406,17 +524,18 @@ send_pin (MMModemGsmCard *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; char *command; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); command = g_strdup_printf ("+CPIN=\"%s\"", pin); - mm_serial_queue_command (MM_SERIAL (modem), command, 3, send_pin_done, info); + mm_serial_port_queue_command (priv->primary, command, 3, send_pin_done, info); g_free (command); } static void -enable_pin_done (MMSerial *serial, +enable_pin_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -435,17 +554,18 @@ enable_pin (MMModemGsmCard *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; char *command; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); command = g_strdup_printf ("+CLCK=\"SC\",%d,\"%s\"", enabled ? 1 : 0, pin); - mm_serial_queue_command (MM_SERIAL (modem), command, 3, enable_pin_done, info); + mm_serial_port_queue_command (priv->primary, command, 3, enable_pin_done, info); g_free (command); } static void -change_pin_done (MMSerial *serial, +change_pin_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -464,12 +584,13 @@ change_pin (MMModemGsmCard *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; char *command; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); command = g_strdup_printf ("+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, new_pin); - mm_serial_queue_command (MM_SERIAL (modem), command, 3, change_pin_done, info); + mm_serial_port_queue_command (priv->primary, command, 3, change_pin_done, info); g_free (command); } @@ -500,30 +621,48 @@ parse_operator (const char *reply) } static void -read_operator_done (MMSerial *serial, - GString *response, - GError *error, - gpointer user_data) +read_operator_code_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) { - if (!error) { - char *oper; + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data); + char *oper; - oper = parse_operator (response->str); - if (oper) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (serial); + if (error) + return; - if (GPOINTER_TO_INT (user_data) == 0) { - g_free (priv->oper_code); - priv->oper_code = oper; - } else { - g_free (priv->oper_name); - priv->oper_name = oper; + oper = parse_operator (response->str); + if (!oper) + return; - mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (serial), priv->reg_status, - priv->oper_code, priv->oper_name); - } - } - } + g_free (priv->oper_code); + priv->oper_code = oper; +} + +static void +read_operator_name_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (user_data); + char *oper; + + if (error) + return; + + oper = parse_operator (response->str); + if (!oper) + return; + + g_free (priv->oper_name); + priv->oper_name = oper; + + mm_modem_gsm_network_registration_info (MM_MODEM_GSM_NETWORK (user_data), + priv->reg_status, + priv->oper_code, + priv->oper_name); } /* Registration */ @@ -618,24 +757,27 @@ reg_status_updated (MMGenericGsm *self, int new_value) } static void -reg_state_changed (MMSerial *serial, +reg_state_changed (MMSerialPort *port, GMatchInfo *match_info, gpointer user_data) { + MMGenericGsm *self = MM_GENERIC_GSM (user_data); char *str; str = g_match_info_fetch (match_info, 1); - reg_status_updated (MM_GENERIC_GSM (serial), atoi (str)); + reg_status_updated (self, atoi (str)); g_free (str); } static gboolean reg_status_again (gpointer data) { + MMGenericGsmPrivate *priv; MMCallbackInfo *info = (MMCallbackInfo *) data; - if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->pending_registration) - get_registration_status (MM_SERIAL (info->modem), info); + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + if (priv->pending_registration) + get_registration_status (priv->primary, info); return FALSE; } @@ -647,13 +789,13 @@ reg_status_again_remove (gpointer data) } static void -get_reg_status_done (MMSerial *serial, +get_reg_status_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (serial); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); if (error) { info->error = g_error_copy (error); @@ -666,7 +808,7 @@ get_reg_status_done (MMSerial *serial, int unsolicited, stat; if (sscanf (response->str + 7, "%d,%d", &unsolicited, &stat)) { - reg_status_updated (MM_GENERIC_GSM (serial), stat); + reg_status_updated (MM_GENERIC_GSM (info->modem), stat); if (!unsolicited && priv->pending_registration) { guint id; @@ -687,19 +829,19 @@ get_reg_status_done (MMSerial *serial, } static void -get_registration_status (MMSerial *serial, MMCallbackInfo *info) +get_registration_status (MMSerialPort *port, MMCallbackInfo *info) { - mm_serial_queue_command (serial, "+CREG?", 3, get_reg_status_done, info); + mm_serial_port_queue_command (port, "+CREG?", 3, get_reg_status_done, info); } static void -register_done (MMSerial *serial, +register_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { /* Ignore errors here, get the actual registration status */ - get_registration_status (serial, (MMCallbackInfo *) user_data); + get_registration_status (port, (MMCallbackInfo *) user_data); } static void @@ -708,12 +850,13 @@ do_register (MMModemGsmNetwork *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; char *command; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - MM_GENERIC_GSM_GET_PRIVATE (modem)->pending_registration = + priv->pending_registration = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 60, pending_registration_timed_out, info, @@ -724,7 +867,7 @@ do_register (MMModemGsmNetwork *modem, else command = g_strdup ("+COPS=0,,"); - mm_serial_queue_command (MM_SERIAL (modem), command, 5, register_done, info); + mm_serial_port_queue_command (priv->primary, command, 5, register_done, info); g_free (command); } @@ -758,7 +901,7 @@ get_registration_info (MMModemGsmNetwork *self, } static void -connect_report_done (MMSerial *serial, +connect_report_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -774,17 +917,19 @@ connect_report_done (MMSerial *serial, } static void -connect_done (MMSerial *serial, +connect_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { + MMGenericGsmPrivate *priv; MMCallbackInfo *info = (MMCallbackInfo *) user_data; if (error) { info->error = g_error_copy (error); /* Try to get more information why it failed */ - mm_serial_queue_command (serial, "+CEER", 3, connect_report_done, info); + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + mm_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info); } else /* Done */ mm_callback_info_schedule (info); @@ -796,6 +941,7 @@ connect (MMModem *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; char *command; guint32 cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (modem)); @@ -816,12 +962,12 @@ connect (MMModem *modem, } else command = g_strconcat ("DT", number, NULL); - mm_serial_queue_command (MM_SERIAL (modem), command, 60, connect_done, info); + mm_serial_port_queue_command (priv->primary, command, 60, connect_done, info); g_free (command); } static void -disconnect_flash_done (MMSerial *serial, gpointer user_data) +disconnect_flash_done (MMSerialPort *port, gpointer user_data) { mm_callback_info_schedule ((MMCallbackInfo *) user_data); } @@ -831,13 +977,14 @@ disconnect (MMModem *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; /* First, reset the previously used CID */ mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0); info = mm_callback_info_new (modem, callback, user_data); - mm_serial_flash (MM_SERIAL (modem), 1000, disconnect_flash_done, info); + mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info); } static void @@ -861,7 +1008,7 @@ destroy_scan_data (gpointer data) } static void -scan_done (MMSerial *serial, +scan_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -880,8 +1027,13 @@ scan_done (MMSerial *serial, reply += 7; - /* Pattern without crazy escaping using | for matching: (|\d|,"|.+|","|.+|","|.+|",|\d|) */ - r = g_regex_new ("\\((\\d),\"(.+)\",\"(.+)\",\"(.+)\",(\\d)\\)", G_REGEX_UNGREEDY, 0, &err); + /* Pattern without crazy escaping using | for matching: (|\d|,"|.+|","|.+|","|.+|"\)?,|\d|) */ + + /* Quirk: Sony-Ericsson TM-506 sometimes includes a stray ')' like so: + * + * +COPS: (2,"","T-Mobile","31026",0),(1,"AT&T","AT&T","310410"),0) + */ + r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\"\\)?,(\\d)\\)", G_REGEX_UNGREEDY, 0, &err); if (err) { g_error ("Invalid regular expression: %s", err->message); g_error_free (err); @@ -922,6 +1074,7 @@ scan (MMModemGsmNetwork *modem, MMModemGsmNetworkScanFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; info = mm_callback_info_new_full (MM_MODEM (modem), @@ -929,13 +1082,13 @@ scan (MMModemGsmNetwork *modem, G_CALLBACK (callback), user_data); - mm_serial_queue_command (MM_SERIAL (modem), "+COPS=?", 60, scan_done, info); + mm_serial_port_queue_command (priv->primary, "+COPS=?", 60, scan_done, info); } /* SetApn */ static void -set_apn_done (MMSerial *serial, +set_apn_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -945,14 +1098,14 @@ set_apn_done (MMSerial *serial, if (error) info->error = g_error_copy (error); else - mm_generic_gsm_set_cid (MM_GENERIC_GSM (serial), + mm_generic_gsm_set_cid (MM_GENERIC_GSM (info->modem), GPOINTER_TO_UINT (mm_callback_info_get_data (info, "cid"))); mm_callback_info_schedule (info); } static void -cid_range_read (MMSerial *serial, +cid_range_read (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1012,13 +1165,13 @@ cid_range_read (MMSerial *serial, mm_callback_info_set_data (info, "cid", GUINT_TO_POINTER (cid), NULL); command = g_strdup_printf ("+CGDCONT=%d, \"IP\", \"%s\"", cid, apn); - mm_serial_queue_command (serial, command, 3, set_apn_done, info); + mm_serial_port_queue_command (port, command, 3, set_apn_done, info); g_free (command); } } static void -existing_apns_read (MMSerial *serial, +existing_apns_read (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1051,7 +1204,7 @@ existing_apns_read (MMSerial *serial, apn = g_match_info_fetch (match_info, 3); if (!strcmp (apn, new_apn)) { - mm_generic_gsm_set_cid (MM_GENERIC_GSM (serial), (guint32) num_cid); + mm_generic_gsm_set_cid (MM_GENERIC_GSM (info->modem), (guint32) num_cid); found = TRUE; } @@ -1083,7 +1236,7 @@ existing_apns_read (MMSerial *serial, mm_callback_info_schedule (info); else /* APN not configured on the card. Get the allowed CID range */ - mm_serial_queue_command_cached (serial, "+CGDCONT=?", 3, cid_range_read, info); + mm_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info); } static void @@ -1092,23 +1245,25 @@ set_apn (MMModemGsmNetwork *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); mm_callback_info_set_data (info, "apn", g_strdup (apn), g_free); /* Start by searching if the APN is already in card */ - mm_serial_queue_command (MM_SERIAL (modem), "+CGDCONT?", 3, existing_apns_read, info); + mm_serial_port_queue_command (priv->primary, "+CGDCONT?", 3, existing_apns_read, info); } /* GetSignalQuality */ static void -get_signal_quality_done (MMSerial *serial, +get_signal_quality_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { + MMGenericGsmPrivate *priv; MMCallbackInfo *info = (MMCallbackInfo *) user_data; char *reply = response->str; @@ -1127,7 +1282,8 @@ get_signal_quality_done (MMSerial *serial, /* Normalize the quality */ quality = quality * 100 / 31; - MM_GENERIC_GSM_GET_PRIVATE (serial)->signal_quality = quality; + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + priv->signal_quality = quality; mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL); } else info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, @@ -1142,23 +1298,26 @@ get_signal_quality (MMModemGsmNetwork *modem, MMModemUIntFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); MMCallbackInfo *info; + gboolean connected; - if (mm_serial_is_connected (MM_SERIAL (modem))) { - g_message ("Returning saved signal quality %d", MM_GENERIC_GSM_GET_PRIVATE (modem)->signal_quality); - callback (MM_MODEM (modem), MM_GENERIC_GSM_GET_PRIVATE (modem)->signal_quality, NULL, user_data); + connected = mm_serial_port_is_connected (priv->primary); + if (connected && !priv->secondary) { + g_message ("Returning saved signal quality %d", priv->signal_quality); + callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data); return; } info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - mm_serial_queue_command (MM_SERIAL (modem), "+CSQ", 3, get_signal_quality_done, info); + mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info); } /*****************************************************************************/ /* MMModemGsmSms interface */ static void -sms_send_done (MMSerial *serial, +sms_send_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -1181,16 +1340,33 @@ sms_send (MMModemGsmSms *modem, MMModemFn callback, gpointer user_data) { + MMGenericGsmPrivate *priv; MMCallbackInfo *info; char *command; + gboolean connected; + MMSerialPort *port = NULL; info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + connected = mm_serial_port_is_connected (priv->primary); + if (connected) + port = priv->secondary; + else + port = priv->primary; + + if (!port) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Cannot send SMS while connected"); + mm_callback_info_schedule (info); + return; + } + /* FIXME: use the PDU mode instead */ - mm_serial_queue_command (MM_SERIAL (modem), "AT+CMGF=1", 3, NULL, NULL); + mm_serial_port_queue_command (port, "AT+CMGF=1", 3, NULL, NULL); command = g_strdup_printf ("+CMGS=\"%s\"\r%s\x1a", number, text); - mm_serial_queue_command (MM_SERIAL (modem), command, 10, sms_send_done, info); + mm_serial_port_queue_command (port, command, 10, sms_send_done, info); g_free (command); } @@ -1441,6 +1617,9 @@ simple_get_status (MMModemSimple *simple, static void modem_init (MMModem *modem_class) { + modem_class->owns_port = owns_port; + modem_class->grab_port = grab_port; + modem_class->release_port = release_port; modem_class->enable = enable; modem_class->connect = connect; modem_class->disconnect = disconnect; @@ -1484,16 +1663,6 @@ modem_simple_init (MMModemSimple *class) static void mm_generic_gsm_init (MMGenericGsm *self) { - GRegex *regex; - - mm_serial_set_response_parser (MM_SERIAL (self), - mm_serial_parser_v1_parse, - mm_serial_parser_v1_new (), - mm_serial_parser_v1_destroy); - - regex = g_regex_new ("\\r\\n\\+CREG: (\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_add_unsolicited_msg_handler (MM_SERIAL (self), regex, reg_state_changed, NULL, NULL); - g_regex_unref (regex); } static void @@ -1507,16 +1676,20 @@ set_property (GObject *object, guint prop_id, /* Construct only */ priv->driver = g_value_dup_string (value); break; - case MM_MODEM_PROP_DEVICE: - g_free (priv->data_device); - priv->data_device = g_value_dup_string (value); + case MM_MODEM_PROP_PLUGIN: + /* Construct only */ + priv->plugin = g_value_dup_string (value); break; - case MM_MODEM_PROP_TYPE: - priv->modem_type = g_value_get_uint (value); + case MM_MODEM_PROP_MASTER_DEVICE: + /* Constrcut only */ + priv->device = g_value_dup_string (value); break; case MM_MODEM_PROP_IP_METHOD: priv->ip_method = g_value_get_uint (value); break; + case MM_MODEM_PROP_TYPE: + case MM_MODEM_PROP_VALID: + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1530,21 +1703,30 @@ get_property (GObject *object, guint prop_id, MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (object); switch (prop_id) { - case MM_MODEM_PROP_DEVICE: - if (priv->data_device) - g_value_set_string (value, priv->data_device); + case MM_MODEM_PROP_DATA_DEVICE: + if (priv->primary) + g_value_set_string (value, mm_serial_port_get_device (priv->primary)); else - g_value_set_string (value, mm_serial_get_device (MM_SERIAL (object))); + g_value_set_string (value, NULL); + break; + case MM_MODEM_PROP_MASTER_DEVICE: + g_value_set_string (value, priv->device); break; case MM_MODEM_PROP_DRIVER: - g_value_set_string (value, MM_GENERIC_GSM_GET_PRIVATE (object)->driver); + g_value_set_string (value, priv->driver); + break; + case MM_MODEM_PROP_PLUGIN: + g_value_set_string (value, priv->plugin); break; case MM_MODEM_PROP_TYPE: - g_value_set_uint (value, priv->modem_type); + g_value_set_uint (value, MM_MODEM_TYPE_GSM); break; case MM_MODEM_PROP_IP_METHOD: g_value_set_uint (value, priv->ip_method); break; + case MM_MODEM_PROP_VALID: + g_value_set_boolean (value, priv->valid); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1581,14 +1763,22 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) /* Properties */ g_object_class_override_property (object_class, - MM_MODEM_PROP_DEVICE, - MM_MODEM_DEVICE); + MM_MODEM_PROP_DATA_DEVICE, + MM_MODEM_DATA_DEVICE); + + g_object_class_override_property (object_class, + MM_MODEM_PROP_MASTER_DEVICE, + MM_MODEM_MASTER_DEVICE); g_object_class_override_property (object_class, MM_MODEM_PROP_DRIVER, MM_MODEM_DRIVER); g_object_class_override_property (object_class, + MM_MODEM_PROP_PLUGIN, + MM_MODEM_PLUGIN); + + g_object_class_override_property (object_class, MM_MODEM_PROP_TYPE, MM_MODEM_TYPE); @@ -1596,6 +1786,9 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) MM_MODEM_PROP_IP_METHOD, MM_MODEM_IP_METHOD); + g_object_class_override_property (object_class, + MM_MODEM_PROP_VALID, + MM_MODEM_VALID); } GType |