diff options
author | Dan Williams <dcbw@redhat.com> | 2009-11-30 15:44:20 -0800 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2009-11-30 15:44:20 -0800 |
commit | 909b8b7c8dbe2de97d9550004641c70411d92c56 (patch) | |
tree | a7546e1461ed81ff9ba9a251fd3fe2decdacf4ad /src | |
parent | c463b5a4005b9e55d0faeb887debe327118ef230 (diff) | |
parent | 0f595adb7f07f575627667480f23775b21f9efb2 (diff) |
Merge commit 'origin/master' into states
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-callback-info.c | 2 | ||||
-rw-r--r-- | src/mm-callback-info.h | 1 | ||||
-rw-r--r-- | src/mm-errors.c | 1 | ||||
-rw-r--r-- | src/mm-errors.h | 3 | ||||
-rw-r--r-- | src/mm-generic-cdma.c | 39 | ||||
-rw-r--r-- | src/mm-generic-cdma.h | 3 | ||||
-rw-r--r-- | src/mm-generic-gsm.c | 127 | ||||
-rw-r--r-- | src/mm-plugin-base.c | 67 | ||||
-rw-r--r-- | src/mm-serial-parsers.c | 14 | ||||
-rw-r--r-- | src/mm-serial-port.c | 21 |
10 files changed, 208 insertions, 70 deletions
diff --git a/src/mm-callback-info.c b/src/mm-callback-info.c index 0aca55da..089f0b73 100644 --- a/src/mm-callback-info.c +++ b/src/mm-callback-info.c @@ -67,6 +67,7 @@ callback_info_done (gpointer user_data) MMCallbackInfo *info = (MMCallbackInfo *) user_data; info->pending_id = 0; + info->called = TRUE; if (info->invoke_fn && info->callback) info->invoke_fn (info); @@ -94,6 +95,7 @@ mm_callback_info_schedule (MMCallbackInfo *info) { g_return_if_fail (info != NULL); g_return_if_fail (info->pending_id == 0); + g_return_if_fail (info->called == FALSE); info->pending_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, callback_info_do, info, callback_info_done); } diff --git a/src/mm-callback-info.h b/src/mm-callback-info.h index 591ac86e..783e1282 100644 --- a/src/mm-callback-info.h +++ b/src/mm-callback-info.h @@ -28,6 +28,7 @@ struct _MMCallbackInfo { MMCallbackInfoInvokeFn invoke_fn; GCallback callback; + gboolean called; gpointer user_data; GError *error; diff --git a/src/mm-errors.c b/src/mm-errors.c index 510fa6d0..6448b807 100644 --- a/src/mm-errors.c +++ b/src/mm-errors.c @@ -39,6 +39,7 @@ mm_serial_error_get_type (void) ENUM_ENTRY (MM_SERIAL_OPEN_FAILED, "SerialOpenFailed"), ENUM_ENTRY (MM_SERIAL_SEND_FAILED, "SerialSendfailed"), ENUM_ENTRY (MM_SERIAL_RESPONSE_TIMEOUT, "SerialResponseTimeout"), + ENUM_ENTRY (MM_SERIAL_OPEN_FAILED_NO_DEVICE, "SerialOpenFailedNoDevice"), { 0, 0, 0 } }; diff --git a/src/mm-errors.h b/src/mm-errors.h index bc43d3e9..4bf8ecad 100644 --- a/src/mm-errors.h +++ b/src/mm-errors.h @@ -22,7 +22,8 @@ enum { MM_SERIAL_OPEN_FAILED = 0, MM_SERIAL_SEND_FAILED = 1, - MM_SERIAL_RESPONSE_TIMEOUT = 2 + MM_SERIAL_RESPONSE_TIMEOUT = 2, + MM_SERIAL_OPEN_FAILED_NO_DEVICE = 3 }; #define MM_SERIAL_ERROR (mm_serial_error_quark ()) diff --git a/src/mm-generic-cdma.c b/src/mm-generic-cdma.c index 0653e708..be95116c 100644 --- a/src/mm-generic-cdma.c +++ b/src/mm-generic-cdma.c @@ -48,7 +48,8 @@ G_DEFINE_TYPE_EXTENDED (MMGenericCdma, mm_generic_cdma, MM_TYPE_MODEM_BASE, 0, #define MM_GENERIC_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), MM_TYPE_GENERIC_CDMA, MMGenericCdmaPrivate)) typedef struct { - guint32 signal_quality; + guint32 cdma1x_quality; + guint32 evdo_quality; gboolean valid; gboolean evdo_rev0; gboolean evdo_revA; @@ -633,13 +634,33 @@ get_card_info (MMModem *modem, /*****************************************************************************/ void -mm_generic_cdma_update_signal_quality (MMGenericCdma *self, guint32 quality) +mm_generic_cdma_update_cdma1x_quality (MMGenericCdma *self, guint32 quality) { + MMGenericCdmaPrivate *priv; + g_return_if_fail (MM_IS_GENERIC_CDMA (self)); g_return_if_fail (quality >= 0 && quality <= 100); - MM_GENERIC_CDMA_GET_PRIVATE (self)->signal_quality = quality; - mm_modem_cdma_emit_signal_quality_changed (MM_MODEM_CDMA (self), quality); + priv = MM_GENERIC_CDMA_GET_PRIVATE (self); + if (priv->cdma1x_quality != quality) { + priv->cdma1x_quality = quality; + mm_modem_cdma_emit_signal_quality_changed (MM_MODEM_CDMA (self), quality); + } +} + +void +mm_generic_cdma_update_evdo_quality (MMGenericCdma *self, guint32 quality) +{ + MMGenericCdmaPrivate *priv; + + g_return_if_fail (MM_IS_GENERIC_CDMA (self)); + g_return_if_fail (quality >= 0 && quality <= 100); + + priv = MM_GENERIC_CDMA_GET_PRIVATE (self); + if (priv->evdo_quality != quality) { + priv->evdo_quality = quality; + // FIXME: emit a signal + } } static void @@ -671,9 +692,11 @@ get_signal_quality_done (MMSerialPort *port, quality = CLAMP (quality, 0, 31) * 100 / 31; priv = MM_GENERIC_CDMA_GET_PRIVATE (info->modem); - priv->signal_quality = quality; mm_callback_info_set_result (info, GUINT_TO_POINTER (quality), NULL); - mm_modem_cdma_emit_signal_quality_changed (MM_MODEM_CDMA (info->modem), quality); + if (priv->cdma1x_quality != quality) { + priv->cdma1x_quality = quality; + mm_modem_cdma_emit_signal_quality_changed (MM_MODEM_CDMA (info->modem), quality); + } } } else info->error = g_error_new (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, @@ -694,8 +717,8 @@ get_signal_quality (MMModemCdma *modem, connected = mm_port_get_connected (MM_PORT (priv->primary)); if (connected && !priv->secondary) { - g_message ("Returning saved signal quality %d", priv->signal_quality); - callback (MM_MODEM (modem), priv->signal_quality, NULL, user_data); + g_message ("Returning saved signal quality %d", priv->cdma1x_quality); + callback (MM_MODEM (modem), priv->cdma1x_quality, NULL, user_data); return; } diff --git a/src/mm-generic-cdma.h b/src/mm-generic-cdma.h index a1200c36..8d85cb38 100644 --- a/src/mm-generic-cdma.h +++ b/src/mm-generic-cdma.h @@ -64,7 +64,8 @@ MMPort * mm_generic_cdma_grab_port (MMGenericCdma *self, MMSerialPort *mm_generic_cdma_get_port (MMGenericCdma *modem, MMPortType ptype); -void mm_generic_cdma_update_signal_quality (MMGenericCdma *self, guint32 quality); +void mm_generic_cdma_update_cdma1x_quality (MMGenericCdma *self, guint32 quality); +void mm_generic_cdma_update_evdo_quality (MMGenericCdma *self, guint32 quality); /* For unsolicited 1x registration state changes */ void mm_generic_cdma_set_1x_registration_state (MMGenericCdma *self, diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c index 468cdfc2..74f7cb2f 100644 --- a/src/mm-generic-gsm.c +++ b/src/mm-generic-gsm.c @@ -835,6 +835,7 @@ read_operator_name_done (MMSerialPort *port, } /* Registration */ +#define REG_STATUS_AGAIN_TAG "reg-status-again" void mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem) @@ -842,21 +843,27 @@ mm_generic_gsm_pending_registration_stop (MMGenericGsm *modem) MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (modem); if (priv->pending_reg_id) { + /* Clear the registration timeout handler */ g_source_remove (priv->pending_reg_id); priv->pending_reg_id = 0; + } + + if (priv->pending_reg_info) { + /* Clear any ongoing registration status callback */ + mm_callback_info_set_data (priv->pending_reg_info, REG_STATUS_AGAIN_TAG, NULL, NULL); + + /* And schedule the callback */ + mm_callback_info_schedule (priv->pending_reg_info); priv->pending_reg_info = NULL; } } static gboolean -reg_status_updated (MMGenericGsm *self, int new_value, MMCallbackInfo *info) +reg_status_updated (MMGenericGsm *self, int new_value, GError **error) { MMModemGsmNetworkRegStatus status; gboolean status_done = FALSE; - /* info must be set to process status updates - for now */ - g_return_val_if_fail (!!info, status_done); - switch (new_value) { case 0: status = MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE; @@ -888,25 +895,25 @@ reg_status_updated (MMGenericGsm *self, int new_value, MMCallbackInfo *info) case MM_MODEM_GSM_NETWORK_REG_STATUS_HOME: case MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING: /* Successfully registered - stop registration */ - mm_callback_info_schedule (info); - mm_generic_gsm_pending_registration_stop (self); status_done = TRUE; break; case MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED: /* registration failed - stop registration */ - info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NETWORK_NOT_ALLOWED); - mm_callback_info_schedule (info); - mm_generic_gsm_pending_registration_stop (self); + if (error) + *error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NETWORK_NOT_ALLOWED); status_done = TRUE; break; case MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING: - info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NETWORK_TIMEOUT); + if (error) + *error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NETWORK_TIMEOUT); break; case MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE: - info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NO_NETWORK); + if (error) + *error = mm_mobile_error_for_code (MM_MOBILE_ERROR_NO_NETWORK); break; default: - info->error = mm_mobile_error_for_code (MM_MOBILE_ERROR_UNKNOWN); + if (error) + *error = mm_mobile_error_for_code (MM_MOBILE_ERROR_UNKNOWN); break; } return status_done; @@ -918,23 +925,21 @@ reg_state_changed (MMSerialPort *port, gpointer user_data) { MMGenericGsm *self = MM_GENERIC_GSM (user_data); - MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (self); char *str; str = g_match_info_fetch (match_info, 1); - if (!reg_status_updated (self, atoi (str), priv->pending_reg_info) && priv->pending_reg_info) - g_clear_error (&priv->pending_reg_info->error); - + reg_status_updated (self, atoi (str), NULL); g_free (str); } static gboolean reg_status_again (gpointer data) { - MMGenericGsmPrivate *priv; MMCallbackInfo *info = (MMCallbackInfo *) data; + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + + g_warn_if_fail (info == priv->pending_reg_info); - priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); if (priv->pending_reg_id) get_registration_status (priv->primary, info); @@ -944,7 +949,11 @@ reg_status_again (gpointer data) static void reg_status_again_remove (gpointer data) { - g_source_remove (GPOINTER_TO_INT (data)); + guint id = GPOINTER_TO_UINT (data); + + /* Technically the GSource ID can be 0, but in practice it won't be */ + if (id > 0) + g_source_remove (id); } static void @@ -956,41 +965,72 @@ 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 unsolicited, stat; + int reg_status = -1; + GRegex *r; + GMatchInfo *match_info; + char *tmp; guint id; + g_warn_if_fail (info == priv->pending_reg_info); + if (error) { info->error = g_error_copy (error); - mm_generic_gsm_pending_registration_stop (self); - mm_callback_info_schedule (info); - return; + goto reg_done; } - if ( !g_str_has_prefix (response->str, "+CREG: ") - || (sscanf (response->str + 7, "%d,%d", &unsolicited, &stat) != 2)) { - g_debug ("%s: unknown response: %s", __func__, response->str); - info->error = g_error_new_literal (MM_MODEM_ERROR, + 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, - "Could not parse the response"); - mm_generic_gsm_pending_registration_stop (self); - mm_callback_info_schedule (info); - return; + "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); } - if (!reg_status_updated (self, stat, info) && priv->pending_reg_id) { + if ( reg_status >= 0 + && !reg_status_updated (self, reg_status, &info->error) + && priv->pending_reg_id) { g_clear_error (&info->error); - /* Registration is still going */ + + /* 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", - GINT_TO_POINTER (id), - reg_status_again_remove); + mm_callback_info_set_data (info, REG_STATUS_AGAIN_TAG, + GUINT_TO_POINTER (id), + reg_status_again_remove); + return; } + +reg_done: + /* This will schedule the callback for us */ + mm_generic_gsm_pending_registration_stop (self); } static void get_registration_status (MMSerialPort *port, MMCallbackInfo *info) { - mm_serial_port_queue_command (port, "+CREG?", 3, get_reg_status_done, info); + MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + + g_warn_if_fail (info == priv->pending_reg_info); + + mm_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info); } static void @@ -1009,6 +1049,8 @@ registration_timed_out (gpointer data) MMCallbackInfo *info = (MMCallbackInfo *) data; MMGenericGsmPrivate *priv = MM_GENERIC_GSM_GET_PRIVATE (info->modem); + g_warn_if_fail (info == priv->pending_reg_info); + priv->pending_reg_id = 0; priv->pending_reg_info = NULL; priv->reg_status = MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE; @@ -1028,6 +1070,9 @@ do_register (MMModemGsmNetwork *modem, MMCallbackInfo *info; char *command; + /* Clear any previous registration */ + mm_generic_gsm_pending_registration_stop (MM_GENERIC_GSM (modem)); + info = mm_callback_info_new (MM_MODEM (modem), callback, user_data); priv->pending_reg_id = g_timeout_add_seconds (60, registration_timed_out, info); @@ -1038,7 +1083,7 @@ do_register (MMModemGsmNetwork *modem, else command = g_strdup ("+COPS=0,,"); - mm_serial_port_queue_command (priv->primary, command, 10, register_done, info); + mm_serial_port_queue_command (priv->primary, command, 120, register_done, info); g_free (command); } @@ -1353,7 +1398,7 @@ cid_range_read (MMSerialPort *port, GRegex *r; GMatchInfo *match_info; - r = g_regex_new ("\\+CGDCONT: \\((\\d+)-(\\d+)\\),\"(\\S+)\"", + r = g_regex_new ("\\+CGDCONT:\\s*\\((\\d+)-(\\d+)\\),\\(?\"(\\S+)\"", G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, &info->error); if (r) { @@ -1398,7 +1443,7 @@ cid_range_read (MMSerialPort *port, mm_callback_info_set_data (info, "cid", GUINT_TO_POINTER (cid), NULL); - command = g_strdup_printf ("+CGDCONT=%d, \"IP\", \"%s\"", cid, apn); + command = g_strdup_printf ("+CGDCONT=%d,\"IP\",\"%s\"", cid, apn); mm_serial_port_queue_command (port, command, 3, set_apn_done, info); g_free (command); } @@ -1419,7 +1464,7 @@ existing_apns_read (MMSerialPort *port, GRegex *r; GMatchInfo *match_info; - r = g_regex_new ("\\+CGDCONT: (\\d+)\\s*,\"(\\S+)\",\"(\\S+)\",\"(\\S+)\"", + r = g_regex_new ("\\+CGDCONT:\\s*(\\d+)\\s*,\"(\\S+)\",\"(\\S+)\",\"(\\S*)\"", G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, &info->error); if (r) { diff --git a/src/mm-plugin-base.c b/src/mm-plugin-base.c index 540670aa..ad849218 100644 --- a/src/mm-plugin-base.c +++ b/src/mm-plugin-base.c @@ -85,6 +85,9 @@ typedef struct { GUdevDevice *physdev; char *driver; + guint open_id; + guint32 open_tries; + MMSerialPort *probe_port; guint32 probed_caps; ProbeState probe_state; @@ -201,7 +204,7 @@ mm_plugin_base_supports_task_init (MMPluginBaseSupportsTask *self) } static void -dispose (GObject *object) +supports_task_dispose (GObject *object) { MMPluginBaseSupportsTaskPrivate *priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (object); @@ -214,6 +217,9 @@ dispose (GObject *object) g_free (priv->probe_resp); g_clear_error (&(priv->probe_error)); + if (priv->open_id) + g_source_remove (priv->open_id); + if (priv->probe_id) g_source_remove (priv->probe_id); if (priv->probe_port) @@ -230,7 +236,7 @@ mm_plugin_base_supports_task_class_init (MMPluginBaseSupportsTaskClass *klass) g_type_class_add_private (object_class, sizeof (MMPluginBaseSupportsTaskPrivate)); /* Virtual methods */ - object_class->dispose = dispose; + object_class->dispose = supports_task_dispose; } /*****************************************************************************/ @@ -467,12 +473,52 @@ flash_done (MMSerialPort *port, GError *error, gpointer user_data) mm_serial_port_queue_command (port, "+GCAP", 3, parse_response, user_data); } +static gboolean +try_open (gpointer user_data) +{ + MMPluginBaseSupportsTask *task = MM_PLUGIN_BASE_SUPPORTS_TASK (user_data); + MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); + GError *error = NULL; + + task_priv->open_id = 0; + + if (!mm_serial_port_open (task_priv->probe_port, &error)) { + if (++task_priv->open_tries > 4) { + /* took too long to open the port; give up */ + g_warning ("(%s): failed to open after 4 tries.", + mm_port_get_device (MM_PORT (task_priv->probe_port))); + probe_complete (task); + } else if (g_error_matches (error, + MM_SERIAL_ERROR, + MM_SERIAL_OPEN_FAILED_NO_DEVICE)) { + /* this is nozomi being dumb; try again */ + task_priv->open_id = g_timeout_add_seconds (1, try_open, task); + } else { + /* some other hard error */ + probe_complete (task); + } + g_clear_error (&error); + } else { + /* success, start probing */ + GUdevDevice *port; + + port = mm_plugin_base_supports_task_get_port (task); + g_assert (port); + + g_debug ("(%s): probe requested by plugin '%s'", + g_udev_device_get_name (port), + mm_plugin_get_name (MM_PLUGIN (task_priv->plugin))); + mm_serial_port_flash (task_priv->probe_port, 100, flash_done, task); + } + + return FALSE; +} + gboolean mm_plugin_base_probe_port (MMPluginBase *self, MMPluginBaseSupportsTask *task, GError **error) { - MMPluginBasePrivate *priv = MM_PLUGIN_BASE_GET_PRIVATE (self); MMPluginBaseSupportsTaskPrivate *task_priv = MM_PLUGIN_BASE_SUPPORTS_TASK_GET_PRIVATE (task); MMSerialPort *serial; const char *name; @@ -488,6 +534,12 @@ mm_plugin_base_probe_port (MMPluginBase *self, g_assert (name); serial = mm_serial_port_new (name, MM_PORT_TYPE_PRIMARY); + if (serial == NULL) { + g_set_error_literal (error, MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL, + "Failed to create new serial port."); + return FALSE; + } + g_object_set (serial, MM_SERIAL_PORT_SEND_DELAY, (guint64) 100000, MM_PORT_CARRIER_DETECT, FALSE, @@ -498,14 +550,9 @@ mm_plugin_base_probe_port (MMPluginBase *self, mm_serial_parser_v1_new (), mm_serial_parser_v1_destroy); - if (!mm_serial_port_open (serial, error)) { - g_object_unref (serial); - return FALSE; - } - - g_debug ("(%s): probe requested by plugin '%s'", name, priv->name); + /* Open the port */ task_priv->probe_port = serial; - mm_serial_port_flash (serial, 100, flash_done, task); + task_priv->open_id = g_idle_add (try_open, task); return TRUE; } diff --git a/src/mm-serial-parsers.c b/src/mm-serial-parsers.c index b36496ff..58985d90 100644 --- a/src/mm-serial-parsers.c +++ b/src/mm-serial-parsers.c @@ -26,15 +26,19 @@ response_clean (GString *response) { char *s; - /* Ends with '<CR><LF>' */ + /* Ends with one or more '<CR><LF>' */ s = response->str + response->len - 1; - if (*s == '\n' && *(--s) == '\r') + while ((s > response->str) && (*s == '\n') && (*(s - 1) == '\r')) { g_string_truncate (response, response->len - 2); + s -= 2; + } - /* Starts with '<CR><LF>' */ + /* Starts with one or more '<CR><LF>' */ s = response->str; - if (*s == '\r' && *(++s) == '\n') + while ((response->len >= 2) && (*s == '\r') && (*(s + 1) == '\n')) { g_string_erase (response, 0, 2); + s = response->str; + } } @@ -199,7 +203,7 @@ mm_serial_parser_v1_new (void) parser = g_slice_new (MMSerialParserV1); - parser->regex_ok = g_regex_new ("\\r\\nOK\\r\\n$", flags, 0, NULL); + parser->regex_ok = g_regex_new ("\\r\\nOK(\\r\\n)+$", flags, 0, NULL); parser->regex_connect = g_regex_new ("\\r\\nCONNECT.*\\r\\n", flags, 0, NULL); parser->regex_detailed_error = g_regex_new ("\\r\\n\\+CME ERROR: (\\d+)\\r\\n$", flags, 0, NULL); parser->regex_unknown_error = g_regex_new ("\\r\\n(ERROR)|(COMMAND NOT SUPPORT)\\r\\n$", flags, 0, NULL); diff --git a/src/mm-serial-port.c b/src/mm-serial-port.c index 250e00be..3abd5619 100644 --- a/src/mm-serial-port.c +++ b/src/mm-serial-port.c @@ -479,9 +479,15 @@ mm_serial_port_schedule_queue_process (MMSerialPort *self) MMSerialPortPrivate *priv = MM_SERIAL_PORT_GET_PRIVATE (self); GSource *source; - if (priv->queue_schedule) + if (priv->timeout_id) { + /* A command is already in progress */ + return; + } + + if (priv->queue_schedule) { /* Already scheduled */ return; + } source = g_idle_source_new (); g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_port_queue_process), G_OBJECT (self))); @@ -568,7 +574,7 @@ mm_serial_port_queue_process (gpointer data) if (mm_serial_port_send_command (self, info->command, &error)) { GSource *source; - source = g_timeout_source_new (info->timeout); + source = g_timeout_source_new_seconds (info->timeout); g_source_set_closure (source, g_cclosure_new_object (G_CALLBACK (mm_serial_port_timed_out), G_OBJECT (self))); g_source_attach (source, NULL); priv->timeout_id = g_source_get_id (source); @@ -791,11 +797,18 @@ mm_serial_port_open (MMSerialPort *self, GError **error) g_message ("(%s) opening serial device...", device); devfile = g_strdup_printf ("/dev/%s", device); + errno = 0; priv->fd = open (devfile, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY); g_free (devfile); if (priv->fd < 0) { - g_set_error (error, MM_SERIAL_ERROR, MM_SERIAL_OPEN_FAILED, + /* nozomi isn't ready yet when the port appears, and it'll return + * ENODEV when open(2) is called on it. Make sure we can handle this + * by returning a special error in that case. + */ + g_set_error (error, + MM_SERIAL_ERROR, + (errno == ENODEV) ? MM_SERIAL_OPEN_FAILED_NO_DEVICE : MM_SERIAL_OPEN_FAILED, "Could not open serial device %s: %s", device, strerror (errno)); return FALSE; } @@ -889,7 +902,7 @@ internal_queue_command (MMSerialPort *self, info = g_slice_new0 (MMQueueData); info->command = g_strdup (command); info->cached = cached; - info->timeout = timeout_seconds * 1000; + info->timeout = timeout_seconds; info->callback = callback; info->user_data = user_data; |