435
441
NMSettingSerial *setting;
442
int i, eagain_count = 1000;
444
guint32 send_delay = G_USEC_PER_SEC / 1000;
439
446
g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), FALSE);
440
447
g_return_val_if_fail (command != NULL, FALSE);
442
449
fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
443
450
setting = NM_SETTING_SERIAL (serial_device_get_setting (device, NM_TYPE_SETTING_SERIAL));
451
if (setting && setting->send_delay)
452
send_delay = setting->send_delay;
445
454
serial_debug ("Sending:", (char *) command->data, command->len);
447
for (i = 0; i < command->len; i++) {
449
status = write (fd, command->data + i, 1);
455
g_warning ("Error in writing (errno %d)", errno);
456
for (i = 0; i < command->len && eagain_count > 0;) {
457
written = write (fd, command->data + i, 1);
462
/* Treat written == 0 as EAGAIN to ensure we break out of the
463
* for() loop eventually.
465
if ((written < 0) && (errno != EAGAIN)) {
466
g_warning ("Error in writing (errno %d)", errno);
459
if (setting->send_delay)
460
usleep (setting->send_delay);
471
g_usleep (send_delay);
474
if (eagain_count <= 0)
475
serial_debug ("Error: too many retries sending:", (char *) command->data, command->len);
486
NMSerialDevice *device;
489
NMSerialGetReplyFn callback;
494
get_reply_done (gpointer data)
496
GetReplyInfo *info = (GetReplyInfo *) data;
498
nm_serial_device_pending_done (info->device);
500
/* Call the callback */
501
info->callback (info->device, info->result->str, info->user_data);
504
g_free (info->terminators);
505
g_string_free (info->result, TRUE);
507
g_slice_free (GetReplyInfo, info);
511
get_reply_got_data (GIOChannel *source,
512
GIOCondition condition,
515
GetReplyInfo *info = (GetReplyInfo *) data;
500
find_terminator (const char *line, const char **terminators)
504
for (i = 0; terminators[i]; i++) {
505
if (!strncasecmp (line, terminators[i], strlen (terminators[i])))
512
find_response (const char *line, const char **responses, gint *idx)
516
/* Don't look for a result again if we got one previously */
517
for (i = 0; responses[i]; i++) {
518
if (strcasestr (line, responses[i])) {
526
#define RESPONSE_LINE_MAX 128
529
nm_serial_device_wait_reply_blocking (NMSerialDevice *device,
530
guint32 timeout_secs,
531
const char **needles,
532
const char **terminators)
517
534
char buf[SERIAL_BUF_SIZE + 1];
535
int fd, reply_index = -1, bytes_read;
536
GString *result = NULL;
538
const char *response = NULL;
519
539
gboolean done = FALSE;
522
if (condition & G_IO_HUP || condition & G_IO_ERR) {
523
g_string_truncate (info->result, 0);
541
g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), -1);
542
g_return_val_if_fail (timeout_secs <= 60, -1);
543
g_return_val_if_fail (needles != NULL, -1);
545
fd = NM_SERIAL_DEVICE_GET_PRIVATE (device)->fd;
549
end = time (NULL) + timeout_secs;
550
result = g_string_sized_new (20);
530
status = g_io_channel_read_chars (source, buf, SERIAL_BUF_SIZE, &bytes_read, &err);
531
if (status == G_IO_STATUS_ERROR) {
532
g_warning ("%s", err->message);
537
if (bytes_read > 0) {
540
serial_debug ("Got:", buf, bytes_read);
543
for (i = 0; i < bytes_read && !done; i++, p++) {
545
gboolean is_terminator = FALSE;
547
for (j = 0; j < strlen (info->terminators); j++) {
548
if (*p == info->terminators[j]) {
549
is_terminator = TRUE;
552
bytes_read = read (fd, buf, SERIAL_BUF_SIZE);
553
if (bytes_read < 0 && errno != EAGAIN) {
554
nm_warning ("%s: read error: %d (%s)",
555
nm_device_get_iface (NM_DEVICE (device)),
563
else if (bytes_read > 0) {
565
g_string_append (result, buf);
567
serial_debug ("Got:", result->str, result->len);
570
/* Look for needles and terminators */
571
if ((bytes_read > 0) && result->str) {
572
char *p = result->str;
574
/* Break the response up into lines and process each one */
575
while ((p < result->str + strlen (result->str)) && !done) {
576
char line[RESPONSE_LINE_MAX] = { '\0', };
579
gboolean got_something = FALSE;
581
for (i = 0; *p && (i < RESPONSE_LINE_MAX - 1); p++) {
582
/* Ignore front CR/LF */
583
if ((*p == '\n') || (*p == '\r')) {
588
got_something = TRUE;
555
/* Ignore terminators in the beginning of the output */
556
if (info->result->len > 0)
559
g_string_append_c (info->result, *p);
593
tmp = g_strstrip (line);
594
if (tmp && strlen (tmp)) {
595
done = find_terminator (tmp, terminators);
596
if (reply_index == -1)
597
response = find_response (tmp, needles, &reply_index);
563
602
/* Limit the size of the buffer */
564
if (info->result->len > SERIAL_BUF_SIZE) {
603
if (result->len > SERIAL_BUF_SIZE) {
565
604
g_warning ("%s (%s): response buffer filled before repsonse received",
566
__func__, nm_device_get_iface (NM_DEVICE (info->device)));
567
g_string_truncate (info->result, 0);
605
__func__, nm_device_get_iface (NM_DEVICE (device)));
570
} while (!done || bytes_read == SERIAL_BUF_SIZE || status == G_IO_STATUS_AGAIN);
576
nm_serial_device_get_reply (NMSerialDevice *device,
578
const char *terminators,
579
NMSerialGetReplyFn callback,
584
g_return_val_if_fail (NM_IS_SERIAL_DEVICE (device), 0);
585
g_return_val_if_fail (terminators != NULL, 0);
586
g_return_val_if_fail (callback != NULL, 0);
588
info = g_slice_new0 (GetReplyInfo);
589
info->device = device;
590
info->terminators = g_strdup (terminators);
591
info->result = g_string_new (NULL);
592
info->callback = callback;
593
info->user_data = user_data;
595
return nm_serial_device_set_pending (device, timeout, get_reply_got_data, info, get_reply_done);
611
} while (!done && (time (NULL) < end));
615
633
nm_serial_device_pending_done (info->device);
617
635
/* Call the callback */
618
info->callback (info->device, info->reply_index, info->user_data);
636
info->callback (info->device, info->reply_index, info->reply_line, info->user_data);
621
639
if (info->result)
622
640
g_string_free (info->result, TRUE);
642
g_free (info->reply_line);
624
644
g_strfreev (info->str_needles);
625
645
g_strfreev (info->terminators);
626
646
g_slice_free (WaitForReplyInfo, info);
630
find_terminator (const char *line, char **terminators)
634
for (i = 0; terminators[i]; i++) {
635
if (!strncasecmp (line, terminators[i], strlen (terminators[i])))
642
find_response (const char *line, char **responses, gint *idx)
646
/* Don't look for a result again if we got one previously */
647
for (i = 0; responses[i]; i++) {
648
if (strcasestr (line, responses[i])) {
656
#define RESPONSE_LINE_MAX 128
659
650
wait_for_reply_got_data (GIOChannel *source,
660
651
GIOCondition condition,
714
703
tmp = g_strstrip (line);
715
704
if (tmp && strlen (tmp)) {
716
done = find_terminator (tmp, info->terminators);
717
if (info->reply_index == -1)
718
got_response = find_response (tmp, info->str_needles, &(info->reply_index));
705
done = find_terminator (tmp, (const char **) info->terminators);
706
if (info->reply_index == -1) {
707
if (find_response (tmp, (const char **) info->str_needles, &(info->reply_index)))
708
info->reply_line = g_strdup (tmp);
722
if (done && got_response)
726
714
/* Limit the size of the buffer */
727
715
if (info->result->len > SERIAL_BUF_SIZE) {
728
g_warning ("%s (%s): response buffer filled before repsonse received",
729
__func__, nm_device_get_iface (NM_DEVICE (info->device)));
716
nm_warning ("(%s): response buffer filled before repsonse received",
717
nm_device_get_iface (NM_DEVICE (info->device)));