diff options
author | Dan Williams <dcbw@redhat.com> | 2010-03-11 13:43:06 -0800 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2010-03-11 13:43:06 -0800 |
commit | 3ec7e89f112cb65a584de84b76e207d7a804bd6f (patch) | |
tree | 19c7f6e104fedbacb3cca281a2198dd56e41643a | |
parent | 479937cbbba560c77ec37ebf6468fe0e568986bd (diff) | |
parent | 749f9c0eb569b29772dde9561b9856e4f878d9ef (diff) |
Merge remote branch 'origin/master' into qcdm
-rw-r--r-- | introspection/mm-modem-gsm-network.xml | 47 | ||||
-rw-r--r-- | introspection/mm-modem-location.xml | 112 | ||||
-rw-r--r-- | src/mm-generic-gsm.c | 40 | ||||
-rw-r--r-- | src/mm-plugin-base.c | 55 | ||||
-rw-r--r-- | src/mm-serial-port.c | 27 | ||||
-rw-r--r-- | src/mm-serial-port.h | 4 |
6 files changed, 246 insertions, 39 deletions
diff --git a/introspection/mm-modem-gsm-network.xml b/introspection/mm-modem-gsm-network.xml index 2922b6c6..dd4d1cf7 100644 --- a/introspection/mm-modem-gsm-network.xml +++ b/introspection/mm-modem-gsm-network.xml @@ -118,10 +118,30 @@ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_gsm_modem_get_reg_info"/> <arg name="info" type="(uss)" direction="out"> <tp:docstring> - The returned information contains: - * Network status. - * Current operator code. - * Current operator name, + The returned information is composed of the following items in the + following order: + <ul> + <li> + Mobile registration status as defined in 3GPP TS 27.007 section + 10.1.19. See the MM_MODEM_GSM_NETWORK_REG_STATUS enumeration for + possible values. + </li> + <li> + Current operator code of the operator to which the mobile is + currently registered. Returned in the format "MCCMNC", where MCC + is the three-digit ITU E.212 Mobile Country Code and MNC is the + two- or three-digit GSM Mobile Network Code. If the MCC and MNC + are not known or the mobile is not registered to a mobile network, + this value should be a zero-length (blank) string. e.g. "31026" + or "310260". + </li> + <li> + Current operator name of the operator to which the mobile is + currently registered. If the operator name is not knowon or the + mobile is not registered to a mobile network, this value should + be a zero-length (blank) string. + </li> + </ul> </tp:docstring> </arg> </method> @@ -174,17 +194,27 @@ </tp:docstring> <arg name="status" type="u" tp:type="MM_MODEM_GSM_NETWORK_REG_STATUS"> <tp:docstring> - The network status. + Mobile registration status as defined in 3GPP TS 27.007 section + 10.1.19. </tp:docstring> </arg> <arg name="operator_code" type="s"> <tp:docstring> - The current operator code. + Current operator code of the operator to which the mobile is + currently registered. Returned in the format "MCCMNC", where MCC + is the three-digit ITU E.212 Mobile Country Code and MNC is the + two- or three-digit GSM Mobile Network Code. If the MCC and MNC + are not known or the mobile is not registered to a mobile network, + this value should be a zero-length (blank) string. e.g. "31026" or + "310260". </tp:docstring> </arg> <arg name="operator_name" type="s"> <tp:docstring> - The current operator name. + Current operator name of the operator to which the mobile is + currently registered. If the operator name is not knowon or the + mobile is not registered to a mobile network, this value should + be a zero-length (blank) string. </tp:docstring> </arg> </signal> @@ -200,6 +230,9 @@ </signal> <tp:enum name="MM_MODEM_GSM_NETWORK_REG_STATUS" type="u"> + <tp:docstring> + GSM registration code as defined in 3GPP TS 27.007 section 10.1.19. + </tp:docstring> <tp:enumvalue suffix="IDLE" value="0"> <tp:docstring> Not registered, not searching for new operator to register. diff --git a/introspection/mm-modem-location.xml b/introspection/mm-modem-location.xml index dfcf9dee..9d3b265e 100644 --- a/introspection/mm-modem-location.xml +++ b/introspection/mm-modem-location.xml @@ -26,7 +26,9 @@ <method name="Enable"> <tp:docstring> Enable or disable location information gathering. This method may - require the client to authenticate itself. + require the client to authenticate itself. This method may also cause + any necessary functionality of the mobile be be turned on, including + enabling the modem device itself. </tp:docstring> <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_modem_location_enable"/> @@ -92,28 +94,116 @@ </tp:docstring> <tp:member type="u" name="Type" tp:type="MM_MODEM_LOCATION_CAPABILITIES"> <tp:docstring> - 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. + 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. </tp:docstring> </tp:member> <tp:member type="v" name="Data"> <tp:docstring> - 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. + Contains type-specific location information. See the documentation for + each type for a description of its data format. </tp:docstring> </tp:member> </tp:mapping> <tp:flags name="MM_MODEM_LOCATION_CAPABILITIES" value-prefix="MM_MODEM_LOCATION_CAPABILITY" type="u"> <tp:flag suffix="UNKNOWN" value="0x0"> - <tp:docstring>Unknown or no capabilties.</tp:docstring> + <tp:docstring><p>Unknown or no capabilties.</p></tp:docstring> </tp:flag> - <tp:flag suffix="ANY" value="0x1"> - <tp:docstring>Reserved.</tp:docstring> - </tp:flag> - <tp:flag suffix="GPS_NMEA" value="0x2"> - <tp:docstring>The device is capable of providing GPS NMEA-format location information.</tp:docstring> + <tp:flag suffix="GPS_NMEA" value="0x1"> + <tp:docstring> + <p>For capability reporting, indicates the device is capable of + providing GPS NMEA-format location information.</p> + + <p>For location reporting, devices supporting this capability return + an array mapping timestamps to specific NMEA sentences (D-Bus + signature 'a(ss)'). The manager will cache the most recent NMEA + sentence of each type for a period of time not less than 30 seconds + and must indicate the time that sentence was receieved from the device + using the timestamp. Timestamps are provided as strings in the "Unix + epoch" format (i.e. number of seconds since 1970-01-01 00:00:00 UTC + with microsecond resolution if available). + </p> + <p> + For example, if at time 1268336242.282202 the device sends a $GPRMC + sentence immediately followed by a $GPGGA sentence, the reported + location array would be: + <pre> + [ '1268336242.282202': '$GPRMC,134523.92,V,,,,,,,030136,,,N*73', + '1268336242.282202': '$GPGGA,,,,,,0,00,0.5,,M,0.0001999,M,0.0000099,0000*45' ] + </pre> + If the device sends a new $GPRMC three seconds later, the new $GPRMC + replaces the previously received $GPRMC sentence, and the updated array + would be: + <pre> + [ '1268336245.282202': '$GPRMC,134526.92,V,,,,,,,030136,,,N*76', + '1268336242.282202': '$GPGGA,,,,,,0,00,0.5,,M,0.0001999,M,0.0000099,0000*45' ] + </pre> + If the device then sends a $GPGSA sentence about 5 seconds later, the + $GPGSA sentence is added to the array (since no $GPGSA sentence was + previously received in this session), the updated array would be: + <pre> + [ '1268336245.282202': '$GPRMC,134526.92,V,,,,,,,030136,,,N*76', + '1268336242.282202': '$GPGGA,,,,,,0,00,0.5,,M,0.0001999,M,0.0000099,0000*45' + '1268336250.395423': '$GPGSA,A,1,,,,,,,,,,,,,1.1,0.5,1.0*34' ] + </pre> + The manager may discard any entries older than 30 seconds. + </p> + <p>This allows clients to read the latest positioning data as soon as + possible after they start, even if the device is not providing + frequent location data updates. Using the timestamp the client can + determine which data is most relevant to its particular uses. + </p> + </tp:docstring> </tp:flag> - <tp:flag suffix="GSM_LAC_CI" value="0x4"> - <tp:docstring>The device is capable of providing GSM Location Area Code/Cell ID location information.</tp:docstring> + <tp:flag suffix="GSM_LAC_CI" value="0x2"> + <tp:docstring> + <p>For capability reporting, indicates the device is capable of + providing GSM Location Area Code/Cell ID location information.</p> + + <p>For location reporting, devices supporting this + capability return a string in the format "MCC,MNC,LAC,CI" (without the + quotes of course) where the following applies:</p> + <ul> + <li> + MCC is the three-digit ITU E.212 Mobile Country Code of the + network provider to which the mobile is currently registered. + This value should be the same MCC as reported by the + org.freedesktop.Modem.Gsm.Network.GetRegistrationInfo() method's + returned "operator code" argument. + e.g. "310" + </li> + <li> + MNC is the two- or three-digit GSM Mobile Network Code of the + network provider to which the mobile is currently registered. + This value should be the same MCC as reported by the + org.freedesktop.Modem.Gsm.Network.GetRegistrationInfo() method's + returned "operator code" argument. + e.g. "26" or "260" + </li> + <li> + LAC is the two-byte Location Area Code of the base station with + which the mobile is registered, in upper-case hexadecimal format + without leading zeros, as specified in 3GPP TS 27.007 section + 10.1.19. e.g. "84CD". + </li> + <li> + CI is the two- or four-byte Cell Identifier with which the mobile + is registered, in upper-case hexadecimal format without leading + zeros, as specified in 3GPP TS 27.007. e.g. "2BAF" or "D30156". + </li> + </ul> + <p>The entire string may only be composed of the ASCII digits [0-9], + the alphabetical characters [A-F], and the comma (,) character. No + other characters are allowed. For example: "310,260,8BE3,2BAF" or + "250,40,CE00,1CEAD8F0".</p> + + <p>If any of these four items (MCC,MNC,LAC,CI) is unknown or the + mobile is not registered with a network, then the GSM_LAC_CI location + information item should not be provided as a returned value from the + GetLocation() method or in the Location property.</p> + </tp:docstring> </tp:flag> </tp:flags> diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 81bf26b1..f6e97c3f 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -157,21 +157,22 @@ typedef struct { } 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 }, + /* Longer entries first so we catch the correct one with strcmp() */ + { "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-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-CORP PIN", "ph-corp-pin", MM_MOBILE_ERROR_CORP_PIN }, + { "PH-CORP PUK", "ph-corp-puk", MM_MOBILE_ERROR_CORP_PUK }, + { "PH-SIM PIN", "ph-sim-pin", MM_MOBILE_ERROR_PH_SIM_PIN }, { "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 }, + { "SIM PIN2", "sim-pin2", MM_MOBILE_ERROR_SIM_PIN2 }, + { "SIM PUK2", "sim-puk2", MM_MOBILE_ERROR_SIM_PUK2 }, + { "SIM PIN", "sim-pin", MM_MOBILE_ERROR_SIM_PIN }, + { "SIM PUK", "sim-puk", MM_MOBILE_ERROR_SIM_PUK }, { NULL, NULL, MM_MOBILE_ERROR_PHONE_FAILURE }, }; @@ -665,11 +666,18 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self, g_return_if_fail (MM_IS_GENERIC_GSM (self)); g_return_if_fail (info != NULL); + priv = MM_GENERIC_GSM_GET_PRIVATE (self); + if (error) { mm_modem_set_state (MM_MODEM (self), MM_MODEM_STATE_DISABLED, MM_MODEM_STATE_REASON_NONE); + if (priv->primary && mm_serial_port_is_open (priv->primary)) + mm_serial_port_close (priv->primary); + if (priv->secondary && mm_serial_port_is_open (priv->secondary)) + mm_serial_port_close (priv->secondary); + info->error = g_error_copy (error); mm_callback_info_schedule (info); return; @@ -678,8 +686,6 @@ mm_generic_gsm_enable_complete (MMGenericGsm *self, mm_generic_gsm_update_enabled_state (self, FALSE, MM_MODEM_STATE_REASON_NONE); } - 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, * but also many devices will send unsolicited registration or other @@ -1965,13 +1971,19 @@ disconnect_flash_done (MMSerialPort *port, char *command; info->error = mm_modem_check_removed (info->modem, error); - if (info->error) { + /* Ignore NO_CARRIER errors and proceed with the PDP context deactivation */ + if ( info->error + && !g_error_matches (info->error, + MM_MODEM_CONNECT_ERROR, + MM_MODEM_CONNECT_ERROR_NO_CARRIER)) { mm_callback_info_schedule (info); return; } - /* Disconnect the PDP context */ priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + mm_port_set_connected (priv->data, FALSE); + + /* Disconnect the PDP context */ if (priv->cid >= 0) command = g_strdup_printf ("+CGACT=0,%d", priv->cid); else { @@ -1979,7 +1991,7 @@ disconnect_flash_done (MMSerialPort *port, command = g_strdup_printf ("+CGACT=0"); } - mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), command, 60, disconnect_cgact_done, info); + mm_at_serial_port_queue_command (MM_AT_SERIAL_PORT (port), command, 3, disconnect_cgact_done, info); g_free (command); } diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c index da24e840..7547fe21 100644 --- a/src/mm-plugin-base.c +++ b/src/mm-plugin-base.c @@ -77,6 +77,8 @@ typedef enum { PROBE_STATE_LAST } ProbeState; +static void probe_complete (MMPluginBaseSupportsTask *task); + /*****************************************************************************/ G_DEFINE_TYPE (MMPluginBaseSupportsTask, mm_plugin_base_supports_task, G_TYPE_OBJECT) @@ -91,6 +93,7 @@ typedef struct { guint open_id; guint32 open_tries; + guint full_id; MMAtSerialPort *probe_port; guint32 probed_caps; @@ -198,6 +201,11 @@ mm_plugin_base_supports_task_complete (MMPluginBaseSupportsTask *task, priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); g_return_if_fail (priv->callback != NULL); + if (priv->full_id) { + g_source_remove (priv->full_id); + priv->full_id = 0; + } + subsys = g_udev_device_get_subsystem (priv->port); name = g_udev_device_get_name (priv->port); @@ -251,11 +259,15 @@ supports_task_dispose (GObject *object) if (priv->open_id) g_source_remove (priv->open_id); + if (priv->full_id) + g_source_remove (priv->full_id); if (priv->probe_id) g_source_remove (priv->probe_id); - if (priv->probe_port) + if (priv->probe_port) { + mm_serial_port_close (priv->probe_port); g_object_unref (priv->probe_port); + } G_OBJECT_CLASS (mm_plugin_base_supports_task_parent_class)->dispose (object); } @@ -349,6 +361,44 @@ parse_cgmm (const char *buf) return 0; } +static const char *dq_strings[] = { + "option/faema_", "os_logids.h", NULL +}; + +static void +port_buffer_full (MMSerialPort *port, GString *buffer, gpointer user_data) +{ + MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data); + MMPluginBaseSupportsTaskPrivate *priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (user_data); + const char **iter; + size_t iter_len; + int i; + + /* Check for an immediate disqualification response. There are some + * ports (Option Icera-based chipsets have them, as do Qualcomm Gobi + * devices before their firmware is loaded) that just shouldn't be + * probed if we get a certain response because we know they can't be + * used. Kernel bugs (at least with 2.6.31 and 2.6.32) also trigger port + * flow control kernel oopses if we read too much data for these ports. + */ + + for (iter = &dq_strings[0]; iter && *iter; iter++) { + /* Search in the response for the item; the response could have embedded + * nulls so we can't use memcmp() or strstr() on the whole response. + */ + iter_len = strlen (*iter); + for (i = 0; i < buffer->len - iter_len; i++) { + if (!memcmp (&buffer->str[i], *iter, iter_len)) { + /* Immediately close the port and complete probing */ + priv->probed_caps = 0; + mm_serial_port_close (priv->probe_port); + probe_complete (task); + return; + } + } + } +} + static gboolean emit_probe_result (gpointer user_data) { @@ -626,6 +676,9 @@ try_open (gpointer user_data) port = mm_plugin_base_supports_task_get_port (task); g_assert (port); + task_priv->full_id = g_signal_connect (task_priv->probe_port, "buffer-full", + G_CALLBACK (port_buffer_full), task); + g_debug ("(%s): probe requested by plugin '%s'", g_udev_device_get_name (port), mm_plugin_get_name (MM_PLUGIN (task_priv->plugin))); diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c index 210ce2e6..29505a21 100644 --- a/src/mm-serial-port.c +++ b/src/mm-serial-port.c @@ -629,9 +629,13 @@ data_available (GIOChannel *source, status = g_io_channel_read_chars (source, buf, SERIAL_BUF_SIZE, &bytes_read, &err); if (status == G_IO_STATUS_ERROR) { - g_warning ("%s", err->message); - g_error_free (err); - err = NULL; + if (err && err->message) + g_warning ("%s", err->message); + g_clear_error (&err); + + /* Serial port is closed; we're done */ + if (priv->watch_id == 0) + break; } /* If no bytes read, just let g_io_channel wait for more data */ @@ -644,9 +648,9 @@ data_available (GIOChannel *source, } /* Make sure the response doesn't grow too long */ - if (priv->response->len > SERIAL_BUF_SIZE) { - g_warning ("%s (%s): response buffer filled before repsonse received", - G_STRFUNC, mm_port_get_device (MM_PORT (self))); + if (priv->response->len > SERIAL_BUF_SIZE) { + /* Notify listeners and then trim the buffer */ + g_signal_emit_by_name (self, "buffer-full", priv->response); g_byte_array_remove_range (priv->response, 0, (SERIAL_BUF_SIZE / 2)); } @@ -789,6 +793,7 @@ mm_serial_port_close (MMSerialPort *self) if (priv->channel) { g_source_remove (priv->watch_id); + priv->watch_id = 0; g_io_channel_shutdown (priv->channel, TRUE, NULL); g_io_channel_unref (priv->channel); priv->channel = NULL; @@ -1238,4 +1243,14 @@ mm_serial_port_class_init (MMSerialPortClass *klass) "Send delay", 0, G_MAXUINT64, 0, G_PARAM_READWRITE)); + + /* Signals */ + g_signal_new ("buffer-full", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (MMSerialPortClass, buffer_full), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); } + diff --git a/src/mm-serial-port.h b/src/mm-serial-port.h index c07d70c8..6835d8bf 100644 --- a/src/mm-serial-port.h +++ b/src/mm-serial-port.h @@ -50,6 +50,7 @@ struct _MMSerialPort { struct _MMSerialPortClass { MMPortClass parent; +<<<<<<< HEAD /* Called for subclasses to parse unsolicited responses. If any recognized * unsolicited response is found, it should be removed from the 'response' * byte array before returning. @@ -80,6 +81,9 @@ struct _MMSerialPortClass { * return FALSE and set 'error' as appropriate. */ gboolean (*config_fd) (MMSerialPort *self, int fd, GError **error); + + /* Signals */ + void (*buffer_full) (MMSerialPort *port, const GByteArray *buffer); }; GType mm_serial_port_get_type (void); |