2008-06-30 Tambet Ingo <tambet@gmail.com>

* src/nm-serial-device.c:
	* src/nm-gsm-device.c:
	* src/nm-cdma-device.c: Move the pending call handling to a common location
	in serial device. Handle setting device state to failed in one place as well.


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3782 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Tambet Ingo 2008-06-30 12:18:57 +00:00
parent 01ea95f444
commit 5cc268ab0e
4 changed files with 253 additions and 337 deletions

View file

@ -1,3 +1,10 @@
2008-06-30 Tambet Ingo <tambet@gmail.com>
* src/nm-serial-device.c:
* src/nm-gsm-device.c:
* src/nm-cdma-device.c: Move the pending call handling to a common location
in serial device. Handle setting device state to failed in one place as well.
2008-06-29 Dan Williams <dcbw@redhat.com>
* src/nm-hal-manager.c

View file

@ -19,7 +19,6 @@ typedef struct {
char *monitor_iface;
NMSerialDevice *monitor_device;
guint pending_id;
guint state_to_disconnected_id;
} NMCdmaDevicePrivate;
@ -59,12 +58,6 @@ nm_cdma_device_new (const char *udi,
NULL);
}
static inline void
cdma_device_set_pending (NMCdmaDevice *device, guint pending_id)
{
NM_CDMA_DEVICE_GET_PRIVATE (device)->pending_id = pending_id;
}
static NMSetting *
cdma_device_get_setting (NMCdmaDevice *device, GType setting_type)
{
@ -90,8 +83,6 @@ dial_done (NMSerialDevice *device,
{
gboolean success = FALSE;
cdma_device_set_pending (NM_CDMA_DEVICE (device), 0);
switch (reply_index) {
case 0:
nm_info ("Connected, Woo!");
@ -125,25 +116,18 @@ do_dial (NMSerialDevice *device)
{
NMSettingCdma *setting;
char *command;
guint id;
guint id = 0;
char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
gboolean success;
setting = NM_SETTING_CDMA (cdma_device_get_setting (NM_CDMA_DEVICE (device), NM_TYPE_SETTING_CDMA));
command = g_strconcat ("ATDT", setting->number, NULL);
success = nm_serial_device_send_command_string (device, command);
if (nm_serial_device_send_command_string (device, command))
id = nm_serial_device_wait_for_reply (device, 60, responses, responses, dial_done, NULL);
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 60, responses, responses, dial_done, NULL);
if (id)
cdma_device_set_pending (NM_CDMA_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
} else {
if (id == 0)
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
}
}
static void
@ -151,8 +135,6 @@ init_done (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
cdma_device_set_pending (NM_CDMA_DEVICE (device), 0);
switch (reply_index) {
case 0:
do_dial (device);
@ -171,37 +153,31 @@ init_done (NMSerialDevice *device,
static void
init_modem (NMSerialDevice *device, gpointer user_data)
{
guint id;
guint id = 0;
char *responses[] = { "OK", "ERROR", "ERR", NULL };
if (!nm_serial_device_send_command_string (device, "ATZ E0")) {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
return;
}
if (nm_serial_device_send_command_string (device, "ATZ E0"))
id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
if (id)
cdma_device_set_pending (NM_CDMA_DEVICE (device), id);
else
if (id == 0)
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
}
static NMActStageReturn
real_act_stage1_prepare (NMDevice *device)
{
NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (device);
NMSerialDevice *serial_device = NM_SERIAL_DEVICE (device);
NMSettingSerial *setting;
guint id;
setting = NM_SETTING_SERIAL (cdma_device_get_setting (NM_CDMA_DEVICE (device), NM_TYPE_SETTING_SERIAL));
if (!nm_serial_device_open (serial_device, setting))
return NM_ACT_STAGE_RETURN_FAILURE;
priv->pending_id = nm_serial_device_flash (serial_device, 100, init_modem, NULL);
id = nm_serial_device_flash (serial_device, 100, init_modem, NULL);
return priv->pending_id ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE;
return id ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE;
}
static NMConnection *
@ -267,19 +243,6 @@ real_connection_secrets_updated (NMDevice *dev,
nm_device_activate_schedule_stage1_device_prepare (dev);
}
static void
real_deactivate_quickly (NMDevice *device)
{
NMCdmaDevicePrivate *priv = NM_CDMA_DEVICE_GET_PRIVATE (device);
if (priv->pending_id) {
g_source_remove (priv->pending_id);
priv->pending_id = 0;
}
NM_DEVICE_CLASS (nm_cdma_device_parent_class)->deactivate_quickly (device);
}
/*****************************************************************************/
/* Monitor device handling */
@ -496,7 +459,6 @@ nm_cdma_device_class_init (NMCdmaDeviceClass *klass)
device_class->get_generic_capabilities = real_get_generic_capabilities;
device_class->act_stage1_prepare = real_act_stage1_prepare;
device_class->connection_secrets_updated = real_connection_secrets_updated;
device_class->deactivate_quickly = real_deactivate_quickly;
/* Properties */
g_object_class_install_property

View file

@ -45,8 +45,8 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
static void enter_pin (NMSerialDevice *device, gboolean retry);
static void automatic_registration (NMSerialDevice *device);
static void enter_pin (NMGsmDevice *device, gboolean retry);
static void automatic_registration (NMGsmDevice *device);
NMGsmDevice *
nm_gsm_device_new (const char *udi,
@ -68,10 +68,39 @@ nm_gsm_device_new (const char *udi,
NULL);
}
static inline void
gsm_device_set_pending (NMGsmDevice *device, guint pending_id)
static void
modem_wait_for_reply (NMGsmDevice *self,
const char *command,
guint timeout,
char **responses,
char **terminators,
NMSerialWaitForReplyFn callback)
{
NM_GSM_DEVICE_GET_PRIVATE (device)->pending_id = pending_id;
NMSerialDevice *serial = NM_SERIAL_DEVICE (self);
guint id = 0;
if (nm_serial_device_send_command_string (serial, command))
id = nm_serial_device_wait_for_reply (serial, timeout, responses, terminators, callback, NULL);
if (id == 0)
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED);
}
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);
}
static NMSetting *
@ -99,8 +128,6 @@ dial_done (NMSerialDevice *device,
{
gboolean success = FALSE;
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
nm_info ("Connected, Woo!");
@ -130,13 +157,11 @@ dial_done (NMSerialDevice *device,
}
static void
do_dial (NMSerialDevice *device, guint cid)
do_dial (NMGsmDevice *device, guint cid)
{
NMSettingGsm *setting;
char *command;
guint id;
char *responses[] = { "CONNECT", "BUSY", "NO DIAL TONE", "NO CARRIER", NULL };
gboolean success;
setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM));
@ -154,18 +179,8 @@ do_dial (NMSerialDevice *device, guint cid)
} else
command = g_strconcat ("ATDT", setting->number, NULL);
success = nm_serial_device_send_command_string (device, command);
modem_wait_for_reply (device, command, 60, responses, responses, dial_done);
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 60, responses, responses, dial_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
} else {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
}
}
static void
@ -173,13 +188,9 @@ set_apn_done (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
guint cid = GPOINTER_TO_UINT (user_data);
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
do_dial (device, cid);
do_dial (NM_GSM_DEVICE (device), 1);
break;
default:
nm_warning ("Setting APN failed");
@ -189,13 +200,11 @@ set_apn_done (NMSerialDevice *device,
}
static void
set_apn (NMSerialDevice *device)
set_apn (NMGsmDevice *device)
{
NMSettingGsm *setting;
char *command;
char *responses[] = { "OK", "ERROR", NULL };
gboolean success;
guint id = 0;
guint cid = 1;
setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM));
@ -207,16 +216,8 @@ set_apn (NMSerialDevice *device)
}
command = g_strdup_printf ("AT+CGDCONT=%d, \"IP\", \"%s\"", cid, setting->apn);
success = nm_serial_device_send_command_string (device, command);
modem_wait_for_reply (device, command, 3, responses, responses, set_apn_done);
g_free (command);
if (success)
id = nm_serial_device_wait_for_reply (device, 3, responses, responses, set_apn_done, GUINT_TO_POINTER (cid));
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
}
static void
@ -224,11 +225,9 @@ manual_registration_done (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
set_apn (device);
set_apn (NM_GSM_DEVICE (device));
break;
case -1:
nm_warning ("Manual registration timed out");
@ -242,29 +241,17 @@ manual_registration_done (NMSerialDevice *device,
}
static void
manual_registration (NMSerialDevice *device)
manual_registration (NMGsmDevice *device)
{
NMSettingGsm *setting;
char *command;
guint id;
char *responses[] = { "OK", "ERROR", "ERR", NULL };
gboolean success;
setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM));
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);
success = nm_serial_device_send_command_string (device, command);
modem_wait_for_reply (device, command, 30, responses, responses, manual_registration_done);
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 30, responses, responses, manual_registration_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
} else {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
}
}
static void
@ -272,38 +259,26 @@ get_network_done (NMSerialDevice *device,
const char *response,
gpointer user_data)
{
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
if (response)
nm_info ("Associated with network: %s", response);
else
nm_warning ("Couldn't read active network name");
set_apn (device);
set_apn (NM_GSM_DEVICE (device));
}
static void
automatic_registration_get_network (NMSerialDevice *device)
automatic_registration_get_network (NMGsmDevice *device)
{
guint id;
const char terminators[] = { '\r', '\n', '\0' };
if (!nm_serial_device_send_command_string (device, "AT+COPS?")) {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
return;
}
id = nm_serial_device_get_reply (device, 10, terminators, get_network_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
modem_get_reply (device, "AT+COPS?", 10, terminators, get_network_done);
}
static gboolean
automatic_registration_again (gpointer data)
{
automatic_registration (NM_SERIAL_DEVICE (data));
automatic_registration (NM_GSM_DEVICE (data));
return FALSE;
}
@ -312,20 +287,17 @@ automatic_registration_response (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
nm_info ("Registered on Home network");
automatic_registration_get_network (device);
automatic_registration_get_network (NM_GSM_DEVICE (device));
break;
case 1:
nm_info ("Registered on Roaming network");
automatic_registration_get_network (device);
automatic_registration_get_network (NM_GSM_DEVICE (device));
break;
case 2:
gsm_device_set_pending (NM_GSM_DEVICE (device),
g_timeout_add (1000, automatic_registration_again, device));
NM_GSM_DEVICE_GET_PRIVATE (device)->pending_id = g_timeout_add (1000, automatic_registration_again, device);
break;
case 3:
nm_warning ("Automatic registration failed: not registered and not searching.");
@ -343,30 +315,20 @@ automatic_registration_response (NMSerialDevice *device,
}
static void
automatic_registration (NMSerialDevice *device)
automatic_registration (NMGsmDevice *device)
{
guint id;
char *responses[] = { "+CREG: 0,1", "+CREG: 0,5", "+CREG: 0,2", "+CREG: 0,0", NULL };
char *terminators[] = { "OK", "ERROR", "ERR", NULL };
if (!nm_serial_device_send_command_string (device, "AT+CREG?")) {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
return;
}
id = nm_serial_device_wait_for_reply (device, 60, responses, terminators, automatic_registration_response, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
modem_wait_for_reply (device, "AT+CREG?", 60, responses, terminators, automatic_registration_response);
}
static void
do_register (NMSerialDevice *device)
do_register (NMGsmDevice *device)
{
NMSettingGsm *setting;
setting = NM_SETTING_GSM (gsm_device_get_setting (NM_GSM_DEVICE (device), NM_TYPE_SETTING_GSM));
setting = NM_SETTING_GSM (gsm_device_get_setting (device, NM_TYPE_SETTING_GSM));
if (setting->network_id)
manual_registration (device);
@ -379,11 +341,9 @@ init_full_done (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
do_register (device);
do_register (NM_GSM_DEVICE (device));
break;
case -1:
nm_warning ("Modem second stage initialization timed out");
@ -397,24 +357,11 @@ init_full_done (NMSerialDevice *device,
}
static void
init_modem_full (NMSerialDevice *device)
init_modem_full (NMGsmDevice *device)
{
guint id;
char *responses[] = { "OK", "ERROR", "ERR", NULL };
/* At this point we know that SIM has been unlocked, and we can safely
* initialize the modem
*/
if (!nm_serial_device_send_command_string (device, "ATZ")) {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
return;
}
id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_full_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
modem_wait_for_reply (device, "ATZ", 10, responses, responses, init_full_done);
}
static void
@ -424,10 +371,9 @@ enter_pin_done (NMSerialDevice *device,
{
NMSettingGsm *setting;
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
init_modem_full (device);
init_modem_full (NM_GSM_DEVICE (device));
break;
case -1:
nm_warning ("Did not receive response for secret");
@ -453,13 +399,13 @@ enter_pin_done (NMSerialDevice *device,
break;
}
enter_pin (device, TRUE);
enter_pin (NM_GSM_DEVICE (device), TRUE);
break;
}
}
static void
enter_pin (NMSerialDevice *device, gboolean retry)
enter_pin (NMGsmDevice *device, gboolean retry)
{
NMSettingGsm *setting;
NMActRequest *req;
@ -490,23 +436,11 @@ enter_pin (NMSerialDevice *device, gboolean retry)
if (secret) {
char *command;
guint id;
char *responses[] = { "OK", "ERROR", "ERR", NULL };
gboolean success;
command = g_strdup_printf ("AT+CPIN=\"%s\"", secret);
success = nm_serial_device_send_command_string (device, command);
modem_wait_for_reply (device, command, 3, responses, responses, enter_pin_done);
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 3, responses, responses, enter_pin_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
} else {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
}
} else {
nm_info ("(%s): GSM %s secret required", nm_device_get_iface (NM_DEVICE (device)), secret_name);
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_NEED_AUTH);
@ -519,19 +453,17 @@ check_pin_done (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
do_register (device);
do_register (NM_GSM_DEVICE (device));
break;
case 1:
NM_GSM_DEVICE_GET_PRIVATE (device)->need_secret = NM_GSM_SECRET_PIN;
enter_pin (device, FALSE);
enter_pin (NM_GSM_DEVICE (device), FALSE);
break;
case 2:
NM_GSM_DEVICE_GET_PRIVATE (device)->need_secret = NM_GSM_SECRET_PUK;
enter_pin (device, FALSE);
enter_pin (NM_GSM_DEVICE (device), FALSE);
break;
case -1:
nm_warning ("PIN checking timed out");
@ -545,22 +477,12 @@ check_pin_done (NMSerialDevice *device,
}
static void
check_pin (NMSerialDevice *device)
check_pin (NMGsmDevice *self)
{
guint id;
char *responses[] = { "READY", "SIM PIN", "SIM PUK", "ERROR", "ERR", NULL };
char *terminators[] = { "OK", "ERROR", "ERR", NULL };
if (!nm_serial_device_send_command_string (device, "AT+CPIN?")) {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
return;
}
id = nm_serial_device_wait_for_reply (device, 3, responses, terminators, check_pin_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
modem_wait_for_reply (self, "AT+CPIN?", 3, responses, terminators, check_pin_done);
}
static void
@ -568,11 +490,9 @@ init_done (NMSerialDevice *device,
int reply_index,
gpointer user_data)
{
gsm_device_set_pending (NM_GSM_DEVICE (device), 0);
switch (reply_index) {
case 0:
check_pin (device);
check_pin (NM_GSM_DEVICE (device));
break;
case -1:
nm_warning ("Modem initialization timed out");
@ -588,18 +508,9 @@ init_done (NMSerialDevice *device,
static void
init_modem (NMSerialDevice *device, gpointer user_data)
{
guint id;
char *responses[] = { "OK", "ERROR", "ERR", NULL };
if (!nm_serial_device_send_command_string (device, "ATZ E0")) {
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
return;
}
id = nm_serial_device_wait_for_reply (device, 10, responses, responses, init_done, NULL);
if (id)
gsm_device_set_pending (NM_GSM_DEVICE (device), id);
else
nm_device_state_changed (NM_DEVICE (device), NM_DEVICE_STATE_FAILED);
modem_wait_for_reply (NM_GSM_DEVICE (device), "AT E0", 10, responses, responses, init_done);
}
static NMActStageReturn
@ -608,6 +519,7 @@ real_act_stage1_prepare (NMDevice *device)
NMGsmDevicePrivate *priv = NM_GSM_DEVICE_GET_PRIVATE (device);
NMSerialDevice *serial_device = NM_SERIAL_DEVICE (device);
NMSettingSerial *setting;
guint id;
priv->need_secret = NM_GSM_SECRET_NONE;
@ -616,9 +528,9 @@ real_act_stage1_prepare (NMDevice *device)
if (!nm_serial_device_open (serial_device, setting))
return NM_ACT_STAGE_RETURN_FAILURE;
priv->pending_id = nm_serial_device_flash (serial_device, 100, init_modem, NULL);
id = nm_serial_device_flash (serial_device, 100, init_modem, NULL);
return priv->pending_id ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE;
return id ? NM_ACT_STAGE_RETURN_POSTPONE : NM_ACT_STAGE_RETURN_FAILURE;
}
static NMConnection *

View file

@ -36,6 +36,9 @@ typedef struct {
NMIP4Config *pending_ip4_config;
struct termios old_t;
guint pending_id;
guint timeout_id;
/* PPP stats */
guint32 in_bytes;
guint32 out_bytes;
@ -228,6 +231,98 @@ serial_device_get_setting (NMSerialDevice *device, GType setting_type)
return setting;
}
/* Timeout handling */
static void
nm_serial_device_timeout_removed (gpointer data)
{
NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (data);
priv->timeout_id = 0;
}
static gboolean
nm_serial_device_timed_out (gpointer data)
{
NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (data);
/* Cancel data reading */
if (priv->pending_id)
g_source_remove (priv->pending_id);
else
nm_warning ("Timeout reached, but there's nothing to time out");
return FALSE;
}
static void
nm_serial_device_add_timeout (NMSerialDevice *self, guint timeout)
{
NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self);
if (priv->pending_id == 0)
nm_warning ("Adding a time out while not waiting for any data");
if (priv->timeout_id) {
nm_warning ("Trying to add a new time out while the old one still exists");
g_source_remove (priv->timeout_id);
}
priv->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
timeout * 1000,
nm_serial_device_timed_out,
self,
nm_serial_device_timeout_removed);
if (G_UNLIKELY (priv->timeout_id == 0))
nm_warning ("Registering serial device time out failed.");
}
static void
nm_serial_device_remove_timeout (NMSerialDevice *self)
{
NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (self);
if (priv->timeout_id)
g_source_remove (priv->timeout_id);
}
/* Pending data reading */
static guint
nm_serial_device_set_pending (NMSerialDevice *device,
guint timeout,
GIOFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
NMSerialDevicePrivate *priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
if (G_UNLIKELY (priv->pending_id)) {
/* FIXME: Probably should queue up pending calls instead? */
/* Multiple pending calls on the same GIOChannel doesn't work, so let's cancel the previous one. */
nm_warning ("Adding new pending call while previous one isn't finished.");
nm_warning ("Cancelling the previous pending call.");
g_source_remove (priv->pending_id);
}
priv->pending_id = g_io_add_watch_full (priv->channel,
G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_ERR | G_IO_HUP,
callback, user_data, notify);
nm_serial_device_add_timeout (device, timeout);
return priv->pending_id;}
static void
nm_serial_device_pending_done (NMSerialDevice *self)
{
NM_SERIAL_DEVICE_GET_PRIVATE (self)->pending_id = 0;
nm_serial_device_remove_timeout (self);
}
/****/
static gboolean
config_fd (NMSerialDevice *device, NMSettingSerial *setting)
{
@ -315,6 +410,9 @@ nm_serial_device_close (NMSerialDevice *device)
priv = NM_SERIAL_DEVICE_GET_PRIVATE (device);
if (priv->pending_id)
g_source_remove (priv->pending_id);
if (priv->fd) {
nm_debug ("Closing device '%s'", nm_device_get_iface (NM_DEVICE (device)));
@ -389,34 +487,23 @@ typedef struct {
GString *result;
NMSerialGetReplyFn callback;
gpointer user_data;
guint timeout_id;
guint got_data_id;
} GetReplyInfo;
static void
get_reply_info_destroy (gpointer data)
get_reply_done (gpointer data)
{
GetReplyInfo *info = (GetReplyInfo *) data;
if (info->got_data_id)
g_source_remove (info->got_data_id);
nm_serial_device_pending_done (info->device);
/* Call the callback */
info->callback (info->device, info->result->str, info->user_data);
/* Free info */
g_free (info->terminators);
g_string_free (info->result, TRUE);
if (info->result)
g_string_free (info->result, TRUE);
g_free (info);
}
static gboolean
get_reply_timeout (gpointer data)
{
GetReplyInfo *info = (GetReplyInfo *) data;
info->callback (info->device, NULL, info->user_data);
return FALSE;
g_slice_free (GetReplyInfo, info);
}
static gboolean
@ -431,8 +518,10 @@ get_reply_got_data (GIOChannel *source,
gboolean done = FALSE;
int i;
if (!(condition & G_IO_IN))
goto done;
if (condition & G_IO_HUP || condition & G_IO_ERR) {
g_string_truncate (info->result, 0);
return FALSE;
}
do {
GError *err = NULL;
@ -474,30 +563,11 @@ get_reply_got_data (GIOChannel *source,
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)));
g_string_free (info->result, TRUE);
info->result = NULL;
g_string_truncate (info->result, 0);
done = TRUE;
}
} while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
done:
if (condition & G_IO_HUP || condition & G_IO_ERR) {
g_string_free (info->result, TRUE);
info->result = NULL;
done = TRUE;
}
if (done) {
char *result = info->result ? g_string_free (info->result, FALSE) : NULL;
info->result = NULL;
info->callback (info->device, result, info->user_data);
g_free (result);
/* Clear the id - returning FALSE already removes it */
info->got_data_id = 0;
g_source_remove (info->timeout_id);
}
return !done;
}
@ -514,25 +584,14 @@ nm_serial_device_get_reply (NMSerialDevice *device,
g_return_val_if_fail (terminators != NULL, 0);
g_return_val_if_fail (callback != NULL, 0);
info = g_new (GetReplyInfo, 1);
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;
info->got_data_id = g_io_add_watch (NM_SERIAL_DEVICE_GET_PRIVATE (device)->channel,
G_IO_IN | G_IO_ERR | G_IO_HUP,
get_reply_got_data,
info);
info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
timeout * 1000,
get_reply_timeout,
info,
get_reply_info_destroy);
return info->timeout_id;
return nm_serial_device_set_pending (device, timeout, get_reply_got_data, info, get_reply_done);
}
typedef struct {
@ -542,36 +601,28 @@ typedef struct {
GString *result;
NMSerialWaitForReplyFn callback;
gpointer user_data;
int reply_index;
guint timeout;
time_t start;
guint timeout_id;
guint got_data_id;
} WaitForReplyInfo;
static void
wait_for_reply_info_destroy (gpointer data)
wait_for_reply_done (gpointer data)
{
WaitForReplyInfo *info = (WaitForReplyInfo *) data;
if (info->got_data_id)
g_source_remove (info->got_data_id);
nm_serial_device_pending_done (info->device);
/* Call the callback */
info->callback (info->device, info->reply_index, info->user_data);
/* Free info */
if (info->result)
g_string_free (info->result, TRUE);
g_strfreev (info->str_needles);
g_strfreev (info->terminators);
g_free (info);
}
static gboolean
wait_for_reply_timeout (gpointer data)
{
WaitForReplyInfo *info = (WaitForReplyInfo *) data;
info->callback (info->device, -1, info->user_data);
return FALSE;
g_slice_free (WaitForReplyInfo, info);
}
static gboolean
@ -614,10 +665,9 @@ wait_for_reply_got_data (GIOChannel *source,
GIOStatus status;
gboolean got_response = FALSE;
gboolean done = FALSE;
int idx = -1;
if (!(condition & G_IO_IN))
goto done;
if (condition & G_IO_HUP || condition & G_IO_ERR)
return FALSE;
do {
GError *err = NULL;
@ -663,8 +713,8 @@ wait_for_reply_got_data (GIOChannel *source,
tmp = g_strstrip (line);
if (tmp && strlen (tmp)) {
done = find_terminator (tmp, info->terminators);
if (idx == -1)
got_response = find_response (tmp, info->str_needles, &idx);
if (info->reply_index == -1)
got_response = find_response (tmp, info->str_needles, &(info->reply_index));
}
}
@ -692,18 +742,6 @@ wait_for_reply_got_data (GIOChannel *source,
g_usleep (50);
} while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
done:
if (condition & G_IO_HUP || condition & G_IO_ERR)
done = TRUE;
if (done) {
info->callback (info->device, idx, info->user_data);
/* Clear the id - returning FALSE already removes it */
info->got_data_id = 0;
g_source_remove (info->timeout_id);
}
return !done;
}
@ -721,28 +759,18 @@ nm_serial_device_wait_for_reply (NMSerialDevice *device,
g_return_val_if_fail (responses != NULL, 0);
g_return_val_if_fail (callback != NULL, 0);
info = g_new0 (WaitForReplyInfo, 1);
info = g_slice_new0 (WaitForReplyInfo);
info->device = device;
info->str_needles = g_strdupv (responses);
info->terminators = g_strdupv (terminators);
info->result = g_string_new (NULL);
info->callback = callback;
info->user_data = user_data;
info->got_data_id = g_io_add_watch (NM_SERIAL_DEVICE_GET_PRIVATE (device)->channel,
G_IO_IN | G_IO_ERR | G_IO_HUP,
wait_for_reply_got_data,
info);
info->reply_index = -1;
info->timeout = timeout * 1000;
info->start = time (NULL);
info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
timeout * 1000,
wait_for_reply_timeout,
info,
wait_for_reply_info_destroy);
return info->timeout_id;
return nm_serial_device_set_pending (device, timeout, wait_for_reply_got_data, info, wait_for_reply_done);
}
#if 0
@ -753,14 +781,18 @@ typedef struct {
gpointer user_data;
} WaitQuietInfo;
static gboolean
static void
wait_quiet_done (gpointer data)
{
WaitQuietInfo *info = (WaitQuietInfo *) data;
nm_serial_device_pending_done (info->device);
/* Call the callback */
info->callback (info->device, info->timed_out, info->user_data);
return FALSE;
/* Free info */
g_slice_free (WaitQuietInfo, info);
}
static gboolean
@ -769,7 +801,7 @@ wait_quiet_quiettime (gpointer data)
WaitQuietInfo *info = (WaitQuietInfo *) data;
info->timed_out = FALSE;
wait_quiet_done (data);
g_source_remove (NM_SERIAL_DEVICE_GET_PRIVATE (info->device)->pending);
return FALSE;
}
@ -784,6 +816,9 @@ wait_quiet_got_data (GIOChannel *source,
char buf[4096];
GIOStatus status;
if (condition & G_IO_HUP || condition & G_IO_ERR)
return FALSE;
if (condition & G_IO_IN) {
do {
status = g_io_channel_read_chars (source, buf, 4096, &bytes_read, NULL);
@ -796,11 +831,6 @@ wait_quiet_got_data (GIOChannel *source,
} while (bytes_read == 4096 || status == G_IO_STATUS_AGAIN);
}
if (condition & G_IO_HUP || condition & G_IO_ERR) {
wait_quiet_done (data);
return FALSE
}
return TRUE;
}
@ -816,27 +846,16 @@ nm_serial_device_wait_quiet (NMSerialDevice *device,
g_return_if_fail (NM_IS_SERIAL_DEVICE (device));
g_return_if_fail (callback != NULL);
info = g_new (WaitQuietInfo, 1);
info = g_slice_new0 (WaitQuietInfo);
info->device = device;
info->timed_out = TRUE;
info->callback = callback;
info->user_data = user_data;
info->got_data_id = g_io_add_watch (NM_SERIAL_DEVICE_GET_PRIVATE (device)->channel,
G_IO_IN | G_IO_ERR | G_IO_HUP,
wait_quiet_got_data,
info);
info->quiet_id = g_timeout_add (quiet_time,
wait_quiet_timeout,
info);
info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
timeout,
wait_quiet_timeout,
info,
wait_quiet_info_destroy);
return nm_serial_device_set_pending (device, timeout, wait_quiet_got_data, info, wait_quiet_done);
}
#endif
@ -874,14 +893,25 @@ set_speed (NMSerialDevice *device, speed_t speed)
tcsetattr (fd, TCSANOW, &options);
}
static gboolean
static void
flash_done (gpointer data)
{
FlashInfo *info = (FlashInfo *) data;
set_speed (info->device, info->current_speed);
NM_SERIAL_DEVICE_GET_PRIVATE (info->device)->pending_id = 0;
info->callback (info->device, info->user_data);
g_slice_free (FlashInfo, info);
}
static gboolean
flash_do (gpointer data)
{
FlashInfo *info = (FlashInfo *) data;
set_speed (info->device, info->current_speed);
return FALSE;
}
@ -892,11 +922,12 @@ nm_serial_device_flash (NMSerialDevice *device,
gpointer user_data)
{
FlashInfo *info;
guint id;
g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0);
g_return_val_if_fail (callback != NULL, 0);
info = g_new (FlashInfo, 1);
info = g_slice_new0 (FlashInfo);
info->device = device;
info->current_speed = get_speed (device);
info->callback = callback;
@ -904,11 +935,15 @@ nm_serial_device_flash (NMSerialDevice *device,
set_speed (device, B0);
return g_timeout_add_full (G_PRIORITY_DEFAULT,
flash_time,
flash_done,
info,
g_free);
id = g_timeout_add_full (G_PRIORITY_DEFAULT,
flash_time,
flash_do,
info,
flash_done);
NM_SERIAL_DEVICE_GET_PRIVATE (device)->pending_id = id;
return id;
}
GIOChannel *