Hey Eric, Some comments inline below.
On Wed, 2011-10-19 at 15:42 -0400, Eric Shienbrood wrote: > From b129d263ec1674462c218b4ec91260cf082bf77e Mon Sep 17 00:00:00 2001 > From: Eric Shienbrood <e...@google.com> > Date: Thu, 11 Aug 2011 13:58:59 -0400 > Subject: [PATCH] Added new property to track which facility locks are > enabled. > > The property EnabledFacilityLocks on the .Modem.Gsm.Card interface > is a bit mask that indicates which of the various personalization > codes from 3GPP TS 22.022, plus the SIM PIN lock and SIM PIN2 lock, > are enabled. The set of facility locks supported by the modem is > determined at the time the modem is initialized, and the state of > each supported lock (enabled or disabled) is determined. When the > state of a lock changes, a property-change signal is sent out. Note > that ModemManager only supports enabling and disabling SIM-PIN, via > the EnablePin method on Modem.Gsm.Card. Why is the new property in the Modem.Gsm.Card interface, and not in the Modem one (close to UnlockRequired and UnlockRetries). Same for the new MMModemGsmFacility flags, why not have them in the Modem interface. Some locks come from the card, but not all, so it's not really card-specific. Maybe there's some reason to have them split like that? For the new API, it would probably be a good idea to have the UnlockRequired property not return a string, and use new MMModemLockFacility enum/flags (equivalent to yours MMModemGsmFacility, not just GSM, or is this a GSM-only thing?). The same enum/flags would be the one used to identify enabled items in the EnabledFacilityLocks bitfield. > --- > ...org.freedesktop.ModemManager.Modem.Gsm.Card.xml | 6 + > .../org.freedesktop.ModemManager.Modem.Gsm.xml | 37 ++++- > src/mm-generic-gsm.c | 186 > +++++++++++++++++--- > src/mm-generic-gsm.h | 3 +- > src/mm-modem-gsm-card.c | 10 + > src/mm-modem-gsm-card.h | 3 + > src/mm-modem-helpers.c | 145 > +++++++++++++++ > src/mm-modem-helpers.h | 7 + > 8 files changed, 369 insertions(+), 28 deletions(-) > > diff --git > a/introspection/org.freedesktop.ModemManager.Modem.Gsm.Card.xml > b/introspection/org.freedesktop.ModemManager.Modem.Gsm.Card.xml > index 03c8a9f..9159052 100644 > --- a/introspection/org.freedesktop.ModemManager.Modem.Gsm.Card.xml > +++ b/introspection/org.freedesktop.ModemManager.Modem.Gsm.Card.xml > @@ -144,5 +144,11 @@ > </tp:docstring> > </property> > > + <property name="EnabledFacilityLocks" type="u" access="read" > tp:type="MM_MODEM_GSM_FACILITY"> > + <tp:docstring> > + Facilities for which PIN locking is enabled. > + </tp:docstring> > + </property> > + > </interface> > </node> > diff --git a/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml > b/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml > index 1abf915..354ce4a 100644 > --- a/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml > +++ b/introspection/org.freedesktop.ModemManager.Modem.Gsm.xml > @@ -4,7 +4,7 @@ > <interface name="org.freedesktop.ModemManager.Modem.Gsm"> > <tp:flags name="MM_MODEM_GSM_MODE" > value-prefix="MM_MODEM_GSM_MODE" type="u"> > <tp:docstring> > - A bitfield describing the specifc access modes and > technologies > + A bitfield describing the specific access modes and > technologies > supported by a device and the access technology in-use when > connected to > a mobile network. > </tp:docstring> > @@ -168,6 +168,41 @@ > </tp:enumvalue> > </tp:enum> > > + <tp:flags name="MM_MODEM_GSM_FACILITY" > value-prefix="MM_MODEM_GSM_FACILITY" type="u"> > + <tp:docstring> > + A bitfield describing which facilities have a lock enabled, > i.e., > + requires a pin or unlock code. The facilities include the > + personalizations (device locks) described in 3GPP spec TS > 22.022, > + and the PIN and PIN2 locks, which are SIM locks. > + </tp:docstring> > + <tp:flag suffix="NONE" value="0x0"> > + <tp:docstring>No facility</tp:docstring> > + </tp:flag> > + <tp:flag suffix="SIM" value="0x1"> > + <tp:docstring>SIM lock</tp:docstring> > + </tp:flag> > + <tp:flag suffix="FIXED_DIALING" value="0x2"> > + <tp:docstring>Fixed dialing (PIN2) SIM lock</tp:docstring> > + </tp:flag> > + <tp:flag suffix="PH_SIM" value="0x4"> > + <tp:docstring>Device is locked to a specific > SIM</tp:docstring> > + </tp:flag> > + <tp:flag suffix="PH_FSIM" value="0x8"> > + <tp:docstring>Device is locked to first SIM > inserted</tp:docstring> > + </tp:flag> > + <tp:flag suffix="NET_PERS" value="0x10"> > + <tp:docstring>Network personalization</tp:docstring> > + </tp:flag> > + <tp:flag suffix="NET_SUB_PERS" value="0x20"> > + <tp:docstring>Network subset personalization</tp:docstring> > + </tp:flag> > + <tp:flag suffix="PROVIDER_PERS" value="0x40"> > + <tp:docstring>Service provider personalization</tp:docstring> > + </tp:flag> > + <tp:flag suffix="CORP_PERS" value="0x80"> > + <tp:docstring>Corporate personalization</tp:docstring> > + </tp:flag> Are these all possibly facility locks that we may find? Or just the ones currently checked during the modem setup? The list of possible string replies in "UnlockRequired" has a longer list of values, so it may happen that we get a string in UnlockRequired without a direct enum value in MmModemGsmFacility. Is that desired? > + </tp:flags> > </interface> > </node> > > diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c > index 82dcf00..36490f4 100644 > --- a/src/mm-generic-gsm.c > +++ b/src/mm-generic-gsm.c > @@ -129,6 +129,13 @@ typedef struct { > > /* SMS */ > GHashTable *sms_present; > + > + /* Facility locks */ > + MMModemGsmFacility supported_facilities; > + MMModemGsmFacility enabled_facilities; > + MMModemGsmFacility pending_facility; > + gboolean pending_facility_enable; > + guint facilities_idx; > } MMGenericGsmPrivate; > > static void get_registration_status (MMAtSerialPort *port, > MMCallbackInfo *info); > @@ -799,6 +806,29 @@ initial_info_check (MMGenericGsm *self) > } > } > > +static void clck_cb (MMAtSerialPort *port, GString *response, GError > *error, gpointer user_data); > + > +static void > +initial_facility_lock_check (MMGenericGsm *self) { > + GError *error = NULL; > + MMGenericGsmPrivate *priv; > + > + g_return_if_fail (MM_IS_GENERIC_GSM (self)); > + priv = MM_GENERIC_GSM_GET_PRIVATE (self); > + > + g_return_if_fail (priv->primary != NULL); > + > + if (mm_serial_port_open (MM_SERIAL_PORT (priv->primary), &error)) > { > + mm_at_serial_port_queue_command (priv->primary, "+CLCK=?", 3, > clck_cb, self); > + } else { > + g_warning ("%s: failed to open serial port: (%d) %s", > + __func__, > + error ? error->code : -1, > + error && error->message ? error->message : > "(unknown)"); > + g_clear_error (&error); > + } > +} > + > static gboolean > owns_port (MMModem *modem, const char *subsys, const char *name) > { > @@ -872,6 +902,9 @@ mm_generic_gsm_grab_port (MMGenericGsm *self, > */ > initial_pin_check (self); > > + /* Determine what facility locks are supported */ > + initial_facility_lock_check (self); > + > } else if (ptype == MM_PORT_TYPE_SECONDARY) > priv->secondary = MM_AT_SERIAL_PORT (port); > } else if (MM_IS_QCDM_SERIAL_PORT (port)) { > @@ -1437,6 +1470,91 @@ cusd_enable_cb (MMAtSerialPort *port, > MM_GENERIC_GSM_GET_PRIVATE (user_data)->ussd_enabled = TRUE; > } > > +static void get_facility_lock_state (MMAtSerialPort *port, > MMGenericGsm *self); > + > +static void > +get_facility_lock_state_done (MMAtSerialPort *port, > + GString *response, > + GError *error, > + gpointer user_data) > +{ > + MMGenericGsm *self; > + MMGenericGsmPrivate *priv; > + gboolean enabled = FALSE; > + > + if (error) > + return; > + > + self = MM_GENERIC_GSM (user_data); > + priv = MM_GENERIC_GSM_GET_PRIVATE (self); > + > + if (mm_gsm_parse_clck_response (response->str, &enabled)) { > + if (enabled) > + priv->enabled_facilities |= priv->pending_facility; > + else > + priv->enabled_facilities &= ~priv->pending_facility; > + } > + priv->pending_facility = MM_MODEM_GSM_FACILITY_NONE; > + ++priv->facilities_idx; > + /* Get the state of the next facility */ > + get_facility_lock_state (port, self); > +} > + > +static void > +get_facility_lock_state (MMAtSerialPort *port, MMGenericGsm *self) > +{ > + MMModemGsmFacility found = MM_MODEM_GSM_FACILITY_NONE; > + gchar *cmd; > + MMGenericGsmPrivate *priv; > + gchar *facility_name; > + > + priv = MM_GENERIC_GSM_GET_PRIVATE (self); > + while (priv->facilities_idx < sizeof (MMModemGsmFacility)*8) { > + guint32 facility = 1 << priv->facilities_idx; > + if (priv->supported_facilities & facility) { > + found = facility; > + break; > + } > + ++priv->facilities_idx; > + } > + if (found != MM_MODEM_GSM_FACILITY_NONE) { > + facility_name = mm_gsm_get_facility_name (found); > + if (facility_name != NULL) { > + priv->pending_facility = found; > + cmd = g_strdup_printf ("+CLCK=\"%s\",2", facility_name); > + mm_at_serial_port_queue_command (port, cmd, 3, > get_facility_lock_state_done, self); > + g_free (cmd); > + return; > + } > + } > + mm_serial_port_close (MM_SERIAL_PORT (port)); > +} > + > +static void > +clck_cb (MMAtSerialPort *port, > + GString *response, > + GError *error, > + gpointer user_data) > +{ > + MMGenericGsm *self; > + MMGenericGsmPrivate *priv; > + MMModemGsmFacility facilities; > + > + if (error) > + return; > + > + self = MM_GENERIC_GSM (user_data); > + priv = MM_GENERIC_GSM_GET_PRIVATE (self); > + > + if (mm_gsm_parse_clck_test_response (response->str, &facilities)) > { > + priv->supported_facilities = facilities; > + priv->facilities_idx = 0; > + get_facility_lock_state (port, self); > + } else { > + mm_serial_port_close (MM_SERIAL_PORT (port)); > + } > +} So, first we query the currently supported locks, with AT+CLCK?; and then we go one by one checking its status. Instead of going one by one, waiting for a check to end to launch the next one, why not just port_queue_command() all AT+CLCK checks we need all together, and go filling-in the priv->enabled_facilities as we get replies of each command send? That would let us get rid of priv->facilities_idx, which is only used during this loop check. > + > void > mm_generic_gsm_enable_complete (MMGenericGsm *self, > GError *error, > @@ -2227,22 +2345,25 @@ pin_puk_recheck_done (MMModem *modem, GError > *error, gpointer user_data) > * if an incorrect PIN was supplied. Check also for a SIM_PUK > * error, which occurs if PIN retries has reached zero. */ > static void > -update_pin_puk_status(MMCallbackInfo *info, GError *error) > +update_pin_puk_status (MMModem *modem, GError *error) > { > + /* Hard-wire to SIM-PIN, because that's the only > + * lock that ChangePin and EnablePin are defined > + * to operate on */ > const char *pin_type = "sim-pin"; > > if (error) { > if (error->domain != MM_MOBILE_ERROR) > return; > if (error->code == MM_MOBILE_ERROR_SIM_PUK) { > - mm_modem_base_set_unlock_required (MM_MODEM_BASE > (info->modem), > + mm_modem_base_set_unlock_required (MM_MODEM_BASE (modem), > "sim-puk"); > pin_type = "sim-puk"; > } else if (error->code != MM_MOBILE_ERROR_WRONG_PASSWORD) { > return; > } > } > - mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD > (info->modem), > + mm_modem_gsm_card_get_unlock_retries (MM_MODEM_GSM_CARD (modem), > pin_type, > get_unlock_retries_cb, > NULL); > @@ -2386,19 +2507,36 @@ send_pin (MMModemGsmCard *modem, > } > > static void > -enable_pin_done (MMAtSerialPort *port, > +pin_operation_done (MMAtSerialPort *port, > GString *response, > GError *error, > gpointer user_data) Some extra whitespaces needed here to align the method members. > { > MMCallbackInfo *info = (MMCallbackInfo *) user_data; > + MMGenericGsmPrivate *priv; > + MMModem *modem; > > /* If the modem has already been removed, return without > * scheduling callback */ > if (mm_callback_info_check_modem_removed (info)) > return; > > - update_pin_puk_status(info, error); > + modem = info->modem; > + priv = MM_GENERIC_GSM_GET_PRIVATE (modem); > + if (!error) { > + if (priv->pending_facility != MM_MODEM_GSM_FACILITY_NONE) { > + MMModemGsmFacility old = priv->enabled_facilities; > + if (priv->pending_facility_enable) > + priv->enabled_facilities |= priv->pending_facility; > + else > + priv->enabled_facilities &= ~priv->pending_facility; > + if (priv->enabled_facilities != old) > + g_object_notify (G_OBJECT (modem), > + > MM_MODEM_GSM_CARD_ENABLED_FACILITY_LOCKS); > + } > + } > + priv->pending_facility = MM_MODEM_GSM_FACILITY_NONE; > + update_pin_puk_status (modem, error); > if (error) > info->error = g_error_copy (error); > mm_callback_info_schedule (info); > @@ -2417,30 +2555,13 @@ enable_pin (MMModemGsmCard *modem, > > info = mm_callback_info_new (MM_MODEM (modem), callback, > user_data); > command = g_strdup_printf ("+CLCK=\"SC\",%d,\"%s\"", enabled ? > 1 : 0, pin); > - mm_at_serial_port_queue_command (priv->primary, command, 3, > enable_pin_done, info); > + priv->pending_facility = MM_MODEM_GSM_FACILITY_SIM; > + priv->pending_facility_enable = enabled; > + mm_at_serial_port_queue_command (priv->primary, command, 3, > pin_operation_done, info); > g_free (command); > } priv->pending_facility and priv->pending_facility_enabled are just used here when we need to update the enabled facilities after a user request to enable/disable pin check. Instead of having them in MMGenericGsmPrivate, you can better associate both values with mm_callback_info_set_data() to the info passed in queue_command() and then use mm_callback_info_get_data() in the callback to get them back. > > static void > -change_pin_done (MMAtSerialPort *port, > - GString *response, > - GError *error, > - gpointer user_data) > -{ > - MMCallbackInfo *info = (MMCallbackInfo *) user_data; > - > - /* If the modem has already been removed, return without > - * scheduling callback */ > - if (mm_callback_info_check_modem_removed (info)) > - return; > - > - update_pin_puk_status(info, error); > - if (error) > - info->error = g_error_copy (error); > - mm_callback_info_schedule (info); > -} > - > -static void > change_pin (MMModemGsmCard *modem, > const char *old_pin, > const char *new_pin, > @@ -2453,7 +2574,7 @@ change_pin (MMModemGsmCard *modem, > > info = mm_callback_info_new (MM_MODEM (modem), callback, > user_data); > command = g_strdup_printf ("+CPWD=\"SC\",\"%s\",\"%s\"", old_pin, > new_pin); > - mm_at_serial_port_queue_command (priv->primary, command, 3, > change_pin_done, info); > + mm_at_serial_port_queue_command (priv->primary, command, 3, > pin_operation_done, info); > g_free (command); > } > > @@ -5622,6 +5743,11 @@ mm_generic_gsm_init (MMGenericGsm *self) > > MM_MODEM_GSM_NETWORK_DBUS_INTERFACE); > > mm_properties_changed_signal_register_property (G_OBJECT (self), > + > MM_MODEM_GSM_CARD_ENABLED_FACILITY_LOCKS, > + NULL, > + > MM_MODEM_GSM_CARD_DBUS_INTERFACE); > + > + mm_properties_changed_signal_register_property (G_OBJECT (self), > > MM_MODEM_LOCATION_CAPABILITIES, > "Capabilities", > > MM_MODEM_LOCATION_DBUS_INTERFACE); > @@ -5675,6 +5801,7 @@ set_property (GObject *object, guint prop_id, > case MM_GENERIC_GSM_PROP_ALLOWED_MODE: > case MM_GENERIC_GSM_PROP_ACCESS_TECHNOLOGY: > case MM_GENERIC_GSM_PROP_SIM_IDENTIFIER: > + case MM_GENERIC_GSM_PROP_ENABLED_FACILITY_LOCKS: > case MM_GENERIC_GSM_PROP_LOC_CAPABILITIES: > case MM_GENERIC_GSM_PROP_LOC_ENABLED: > case MM_GENERIC_GSM_PROP_LOC_SIGNAL: > @@ -5765,6 +5892,9 @@ get_property (GObject *object, guint prop_id, > case MM_GENERIC_GSM_PROP_SIM_IDENTIFIER: > g_value_set_string (value, priv->simid); > break; > + case MM_GENERIC_GSM_PROP_ENABLED_FACILITY_LOCKS: > + g_value_set_uint (value, priv->enabled_facilities); > + break; > case MM_GENERIC_GSM_PROP_LOC_CAPABILITIES: > g_value_set_uint (value, priv->loc_caps); > break; > @@ -5883,6 +6013,10 @@ mm_generic_gsm_class_init (MMGenericGsmClass > *klass) > > MM_MODEM_GSM_CARD_SUPPORTED_MODES); > > g_object_class_override_property (object_class, > + > MM_GENERIC_GSM_PROP_ENABLED_FACILITY_LOCKS, > + > MM_MODEM_GSM_CARD_ENABLED_FACILITY_LOCKS); > + > + g_object_class_override_property (object_class, > > MM_GENERIC_GSM_PROP_ALLOWED_MODE, > > MM_MODEM_GSM_NETWORK_ALLOWED_MODE); > > diff --git a/src/mm-generic-gsm.h b/src/mm-generic-gsm.h > index 7fba1f3..bbf7988 100644 > --- a/src/mm-generic-gsm.h > +++ b/src/mm-generic-gsm.h > @@ -64,7 +64,8 @@ typedef enum { > MM_GENERIC_GSM_PROP_FLOW_CONTROL_CMD, > MM_GENERIC_GSM_PROP_SMS_INDICATION_ENABLE_CMD, > MM_GENERIC_GSM_PROP_SMS_STORAGE_LOCATION_CMD, > - MM_GENERIC_GSM_PROP_CMER_ENABLE_CMD > + MM_GENERIC_GSM_PROP_CMER_ENABLE_CMD, > + MM_GENERIC_GSM_PROP_ENABLED_FACILITY_LOCKS > } MMGenericGsmProp; > > typedef enum { > diff --git a/src/mm-modem-gsm-card.c b/src/mm-modem-gsm-card.c > index 9b1fd77..8c4cf1c 100644 > --- a/src/mm-modem-gsm-card.c > +++ b/src/mm-modem-gsm-card.c > @@ -661,6 +661,16 @@ mm_modem_gsm_card_init (gpointer g_iface) > 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_CARD_ENABLED_FACILITY_LOCKS, > + "Enabled Facility Locks", > + "Facility locks (i.e. PINs) that are > enabled", > + MM_MODEM_GSM_FACILITY_NONE, > + G_MAXUINT32, > + MM_MODEM_GSM_FACILITY_NONE, > + G_PARAM_READWRITE | > G_PARAM_CONSTRUCT_ONLY)); > } > > GType > diff --git a/src/mm-modem-gsm-card.h b/src/mm-modem-gsm-card.h > index 9716bf7..bee9000 100644 > --- a/src/mm-modem-gsm-card.h > +++ b/src/mm-modem-gsm-card.h > @@ -19,6 +19,8 @@ > > #include <mm-modem.h> > > +#define MM_MODEM_GSM_CARD_DBUS_INTERFACE > "org.freedesktop.ModemManager.Modem.Gsm.Card" > + You can use the MM_DBUS_INTERFACE_MODEM_GSM_CARD from ModemManager.h, instead of defining a new one. I see other files defining custom symbols for the DBus Interface paths, but that shouldn't be needed as they are already in the autogenerated ModemManager.h. Not a big deal, will get this changed in the port to the new API. > #define MM_TYPE_MODEM_GSM_CARD (mm_modem_gsm_card_get_type ()) > #define MM_MODEM_GSM_CARD(obj) (G_TYPE_CHECK_INSTANCE_CAST > ((obj), MM_TYPE_MODEM_GSM_CARD, MMModemGsmCard)) > #define MM_IS_MODEM_GSM_CARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE > ((obj), MM_TYPE_MODEM_GSM_CARD)) > @@ -27,6 +29,7 @@ > #define MM_MODEM_GSM_CARD_SUPPORTED_BANDS "supported-bands" > #define MM_MODEM_GSM_CARD_SUPPORTED_MODES "supported-modes" > #define MM_MODEM_GSM_CARD_SIM_IDENTIFIER "sim-identifier" > +#define MM_MODEM_GSM_CARD_ENABLED_FACILITY_LOCKS > "enabled-facility-locks" > > #define MM_MODEM_GSM_CARD_SIM_PIN "sim-pin" > #define MM_MODEM_GSM_CARD_SIM_PIN2 "sim-pin2" > diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c > index 66c3fb6..652aadb 100644 > --- a/src/mm-modem-helpers.c > +++ b/src/mm-modem-helpers.c > @@ -788,6 +788,151 @@ mm_gsm_parse_cscs_support_response (const char > *reply, > > /*************************************************************************/ > > +/* Map two letter facility codes into flag values. There are > + * many more facilities defined (for various flavors of call > + * barring); we only map the ones we care about. */ > +static MMModemGsmFacility > +mm_gsm_string_to_facility (const char *string) > +{ > + g_return_val_if_fail (string != NULL, > MM_MODEM_GSM_FACILITY_NONE); > + > + if (!strcmp(string, "SC")) > + return MM_MODEM_GSM_FACILITY_SIM; > + else if (!strcmp(string, "PS")) > + return MM_MODEM_GSM_FACILITY_PH_SIM; > + else if (!strcmp(string, "PF")) > + return MM_MODEM_GSM_FACILITY_PH_FSIM; > + else if (!strcmp(string, "FD")) > + return MM_MODEM_GSM_FACILITY_FIXED_DIALING; > + else if (!strcmp(string, "PN")) > + return MM_MODEM_GSM_FACILITY_NET_PERS; > + else if (!strcmp(string, "PU")) > + return MM_MODEM_GSM_FACILITY_NET_SUB_PERS; > + else if (!strcmp(string, "PP")) > + return MM_MODEM_GSM_FACILITY_PROVIDER_PERS; > + else if (!strcmp(string, "PC")) > + return MM_MODEM_GSM_FACILITY_CORP_PERS; > + else > + return MM_MODEM_GSM_FACILITY_NONE; > + > +} > + > +/*************************************************************************/ > + > +char * > +mm_gsm_get_facility_name(MMModemGsmFacility facility) > +{ > + switch (facility) { > + case MM_MODEM_GSM_FACILITY_SIM: > + return "SC"; > + case MM_MODEM_GSM_FACILITY_PH_SIM: > + return "PS"; > + case MM_MODEM_GSM_FACILITY_PH_FSIM: > + return "PF"; > + case MM_MODEM_GSM_FACILITY_FIXED_DIALING: > + return "FD"; > + case MM_MODEM_GSM_FACILITY_NET_PERS: > + return "PN"; > + case MM_MODEM_GSM_FACILITY_NET_SUB_PERS: > + return "PU"; > + case MM_MODEM_GSM_FACILITY_PROVIDER_PERS: > + return "PP"; > + case MM_MODEM_GSM_FACILITY_CORP_PERS: > + return "PC"; > + default: > + return NULL; > + } > +} > + > +gboolean > +mm_gsm_parse_clck_test_response (const char *reply, > + MMModemGsmFacility *out_facilities) > +{ > + MMModemGsmFacility facilities = MM_MODEM_GSM_FACILITY_NONE; > + GRegex *r; > + GMatchInfo *match_info; > + char *p, *str; > + gboolean success = FALSE; > + > + g_return_val_if_fail (reply != NULL, FALSE); > + g_return_val_if_fail (out_facilities != NULL, FALSE); > + > + /* the general format is: > + * > + * +CLCK: ("SC","AO","AI","PN") > + */ > + p = strchr (reply, '('); > + if (p) > + p++; > + else { > + p = strchr (reply, '"'); > + if (!p) > + return FALSE; > + } > + > + /* Now parse each facility */ > + r = g_regex_new ("\\s*\"([^,\\)]+)\"\\s*", 0, 0, NULL); > + if (!r) > + return FALSE; > + > + if (g_regex_match_full (r, p, strlen (p), 0, 0, &match_info, > NULL)) { > + while (g_match_info_matches (match_info)) { > + str = g_match_info_fetch (match_info, 1); > + if (str) > + facilities |= mm_gsm_string_to_facility (str); > + g_free (str); > + > + g_match_info_next (match_info, NULL); > + success = TRUE; > + } > + } > + g_match_info_free (match_info); > + g_regex_unref (r); > + > + if (success) > + *out_facilities = facilities; > + > + return success; > +} > + > +gboolean > +mm_gsm_parse_clck_response (const char *reply, gboolean *enabled) > +{ > + GRegex *r; > + GMatchInfo *match_info; > + char *p, *str; > + gboolean success = FALSE; > + > + g_return_val_if_fail (reply != NULL, FALSE); > + g_return_val_if_fail (enabled != NULL, FALSE); > + > + p = strchr (reply, ':'); > + if (p) > + p++; > + > + r = g_regex_new ("\\s*([01])\\s*", 0, 0, NULL); > + if (!r) > + return FALSE; > + > + if (g_regex_match (r, p, 0, &match_info)) { > + success = TRUE; > + str = g_match_info_fetch (match_info, 1); > + if (str) { > + if (*str == '0') > + *enabled = FALSE; > + else if (*str == '1') > + *enabled = TRUE; > + else > + success = FALSE; > + } > + } > + g_match_info_free (match_info); > + g_regex_unref (r); > + return success; > +} > + > +/*************************************************************************/ > + > MMModemGsmAccessTech > mm_gsm_string_to_access_tech (const char *string) > { > diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h > index a47f469..8a98672 100644 > --- a/src/mm-modem-helpers.h > +++ b/src/mm-modem-helpers.h > @@ -58,6 +58,13 @@ gboolean mm_cdma_parse_eri (const char *reply, > gboolean mm_gsm_parse_cscs_support_response (const char *reply, > MMModemCharset > *out_charsets); > > +gboolean mm_gsm_parse_clck_test_response (const char *reply, > + MMModemGsmFacility > *out_facilities); > +gboolean mm_gsm_parse_clck_response (const char *reply, > + gboolean *enabled); > + > +char *mm_gsm_get_facility_name(MMModemGsmFacility facility); > + > MMModemGsmAccessTech mm_gsm_string_to_access_tech (const char > *string); > > char *mm_create_device_identifier (guint vid, > -- > 1.7.3.1 -- Aleksander _______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org http://mail.gnome.org/mailman/listinfo/networkmanager-list