NetworkManager r4119 - in trunk: . src
- From: dcbw svn gnome org
- To: svn-commits-list gnome org
- Subject: NetworkManager r4119 - in trunk: . src
- Date: Sun, 28 Sep 2008 22:55:40 +0000 (UTC)
Author: dcbw
Date: Sun Sep 28 22:55:40 2008
New Revision: 4119
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4119&view=rev
Log:
2008-09-28 Dan Williams <dcbw redhat com>
* src/nm-serial-device.c
src/nm-serial-device.h
- (nm_serial_device_close): stop PPP manager here so that PPP gets
cleaned at the right times when subclasses close the serial port too
- (nm_serial_device_send_command): use a default send delay; don't
spin forever on EAGAIN
- (get_reply_done, get_reply_got_data, nm_serial_device_get_reply):
remove, no longer used
- (find_response): return the matched response if any
- (nm_serial_device_wait_reply_blocking): wait for a reply but block
while doing so
- (wait_for_reply_done): pass the matched response to the callback
- (wait_for_reply_got_data): save the matched response; simplify timeout
handling
- (nm_serial_device_wait_for_reply): make 'responses' and 'terminators'
const since they never get modified
- (cleanup_device): split out common cleanup stuff to a new function
- (real_deactivate_quickly, finalize): use cleanup_device()
* src/nm-gsm-device.c
- (modem_get_reply): remove, unused
- (set_apn): give the card a bit more time to respond
- (manual_registration_again, schedule_manual_registration_again,
manual_registration_response, manual_registration): handle manual
registration timeouts better by retrying registration a few times
because cards are a bit slow after CFUN=1
- (automatic_registration_get_network, get_network_response): use
modem_wait_for_reply() because it interacts better with the serial
buffer and does more intelligent matching; need to wait for 'OK'
rather than just matching terminators
- (schedule_automatic_registration_again,
automatic_registration_response, automatic_registration): retry
registration a few times on timeout or "searching" because cards
take a bit to find a network after being powered up with CFUN=1
- (power_up_response, power_up, init_full_done, enter_pin,
check_pin_done): power up the card with CFUN=1 before trying to
register with the network
- (init_modem_full, init_modem): use more standard 3G init strings
* src/nm-hso-gsm-device.c
- (modem_get_reply): remove, unused
- (hso_ip4_config_response, real_act_stage3_ip_config_start): use
modem_wait_for_reply() to match actual responses instead of single
termination characters; it doesn't leave stuff in the serial buffer
that might confuse later calls
- (real_deactivate_quickly): use nm_serial_device_wait_reply_blocking()
to ensure that the call is really disconnected and not leave extra
stuff in the serial buffer
* src/nm-cdma-device.c
- (power_up_response, power_up, init_done): try Sierra-style modem
power up before attempting to connect
Modified:
trunk/ChangeLog
trunk/src/nm-cdma-device.c
trunk/src/nm-gsm-device.c
trunk/src/nm-hso-gsm-device.c
trunk/src/nm-serial-device.c
trunk/src/nm-serial-device.h
Modified: trunk/src/nm-cdma-device.c
==============================================================================
--- trunk/src/nm-cdma-device.c (original)
+++ trunk/src/nm-cdma-device.c Sun Sep 28 22:55:40 2008
@@ -79,6 +79,7 @@
static void
dial_done (NMSerialDevice *device,
int reply_index,
+ const char *reply,
gpointer user_data)
{
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_UNKNOWN;
@@ -122,7 +123,7 @@
NMSettingCdma *setting;
char *command;
guint id = 0;
- char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
+ const char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
setting = NM_SETTING_CDMA (cdma_device_get_setting (NM_CDMA_DEVICE (device), NM_TYPE_SETTING_CDMA));
@@ -138,13 +139,40 @@
}
static void
+power_up_response (NMSerialDevice *device,
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
+{
+ /* Ignore errors */
+ do_dial (device);
+}
+
+static void
+power_up (NMSerialDevice *device)
+{
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ guint id = 0;
+
+ /* Only works on Sierra cards */
+ nm_info ("(%s): powering up...", nm_device_get_iface (NM_DEVICE (device)));
+ if (nm_serial_device_send_command_string (device, "at!pcstate=1"))
+ id = nm_serial_device_wait_for_reply (device, 10, responses, responses, power_up_response, NULL);
+
+ /* Ignore errors */
+ if (id == 0)
+ do_dial (device);
+}
+
+static void
init_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
switch (reply_index) {
case 0:
- do_dial (device);
+ power_up (device);
break;
case -1:
nm_warning ("Modem initialization timed out");
@@ -165,7 +193,7 @@
init_modem (NMSerialDevice *device, gpointer user_data)
{
guint id = 0;
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
if (nm_serial_device_send_command_string (device, "ATZ E0"))
id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
Modified: trunk/src/nm-gsm-device.c
==============================================================================
--- trunk/src/nm-gsm-device.c (original)
+++ trunk/src/nm-gsm-device.c Sun Sep 28 22:55:40 2008
@@ -28,6 +28,8 @@
NMGsmSecret need_secret;
guint pending_id;
guint state_to_disconnected_id;
+
+ guint reg_tries;
} NMGsmDevicePrivate;
enum {
@@ -46,6 +48,7 @@
static guint signals[LAST_SIGNAL] = { 0 };
static void enter_pin (NMGsmDevice *device, gboolean retry);
+static void manual_registration (NMGsmDevice *device);
static void automatic_registration (NMGsmDevice *device);
NMGsmDevice *
@@ -70,12 +73,12 @@
static void
modem_wait_for_reply (NMGsmDevice *self,
- const char *command,
- guint timeout,
- char **responses,
- char **terminators,
- NMSerialWaitForReplyFn callback,
- gpointer user_data)
+ const char *command,
+ guint timeout,
+ const char **responses,
+ const char **terminators,
+ NMSerialWaitForReplyFn callback,
+ gpointer user_data)
{
NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
guint id = 0;
@@ -87,23 +90,6 @@
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
}
-static void
-modem_get_reply (NMGsmDevice *self,
- const char *command,
- guint timeout,
- const char *terminators,
- NMSerialGetReplyFn callback)
-{
- NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
- guint id = 0;
-
- if (nm_serial_device_send_command_string (serial, command))
- id = nm_serial_device_get_reply (serial, timeout, terminators, callback, NULL);
-
- if (id == 0)
- nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
-}
-
static NMSetting *
gsm_device_get_setting (NMGsmDevice *device, GType setting_type)
{
@@ -124,8 +110,9 @@
static void
dial_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
gboolean success = FALSE;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_UNKNOWN;
@@ -168,7 +155,7 @@
{
NMSettingGsm *setting;
char *command;
- char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
+ const char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM));
@@ -192,8 +179,9 @@
static void
set_apn_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
switch (reply_index) {
case 0:
@@ -211,11 +199,14 @@
static void
set_apn (NMGsmDevice *device)
{
+ NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
NMSettingGsm *setting;
char *command;
- char *responses[] = { "OK", "ERROR", NULL };
+ const char *responses[] = { "OK", "ERROR", NULL };
guint cid = 1;
+ priv->reg_tries = 0;
+
setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM));
if (!setting->apn) {
/* APN not set, nothing to do */
@@ -224,24 +215,54 @@
}
command = g_strdup_printf ("AT+CGDCONT=%d, \"IP\", \"%s\"", cid, setting->apn);
- modem_wait_for_reply (device, command, 3, responses, responses, set_apn_done, GUINT_TO_POINTER (cid));
+ modem_wait_for_reply (device, command, 7, responses, responses, set_apn_done, GUINT_TO_POINTER (cid));
g_free (command);
}
+static gboolean
+manual_registration_again (gpointer data)
+{
+ manual_registration (NM_GSM_DEVICE (data));
+ return FALSE;
+}
+
+static void
+schedule_manual_registration_again (NMGsmDevice *self)
+{
+ NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (self);
+
+ if (priv->pending_id)
+ g_source_remove (priv->pending_id);
+
+ priv->pending_id = g_idle_add (manual_registration_again, self);
+}
+
static void
-manual_registration_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+manual_registration_response (NMSerialDevice *device,
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
+ NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
+
switch (reply_index) {
case 0:
set_apn (NM_GSM_DEVICE (device));
break;
case -1:
- nm_warning ("Manual registration timed out");
- nm_device_state_changed (NM_DEVICE (device),
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT);
+ /* Some cards (ex. Sierra AC860) don't immediately respond to commands
+ * after they are powered up with CFUN=1, but take a few seconds to come
+ * back to life. So try registration a few times.
+ */
+ if (priv->reg_tries++ < 6) {
+ schedule_manual_registration_again (NM_GSM_DEVICE (device));
+ } else {
+ nm_warning ("Manual registration timed out");
+ priv->reg_tries = 0;
+ nm_device_state_changed (NM_DEVICE (device),
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT);
+ }
break;
default:
nm_warning ("Manual registration failed");
@@ -257,24 +278,29 @@
{
NMSettingGsm *setting;
char *command;
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
setting = NM_SETTING_GSM (gsm_device_get_setting (device, NM_TYPE_SETTING_GSM));
command = g_strdup_printf ("AT+COPS=1,2,\"%s\"", setting->network_id);
- modem_wait_for_reply (device, command, 30, responses, responses, manual_registration_done, NULL);
+ modem_wait_for_reply (device, command, 15, responses, responses, manual_registration_response, NULL);
g_free (command);
}
static void
-get_network_done (NMSerialDevice *device,
- const char *response,
- gpointer user_data)
+get_network_response (NMSerialDevice *device,
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
- if (response)
- nm_info ("Associated with network: %s", response);
- else
+ switch (reply_index) {
+ case 0:
+ nm_info ("Associated with network: %s", reply);
+ break;
+ default:
nm_warning ("Couldn't read active network name");
+ break;
+ }
set_apn (NM_GSM_DEVICE (device));
}
@@ -282,9 +308,10 @@
static void
automatic_registration_get_network (NMGsmDevice *device)
{
- const char terminators[] = { '\r', '\n', '\0' };
+ const char *responses[] = { "+COPS: ", NULL };
+ const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
- modem_get_reply (device, "AT+COPS?", 10, terminators, get_network_done);
+ modem_wait_for_reply (device, "AT+COPS?", 10, responses, terminators, get_network_response, NULL);
}
static gboolean
@@ -295,23 +322,49 @@
}
static void
+schedule_automatic_registration_again (NMGsmDevice *self)
+{
+ NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (self);
+
+ if (priv->pending_id)
+ g_source_remove (priv->pending_id);
+
+ priv->pending_id = g_idle_add (automatic_registration_again, self);
+}
+
+static void
automatic_registration_response (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
+ NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
+
switch (reply_index) {
case 0:
- nm_warning ("Automatic registration failed: not registered and not searching.");
- nm_device_state_changed (NM_DEVICE (device),
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING);
+ /* Try autoregistration a few times here because the card is actually
+ * responding to the query and thus we aren't waiting as long for
+ * each CREG request. Some cards (ex. Option iCON 225) return OK
+ * immediately from CFUN, but take a bit to start searching for a network.
+ */
+ if (priv->reg_tries++ < 15) {
+ /* Can happen a few times while the modem is powering up */
+ schedule_automatic_registration_again (NM_GSM_DEVICE (device));
+ } else {
+ priv->reg_tries = 0;
+ nm_warning ("Automatic registration failed: not registered and not searching.");
+ nm_device_state_changed (NM_DEVICE (device),
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING);
+ }
break;
case 1:
nm_info ("Registered on Home network");
automatic_registration_get_network (NM_GSM_DEVICE (device));
break;
case 2:
- NM_GSM_DEVICE_GET_PRIVATE (device)->pending_id = g_timeout_add (1000, automatic_registration_again, device);
+ nm_info ("Searching for a network...");
+ schedule_automatic_registration_again (NM_GSM_DEVICE (device));
break;
case 3:
nm_warning ("Automatic registration failed: registration denied.");
@@ -324,10 +377,19 @@
automatic_registration_get_network (NM_GSM_DEVICE (device));
break;
case -1:
+ /* Some cards (ex. Sierra AC860) don't immediately respond to commands
+ * after they are powered up with CFUN=1, but take a few seconds to come
+ * back to life. So try registration a few times.
+ */
nm_warning ("Automatic registration timed out");
- nm_device_state_changed (NM_DEVICE (device),
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT);
+ if (priv->reg_tries++ < 6) {
+ schedule_automatic_registration_again (NM_GSM_DEVICE (device));
+ } else {
+ priv->reg_tries = 0;
+ nm_device_state_changed (NM_DEVICE (device),
+ NM_DEVICE_STATE_FAILED,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT);
+ }
break;
default:
nm_warning ("Automatic registration failed");
@@ -341,19 +403,21 @@
static void
automatic_registration (NMGsmDevice *device)
{
- char *responses[] = { "+CREG: 0,0", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,5", NULL };
- char *terminators[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "+CREG: 0,0", "+CREG: 0,1", "+CREG: 0,2", "+CREG: 0,3", "+CREG: 0,5", NULL };
+ const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
- modem_wait_for_reply (device, "AT+CREG?", 60, responses, terminators, automatic_registration_response, NULL);
+ modem_wait_for_reply (device, "AT+CREG?", 15, responses, terminators, automatic_registration_response, NULL);
}
static void
do_register (NMGsmDevice *device)
{
+ NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
NMSettingGsm *setting;
setting = NM_SETTING_GSM (gsm_device_get_setting (device, NM_TYPE_SETTING_GSM));
+ priv->reg_tries = 0;
if (setting->network_id)
manual_registration (device);
else
@@ -361,13 +425,33 @@
}
static void
+power_up_response (NMSerialDevice *device,
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
+{
+ /* Ignore errors */
+ do_register (NM_GSM_DEVICE (device));
+}
+
+static void
+power_up (NMGsmDevice *device)
+{
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
+
+ nm_info ("(%s): powering up...", nm_device_get_iface (NM_DEVICE (device)));
+ modem_wait_for_reply (device, "AT+CFUN=1", 10, responses, responses, power_up_response, NULL);
+}
+
+static void
init_full_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
switch (reply_index) {
case 0:
- do_register (NM_GSM_DEVICE (device));
+ power_up (NM_GSM_DEVICE (device));
break;
case -1:
nm_warning ("Modem second stage initialization timed out");
@@ -387,19 +471,20 @@
static void
init_modem_full (NMGsmDevice *device)
{
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
/* Send E0 too because some devices turn echo back on after CPIN which
* just breaks stuff since echo-ed commands are interpreted as replies.
* rh #456770
*/
- modem_wait_for_reply (device, "ATZ E0", 10, responses, responses, init_full_done, NULL);
+ modem_wait_for_reply (device, "ATZ E0 V1 X4 &C1 +FCLASS=0", 10, responses, responses, init_full_done, NULL);
}
static void
enter_pin_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
NMSettingGsm *setting;
@@ -464,13 +549,13 @@
secret_name = NM_SETTING_GSM_PUK;
break;
default:
- do_register (device);
+ power_up (device);
return;
}
if (secret) {
char *command;
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
command = g_strdup_printf ("AT+CPIN=\"%s\"", secret);
modem_wait_for_reply (device, command, 3, responses, responses, enter_pin_done, NULL);
@@ -491,12 +576,13 @@
static void
check_pin_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
switch (reply_index) {
case 0:
- do_register (NM_GSM_DEVICE (device));
+ power_up (NM_GSM_DEVICE (device));
break;
case 1:
NM_GSM_DEVICE_GET_PRIVATE (device)->need_secret = NM_GSM_SECRET_PIN;
@@ -524,16 +610,17 @@
static void
check_pin (NMGsmDevice *self)
{
- char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
- char *terminators[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
+ const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
modem_wait_for_reply (self, "AT+CPIN?", 3, responses, terminators, check_pin_done, NULL);
}
static void
init_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
switch (reply_index) {
case 0:
@@ -557,9 +644,9 @@
static void
init_modem (NMSerialDevice *device, gpointer user_data)
{
- char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
- modem_wait_for_reply (NM_GSM_DEVICE (device), "AT E0", 10, responses, responses, init_done, NULL);
+ modem_wait_for_reply (NM_GSM_DEVICE (device), "ATZ E0 V1 X4 &C1 +FCLASS=0", 10, responses, responses, init_done, NULL);
}
static NMActStageReturn
@@ -680,12 +767,15 @@
{
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
+ priv->reg_tries = 0;
+
if (priv->pending_id) {
g_source_remove (priv->pending_id);
priv->pending_id = 0;
}
- NM_DEVICE_CLASS (nm_gsm_device_parent_class)->deactivate_quickly (device);
+ if (NM_DEVICE_CLASS (nm_gsm_device_parent_class)->deactivate_quickly)
+ NM_DEVICE_CLASS (nm_gsm_device_parent_class)->deactivate_quickly (device);
}
/*****************************************************************************/
@@ -793,10 +883,7 @@
priv->state_to_disconnected_id = 0;
}
- /* If transitioning to UNAVAILBLE and we have a carrier, transition to
- * DISCONNECTED because the device is ready to use. Otherwise the carrier-on
- * handler will handle the transition to DISCONNECTED when the carrier is detected.
- */
+ /* Transition to DISCONNECTED from an idle handler */
if (new_state == NM_DEVICE_STATE_UNAVAILABLE)
priv->state_to_disconnected_id = g_idle_add (unavailable_to_disconnected, self);
Modified: trunk/src/nm-hso-gsm-device.c
==============================================================================
--- trunk/src/nm-hso-gsm-device.c (original)
+++ trunk/src/nm-hso-gsm-device.c Sun Sep 28 22:55:40 2008
@@ -64,12 +64,12 @@
static void
modem_wait_for_reply (NMGsmDevice *self,
- const char *command,
- guint timeout,
- char **responses,
- char **terminators,
- NMSerialWaitForReplyFn callback,
- gpointer user_data)
+ const char *command,
+ guint timeout,
+ const char **responses,
+ const char **terminators,
+ NMSerialWaitForReplyFn callback,
+ gpointer user_data)
{
NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
guint id = 0;
@@ -81,23 +81,6 @@
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
}
-static void
-modem_get_reply (NMGsmDevice *self,
- const char *command,
- guint timeout,
- const char *terminators,
- NMSerialGetReplyFn callback)
-{
- NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
- guint id = 0;
-
- if (nm_serial_device_send_command_string (serial, command))
- id = nm_serial_device_get_reply (serial, timeout, terminators, callback, NULL);
-
- if (id == 0)
- nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_UNKNOWN);
-}
-
static NMSetting *
gsm_device_get_setting (NMGsmDevice *device, GType setting_type)
{
@@ -119,6 +102,7 @@
static void
hso_call_done (NMSerialDevice *device,
int reply_index,
+ const char *reply,
gpointer user_data)
{
gboolean success = FALSE;
@@ -141,10 +125,11 @@
static void
hso_clear_done (NMSerialDevice *device,
- int reply_index,
- gpointer user_data)
+ int reply_index,
+ const char *reply,
+ gpointer user_data)
{
- char *responses[] = { "_OWANCALL: ", "ERROR", NULL };
+ const char *responses[] = { "_OWANCALL: ", "ERROR", NULL };
guint cid = GPOINTER_TO_UINT (user_data);
char *command;
@@ -157,10 +142,11 @@
static void
hso_auth_done (NMSerialDevice *device,
int reply_index,
+ const char *reply,
gpointer user_data)
{
gboolean success = FALSE;
- char *responses[] = { "_OWANCALL: ", "ERROR", "NO CARRIER", NULL };
+ const char *responses[] = { "_OWANCALL: ", "ERROR", "NO CARRIER", NULL };
guint cid = GPOINTER_TO_UINT (user_data);
char *command;
@@ -190,7 +176,7 @@
{
NMSettingGsm *s_gsm;
NMActRequest *req;
- char *responses[] = { "OK", "ERROR", NULL };
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
char *command;
guint cid;
@@ -269,9 +255,10 @@
#define OWANDATA_TAG "_OWANDATA: "
static void
-hso_ip4_config_done (NMSerialDevice *device,
- const char *response,
- gpointer user_data)
+hso_ip4_config_response (NMSerialDevice *device,
+ int reply_index,
+ const char *response,
+ gpointer user_data)
{
NMHsoGsmDevicePrivate *priv = NM_HSO_GSM_DEVICE_GET_PRIVATE (device);
NMActRequest *req;
@@ -280,7 +267,9 @@
NMSettingIP4Address addr = { 0, 32, 0 };
guint32 dns1 = 0, dns2 = 0;
- if (!response || strncmp (response, OWANDATA_TAG, strlen (OWANDATA_TAG))) {
+ if ( (reply_index < 0)
+ || !response
+ || strncmp (response, OWANDATA_TAG, strlen (OWANDATA_TAG))) {
nm_device_activate_schedule_stage4_ip_config_timeout (NM_DEVICE (device));
return;
}
@@ -338,17 +327,18 @@
static NMActStageReturn
real_act_stage3_ip_config_start (NMDevice *device, NMDeviceStateReason *reason)
{
- const char terminators[] = { '\r', '\n', '\0' };
NMActRequest *req;
char *command;
gint cid;
+ const char *responses[] = { "_OWANDATA: ", NULL };
+ const char *terminators[] = { "OK", "ERROR", "ERR", NULL };
req = nm_device_get_act_request (device);
g_assert (req);
cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID));
command = g_strdup_printf ("AT_OWANDATA=%d", cid);
- modem_get_reply (NM_GSM_DEVICE (device), command, 5, terminators, hso_ip4_config_done);
+ modem_wait_for_reply (NM_GSM_DEVICE (device), command, 5, responses, terminators, hso_ip4_config_response, NULL);
g_free (command);
return NM_ACT_STAGE_RETURN_POSTPONE;
@@ -410,18 +400,19 @@
if (req) {
cid = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (req), GSM_CID));
if (cid) {
- command = g_strdup_printf ("AT_OWANCALL=%d,0,1", cid);
- nm_serial_device_send_command_string (NM_SERIAL_DEVICE (device), command);
- g_free (command);
+ const char *responses[] = { "OK", "ERROR", "ERR", NULL };
+ int reply;
- /* FIXME: doesn't seem to take the command otherwise, perhaps since
- * the serial port gets closed right away
+ /* Disconnect and disable asynchonous notification to keep serial
+ * buffer empty after the OK.
*/
- g_usleep (G_USEC_PER_SEC / 3);
+ command = g_strdup_printf ("AT_OWANCALL=%d,0,0", cid);
+ nm_serial_device_send_command_string (NM_SERIAL_DEVICE (device), command);
+ reply = nm_serial_device_wait_reply_blocking (NM_SERIAL_DEVICE (device), 5, responses, responses);
+ g_free (command);
}
}
-
if (NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly)
NM_DEVICE_CLASS (nm_hso_gsm_device_parent_class)->deactivate_quickly (device);
}
Modified: trunk/src/nm-serial-device.c
==============================================================================
--- trunk/src/nm-serial-device.c (original)
+++ trunk/src/nm-serial-device.c Sun Sep 28 22:55:40 2008
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
#define _GNU_SOURCE /* for strcasestr() */
@@ -363,7 +363,7 @@
gboolean
nm_serial_device_open (NMSerialDevice *device,
- NMSettingSerial *setting)
+ NMSettingSerial *setting)
{
NMSerialDevicePrivate *priv;
const char *iface;
@@ -414,6 +414,12 @@
if (priv->pending_id)
g_source_remove (priv->pending_id);
+ if (priv->ppp_manager) {
+ nm_ppp_manager_stop (priv->ppp_manager);
+ g_object_unref (priv->ppp_manager);
+ priv->ppp_manager = NULL;
+ }
+
if (priv->fd) {
nm_debug ("Closing device '%s'", nm_device_get_iface (NM_DEVICE (device)));
@@ -433,33 +439,41 @@
{
int fd;
NMSettingSerial *setting;
- int i;
- ssize_t status;
+ int i, eagain_count = 1000;
+ ssize_t written;
+ guint32 send_delay = G_USEC_PER_SEC / 1000;
g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE);
g_return_val_if_fail (command != NULL, FALSE);
fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
setting = NM_SETTING_SERIAL (serial_device_get_setting (device, NM_TYPE_SETTING_SERIAL));
+ if (setting && setting->send_delay)
+ send_delay = setting->send_delay;
serial_debug ("Sending:", (char *) command->data, command->len);
- for (i = 0; i < command->len; i++) {
- again:
- status = write (fd, command->data + i, 1);
-
- if (status < 0) {
- if (errno == EAGAIN)
- goto again;
+ for (i = 0; i < command->len && eagain_count > 0;) {
+ written = write (fd, command->data + i, 1);
- g_warning ("Error in writing (errno %d)", errno);
- return FALSE;
+ if (written > 0)
+ i += written;
+ else {
+ /* Treat written == 0 as EAGAIN to ensure we break out of the
+ * for() loop eventually.
+ */
+ if ((written < 0) && (errno != EAGAIN)) {
+ g_warning ("Error in writing (errno %d)", errno);
+ return FALSE;
+ }
+ eagain_count--;
}
-
- if (setting->send_delay)
- usleep (setting->send_delay);
+ g_usleep (send_delay);
}
+ if (eagain_count <= 0)
+ serial_debug ("Error: too many retries sending:", (char *) command->data, command->len);
+
return TRUE;
}
@@ -482,117 +496,121 @@
return ret;
}
-typedef struct {
- NMSerialDevice *device;
- char *terminators;
- GString *result;
- NMSerialGetReplyFn callback;
- gpointer user_data;
-} GetReplyInfo;
-
-static void
-get_reply_done (gpointer data)
+static gboolean
+find_terminator (const char *line, const char **terminators)
{
- GetReplyInfo *info = (GetReplyInfo *) data;
-
- nm_serial_device_pending_done (info->device);
+ int i;
- /* Call the callback */
- info->callback (info->device, info->result->str, info->user_data);
+ for (i = 0; terminators[i]; i++) {
+ if (!strncasecmp (line, terminators[i], strlen (terminators[i])))
+ return TRUE;
+ }
+ return FALSE;
+}
- /* Free info */
- g_free (info->terminators);
- g_string_free (info->result, TRUE);
+static const char *
+find_response (const char *line, const char **responses, gint *idx)
+{
+ int i;
- g_slice_free (GetReplyInfo, info);
+ /* Don't look for a result again if we got one previously */
+ for (i = 0; responses[i]; i++) {
+ if (strcasestr (line, responses[i])) {
+ *idx = i;
+ return line;
+ }
+ }
+ return NULL;
}
-static gboolean
-get_reply_got_data (GIOChannel *source,
- GIOCondition condition,
- gpointer data)
+#define RESPONSE_LINE_MAX 128
+
+int
+nm_serial_device_wait_reply_blocking (NMSerialDevice *device,
+ guint32 timeout_secs,
+ const char **needles,
+ const char **terminators)
{
- GetReplyInfo *info = (GetReplyInfo *) data;
- gsize bytes_read;
char buf[SERIAL_BUF_SIZE + 1];
- GIOStatus status;
+ int fd, reply_index = -1, bytes_read;
+ GString *result = NULL;
+ time_t end;
+ const char *response = NULL;
gboolean done = FALSE;
- int i;
- if (condition & G_IO_HUP || condition & G_IO_ERR) {
- g_string_truncate (info->result, 0);
- return FALSE;
- }
+ g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), -1);
+ g_return_val_if_fail (timeout_secs <= 60, -1);
+ g_return_val_if_fail (needles != NULL, -1);
+
+ fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
+ if (fd < 0)
+ return -1;
+ end = time (NULL) + timeout_secs;
+ result = g_string_sized_new (20);
do {
- GError *err = NULL;
+ bytes_read = read (fd, buf, SERIAL_BUF_SIZE);
+ if (bytes_read < 0 && errno != EAGAIN) {
+ nm_warning ("%s: read error: %d (%s)",
+ nm_device_get_iface (NM_DEVICE (device)),
+ errno,
+ strerror (errno));
+ return -1;
+ }
- 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 (bytes_read == 0)
+ break; /* EOF */
+ else if (bytes_read > 0) {
+ buf[bytes_read] = 0;
+ g_string_append (result, buf);
+
+ serial_debug ("Got:", result->str, result->len);
}
- if (bytes_read > 0) {
- char *p;
+ /* Look for needles and terminators */
+ if ((bytes_read > 0) && result->str) {
+ char *p = result->str;
- serial_debug ("Got:", buf, bytes_read);
+ /* Break the response up into lines and process each one */
+ while ((p < result->str + strlen (result->str)) && !done) {
+ char line[RESPONSE_LINE_MAX] = { '\0', };
+ char *tmp;
+ int i;
+ gboolean got_something = FALSE;
- p = &buf[0];
- for (i = 0; i < bytes_read && !done; i++, p++) {
- int j;
- gboolean is_terminator = FALSE;
-
- for (j = 0; j < strlen (info->terminators); j++) {
- if (*p == info->terminators[j]) {
- is_terminator = TRUE;
- break;
+ for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) {
+ /* Ignore front CR/LF */
+ if ((*p == '\n') || (*p == '\r')) {
+ if (got_something)
+ break;
+ } else {
+ line[i++] = *p;
+ got_something = TRUE;
}
}
+ line[i] = '\0';
- if (is_terminator) {
- /* Ignore terminators in the beginning of the output */
- if (info->result->len > 0)
- done = TRUE;
- } else
- g_string_append_c (info->result, *p);
+ tmp = g_strstrip (line);
+ if (tmp && strlen (tmp)) {
+ done = find_terminator (tmp, terminators);
+ if (reply_index == -1)
+ response = find_response (tmp, needles, &reply_index);
+ }
}
}
/* Limit the size of the buffer */
- if (info->result->len > SERIAL_BUF_SIZE) {
+ if (result->len > SERIAL_BUF_SIZE) {
g_warning ("%s (%s): response buffer filled before repsonse received",
- __func__, nm_device_get_iface (NM_DEVICE (info->device)));
- g_string_truncate (info->result, 0);
- done = TRUE;
+ __func__, nm_device_get_iface (NM_DEVICE (device)));
+ break;
}
- } while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
-
- return !done;
-}
-guint
-nm_serial_device_get_reply (NMSerialDevice *device,
- guint timeout,
- const char *terminators,
- NMSerialGetReplyFn callback,
- gpointer user_data)
-{
- GetReplyInfo *info;
+ if (!done)
+ g_usleep (100);
+ } while (!done && (time (NULL) < end));
- g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0);
- g_return_val_if_fail (terminators != NULL, 0);
- g_return_val_if_fail (callback != NULL, 0);
-
- info = g_slice_new0 (GetReplyInfo);
- info->device = device;
- info->terminators = g_strdup (terminators);
- info->result = g_string_new (NULL);
- info->callback = callback;
- info->user_data = user_data;
-
- return nm_serial_device_set_pending (device, timeout, get_reply_got_data, info, get_reply_done);
+ return reply_index;
}
typedef struct {
@@ -603,8 +621,8 @@
NMSerialWaitForReplyFn callback;
gpointer user_data;
int reply_index;
- guint timeout;
- time_t start;
+ char *reply_line;
+ time_t end;
} WaitForReplyInfo;
static void
@@ -615,47 +633,20 @@
nm_serial_device_pending_done (info->device);
/* Call the callback */
- info->callback (info->device, info->reply_index, info->user_data);
+ info->callback (info->device, info->reply_index, info->reply_line, info->user_data);
/* Free info */
if (info->result)
g_string_free (info->result, TRUE);
+ g_free (info->reply_line);
+
g_strfreev (info->str_needles);
g_strfreev (info->terminators);
g_slice_free (WaitForReplyInfo, info);
}
static gboolean
-find_terminator (const char *line, char **terminators)
-{
- int i;
-
- for (i = 0; terminators[i]; i++) {
- if (!strncasecmp (line, terminators[i], strlen (terminators[i])))
- return TRUE;
- }
- return FALSE;
-}
-
-static gboolean
-find_response (const char *line, char **responses, gint *idx)
-{
- int i;
-
- /* Don't look for a result again if we got one previously */
- for (i = 0; responses[i]; i++) {
- if (strcasestr (line, responses[i])) {
- *idx = i;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-#define RESPONSE_LINE_MAX 128
-
-static gboolean
wait_for_reply_got_data (GIOChannel *source,
GIOCondition condition,
gpointer data)
@@ -664,7 +655,6 @@
gchar buf[SERIAL_BUF_SIZE + 1];
gsize bytes_read;
GIOStatus status;
- gboolean got_response = FALSE;
gboolean done = FALSE;
if (condition & G_IO_HUP || condition & G_IO_ERR)
@@ -692,8 +682,7 @@
char *p = info->result->str;
/* Break the response up into lines and process each one */
- while ( (p < info->result->str + strlen (info->result->str))
- && !(done && got_response)) {
+ while ((p < info->result->str + strlen (info->result->str)) && !done) {
char line[RESPONSE_LINE_MAX] = { '\0', };
char *tmp;
int i;
@@ -713,20 +702,19 @@
tmp = g_strstrip (line);
if (tmp && strlen (tmp)) {
- done = find_terminator (tmp, info->terminators);
- if (info->reply_index == -1)
- got_response = find_response (tmp, info->str_needles, &(info->reply_index));
+ done = find_terminator (tmp, (const char **) info->terminators);
+ if (info->reply_index == -1) {
+ if (find_response (tmp, (const char **) info->str_needles, &(info->reply_index)))
+ info->reply_line = g_strdup (tmp);
+ }
}
}
-
- if (done && got_response)
- break;
}
/* Limit the size of the buffer */
if (info->result->len > SERIAL_BUF_SIZE) {
- g_warning ("%s (%s): response buffer filled before repsonse received",
- __func__, nm_device_get_iface (NM_DEVICE (info->device)));
+ nm_warning ("(%s): response buffer filled before repsonse received",
+ nm_device_get_iface (NM_DEVICE (info->device)));
done = TRUE;
break;
}
@@ -736,10 +724,10 @@
* terminate (terminator not found, whatever) then this should make
* sure that NM doesn't spin the CPU forever.
*/
- if (time (NULL) - info->start > info->timeout + 1) {
+ if (time (NULL) > info->end) {
done = TRUE;
break;
- } else
+ } else if (!done)
g_usleep (50);
} while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
@@ -748,11 +736,11 @@
guint
nm_serial_device_wait_for_reply (NMSerialDevice *device,
- guint timeout,
- char **responses,
- char **terminators,
- NMSerialWaitForReplyFn callback,
- gpointer user_data)
+ guint timeout,
+ const char **responses,
+ const char **terminators,
+ NMSerialWaitForReplyFn callback,
+ gpointer user_data)
{
WaitForReplyInfo *info;
@@ -762,14 +750,13 @@
info = g_slice_new0 (WaitForReplyInfo);
info->device = device;
- info->str_needles = g_strdupv (responses);
- info->terminators = g_strdupv (terminators);
+ info->str_needles = g_strdupv ((char **) responses);
+ info->terminators = g_strdupv ((char **) terminators);
info->result = g_string_new (NULL);
info->callback = callback;
info->user_data = user_data;
info->reply_index = -1;
- info->timeout = timeout;
- info->start = time (NULL);
+ info->end = time (NULL) + timeout;
return nm_serial_device_set_pending (device, timeout, wait_for_reply_got_data, info, wait_for_reply_done);
}
@@ -1074,12 +1061,11 @@
}
static void
-real_deactivate_quickly (NMDevice *device)
+cleanup_device (NMSerialDevice *device)
{
- NMSerialDevice *self = NM_SERIAL_DEVICE (device);
NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
- nm_device_set_ip_iface (device, NULL);
+ nm_device_set_ip_iface (NM_DEVICE (device), NULL);
if (priv->pending_ip4_config) {
g_object_unref (priv->pending_ip4_config);
@@ -1087,12 +1073,14 @@
}
priv->in_bytes = priv->out_bytes = 0;
+}
- if (priv->ppp_manager) {
- g_object_unref (priv->ppp_manager);
- priv->ppp_manager = NULL;
- }
+static void
+real_deactivate_quickly (NMDevice *device)
+{
+ NMSerialDevice *self = NM_SERIAL_DEVICE (device);
+ cleanup_device (self);
nm_serial_device_close (self);
}
@@ -1114,6 +1102,7 @@
{
NMSerialDevice *self = NM_SERIAL_DEVICE (object);
+ cleanup_device (self);
nm_serial_device_close (self);
G_OBJECT_CLASS (nm_serial_device_parent_class)->finalize (object);
Modified: trunk/src/nm-serial-device.h
==============================================================================
--- trunk/src/nm-serial-device.h (original)
+++ trunk/src/nm-serial-device.h Sun Sep 28 22:55:40 2008
@@ -34,8 +34,9 @@
gpointer user_data);
typedef void (*NMSerialWaitForReplyFn) (NMSerialDevice *device,
- int reply_index,
- gpointer user_data);
+ int reply_index,
+ const char *reply,
+ gpointer user_data);
typedef void (*NMSerialWaitQuietFn) (NMSerialDevice *device,
gboolean timed_out,
@@ -56,16 +57,15 @@
gboolean nm_serial_device_send_command_string (NMSerialDevice *device,
const char *str);
-guint nm_serial_device_get_reply (NMSerialDevice *device,
- guint timeout,
- const char *terminators,
- NMSerialGetReplyFn callback,
- gpointer user_data);
+int nm_serial_device_wait_reply_blocking (NMSerialDevice *device,
+ guint32 timeout_secs,
+ const char **needles,
+ const char **terminators);
guint nm_serial_device_wait_for_reply (NMSerialDevice *device,
guint timeout,
- char **responses,
- char **terminators,
+ const char **responses,
+ const char **terminators,
NMSerialWaitForReplyFn callback,
gpointer user_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]