diff options
Diffstat (limited to 'src/mm-generic-gsm.c')
-rw-r--r-- | src/mm-generic-gsm.c | 217 |
1 files changed, 117 insertions, 100 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 568cc8fd..0a0a2a1a 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -11,7 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 - 2010 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. * Copyright (C) 2009 - 2010 Ericsson */ @@ -116,6 +116,7 @@ typedef struct { MMAtSerialPort *secondary; MMQcdmSerialPort *qcdm; MMPort *data; + gboolean data_opened_at_connect; /* Location API */ guint32 loc_caps; @@ -843,39 +844,28 @@ owns_port (MMModem *modem, const char *subsys, const char *name) return !!mm_modem_base_get_port (MM_MODEM_BASE (modem), subsys, name); } -MMPort * -mm_generic_gsm_grab_port (MMGenericGsm *self, - const char *subsys, - const char *name, - MMPortType ptype, - GError **error) +static void +port_grabbed (MMModemBase *base, + MMPort *port, + MMAtPortFlags at_pflags, + gpointer user_data) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - MMPort *port = NULL; + MMGenericGsm *self = MM_GENERIC_GSM (base); + GPtrArray *array; GRegex *regex; - - g_return_val_if_fail (!strcmp (subsys, "net") || !strcmp (subsys, "tty"), FALSE); - - port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype); - if (!port) { - g_warn_if_fail (port != NULL); - return NULL; - } + int i; if (MM_IS_AT_SERIAL_PORT (port)) { - GPtrArray *array; - int i; - mm_at_serial_port_set_response_parser (MM_AT_SERIAL_PORT (port), mm_serial_parser_v1_parse, mm_serial_parser_v1_new (), mm_serial_parser_v1_destroy); + mm_at_serial_port_set_flags (MM_AT_SERIAL_PORT (port), at_pflags); /* Set up CREG unsolicited message handlers */ array = mm_gsm_creg_regex_get (FALSE); for (i = 0; i < array->len; i++) { regex = g_ptr_array_index (array, i); - mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, reg_state_changed, self, NULL); } mm_gsm_creg_regex_destroy (array); @@ -891,72 +881,48 @@ mm_generic_gsm_grab_port (MMGenericGsm *self, regex = g_regex_new ("\\r\\n\\+CUSD:\\s*(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_at_serial_port_add_unsolicited_msg_handler (MM_AT_SERIAL_PORT (port), regex, cusd_received, self, NULL); g_regex_unref (regex); - - if (ptype == MM_PORT_TYPE_PRIMARY) { - priv->primary = MM_AT_SERIAL_PORT (port); - if (!priv->data) { - priv->data = port; - g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); - } - - /* Get the modem's general info */ - initial_info_check (self); - - /* Get modem's IMEI */ - initial_imei_check (self); - - /* Get modem's initial lock/unlock state; this also ensures the - * SIM is ready by waiting if necessary for the SIM to initalize. - */ - initial_pin_check (self); - - /* Determine what facility locks are supported */ - initial_facility_lock_check (self); - - } else if (ptype == MM_PORT_TYPE_SECONDARY) - priv->secondary = MM_AT_SERIAL_PORT (port); - } else if (MM_IS_QCDM_SERIAL_PORT (port)) { - if (!priv->qcdm) - priv->qcdm = MM_QCDM_SERIAL_PORT (port); - } else if (!strcmp (subsys, "net")) { - /* Net device (if any) is the preferred data port */ - if (!priv->data || MM_IS_AT_SERIAL_PORT (priv->data)) { - priv->data = port; - g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); - check_valid (self); - } } - return port; + if (MM_GENERIC_GSM_GET_CLASS (self)->port_grabbed) + MM_GENERIC_GSM_GET_CLASS (self)->port_grabbed (self, port, at_pflags, user_data); } static gboolean -grab_port (MMModem *modem, - const char *subsys, - const char *name, - MMPortType suggested_type, - gpointer user_data, - GError **error) +organize_ports (MMModem *modem, GError **error) { MMGenericGsm *self = MM_GENERIC_GSM (modem); MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - MMPortType ptype = MM_PORT_TYPE_IGNORED; - if (priv->primary) - g_return_val_if_fail (suggested_type != MM_PORT_TYPE_PRIMARY, FALSE); + if (!mm_modem_base_organize_ports (MM_MODEM_BASE (modem), + &priv->primary, + &priv->secondary, + &priv->data, + &priv->qcdm, + error)) + return FALSE; + + /* Let subclasses twiddle ports if they want */ + if (MM_GENERIC_GSM_GET_CLASS (self)->ports_organized) + MM_GENERIC_GSM_GET_CLASS (self)->ports_organized (self, priv->primary); - if (!strcmp (subsys, "tty")) { - if (suggested_type != MM_PORT_TYPE_UNKNOWN) - ptype = suggested_type; - else { - if (!priv->primary) - ptype = MM_PORT_TYPE_PRIMARY; - else if (!priv->secondary) - ptype = MM_PORT_TYPE_SECONDARY; - } - } + g_object_notify (G_OBJECT (self), MM_MODEM_DATA_DEVICE); + + /* Get the modem's general info */ + initial_info_check (self); + + /* Get modem's IMEI */ + initial_imei_check (self); - return !!mm_generic_gsm_grab_port (self, subsys, name, ptype, error); + /* Get modem's initial lock/unlock state; this also ensures the + * SIM is ready by waiting if necessary for the SIM to initalize. + */ + initial_pin_check (self); + + /* Determine what facility locks are supported */ + initial_facility_lock_check (self); + + check_valid (self); + return TRUE; } static void @@ -3824,9 +3790,27 @@ connect (MMModem *modem, MMCallbackInfo *info; char *command; gint cid = mm_generic_gsm_get_cid (MM_GENERIC_GSM (modem)); + MMAtSerialPort *dial_port; info = mm_callback_info_new (modem, callback, user_data); + /* Dial port might not be the primary port*/ + priv->data_opened_at_connect = FALSE; + dial_port = priv->primary; + if (MM_IS_AT_SERIAL_PORT (priv->data)) { + dial_port = MM_AT_SERIAL_PORT (priv->data); + + if (!mm_serial_port_open (MM_SERIAL_PORT (dial_port), &info->error)) { + g_warning ("%s: failed to open dial port: (%d) %s", + __func__, + info->error ? info->error->code : -1, + info->error && info->error->message ? info->error->message : "(unknown)"); + mm_callback_info_schedule (info); + return; + } + priv->data_opened_at_connect = TRUE; + } + mm_modem_set_state (modem, MM_MODEM_STATE_CONNECTING, MM_MODEM_STATE_REASON_NONE); if (cid > 0) { @@ -3843,7 +3827,7 @@ connect (MMModem *modem, } else command = g_strconcat ("DT", number, NULL); - mm_at_serial_port_queue_command (priv->primary, command, 60, connect_done, info); + mm_at_serial_port_queue_command (dial_port, command, 60, connect_done, info); g_free (command); } @@ -3854,11 +3838,13 @@ disconnect_done (MMModem *modem, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMModemState prev_state; + MMGenericGsmPrivate *priv; /* Do nothing if modem removed */ if (!modem || mm_callback_info_check_modem_removed (info)) return; + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); if (error) { info->error = g_error_copy (error); /* Reset old state since the operation failed */ @@ -3867,12 +3853,19 @@ disconnect_done (MMModem *modem, prev_state, MM_MODEM_STATE_REASON_NONE); } else { - MMGenericGsm *self = MM_GENERIC_GSM (modem); - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - mm_port_set_connected (priv->data, FALSE); priv->cid = -1; - mm_generic_gsm_update_enabled_state (self, FALSE, MM_MODEM_STATE_REASON_NONE); + mm_generic_gsm_update_enabled_state (MM_GENERIC_GSM (modem), FALSE, MM_MODEM_STATE_REASON_NONE); + } + + /* Balance any open from connect(); subclasses may not use the generic + * class' connect function and so the dial port may not have been + * opened at all. + */ + if (priv->data_opened_at_connect) { + if (MM_IS_AT_SERIAL_PORT (priv->data)) + mm_serial_port_close (MM_SERIAL_PORT (priv->data)); + priv->data_opened_at_connect = FALSE; } mm_callback_info_schedule (info); @@ -3965,6 +3958,7 @@ disconnect_secondary_cgact_done (MMAtSerialPort *port, MMCallbackInfo *info = user_data; MMGenericGsm *self; MMGenericGsmPrivate *priv; + MMSerialPort *dial_port; /* If the modem has already been removed, return without * scheduling callback */ @@ -3980,7 +3974,11 @@ disconnect_secondary_cgact_done (MMAtSerialPort *port, if (!error) mm_callback_info_set_data (info, DISCONNECT_CGACT_DONE_TAG, GUINT_TO_POINTER (TRUE), NULL); - mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, TRUE, disconnect_flash_done, info); + dial_port = MM_SERIAL_PORT (priv->primary); + if (MM_IS_AT_SERIAL_PORT (priv->data)) + dial_port = MM_SERIAL_PORT (priv->data); + + mm_serial_port_flash (dial_port, 1000, TRUE, disconnect_flash_done, info); } static void @@ -3991,6 +3989,7 @@ real_do_disconnect (MMGenericGsm *self, { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); MMCallbackInfo *info; + MMSerialPort *dial_port; info = mm_callback_info_new (MM_MODEM (self), callback, user_data); @@ -4007,8 +4006,12 @@ real_do_disconnect (MMGenericGsm *self, disconnect_secondary_cgact_done, info); } else { - /* Just flash the primary port */ - mm_serial_port_flash (MM_SERIAL_PORT (priv->primary), 1000, TRUE, disconnect_flash_done, info); + /* Just flash the dial port */ + dial_port = MM_SERIAL_PORT (priv->primary); + if (MM_IS_AT_SERIAL_PORT (priv->data)) + dial_port = MM_SERIAL_PORT (priv->data); + + mm_serial_port_flash (dial_port, 1000, TRUE, disconnect_flash_done, info); } } @@ -5487,15 +5490,26 @@ sms_list (MMModemGsmSms *modem, MMAtSerialPort * mm_generic_gsm_get_at_port (MMGenericGsm *modem, - MMPortType ptype) + MMAtPortFlags flag) { + MMGenericGsmPrivate *priv; + g_return_val_if_fail (MM_IS_GENERIC_GSM (modem), NULL); - g_return_val_if_fail (ptype != MM_PORT_TYPE_UNKNOWN, NULL); - if (ptype == MM_PORT_TYPE_PRIMARY) - return MM_GENERIC_GSM_GET_PRIVATE (modem)->primary; - else if (ptype == MM_PORT_TYPE_SECONDARY) - return MM_GENERIC_GSM_GET_PRIVATE (modem)->secondary; + /* We only search for a single value even though it's a bitfield */ + g_return_val_if_fail ( flag == MM_AT_PORT_FLAG_NONE + || flag == MM_AT_PORT_FLAG_PRIMARY + || flag == MM_AT_PORT_FLAG_SECONDARY + || flag == MM_AT_PORT_FLAG_PPP, NULL); + + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + if (flag == MM_AT_PORT_FLAG_SECONDARY) + return priv->secondary; + else if (flag == MM_AT_PORT_FLAG_PRIMARY) + return priv->primary; + else if ((flag == MM_AT_PORT_FLAG_PPP) && MM_IS_AT_SERIAL_PORT (priv->data)) + return MM_AT_SERIAL_PORT (priv->data); return NULL; } @@ -6481,7 +6495,7 @@ static void modem_init (MMModem *modem_class) { modem_class->owns_port = owns_port; - modem_class->grab_port = grab_port; + modem_class->organize_ports = organize_ports; modem_class->release_port = release_port; modem_class->enable = enable; modem_class->disable = disable; @@ -6817,11 +6831,12 @@ finalize (GObject *object) } static void -mm_generic_gsm_class_init (MMGenericGsmClass *klass) +mm_generic_gsm_class_init (MMGenericGsmClass *generic_class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (generic_class); + MMModemBaseClass *base_class = MM_MODEM_BASE_CLASS (generic_class); - mm_generic_gsm_parent_class = g_type_class_peek_parent (klass); + mm_generic_gsm_parent_class = g_type_class_peek_parent (generic_class); g_type_class_add_private (object_class, sizeof (MMGenericGsmPrivate)); /* Virtual methods */ @@ -6829,12 +6844,14 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) object_class->get_property = get_property; object_class->finalize = finalize; - klass->do_enable = real_do_enable; - klass->do_enable_power_up_done = real_do_enable_power_up_done; - klass->do_disconnect = real_do_disconnect; - klass->get_sim_iccid = real_get_sim_iccid; - klass->get_operator_name = real_get_operator_name; - klass->get_operator_code = real_get_operator_code; + base_class->port_grabbed = port_grabbed; + + generic_class->do_enable = real_do_enable; + generic_class->do_enable_power_up_done = real_do_enable_power_up_done; + generic_class->do_disconnect = real_do_disconnect; + generic_class->get_sim_iccid = real_get_sim_iccid; + generic_class->get_operator_name = real_get_operator_name; + generic_class->get_operator_code = real_get_operator_code; /* Properties */ g_object_class_override_property (object_class, |