2008-04-17 Dan Williams <dcbw@redhat.com>

* src/nm-serial-device.c
	  src/nm-serial-device.h
		- (wait_for_reply_got_data): break input into lines, and search each
			line for responses _and_ terminator strings; also make sure that
			the read loop doesn't continue after the timeout is supposed to fire
		- (nm_serial_device_wait_for_reply): take an array of terminators too

	* src/nm-gsm-device.c
	  src/nm-cdma-device.c
		- Send terminators to nm_serial_device_wait_for_reply()



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3570 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2008-04-17 11:08:52 +00:00
parent 48971a4e85
commit bcbf96cf7f
5 changed files with 110 additions and 28 deletions

View file

@ -1,3 +1,16 @@
2008-04-17 Dan Williams <dcbw@redhat.com>
* src/nm-serial-device.c
src/nm-serial-device.h
- (wait_for_reply_got_data): break input into lines, and search each
line for responses _and_ terminator strings; also make sure that
the read loop doesn't continue after the timeout is supposed to fire
- (nm_serial_device_wait_for_reply): take an array of terminators too
* src/nm-gsm-device.c
src/nm-cdma-device.c
- Send terminators to nm_serial_device_wait_for_reply()
2008-04-16 Dan Williams <dcbw@redhat.com>
Patch from 陈鑫 <znscnchen@gmail.com>

View file

@ -135,7 +135,7 @@ do_dial (NMSerialDevice *device)
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 60, responses, dial_done, NULL);
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
@ -171,14 +171,14 @@ static void
init_modem (NMSerialDevice *device, gpointer user_data)
{
guint id;
char *responses[] = { "OK", "ERR", NULL };
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, 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);

View file

@ -144,7 +144,7 @@ do_dial (NMSerialDevice *device)
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 60, responses, dial_done, NULL);
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
@ -192,7 +192,7 @@ manual_registration (NMSerialDevice *device)
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 30, responses, manual_registration_done, NULL);
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
@ -282,13 +282,14 @@ automatic_registration (NMSerialDevice *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, automatic_registration_response, NULL);
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
@ -391,7 +392,7 @@ enter_pin (NMSerialDevice *device, gboolean retry)
g_free (command);
if (success) {
id = nm_serial_device_wait_for_reply (device, 3, responses, enter_pin_done, NULL);
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
@ -441,13 +442,14 @@ check_pin (NMSerialDevice *device)
{
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, check_pin_done, NULL);
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
@ -480,14 +482,14 @@ static void
init_modem (NMSerialDevice *device, gpointer user_data)
{
guint id;
char *responses[] = { "OK", "ERR", NULL };
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, init_done, NULL);
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

View file

@ -524,9 +524,12 @@ nm_serial_device_get_reply (NMSerialDevice *device,
typedef struct {
NMSerialDevice *device;
char **str_needles;
char **terminators;
GString *result;
NMSerialWaitForReplyFn callback;
gpointer user_data;
guint timeout;
time_t start;
guint timeout_id;
guint got_data_id;
} WaitForReplyInfo;
@ -543,6 +546,7 @@ wait_for_reply_info_destroy (gpointer data)
g_string_free (info->result, TRUE);
g_strfreev (info->str_needles);
g_strfreev (info->terminators);
g_free (info);
}
@ -556,6 +560,35 @@ wait_for_reply_timeout (gpointer data)
return FALSE;
}
static gboolean
find_terminator (const char *line, char **terminators)
{
int i;
for (i = 0; terminators[i]; i++) {
if (!strcasecmp (line, 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,
@ -565,9 +598,9 @@ wait_for_reply_got_data (GIOChannel *source,
gchar buf[SERIAL_BUF_SIZE + 1];
gsize bytes_read;
GIOStatus status;
gboolean got_response = FALSE;
gboolean done = FALSE;
int idx = -1;
int i;
if (!(condition & G_IO_IN))
goto done;
@ -587,14 +620,42 @@ wait_for_reply_got_data (GIOChannel *source,
g_string_append (info->result, buf);
serial_debug ("Got:", info->result->str, info->result->len);
}
for (i = 0; info->str_needles[i]; i++) {
if ( info->result->str
&& strcasestr (info->result->str, info->str_needles[i])) {
idx = i;
done = TRUE;
/* Look for needles and terminators */
if ((bytes_read > 0) && info->result->str) {
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)) {
char line[RESPONSE_LINE_MAX] = { '\0', };
char *tmp;
int i;
gboolean got_something = FALSE;
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';
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 (done && got_response)
break;
}
/* Limit the size of the buffer */
@ -602,7 +663,19 @@ wait_for_reply_got_data (GIOChannel *source,
g_warning ("%s (%s): response buffer filled before repsonse received",
__func__, nm_device_get_iface (NM_DEVICE (info->device)));
done = TRUE;
break;
}
/* Make sure we don't go over the timeout, in addition to the timeout
* handler that's been scheduled. If for some reason this loop doesn't
* 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) {
done = TRUE;
break;
} else
g_usleep (50);
} while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
done:
@ -624,29 +697,20 @@ guint
nm_serial_device_wait_for_reply (NMSerialDevice *device,
guint timeout,
char **responses,
char **terminators,
NMSerialWaitForReplyFn callback,
gpointer user_data)
{
WaitForReplyInfo *info;
char **str_array;
int i;
g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0);
g_return_val_if_fail (responses != NULL, 0);
g_return_val_if_fail (callback != NULL, 0);
/* Copy the array */
str_array = g_new (char*, g_strv_length (responses) + 1);
i = 0;
while (responses[i]) {
str_array[i] = g_strdup (responses[i]);
i++;
}
str_array[i] = NULL;
info = g_new0 (WaitForReplyInfo, 1);
info->device = device;
info->str_needles = str_array;
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;
@ -656,6 +720,8 @@ nm_serial_device_wait_for_reply (NMSerialDevice *device,
wait_for_reply_got_data,
info);
info->timeout = timeout * 1000;
info->start = time (NULL);
info->timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
timeout * 1000,
wait_for_reply_timeout,

View file

@ -61,6 +61,7 @@ guint nm_serial_device_get_reply (NMSerialDevice *device,
guint nm_serial_device_wait_for_reply (NMSerialDevice *device,
guint timeout,
char **responses,
char **terminators,
NMSerialWaitForReplyFn callback,
gpointer user_data);