From a9ef8cb1759f25ee26f8015aa2e45a2bd3cd2da7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 1 Mar 2010 09:15:01 -0800 Subject: [PATCH 01/38] policy: split Device into Info and Control It's useful to let distros and admins set policy differently for device information (for support, inventory, etc) than for actually controlling the device like PIN/PUK unlocks. --- policy/org.freedesktop.modem-manager.policy.in | 15 ++++++++++++--- src/mm-auth-provider.h | 7 ++++--- src/mm-modem-cdma.c | 2 +- src/mm-modem-gsm-card.c | 12 ++++++------ src/mm-modem-gsm-network.c | 2 +- 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/policy/org.freedesktop.modem-manager.policy.in b/policy/org.freedesktop.modem-manager.policy.in index 1c6f214c..6ac75f4c 100644 --- a/policy/org.freedesktop.modem-manager.policy.in +++ b/policy/org.freedesktop.modem-manager.policy.in @@ -9,9 +9,18 @@ http://www.freedesktop.org/wiki/ModemManager modem-manager - - <_description>Unlock and retrieve mobile broadband device information - <_message>System policy prevents unlocking the device or requesting information from it. + + <_description>Unlock and control a mobile broadband device + <_message>System policy prevents unlocking or controlling the mobile broadband device. + + no + auth_self_keep + + + + + <_description>Request mobile broadband device identifying information + <_message>System policy prevents requesting identifying information from the mobile broadband device. no auth_self_keep diff --git a/src/mm-auth-provider.h b/src/mm-auth-provider.h index 94edc44d..c5fc961b 100644 --- a/src/mm-auth-provider.h +++ b/src/mm-auth-provider.h @@ -22,9 +22,10 @@ #include "mm-auth-request.h" /* Authorizations */ -#define MM_AUTHORIZATION_DEVICE "org.freedesktop.ModemManager.Device" -#define MM_AUTHORIZATION_CONTACTS "org.freedesktop.ModemManager.Contacts" -#define MM_AUTHORIZATION_SMS "org.freedesktop.ModemManager.SMS" +#define MM_AUTHORIZATION_DEVICE_INFO "org.freedesktop.ModemManager.Device.Info" +#define MM_AUTHORIZATION_DEVICE_CONTROL "org.freedesktop.ModemManager.Device.Control" +#define MM_AUTHORIZATION_CONTACTS "org.freedesktop.ModemManager.Contacts" +#define MM_AUTHORIZATION_SMS "org.freedesktop.ModemManager.SMS" /******************/ diff --git a/src/mm-modem-cdma.c b/src/mm-modem-cdma.c index 1a4fe6a2..e80dc4e2 100644 --- a/src/mm-modem-cdma.c +++ b/src/mm-modem-cdma.c @@ -212,7 +212,7 @@ impl_modem_cdma_get_esn (MMModemCdma *self, DBusGMethodInvocation *context) /* Make sure the caller is authorized to get the ESN */ if (!mm_modem_auth_request (MM_MODEM (self), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_INFO, context, esn_auth_cb, NULL, diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c index 9881871c..f4a5138f 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -225,7 +225,7 @@ impl_gsm_modem_get_imei (MMModemGsmCard *modem, DBusGMethodInvocation *context) /* Make sure the caller is authorized to get the IMEI */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_INFO, context, imei_auth_cb, NULL, @@ -262,7 +262,7 @@ impl_gsm_modem_get_imsi (MMModemGsmCard *modem, DBusGMethodInvocation *context) /* Make sure the caller is authorized to get the IMSI */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_INFO, context, imsi_auth_cb, NULL, @@ -343,7 +343,7 @@ impl_gsm_modem_send_puk (MMModemGsmCard *modem, /* Make sure the caller is authorized to send the PUK */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_CONTROL, context, send_puk_auth_cb, info, @@ -386,7 +386,7 @@ impl_gsm_modem_send_pin (MMModemGsmCard *modem, /* Make sure the caller is authorized to unlock the modem */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_CONTROL, context, send_pin_auth_cb, info, @@ -430,7 +430,7 @@ impl_gsm_modem_enable_pin (MMModemGsmCard *modem, /* Make sure the caller is authorized to enable a PIN */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_CONTROL, context, enable_pin_auth_cb, info, @@ -474,7 +474,7 @@ impl_gsm_modem_change_pin (MMModemGsmCard *modem, /* Make sure the caller is authorized to change the PIN */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_CONTROL, context, change_pin_auth_cb, info, diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index bf52b942..f332f580 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -422,7 +422,7 @@ impl_gsm_modem_scan (MMModemGsmNetwork *modem, /* Make sure the caller is authorized to request a scan */ if (!mm_modem_auth_request (MM_MODEM (modem), - MM_AUTHORIZATION_DEVICE, + MM_AUTHORIZATION_DEVICE_CONTROL, context, scan_auth_cb, NULL, From 3b9b7920f5157c62715f7450574335b3c1ca4d64 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 10:29:42 -0800 Subject: [PATCH 02/38] core: register Modem UnlockRequired property for changed signals too --- src/mm-modem-base.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mm-modem-base.c b/src/mm-modem-base.c index af1c6258..890c55c7 100644 --- a/src/mm-modem-base.c +++ b/src/mm-modem-base.c @@ -265,6 +265,9 @@ mm_modem_base_init (MMModemBase *self) mm_properties_changed_signal_register_property (G_OBJECT (self), MM_MODEM_ENABLED, MM_MODEM_DBUS_INTERFACE); + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_UNLOCK_REQUIRED, + MM_MODEM_DBUS_INTERFACE); } static void From 6dd751bf3f7bf515767ac6864b7eaf126e01fb3d Mon Sep 17 00:00:00 2001 From: Torgny Johansson Date: Thu, 4 Mar 2010 17:19:28 -0800 Subject: [PATCH 03/38] mbm: handle E2NAP disconnect notification during connection attempt If E2NAP:0 is received during a connection attempt the connection attempt has failed or will fail. So stop polling for connection success for another 50 seconds and abort the connection attempt immediately. Also moves the E2NAP request call a bit earlier to ensure that no E2NAP unsolicited messages are lost. --- plugins/mm-modem-mbm.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index 4e08c689..eb98990c 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -521,14 +521,23 @@ mbm_ciev_received (MMSerialPort *port, } static void -mbm_do_connect_done (MMModemMbm *self) +mbm_do_connect_done (MMModemMbm *self, gboolean success) { MMModemMbmPrivate *priv = MM_MODEM_MBM_GET_PRIVATE (self); - if (priv->pending_connect_info) { + if (!priv->pending_connect_info) + return; + + if (success) mm_generic_gsm_connect_complete (MM_GENERIC_GSM (self), NULL, priv->pending_connect_info); - priv->pending_connect_info = NULL; + else { + GError *connect_error; + + connect_error = mm_modem_connect_error_for_code (MM_MODEM_CONNECT_ERROR_BUSY); + mm_generic_gsm_connect_complete (MM_GENERIC_GSM (self), connect_error, priv->pending_connect_info); + g_error_free (connect_error); } + priv->pending_connect_info = NULL; } static void @@ -543,17 +552,18 @@ mbm_e2nap_received (MMSerialPort *port, if (str) state = atoi (str); - if (MBM_E2NAP_DISCONNECTED == state) - g_debug ("%s, disconnected", __func__); - else if (MBM_E2NAP_CONNECTED == state) { - g_debug ("%s, connected", __func__); - mbm_do_connect_done (MM_MODEM_MBM (user_data)); + if (MBM_E2NAP_DISCONNECTED == state) { + g_debug ("%s: disconnected", __func__); + mbm_do_connect_done (MM_MODEM_MBM (user_data), FALSE); + } else if (MBM_E2NAP_CONNECTED == state) { + g_debug ("%s: connected", __func__); + mbm_do_connect_done (MM_MODEM_MBM (user_data), TRUE); } else if (MBM_E2NAP_CONNECTING == state) - g_debug("%s, connecting", __func__); + g_debug("%s: connecting", __func__); else { /* Should not happen */ - g_debug("%s, undefined e2nap status",__FUNCTION__); - g_assert_not_reached (); + g_debug("%s: unhandled E2NAP state %d", __func__, state); + mbm_do_connect_done (MM_MODEM_MBM (user_data), FALSE); } } @@ -619,7 +629,6 @@ enap_done (MMSerialPort *port, tid = g_timeout_add_seconds (1, enap_poll, user_data); /* remember poll id as callback info object, with source_remove as free func */ mm_callback_info_set_data (info, "mbm-enap-poll-id", GUINT_TO_POINTER (tid), (GFreeFunc) g_source_remove); - mm_serial_port_queue_command (port, "AT*E2NAP=1", 3, NULL, NULL); } static void @@ -639,6 +648,9 @@ mbm_auth_done (MMSerialPort *port, } cid = mm_generic_gsm_get_cid (modem); + + mm_serial_port_queue_command (port, "AT*E2NAP=1", 3, NULL, NULL); + command = g_strdup_printf ("AT*ENAP=1,%d", cid); mm_serial_port_queue_command (port, command, 3, enap_done, user_data); g_free (command); From 3457adefefa8bedd0349e6ac3d5cebcacf958000 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 17:28:36 -0800 Subject: [PATCH 04/38] gsm: clarify generic GSM subclass API a bit --- src/mm-generic-gsm.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index de0b00b7..4f190f8b 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -59,7 +59,10 @@ typedef struct { * 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. + * sequence has completed. When the subclass' enable attempt is complete + * the subclass should call mm_generic_gsm_enable_complete() with any error + * encountered during the process and the MMCallbackInfo created from the + * callback and user_data passed in here. */ void (*do_enable) (MMGenericGsm *self, MMModemFn callback, gpointer user_data); } MMGenericGsmClass; From 021ca1244e2be8afcf6bdb552866263dc20c9285 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 19:01:13 -0800 Subject: [PATCH 05/38] gsm: postpone PIN/PUK success reply until we know updated unlock status Don't return until we know what the updated lock status is. Fixes an issue where callers that send the PIN before the modem is enabled (remember, some modems can't be enabled until the PIN is entered, so sometimes we have to send the PIN before it's enabled) would get the reply too early and get failures from other operations. --- src/mm-generic-gsm.c | 45 +++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 6f88a031..9e38b29a 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -799,24 +799,25 @@ get_card_info (MMModem *modem, mm_serial_port_queue_command_cached (priv->primary, "+CGMR", 3, get_version_done, info); } +#define PIN_CLOSE_PORT_TAG "close-port" + static void pin_puk_recheck_done (MMModem *modem, GError *error, gpointer user_data) { - gboolean close_port = !!user_data; + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + gboolean close_port = !!mm_callback_info_get_data (info, PIN_CLOSE_PORT_TAG); /* modem could have been removed before we get here, in which case * 'modem' will be NULL. */ - if (modem) { - g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + info->error = mm_modem_check_removed (modem, error); - if (close_port) - mm_serial_port_close (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary); - } + if (modem && close_port) + mm_serial_port_close (MM_GENERIC_GSM_GET_PRIVATE (modem)->primary); + + mm_callback_info_schedule (info); } -#define PIN_CLOSE_PORT_TAG "close-port" - static void send_puk_done (MMSerialPort *port, GString *response, @@ -826,15 +827,16 @@ send_puk_done (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; gboolean close_port = !!mm_callback_info_get_data (info, PIN_CLOSE_PORT_TAG); - if (error) + if (error) { info->error = g_error_copy (error); + mm_callback_info_schedule (info); + if (close_port) + mm_serial_port_close (port); + return; + } - /* Get latest PUK status */ - mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), - pin_puk_recheck_done, - GUINT_TO_POINTER (close_port)); - - mm_callback_info_schedule (info); + /* Get latest PIN status */ + mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), pin_puk_recheck_done, info); } static void @@ -886,15 +888,16 @@ send_pin_done (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; gboolean close_port = !!mm_callback_info_get_data (info, PIN_CLOSE_PORT_TAG); - if (error) + if (error) { info->error = g_error_copy (error); + mm_callback_info_schedule (info); + if (close_port) + mm_serial_port_close (port); + return; + } /* Get latest PIN status */ - mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), - pin_puk_recheck_done, - GUINT_TO_POINTER (close_port)); - - mm_callback_info_schedule (info); + mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), pin_puk_recheck_done, info); } static void From 407abc65c6ccd802ce8456e5a63e68fab1c7d0a1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 19:30:54 -0800 Subject: [PATCH 06/38] gsm: handle PINs better during modem enable and simple state machine First, short-circuit the Enable process if the device requires a PIN or PUK since for many devices the enable is going to fail anyway until the PIN is sent. Second, send the PIN first during the simple state machine for the same reason; we need the device unlocked before we want to try to enable it. This also reworks the simple state machine to be a bit clearer and make each state step correspond to the action it's actually doing instead of being off-by-one visually (but not logically). --- src/mm-generic-gsm.c | 167 ++++++++++++++++++++++++++----------------- 1 file changed, 103 insertions(+), 64 deletions(-) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 9e38b29a..28a3a4fa 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -141,6 +141,45 @@ typedef struct { guint code; } CPinResult; +static CPinResult unlock_results[] = { + { "SIM PIN", "sim-pin", MM_MOBILE_ERROR_SIM_PIN }, + { "SIM PUK", "sim-puk", MM_MOBILE_ERROR_SIM_PUK }, + { "PH-SIM PIN", "ph-sim-pin", MM_MOBILE_ERROR_PH_SIM_PIN }, + { "PH-FSIM PIN", "ph-fsim-pin", MM_MOBILE_ERROR_PH_FSIM_PIN }, + { "PH-FSIM PUK", "ph-fsim-puk", MM_MOBILE_ERROR_PH_FSIM_PUK }, + { "SIM PIN2", "sim-pin2", MM_MOBILE_ERROR_SIM_PIN2 }, + { "SIM PUK2", "sim-puk2", MM_MOBILE_ERROR_SIM_PUK2 }, + { "PH-NET PIN", "ph-net-pin", MM_MOBILE_ERROR_NETWORK_PIN }, + { "PH-NET PUK", "ph-net-puk", MM_MOBILE_ERROR_NETWORK_PUK }, + { "PH-NETSUB PIN", "ph-netsub-pin", MM_MOBILE_ERROR_NETWORK_SUBSET_PIN }, + { "PH-NETSUB PUK", "ph-netsub-puk", MM_MOBILE_ERROR_NETWORK_SUBSET_PUK }, + { "PH-SP PIN", "ph-sp-pin", MM_MOBILE_ERROR_SERVICE_PIN }, + { "PH-SP PUK", "ph-sp-puk", MM_MOBILE_ERROR_SERVICE_PUK }, + { "PH-CORP PIN", "ph-corp-pin", MM_MOBILE_ERROR_CORP_PIN }, + { "PH-CORP PUK", "ph-corp-puk", MM_MOBILE_ERROR_CORP_PUK }, + { NULL, NULL, MM_MOBILE_ERROR_PHONE_FAILURE }, +}; + +static GError * +error_for_unlock_required (const char *unlock) +{ + CPinResult *iter = &unlock_results[0]; + + if (!unlock || !strlen (unlock)) + return NULL; + + /* Translate the error */ + while (iter->result) { + if (!strcmp (iter->normalized, unlock)) + return mm_mobile_error_for_code (iter->code); + iter++; + } + + return g_error_new (MM_MOBILE_ERROR, + MM_MOBILE_ERROR_UNKNOWN, + "Unknown unlock request '%s'", unlock); +} + static void pin_check_done (MMSerialPort *port, GString *response, @@ -149,24 +188,6 @@ pin_check_done (MMSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; gboolean parsed = FALSE; - static CPinResult results[] = { - { "SIM PIN", "sim-pin", MM_MOBILE_ERROR_SIM_PIN }, - { "SIM PUK", "sim-puk", MM_MOBILE_ERROR_SIM_PUK }, - { "PH-SIM PIN", "ph-sim-pin", MM_MOBILE_ERROR_PH_SIM_PIN }, - { "PH-FSIM PIN", "ph-fsim-pin", MM_MOBILE_ERROR_PH_FSIM_PIN }, - { "PH-FSIM PUK", "ph-fsim-puk", MM_MOBILE_ERROR_PH_FSIM_PUK }, - { "SIM PIN2", "sim-pin2", MM_MOBILE_ERROR_SIM_PIN2 }, - { "SIM PUK2", "sim-puk2", MM_MOBILE_ERROR_SIM_PUK2 }, - { "PH-NET PIN", "ph-net-pin", MM_MOBILE_ERROR_NETWORK_PIN }, - { "PH-NET PUK", "ph-net-puk", MM_MOBILE_ERROR_NETWORK_PUK }, - { "PH-NETSUB PIN", "ph-netsub-pin", MM_MOBILE_ERROR_NETWORK_SUBSET_PIN }, - { "PH-NETSUB PUK", "ph-netsub-puk", MM_MOBILE_ERROR_NETWORK_SUBSET_PUK }, - { "PH-SP PIN", "ph-sp-pin", MM_MOBILE_ERROR_SERVICE_PIN }, - { "PH-SP PUK", "ph-sp-puk", MM_MOBILE_ERROR_SERVICE_PUK }, - { "PH-CORP PIN", "ph-corp-pin", MM_MOBILE_ERROR_CORP_PIN }, - { "PH-CORP PUK", "ph-corp-puk", MM_MOBILE_ERROR_CORP_PUK }, - { NULL, NULL, MM_MOBILE_ERROR_PHONE_FAILURE }, - }; if (error) info->error = g_error_copy (error); @@ -177,7 +198,7 @@ pin_check_done (MMSerialPort *port, mm_modem_base_set_unlock_required (MM_MODEM_BASE (info->modem), NULL); parsed = TRUE; } else { - CPinResult *iter = &results[0]; + CPinResult *iter = &unlock_results[0]; /* Translate the error */ while (iter->result) { @@ -563,6 +584,18 @@ enable (MMModem *modem, { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); GError *error = NULL; + const char *unlock; + + /* If the device needs a PIN, deal with that now */ + unlock = mm_modem_base_get_unlock_required (MM_MODEM_BASE (modem)); + if (unlock) { + MMCallbackInfo *info; + + info = mm_callback_info_new (modem, callback, user_data); + info->error = error_for_unlock_required (unlock); + mm_callback_info_schedule (info); + return; + } /* First, reset the previously used CID */ mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0); @@ -1969,9 +2002,8 @@ mm_generic_gsm_get_port (MMGenericGsm *modem, /* MMModemSimple interface */ typedef enum { - SIMPLE_STATE_BEGIN = 0, + SIMPLE_STATE_CHECK_PIN = 0, SIMPLE_STATE_ENABLE, - SIMPLE_STATE_CHECK_PIN, SIMPLE_STATE_REGISTER, SIMPLE_STATE_SET_APN, SIMPLE_STATE_CONNECT, @@ -2002,68 +2034,75 @@ static void simple_state_machine (MMModem *modem, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - const char *str; + const char *str, *unlock = NULL; SimpleState state = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "simple-connect-state")); - gboolean need_pin = FALSE; + SimpleState next_state = state; + gboolean done = FALSE; if (error) { - if (g_error_matches (error, MM_MOBILE_ERROR, MM_MOBILE_ERROR_SIM_PIN)) { - need_pin = TRUE; - state = SIMPLE_STATE_CHECK_PIN; - } else { - info->error = g_error_copy (error); - goto out; - } + info->error = g_error_copy (error); + goto out; } switch (state) { - case SIMPLE_STATE_BEGIN: - state = SIMPLE_STATE_ENABLE; - mm_modem_enable (modem, simple_state_machine, info); - break; - case SIMPLE_STATE_ENABLE: - state = SIMPLE_STATE_CHECK_PIN; - mm_generic_gsm_check_pin (MM_GENERIC_GSM (modem), simple_state_machine, info); - break; case SIMPLE_STATE_CHECK_PIN: - if (need_pin) { - str = simple_get_string_property (info, "pin", &info->error); - if (str) - mm_modem_gsm_card_send_pin (MM_MODEM_GSM_CARD (modem), str, simple_state_machine, info); - else - info->error = g_error_copy (error); - } else { - str = simple_get_string_property (info, "network_id", &info->error); - state = SIMPLE_STATE_REGISTER; - if (!info->error) - mm_modem_gsm_network_register (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info); - } - break; - case SIMPLE_STATE_REGISTER: - str = simple_get_string_property (info, "apn", &info->error); - if (str) { - state = SIMPLE_STATE_SET_APN; - mm_modem_gsm_network_set_apn (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info); + next_state = SIMPLE_STATE_ENABLE; + + /* If we need a PIN, send it now */ + unlock = mm_modem_base_get_unlock_required (MM_MODEM_BASE (modem)); + if (unlock) { + gboolean success = FALSE; + + if (!strcmp (unlock, "sim-pin")) { + str = simple_get_string_property (info, "pin", &info->error); + if (str) { + mm_modem_gsm_card_send_pin (MM_MODEM_GSM_CARD (modem), str, simple_state_machine, info); + success = TRUE; + } + } + if (!success && !info->error) + info->error = error_for_unlock_required (unlock); break; } - /* Fall through */ - case SIMPLE_STATE_SET_APN: - str = simple_get_string_property (info, "number", &info->error); - state = SIMPLE_STATE_CONNECT; - mm_modem_connect (modem, str, simple_state_machine, info); + /* Fall through if no PIN required */ + case SIMPLE_STATE_ENABLE: + next_state = SIMPLE_STATE_REGISTER; + mm_modem_enable (modem, simple_state_machine, info); break; + case SIMPLE_STATE_REGISTER: + next_state = SIMPLE_STATE_SET_APN; + str = simple_get_string_property (info, "network_id", &info->error); + if (str || info->error) { + if (str) + mm_modem_gsm_network_register (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info); + break; + } + /* Fall through if no explicit network registration is required */ + case SIMPLE_STATE_SET_APN: + next_state = SIMPLE_STATE_CONNECT; + str = simple_get_string_property (info, "apn", &info->error); + if (str || info->error) { + if (str) + mm_modem_gsm_network_set_apn (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info); + break; + } + /* Fall through if no APN or no 'apn' property error */ case SIMPLE_STATE_CONNECT: - state = SIMPLE_STATE_DONE; + next_state = SIMPLE_STATE_DONE; + str = simple_get_string_property (info, "number", &info->error); + if (!info->error) + mm_modem_connect (modem, str, simple_state_machine, info); break; case SIMPLE_STATE_DONE: + done = TRUE; break; } out: - if (info->error || state == SIMPLE_STATE_DONE) + if (info->error || done) mm_callback_info_schedule (info); else - mm_callback_info_set_data (info, "simple-connect-state", GUINT_TO_POINTER (state), NULL); + mm_callback_info_set_data (info, "simple-connect-state", GUINT_TO_POINTER (next_state), NULL); } static void From 3f7b173932bfb23ce83bfab8a74490f7dc85a7f7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 19:40:33 -0800 Subject: [PATCH 07/38] sierra: fix comment about CFUN=1 delay --- plugins/mm-modem-sierra-gsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mm-modem-sierra-gsm.c b/plugins/mm-modem-sierra-gsm.c index c2240908..3ed699ca 100644 --- a/plugins/mm-modem-sierra-gsm.c +++ b/plugins/mm-modem-sierra-gsm.c @@ -78,7 +78,7 @@ parent_enable_done (MMModem *modem, GError *error, gpointer user_data) return; } - /* Sierra returns OK on +CFUN=1 right away but needs some time + /* Some Sierra devices return OK on +CFUN=1 right away but need some time * to finish initialization. */ g_timeout_add_seconds (10, sierra_enabled, info); From c915de5512f69678d0062ceec4cc69fefcdf8fd3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 20:06:17 -0800 Subject: [PATCH 08/38] gsm: add ability for subclasses to handle power-on response This lets subclasses handle errors when they know the device supports the power-up command. Also will let us simplify a number of plugins. --- src/mm-generic-gsm.c | 28 +++++++++++++++++++--------- src/mm-generic-gsm.h | 11 +++++++++++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 28a3a4fa..eb1c6756 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -495,6 +495,16 @@ mm_generic_gsm_enable_complete (MMGenericGsm *modem, mm_callback_info_schedule (info); } +static void +real_do_enable_power_up_done (MMGenericGsm *self, + GString *response, + GError *error, + MMCallbackInfo *info) +{ + /* Ignore power-up errors as not all devices actually support CFUN=1 */ + mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), NULL, info); +} + static void enable_done (MMSerialPort *port, GString *response, @@ -503,16 +513,15 @@ enable_done (MMSerialPort *port, { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - /* Ignore power-up command errors, not all devices actually support - * CFUN=1. + /* Let subclasses handle the power up command response/error; many devices + * don't support +CFUN, but for those that do let them handle the error + * correctly. */ - /* FIXME: instead of just ignoring errors, since we allow subclasses - * to override the power-on command, make a class function for powering - * on the phone and let the subclass decided whether it wants to handle - * errors or ignore them. - */ - - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), NULL, info); + g_assert (MM_GENERIC_GSM_GET_CLASS (info->modem)->do_enable_power_up_done); + MM_GENERIC_GSM_GET_CLASS (info->modem)->do_enable_power_up_done (MM_GENERIC_GSM (info->modem), + response, + error, + info); } static void @@ -2396,6 +2405,7 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) object_class->finalize = finalize; klass->do_enable = real_do_enable; + klass->do_enable_power_up_done = real_do_enable_power_up_done; /* Properties */ g_object_class_override_property (object_class, diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 4f190f8b..7589cf98 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -65,6 +65,17 @@ typedef struct { * callback and user_data passed in here. */ void (*do_enable) (MMGenericGsm *self, MMModemFn callback, gpointer user_data); + + /* Called after the generic class has attempted to power up the modem. + * Subclasses can handle errors here if they know the device supports their + * power up command. Will only be called if the device does *not* override + * the MMModem enable() command or allows the generic class' do_enable() + * handler to execute. + */ + void (*do_enable_power_up_done) (MMGenericGsm *self, + GString *response, + GError *error, + MMCallbackInfo *info); } MMGenericGsmClass; GType mm_generic_gsm_get_type (void); From d94ca3d310f11d98589a76a3d864efe613f4d515 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 20:09:54 -0800 Subject: [PATCH 09/38] sierra: fix power-on delay Since the modem states patch the delay for power-on wasn't honored for Sierra devices. Fix that using the new power-on-done handler and also fix the bug where if the modem was removed, the plugin would crash because it wasn't handling the timeout removal. Also remove the explicit PIN check since that's now handled by the generic GSM code before the modem is even exported over DBus. --- plugins/mm-modem-sierra-gsm.c | 75 ++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/plugins/mm-modem-sierra-gsm.c b/plugins/mm-modem-sierra-gsm.c index 3ed699ca..ce4bca6d 100644 --- a/plugins/mm-modem-sierra-gsm.c +++ b/plugins/mm-modem-sierra-gsm.c @@ -27,6 +27,11 @@ static void modem_init (MMModem *modem_class); G_DEFINE_TYPE_EXTENDED (MMModemSierraGsm, mm_modem_sierra_gsm, MM_TYPE_GENERIC_GSM, 0, G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM, modem_init)) +#define MM_MODEM_SIERRA_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_SIERRA_GSM, MMModemSierraGsmPrivate)) + +typedef struct { + guint enable_wait_id; +} MMModemSierraGsmPrivate; MMModem * mm_modem_sierra_gsm_new (const char *device, @@ -48,51 +53,42 @@ mm_modem_sierra_gsm_new (const char *device, /* Modem class override functions */ /*****************************************************************************/ -static void -pin_check_done (MMModem *modem, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (modem), error, info); -} - static gboolean -sierra_enabled (gpointer data) +sierra_enabled (gpointer user_data) { - MMCallbackInfo *info = (MMCallbackInfo *) data; + MMCallbackInfo *info = user_data; + MMGenericGsm *modem; + MMModemSierraGsmPrivate *priv; - /* Now check the PIN explicitly, sierra doesn't seem to report - * that it needs it otherwise. - */ - mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), pin_check_done, info); + /* Make sure we don't use an invalid modem that may have been removed */ + if (info->modem) { + modem = MM_GENERIC_GSM (info->modem); + priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (modem); + priv->enable_wait_id = 0; + MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_enable_power_up_done (modem, NULL, NULL, info); + } return FALSE; } static void -parent_enable_done (MMModem *modem, GError *error, gpointer user_data) +real_do_enable_power_up_done (MMGenericGsm *gsm, + GString *response, + GError *error, + MMCallbackInfo *info) { - MMCallbackInfo *info = (MMCallbackInfo *) user_data; + MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (gsm); if (error) { - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (modem), error, info); + /* Chain up to parent */ + MM_GENERIC_GSM_CLASS (mm_modem_sierra_gsm_parent_class)->do_enable_power_up_done (gsm, NULL, error, info); return; } /* Some Sierra devices return OK on +CFUN=1 right away but need some time * to finish initialization. */ - g_timeout_add_seconds (10, sierra_enabled, info); -} - -static void -enable (MMModem *modem, MMModemFn callback, gpointer user_data) -{ - MMModem *parent_modem_iface; - MMCallbackInfo *info; - - info = mm_callback_info_new (modem, callback, user_data); - parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem)); - parent_modem_iface->enable (modem, parent_enable_done, info); + g_warn_if_fail (priv->enable_wait_id == 0); + priv->enable_wait_id = g_timeout_add_seconds (10, sierra_enabled, info); } static gboolean @@ -135,7 +131,6 @@ grab_port (MMModem *modem, static void modem_init (MMModem *modem_class) { - modem_class->enable = enable; modem_class->grab_port = grab_port; } @@ -145,8 +140,24 @@ mm_modem_sierra_gsm_init (MMModemSierraGsm *self) } static void -mm_modem_sierra_gsm_class_init (MMModemSierraGsmClass *klass) +dispose (GObject *object) { - mm_modem_sierra_gsm_parent_class = g_type_class_peek_parent (klass); + MMModemSierraGsmPrivate *priv = MM_MODEM_SIERRA_GSM_GET_PRIVATE (object); + + if (priv->enable_wait_id) + g_source_remove (priv->enable_wait_id); +} + +static void +mm_modem_sierra_gsm_class_init (MMModemSierraGsmClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass); + + mm_modem_sierra_gsm_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (object_class, sizeof (MMModemSierraGsmPrivate)); + + object_class->dispose = dispose; + gsm_class->do_enable_power_up_done = real_do_enable_power_up_done; } From a40d3dbead026db43b62d8e859b29f6e564d24f9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 20:27:44 -0800 Subject: [PATCH 10/38] option: fix power-on delay Since the modem states patch the delay for power-on wasn't honored for Option devices. Fix that using the new power-on-done handler and also fix the bug where if the modem was removed, the plugin would crash because it wasn't handling the timeout removal. Also remove the explicit PIN check since that's now handled by the generic GSM code before the modem is even exported over DBus. --- plugins/mm-modem-option.c | 88 ++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/plugins/mm-modem-option.c b/plugins/mm-modem-option.c index 2076ae66..273cb95a 100644 --- a/plugins/mm-modem-option.c +++ b/plugins/mm-modem-option.c @@ -22,13 +22,16 @@ #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); G_DEFINE_TYPE_EXTENDED (MMModemOption, mm_modem_option, 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)) +#define MM_MODEM_OPTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_OPTION, MMModemOptionPrivate)) + +typedef struct { + guint enable_wait_id; +} MMModemOptionPrivate; MMModem * mm_modem_option_new (const char *device, @@ -48,53 +51,42 @@ mm_modem_option_new (const char *device, /*****************************************************************************/ -static void -pin_check_done (MMModem *modem, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (modem), error, info); -} - static gboolean -option_enabled (gpointer data) +option_enabled (gpointer user_data) { - MMCallbackInfo *info = (MMCallbackInfo *) data; + MMCallbackInfo *info = user_data; + MMGenericGsm *modem; + MMModemOptionPrivate *priv; - /* Now check the PIN explicitly, option doesn't seem to report - * that it needs it otherwise. - */ - mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), pin_check_done, info); + /* Make sure we don't use an invalid modem that may have been removed */ + if (info->modem) { + modem = MM_GENERIC_GSM (info->modem); + priv = MM_MODEM_OPTION_GET_PRIVATE (modem); + priv->enable_wait_id = 0; + MM_GENERIC_GSM_CLASS (mm_modem_option_parent_class)->do_enable_power_up_done (modem, NULL, NULL, info); + } return FALSE; } static void -parent_enable_done (MMModem *modem, GError *error, gpointer user_data) +real_do_enable_power_up_done (MMGenericGsm *gsm, + GString *response, + GError *error, + MMCallbackInfo *info) { - MMCallbackInfo *info = (MMCallbackInfo *) user_data; + MMModemOptionPrivate *priv = MM_MODEM_OPTION_GET_PRIVATE (gsm); if (error) { - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (modem), error, info); + /* Chain up to parent */ + MM_GENERIC_GSM_CLASS (mm_modem_option_parent_class)->do_enable_power_up_done (gsm, NULL, error, info); return; } - /* Option returns OK on +CFUN=1 right away but needs some time - * to finish initialization + /* Some Option devices return OK on +CFUN=1 right away but need some time + * to finish initialization. */ - g_timeout_add_seconds (10, option_enabled, info); -} - -static void -enable (MMModem *modem, - MMModemFn callback, - gpointer user_data) -{ - MMModem *parent_modem_iface; - MMCallbackInfo *info; - - info = mm_callback_info_new (modem, callback, user_data); - parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (modem)); - parent_modem_iface->enable (modem, parent_enable_done, info); + g_warn_if_fail (priv->enable_wait_id == 0); + priv->enable_wait_id = g_timeout_add_seconds (10, option_enabled, info); } static void @@ -218,12 +210,6 @@ set_network_mode (MMModemGsmNetwork *modem, /*****************************************************************************/ -static void -modem_init (MMModem *modem_class) -{ - modem_class->enable = enable; -} - static void modem_gsm_network_init (MMModemGsmNetwork *class) { @@ -237,8 +223,24 @@ mm_modem_option_init (MMModemOption *self) } static void -mm_modem_option_class_init (MMModemOptionClass *klass) +dispose (GObject *object) { - mm_modem_option_parent_class = g_type_class_peek_parent (klass); + MMModemOptionPrivate *priv = MM_MODEM_OPTION_GET_PRIVATE (object); + + if (priv->enable_wait_id) + g_source_remove (priv->enable_wait_id); +} + +static void +mm_modem_option_class_init (MMModemOptionClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass); + + mm_modem_option_parent_class = g_type_class_peek_parent (klass); + g_type_class_add_private (object_class, sizeof (MMModemOptionPrivate)); + + object_class->dispose = dispose; + gsm_class->do_enable_power_up_done = real_do_enable_power_up_done; } From c02835722fda93e3f796d183b2994c89dc817baf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 20:37:36 -0800 Subject: [PATCH 11/38] novatel: remove PIN checking code This is handled by the generic class before the modem is even exported over D-Bus. --- plugins/mm-modem-novatel-gsm.c | 76 ---------------------------------- 1 file changed, 76 deletions(-) diff --git a/plugins/mm-modem-novatel-gsm.c b/plugins/mm-modem-novatel-gsm.c index 8189627d..4a846269 100644 --- a/plugins/mm-modem-novatel-gsm.c +++ b/plugins/mm-modem-novatel-gsm.c @@ -48,78 +48,6 @@ mm_modem_novatel_gsm_new (const char *device, /* Modem class override functions */ /*****************************************************************************/ -static void -init_modem_done (MMSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); -} - -static void -pin_check_done (MMModem *modem, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMGenericGsm *self = MM_GENERIC_GSM (modem); - MMSerialPort *primary; - - if (error) { - mm_generic_gsm_enable_complete (self, error, info); - return; - } - - /* Finish the initialization */ - primary = mm_generic_gsm_get_port (self, MM_PORT_TYPE_PRIMARY); - g_assert (primary); - mm_serial_port_queue_command (primary, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1", 10, init_modem_done, info); -} - -static void -pre_init_done (MMSerialPort *port, - GString *response, - GError *error, - gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - if (error) { - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); - return; - } - - /* Now check the PIN explicitly, novatel doesn't seem to report - * that it needs it otherwise. - */ - mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), pin_check_done, info); -} - -static void -enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = user_data; - - if (error) - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); - else - mm_serial_port_queue_command (port, "E0 V1", 3, pre_init_done, user_data); -} - -static void -do_enable (MMGenericGsm *modem, MMModemFn callback, gpointer user_data) -{ - MMCallbackInfo *info; - MMSerialPort *primary; - - primary = mm_generic_gsm_get_port (modem, MM_PORT_TYPE_PRIMARY); - g_assert (primary); - - info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - mm_serial_port_flash (primary, 100, enable_flash_done, info); -} - static void dmat_callback (MMSerialPort *port, GString *response, @@ -175,10 +103,6 @@ mm_modem_novatel_gsm_init (MMModemNovatelGsm *self) static void mm_modem_novatel_gsm_class_init (MMModemNovatelGsmClass *klass) { - MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass); - mm_modem_novatel_gsm_parent_class = g_type_class_peek_parent (klass); - - gsm_class->do_enable = do_enable; } From 6c760464d4545d5bedaef01dbbdd8fba5617aa26 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 20:43:22 -0800 Subject: [PATCH 12/38] zte: remove PIN checking code This is handled by the generic class before the modem is even exported over D-Bus. --- plugins/mm-modem-zte.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c index 6198a60b..4412fa22 100644 --- a/plugins/mm-modem-zte.c +++ b/plugins/mm-modem-zte.c @@ -118,23 +118,6 @@ init_modem_done (MMSerialPort *port, mm_serial_port_queue_command (port, "+CPMS?", 10, cpms_try_done, info); } -static void -pin_check_done (MMModem *modem, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMSerialPort *primary; - - if (error) { - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (modem), error, info); - return; - } - - /* Finish the initialization */ - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); - g_assert (primary); - mm_serial_port_queue_command (primary, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info); -} - static void enable_flash_done (MMSerialPort *port, GError *error, gpointer user_data); @@ -157,9 +140,8 @@ pre_init_done (MMSerialPort *port, } else mm_generic_gsm_enable_complete (MM_GENERIC_GSM (info->modem), error, info); } else { - /* Now check the PIN explicitly, zte doesn't seem to report - that it needs it otherwise */ - mm_generic_gsm_check_pin (MM_GENERIC_GSM (info->modem), pin_check_done, info); + /* Finish the initialization */ + mm_serial_port_queue_command (port, "Z E0 V1 X4 &C1 +CMEE=1;+CFUN=1;", 10, init_modem_done, info); } } From e6e3784c028f8d55bc9d2bd3fd207d958eba5ff4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 4 Mar 2010 20:45:30 -0800 Subject: [PATCH 13/38] hso: remove PIN checking code This is handled by the generic class before the modem is even exported over D-Bus. --- plugins/mm-modem-hso.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c index f1295e24..8bd42889 100644 --- a/plugins/mm-modem-hso.c +++ b/plugins/mm-modem-hso.c @@ -287,40 +287,6 @@ mm_hso_modem_authenticate (MMModemHso *self, /*****************************************************************************/ -static void -enable_done (MMModem *modem, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - - mm_generic_gsm_enable_complete (MM_GENERIC_GSM (modem), error, info); -} - -static void -parent_enable_done (MMModem *modem, GError *error, gpointer user_data) -{ - MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMGenericGsm *self = MM_GENERIC_GSM (modem); - - if (error) { - mm_generic_gsm_enable_complete (self, error, info); - return; - } - - /* HSO needs manual PIN checking */ - mm_generic_gsm_check_pin (self, enable_done, info); -} - -static void -enable (MMModem *modem, MMModemFn callback, gpointer user_data) -{ - MMModem *parent_modem_iface; - MMCallbackInfo *info; - - info = mm_callback_info_new (modem, callback, user_data); - parent_modem_iface = g_type_interface_peek_parent (MM_MODEM_GET_INTERFACE (info->modem)); - parent_modem_iface->enable (info->modem, parent_enable_done, info); -} - static void parent_disable_done (MMModem *modem, GError *error, gpointer user_data) { @@ -712,7 +678,6 @@ modem_simple_init (MMModemSimple *class) static void modem_init (MMModem *modem_class) { - modem_class->enable = enable; modem_class->disable = disable; modem_class->connect = do_connect; modem_class->get_ip4_config = get_ip4_config; From e4350152c86099e908921df64ba2e16f81ade5cb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Mar 2010 11:47:23 -0800 Subject: [PATCH 14/38] gsm: common CREG/CGREG parsing function and testcases --- src/mm-modem-helpers.c | 222 ++++++++++++++++++++++++ src/mm-modem-helpers.h | 11 ++ src/tests/test-modem-helpers.c | 298 +++++++++++++++++++++++++++++---- 3 files changed, 500 insertions(+), 31 deletions(-) diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index 1741b5f0..d909ce94 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "mm-errors.h" #include "mm-modem-helpers.h" @@ -201,3 +202,224 @@ mm_gsm_destroy_scan_data (gpointer data) g_ptr_array_free (results, TRUE); } +/*************************************************************************/ + +/* +CREG: (GSM 07.07 CREG=1 unsolicited) */ +#define CREG1 "\\+CG?REG:\\s*(\\d{1})" + +/* +CREG: , (GSM 07.07 CREG=1 solicited) */ +#define CREG2 "\\+CG?REG:\\s*(\\d{1}),\\s*(\\d{1})" + +/* +CREG: ,, (GSM 07.07 CREG=2 unsolicited) */ +#define CREG3 "\\+CG?REG:\\s*(\\d{1}),\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)" + +/* +CREG: ,,, (GSM 07.07 solicited and some CREG=2 unsolicited) */ +#define CREG4 "\\+CG?REG:\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)" + +/* +CREG: ,,, (ETSI 27.007 CREG=2 unsolicited) */ +#define CREG5 "\\+CG?REG:\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})" + +/* +CREG: ,,,, (ETSI 27.007 solicited and some CREG=2 unsolicited) */ +#define CREG6 "\\+CG?REG:\\s*(\\d{1}),\\s*(\\d{1})\\s*,\\s*([^,\\s]*)\\s*,\\s*([^,\\s]*)\\s*,\\s*(\\d{1,2})" + +GPtrArray * +mm_gsm_creg_regex_get (gboolean solicited) +{ + GPtrArray *array = g_ptr_array_sized_new (6); + GRegex *regex; + + /* #1 */ + if (solicited) + regex = g_regex_new (CREG1 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CREG1 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + /* #2 */ + if (solicited) + regex = g_regex_new (CREG2 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CREG2 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + /* #3 */ + if (solicited) + regex = g_regex_new (CREG3 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CREG3 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + /* #4 */ + if (solicited) + regex = g_regex_new (CREG4 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CREG4 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + /* #5 */ + if (solicited) + regex = g_regex_new (CREG5 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CREG5 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + /* #6 */ + if (solicited) + regex = g_regex_new (CREG6 "$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + else + regex = g_regex_new ("\\r\\n" CREG6 "\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + g_assert (regex); + g_ptr_array_add (array, regex); + + return array; +} + +void +mm_gsm_creg_regex_destroy (GPtrArray *array) +{ + g_ptr_array_foreach (array, (GFunc) g_regex_unref, NULL); + g_ptr_array_free (array, TRUE); +} + +/*************************************************************************/ + +static gulong +parse_uint (char *str, int base, glong nmin, glong nmax, gboolean *valid) +{ + gulong ret = 0; + char *endquote; + + *valid = FALSE; + if (!str) + return 0; + + /* Strip quotes */ + if (str[0] == '"') + str++; + endquote = strchr (str, '"'); + if (endquote) + *endquote = '\0'; + + if (strlen (str)) { + ret = strtol (str, NULL, base); + if ((nmin == nmax) || (ret >= nmin && ret <= nmax)) + *valid = TRUE; + } + return *valid ? (guint) ret : 0; +} + +gboolean +mm_gsm_parse_creg_response (GMatchInfo *info, + guint32 *out_reg_state, + gulong *out_lac, + gulong *out_ci, + gint *out_act, + GError **error) +{ + gboolean success = FALSE, foo; + gint n_matches, act = -1; + gulong stat = 0, lac = 0, ci = 0; + guint istat = 0, ilac = 0, ici = 0, iact = 0; + char *str; + + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (out_reg_state != NULL, FALSE); + g_return_val_if_fail (out_lac != NULL, FALSE); + g_return_val_if_fail (out_ci != NULL, FALSE); + g_return_val_if_fail (out_act != NULL, FALSE); + + /* Normally the number of matches could be used to determine what each + * item is, but we have overlap in one case. + */ + n_matches = g_match_info_get_match_count (info); + if (n_matches == 2) { + /* CREG=1: +CREG: */ + istat = 1; + } else if (n_matches == 3) { + /* Solicited response: +CREG: , */ + istat = 2; + } else if (n_matches == 4) { + /* CREG=2 (GSM 07.07): +CREG: ,, */ + istat = 1; + ilac = 2; + ici = 3; + } else if (n_matches == 5) { + /* CREG=2 (ETSI 27.007): +CREG: ,,, + * CREG=2 (non-standard): +CREG: ,,, + */ + + /* To distinguish, check length of the second match item. If it's + * more than one digit or has quotes in it, then we have the first format. + */ + str = g_match_info_fetch (info, 2); + if (str && (strchr (str, '"') || strlen (str) > 1)) { + g_free (str); + istat = 1; + ilac = 2; + ici = 3; + iact = 4; + } else { + istat = 2; + ilac = 3; + ici = 4; + } + } else if (n_matches == 6) { + /* CREG=2 (non-standard): +CREG: ,,,, */ + istat = 2; + ilac = 3; + ici = 4; + iact = 5; + } + + /* Status */ + str = g_match_info_fetch (info, istat); + stat = parse_uint (str, 10, 0, 5, &success); + g_free (str); + if (!success) { + g_set_error_literal (error, + MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Could not parse the registration status response"); + return FALSE; + } + + /* Location Area Code */ + if (ilac) { + /* FIXME: some phones apparently swap the LAC bytes (LG, SonyEricsson, + * Sagem). Need to handle that. + */ + str = g_match_info_fetch (info, ilac); + lac = parse_uint (str, 16, 1, 0xFFFF, &foo); + g_free (str); + } + + /* Cell ID */ + if (ici) { + str = g_match_info_fetch (info, ici); + ci = parse_uint (str, 16, 1, 0x0FFFFFFE, &foo); + g_free (str); + } + + /* Access Technology */ + if (iact) { + str = g_match_info_fetch (info, iact); + act = (gint) parse_uint (str, 10, 0, 7, &foo); + g_free (str); + if (!foo) + act = -1; + } + + *out_reg_state = (guint32) stat; + if (stat != 4) { + /* Don't fill in lac/ci/act if the device's state is unknown */ + *out_lac = lac; + *out_ci = ci; + *out_act = act; + } + return TRUE; +} + diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index ddc9cbce..f9582e24 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -27,5 +27,16 @@ GPtrArray *mm_gsm_parse_scan_response (const char *reply, GError **error); void mm_gsm_destroy_scan_data (gpointer data); +GPtrArray *mm_gsm_creg_regex_get (gboolean solicited); + +void mm_gsm_creg_regex_destroy (GPtrArray *array); + +gboolean mm_gsm_parse_creg_response (GMatchInfo *info, + guint32 *out_reg_state, + gulong *out_lac, + gulong *out_ci, + gint *out_act, + GError **error); + #endif /* MM_MODEM_HELPERS_H */ diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index f5b4b6a8..bc578e77 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -18,6 +18,11 @@ #include "mm-modem-helpers.h" +typedef struct { + GPtrArray *solicited_creg; + GPtrArray *unsolicited_creg; +} TestData; + #define MM_SCAN_TAG_STATUS "status" #define MM_SCAN_TAG_OPER_LONG "operator-long" #define MM_SCAN_TAG_OPER_SHORT "operator-short" @@ -35,10 +40,10 @@ typedef struct { #define ARRAY_LEN(i) (sizeof (i) / sizeof (i[0])) static void -test_results (const char *desc, - const char *reply, - OperEntry *expected_results, - guint32 expected_results_len) +test_cops_results (const char *desc, + const char *reply, + OperEntry *expected_results, + guint32 expected_results_len) { guint i; GError *error = NULL; @@ -101,7 +106,7 @@ test_cops_response_tm506 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" } }; - test_results ("TM-506", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("TM-506", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -113,7 +118,7 @@ test_cops_response_gt3gplus (void *f, gpointer d) { "1", "Cingular", "Cingular", "310410", "0" }, }; - test_results ("GlobeTrotter 3G+ (nozomi)", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("GlobeTrotter 3G+ (nozomi)", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -126,7 +131,7 @@ test_cops_response_ac881 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Sierra AirCard 881", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Sierra AirCard 881", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -139,7 +144,7 @@ test_cops_response_gtmax36 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Option GlobeTrotter MAX 3.6", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Option GlobeTrotter MAX 3.6", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -152,7 +157,7 @@ test_cops_response_ac860 (void *f, gpointer d) { "1", "Cingular", "Cinglr", "310410", "0" }, }; - test_results ("Sierra AirCard 860", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Sierra AirCard 860", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -165,7 +170,7 @@ test_cops_response_gtm378 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Option GTM378", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Option GTM378", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -177,7 +182,7 @@ test_cops_response_motoc (void *f, gpointer d) { "0", "Cingular Wireless", NULL, "310410", NULL }, }; - test_results ("BUSlink SCWi275u (Motorola C-series)", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("BUSlink SCWi275u (Motorola C-series)", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -189,7 +194,7 @@ test_cops_response_mf627a (void *f, gpointer d) { "3", "Voicestream Wireless Corporation", "VSTREAM", "31026", "0" }, }; - test_results ("ZTE MF627 (A)", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("ZTE MF627 (A)", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -201,7 +206,7 @@ test_cops_response_mf627b (void *f, gpointer d) { "3", NULL, NULL, "31026", "0" }, }; - test_results ("ZTE MF627 (B)", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("ZTE MF627 (B)", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -213,7 +218,7 @@ test_cops_response_e160g (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Huawei E160G", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Huawei E160G", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -226,7 +231,7 @@ test_cops_response_mercury (void *f, gpointer d) { "1", "T-Mobile", "TMO", "31026", "0" }, }; - test_results ("Sierra AT&T USBConnect Mercury", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Sierra AT&T USBConnect Mercury", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -239,7 +244,7 @@ test_cops_response_quicksilver (void *f, gpointer d) { "1", "AT&T", NULL, "310260", "0" }, }; - test_results ("Option AT&T Quicksilver", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Option AT&T Quicksilver", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -251,7 +256,7 @@ test_cops_response_icon225 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Option iCON 225", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Option iCON 225", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -265,7 +270,7 @@ test_cops_response_icon452 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" } }; - test_results ("Option iCON 452", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Option iCON 452", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -278,7 +283,7 @@ test_cops_response_f3507g (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "2" } }; - test_results ("Ericsson F3507g", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Ericsson F3507g", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -291,7 +296,7 @@ test_cops_response_f3607gw (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" } }; - test_results ("Ericsson F3607gw", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Ericsson F3607gw", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -304,7 +309,7 @@ test_cops_response_mc8775 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" } }; - test_results ("Sierra MC8775", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Sierra MC8775", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -317,7 +322,7 @@ test_cops_response_n80 (void *f, gpointer d) { "1", "Cingular", NULL, "31041", NULL }, }; - test_results ("Nokia N80", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Nokia N80", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -329,7 +334,7 @@ test_cops_response_e1550 (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Huawei E1550", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Huawei E1550", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -341,7 +346,7 @@ test_cops_response_mf622 (void *f, gpointer d) { "1", NULL, NULL, "310410", "0" }, }; - test_results ("ZTE MF622", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("ZTE MF622", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -354,7 +359,7 @@ test_cops_response_e226 (void *f, gpointer d) { "1", NULL, NULL, "310410", "0" }, }; - test_results ("Huawei E226", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Huawei E226", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -367,7 +372,7 @@ test_cops_response_xu870 (void *f, gpointer d) { "1", "T-Mobile", "TMO", "31026", "0" }, }; - test_results ("Novatel XU870", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Novatel XU870", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -380,7 +385,7 @@ test_cops_response_gtultraexpress (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Option GlobeTrotter Ultra Express", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Option GlobeTrotter Ultra Express", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -392,7 +397,7 @@ test_cops_response_n2720 (void *f, gpointer d) { "1", "AT&T", NULL, "310410", "0" }, }; - test_results ("Nokia 2720", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Nokia 2720", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -405,7 +410,7 @@ test_cops_response_gobi (void *f, gpointer d) { "1", "AT&T", "AT&T", "310410", "0" }, }; - test_results ("Qualcomm Gobi", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Qualcomm Gobi", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -426,7 +431,7 @@ test_cops_response_sek600i (void *f, gpointer d) { "3", NULL, NULL, "26207", NULL }, }; - test_results ("Sony-Ericsson K600i", reply, &expected[0], ARRAY_LEN (expected)); + test_cops_results ("Sony-Ericsson K600i", reply, &expected[0], ARRAY_LEN (expected)); } static void @@ -453,6 +458,216 @@ test_cops_response_umts_invalid (void *f, gpointer d) g_assert (error == NULL); } +typedef struct { + guint32 state; + gulong lac; + gulong ci; + gint act; + + guint regex_num; +} CregResult; + +static void +test_creg_match (const char *test, + gboolean solicited, + const char *reply, + TestData *data, + const CregResult *result) +{ + int i; + GMatchInfo *info = NULL; + guint32 state = 0; + gulong lac = 0, ci = 0; + gint access_tech = -1; + GError *error = NULL; + gboolean success; + guint regex_num = 0; + GPtrArray *array; + + g_assert (reply); + g_assert (test); + g_assert (data); + g_assert (result); + + g_print ("\nTesting %s +CREG %s response...\n", + test, + solicited ? "solicited" : "unsolicited"); + + array = solicited ? data->solicited_creg : data->unsolicited_creg; + for (i = 0; i < array->len; i++) { + GRegex *r = g_ptr_array_index (array, i); + + if (g_regex_match (r, reply, 0, &info)) { + regex_num = i + 1; + break; + } + g_match_info_free (info); + info = NULL; + } + + g_assert (info != NULL); + g_assert (regex_num == result->regex_num); + + success = mm_gsm_parse_creg_response (info, &state, &lac, &ci, &access_tech, &error); + g_assert (success); + g_assert (error == NULL); + g_assert (state == result->state); + g_assert (lac == result->lac); + g_assert (ci == result->ci); + g_assert (access_tech == result->act); +} + +static void +test_creg1_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CREG: 1,3"; + const CregResult result = { 3, 0, 0, -1 , 2}; + + test_creg_match ("CREG=1", TRUE, reply, data, &result); +} + +static void +test_creg1_unsolicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CREG: 3\r\n"; + const CregResult result = { 3, 0, 0, -1 , 1}; + + test_creg_match ("CREG=1", FALSE, reply, data, &result); +} + +static void +test_creg2_mercury_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CREG: 0,1,84CD,00D30173"; + const CregResult result = { 1, 0x84cd, 0xd30173, -1 , 4}; + + test_creg_match ("Sierra Mercury CREG=2", TRUE, reply, data, &result); +} + +static void +test_creg2_mercury_unsolicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CREG: 1,84CD,00D30156\r\n"; + const CregResult result = { 1, 0x84cd, 0xd30156, -1 , 3}; + + test_creg_match ("Sierra Mercury CREG=2", FALSE, reply, data, &result); +} + +static void +test_creg2_sek850i_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CREG: 2,1,\"CE00\",\"01CEAD8F\""; + const CregResult result = { 1, 0xce00, 0x01cead8f, -1 , 4}; + + test_creg_match ("Sony Ericsson K850i CREG=2", TRUE, reply, data, &result); +} + +static void +test_creg2_sek850i_unsolicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CREG: 1,\"CE00\",\"00005449\"\r\n"; + const CregResult result = { 1, 0xce00, 0x5449, -1 , 3}; + + test_creg_match ("Sony Ericsson K850i CREG=2", FALSE, reply, data, &result); +} + +static void +test_creg2_e160g_solicited_unregistered (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CREG: 2,0,00,0"; + const CregResult result = { 0, 0, 0, -1 , 4}; + + test_creg_match ("Huawei E160G unregistered CREG=2", TRUE, reply, data, &result); +} + +static void +test_creg2_e160g_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CREG: 2,1,8BE3,2BAF"; + const CregResult result = { 1, 0x8be3, 0x2baf, -1 , 4}; + + test_creg_match ("Huawei E160G CREG=2", TRUE, reply, data, &result); +} + +static void +test_creg2_e160g_unsolicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CREG: 2,8BE3,2BAF\r\n"; + const CregResult result = { 2, 0x8be3, 0x2baf, -1 , 3}; + + test_creg_match ("Huawei E160G CREG=2", FALSE, reply, data, &result); +} + +static void +test_creg2_tm506_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CREG: 2,1,\"8BE3\",\"00002BAF\""; + const CregResult result = { 1, 0x8BE3, 0x2BAF, -1 , 4}; + + /* Test leading zeros in the CI */ + test_creg_match ("Sony Ericsson TM-506 CREG=2", TRUE, reply, data, &result); +} + +static void +test_creg2_xu870_unsolicited_unregistered (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CREG: 2,,\r\n"; + const CregResult result = { 2, 0, 0, -1 , 3}; + + test_creg_match ("Novatel XU870 unregistered CREG=2", FALSE, reply, data, &result); +} + +static void +test_cgreg2_f3607gw_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CGREG: 2,1,\"8BE3\",\"00002B5D\",3"; + const CregResult result = { 1, 0x8BE3, 0x2B5D, 3 , 6}; + + test_creg_match ("Ericsson F3607gw CGREG=2", TRUE, reply, data, &result); +} + +static void +test_cgreg2_f3607gw_unsolicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CGREG: 1,\"8BE3\",\"00002B5D\",3\r\n"; + const CregResult result = { 1, 0x8BE3, 0x2B5D, 3 , 5}; + + test_creg_match ("Ericsson F3607gw CGREG=2", FALSE, reply, data, &result); +} + + +static TestData * +test_data_new (void) +{ + TestData *data; + + data = g_malloc0 (sizeof (TestData)); + data->solicited_creg = mm_gsm_creg_regex_get (TRUE); + data->unsolicited_creg = mm_gsm_creg_regex_get (FALSE); + return data; +} + +static void +test_data_free (TestData *data) +{ + mm_gsm_creg_regex_destroy (data->solicited_creg); + mm_gsm_creg_regex_destroy (data->unsolicited_creg); + g_free (data); +} + typedef void (*TCFunc)(void); @@ -461,10 +676,13 @@ typedef void (*TCFunc)(void); int main (int argc, char **argv) { GTestSuite *suite; + TestData *data; + gint result; g_test_init (&argc, &argv, NULL); suite = g_test_get_root (); + data = test_data_new (); g_test_suite_add (suite, TESTCASE (test_cops_response_tm506, NULL)); g_test_suite_add (suite, TESTCASE (test_cops_response_gt3gplus, NULL)); @@ -496,6 +714,24 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_cops_response_gsm_invalid, NULL)); g_test_suite_add (suite, TESTCASE (test_cops_response_umts_invalid, NULL)); - return g_test_run (); + g_test_suite_add (suite, TESTCASE (test_creg1_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg1_unsolicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_mercury_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_mercury_unsolicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_sek850i_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_sek850i_unsolicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_e160g_solicited_unregistered, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_e160g_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_e160g_unsolicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_tm506_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_creg2_xu870_unsolicited_unregistered, data)); + g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_unsolicited, data)); + + result = g_test_run (); + + test_data_free (data); + + return result; } From ad7bbb2f160d52ff581c334ac85c29d10b3e4451 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Mar 2010 14:08:40 -0800 Subject: [PATCH 15/38] gsm: indicate CREG vs. CGREG --- src/mm-modem-helpers.c | 6 ++++ src/mm-modem-helpers.h | 1 + src/tests/test-modem-helpers.c | 55 ++++++++++++++++++++++++---------- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index d909ce94..56834d6d 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -319,6 +319,7 @@ mm_gsm_parse_creg_response (GMatchInfo *info, gulong *out_lac, gulong *out_ci, gint *out_act, + gboolean *out_greg, GError **error) { gboolean success = FALSE, foo; @@ -326,12 +327,14 @@ mm_gsm_parse_creg_response (GMatchInfo *info, gulong stat = 0, lac = 0, ci = 0; guint istat = 0, ilac = 0, ici = 0, iact = 0; char *str; + const char *orig_str; g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (out_reg_state != NULL, FALSE); g_return_val_if_fail (out_lac != NULL, FALSE); g_return_val_if_fail (out_ci != NULL, FALSE); g_return_val_if_fail (out_act != NULL, FALSE); + g_return_val_if_fail (out_greg != NULL, FALSE); /* Normally the number of matches could be used to determine what each * item is, but we have overlap in one case. @@ -413,6 +416,9 @@ mm_gsm_parse_creg_response (GMatchInfo *info, act = -1; } + orig_str = g_match_info_get_string (info); + *out_greg = !!strstr (orig_str, "+CGREG"); + *out_reg_state = (guint32) stat; if (stat != 4) { /* Don't fill in lac/ci/act if the device's state is unknown */ diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index f9582e24..57956766 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -36,6 +36,7 @@ gboolean mm_gsm_parse_creg_response (GMatchInfo *info, gulong *out_lac, gulong *out_ci, gint *out_act, + gboolean *out_greg, GError **error); #endif /* MM_MODEM_HELPERS_H */ diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index bc578e77..980c4ae7 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -465,6 +465,7 @@ typedef struct { gint act; guint regex_num; + gboolean cgreg; } CregResult; static void @@ -480,7 +481,7 @@ test_creg_match (const char *test, gulong lac = 0, ci = 0; gint access_tech = -1; GError *error = NULL; - gboolean success; + gboolean success, cgreg = FALSE; guint regex_num = 0; GPtrArray *array; @@ -508,13 +509,14 @@ test_creg_match (const char *test, g_assert (info != NULL); g_assert (regex_num == result->regex_num); - success = mm_gsm_parse_creg_response (info, &state, &lac, &ci, &access_tech, &error); + success = mm_gsm_parse_creg_response (info, &state, &lac, &ci, &access_tech, &cgreg, &error); g_assert (success); g_assert (error == NULL); g_assert (state == result->state); g_assert (lac == result->lac); g_assert (ci == result->ci); g_assert (access_tech == result->act); + g_assert (cgreg == result->cgreg); } static void @@ -522,7 +524,7 @@ test_creg1_solicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CREG: 1,3"; - const CregResult result = { 3, 0, 0, -1 , 2}; + const CregResult result = { 3, 0, 0, -1 , 2, FALSE}; test_creg_match ("CREG=1", TRUE, reply, data, &result); } @@ -532,7 +534,7 @@ test_creg1_unsolicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "\r\n+CREG: 3\r\n"; - const CregResult result = { 3, 0, 0, -1 , 1}; + const CregResult result = { 3, 0, 0, -1 , 1, FALSE}; test_creg_match ("CREG=1", FALSE, reply, data, &result); } @@ -542,7 +544,7 @@ test_creg2_mercury_solicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CREG: 0,1,84CD,00D30173"; - const CregResult result = { 1, 0x84cd, 0xd30173, -1 , 4}; + const CregResult result = { 1, 0x84cd, 0xd30173, -1 , 4, FALSE}; test_creg_match ("Sierra Mercury CREG=2", TRUE, reply, data, &result); } @@ -552,7 +554,7 @@ test_creg2_mercury_unsolicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "\r\n+CREG: 1,84CD,00D30156\r\n"; - const CregResult result = { 1, 0x84cd, 0xd30156, -1 , 3}; + const CregResult result = { 1, 0x84cd, 0xd30156, -1 , 3, FALSE}; test_creg_match ("Sierra Mercury CREG=2", FALSE, reply, data, &result); } @@ -562,7 +564,7 @@ test_creg2_sek850i_solicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CREG: 2,1,\"CE00\",\"01CEAD8F\""; - const CregResult result = { 1, 0xce00, 0x01cead8f, -1 , 4}; + const CregResult result = { 1, 0xce00, 0x01cead8f, -1 , 4, FALSE}; test_creg_match ("Sony Ericsson K850i CREG=2", TRUE, reply, data, &result); } @@ -572,7 +574,7 @@ test_creg2_sek850i_unsolicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "\r\n+CREG: 1,\"CE00\",\"00005449\"\r\n"; - const CregResult result = { 1, 0xce00, 0x5449, -1 , 3}; + const CregResult result = { 1, 0xce00, 0x5449, -1 , 3, FALSE}; test_creg_match ("Sony Ericsson K850i CREG=2", FALSE, reply, data, &result); } @@ -582,7 +584,7 @@ test_creg2_e160g_solicited_unregistered (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CREG: 2,0,00,0"; - const CregResult result = { 0, 0, 0, -1 , 4}; + const CregResult result = { 0, 0, 0, -1 , 4, FALSE}; test_creg_match ("Huawei E160G unregistered CREG=2", TRUE, reply, data, &result); } @@ -592,7 +594,7 @@ test_creg2_e160g_solicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CREG: 2,1,8BE3,2BAF"; - const CregResult result = { 1, 0x8be3, 0x2baf, -1 , 4}; + const CregResult result = { 1, 0x8be3, 0x2baf, -1 , 4, FALSE}; test_creg_match ("Huawei E160G CREG=2", TRUE, reply, data, &result); } @@ -602,7 +604,7 @@ test_creg2_e160g_unsolicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "\r\n+CREG: 2,8BE3,2BAF\r\n"; - const CregResult result = { 2, 0x8be3, 0x2baf, -1 , 3}; + const CregResult result = { 2, 0x8be3, 0x2baf, -1 , 3, FALSE}; test_creg_match ("Huawei E160G CREG=2", FALSE, reply, data, &result); } @@ -612,7 +614,7 @@ test_creg2_tm506_solicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CREG: 2,1,\"8BE3\",\"00002BAF\""; - const CregResult result = { 1, 0x8BE3, 0x2BAF, -1 , 4}; + const CregResult result = { 1, 0x8BE3, 0x2BAF, -1 , 4, FALSE}; /* Test leading zeros in the CI */ test_creg_match ("Sony Ericsson TM-506 CREG=2", TRUE, reply, data, &result); @@ -623,17 +625,37 @@ test_creg2_xu870_unsolicited_unregistered (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "\r\n+CREG: 2,,\r\n"; - const CregResult result = { 2, 0, 0, -1 , 3}; + const CregResult result = { 2, 0, 0, -1 , 3, FALSE}; test_creg_match ("Novatel XU870 unregistered CREG=2", FALSE, reply, data, &result); } +static void +test_cgreg1_solicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "+CGREG: 1,3"; + const CregResult result = { 3, 0, 0, -1 , 2, TRUE}; + + test_creg_match ("CGREG=1", TRUE, reply, data, &result); +} + +static void +test_cgreg1_unsolicited (void *f, gpointer d) +{ + TestData *data = (TestData *) d; + const char *reply = "\r\n+CGREG: 3\r\n"; + const CregResult result = { 3, 0, 0, -1 , 1, TRUE}; + + test_creg_match ("CGREG=1", FALSE, reply, data, &result); +} + static void test_cgreg2_f3607gw_solicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "+CGREG: 2,1,\"8BE3\",\"00002B5D\",3"; - const CregResult result = { 1, 0x8BE3, 0x2B5D, 3 , 6}; + const CregResult result = { 1, 0x8BE3, 0x2B5D, 3 , 6, TRUE}; test_creg_match ("Ericsson F3607gw CGREG=2", TRUE, reply, data, &result); } @@ -643,7 +665,7 @@ test_cgreg2_f3607gw_unsolicited (void *f, gpointer d) { TestData *data = (TestData *) d; const char *reply = "\r\n+CGREG: 1,\"8BE3\",\"00002B5D\",3\r\n"; - const CregResult result = { 1, 0x8BE3, 0x2B5D, 3 , 5}; + const CregResult result = { 1, 0x8BE3, 0x2B5D, 3 , 5, TRUE}; test_creg_match ("Ericsson F3607gw CGREG=2", FALSE, reply, data, &result); } @@ -725,6 +747,9 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_creg2_e160g_unsolicited, data)); g_test_suite_add (suite, TESTCASE (test_creg2_tm506_solicited, data)); g_test_suite_add (suite, TESTCASE (test_creg2_xu870_unsolicited_unregistered, data)); + + g_test_suite_add (suite, TESTCASE (test_cgreg1_solicited, data)); + g_test_suite_add (suite, TESTCASE (test_cgreg1_unsolicited, data)); g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_solicited, data)); g_test_suite_add (suite, TESTCASE (test_cgreg2_f3607gw_unsolicited, data)); From 12a8a63fc1510d1af79581dc66e2b48a8eefcdb6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Mar 2010 17:52:55 -0800 Subject: [PATCH 16/38] api: first draft of Location information API NOT FINAL; need to discuss with Pablo and others and actually implement it before declaring it final. --- introspection/Makefile.am | 3 +- introspection/all.xml | 1 + introspection/mm-modem-location.xml | 70 +++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 introspection/mm-modem-location.xml diff --git a/introspection/Makefile.am b/introspection/Makefile.am index 404c1d93..175162cc 100644 --- a/introspection/Makefile.am +++ b/introspection/Makefile.am @@ -13,4 +13,5 @@ EXTRA_DIST = \ mm-modem-gsm-network.xml \ mm-modem-gsm-sms.xml \ mm-modem-simple.xml \ - mm-serial-error.xml + mm-serial-error.xml \ + mm-modem-location.xml diff --git a/introspection/all.xml b/introspection/all.xml index 426baf0e..30725c73 100644 --- a/introspection/all.xml +++ b/introspection/all.xml @@ -25,6 +25,7 @@ + diff --git a/introspection/mm-modem-location.xml b/introspection/mm-modem-location.xml new file mode 100644 index 00000000..ccd1e3a4 --- /dev/null +++ b/introspection/mm-modem-location.xml @@ -0,0 +1,70 @@ + + + + + + + + Location capabilities of the device. + + + + + + TRUE if location information gathering is enabled for this device, FALSE if it is disabled. When disabled, the device will not provide location information. + + + + + + Enable or disable location information gathering. When enabled, *all* clients can retrieve location information unless restricted through D-Bus service permissions; this could allow malicious applications to track your location so use this functionality carefully. + + + + + + TRUE to enable location information gathering, FALSE to disable. + + + + + + + Dict of available location information when location information gathering is enabled. If the modem supports multiple location types it may return more than one here. + + + + + + A mapping from unsigned integers to a variant representing location information. + + + + Identifies the type and format of the associated location information. Contrary to the value description, this is not a bitfield but uses the same values as the MM_MODEM_LOCATION_CAPABILITIES bitfield. + + + + + Contains type-specific location information. GSM_LAC_CI data is a string with the format "LAC,CI" (ex "84CD,00D30156") while GPS_NMEA is a string in NMEA-compatible format. + + + + + + + Unknown or no capabilties. + + + Reserved. + + + The device is capable of providing GPS NMEA-format location information. + + + The device is capable of providing GSM Location Area Code/Cell ID location information. + + + + + + From 2950f3106859fb8bb90f6eab8a8de5298fd5d297 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Mar 2010 17:55:48 -0800 Subject: [PATCH 17/38] api: clarify some Location API bits --- introspection/mm-modem-location.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/introspection/mm-modem-location.xml b/introspection/mm-modem-location.xml index ccd1e3a4..5ec62df1 100644 --- a/introspection/mm-modem-location.xml +++ b/introspection/mm-modem-location.xml @@ -36,7 +36,7 @@ - A mapping from unsigned integers to a variant representing location information. + A mapping from location type to type-specific location information. From 3232a3f7d6d01400c4ed9acb6692fa119b7720b2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 5 Mar 2010 18:17:51 -0800 Subject: [PATCH 18/38] api: better handling of Location API security issues Since D-Bus signals cannot by nature be restricted to authenticated clients (unless using private D-Bus connections) we can handle the security a bit differently here. Since the Enable() call can be authenticated, we'll trust the client to say whether higher security should be used by disallowing location update signals. This does mean the client will have to poll for location updates, but at least then clients requesting location information can be authenticated. --- introspection/mm-modem-location.xml | 58 +++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/introspection/mm-modem-location.xml b/introspection/mm-modem-location.xml index 5ec62df1..dfcf9dee 100644 --- a/introspection/mm-modem-location.xml +++ b/introspection/mm-modem-location.xml @@ -2,6 +2,12 @@ + + This interface allows devices to provide location information to client + applications. Not all devices can provide this information, or even if + they do, they may not be able to provide it while a data session is + active. + @@ -11,13 +17,16 @@ - TRUE if location information gathering is enabled for this device, FALSE if it is disabled. When disabled, the device will not provide location information. + TRUE if location information gathering is enabled for this device, FALSE + if it is disabled. When disabled, the device will not provide location + information. - Enable or disable location information gathering. When enabled, *all* clients can retrieve location information unless restricted through D-Bus service permissions; this could allow malicious applications to track your location so use this functionality carefully. + Enable or disable location information gathering. This method may + require the client to authenticate itself. @@ -26,11 +35,54 @@ TRUE to enable location information gathering, FALSE to disable. + + + When enabling location information gathering, this argument controls + whether the device emits signals with new location information or not. + When signals are emitted, any client application (including malicious + ones!) can listen for location updates unless D-Bus permissions + restrict these signals from certain users. If further security is + desired, this argument can be set to FALSE to disable location + updates via D-Bus signals and require applications to call + authenticated APIs (like GetLocation) to get location information. + This argument is ignored when disabling location information + gathering. + + + + + Return current location information, if any. This method may require + the client to authenticate itself. + + + + + + Dict of available location information when location information + gathering is enabled. If the modem supports multiple location types + it may return more than one here. + + + + + + + TRUE if location updates will be emitted via D-Bus signals, FALSE + if location updates will not be emitted. See the Enable method for + more information. + + + - Dict of available location information when location information gathering is enabled. If the modem supports multiple location types it may return more than one here. + Dict of available location information when location information + gathering is enabled. If the modem supports multiple location types + it may return more than one here. Note that if the device was told + not to emit updated location information when location information + gathering was initially enabled, this property may not return + any location information for security reasons. From 31fb97919cd7d95d1f9b23bd0c2428d8a19dc3e4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 6 Mar 2010 00:26:54 -0800 Subject: [PATCH 19/38] gsm: fix simple state machine network registration after 407abc65c6ccd802ce8456e5a63e68fab1c7d0a1 Got the logic wrong in that commit. Fix it. Network registration should always be run since it handles polling for registration state if needed before continuing. --- src/mm-generic-gsm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index eb1c6756..84d4136c 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -2081,12 +2081,10 @@ simple_state_machine (MMModem *modem, GError *error, gpointer user_data) case SIMPLE_STATE_REGISTER: next_state = SIMPLE_STATE_SET_APN; str = simple_get_string_property (info, "network_id", &info->error); - if (str || info->error) { - if (str) - mm_modem_gsm_network_register (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info); - break; - } - /* Fall through if no explicit network registration is required */ + if (info->error) + str = NULL; + mm_modem_gsm_network_register (MM_MODEM_GSM_NETWORK (modem), str, simple_state_machine, info); + break; case SIMPLE_STATE_SET_APN: next_state = SIMPLE_STATE_CONNECT; str = simple_get_string_property (info, "apn", &info->error); From 54c1d069eb688f60cc721fb435953dfaebcfa6d7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 6 Mar 2010 10:28:11 -0800 Subject: [PATCH 20/38] gsm: rework registration handling First, generically handle registration polling if the device does not support unsolicited registration. Second, using the new creg/cgreg parsing functions from mm-modem-helpers.c, handle CREG=2 unsolicited registration replies to capture the GSM LAC/CI for the location information API. Because of these changes we can simplify the registration polling during connection as well by using the common registration parsing code and the cached registration state. --- plugins/mm-modem-hso.c | 2 - plugins/mm-modem-huawei-gsm.c | 2 - plugins/mm-modem-mbm.c | 2 - plugins/mm-modem-zte.c | 1 - src/mm-generic-gsm.c | 428 ++++++++++++++++++++++++++-------- src/mm-generic-gsm.h | 5 +- 6 files changed, 334 insertions(+), 106 deletions(-) diff --git a/plugins/mm-modem-hso.c b/plugins/mm-modem-hso.c index 8bd42889..a3fb95c4 100644 --- a/plugins/mm-modem-hso.c +++ b/plugins/mm-modem-hso.c @@ -647,8 +647,6 @@ grab_port (MMModem *modem, if (ptype == MM_PORT_TYPE_PRIMARY) { GRegex *regex; - mm_generic_gsm_set_unsolicited_registration (gsm, TRUE); - regex = g_regex_new ("_OWANCALL: (\\d),\\s*(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, connection_enabled, modem, NULL); g_regex_unref (regex); diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index d450f258..76a2d76b 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -560,8 +560,6 @@ grab_port (MMModem *modem, if (ptype == MM_PORT_TYPE_SECONDARY) { GRegex *regex; - mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (modem), TRUE); - regex = g_regex_new ("\\r\\n\\^RSSI:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_signal_quality_change, modem, NULL); g_regex_unref (regex); diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index eb98990c..417457f7 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -747,8 +747,6 @@ grab_port (MMModem *modem, if (port && MM_IS_SERIAL_PORT (port) && (ptype == MM_PORT_TYPE_PRIMARY)) { GRegex *regex; - mm_generic_gsm_set_unsolicited_registration (MM_GENERIC_GSM (modem), TRUE); - regex = g_regex_new ("\\r\\n\\*EMRDY: \\d\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, mbm_emrdy_received, modem, NULL); g_regex_unref (regex); diff --git a/plugins/mm-modem-zte.c b/plugins/mm-modem-zte.c index 4412fa22..663a728e 100644 --- a/plugins/mm-modem-zte.c +++ b/plugins/mm-modem-zte.c @@ -211,7 +211,6 @@ grab_port (MMModem *modem, if (port && MM_IS_SERIAL_PORT (port)) { GRegex *regex; - mm_generic_gsm_set_unsolicited_registration (gsm, TRUE); g_object_set (port, MM_PORT_CARRIER_DETECT, FALSE, NULL); regex = g_regex_new ("\\r\\n\\+ZUSIMR:(.*)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 84d4136c..37ad5a9e 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -28,6 +28,7 @@ #include "mm-callback-info.h" #include "mm-serial-parsers.h" #include "mm-modem-helpers.h" +#include "mm-options.h" static void modem_init (MMModem *modem_class); static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); @@ -57,7 +58,16 @@ typedef struct { char *oper_code; char *oper_name; guint32 ip_method; - gboolean unsolicited_registration; + + GPtrArray *reg_regex; + + /* CREG and CGREG info */ + guint reg_poll_id; + guint greg_poll_id; + /* Index 0 for CREG, index 1 for CGREG */ + gulong lac[2]; + gulong cell_id[2]; + gint access_tech[2]; MMModemGsmNetworkRegStatus reg_status; guint pending_reg_id; @@ -86,6 +96,15 @@ static void reg_state_changed (MMSerialPort *port, GMatchInfo *match_info, gpointer user_data); +static void get_reg_status_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data); + +static gboolean handle_reg_status_response (MMGenericGsm *self, + GString *response, + GError **error); + MMModem * mm_generic_gsm_new (const char *device, const char *driver, @@ -102,15 +121,6 @@ mm_generic_gsm_new (const char *device, NULL)); } -void -mm_generic_gsm_set_unsolicited_registration (MMGenericGsm *modem, - gboolean enabled) -{ - g_return_if_fail (MM_IS_GENERIC_GSM (modem)); - - MM_GENERIC_GSM_GET_PRIVATE (modem)->unsolicited_registration = enabled; -} - void mm_generic_gsm_set_cid (MMGenericGsm *modem, guint32 cid) { @@ -379,14 +389,22 @@ mm_generic_gsm_grab_port (MMGenericGsm *self, port = mm_modem_base_add_port (MM_MODEM_BASE (self), subsys, name, ptype); if (port && MM_IS_SERIAL_PORT (port)) { + GPtrArray *array; + int i; + mm_serial_port_set_response_parser (MM_SERIAL_PORT (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 (MM_SERIAL_PORT (port), regex, reg_state_changed, self, NULL); - g_regex_unref (regex); + /* 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_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, reg_state_changed, self, NULL); + } + mm_gsm_creg_regex_destroy (array); if (ptype == MM_PORT_TYPE_PRIMARY) { priv->primary = MM_SERIAL_PORT (port); @@ -472,11 +490,174 @@ release_port (MMModem *modem, const char *subsys, const char *name) check_valid (MM_GENERIC_GSM (modem)); } +static void +reg_poll_response (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMGenericGsm *self = MM_GENERIC_GSM (user_data); + + if (!error) + handle_reg_status_response (self, response, NULL); +} + +static gboolean +greg_poll_cb (gpointer user_data) +{ + MMGenericGsm *self = MM_GENERIC_GSM (user_data); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + MMSerialPort *port = priv->primary; + + if (mm_port_get_connected (MM_PORT (priv->primary))) { + if (!priv->secondary) + return TRUE; /* oh well, try later */ + + /* Use secondary port if primary is connected */ + port = priv->secondary; + } + + mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, self); + + return TRUE; /* continue running */ +} + +static gboolean +reg_poll_cb (gpointer user_data) +{ + MMGenericGsm *self = MM_GENERIC_GSM (user_data); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + MMSerialPort *port = priv->primary; + + if (mm_port_get_connected (MM_PORT (priv->primary))) { + if (!priv->secondary) + return TRUE; /* oh well, try later */ + + /* Use secondary port if primary is connected */ + port = priv->secondary; + } + + mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, self); + + return TRUE; /* continue running */ +} + +static void +greg1_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = user_data; + + info->error = mm_modem_check_removed (info->modem, error); + if (info->modem) { + if (info->error) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + + g_clear_error (&info->error); + + /* The modem doesn't like unsolicited CGREG, so we'll need to poll */ + priv->greg_poll_id = g_timeout_add_seconds (10, greg_poll_cb, info->modem); + } + /* Success; get initial state */ + greg_poll_cb (info->modem); + } + mm_callback_info_schedule (info); +} + +static void +greg2_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = user_data; + + /* Ignore errors except modem removal errors */ + info->error = mm_modem_check_removed (info->modem, error); + if (info->modem) { + if (info->error) { + g_clear_error (&info->error); + /* Try CGREG=1 instead */ + mm_serial_port_queue_command (port, "+CGREG=1", 3, greg1_done, info); + } else { + /* Success; get initial state */ + greg_poll_cb (info->modem); + + /* All done */ + mm_callback_info_schedule (info); + } + } else { + /* Modem got removed */ + mm_callback_info_schedule (info); + } +} + +static void +creg1_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = user_data; + + info->error = mm_modem_check_removed (info->modem, error); + if (info->modem) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + + if (info->error) { + g_clear_error (&info->error); + + /* The modem doesn't like unsolicited CREG, so we'll need to poll */ + priv->reg_poll_id = g_timeout_add_seconds (10, reg_poll_cb, info->modem); + reg_poll_cb (info->modem); + } + /* Success; get initial state */ + reg_poll_cb (info->modem); + + /* Now try to set up CGREG messages */ + mm_serial_port_queue_command (port, "+CGREG=2", 3, greg2_done, info); + } else { + /* Modem got removed */ + mm_callback_info_schedule (info); + } +} + +static void +creg2_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = user_data; + + /* Ignore errors except modem removal errors */ + info->error = mm_modem_check_removed (info->modem, error); + if (info->modem) { + if (info->error) { + g_clear_error (&info->error); + mm_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); + } else { + /* Success; get initial state */ + reg_poll_cb (info->modem); + + /* Now try to set up CGREG messages */ + mm_serial_port_queue_command (port, "+CGREG=2", 3, greg2_done, info); + } + } else { + /* Modem got removed */ + mm_callback_info_schedule (info); + } +} + void mm_generic_gsm_enable_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); @@ -492,7 +673,8 @@ mm_generic_gsm_enable_complete (MMGenericGsm *modem, mm_generic_gsm_update_enabled_state (modem, FALSE, MM_MODEM_STATE_REASON_NONE); } - mm_callback_info_schedule (info); + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + mm_serial_port_queue_command (priv->primary, "+CREG=2", 3, creg2_done, info); } static void @@ -547,11 +729,6 @@ init_done (MMSerialPort *port, 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); - 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); @@ -690,6 +867,23 @@ disable (MMModem *modem, mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0); mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem)); + if (priv->reg_poll_id) { + g_source_remove (priv->reg_poll_id); + priv->reg_poll_id = 0; + } + + if (priv->greg_poll_id) { + g_source_remove (priv->greg_poll_id); + priv->greg_poll_id = 0; + } + + priv->lac[0] = 0; + priv->lac[1] = 0; + priv->cell_id[0] = 0; + priv->cell_id[1] = 0; + priv->access_tech[0] = -1; + priv->access_tech[1] = -1; + info = mm_callback_info_new (modem, callback, user_data); /* Cache the previous state so we can reset it if the operation fails */ @@ -1238,14 +1432,22 @@ reg_state_changed (MMSerialPort *port, { MMGenericGsm *self = MM_GENERIC_GSM (user_data); MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - char *str; - gboolean done; + guint32 state = 0, idx; + gulong lac = 0, cell_id = 0; + gint access_tech = -1; + gboolean cgreg = FALSE; + GError *error = NULL; - str = g_match_info_fetch (match_info, 1); - done = reg_status_updated (self, atoi (str), NULL); - g_free (str); + if (!mm_gsm_parse_creg_response (match_info, &state, &lac, &cell_id, &access_tech, &cgreg, &error)) { + if (mm_options_debug ()) { + g_warning ("%s: error parsing unsolicited registration: %s", + __func__, + error && error->message ? error->message : "(unknown)"); + } + return; + } - if (done) { + if (reg_status_updated (self, state, NULL)) { /* If registration is finished (either registered or failed) but the * registration query hasn't completed yet, just remove the timeout and * let the registration query complete. @@ -1255,6 +1457,11 @@ reg_state_changed (MMSerialPort *port, priv->pending_reg_id = 0; } } + + idx = cgreg ? 1 : 0; + priv->lac[idx] = lac; + priv->cell_id[idx] = cell_id; + priv->access_tech[idx] = access_tech; } static gboolean @@ -1281,6 +1488,56 @@ reg_status_again_remove (gpointer data) g_source_remove (id); } +static gboolean +handle_reg_status_response (MMGenericGsm *self, + GString *response, + GError **error) +{ + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + GMatchInfo *match_info; + guint32 status = 0, idx; + gulong lac = 0, ci = 0; + gint act = -1; + gboolean cgreg = FALSE; + guint i; + + /* Try to match the response */ + for (i = 0; i < priv->reg_regex->len; i++) { + GRegex *r = g_ptr_array_index (priv->reg_regex, i); + + if (g_regex_match (r, response->str, 0, &match_info)) + break; + g_match_info_free (match_info); + match_info = NULL; + } + + if (!match_info) { + g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Could not parse the registration status response"); + return FALSE; + } + + /* And parse it */ + if (!mm_gsm_parse_creg_response (match_info, &status, &lac, &ci, &act, &cgreg, error)) { + g_match_info_free (match_info); + return FALSE; + } + + /* Success; update cached location information */ + idx = cgreg ? 1 : 0; + priv->lac[idx] = lac; + priv->cell_id[idx] = ci; + if (act >= 0) /* Let subclasses handle if they want */ + priv->access_tech[idx] = act; + + if ((cgreg == FALSE) && status >= 0) { + /* Update cached registration status */ + reg_status_updated (self, status, NULL); + } + + return TRUE; +} + static void get_reg_status_done (MMSerialPort *port, GString *response, @@ -1290,72 +1547,46 @@ get_reg_status_done (MMSerialPort *port, MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMGenericGsm *self = MM_GENERIC_GSM (info->modem); MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - int reg_status = -1; - GRegex *r; - GMatchInfo *match_info; - char *tmp; guint id; - gboolean status_done; + + /* This function should only get called during the connect sequence when + * polling for registration state, since explicit registration requests + * from D-Bus clients are filled from the cached registration state. + */ + g_return_if_fail (info == priv->pending_reg_info); if (error) { info->error = g_error_copy (error); goto reg_done; } - r = g_regex_new ("\\+CREG:\\s*(\\d+),\\s*(\\d+)", - G_REGEX_RAW | G_REGEX_OPTIMIZE, - 0, &info->error); - if (r) { - g_regex_match_full (r, response->str, response->len, 0, 0, &match_info, &info->error); - if (g_match_info_matches (match_info)) { - /* Get reg status */ - tmp = g_match_info_fetch (match_info, 2); - if (isdigit (tmp[0])) { - tmp[1] = '\0'; - reg_status = atoi (tmp); - } else { - info->error = g_error_new (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Unknown registration status '%s'", - tmp); - } - g_free (tmp); - } else { - info->error = g_error_new_literal (MM_MODEM_ERROR, - MM_MODEM_ERROR_GENERAL, - "Could not parse the registration status response"); - } - g_match_info_free (match_info); - g_regex_unref (r); + /* The unsolicited registration state handlers will intercept the CREG + * response and update the cached registration state for us, so we usually + * just need to check the cached state here. + */ + + if (strlen (response->str)) { + /* But just in case the unsolicited handlers doesn't do it... */ + if (!handle_reg_status_response (self, response, &info->error)) + goto reg_done; } - if (reg_status >= 0) { - /* Update cached registration status */ - status_done = reg_status_updated (self, reg_status, &info->error); - - /* If we're waiting for automatic registration to complete and it's - * not done yet, check again in a few seconds. + if ( priv->reg_status != MM_MODEM_GSM_NETWORK_REG_STATUS_HOME + && priv->reg_status != MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING + && priv->reg_status != MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED) { + /* If we're still waiting for automatic registration to complete or + * fail, check again in a few seconds. */ - if ((info == priv->pending_reg_info) && !status_done) { - g_clear_error (&info->error); - - /* Not registered yet; poll registration status again */ - id = g_timeout_add_seconds (1, reg_status_again, info); - mm_callback_info_set_data (info, REG_STATUS_AGAIN_TAG, - GUINT_TO_POINTER (id), - reg_status_again_remove); - return; - } + id = g_timeout_add_seconds (1, reg_status_again, info); + mm_callback_info_set_data (info, REG_STATUS_AGAIN_TAG, + GUINT_TO_POINTER (id), + reg_status_again_remove); + return; } reg_done: - if (info == priv->pending_reg_info) { - /* For pending registration, this will schedule the callback for us */ - mm_generic_gsm_pending_registration_stop (self); - } else { - /* Otherwise for a direct registration request, schedule the callback now */ - mm_callback_info_schedule (info); - } + /* This will schedule the pending registration's the callback for us */ + mm_generic_gsm_pending_registration_stop (self); } static void @@ -1384,7 +1615,9 @@ register_done (MMSerialPort *port, if (priv->pending_reg_info) { g_warn_if_fail (info == priv->pending_reg_info); - /* Ignore errors here, get the actual registration status */ + /* Don't use cached registration state here since it could be up to + * 30 seconds old. Get fresh registration state. + */ get_registration_status (port, info); } } @@ -1469,28 +1702,16 @@ get_registration_info (MMModemGsmNetwork *self, MMModemGsmNetworkRegInfoFn callback, gpointer user_data) { - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); MMCallbackInfo *info; - MMSerialPort *port = priv->primary; info = mm_callback_info_new_full (MM_MODEM (self), gsm_network_reg_info_invoke, G_CALLBACK (callback), user_data); - - if (mm_port_get_connected (MM_PORT (priv->primary))) { - if (!priv->secondary) { - info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_CONNECTED, - "Cannot get registration info while connected"); - mm_callback_info_schedule (info); - return; - } - - /* Use secondary port if primary is connected */ - port = priv->secondary; - } - - get_registration_status (port, info); + /* Registration info updates are handled internally either by unsolicited + * updates or by polling. Thus just return the cached registration state. + */ + mm_callback_info_schedule (info); } void @@ -2305,6 +2526,11 @@ modem_simple_init (MMModemSimple *class) static void mm_generic_gsm_init (MMGenericGsm *self) { + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); + + priv->access_tech[0] = -1; + priv->access_tech[1] = -1; + priv->reg_regex = mm_gsm_creg_regex_get (TRUE); } static void @@ -2383,6 +2609,18 @@ finalize (GObject *object) if (priv->pin_check_timeout) g_source_remove (priv->pin_check_timeout); + if (priv->reg_poll_id) { + g_source_remove (priv->reg_poll_id); + priv->reg_poll_id = 0; + } + + if (priv->greg_poll_id) { + g_source_remove (priv->greg_poll_id); + priv->greg_poll_id = 0; + } + + mm_gsm_creg_regex_destroy (priv->reg_regex); + g_free (priv->oper_code); g_free (priv->oper_name); diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 7589cf98..5e07b77d 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -88,10 +88,7 @@ MMModem *mm_generic_gsm_new (const char *device, #define MM_GENERIC_GSM_PREV_STATE_TAG "prev-state" -void mm_generic_gsm_set_unsolicited_registration (MMGenericGsm *modem, - gboolean enabled); - -void mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem); +void mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem); void mm_generic_gsm_set_cid (MMGenericGsm *modem, guint32 cid); From 201295b65e4e9cf3686ee29673f7738d2810dd16 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 6 Mar 2010 10:43:54 -0800 Subject: [PATCH 21/38] gsm: use secondary serial port while connected For registration updates and signal strength. --- src/mm-generic-gsm.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 37ad5a9e..d33c7ec3 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -674,6 +674,23 @@ mm_generic_gsm_enable_complete (MMGenericGsm *modem, } priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + /* Open the second port here if the modem has one. We'll use it for + * signal strength and registration updates when the device is connected, + * but also many devices will send unsolicited registration or other + * messages to the secondary port but not the primary. + */ + if (priv->secondary) { + if (!mm_serial_port_open (priv->secondary, &error)) { + if (mm_options_debug ()) { + g_warning ("%s: error opening secondary port: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + } + } + } + mm_serial_port_queue_command (priv->primary, "+CREG=2", 3, creg2_done, info); } @@ -884,6 +901,10 @@ disable (MMModem *modem, priv->access_tech[0] = -1; priv->access_tech[1] = -1; + /* Close the secondary port if its open */ + if (priv->secondary && mm_serial_port_is_open (priv->secondary)) + mm_serial_port_close (priv->secondary); + info = mm_callback_info_new (modem, callback, user_data); /* Cache the previous state so we can reset it if the operation fails */ From 7701478703d6c119c13d544bd594a6ff7b7100d1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 07:13:43 -0800 Subject: [PATCH 22/38] gsm: simplify registration state polling code --- src/mm-generic-gsm.c | 94 +++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 58 deletions(-) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index d33c7ec3..6f0cd715 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -61,9 +61,11 @@ typedef struct { GPtrArray *reg_regex; + guint poll_id; + /* CREG and CGREG info */ - guint reg_poll_id; - guint greg_poll_id; + gboolean creg_poll; + gboolean cgreg_poll; /* Index 0 for CREG, index 1 for CGREG */ gulong lac[2]; gulong cell_id[2]; @@ -503,7 +505,7 @@ reg_poll_response (MMSerialPort *port, } static gboolean -greg_poll_cb (gpointer user_data) +periodic_poll_cb (gpointer user_data) { MMGenericGsm *self = MM_GENERIC_GSM (user_data); MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); @@ -517,36 +519,19 @@ greg_poll_cb (gpointer user_data) port = priv->secondary; } - mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, self); - - return TRUE; /* continue running */ -} - -static gboolean -reg_poll_cb (gpointer user_data) -{ - MMGenericGsm *self = MM_GENERIC_GSM (user_data); - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - MMSerialPort *port = priv->primary; - - if (mm_port_get_connected (MM_PORT (priv->primary))) { - if (!priv->secondary) - return TRUE; /* oh well, try later */ - - /* Use secondary port if primary is connected */ - port = priv->secondary; - } - - mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, self); + if (priv->creg_poll) + mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, self); + if (priv->cgreg_poll) + mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, self); return TRUE; /* continue running */ } static void -greg1_done (MMSerialPort *port, - GString *response, - GError *error, - gpointer user_data) +cgreg1_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) { MMCallbackInfo *info = user_data; @@ -558,19 +543,21 @@ greg1_done (MMSerialPort *port, g_clear_error (&info->error); /* The modem doesn't like unsolicited CGREG, so we'll need to poll */ - priv->greg_poll_id = g_timeout_add_seconds (10, greg_poll_cb, info->modem); + priv->cgreg_poll = TRUE; + if (!priv->poll_id) + priv->poll_id = g_timeout_add_seconds (10, periodic_poll_cb, info->modem); } /* Success; get initial state */ - greg_poll_cb (info->modem); + mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info); } mm_callback_info_schedule (info); } static void -greg2_done (MMSerialPort *port, - GString *response, - GError *error, - gpointer user_data) +cgreg2_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) { MMCallbackInfo *info = user_data; @@ -580,10 +567,10 @@ greg2_done (MMSerialPort *port, if (info->error) { g_clear_error (&info->error); /* Try CGREG=1 instead */ - mm_serial_port_queue_command (port, "+CGREG=1", 3, greg1_done, info); + mm_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info); } else { /* Success; get initial state */ - greg_poll_cb (info->modem); + mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info); /* All done */ mm_callback_info_schedule (info); @@ -610,14 +597,15 @@ creg1_done (MMSerialPort *port, g_clear_error (&info->error); /* The modem doesn't like unsolicited CREG, so we'll need to poll */ - priv->reg_poll_id = g_timeout_add_seconds (10, reg_poll_cb, info->modem); - reg_poll_cb (info->modem); + priv->creg_poll = TRUE; + if (!priv->poll_id) + priv->poll_id = g_timeout_add_seconds (10, periodic_poll_cb, info->modem); } /* Success; get initial state */ - reg_poll_cb (info->modem); + mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info); /* Now try to set up CGREG messages */ - mm_serial_port_queue_command (port, "+CGREG=2", 3, greg2_done, info); + mm_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); } else { /* Modem got removed */ mm_callback_info_schedule (info); @@ -640,10 +628,10 @@ creg2_done (MMSerialPort *port, mm_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); } else { /* Success; get initial state */ - reg_poll_cb (info->modem); + mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info); /* Now try to set up CGREG messages */ - mm_serial_port_queue_command (port, "+CGREG=2", 3, greg2_done, info); + mm_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); } } else { /* Modem got removed */ @@ -884,14 +872,9 @@ disable (MMModem *modem, mm_generic_gsm_set_cid (MM_GENERIC_GSM (modem), 0); mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem)); - if (priv->reg_poll_id) { - g_source_remove (priv->reg_poll_id); - priv->reg_poll_id = 0; - } - - if (priv->greg_poll_id) { - g_source_remove (priv->greg_poll_id); - priv->greg_poll_id = 0; + if (priv->poll_id) { + g_source_remove (priv->poll_id); + priv->poll_id = 0; } priv->lac[0] = 0; @@ -2630,14 +2613,9 @@ finalize (GObject *object) if (priv->pin_check_timeout) g_source_remove (priv->pin_check_timeout); - if (priv->reg_poll_id) { - g_source_remove (priv->reg_poll_id); - priv->reg_poll_id = 0; - } - - if (priv->greg_poll_id) { - g_source_remove (priv->greg_poll_id); - priv->greg_poll_id = 0; + if (priv->poll_id) { + g_source_remove (priv->poll_id); + priv->poll_id = 0; } mm_gsm_creg_regex_destroy (priv->reg_regex); From 547a9eb9c016dd528a4a275a52da39a24f775a13 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 07:35:11 -0800 Subject: [PATCH 23/38] introspection: add missing 27.007 access technologies --- introspection/mm-modem-gsm.xml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/introspection/mm-modem-gsm.xml b/introspection/mm-modem-gsm.xml index d6c42c89..25180eec 100644 --- a/introspection/mm-modem-gsm.xml +++ b/introspection/mm-modem-gsm.xml @@ -19,22 +19,28 @@ UMTS (3G) - HSDPA + HSDPA (3G) Prefer 2G (GPRS or EDGE) - Prefer 3G (UMTS or HSDPA) + Prefer 3G (UMTS/HSDPA/HSUPA/HSPA) Use only 2G (GPRS or EDGE) - Use only 3G (UMTS or HSDPA) + Use only 3G (UMTS/HSDPA/HSUPA/HSPA) - HSUPA + HSUPA (3G) + + + GSM + + + GSM Compact From ba977cd52966a15b74b261bf6cf370f535ed8d29 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 09:52:48 -0800 Subject: [PATCH 24/38] api: readability fixes --- introspection/mm-modem-gsm-card.xml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/introspection/mm-modem-gsm-card.xml b/introspection/mm-modem-gsm-card.xml index ad9348d3..708d5c9a 100644 --- a/introspection/mm-modem-gsm-card.xml +++ b/introspection/mm-modem-gsm-card.xml @@ -96,11 +96,17 @@ - Bands supported by the card. (Note for plugin writers: returned value must not contain ANY) + + Bands supported by the card. (Note for plugin writers: + returned value must not contain ANY) + - Network selection modes supported by the card. (Note for plugin writers: returned value must not contain ANY) + + Network selection modes supported by the card. (Note for plugin writers: + returned value must not contain ANY) + From e7dd2926a3ba1cf6129996ec63accee7fa1ad155 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 09:53:03 -0800 Subject: [PATCH 25/38] api: revert parts of 2d194a5798fb06f41b018c2d8c2216f45bfc41a4 MM hadn't implemented it yet, but Wader already implemented an earlier version that didn't use a bitfield but an enum. Unfortunately the network mode stuff doesn't allow for distinguishing between the device's mode preference and the current access technology. So deprecate the current network mode stuff in the API in preparation for improved API. --- introspection/mm-modem-gsm-network.xml | 56 +++++++++++++++++++++----- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/introspection/mm-modem-gsm-network.xml b/introspection/mm-modem-gsm-network.xml index 934e8e0b..0e52ebd4 100644 --- a/introspection/mm-modem-gsm-network.xml +++ b/introspection/mm-modem-gsm-network.xml @@ -82,11 +82,12 @@ - Set the desired mode the device may use when connecting to a mobile network. + Set the desired mode the device may use when connecting to a mobile + network (DEPRECATED; see SetAllowedModes instead). - + The desired network mode. Only one mode may be specified, and may not be UNKNOWN. @@ -95,11 +96,13 @@ - Returns the current network mode of the device. (Note for plugin writers: returned value *may* be ANY) + Returns the current network mode of the device (DEPRECATED; does not + allow returning both the saved mode preference *and* the current access + technology of the device at the same time. See GetAllowedModes instead). - + Returns the general network mode (ex. 2G/3G preference) of the device. @@ -156,12 +159,11 @@ - The network mode changed. + The network mode preference changed. (DEPRECATED; see documentation + for GetNetworkMode/SetNetworkMode) - - - The new network mode. - + + The new network mode. @@ -198,5 +200,41 @@ + + + Any network mode can be used + + + GPRS + + + EDGE + + + UMTS (3G) + + + HSDPA + + + Prefer 2G (GPRS or EDGE) + + + Prefer 3G (UMTS/HSDPA/HSUPA/HSPA) + + + Use only 2G (GPRS or EDGE) + + + Use only 3G (UMTS/HSDPA/HSUPA/HSPA) + + + HSUPA + + + HSPA (HSDPA + HSUPA) + + + From 8fcc5b7fe2458eee7b1ca0a7a39cbc710ea48b60 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 09:53:28 -0800 Subject: [PATCH 26/38] api: more clearly document modes and bands --- introspection/mm-modem-gsm.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/introspection/mm-modem-gsm.xml b/introspection/mm-modem-gsm.xml index 25180eec..579899cc 100644 --- a/introspection/mm-modem-gsm.xml +++ b/introspection/mm-modem-gsm.xml @@ -3,6 +3,11 @@ + + A bitfield describing the specifc access modes and technologies + supported by a device, the device's current access mode preference, and + the access technology in-use when connected to a mobile network. + Unknown or invalid mode. @@ -46,7 +51,9 @@ - GSM network and device bands. + A bitfield describing the specific radio bands supported by the device + and the radio bands the device is allowed to use when connecting to a + mobile network. Unknown or invalid band From 45fd96132f4568c97a85524b530c2b682fa07c14 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 09:58:30 -0800 Subject: [PATCH 27/38] api: add new AllowedModes and AccessTechnology API This adds split properties and functions for the allowed modes and the current access technology used by the device when connected to the mobile network. --- introspection/mm-modem-gsm-network.xml | 38 +++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/introspection/mm-modem-gsm-network.xml b/introspection/mm-modem-gsm-network.xml index 0e52ebd4..03425c6e 100644 --- a/introspection/mm-modem-gsm-network.xml +++ b/introspection/mm-modem-gsm-network.xml @@ -98,7 +98,8 @@ Returns the current network mode of the device (DEPRECATED; does not allow returning both the saved mode preference *and* the current access - technology of the device at the same time. See GetAllowedModes instead). + technology of the device at the same time. See the AllowedModes + property instead). @@ -125,6 +126,41 @@ + + + Set the allowed access technologies to use when connecting to a mobile + network. + + + + + + The allowed access technologies. Only one mode flag may be specified, + and it may not be UNKNOWN. The device may not support all modes; see + the org.freedesktop.ModemManager.Gsm.Card.SupportedModes property for + allowed modes for each device. All devices support the "ANY" flag. + + + + + + + The allowed access technologies (eg 2G/3G preference or specific access + technology) to use when connecting to a mobile network. (Note for plugin + writers: this value may be ANY) + + + + + + The current network access technology used by the device to communicate + with the base station. (Note to plugin writers: if the device's access + technology cannot be determined, use UNKNOWN. Using any of the + PREFER flags or the ANY in this field is invalid as they are not a + specific access technology.) + + + The signal quality changed. From 74ed9baefa0e1b10d1bec184e2dcfca4dc718eff Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 11:01:08 -0800 Subject: [PATCH 28/38] gsm: add missing 27.007 access technologies --- src/mm-modem-gsm.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index 852ff853..b10baf04 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -29,9 +29,10 @@ typedef enum { MM_MODEM_GSM_MODE_2G_ONLY = 0x00000080, MM_MODEM_GSM_MODE_3G_ONLY = 0x00000100, MM_MODEM_GSM_MODE_HSUPA = 0x00000200, - MM_MODEM_GSM_MODE_HSPA = 0x00000400, + MM_MODEM_GSM_MODE_GSM = 0x00000400, + MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00000800, - MM_MODEM_GSM_MODE_LAST = MM_MODEM_GSM_MODE_HSPA + MM_MODEM_GSM_MODE_LAST = MM_MODEM_GSM_MODE_GSM_COMPACT } MMModemGsmMode; typedef enum { From 82d7c8342d749c827161fbcbc5db670b671282d9 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 7 Mar 2010 14:46:38 -0800 Subject: [PATCH 29/38] gsm: fix crash getting initial registration state --- src/mm-generic-gsm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 6f0cd715..9e35b339 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -548,7 +548,7 @@ cgreg1_done (MMSerialPort *port, priv->poll_id = g_timeout_add_seconds (10, periodic_poll_cb, info->modem); } /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info); + mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); } mm_callback_info_schedule (info); } @@ -570,7 +570,7 @@ cgreg2_done (MMSerialPort *port, mm_serial_port_queue_command (port, "+CGREG=1", 3, cgreg1_done, info); } else { /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info); + mm_serial_port_queue_command (port, "+CGREG?", 10, reg_poll_response, info->modem); /* All done */ mm_callback_info_schedule (info); @@ -602,7 +602,7 @@ creg1_done (MMSerialPort *port, priv->poll_id = g_timeout_add_seconds (10, periodic_poll_cb, info->modem); } /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info); + mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); /* Now try to set up CGREG messages */ mm_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); @@ -628,7 +628,7 @@ creg2_done (MMSerialPort *port, mm_serial_port_queue_command (port, "+CREG=1", 3, creg1_done, info); } else { /* Success; get initial state */ - mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info); + mm_serial_port_queue_command (port, "+CREG?", 10, reg_poll_response, info->modem); /* Now try to set up CGREG messages */ mm_serial_port_queue_command (port, "+CGREG=2", 3, cgreg2_done, info); From 343245fc2179a6d05ba131771def84c84b1be639 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 11:40:54 -0800 Subject: [PATCH 30/38] gsm: add AccessTechnology property and associated infrastructure AccessTechnology takes over half of what NetworkMode was supposed to do, but we'll keep NetworkMode around for a while for compatibility anyway. Create async updaters that subclasses can use to update the access tech when they get unsolicited messages. --- plugins/mm-modem-huawei-gsm.c | 20 ++--- src/mm-generic-gsm.c | 144 ++++++++++++++++++++++++++++------ src/mm-generic-gsm.h | 19 ++++- src/mm-modem-gsm-network.c | 85 ++++++++++++++++++++ src/mm-modem-gsm-network.h | 16 +++- src/mm-modem-gsm.h | 15 ++++ 6 files changed, 263 insertions(+), 36 deletions(-) diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index 76a2d76b..af6a4b7b 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -11,7 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #include @@ -459,7 +459,7 @@ handle_mode_change (MMSerialPort *port, gpointer user_data) { MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (user_data); - MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self); + MMModemGsmMode new_mode = MM_MODEM_GSM_MODE_UNKNOWN; char *str; int a; int b; @@ -473,24 +473,24 @@ handle_mode_change (MMSerialPort *port, g_free (str); if (a == 3 && b == 2) - priv->mode = MM_MODEM_GSM_MODE_GPRS; + new_mode = MM_MODEM_GSM_MODE_GPRS; else if (a == 3 && b == 3) - priv->mode = MM_MODEM_GSM_MODE_EDGE; + new_mode = MM_MODEM_GSM_MODE_EDGE; else if (a == 5 && b == 4) - priv->mode = MM_MODEM_GSM_MODE_UMTS; + new_mode = MM_MODEM_GSM_MODE_UMTS; else if (a == 5 && b == 5) - priv->mode = MM_MODEM_GSM_MODE_HSDPA; + new_mode = MM_MODEM_GSM_MODE_HSDPA; else if (a == 5 && b == 6) - priv->mode = MM_MODEM_GSM_MODE_HSUPA; + new_mode = MM_MODEM_GSM_MODE_HSUPA; else if (a == 5 && b == 7) - priv->mode = MM_MODEM_GSM_MODE_HSPA; + new_mode = MM_MODEM_GSM_MODE_HSPA; else { g_warning ("Couldn't parse mode change value: '%s'", str); return; } - g_debug ("Mode: %d", priv->mode); - mm_modem_gsm_network_mode (MM_MODEM_GSM_NETWORK (self), priv->mode); + g_debug ("Access Technology: %d", new_mode); + mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), new_mode); } static void diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 9e35b339..b28000c6 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -29,6 +29,7 @@ #include "mm-serial-parsers.h" #include "mm-modem-helpers.h" #include "mm-options.h" +#include "mm-properties-changed-signal.h" static void modem_init (MMModem *modem_class); static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class); @@ -69,7 +70,7 @@ typedef struct { /* Index 0 for CREG, index 1 for CGREG */ gulong lac[2]; gulong cell_id[2]; - gint access_tech[2]; + MMModemGsmMode access_tech; MMModemGsmNetworkRegStatus reg_status; guint pending_reg_id; @@ -107,6 +108,8 @@ static gboolean handle_reg_status_response (MMGenericGsm *self, GString *response, GError **error); +static MMModemGsmMode etsi_act_to_mm_mode (gint act); + MMModem * mm_generic_gsm_new (const char *device, const char *driver, @@ -864,7 +867,8 @@ disable (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; @@ -881,8 +885,7 @@ disable (MMModem *modem, priv->lac[1] = 0; priv->cell_id[0] = 0; priv->cell_id[1] = 0; - priv->access_tech[0] = -1; - priv->access_tech[1] = -1; + mm_generic_gsm_update_access_technology (self, MM_MODEM_GSM_MODE_UNKNOWN); /* Close the secondary port if its open */ if (priv->secondary && mm_serial_port_is_open (priv->secondary)) @@ -1465,7 +1468,10 @@ reg_state_changed (MMSerialPort *port, idx = cgreg ? 1 : 0; priv->lac[idx] = lac; priv->cell_id[idx] = cell_id; - priv->access_tech[idx] = access_tech; + + /* Only update access technology if it appeared in the CREG/CGREG response */ + if (access_tech != -1) + mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_mode (access_tech)); } static gboolean @@ -1531,8 +1537,10 @@ handle_reg_status_response (MMGenericGsm *self, idx = cgreg ? 1 : 0; priv->lac[idx] = lac; priv->cell_id[idx] = ci; - if (act >= 0) /* Let subclasses handle if they want */ - priv->access_tech[idx] = act; + + /* Only update access technology if it appeared in the CREG/CGREG response */ + if (act != -1) + mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_mode (act)); if ((cgreg == FALSE) && status >= 0) { /* Update cached registration status */ @@ -2160,6 +2168,84 @@ get_signal_quality (MMModemGsmNetwork *modem, mm_serial_port_queue_command (connected ? priv->secondary : priv->primary, "+CSQ", 3, get_signal_quality_done, info); } +/*****************************************************************************/ + +typedef struct { + MMModemGsmMode mode; + gint etsi_act; +} ModeEtsi; + +static ModeEtsi modes_table[] = { + { MM_MODEM_GSM_MODE_GSM, 0 }, + { MM_MODEM_GSM_MODE_GSM_COMPACT, 1 }, + { MM_MODEM_GSM_MODE_UMTS, 2 }, + { MM_MODEM_GSM_MODE_EDGE, 3 }, + { MM_MODEM_GSM_MODE_HSDPA, 4 }, + { MM_MODEM_GSM_MODE_HSUPA, 5 }, + { MM_MODEM_GSM_MODE_HSDPA | + MM_MODEM_GSM_MODE_HSUPA, 6 }, + { MM_MODEM_GSM_MODE_HSDPA | + MM_MODEM_GSM_MODE_HSUPA, 7 }, /* E-UTRAN/LTE */ + { MM_MODEM_GSM_MODE_UNKNOWN, -1 }, +}; + +static MMModemGsmMode +etsi_act_to_mm_mode (gint act) +{ + ModeEtsi *iter = &modes_table[0]; + + while (iter->mode != MM_MODEM_GSM_MODE_UNKNOWN) { + if (iter->etsi_act == act) + return iter->mode; + } + return MM_MODEM_GSM_MODE_UNKNOWN; +} + +static gboolean +check_for_single_value (guint32 value) +{ + gboolean found = FALSE; + guint32 i; + + for (i = 1; i <= 32; i++) { + if (value & 0x1) { + if (found) + return FALSE; /* More than one bit set */ + found = TRUE; + } + value >>= 1; + } + + return TRUE; +} + +void +mm_generic_gsm_update_access_technology (MMGenericGsm *modem, + MMModemGsmMode mode) +{ + MMGenericGsmPrivate *priv; + + g_return_if_fail (modem != NULL); + g_return_if_fail (MM_IS_GENERIC_GSM (modem)); + + g_return_if_fail (check_for_single_value (mode) || (mode == MM_MODEM_GSM_MODE_HSPA)); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_ANY) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_PREFERRED) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_PREFERRED) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_ONLY) == 0); + g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_ONLY) == 0); + + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + + if (mode != priv->access_tech) { + priv->access_tech = mode; + g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); + + /* Deprecated value */ + g_signal_emit_by_name (G_OBJECT (modem), "NetworkMode", mode); + } +} + /*****************************************************************************/ /* MMModemGsmSms interface */ @@ -2409,17 +2495,6 @@ simple_status_got_band (MMModem *modem, g_hash_table_insert ((GHashTable *) user_data, "band", simple_uint_value (result)); } -static void -simple_status_got_mode (MMModem *modem, - guint32 result, - GError *error, - gpointer user_data) -{ - /* Ignore network mode errors since there's no generic implementation for it */ - if (!error) - g_hash_table_insert ((GHashTable *) user_data, "network_mode", simple_uint_value (result)); -} - static void simple_status_got_reg_info (MMModemGsmNetwork *modem, MMModemGsmNetworkRegStatus status, @@ -2459,9 +2534,11 @@ simple_get_status (MMModemSimple *simple, MMModemSimpleGetStatusFn callback, gpointer user_data) { - MMModemGsmNetwork *gsm; + MMModemGsmNetwork *gsm = MM_MODEM_GSM_NETWORK (simple); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (simple); GHashTable *properties; MMCallbackInfo *info; + MMModemDeprecatedMode old_mode; info = mm_callback_info_new_full (MM_MODEM (simple), simple_get_status_invoke, @@ -2471,11 +2548,18 @@ simple_get_status (MMModemSimple *simple, properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, simple_free_gvalue); mm_callback_info_set_data (info, "simple-get-status", properties, (GDestroyNotify) g_hash_table_unref); - gsm = MM_MODEM_GSM_NETWORK (simple); mm_modem_gsm_network_get_signal_quality (gsm, simple_status_got_signal_quality, properties); mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties); - mm_modem_gsm_network_get_mode (gsm, simple_status_got_mode, properties); mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, properties); + + if (priv->access_tech > -1) { + /* Deprecated key */ + old_mode = mm_modem_gsm_network_new_mode_to_old (priv->access_tech); + g_hash_table_insert (properties, "network_mode", simple_uint_value (old_mode)); + + /* New key */ + g_hash_table_insert (properties, "access_technology", simple_uint_value (priv->access_tech)); + } } /*****************************************************************************/ @@ -2532,9 +2616,12 @@ mm_generic_gsm_init (MMGenericGsm *self) { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - priv->access_tech[0] = -1; - priv->access_tech[1] = -1; + priv->access_tech = MM_MODEM_GSM_MODE_UNKNOWN; priv->reg_regex = mm_gsm_creg_regex_get (TRUE); + + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, + MM_MODEM_GSM_NETWORK_DBUS_INTERFACE); } static void @@ -2549,6 +2636,7 @@ set_property (GObject *object, guint prop_id, case MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL: case MM_GENERIC_GSM_PROP_SUPPORTED_BANDS: case MM_GENERIC_GSM_PROP_SUPPORTED_MODES: + case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2597,6 +2685,12 @@ get_property (GObject *object, guint prop_id, case MM_GENERIC_GSM_PROP_SUPPORTED_MODES: g_value_set_uint (value, 0); break; + case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: + if (mm_modem_get_state (MM_MODEM (object)) >= MM_MODEM_STATE_ENABLED) + g_value_set_uint (value, priv->access_tech); + else + g_value_set_uint (value, MM_MODEM_GSM_MODE_UNKNOWN); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2659,6 +2753,10 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) MM_GENERIC_GSM_PROP_SUPPORTED_MODES, MM_MODEM_GSM_CARD_SUPPORTED_MODES); + g_object_class_override_property (object_class, + MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY, + MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); + g_object_class_install_property (object_class, MM_GENERIC_GSM_PROP_POWER_UP_CMD, g_param_spec_string (MM_GENERIC_GSM_POWER_UP_CMD, diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 5e07b77d..477ec6b7 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -11,7 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 - 2009 Novell, Inc. - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #ifndef MM_GENERIC_GSM_H @@ -43,7 +43,8 @@ typedef enum { MM_GENERIC_GSM_PROP_INIT_CMD, MM_GENERIC_GSM_PROP_SUPPORTED_BANDS, MM_GENERIC_GSM_PROP_SUPPORTED_MODES, - MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL + MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL, + MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY } MMGenericGsmProp; @@ -76,6 +77,13 @@ typedef struct { GString *response, GError *error, MMCallbackInfo *info); + + /* Called by the generic class to the current radio access technology the + * device is using while communicating with the base station. + */ + void (*get_access_technology) (MMGenericGsm *self, + MMModemUIntFn callback, + gpointer user_data); } MMGenericGsmClass; GType mm_generic_gsm_get_type (void); @@ -97,6 +105,13 @@ guint32 mm_generic_gsm_get_cid (MMGenericGsm *modem); void mm_generic_gsm_set_reg_status (MMGenericGsm *modem, MMModemGsmNetworkRegStatus status); +/* Called to asynchronously update the current access technology of the device; + * this is NOT the 2G/3G mode preference, but the current radio access + * technology being used to communicate with the base station. + */ +void mm_generic_gsm_update_access_technology (MMGenericGsm *modem, + MMModemGsmMode mode); + void mm_generic_gsm_check_pin (MMGenericGsm *modem, MMModemFn callback, gpointer user_data); diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index f332f580..ca00decc 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -11,6 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 Novell, Inc. + * Copyright (C) 2010 Red Hat, Inc. */ #include @@ -42,6 +43,10 @@ static void impl_gsm_modem_set_band (MMModemGsmNetwork *modem, static void impl_gsm_modem_get_band (MMModemGsmNetwork *modem, DBusGMethodInvocation *context); +static void impl_gsm_modem_set_allowed_modes (MMModemGsmNetwork *modem, + MMModemGsmMode mode, + DBusGMethodInvocation *context); + static void impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, MMModemGsmMode mode, DBusGMethodInvocation *context); @@ -68,6 +73,67 @@ static guint signals[LAST_SIGNAL] = { 0 }; /*****************************************************************************/ +MMModemGsmMode +mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode) +{ + /* Translate deprecated mode into new mode */ + switch (old_mode) { + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS: + return MM_MODEM_GSM_MODE_GPRS; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE: + return MM_MODEM_GSM_MODE_EDGE; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS: + return MM_MODEM_GSM_MODE_UMTS; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA: + return MM_MODEM_GSM_MODE_HSDPA; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED: + return MM_MODEM_GSM_MODE_2G_PREFERRED; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED: + return MM_MODEM_GSM_MODE_3G_PREFERRED; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY: + return MM_MODEM_GSM_MODE_2G_ONLY; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY: + return MM_MODEM_GSM_MODE_3G_ONLY; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA: + return MM_MODEM_GSM_MODE_HSUPA; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA: + return MM_MODEM_GSM_MODE_HSDPA | MM_MODEM_GSM_MODE_HSUPA; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY: + default: + break; + } + + return MM_MODEM_GSM_MODE_ANY; +} + +MMModemDeprecatedMode +mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode) +{ + /* Translate new mode into old deprecated mode */ + if (new_mode & MM_MODEM_GSM_MODE_GPRS) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS; + else if (new_mode & MM_MODEM_GSM_MODE_EDGE) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE; + else if (new_mode & MM_MODEM_GSM_MODE_UMTS) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS; + else if (new_mode & MM_MODEM_GSM_MODE_HSDPA) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA; + else if (new_mode & MM_MODEM_GSM_MODE_2G_PREFERRED) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED; + else if (new_mode & MM_MODEM_GSM_MODE_3G_PREFERRED) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED; + else if (new_mode & MM_MODEM_GSM_MODE_2G_ONLY) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY; + else if (new_mode & MM_MODEM_GSM_MODE_3G_ONLY) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY; + else if (new_mode & MM_MODEM_GSM_MODE_HSUPA) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA; + + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY; +} + +/*****************************************************************************/ + static void async_call_done (MMModem *modem, GError *error, gpointer user_data) { @@ -491,6 +557,14 @@ impl_gsm_modem_get_band (MMModemGsmNetwork *modem, mm_modem_gsm_network_get_band (modem, uint_call_done, context); } +static void +impl_gsm_modem_set_allowed_modes (MMModemGsmNetwork *modem, + MMModemGsmMode mode, + DBusGMethodInvocation *context) +{ + dbus_g_method_return (context); +} + static void impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, MMModemGsmMode mode, @@ -534,6 +608,17 @@ mm_modem_gsm_network_init (gpointer g_iface) if (initialized) return; + g_object_interface_install_property + (g_iface, + g_param_spec_uint (MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, + "Access Technology", + "Current access technology in use when connected to " + "a mobile network.", + MM_MODEM_GSM_MODE_UNKNOWN, + MM_MODEM_GSM_MODE_LAST, + MM_MODEM_GSM_MODE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /* Signals */ signals[SIGNAL_QUALITY] = g_signal_new ("signal-quality", diff --git a/src/mm-modem-gsm-network.h b/src/mm-modem-gsm-network.h index 493baec7..3aa6ce30 100644 --- a/src/mm-modem-gsm-network.h +++ b/src/mm-modem-gsm-network.h @@ -11,7 +11,7 @@ * GNU General Public License for more details: * * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2010 Red Hat, Inc. */ #ifndef MM_MODEM_GSM_NETWORK_H @@ -20,11 +20,21 @@ #include #include +#define MM_MODEM_GSM_NETWORK_DBUS_INTERFACE "org.freedesktop.ModemManager.Modem.Gsm.Network" + #define MM_TYPE_MODEM_GSM_NETWORK (mm_modem_gsm_network_get_type ()) #define MM_MODEM_GSM_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_MODEM_GSM_NETWORK, MMModemGsmNetwork)) #define MM_IS_MODEM_GSM_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_GSM_NETWORK)) #define MM_MODEM_GSM_NETWORK_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM_GSM_NETWORK, MMModemGsmNetwork)) +#define MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY "access-technology" + +typedef enum { + MM_MODEM_GSM_NETWORK_PROP_FIRST = 0x1200, + + MM_MODEM_GSM_NETWORK_PROP_ACCESS_TECHNOLOGY = MM_MODEM_GSM_NETWORK_PROP_FIRST, +} MMModemGsmNetworkProp; + typedef enum { MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE = 0, MM_MODEM_GSM_NETWORK_REG_STATUS_HOME = 1, @@ -161,4 +171,8 @@ void mm_modem_gsm_network_registration_info (MMModemGsmNetwork *self, void mm_modem_gsm_network_mode (MMModemGsmNetwork *self, MMModemGsmMode mode); +MMModemDeprecatedMode mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode); + +MMModemGsmMode mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode); + #endif /* MM_MODEM_GSM_NETWORK_H */ diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index b10baf04..cac7c65f 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -29,12 +29,27 @@ typedef enum { MM_MODEM_GSM_MODE_2G_ONLY = 0x00000080, MM_MODEM_GSM_MODE_3G_ONLY = 0x00000100, MM_MODEM_GSM_MODE_HSUPA = 0x00000200, + MM_MODEM_GSM_MODE_HSPA = 0x00000210, /* HSDPA + HSUPA */ MM_MODEM_GSM_MODE_GSM = 0x00000400, MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00000800, MM_MODEM_GSM_MODE_LAST = MM_MODEM_GSM_MODE_GSM_COMPACT } MMModemGsmMode; +typedef enum { + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA +} MMModemDeprecatedMode; + typedef enum { MM_MODEM_GSM_BAND_UNKNOWN = 0x00000000, MM_MODEM_GSM_BAND_ANY = 0x00000001, From 5e2983484e4ab3a594e63b03d34804d57c0dc292 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 14:15:25 -0800 Subject: [PATCH 31/38] api: make HSPA a standalone network mode again It's just easier this way. It makes little sense to allow selecting mode combinations for anything other than (HSDPA | HSUPA). Most radios don't allow fine-grained control of the different technologies within each 2G or 3G class anyway thus combinations like (GPRS | UMTS) are pointless since the device wouldn't be able to use GPRS but not use EDGE. --- introspection/mm-modem-gsm.xml | 7 +++++-- src/mm-modem-gsm.h | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/introspection/mm-modem-gsm.xml b/introspection/mm-modem-gsm.xml index 579899cc..f5def8ac 100644 --- a/introspection/mm-modem-gsm.xml +++ b/introspection/mm-modem-gsm.xml @@ -41,10 +41,13 @@ HSUPA (3G) - + + HSPA (3G) + + GSM - + GSM Compact diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index cac7c65f..8f1155ec 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -29,9 +29,9 @@ typedef enum { MM_MODEM_GSM_MODE_2G_ONLY = 0x00000080, MM_MODEM_GSM_MODE_3G_ONLY = 0x00000100, MM_MODEM_GSM_MODE_HSUPA = 0x00000200, - MM_MODEM_GSM_MODE_HSPA = 0x00000210, /* HSDPA + HSUPA */ - MM_MODEM_GSM_MODE_GSM = 0x00000400, - MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00000800, + MM_MODEM_GSM_MODE_HSPA = 0x00000400, + MM_MODEM_GSM_MODE_GSM = 0x00000800, + MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00001000, MM_MODEM_GSM_MODE_LAST = MM_MODEM_GSM_MODE_GSM_COMPACT } MMModemGsmMode; From e2c487472e52bc14acd04e93a6d5b7d54a2bcfa5 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 14:34:30 -0800 Subject: [PATCH 32/38] api: s/AllowedModes/AllowedMode in Gsm.Network Only one mode is going to be stored here so it shouldn't be plural. --- introspection/mm-modem-gsm-network.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/introspection/mm-modem-gsm-network.xml b/introspection/mm-modem-gsm-network.xml index 03425c6e..82eb177d 100644 --- a/introspection/mm-modem-gsm-network.xml +++ b/introspection/mm-modem-gsm-network.xml @@ -83,7 +83,7 @@ Set the desired mode the device may use when connecting to a mobile - network (DEPRECATED; see SetAllowedModes instead). + network (DEPRECATED; see SetAllowedMode instead). @@ -98,7 +98,7 @@ Returns the current network mode of the device (DEPRECATED; does not allow returning both the saved mode preference *and* the current access - technology of the device at the same time. See the AllowedModes + technology of the device at the same time. See the AllowedMode property instead). @@ -126,13 +126,13 @@ - + Set the allowed access technologies to use when connecting to a mobile network. - + The allowed access technologies. Only one mode flag may be specified, @@ -143,9 +143,9 @@ - + - The allowed access technologies (eg 2G/3G preference or specific access + The allowed access technologies (eg 2G/3G preference or a specific access technology) to use when connecting to a mobile network. (Note for plugin writers: this value may be ANY) From d298885faa72398368a67a7738a6208dae0c6f0a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 14:50:07 -0800 Subject: [PATCH 33/38] gsm: fix GObject property maximums for SupportedModes and SupportedBands Since the values they carry are bitfields, using the highest value as the maximum isn't the right thing to do. --- src/mm-modem-gsm-card.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c index f4a5138f..432a4a3f 100644 --- a/src/mm-modem-gsm-card.c +++ b/src/mm-modem-gsm-card.c @@ -503,7 +503,7 @@ mm_modem_gsm_card_init (gpointer g_iface) "Supported Modes", "Supported frequency bands of the card", MM_MODEM_GSM_BAND_UNKNOWN, - MM_MODEM_GSM_BAND_LAST, + G_MAXUINT32, MM_MODEM_GSM_BAND_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); @@ -513,7 +513,7 @@ mm_modem_gsm_card_init (gpointer g_iface) "Supported Modes", "Supported modes of the card (ex 2G preferred, 3G preferred, 2G only, etc", MM_MODEM_GSM_MODE_UNKNOWN, - MM_MODEM_GSM_MODE_LAST, + G_MAXUINT32, MM_MODEM_GSM_MODE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } From aeac17a81edfb3304de405127bb06d100c8a5522 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 15:13:14 -0800 Subject: [PATCH 34/38] gsm: implement allowed mode --- plugins/mm-modem-huawei-gsm.c | 101 +++++++++++++------------------- plugins/mm-modem-mbm.c | 65 +++++++++++++++------ plugins/mm-modem-option.c | 46 +++++---------- src/mm-generic-gsm.c | 106 +++++++++++++++++++++++++++++++--- src/mm-generic-gsm.h | 21 +++++++ src/mm-modem-gsm-network.c | 92 +++++++++++++++-------------- src/mm-modem-gsm-network.h | 22 ++++--- src/mm-modem-gsm.h | 2 - 8 files changed, 283 insertions(+), 172 deletions(-) diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index af6a4b7b..4594872b 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -41,7 +41,6 @@ G_DEFINE_TYPE_EXTENDED (MMModemHuaweiGsm, mm_modem_huawei_gsm, MM_TYPE_GENERIC_G typedef struct { /* Cached state */ guint signal_quality; - MMModemGsmMode mode; MMModemGsmBand band; } MMModemHuaweiGsmPrivate; @@ -68,23 +67,28 @@ parse_syscfg (MMModemHuaweiGsm *self, int *mode_b, guint32 *band, int *unknown1, - int *unknown2) + int *unknown2, + MMModemGsmMode *out_mode) { if (reply == NULL || strncmp (reply, "^SYSCFG:", 8)) return FALSE; if (sscanf (reply + 8, "%d,%d,%x,%d,%d", mode_a, mode_b, band, unknown1, unknown2)) { MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self); - + MMModemGsmMode new_mode = MM_MODEM_GSM_MODE_ANY; + /* Network mode */ if (*mode_a == 2 && *mode_b == 1) - priv->mode = MM_MODEM_GSM_MODE_2G_PREFERRED; + new_mode = MM_MODEM_GSM_MODE_2G_PREFERRED; else if (*mode_a == 2 && *mode_b == 2) - priv->mode = MM_MODEM_GSM_MODE_3G_PREFERRED; + new_mode = MM_MODEM_GSM_MODE_3G_PREFERRED; else if (*mode_a == 13 && *mode_b == 1) - priv->mode = MM_MODEM_GSM_MODE_2G_ONLY; + new_mode = MM_MODEM_GSM_MODE_2G_ONLY; else if (*mode_a == 14 && *mode_b == 2) - priv->mode = MM_MODEM_GSM_MODE_3G_ONLY; + new_mode = MM_MODEM_GSM_MODE_3G_ONLY; + + if (out_mode) + *out_mode = new_mode; /* Band */ if (*band == 0x3FFFFFFF) @@ -101,26 +105,21 @@ parse_syscfg (MMModemHuaweiGsm *self, } static void -set_network_mode_done (MMSerialPort *port, +set_allowed_mode_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; - MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (info->modem); - MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self); if (error) info->error = g_error_copy (error); - else - /* Success, cache the value */ - priv->mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode")); mm_callback_info_schedule (info); } static void -set_network_mode_get_done (MMSerialPort *port, +set_allowed_mode_get_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -134,7 +133,7 @@ set_network_mode_get_done (MMSerialPort *port, int a, b, u1, u2; guint32 band; - if (parse_syscfg (MM_MODEM_HUAWEI_GSM (info->modem), response->str, &a, &b, &band, &u1, &u2)) { + if (parse_syscfg (MM_MODEM_HUAWEI_GSM (info->modem), response->str, &a, &b, &band, &u1, &u2, NULL)) { char *command; switch (GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode"))) { @@ -142,16 +141,10 @@ set_network_mode_get_done (MMSerialPort *port, a = 2; b = 0; break; - case MM_MODEM_GSM_MODE_GPRS: - case MM_MODEM_GSM_MODE_EDGE: case MM_MODEM_GSM_MODE_2G_ONLY: a = 13; b = 1; break; - case MM_MODEM_GSM_MODE_UMTS: - case MM_MODEM_GSM_MODE_HSDPA: - case MM_MODEM_GSM_MODE_HSUPA: - case MM_MODEM_GSM_MODE_HSPA: case MM_MODEM_GSM_MODE_3G_ONLY: a = 14; b = 2; @@ -169,14 +162,14 @@ set_network_mode_get_done (MMSerialPort *port, } command = g_strdup_printf ("AT^SYSCFG=%d,%d,%X,%d,%d", a, b, band, u1, u2); - mm_serial_port_queue_command (port, command, 3, set_network_mode_done, info); + mm_serial_port_queue_command (port, command, 3, set_allowed_mode_done, info); g_free (command); } } } static void -set_network_mode (MMModemGsmNetwork *modem, +set_allowed_mode (MMGenericGsm *gsm, MMModemGsmMode mode, MMModemFn callback, gpointer user_data) @@ -184,28 +177,26 @@ set_network_mode (MMModemGsmNetwork *modem, MMCallbackInfo *info; MMSerialPort *primary; - info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); + info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); switch (mode) { case MM_MODEM_GSM_MODE_ANY: - case MM_MODEM_GSM_MODE_GPRS: - case MM_MODEM_GSM_MODE_EDGE: - case MM_MODEM_GSM_MODE_UMTS: - case MM_MODEM_GSM_MODE_HSDPA: - case MM_MODEM_GSM_MODE_HSUPA: - case MM_MODEM_GSM_MODE_HSPA: case MM_MODEM_GSM_MODE_2G_PREFERRED: case MM_MODEM_GSM_MODE_3G_PREFERRED: case MM_MODEM_GSM_MODE_2G_ONLY: case MM_MODEM_GSM_MODE_3G_ONLY: /* Allowed values */ mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (gsm), MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_network_mode_get_done, info); + + /* Get current configuration first so we don't change band and other + * stuff when updating the mode. + */ + mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_allowed_mode_get_done, info); return; default: - info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid mode."); + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unsupported allowed mode."); break; } @@ -213,49 +204,37 @@ set_network_mode (MMModemGsmNetwork *modem, } static void -get_network_mode_done (MMSerialPort *port, +get_allowed_mode_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) { MMCallbackInfo *info = (MMCallbackInfo *) user_data; MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (info->modem); - MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self); int mode_a, mode_b, u1, u2; guint32 band; + MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; if (error) info->error = g_error_copy (error); - else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2)) - mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->mode), NULL); + else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2, &mode)) + mm_callback_info_set_result (info, GUINT_TO_POINTER (mode), NULL); mm_callback_info_schedule (info); } static void -get_network_mode (MMModemGsmNetwork *modem, +get_allowed_mode (MMGenericGsm *gsm, MMModemUIntFn callback, gpointer user_data) { - MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (modem); + MMCallbackInfo *info; + MMSerialPort *primary; - if (priv->mode != MM_MODEM_GSM_MODE_ANY) { - /* have cached mode (from an unsolicited message). Use that */ - MMCallbackInfo *info; - - info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->mode), NULL); - mm_callback_info_schedule (info); - } else { - /* Get it from modem */ - MMCallbackInfo *info; - MMSerialPort *primary; - - info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); - g_assert (primary); - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_network_mode_done, info); - } + info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); + primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); + g_assert (primary); + mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, get_allowed_mode_done, info); } static void @@ -293,7 +272,7 @@ set_band_get_done (MMSerialPort *port, int a, b, u1, u2; guint32 band; - if (parse_syscfg (self, response->str, &a, &b, &band, &u1, &u2)) { + if (parse_syscfg (self, response->str, &a, &b, &band, &u1, &u2, NULL)) { char *command; switch (GPOINTER_TO_UINT (mm_callback_info_get_data (info, "band"))) { @@ -370,7 +349,7 @@ get_band_done (MMSerialPort *port, if (error) info->error = g_error_copy (error); - else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2)) + else if (parse_syscfg (self, response->str, &mode_a, &mode_b, &band, &u1, &u2, NULL)) mm_callback_info_set_result (info, GUINT_TO_POINTER (priv->band), NULL); mm_callback_info_schedule (info); @@ -596,8 +575,6 @@ modem_init (MMModem *modem_class) static void modem_gsm_network_init (MMModemGsmNetwork *class) { - class->set_network_mode = set_network_mode; - class->get_network_mode = get_network_mode; class->set_band = set_band; class->get_band = get_band; class->get_signal_quality = get_signal_quality; @@ -612,8 +589,12 @@ static void mm_modem_huawei_gsm_class_init (MMModemHuaweiGsmClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass); mm_modem_huawei_gsm_parent_class = g_type_class_peek_parent (klass); g_type_class_add_private (object_class, sizeof (MMModemHuaweiGsmPrivate)); + + gsm_class->set_allowed_mode = set_allowed_mode; + gsm_class->get_allowed_mode = get_allowed_mode; } diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index 417457f7..72bd48a7 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -1,11 +1,13 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* - * Copyright (C) 2008 Ericsson AB + * Copyright (C) 2008 - 2010 Ericsson AB + * Copyright (C) 2009 - 2010 Red Hat, Inc. * * Author: Per Hallsmark * Bjorn Runaker * Torgny Johansson * Jonas Sjöquist + * Dan Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -170,14 +172,9 @@ mbm_parse_network_mode (MMModemGsmMode network_mode) case MM_MODEM_GSM_MODE_3G_PREFERRED: case MM_MODEM_GSM_MODE_2G_PREFERRED: return MBM_NETWORK_MODE_ANY; - case MM_MODEM_GSM_MODE_GPRS: - case MM_MODEM_GSM_MODE_EDGE: case MM_MODEM_GSM_MODE_2G_ONLY: return MBM_NETWORK_MODE_2G; case MM_MODEM_GSM_MODE_3G_ONLY: - case MM_MODEM_GSM_MODE_HSDPA: - case MM_MODEM_GSM_MODE_HSUPA: - case MM_MODEM_GSM_MODE_HSPA: return MBM_NETWORK_MODE_3G; default: return MBM_NETWORK_MODE_ANY; @@ -185,7 +182,7 @@ mbm_parse_network_mode (MMModemGsmMode network_mode) } static void -mbm_set_network_mode_done (MMSerialPort *port, +mbm_set_allowed_mode_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -199,7 +196,7 @@ mbm_set_network_mode_done (MMSerialPort *port, } static void -set_network_mode (MMModemGsmNetwork *modem, +set_allowed_mode (MMGenericGsm *gsm, MMModemGsmMode mode, MMModemFn callback, gpointer user_data) @@ -208,15 +205,16 @@ set_network_mode (MMModemGsmNetwork *modem, char *command; MMSerialPort *primary; - info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); + primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); command = g_strdup_printf ("+CFUN=%d", mbm_parse_network_mode (mode)); - mm_serial_port_queue_command (primary, command, 3, mbm_set_network_mode_done, info); + mm_serial_port_queue_command (primary, command, 3, mbm_set_allowed_mode_done, info); g_free (command); } +#if 0 static void get_network_mode_done (MMSerialPort *port, GString *response, @@ -266,19 +264,52 @@ done: mm_callback_info_schedule (info); } +#endif static void -get_network_mode (MMModemGsmNetwork *modem, +get_allowed_mode_done (MMSerialPort *port, + GString *response, + GError *error, + gpointer user_data) +{ + MMCallbackInfo *info = (MMCallbackInfo *) user_data; + gboolean parsed = FALSE; + + if (error) + info->error = g_error_copy (error); + else if (!g_str_has_prefix (response->str, "CFUN: ")) { + MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; + int a; + + a = atoi (response->str + 6); + if (a == MBM_NETWORK_MODE_2G) + mode = MM_MODEM_GSM_MODE_2G_ONLY; + else if (a == MBM_NETWORK_MODE_3G) + mode = MM_MODEM_GSM_MODE_3G_ONLY; + + mm_callback_info_set_result (info, GUINT_TO_POINTER (mode), NULL); + parsed = TRUE; + } + + if (!error && !parsed) + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Could not parse allowed mode results"); + + mm_callback_info_schedule (info); +} + +static void +get_allowed_mode (MMGenericGsm *gsm, MMModemUIntFn callback, gpointer user_data) { MMCallbackInfo *info; MMSerialPort *primary; - info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); + primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "*ERINFO?", 3, get_network_mode_done, info); + mm_serial_port_queue_command (primary, "CFUN?", 3, get_allowed_mode_done, info); } /*****************************************************************************/ @@ -782,8 +813,6 @@ static void modem_gsm_network_init (MMModemGsmNetwork *class) { class->do_register = do_register; - class->get_network_mode = get_network_mode; - class->set_network_mode = set_network_mode; } static void @@ -832,5 +861,7 @@ mm_modem_mbm_class_init (MMModemMbmClass *klass) object_class->finalize = finalize; gsm_class->do_enable = do_enable; + gsm_class->get_allowed_mode = get_allowed_mode; + gsm_class->set_allowed_mode = set_allowed_mode; } diff --git a/plugins/mm-modem-option.c b/plugins/mm-modem-option.c index 273cb95a..ddd947da 100644 --- a/plugins/mm-modem-option.c +++ b/plugins/mm-modem-option.c @@ -22,10 +22,7 @@ #include "mm-errors.h" #include "mm-callback-info.h" -static void modem_gsm_network_init (MMModemGsmNetwork *gsm_network_class); - -G_DEFINE_TYPE_EXTENDED (MMModemOption, mm_modem_option, MM_TYPE_GENERIC_GSM, 0, - G_IMPLEMENT_INTERFACE (MM_TYPE_MODEM_GSM_NETWORK, modem_gsm_network_init)) +G_DEFINE_TYPE (MMModemOption, mm_modem_option, MM_TYPE_GENERIC_GSM) #define MM_MODEM_OPTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_MODEM_OPTION, MMModemOptionPrivate)) @@ -90,7 +87,7 @@ real_do_enable_power_up_done (MMGenericGsm *gsm, } static void -get_network_mode_done (MMSerialPort *port, +get_allowed_mode_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -130,27 +127,27 @@ get_network_mode_done (MMSerialPort *port, if (!error && !parsed) info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, - "Could not parse network mode results"); + "Could not parse allowed mode results"); mm_callback_info_schedule (info); } static void -get_network_mode (MMModemGsmNetwork *modem, +get_allowed_mode (MMGenericGsm *gsm, MMModemUIntFn callback, gpointer user_data) { MMCallbackInfo *info; MMSerialPort *primary; - info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + info = mm_callback_info_uint_new (MM_MODEM (gsm), callback, user_data); + primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, "AT_OPSYS?", 3, get_network_mode_done, info); + mm_serial_port_queue_command (primary, "AT_OPSYS?", 3, get_allowed_mode_done, info); } static void -set_network_mode_done (MMSerialPort *port, +set_allowed_mode_done (MMSerialPort *port, GString *response, GError *error, gpointer user_data) @@ -159,12 +156,12 @@ set_network_mode_done (MMSerialPort *port, if (error) info->error = g_error_copy (error); - + mm_callback_info_schedule (info); } static void -set_network_mode (MMModemGsmNetwork *modem, +set_allowed_mode (MMGenericGsm *gsm, MMModemGsmMode mode, MMModemFn callback, gpointer user_data) @@ -174,19 +171,12 @@ set_network_mode (MMModemGsmNetwork *modem, char *command; int i; - info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); + info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); switch (mode) { - case MM_MODEM_GSM_MODE_ANY: - case MM_MODEM_GSM_MODE_GPRS: - case MM_MODEM_GSM_MODE_EDGE: case MM_MODEM_GSM_MODE_2G_ONLY: i = 0; break; - case MM_MODEM_GSM_MODE_UMTS: - case MM_MODEM_GSM_MODE_HSDPA: - case MM_MODEM_GSM_MODE_HSUPA: - case MM_MODEM_GSM_MODE_HSPA: case MM_MODEM_GSM_MODE_3G_ONLY: i = 1; break; @@ -196,27 +186,21 @@ set_network_mode (MMModemGsmNetwork *modem, case MM_MODEM_GSM_MODE_3G_PREFERRED: i = 3; break; + case MM_MODEM_GSM_MODE_ANY: default: i = 5; break; } command = g_strdup_printf ("AT_OPSYS=%d,2", i); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (modem), MM_PORT_TYPE_PRIMARY); + primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - mm_serial_port_queue_command (primary, command, 3, set_network_mode_done, info); + mm_serial_port_queue_command (primary, command, 3, set_allowed_mode_done, info); g_free (command); } /*****************************************************************************/ -static void -modem_gsm_network_init (MMModemGsmNetwork *class) -{ - class->set_network_mode = set_network_mode; - class->get_network_mode = get_network_mode; -} - static void mm_modem_option_init (MMModemOption *self) { @@ -242,5 +226,7 @@ mm_modem_option_class_init (MMModemOptionClass *klass) object_class->dispose = dispose; gsm_class->do_enable_power_up_done = real_do_enable_power_up_done; + gsm_class->set_allowed_mode = set_allowed_mode; + gsm_class->get_allowed_mode = get_allowed_mode; } diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index b28000c6..917a7621 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -56,6 +56,8 @@ typedef struct { guint32 pin_check_tries; guint pin_check_timeout; + guint32 allowed_mode; + char *oper_code; char *oper_name; guint32 ip_method; @@ -642,29 +644,43 @@ creg2_done (MMSerialPort *port, } } +static void +get_allowed_mode_done (MMModem *modem, + MMModemGsmMode mode, + GError *error, + gpointer user_data) +{ + if (modem) { + mm_generic_gsm_update_allowed_mode (MM_GENERIC_GSM (modem), + error ? MM_MODEM_GSM_MODE_UNKNOWN : mode); + } +} + void -mm_generic_gsm_enable_complete (MMGenericGsm *modem, +mm_generic_gsm_enable_complete (MMGenericGsm *self, 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 (self != NULL); + g_return_if_fail (MM_IS_GENERIC_GSM (self)); g_return_if_fail (info != NULL); if (error) { - mm_modem_set_state (MM_MODEM (modem), + mm_modem_set_state (MM_MODEM (self), MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_REASON_NONE); info->error = g_error_copy (error); + mm_callback_info_schedule (info); + return; } else { /* Modem is enabled; update the state */ - mm_generic_gsm_update_enabled_state (modem, FALSE, MM_MODEM_STATE_REASON_NONE); + mm_generic_gsm_update_enabled_state (self, FALSE, MM_MODEM_STATE_REASON_NONE); } - priv = MM_GENERIC_GSM_GET_PRIVATE (modem); + priv = MM_GENERIC_GSM_GET_PRIVATE (self); /* Open the second port here if the modem has one. We'll use it for * signal strength and registration updates when the device is connected, @@ -682,6 +698,11 @@ mm_generic_gsm_enable_complete (MMGenericGsm *modem, } } + /* Get allowed mode */ + if (MM_GENERIC_GSM_GET_CLASS (self)->get_allowed_mode) + MM_GENERIC_GSM_GET_CLASS (self)->get_allowed_mode (self, get_allowed_mode_done, NULL); + + /* Set up unsolicited registration notifications */ mm_serial_port_queue_command (priv->primary, "+CREG=2", 3, creg2_done, info); } @@ -2228,7 +2249,7 @@ mm_generic_gsm_update_access_technology (MMGenericGsm *modem, g_return_if_fail (modem != NULL); g_return_if_fail (MM_IS_GENERIC_GSM (modem)); - g_return_if_fail (check_for_single_value (mode) || (mode == MM_MODEM_GSM_MODE_HSPA)); + g_return_if_fail (check_for_single_value (mode)); g_return_if_fail ((mode & MM_MODEM_GSM_MODE_ANY) == 0); g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_PREFERRED) == 0); g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_PREFERRED) == 0); @@ -2242,7 +2263,63 @@ mm_generic_gsm_update_access_technology (MMGenericGsm *modem, g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); /* Deprecated value */ - g_signal_emit_by_name (G_OBJECT (modem), "NetworkMode", mode); + g_signal_emit_by_name (G_OBJECT (modem), "network-mode", mode); + } +} + +void +mm_generic_gsm_update_allowed_mode (MMGenericGsm *self, + MMModemGsmMode mode) +{ + MMGenericGsmPrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (MM_IS_GENERIC_GSM (self)); + + priv = MM_GENERIC_GSM_GET_PRIVATE (self); + + if (mode != priv->allowed_mode) { + priv->allowed_mode = mode; + g_object_notify (G_OBJECT (self), MM_MODEM_GSM_NETWORK_ALLOWED_MODE); + } +} + +static void +set_allowed_mode_done (MMModem *modem, GError *error, gpointer user_data) +{ + MMCallbackInfo *info = user_data; + + info->error = mm_modem_check_removed (info->modem, error); + if (!info->error) { + MMModemGsmMode mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode")); + + mm_generic_gsm_update_allowed_mode (MM_GENERIC_GSM (info->modem), mode); + } + + mm_callback_info_schedule (info); +} + +static void +set_allowed_mode (MMModemGsmNetwork *net, + MMModemGsmMode mode, + MMModemFn callback, + gpointer user_data) +{ + MMGenericGsm *self = MM_GENERIC_GSM (net); + MMCallbackInfo *info; + + info = mm_callback_info_new (MM_MODEM (self), callback, user_data); + + if (mode == MM_MODEM_GSM_MODE_UNKNOWN) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid mode."); + mm_callback_info_schedule (info); + } else if (!MM_GENERIC_GSM_GET_CLASS (self)->set_allowed_mode) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, + "Operation not supported"); + mm_callback_info_schedule (info); + } else { + mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); + MM_GENERIC_GSM_GET_CLASS (self)->set_allowed_mode (self, mode, set_allowed_mode_done, info); } } @@ -2593,6 +2670,7 @@ modem_gsm_network_init (MMModemGsmNetwork *class) { class->do_register = do_register; class->get_registration_info = get_registration_info; + class->set_allowed_mode = set_allowed_mode; class->set_apn = set_apn; class->scan = scan; class->get_signal_quality = get_signal_quality; @@ -2619,6 +2697,10 @@ mm_generic_gsm_init (MMGenericGsm *self) priv->access_tech = MM_MODEM_GSM_MODE_UNKNOWN; priv->reg_regex = mm_gsm_creg_regex_get (TRUE); + mm_properties_changed_signal_register_property (G_OBJECT (self), + MM_MODEM_GSM_NETWORK_ALLOWED_MODE, + MM_MODEM_GSM_NETWORK_DBUS_INTERFACE); + mm_properties_changed_signal_register_property (G_OBJECT (self), MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, MM_MODEM_GSM_NETWORK_DBUS_INTERFACE); @@ -2636,6 +2718,7 @@ set_property (GObject *object, guint prop_id, case MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL: case MM_GENERIC_GSM_PROP_SUPPORTED_BANDS: case MM_GENERIC_GSM_PROP_SUPPORTED_MODES: + case MM_GENERIC_GSM_PROP_ALLOWED_MODE: case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: break; default: @@ -2685,6 +2768,9 @@ get_property (GObject *object, guint prop_id, case MM_GENERIC_GSM_PROP_SUPPORTED_MODES: g_value_set_uint (value, 0); break; + case MM_GENERIC_GSM_PROP_ALLOWED_MODE: + g_value_set_uint (value, priv->allowed_mode); + break; case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: if (mm_modem_get_state (MM_MODEM (object)) >= MM_MODEM_STATE_ENABLED) g_value_set_uint (value, priv->access_tech); @@ -2753,6 +2839,10 @@ mm_generic_gsm_class_init (MMGenericGsmClass *klass) MM_GENERIC_GSM_PROP_SUPPORTED_MODES, MM_MODEM_GSM_CARD_SUPPORTED_MODES); + g_object_class_override_property (object_class, + MM_GENERIC_GSM_PROP_ALLOWED_MODE, + MM_MODEM_GSM_NETWORK_ALLOWED_MODE); + g_object_class_override_property (object_class, MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY, MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 477ec6b7..9b4c4848 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -44,6 +44,7 @@ typedef enum { MM_GENERIC_GSM_PROP_SUPPORTED_BANDS, MM_GENERIC_GSM_PROP_SUPPORTED_MODES, MM_GENERIC_GSM_PROP_INIT_CMD_OPTIONAL, + MM_GENERIC_GSM_PROP_ALLOWED_MODE, MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY } MMGenericGsmProp; @@ -78,6 +79,17 @@ typedef struct { GError *error, MMCallbackInfo *info); + /* Called by the generic class to set the allowed operating mode of the device */ + void (*set_allowed_mode) (MMGenericGsm *self, + MMModemGsmMode mode, + MMModemFn callback, + gpointer user_data); + + /* Called by the generic class to get the allowed operating mode of the device */ + void (*get_allowed_mode) (MMGenericGsm *self, + MMModemUIntFn callback, + gpointer user_data); + /* Called by the generic class to the current radio access technology the * device is using while communicating with the base station. */ @@ -105,6 +117,15 @@ guint32 mm_generic_gsm_get_cid (MMGenericGsm *modem); void mm_generic_gsm_set_reg_status (MMGenericGsm *modem, MMModemGsmNetworkRegStatus status); +/* Called to asynchronously update the current allowed operating mode that the + * device is allowed to use when connecting to a network. This isn't the + * specific access technology the device is currently using (see + * mm_generic_gsm_set_access_technology() for that) but the mode the device is + * allowed to choose from when connecting. + */ +void mm_generic_gsm_update_allowed_mode (MMGenericGsm *modem, + MMModemGsmMode mode); + /* Called to asynchronously update the current access technology of the device; * this is NOT the 2G/3G mode preference, but the current radio access * technology being used to communicate with the base station. diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index ca00decc..aae55574 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -43,12 +43,12 @@ static void impl_gsm_modem_set_band (MMModemGsmNetwork *modem, static void impl_gsm_modem_get_band (MMModemGsmNetwork *modem, DBusGMethodInvocation *context); -static void impl_gsm_modem_set_allowed_modes (MMModemGsmNetwork *modem, - MMModemGsmMode mode, - DBusGMethodInvocation *context); +static void impl_gsm_modem_set_allowed_mode (MMModemGsmNetwork *modem, + MMModemGsmMode mode, + DBusGMethodInvocation *context); static void impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, - MMModemGsmMode mode, + MMModemDeprecatedMode old_mode, DBusGMethodInvocation *context); static void impl_gsm_modem_get_network_mode (MMModemGsmNetwork *modem, @@ -371,34 +371,20 @@ mm_modem_gsm_network_get_band (MMModemGsmNetwork *self, } void -mm_modem_gsm_network_set_mode (MMModemGsmNetwork *self, - MMModemGsmMode mode, - MMModemFn callback, - gpointer user_data) +mm_modem_gsm_network_set_allowed_mode (MMModemGsmNetwork *self, + MMModemGsmMode mode, + MMModemFn callback, + gpointer user_data) { g_return_if_fail (MM_IS_MODEM_GSM_NETWORK (self)); g_return_if_fail (callback != NULL); - if (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)->set_network_mode) - MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)->set_network_mode (self, mode, callback, user_data); + if (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)->set_allowed_mode) + MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)->set_allowed_mode (self, mode, callback, user_data); else async_call_not_supported (self, callback, user_data); } -void -mm_modem_gsm_network_get_mode (MMModemGsmNetwork *self, - MMModemUIntFn callback, - gpointer user_data) -{ - g_return_if_fail (MM_IS_MODEM_GSM_NETWORK (self)); - g_return_if_fail (callback != NULL); - - if (MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)->get_network_mode) - MM_MODEM_GSM_NETWORK_GET_INTERFACE (self)->get_network_mode (self, callback, user_data); - else - uint_call_not_supported (self, callback, user_data); -} - void mm_modem_gsm_network_get_registration_info (MMModemGsmNetwork *self, MMModemGsmNetworkRegInfoFn callback, @@ -435,15 +421,6 @@ mm_modem_gsm_network_registration_info (MMModemGsmNetwork *self, oper_name ? oper_name : ""); } -void -mm_modem_gsm_network_mode (MMModemGsmNetwork *self, - MMModemGsmMode mode) -{ - g_return_if_fail (MM_IS_MODEM_GSM_NETWORK (self)); - - g_signal_emit (self, signals[NETWORK_MODE], 0, mode); -} - /*****************************************************************************/ static void @@ -558,15 +535,28 @@ impl_gsm_modem_get_band (MMModemGsmNetwork *modem, } static void -impl_gsm_modem_set_allowed_modes (MMModemGsmNetwork *modem, - MMModemGsmMode mode, - DBusGMethodInvocation *context) +impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, + MMModemDeprecatedMode old_mode, + DBusGMethodInvocation *context) { - dbus_g_method_return (context); + if (!check_for_single_value (old_mode)) { + GError *error; + + error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, + "Invalid arguments (more than one value given)"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + mm_modem_gsm_network_set_allowed_mode (modem, + mm_modem_gsm_network_old_mode_to_new (old_mode), + async_call_done, + context); } static void -impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, +impl_gsm_modem_set_allowed_mode (MMModemGsmNetwork *modem, MMModemGsmMode mode, DBusGMethodInvocation *context) { @@ -580,14 +570,20 @@ impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, return; } - mm_modem_gsm_network_set_mode (modem, mode, async_call_done, context); + mm_modem_gsm_network_set_allowed_mode (modem, mode, async_call_done, context); } static void impl_gsm_modem_get_network_mode (MMModemGsmNetwork *modem, DBusGMethodInvocation *context) { - mm_modem_gsm_network_get_mode (modem, uint_call_done, context); + MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; + + /* DEPRECATED; it's now a property so it's quite easy to handle */ + g_object_get (G_OBJECT (modem), + MM_MODEM_GSM_NETWORK_ALLOWED_MODE, &mode, + NULL); + dbus_g_method_return (context, mm_modem_gsm_network_new_mode_to_old (mode)); } static void @@ -608,6 +604,17 @@ mm_modem_gsm_network_init (gpointer g_iface) if (initialized) return; + /* Properties */ + g_object_interface_install_property + (g_iface, + g_param_spec_uint (MM_MODEM_GSM_NETWORK_ALLOWED_MODE, + "Allowed Mode", + "Allowed network access mode", + MM_MODEM_GSM_MODE_UNKNOWN, + G_MAXUINT32, + MM_MODEM_GSM_MODE_UNKNOWN, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_interface_install_property (g_iface, g_param_spec_uint (MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, @@ -615,7 +622,7 @@ mm_modem_gsm_network_init (gpointer g_iface) "Current access technology in use when connected to " "a mobile network.", MM_MODEM_GSM_MODE_UNKNOWN, - MM_MODEM_GSM_MODE_LAST, + G_MAXUINT32, MM_MODEM_GSM_MODE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); @@ -644,8 +651,7 @@ mm_modem_gsm_network_init (gpointer g_iface) g_signal_new ("network-mode", iface_type, G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (MMModemGsmNetwork, network_mode), - NULL, NULL, + 0, NULL, NULL, g_cclosure_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); diff --git a/src/mm-modem-gsm-network.h b/src/mm-modem-gsm-network.h index 3aa6ce30..bfd754ed 100644 --- a/src/mm-modem-gsm-network.h +++ b/src/mm-modem-gsm-network.h @@ -27,12 +27,14 @@ #define MM_IS_MODEM_GSM_NETWORK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_MODEM_GSM_NETWORK)) #define MM_MODEM_GSM_NETWORK_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_MODEM_GSM_NETWORK, MMModemGsmNetwork)) +#define MM_MODEM_GSM_NETWORK_ALLOWED_MODE "allowed-mode" #define MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY "access-technology" typedef enum { MM_MODEM_GSM_NETWORK_PROP_FIRST = 0x1200, - MM_MODEM_GSM_NETWORK_PROP_ACCESS_TECHNOLOGY = MM_MODEM_GSM_NETWORK_PROP_FIRST, + MM_MODEM_GSM_NETWORK_PROP_ALLOWED_MODE = MM_MODEM_GSM_NETWORK_PROP_FIRST, + MM_MODEM_GSM_NETWORK_PROP_ACCESS_TECHNOLOGY, } MMModemGsmNetworkProp; typedef enum { @@ -90,15 +92,11 @@ struct _MMModemGsmNetwork { MMModemUIntFn callback, gpointer user_data); - void (*set_network_mode) (MMModemGsmNetwork *self, + void (*set_allowed_mode) (MMModemGsmNetwork *self, MMModemGsmMode mode, MMModemFn callback, gpointer user_data); - void (*get_network_mode) (MMModemGsmNetwork *self, - MMModemUIntFn callback, - gpointer user_data); - void (*get_registration_info) (MMModemGsmNetwork *self, MMModemGsmNetworkRegInfoFn callback, gpointer user_data); @@ -111,9 +109,6 @@ struct _MMModemGsmNetwork { MMModemGsmNetworkRegStatus status, const char *open_code, const char *oper_name); - - void (*network_mode) (MMModemGsmNetwork *self, - MMModemGsmMode mode); }; GType mm_modem_gsm_network_get_type (void); @@ -163,14 +158,17 @@ void mm_modem_gsm_network_get_registration_info (MMModemGsmNetwork *self, void mm_modem_gsm_network_signal_quality (MMModemGsmNetwork *self, guint32 quality); +void mm_modem_gsm_network_set_allowed_mode (MMModemGsmNetwork *self, + MMModemGsmMode mode, + MMModemFn callback, + gpointer user_data); + void mm_modem_gsm_network_registration_info (MMModemGsmNetwork *self, MMModemGsmNetworkRegStatus status, const char *oper_code, const char *oper_name); -void mm_modem_gsm_network_mode (MMModemGsmNetwork *self, - MMModemGsmMode mode); - +/* Private */ MMModemDeprecatedMode mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode); MMModemGsmMode mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode); diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index 8f1155ec..e64f6804 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -32,8 +32,6 @@ typedef enum { MM_MODEM_GSM_MODE_HSPA = 0x00000400, MM_MODEM_GSM_MODE_GSM = 0x00000800, MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00001000, - - MM_MODEM_GSM_MODE_LAST = MM_MODEM_GSM_MODE_GSM_COMPACT } MMModemGsmMode; typedef enum { From c5a897d0ae1e4609cc2f9d3e127c1e50be9a84c1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 17:27:56 -0800 Subject: [PATCH 35/38] api+gsm: clean up AllowedMode values Instead of trying to stuff everything into the mode bitfield it turns out it's just easier, clearer, and simpler to use different values for each of the following: 1) the device's supported access technologies and allowed modes 2) the device's current access technology 3) the device's allowed mode preference Since none of the AccessTechnology or AllowedMode stuff has hit a release yet, let's make sure we're doing it the right way early on. --- introspection/mm-modem-gsm-network.xml | 16 ++++--- introspection/mm-modem-gsm.xml | 29 ++++++++++++- plugins/mm-modem-huawei-gsm.c | 58 ++++++++++---------------- plugins/mm-modem-mbm.c | 39 +++++++++++------ plugins/mm-modem-option.c | 22 +++++----- src/mm-generic-gsm.c | 42 ++++++++++++------- src/mm-generic-gsm.h | 4 +- src/mm-modem-gsm-network.c | 46 +++++++------------- src/mm-modem-gsm-network.h | 17 ++------ src/mm-modem-gsm.h | 10 +++++ 10 files changed, 153 insertions(+), 130 deletions(-) diff --git a/introspection/mm-modem-gsm-network.xml b/introspection/mm-modem-gsm-network.xml index 82eb177d..12fca5d9 100644 --- a/introspection/mm-modem-gsm-network.xml +++ b/introspection/mm-modem-gsm-network.xml @@ -128,26 +128,24 @@ - Set the allowed access technologies to use when connecting to a mobile - network. + Set the access technologies a device is allowed to use when connecting + to a mobile network. - + - The allowed access technologies. Only one mode flag may be specified, - and it may not be UNKNOWN. The device may not support all modes; see + The allowed mode. The device may not support all modes; see the org.freedesktop.ModemManager.Gsm.Card.SupportedModes property for allowed modes for each device. All devices support the "ANY" flag. - + - The allowed access technologies (eg 2G/3G preference or a specific access - technology) to use when connecting to a mobile network. (Note for plugin - writers: this value may be ANY) + The allowed access technologies (eg 2G/3G preference) the device is allowed + to use when connecting to a mobile network. diff --git a/introspection/mm-modem-gsm.xml b/introspection/mm-modem-gsm.xml index f5def8ac..15e378a6 100644 --- a/introspection/mm-modem-gsm.xml +++ b/introspection/mm-modem-gsm.xml @@ -5,8 +5,8 @@ A bitfield describing the specifc access modes and technologies - supported by a device, the device's current access mode preference, and - the access technology in-use when connected to a mobile network. + supported by a device and the access technology in-use when connected to + a mobile network. Unknown or invalid mode. @@ -98,5 +98,30 @@ WCDMA 3GPP UMTS 1700 MHz (Class IX) + + + + Describes the device's current access mode preference; ie the specific + technology preferences the device is allowed to use when connecting to + a mobile network. + + + Any mode can be used + + + Prefer 2G (GPRS or EDGE) + + + Prefer 3G (UMTS or HSxPA) + + + Use only 2G (GPRS or EDGE) + + + Use only 3G (UMTS or HSxPA) + + + + diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index 4594872b..12c4d894 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -68,24 +68,24 @@ parse_syscfg (MMModemHuaweiGsm *self, guint32 *band, int *unknown1, int *unknown2, - MMModemGsmMode *out_mode) + MMModemGsmAllowedMode *out_mode) { if (reply == NULL || strncmp (reply, "^SYSCFG:", 8)) return FALSE; if (sscanf (reply + 8, "%d,%d,%x,%d,%d", mode_a, mode_b, band, unknown1, unknown2)) { MMModemHuaweiGsmPrivate *priv = MM_MODEM_HUAWEI_GSM_GET_PRIVATE (self); - MMModemGsmMode new_mode = MM_MODEM_GSM_MODE_ANY; + MMModemGsmAllowedMode new_mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; /* Network mode */ if (*mode_a == 2 && *mode_b == 1) - new_mode = MM_MODEM_GSM_MODE_2G_PREFERRED; + new_mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; else if (*mode_a == 2 && *mode_b == 2) - new_mode = MM_MODEM_GSM_MODE_3G_PREFERRED; + new_mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; else if (*mode_a == 13 && *mode_b == 1) - new_mode = MM_MODEM_GSM_MODE_2G_ONLY; + new_mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; else if (*mode_a == 14 && *mode_b == 2) - new_mode = MM_MODEM_GSM_MODE_3G_ONLY; + new_mode = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY; if (out_mode) *out_mode = new_mode; @@ -134,26 +134,28 @@ set_allowed_mode_get_done (MMSerialPort *port, guint32 band; if (parse_syscfg (MM_MODEM_HUAWEI_GSM (info->modem), response->str, &a, &b, &band, &u1, &u2, NULL)) { + MMModemGsmAllowedMode mode; char *command; - switch (GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode"))) { - case MM_MODEM_GSM_MODE_ANY: + mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode")); + switch (mode) { + case MM_MODEM_GSM_ALLOWED_MODE_ANY: a = 2; b = 0; break; - case MM_MODEM_GSM_MODE_2G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: a = 13; b = 1; break; - case MM_MODEM_GSM_MODE_3G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: a = 14; b = 2; break; - case MM_MODEM_GSM_MODE_2G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: a = 2; b = 1; break; - case MM_MODEM_GSM_MODE_3G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: a = 2; b = 2; break; @@ -170,7 +172,7 @@ set_allowed_mode_get_done (MMSerialPort *port, static void set_allowed_mode (MMGenericGsm *gsm, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data) { @@ -179,28 +181,14 @@ set_allowed_mode (MMGenericGsm *gsm, info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); - switch (mode) { - case MM_MODEM_GSM_MODE_ANY: - case MM_MODEM_GSM_MODE_2G_PREFERRED: - case MM_MODEM_GSM_MODE_3G_PREFERRED: - case MM_MODEM_GSM_MODE_2G_ONLY: - case MM_MODEM_GSM_MODE_3G_ONLY: - /* Allowed values */ - mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); - primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (gsm), MM_PORT_TYPE_PRIMARY); - g_assert (primary); + mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); + primary = mm_generic_gsm_get_port (MM_GENERIC_GSM (gsm), MM_PORT_TYPE_PRIMARY); + g_assert (primary); - /* Get current configuration first so we don't change band and other - * stuff when updating the mode. - */ - mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_allowed_mode_get_done, info); - return; - default: - info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Unsupported allowed mode."); - break; - } - - mm_callback_info_schedule (info); + /* Get current configuration first so we don't change band and other + * stuff when updating the mode. + */ + mm_serial_port_queue_command (primary, "AT^SYSCFG?", 3, set_allowed_mode_get_done, info); } static void @@ -213,7 +201,7 @@ get_allowed_mode_done (MMSerialPort *port, MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (info->modem); int mode_a, mode_b, u1, u2; guint32 band; - MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; + MMModemGsmAllowedMode mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; if (error) info->error = g_error_copy (error); diff --git a/plugins/mm-modem-mbm.c b/plugins/mm-modem-mbm.c index 72bd48a7..ccf20d85 100644 --- a/plugins/mm-modem-mbm.c +++ b/plugins/mm-modem-mbm.c @@ -165,16 +165,16 @@ do_register (MMModemGsmNetwork *modem, } static int -mbm_parse_network_mode (MMModemGsmMode network_mode) +mbm_parse_allowed_mode (MMModemGsmAllowedMode network_mode) { switch (network_mode) { - case MM_MODEM_GSM_MODE_ANY: - case MM_MODEM_GSM_MODE_3G_PREFERRED: - case MM_MODEM_GSM_MODE_2G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_ANY: + case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: return MBM_NETWORK_MODE_ANY; - case MM_MODEM_GSM_MODE_2G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: return MBM_NETWORK_MODE_2G; - case MM_MODEM_GSM_MODE_3G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: return MBM_NETWORK_MODE_3G; default: return MBM_NETWORK_MODE_ANY; @@ -197,7 +197,7 @@ mbm_set_allowed_mode_done (MMSerialPort *port, static void set_allowed_mode (MMGenericGsm *gsm, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data) { @@ -209,7 +209,7 @@ set_allowed_mode (MMGenericGsm *gsm, primary = mm_generic_gsm_get_port (gsm, MM_PORT_TYPE_PRIMARY); g_assert (primary); - command = g_strdup_printf ("+CFUN=%d", mbm_parse_network_mode (mode)); + command = g_strdup_printf ("+CFUN=%d", mbm_parse_allowed_mode (mode)); mm_serial_port_queue_command (primary, command, 3, mbm_set_allowed_mode_done, info); g_free (command); } @@ -278,14 +278,14 @@ get_allowed_mode_done (MMSerialPort *port, if (error) info->error = g_error_copy (error); else if (!g_str_has_prefix (response->str, "CFUN: ")) { - MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; + MMModemGsmAllowedMode mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; int a; a = atoi (response->str + 6); if (a == MBM_NETWORK_MODE_2G) - mode = MM_MODEM_GSM_MODE_2G_ONLY; + mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; else if (a == MBM_NETWORK_MODE_3G) - mode = MM_MODEM_GSM_MODE_3G_ONLY; + mode = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY; mm_callback_info_set_result (info, GUINT_TO_POINTER (mode), NULL); parsed = TRUE; @@ -331,7 +331,22 @@ simple_connect (MMModemSimple *simple, priv->password = mbm_simple_get_string_property (properties, "password", &info->error); network_mode = mbm_simple_get_uint_property (properties, "network_mode", &info->error); - priv->network_mode = mbm_parse_network_mode (network_mode); + switch (network_mode) { + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY: + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED: + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED: + priv->network_mode = MBM_NETWORK_MODE_ANY; + break; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY: + priv->network_mode = MBM_NETWORK_MODE_2G; + break; + case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY: + priv->network_mode = MBM_NETWORK_MODE_3G; + break; + default: + priv->network_mode = MBM_NETWORK_MODE_ANY; + break; + } parent_iface = g_type_interface_peek_parent (MM_MODEM_SIMPLE_GET_INTERFACE (simple)); parent_iface->connect (MM_MODEM_SIMPLE (simple), properties, callback, info); diff --git a/plugins/mm-modem-option.c b/plugins/mm-modem-option.c index ddd947da..a7faf4d3 100644 --- a/plugins/mm-modem-option.c +++ b/plugins/mm-modem-option.c @@ -101,20 +101,20 @@ get_allowed_mode_done (MMSerialPort *port, int a, b; if (sscanf (response->str + 8, "%d,%d", &a, &b)) { - MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; + MMModemGsmAllowedMode mode = MM_MODEM_GSM_ALLOWED_MODE_ANY; switch (a) { case 0: - mode = MM_MODEM_GSM_MODE_2G_ONLY; + mode = MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; break; case 1: - mode = MM_MODEM_GSM_MODE_3G_ONLY; + mode = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY; break; case 2: - mode = MM_MODEM_GSM_MODE_2G_PREFERRED; + mode = MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; break; case 3: - mode = MM_MODEM_GSM_MODE_3G_PREFERRED; + mode = MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; break; default: break; @@ -162,7 +162,7 @@ set_allowed_mode_done (MMSerialPort *port, static void set_allowed_mode (MMGenericGsm *gsm, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data) { @@ -174,19 +174,19 @@ set_allowed_mode (MMGenericGsm *gsm, info = mm_callback_info_new (MM_MODEM (gsm), callback, user_data); switch (mode) { - case MM_MODEM_GSM_MODE_2G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: i = 0; break; - case MM_MODEM_GSM_MODE_3G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: i = 1; break; - case MM_MODEM_GSM_MODE_2G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: i = 2; break; - case MM_MODEM_GSM_MODE_3G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: i = 3; break; - case MM_MODEM_GSM_MODE_ANY: + case MM_MODEM_GSM_ALLOWED_MODE_ANY: default: i = 5; break; diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 917a7621..4b1b65bf 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -56,7 +56,7 @@ typedef struct { guint32 pin_check_tries; guint pin_check_timeout; - guint32 allowed_mode; + MMModemGsmAllowedMode allowed_mode; char *oper_code; char *oper_name; @@ -646,13 +646,13 @@ creg2_done (MMSerialPort *port, static void get_allowed_mode_done (MMModem *modem, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, GError *error, gpointer user_data) { if (modem) { mm_generic_gsm_update_allowed_mode (MM_GENERIC_GSM (modem), - error ? MM_MODEM_GSM_MODE_UNKNOWN : mode); + error ? MM_MODEM_GSM_ALLOWED_MODE_ANY : mode); } } @@ -2269,7 +2269,7 @@ mm_generic_gsm_update_access_technology (MMGenericGsm *modem, void mm_generic_gsm_update_allowed_mode (MMGenericGsm *self, - MMModemGsmMode mode) + MMModemGsmAllowedMode mode) { MMGenericGsmPrivate *priv; @@ -2291,7 +2291,7 @@ set_allowed_mode_done (MMModem *modem, GError *error, gpointer user_data) info->error = mm_modem_check_removed (info->modem, error); if (!info->error) { - MMModemGsmMode mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode")); + MMModemGsmAllowedMode mode = GPOINTER_TO_UINT (mm_callback_info_get_data (info, "mode")); mm_generic_gsm_update_allowed_mode (MM_GENERIC_GSM (info->modem), mode); } @@ -2301,7 +2301,7 @@ set_allowed_mode_done (MMModem *modem, GError *error, gpointer user_data) static void set_allowed_mode (MMModemGsmNetwork *net, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data) { @@ -2310,17 +2310,27 @@ set_allowed_mode (MMModemGsmNetwork *net, info = mm_callback_info_new (MM_MODEM (self), callback, user_data); - if (mode == MM_MODEM_GSM_MODE_UNKNOWN) { + switch (mode) { + case MM_MODEM_GSM_ALLOWED_MODE_ANY: + case MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED: + case MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY: + case MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY: + if (!MM_GENERIC_GSM_GET_CLASS (self)->set_allowed_mode) { + info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, + "Operation not supported"); + } else { + mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); + MM_GENERIC_GSM_GET_CLASS (self)->set_allowed_mode (self, mode, set_allowed_mode_done, info); + } + break; + default: info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, "Invalid mode."); - mm_callback_info_schedule (info); - } else if (!MM_GENERIC_GSM_GET_CLASS (self)->set_allowed_mode) { - info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_OPERATION_NOT_SUPPORTED, - "Operation not supported"); - mm_callback_info_schedule (info); - } else { - mm_callback_info_set_data (info, "mode", GUINT_TO_POINTER (mode), NULL); - MM_GENERIC_GSM_GET_CLASS (self)->set_allowed_mode (self, mode, set_allowed_mode_done, info); + break; } + + if (info->error) + mm_callback_info_schedule (info); } /*****************************************************************************/ @@ -2631,7 +2641,7 @@ simple_get_status (MMModemSimple *simple, if (priv->access_tech > -1) { /* Deprecated key */ - old_mode = mm_modem_gsm_network_new_mode_to_old (priv->access_tech); + old_mode = mm_modem_gsm_network_act_to_old_mode (priv->access_tech); g_hash_table_insert (properties, "network_mode", simple_uint_value (old_mode)); /* New key */ diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 9b4c4848..6fa86a59 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -81,7 +81,7 @@ typedef struct { /* Called by the generic class to set the allowed operating mode of the device */ void (*set_allowed_mode) (MMGenericGsm *self, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data); @@ -124,7 +124,7 @@ void mm_generic_gsm_set_reg_status (MMGenericGsm *modem, * allowed to choose from when connecting. */ void mm_generic_gsm_update_allowed_mode (MMGenericGsm *modem, - MMModemGsmMode mode); + MMModemGsmAllowedMode mode); /* Called to asynchronously update the current access technology of the device; * this is NOT the 2G/3G mode preference, but the current radio access diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index aae55574..72571c22 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -44,7 +44,7 @@ static void impl_gsm_modem_get_band (MMModemGsmNetwork *modem, DBusGMethodInvocation *context); static void impl_gsm_modem_set_allowed_mode (MMModemGsmNetwork *modem, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, DBusGMethodInvocation *context); static void impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, @@ -73,41 +73,27 @@ static guint signals[LAST_SIGNAL] = { 0 }; /*****************************************************************************/ -MMModemGsmMode -mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode) +MMModemGsmAllowedMode +mm_modem_gsm_network_old_mode_to_allowed (MMModemDeprecatedMode old_mode) { /* Translate deprecated mode into new mode */ switch (old_mode) { - case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS: - return MM_MODEM_GSM_MODE_GPRS; - case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE: - return MM_MODEM_GSM_MODE_EDGE; - case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS: - return MM_MODEM_GSM_MODE_UMTS; - case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA: - return MM_MODEM_GSM_MODE_HSDPA; case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED: - return MM_MODEM_GSM_MODE_2G_PREFERRED; + return MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED; case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED: - return MM_MODEM_GSM_MODE_3G_PREFERRED; + return MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED; case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY: - return MM_MODEM_GSM_MODE_2G_ONLY; + return MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY; case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY: - return MM_MODEM_GSM_MODE_3G_ONLY; - case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA: - return MM_MODEM_GSM_MODE_HSUPA; - case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA: - return MM_MODEM_GSM_MODE_HSDPA | MM_MODEM_GSM_MODE_HSUPA; + return MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY; case MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY: default: - break; + return MM_MODEM_GSM_ALLOWED_MODE_ANY; } - - return MM_MODEM_GSM_MODE_ANY; } MMModemDeprecatedMode -mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode) +mm_modem_gsm_network_act_to_old_mode (MMModemGsmMode new_mode) { /* Translate new mode into old deprecated mode */ if (new_mode & MM_MODEM_GSM_MODE_GPRS) @@ -372,7 +358,7 @@ mm_modem_gsm_network_get_band (MMModemGsmNetwork *self, void mm_modem_gsm_network_set_allowed_mode (MMModemGsmNetwork *self, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data) { @@ -550,14 +536,14 @@ impl_gsm_modem_set_network_mode (MMModemGsmNetwork *modem, } mm_modem_gsm_network_set_allowed_mode (modem, - mm_modem_gsm_network_old_mode_to_new (old_mode), + mm_modem_gsm_network_old_mode_to_allowed (old_mode), async_call_done, context); } static void impl_gsm_modem_set_allowed_mode (MMModemGsmNetwork *modem, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, DBusGMethodInvocation *context) { if (!check_for_single_value (mode)) { @@ -581,9 +567,9 @@ impl_gsm_modem_get_network_mode (MMModemGsmNetwork *modem, /* DEPRECATED; it's now a property so it's quite easy to handle */ g_object_get (G_OBJECT (modem), - MM_MODEM_GSM_NETWORK_ALLOWED_MODE, &mode, + MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, &mode, NULL); - dbus_g_method_return (context, mm_modem_gsm_network_new_mode_to_old (mode)); + dbus_g_method_return (context, mm_modem_gsm_network_act_to_old_mode (mode)); } static void @@ -610,8 +596,8 @@ mm_modem_gsm_network_init (gpointer g_iface) g_param_spec_uint (MM_MODEM_GSM_NETWORK_ALLOWED_MODE, "Allowed Mode", "Allowed network access mode", - MM_MODEM_GSM_MODE_UNKNOWN, - G_MAXUINT32, + MM_MODEM_GSM_ALLOWED_MODE_ANY, + MM_MODEM_GSM_ALLOWED_MODE_LAST, MM_MODEM_GSM_MODE_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); diff --git a/src/mm-modem-gsm-network.h b/src/mm-modem-gsm-network.h index bfd754ed..757d098b 100644 --- a/src/mm-modem-gsm-network.h +++ b/src/mm-modem-gsm-network.h @@ -93,7 +93,7 @@ struct _MMModemGsmNetwork { gpointer user_data); void (*set_allowed_mode) (MMModemGsmNetwork *self, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data); @@ -140,15 +140,6 @@ void mm_modem_gsm_network_get_band (MMModemGsmNetwork *self, MMModemUIntFn callback, gpointer user_data); -void mm_modem_gsm_network_set_mode (MMModemGsmNetwork *self, - MMModemGsmMode mode, - MMModemFn callback, - gpointer user_data); - -void mm_modem_gsm_network_get_mode (MMModemGsmNetwork *self, - MMModemUIntFn callback, - gpointer user_data); - void mm_modem_gsm_network_get_registration_info (MMModemGsmNetwork *self, MMModemGsmNetworkRegInfoFn callback, gpointer user_data); @@ -159,7 +150,7 @@ void mm_modem_gsm_network_signal_quality (MMModemGsmNetwork *self, guint32 quality); void mm_modem_gsm_network_set_allowed_mode (MMModemGsmNetwork *self, - MMModemGsmMode mode, + MMModemGsmAllowedMode mode, MMModemFn callback, gpointer user_data); @@ -169,8 +160,8 @@ void mm_modem_gsm_network_registration_info (MMModemGsmNetwork *self, const char *oper_name); /* Private */ -MMModemDeprecatedMode mm_modem_gsm_network_new_mode_to_old (MMModemGsmMode new_mode); +MMModemDeprecatedMode mm_modem_gsm_network_act_to_old_mode (MMModemGsmMode new_mode); -MMModemGsmMode mm_modem_gsm_network_old_mode_to_new (MMModemDeprecatedMode old_mode); +MMModemGsmAllowedMode mm_modem_gsm_network_old_mode_to_allowed (MMModemDeprecatedMode old_mode); #endif /* MM_MODEM_GSM_NETWORK_H */ diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index e64f6804..d10982b7 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -34,6 +34,16 @@ typedef enum { MM_MODEM_GSM_MODE_GSM_COMPACT = 0x00001000, } MMModemGsmMode; +typedef enum { + MM_MODEM_GSM_ALLOWED_MODE_ANY = 0, + MM_MODEM_GSM_ALLOWED_MODE_2G_PREFERRED = 1, + MM_MODEM_GSM_ALLOWED_MODE_3G_PREFERRED = 2, + MM_MODEM_GSM_ALLOWED_MODE_2G_ONLY = 3, + MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY = 4, + + MM_MODEM_GSM_ALLOWED_MODE_LAST = MM_MODEM_GSM_ALLOWED_MODE_3G_ONLY +} MMModemGsmAllowedMode; + typedef enum { MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, From cdf9279ee8cb52d13242dbfad0e8c07c6d7270f3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 18:02:14 -0800 Subject: [PATCH 36/38] api+gsm: split out access technology As with allowed modes, make things clearer and simpler by giving access technology it's own values. --- introspection/mm-modem-gsm-network.xml | 10 +-- introspection/mm-modem-gsm.xml | 34 +++++++++ plugins/mm-modem-huawei-gsm.c | 36 +++++----- src/mm-generic-gsm.c | 96 ++++++++++---------------- src/mm-generic-gsm.h | 2 +- src/mm-modem-gsm-network.c | 36 ++++------ src/mm-modem-gsm-network.h | 2 +- src/mm-modem-gsm.h | 39 +++++++---- 8 files changed, 140 insertions(+), 115 deletions(-) diff --git a/introspection/mm-modem-gsm-network.xml b/introspection/mm-modem-gsm-network.xml index 12fca5d9..2922b6c6 100644 --- a/introspection/mm-modem-gsm-network.xml +++ b/introspection/mm-modem-gsm-network.xml @@ -149,13 +149,11 @@ - + The current network access technology used by the device to communicate with the base station. (Note to plugin writers: if the device's access - technology cannot be determined, use UNKNOWN. Using any of the - PREFER flags or the ANY in this field is invalid as they are not a - specific access technology.) + technology cannot be determined, use UNKNOWN) @@ -235,6 +233,10 @@ + + DEPRECATED; should not be used in new applications. Use + AccessTechnology, AllowedMode, and SetAllowedMode() instead. + Any network mode can be used diff --git a/introspection/mm-modem-gsm.xml b/introspection/mm-modem-gsm.xml index 15e378a6..5b1560dd 100644 --- a/introspection/mm-modem-gsm.xml +++ b/introspection/mm-modem-gsm.xml @@ -122,6 +122,40 @@ + + + Describes various access technologies that a device uses when connected + to a mobile network. + + + The access technology used is unknown + + + GSM + + + Compact GSM + + + GPRS + + + EDGE (ETSI 27.007: "GSM w/EGPRS") + + + UMTS (ETSI 27.007: "UTRAN") + + + HSDPA (ETSI 27.007: "UTRAN w/HSDPA") + + + HSUPA (ETSI 27.007: "UTRAN w/HSUPA") + + + HSPA (ETSI 27.007: "UTRAN w/HSDPA and HSUPA") + + + diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index 12c4d894..2825d493 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -426,7 +426,7 @@ handle_mode_change (MMSerialPort *port, gpointer user_data) { MMModemHuaweiGsm *self = MM_MODEM_HUAWEI_GSM (user_data); - MMModemGsmMode new_mode = MM_MODEM_GSM_MODE_UNKNOWN; + MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; char *str; int a; int b; @@ -439,25 +439,29 @@ handle_mode_change (MMSerialPort *port, b = atoi (str); g_free (str); - if (a == 3 && b == 2) - new_mode = MM_MODEM_GSM_MODE_GPRS; - else if (a == 3 && b == 3) - new_mode = MM_MODEM_GSM_MODE_EDGE; - else if (a == 5 && b == 4) - new_mode = MM_MODEM_GSM_MODE_UMTS; - else if (a == 5 && b == 5) - new_mode = MM_MODEM_GSM_MODE_HSDPA; - else if (a == 5 && b == 6) - new_mode = MM_MODEM_GSM_MODE_HSUPA; - else if (a == 5 && b == 7) - new_mode = MM_MODEM_GSM_MODE_HSPA; - else { + if (a == 3) { /* GSM/GPRS mode */ + if (b == 1) + act = MM_MODEM_GSM_ACCESS_TECH_GSM; + else if (b == 2) + act = MM_MODEM_GSM_ACCESS_TECH_GPRS; + else if (b == 3) + act = MM_MODEM_GSM_ACCESS_TECH_EDGE; + } else if (a == 5) { /* WCDMA mode */ + if (b == 4) + act = MM_MODEM_GSM_ACCESS_TECH_UMTS; + else if (b == 5) + act = MM_MODEM_GSM_ACCESS_TECH_HSDPA; + else if (b == 6) + act = MM_MODEM_GSM_ACCESS_TECH_HSUPA; + else if (b == 7) + act = MM_MODEM_GSM_ACCESS_TECH_HSPA; + } else { g_warning ("Couldn't parse mode change value: '%s'", str); return; } - g_debug ("Access Technology: %d", new_mode); - mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), new_mode); + g_debug ("Access Technology: %d", act); + mm_generic_gsm_update_access_technology (MM_GENERIC_GSM (self), act); } static void diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 4b1b65bf..b2794e21 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -72,7 +72,7 @@ typedef struct { /* Index 0 for CREG, index 1 for CGREG */ gulong lac[2]; gulong cell_id[2]; - MMModemGsmMode access_tech; + MMModemGsmAccessTech act; MMModemGsmNetworkRegStatus reg_status; guint pending_reg_id; @@ -110,7 +110,7 @@ static gboolean handle_reg_status_response (MMGenericGsm *self, GString *response, GError **error); -static MMModemGsmMode etsi_act_to_mm_mode (gint act); +static MMModemGsmAccessTech etsi_act_to_mm_act (gint act); MMModem * mm_generic_gsm_new (const char *device, @@ -906,7 +906,7 @@ disable (MMModem *modem, priv->lac[1] = 0; priv->cell_id[0] = 0; priv->cell_id[1] = 0; - mm_generic_gsm_update_access_technology (self, MM_MODEM_GSM_MODE_UNKNOWN); + mm_generic_gsm_update_access_technology (self, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN); /* Close the secondary port if its open */ if (priv->secondary && mm_serial_port_is_open (priv->secondary)) @@ -1462,11 +1462,11 @@ reg_state_changed (MMSerialPort *port, MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); guint32 state = 0, idx; gulong lac = 0, cell_id = 0; - gint access_tech = -1; + gint act = -1; gboolean cgreg = FALSE; GError *error = NULL; - if (!mm_gsm_parse_creg_response (match_info, &state, &lac, &cell_id, &access_tech, &cgreg, &error)) { + if (!mm_gsm_parse_creg_response (match_info, &state, &lac, &cell_id, &act, &cgreg, &error)) { if (mm_options_debug ()) { g_warning ("%s: error parsing unsolicited registration: %s", __func__, @@ -1491,8 +1491,8 @@ reg_state_changed (MMSerialPort *port, priv->cell_id[idx] = cell_id; /* Only update access technology if it appeared in the CREG/CGREG response */ - if (access_tech != -1) - mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_mode (access_tech)); + if (act != -1) + mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_act (act)); } static gboolean @@ -1561,7 +1561,7 @@ handle_reg_status_response (MMGenericGsm *self, /* Only update access technology if it appeared in the CREG/CGREG response */ if (act != -1) - mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_mode (act)); + mm_generic_gsm_update_access_technology (self, etsi_act_to_mm_act (act)); if ((cgreg == FALSE) && status >= 0) { /* Update cached registration status */ @@ -2192,78 +2192,56 @@ get_signal_quality (MMModemGsmNetwork *modem, /*****************************************************************************/ typedef struct { - MMModemGsmMode mode; + MMModemGsmAccessTech mm_act; gint etsi_act; } ModeEtsi; static ModeEtsi modes_table[] = { - { MM_MODEM_GSM_MODE_GSM, 0 }, - { MM_MODEM_GSM_MODE_GSM_COMPACT, 1 }, - { MM_MODEM_GSM_MODE_UMTS, 2 }, - { MM_MODEM_GSM_MODE_EDGE, 3 }, - { MM_MODEM_GSM_MODE_HSDPA, 4 }, - { MM_MODEM_GSM_MODE_HSUPA, 5 }, - { MM_MODEM_GSM_MODE_HSDPA | - MM_MODEM_GSM_MODE_HSUPA, 6 }, - { MM_MODEM_GSM_MODE_HSDPA | - MM_MODEM_GSM_MODE_HSUPA, 7 }, /* E-UTRAN/LTE */ - { MM_MODEM_GSM_MODE_UNKNOWN, -1 }, + { MM_MODEM_GSM_ACCESS_TECH_GSM, 0 }, + { MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT, 1 }, + { MM_MODEM_GSM_ACCESS_TECH_UMTS, 2 }, + { MM_MODEM_GSM_ACCESS_TECH_EDGE, 3 }, + { MM_MODEM_GSM_ACCESS_TECH_HSDPA, 4 }, + { MM_MODEM_GSM_ACCESS_TECH_HSUPA, 5 }, + { MM_MODEM_GSM_ACCESS_TECH_HSPA, 6 }, + { MM_MODEM_GSM_ACCESS_TECH_HSPA, 7 }, /* E-UTRAN/LTE => HSPA for now */ + { MM_MODEM_GSM_ACCESS_TECH_UNKNOWN, -1 }, }; -static MMModemGsmMode -etsi_act_to_mm_mode (gint act) +static MMModemGsmAccessTech +etsi_act_to_mm_act (gint act) { ModeEtsi *iter = &modes_table[0]; - while (iter->mode != MM_MODEM_GSM_MODE_UNKNOWN) { + while (iter->mm_act != MM_MODEM_GSM_ACCESS_TECH_UNKNOWN) { if (iter->etsi_act == act) - return iter->mode; + return iter->mm_act; } - return MM_MODEM_GSM_MODE_UNKNOWN; -} - -static gboolean -check_for_single_value (guint32 value) -{ - gboolean found = FALSE; - guint32 i; - - for (i = 1; i <= 32; i++) { - if (value & 0x1) { - if (found) - return FALSE; /* More than one bit set */ - found = TRUE; - } - value >>= 1; - } - - return TRUE; + return MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; } void mm_generic_gsm_update_access_technology (MMGenericGsm *modem, - MMModemGsmMode mode) + MMModemGsmAccessTech act) { MMGenericGsmPrivate *priv; g_return_if_fail (modem != NULL); g_return_if_fail (MM_IS_GENERIC_GSM (modem)); - g_return_if_fail (check_for_single_value (mode)); - g_return_if_fail ((mode & MM_MODEM_GSM_MODE_ANY) == 0); - g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_PREFERRED) == 0); - g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_PREFERRED) == 0); - g_return_if_fail ((mode & MM_MODEM_GSM_MODE_2G_ONLY) == 0); - g_return_if_fail ((mode & MM_MODEM_GSM_MODE_3G_ONLY) == 0); + g_return_if_fail (act >= MM_MODEM_GSM_ACCESS_TECH_UNKNOWN && act <= MM_MODEM_GSM_ACCESS_TECH_LAST); priv = MM_GENERIC_GSM_GET_PRIVATE (modem); - if (mode != priv->access_tech) { - priv->access_tech = mode; + if (act != priv->act) { + MMModemDeprecatedMode old_mode; + + priv->act = act; g_object_notify (G_OBJECT (modem), MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY); /* Deprecated value */ - g_signal_emit_by_name (G_OBJECT (modem), "network-mode", mode); + old_mode = mm_modem_gsm_network_act_to_old_mode (act); + g_signal_emit_by_name (G_OBJECT (modem), "network-mode", old_mode); } } @@ -2639,13 +2617,13 @@ simple_get_status (MMModemSimple *simple, mm_modem_gsm_network_get_band (gsm, simple_status_got_band, properties); mm_modem_gsm_network_get_registration_info (gsm, simple_status_got_reg_info, properties); - if (priv->access_tech > -1) { + if (priv->act > -1) { /* Deprecated key */ - old_mode = mm_modem_gsm_network_act_to_old_mode (priv->access_tech); + old_mode = mm_modem_gsm_network_act_to_old_mode (priv->act); g_hash_table_insert (properties, "network_mode", simple_uint_value (old_mode)); /* New key */ - g_hash_table_insert (properties, "access_technology", simple_uint_value (priv->access_tech)); + g_hash_table_insert (properties, "access_technology", simple_uint_value (priv->act)); } } @@ -2704,7 +2682,7 @@ mm_generic_gsm_init (MMGenericGsm *self) { MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); - priv->access_tech = MM_MODEM_GSM_MODE_UNKNOWN; + priv->act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; priv->reg_regex = mm_gsm_creg_regex_get (TRUE); mm_properties_changed_signal_register_property (G_OBJECT (self), @@ -2783,9 +2761,9 @@ get_property (GObject *object, guint prop_id, break; case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: if (mm_modem_get_state (MM_MODEM (object)) >= MM_MODEM_STATE_ENABLED) - g_value_set_uint (value, priv->access_tech); + g_value_set_uint (value, priv->act); else - g_value_set_uint (value, MM_MODEM_GSM_MODE_UNKNOWN); + g_value_set_uint (value, MM_MODEM_GSM_ACCESS_TECH_UNKNOWN); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h index 6fa86a59..13c996be 100644 --- a/src/mm-generic-gsm.h +++ b/src/mm-generic-gsm.h @@ -131,7 +131,7 @@ void mm_generic_gsm_update_allowed_mode (MMGenericGsm *modem, * technology being used to communicate with the base station. */ void mm_generic_gsm_update_access_technology (MMGenericGsm *modem, - MMModemGsmMode mode); + MMModemGsmAccessTech act); void mm_generic_gsm_check_pin (MMGenericGsm *modem, MMModemFn callback, diff --git a/src/mm-modem-gsm-network.c b/src/mm-modem-gsm-network.c index 72571c22..7f7b655b 100644 --- a/src/mm-modem-gsm-network.c +++ b/src/mm-modem-gsm-network.c @@ -93,27 +93,21 @@ mm_modem_gsm_network_old_mode_to_allowed (MMModemDeprecatedMode old_mode) } MMModemDeprecatedMode -mm_modem_gsm_network_act_to_old_mode (MMModemGsmMode new_mode) +mm_modem_gsm_network_act_to_old_mode (MMModemGsmAccessTech act) { /* Translate new mode into old deprecated mode */ - if (new_mode & MM_MODEM_GSM_MODE_GPRS) + if (act & MM_MODEM_GSM_ACCESS_TECH_GPRS) return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS; - else if (new_mode & MM_MODEM_GSM_MODE_EDGE) + else if (act & MM_MODEM_GSM_ACCESS_TECH_EDGE) return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE; - else if (new_mode & MM_MODEM_GSM_MODE_UMTS) + else if (act & MM_MODEM_GSM_ACCESS_TECH_UMTS) return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS; - else if (new_mode & MM_MODEM_GSM_MODE_HSDPA) + else if (act & MM_MODEM_GSM_ACCESS_TECH_HSDPA) return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA; - else if (new_mode & MM_MODEM_GSM_MODE_2G_PREFERRED) - return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED; - else if (new_mode & MM_MODEM_GSM_MODE_3G_PREFERRED) - return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED; - else if (new_mode & MM_MODEM_GSM_MODE_2G_ONLY) - return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY; - else if (new_mode & MM_MODEM_GSM_MODE_3G_ONLY) - return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY; - else if (new_mode & MM_MODEM_GSM_MODE_HSUPA) + else if (act & MM_MODEM_GSM_ACCESS_TECH_HSUPA) return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA; + else if (act & MM_MODEM_GSM_ACCESS_TECH_HSPA) + return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA; return MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY; } @@ -563,13 +557,13 @@ static void impl_gsm_modem_get_network_mode (MMModemGsmNetwork *modem, DBusGMethodInvocation *context) { - MMModemGsmMode mode = MM_MODEM_GSM_MODE_ANY; + MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN; /* DEPRECATED; it's now a property so it's quite easy to handle */ g_object_get (G_OBJECT (modem), - MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, &mode, + MM_MODEM_GSM_NETWORK_ACCESS_TECHNOLOGY, &act, NULL); - dbus_g_method_return (context, mm_modem_gsm_network_act_to_old_mode (mode)); + dbus_g_method_return (context, mm_modem_gsm_network_act_to_old_mode (act)); } static void @@ -598,7 +592,7 @@ mm_modem_gsm_network_init (gpointer g_iface) "Allowed network access mode", MM_MODEM_GSM_ALLOWED_MODE_ANY, MM_MODEM_GSM_ALLOWED_MODE_LAST, - MM_MODEM_GSM_MODE_UNKNOWN, + MM_MODEM_GSM_ALLOWED_MODE_ANY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_interface_install_property @@ -607,9 +601,9 @@ mm_modem_gsm_network_init (gpointer g_iface) "Access Technology", "Current access technology in use when connected to " "a mobile network.", - MM_MODEM_GSM_MODE_UNKNOWN, - G_MAXUINT32, - MM_MODEM_GSM_MODE_UNKNOWN, + MM_MODEM_GSM_ACCESS_TECH_UNKNOWN, + MM_MODEM_GSM_ACCESS_TECH_LAST, + MM_MODEM_GSM_ACCESS_TECH_UNKNOWN, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /* Signals */ diff --git a/src/mm-modem-gsm-network.h b/src/mm-modem-gsm-network.h index 757d098b..a5157893 100644 --- a/src/mm-modem-gsm-network.h +++ b/src/mm-modem-gsm-network.h @@ -160,7 +160,7 @@ void mm_modem_gsm_network_registration_info (MMModemGsmNetwork *self, const char *oper_name); /* Private */ -MMModemDeprecatedMode mm_modem_gsm_network_act_to_old_mode (MMModemGsmMode new_mode); +MMModemDeprecatedMode mm_modem_gsm_network_act_to_old_mode (MMModemGsmAccessTech act); MMModemGsmAllowedMode mm_modem_gsm_network_old_mode_to_allowed (MMModemDeprecatedMode old_mode); diff --git a/src/mm-modem-gsm.h b/src/mm-modem-gsm.h index d10982b7..5f20b20d 100644 --- a/src/mm-modem-gsm.h +++ b/src/mm-modem-gsm.h @@ -45,18 +45,18 @@ typedef enum { } MMModemGsmAllowedMode; typedef enum { - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, - MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA -} MMModemDeprecatedMode; + MM_MODEM_GSM_ACCESS_TECH_UNKNOWN = 0, + MM_MODEM_GSM_ACCESS_TECH_GSM = 1, + MM_MODEM_GSM_ACCESS_TECH_GSM_COMPACT = 2, + MM_MODEM_GSM_ACCESS_TECH_GPRS = 3, + MM_MODEM_GSM_ACCESS_TECH_EDGE = 4, /* GSM w/EGPRS */ + MM_MODEM_GSM_ACCESS_TECH_UMTS = 5, /* UTRAN */ + MM_MODEM_GSM_ACCESS_TECH_HSDPA = 6, /* UTRAN w/HSDPA */ + MM_MODEM_GSM_ACCESS_TECH_HSUPA = 7, /* UTRAN w/HSUPA */ + MM_MODEM_GSM_ACCESS_TECH_HSPA = 8, /* UTRAN w/HSDPA and HSUPA */ + + MM_MODEM_GSM_ACCESS_TECH_LAST = MM_MODEM_GSM_ACCESS_TECH_HSPA +} MMModemGsmAccessTech; typedef enum { MM_MODEM_GSM_BAND_UNKNOWN = 0x00000000, @@ -77,5 +77,18 @@ typedef enum { } MMModemGsmBand; -#endif /* MM_MODEM_GSM_H */ +typedef enum { + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_ANY = 0, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_GPRS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_EDGE, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_UMTS, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSDPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_PREFERRED, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_2G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_3G_ONLY, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSUPA, + MM_MODEM_GSM_NETWORK_DEPRECATED_MODE_HSPA +} MMModemDeprecatedMode; +#endif /* MM_MODEM_GSM_H */ From 29a67e9d89f2f4538ae9b0e3e09db6d087b84f61 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 18:04:14 -0800 Subject: [PATCH 37/38] huawei: unify GSM device probing Using the USB product ID to direct certain modems to the generic driver is wrong since even new modems like the E1550 are 0x1001 after the modeswitch. Instead, lets assume that most current modes use the Huawei-specific AT command set. --- plugins/mm-plugin-huawei.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/plugins/mm-plugin-huawei.c b/plugins/mm-plugin-huawei.c index ad799f0a..96edc086 100644 --- a/plugins/mm-plugin-huawei.c +++ b/plugins/mm-plugin-huawei.c @@ -283,16 +283,9 @@ grab_port (MMPluginBase *base, caps = mm_plugin_base_supports_task_get_probed_capabilities (task); if (!existing) { if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) { - if (product == 0x1001) { - /* This modem is handled by generic GSM driver */ - modem = mm_generic_gsm_new (sysfs_path, - mm_plugin_base_supports_task_get_driver (task), - mm_plugin_get_name (MM_PLUGIN (base))); - } else { - modem = mm_modem_huawei_gsm_new (sysfs_path, - mm_plugin_base_supports_task_get_driver (task), - mm_plugin_get_name (MM_PLUGIN (base))); - } + modem = mm_modem_huawei_gsm_new (sysfs_path, + mm_plugin_base_supports_task_get_driver (task), + mm_plugin_get_name (MM_PLUGIN (base))); } else if (caps & CAP_CDMA) { modem = mm_modem_huawei_cdma_new (sysfs_path, mm_plugin_base_supports_task_get_driver (task), @@ -312,7 +305,7 @@ grab_port (MMPluginBase *base, MMPortType ptype = MM_PORT_TYPE_UNKNOWN; info = g_object_get_data (G_OBJECT (task), TAG_SUPPORTS_INFO); - if (info && info->secondary && (product != 0x1001)) + if (info && info->secondary) ptype = MM_PORT_TYPE_SECONDARY; modem = existing; From 9e231c3d4b463c32e17c7d2b1c50cea4e19d03ac Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 8 Mar 2010 18:06:10 -0800 Subject: [PATCH 38/38] huawei: attach unsolicited message handlers to the primary port too --- plugins/mm-modem-huawei-gsm.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/plugins/mm-modem-huawei-gsm.c b/plugins/mm-modem-huawei-gsm.c index 2825d493..67d27920 100644 --- a/plugins/mm-modem-huawei-gsm.c +++ b/plugins/mm-modem-huawei-gsm.c @@ -527,26 +527,25 @@ grab_port (MMModem *modem, port = mm_generic_gsm_grab_port (gsm, subsys, name, ptype, error); if (port && MM_IS_SERIAL_PORT (port)) { + GRegex *regex; + g_object_set (G_OBJECT (port), MM_PORT_CARRIER_DETECT, FALSE, NULL); - if (ptype == MM_PORT_TYPE_SECONDARY) { - GRegex *regex; - regex = g_regex_new ("\\r\\n\\^RSSI:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_signal_quality_change, modem, NULL); - g_regex_unref (regex); + regex = g_regex_new ("\\r\\n\\^RSSI:(\\d+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_signal_quality_change, modem, NULL); + g_regex_unref (regex); - regex = g_regex_new ("\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_mode_change, modem, NULL); - g_regex_unref (regex); + regex = g_regex_new ("\\r\\n\\^MODE:(\\d),(\\d)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_mode_change, modem, NULL); + g_regex_unref (regex); - regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_status_change, modem, NULL); - g_regex_unref (regex); + regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, handle_status_change, modem, NULL); + g_regex_unref (regex); - regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); - mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, modem, NULL); - g_regex_unref (regex); - } + regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL); + mm_serial_port_add_unsolicited_msg_handler (MM_SERIAL_PORT (port), regex, NULL, modem, NULL); + g_regex_unref (regex); } out: