diff options
author | Dan Williams <dcbw@redhat.com> | 2009-12-02 14:43:09 -0800 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2009-12-02 14:43:09 -0800 |
commit | 5bdabaabec5ecb64986036bf783196eeee3756e7 (patch) | |
tree | c875f5dabc4572b44f9fac60a78de4c01590eb48 /src | |
parent | 872fe9bf6bb0555f7e4df85fc06314a013404428 (diff) |
gsm: implement enable/connecting/disconnecting state handling
And consolidate generic port enable code in one place since pretty
much every modem needs that.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-generic-gsm.c | 170 | ||||
-rw-r--r-- | src/mm-generic-gsm.h | 28 |
2 files changed, 143 insertions, 55 deletions
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index f9f87657..d351aca2 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -398,6 +398,29 @@ release_port (MMModem *modem, const char *subsys, const char *name) check_valid (MM_GENERIC_GSM (modem)); } +void +mm_generic_gsm_enable_complete (MMGenericGsm *modem, + GError *error, + MMCallbackInfo *info) +{ + g_return_if_fail (modem != NULL); + g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + g_return_if_fail (info != NULL); + + if (error) { + mm_modem_set_state (MM_MODEM (modem), + MM_MODEM_STATE_DISABLED, + MM_MODEM_STATE_REASON_NONE); + + info->error = g_error_copy (error); + } else { + /* Modem is enabled; update the state */ + mm_generic_gsm_update_enabled_state (modem, FALSE, MM_MODEM_STATE_REASON_NONE); + } + + mm_callback_info_schedule (info); +} + static void enable_done (MMSerialPort *port, GString *response, @@ -415,11 +438,7 @@ enable_done (MMSerialPort *port, * errors or ignore them. */ - mm_generic_gsm_update_enabled_state (MM_GENERIC_GSM (info->modem), - FALSE, - MM_MODEM_STATE_REASON_NONE); - - mm_callback_info_schedule (info); + mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), NULL, info); } static void @@ -432,34 +451,30 @@ init_done (MMSerialPort *port, char *cmd = NULL; if (error) { - mm_modem_set_state (MM_MODEM (info->modem), - MM_MODEM_STATE_DISABLED, - MM_MODEM_STATE_REASON_NONE); + mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); + return; + } - info->error = g_error_copy (error); - mm_callback_info_schedule (info); - } else { - /* Ensure echo is off after the init command; some modems ignore the - * E0 when it's in the same like as ATZ (Option GIO322). - */ - mm_serial_port_queue_command (port, "E0 +CMEE=1", 2, NULL, NULL); + /* Ensure echo is off after the init command; some modems ignore the + * E0 when it's in the same like as ATZ (Option GIO322). + */ + mm_serial_port_queue_command (port, "E0 +CMEE=1", 2, NULL, NULL); - g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD_OPTIONAL, &cmd, NULL); - mm_serial_port_queue_command (port, cmd, 2, NULL, NULL); - g_free (cmd); + g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_INIT_CMD_OPTIONAL, &cmd, NULL); + mm_serial_port_queue_command (port, cmd, 2, NULL, NULL); + g_free (cmd); - if (MM_GENERIC_GSM_GET_PRIVATE (info->modem)->unsolicited_registration) - mm_serial_port_queue_command (port, "+CREG=1", 5, NULL, NULL); - else - mm_serial_port_queue_command (port, "+CREG=0", 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_port_queue_command (port, "+CREG=0", 5, NULL, NULL); - g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL); - if (cmd && strlen (cmd)) - mm_serial_port_queue_command (port, cmd, 5, enable_done, user_data); - else - enable_done (port, NULL, NULL, user_data); - g_free (cmd); - } + g_object_get (G_OBJECT (info->modem), MM_GENERIC_GSM_POWER_UP_CMD, &cmd, NULL); + if (cmd && strlen (cmd)) + mm_serial_port_queue_command (port, cmd, 5, enable_done, user_data); + else + enable_done (port, NULL, NULL, user_data); + g_free (cmd); } static void @@ -469,12 +484,7 @@ enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data) char *cmd = NULL; if (error) { - mm_modem_set_state (MM_MODEM (info->modem), - MM_MODEM_STATE_DISABLED, - MM_MODEM_STATE_REASON_NONE); - - info->error = g_error_copy (error); - mm_callback_info_schedule (info); + mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); return; } @@ -484,29 +494,40 @@ enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data) } static void +real_do_enable (MMGenericGsm *self, 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, 100, enable_flash_done, info); +} + +static void enable (MMModem *modem, MMModemFn callback, gpointer user_data) { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); - MMCallbackInfo *info; + GError *error = NULL; /* 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); + if (!mm_serial_port_open (priv->primary, &error)) { + MMCallbackInfo *info; - if (!mm_serial_port_open (priv->primary, &info->error)) { - g_assert (info->error); + g_assert (error); + info = mm_callback_info_new (modem, callback, user_data); + info->error = error; mm_callback_info_schedule (info); return; } - mm_modem_set_state (MM_MODEM (info->modem), - MM_MODEM_STATE_ENABLING, - MM_MODEM_STATE_REASON_NONE); + mm_modem_set_state (modem, MM_MODEM_STATE_ENABLING, MM_MODEM_STATE_REASON_NONE); - mm_serial_port_flash (priv->primary, 100, enable_flash_done, info); + g_assert (MM_GENERIC_GSM_GET_CLASS (modem)->do_enable); + MM_GENERIC_GSM_GET_CLASS (modem)->do_enable (MM_GENERIC_GSM (modem), callback, user_data); } static void @@ -1190,6 +1211,33 @@ get_registration_info (MMModemGsmNetwork *self, mm_callback_info_schedule (info); } +void +mm_generic_gsm_connect_complete (MMGenericGsm *modem, + GError *error, + MMCallbackInfo *info) +{ + MMGenericGsmPrivate *priv; + + g_return_if_fail (modem != NULL); + g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + g_return_if_fail (info != NULL); + + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + if (error) { + mm_generic_gsm_update_enabled_state (modem, FALSE, MM_MODEM_STATE_REASON_NONE); + info->error = g_error_copy (error); + } else { + /* Modem is connected; update the state */ + mm_port_set_connected (priv->data, TRUE); + mm_modem_set_state (MM_MODEM (modem), + MM_MODEM_STATE_CONNECTED, + MM_MODEM_STATE_REASON_NONE); + } + + mm_callback_info_schedule (info); +} + static void connect_report_done (MMSerialPort *port, GString *response, @@ -1197,14 +1245,28 @@ connect_report_done (MMSerialPort *port, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; + GError *real_error; + + /* If the CEER command was successful, copy that error reason into the + * callback's error. If not, use the original error. + */ - if (!error && g_str_has_prefix (response->str, "+CEER: ")) { - g_free (info->error->message); - info->error->message = g_strdup (response->str + 7); /* skip the "+CEER: " */ + /* Have to do this little dance since mm_generic_gsm_connect_complete() + * copies the provided error into the callback info. + */ + real_error = info->error; + info->error = NULL; + + if ( !error + && g_str_has_prefix (response->str, "+CEER: ") + && (strlen (response->str) > 7)) { + /* copy the connect failure reason into the error */ + g_free (real_error->message); + real_error->message = g_strdup (response->str + 7); /* skip the "+CEER: " */ } - - mm_generic_gsm_update_enabled_state (MM_GENERIC_GSM (info->modem), FALSE, MM_MODEM_STATE_REASON_NONE); - mm_callback_info_schedule (info); + + mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), real_error, info); + g_error_free (real_error); } static void @@ -1221,12 +1283,8 @@ connect_done (MMSerialPort *port, /* Try to get more information why it failed */ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); mm_serial_port_queue_command (priv->primary, "+CEER", 3, connect_report_done, info); - } else { - /* Done */ - mm_port_set_connected (priv->data, TRUE); - mm_modem_set_state (info->modem, MM_MODEM_STATE_CONNECTED, MM_MODEM_STATE_REASON_NONE); - mm_callback_info_schedule (info); - } + } else + mm_generic_gsm_connect_complete (MM_GENERIC_GSM (info->modem), NULL, info); } static void @@ -2155,6 +2213,8 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) object_class->get_property = get_property; object_class->finalize = finalize; + klass->do_enable = real_do_enable; + /* Properties */ g_object_class_override_property (object_class, MM_MODEM_PROP_DATA_DEVICE, diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index ea60ffbf..de0b00b7 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -21,6 +21,7 @@ #include "mm-modem-gsm-network.h" #include "mm-modem-base.h" #include "mm-serial-port.h" +#include "mm-callback-info.h" #define MM_TYPE_GENERIC_GSM (mm_generic_gsm_get_type ()) #define MM_GENERIC_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_GENERIC_GSM, MMGenericGsm)) @@ -52,6 +53,15 @@ typedef struct { typedef struct { MMModemBaseClass parent; + + /* Called after opening the primary serial port and updating the modem's + * state to ENABLING, but before sending any commands to the device. Modems + * that need to perform custom initialization sequences or other setup should + * generally override this method instead of the MMModem interface's enable() + * method, unless the customization must happen *after* the generic init + * sequence has completed. + */ + void (*do_enable) (MMGenericGsm *self, MMModemFn callback, gpointer user_data); } MMGenericGsmClass; GType mm_generic_gsm_get_type (void); @@ -98,4 +108,22 @@ void mm_generic_gsm_update_enabled_state (MMGenericGsm *modem, gboolean stay_connected, MMModemStateReason reason); +/* Called to complete the enable operation for custom enable() handling; if an + * error is passed in, it copies the error to the callback info. This function + * always schedules the callback info. It will also update the modem with the + * correct state for both failure and success of the enable operation. + */ +void mm_generic_gsm_enable_complete (MMGenericGsm *modem, + GError *error, + MMCallbackInfo *info); + +/* Called to complete the enable operation for custom connect() handling; if an + * error is passed in, it copies the error to the callback info. This function + * always schedules the callback info. It will also update the modem with the + * correct state for both failure and success of the connect operation. + */ +void mm_generic_gsm_connect_complete (MMGenericGsm *modem, + GError *error, + MMCallbackInfo *info); + #endif /* MM_GENERIC_GSM_H */ |