diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-generic-gsm.c | 118 | ||||
-rw-r--r-- | src/mm-generic-gsm.h | 12 |
2 files changed, 94 insertions, 36 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 5a50b24a..dcb37c32 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -81,7 +81,7 @@ typedef struct { guint signal_quality_id; time_t signal_quality_timestamp; guint32 signal_quality; - guint32 cid; + gint cid; MMSerialPort *primary; MMSerialPort *secondary; @@ -141,15 +141,7 @@ mm_generic_gsm_new (const char *device, NULL)); } -void -mm_generic_gsm_set_cid (MMGenericGsm *modem, guint32 cid) -{ - g_return_if_fail (MM_IS_GENERIC_GSM (modem)); - - MM_GENERIC_GSM_GET_PRIVATE (modem)->cid = cid; -} - -guint32 +gint mm_generic_gsm_get_cid (MMGenericGsm *modem) { g_return_val_if_fail (MM_IS_GENERIC_GSM (modem), 0); @@ -821,7 +813,7 @@ enable (MMModem *modem, } /* First, reset the previously used CID */ - mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0); + priv->cid = -1; if (!mm_serial_port_open (priv->primary, &error)) { MMCallbackInfo *info; @@ -907,7 +899,9 @@ disable (MMModem *modem, MMModemState state; /* First, reset the previously used CID and clean up registration */ - mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0); + g_warn_if_fail (priv->cid == -1); + priv->cid = -1; + mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem)); if (priv->poll_id) { @@ -1919,16 +1913,16 @@ connect (MMModem *modem, } static void -disconnect_flash_done (MMSerialPort *port, - GError *error, - gpointer user_data) +disconnect_done (MMModem *modem, + GError *error, + gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMModemState prev_state; - info->error = mm_modem_check_removed (info->modem, error); + info->error = mm_modem_check_removed (modem, error); if (info->error) { - if (info->modem) { + if (info->modem && modem) { /* Reset old state since the operation failed */ prev_state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, MM_GENERIC_GSM_PREV_STATE_TAG)); mm_modem_set_state (MM_MODEM (info->modem), @@ -1936,10 +1930,11 @@ disconnect_flash_done (MMSerialPort *port, MM_MODEM_STATE_REASON_NONE); } } else { - MMGenericGsm *self = MM_GENERIC_GSM (info->modem); + 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); } @@ -1947,17 +1942,65 @@ disconnect_flash_done (MMSerialPort *port, } static void +disconnect_cgact_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + mm_callback_info_schedule ((MMCallbackInfo *) user_data); +} + +static void +disconnect_flash_done (MMSerialPort *port, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + MMGenericGsmPrivate *priv; + char *command; + + info->error = mm_modem_check_removed (info->modem, error); + if (info->error) { + mm_callback_info_schedule (info); + return; + } + + /* Disconnect the PDP context */ + priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + if (priv->cid >= 0) + command = g_strdup_printf ("+CGACT=0,%d", priv->cid); + else { + /* Disable all PDP contexts */ + command = g_strdup_printf ("+CGACT=0"); + } + + mm_serial_port_queue_command (port, command, 60, disconnect_cgact_done, info); + g_free (command); +} + +static void +real_do_disconnect (MMGenericGsm *self, + gint cid, + MMModemFn callback, + gpointer user_data) +{ + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + MMCallbackInfo *info; + + info = mm_callback_info_new (MM_MODEM (self), callback, user_data); + mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info); +} + +static void disconnect (MMModem *modem, MMModemFn callback, gpointer user_data) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + MMGenericGsm *self = MM_GENERIC_GSM (modem); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); MMCallbackInfo *info; MMModemState state; - /* 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); /* Cache the previous state so we can reset it if the operation fails */ @@ -1968,7 +2011,9 @@ disconnect (MMModem *modem, NULL); mm_modem_set_state (modem, MM_MODEM_STATE_DISCONNECTING, MM_MODEM_STATE_REASON_NONE); - mm_serial_port_flash (priv->primary, 1000, disconnect_flash_done, info); + + g_assert (MM_GENERIC_GSM_GET_CLASS (self)->do_disconnect); + MM_GENERIC_GSM_GET_CLASS (self)->do_disconnect (self, priv->cid, disconnect_done, info); } static void @@ -2020,6 +2065,8 @@ scan (MMModemGsmNetwork *modem, /* SetApn */ +#define APN_CID_TAG "generic-gsm-cid" + static void set_apn_done (MMSerialPort *port, GString *response, @@ -2028,11 +2075,12 @@ set_apn_done (MMSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - if (error) - info->error = g_error_copy (error); - else - mm_generic_gsm_set_cid (MM_GENERIC_GSM (info->modem), - GPOINTER_TO_UINT (mm_callback_info_get_data (info, "cid"))); + info->error = mm_modem_check_removed (info->modem, error); + if (!info->error) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + + priv->cid = GPOINTER_TO_INT (mm_callback_info_get_data (info, APN_CID_TAG)); + } mm_callback_info_schedule (info); } @@ -2095,7 +2143,7 @@ cid_range_read (MMSerialPort *port, const char *apn = (const char *) mm_callback_info_get_data (info, "apn"); char *command; - mm_callback_info_set_data (info, "cid", GUINT_TO_POINTER (cid), NULL); + mm_callback_info_set_data (info, APN_CID_TAG, GINT_TO_POINTER (cid), NULL); command = g_strdup_printf ("+CGDCONT=%d,\"IP\",\"%s\"", cid, apn); mm_serial_port_queue_command (port, command, 3, set_apn_done, info); @@ -2112,8 +2160,9 @@ existing_apns_read (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; gboolean found = FALSE; - if (error) - info->error = g_error_copy (error); + info->error = mm_modem_check_removed (info->modem, error); + if (info->error) + goto done; else if (g_str_has_prefix (response->str, "+CGDCONT: ")) { GRegex *r; GMatchInfo *match_info; @@ -2137,7 +2186,7 @@ existing_apns_read (MMSerialPort *port, apn = g_match_info_fetch (match_info, 3); if (!strcmp (apn, new_apn)) { - mm_generic_gsm_set_cid (MM_GENERIC_GSM (info->modem), (guint32) num_cid); + MM_GENERIC_GSM_GET_PRIVATE (info->modem)->cid = num_cid; found = TRUE; } @@ -2165,11 +2214,13 @@ existing_apns_read (MMSerialPort *port, MM_MODEM_ERROR_GENERAL, "Could not parse the response"); +done: if (found || info->error) mm_callback_info_schedule (info); - else + else { /* APN not configured on the card. Get the allowed CID range */ mm_serial_port_queue_command_cached (port, "+CGDCONT=?", 3, cid_range_read, info); + } } static void @@ -2983,6 +3034,7 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) klass->do_enable = real_do_enable; klass->do_enable_power_up_done = real_do_enable_power_up_done; + klass->do_disconnect = real_do_disconnect; /* Properties */ g_object_class_override_property (object_class, diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 348ff4f8..9aef615e 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -79,6 +79,14 @@ typedef struct { GError *error, MMCallbackInfo *info); + /* Called to terminate the active data call and deactivate the given PDP + * context. + */ + void (*do_disconnect) (MMGenericGsm *self, + gint cid, + MMModemFn callback, + gpointer user_data); + /* Called by the generic class to set the allowed operating mode of the device */ void (*set_allowed_mode) (MMGenericGsm *self, MMModemGsmAllowedMode mode, @@ -110,10 +118,8 @@ MMModem *mm_generic_gsm_new (const char *device, void mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem); -void mm_generic_gsm_set_cid (MMGenericGsm *modem, - guint32 cid); +gint mm_generic_gsm_get_cid (MMGenericGsm *modem); -guint32 mm_generic_gsm_get_cid (MMGenericGsm *modem); void mm_generic_gsm_set_reg_status (MMGenericGsm *modem, MMModemGsmNetworkRegStatus status); |