source: MondoRescue/branches/3.3/mindi-busybox/miscutils/setserial.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 16.0 KB
RevLine 
[3621]1/* vi: set sw=4 ts=4: */
2/*
3 * setserial implementation for busybox
4 *
5 *
6 * Copyright (C) 2011 Marek Bečka <yuen@klacno.sk>
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */
10
11//config:config SETSERIAL
12//config: bool "setserial"
13//config: default y
14//config: select PLATFORM_LINUX
15//config: help
16//config: Retrieve or set Linux serial port.
17
18//applet:IF_SETSERIAL(APPLET(setserial, BB_DIR_BIN, BB_SUID_DROP))
19
20//kbuild:lib-$(CONFIG_SETSERIAL) += setserial.o
21
22#include "libbb.h"
23#include <assert.h>
24
25#ifndef PORT_UNKNOWN
26# define PORT_UNKNOWN 0
27#endif
28#ifndef PORT_8250
29# define PORT_8250 1
30#endif
31#ifndef PORT_16450
32# define PORT_16450 2
33#endif
34#ifndef PORT_16550
35# define PORT_16550 3
36#endif
37#ifndef PORT_16550A
38# define PORT_16550A 4
39#endif
40#ifndef PORT_CIRRUS
41# define PORT_CIRRUS 5
42#endif
43#ifndef PORT_16650
44# define PORT_16650 6
45#endif
46#ifndef PORT_16650V2
47# define PORT_16650V2 7
48#endif
49#ifndef PORT_16750
50# define PORT_16750 8
51#endif
52#ifndef PORT_STARTECH
53# define PORT_STARTECH 9
54#endif
55#ifndef PORT_16C950
56# define PORT_16C950 10
57#endif
58#ifndef PORT_16654
59# define PORT_16654 11
60#endif
61#ifndef PORT_16850
62# define PORT_16850 12
63#endif
64#ifndef PORT_RSA
65# define PORT_RSA 13
66#endif
67#ifndef PORT_NS16550A
68# define PORT_NS16550A 14
69#endif
70#ifndef PORT_XSCALE
71# define PORT_XSCALE 15
72#endif
73#ifndef PORT_RM9000
74# define PORT_RM9000 16
75#endif
76#ifndef PORT_OCTEON
77# define PORT_OCTEON 17
78#endif
79#ifndef PORT_AR7
80# define PORT_AR7 18
81#endif
82#ifndef PORT_U6_16550A
83# define PORT_U6_16550A 19
84#endif
85
86#ifndef ASYNCB_HUP_NOTIFY
87# define ASYNCB_HUP_NOTIFY 0
88#endif
89#ifndef ASYNCB_FOURPORT
90# define ASYNCB_FOURPORT 1
91#endif
92#ifndef ASYNCB_SAK
93# define ASYNCB_SAK 2
94#endif
95#ifndef ASYNCB_SPLIT_TERMIOS
96# define ASYNCB_SPLIT_TERMIOS 3
97#endif
98#ifndef ASYNCB_SPD_HI
99# define ASYNCB_SPD_HI 4
100#endif
101#ifndef ASYNCB_SPD_VHI
102# define ASYNCB_SPD_VHI 5
103#endif
104#ifndef ASYNCB_SKIP_TEST
105# define ASYNCB_SKIP_TEST 6
106#endif
107#ifndef ASYNCB_AUTO_IRQ
108# define ASYNCB_AUTO_IRQ 7
109#endif
110#ifndef ASYNCB_SESSION_LOCKOUT
111# define ASYNCB_SESSION_LOCKOUT 8
112#endif
113#ifndef ASYNCB_PGRP_LOCKOUT
114# define ASYNCB_PGRP_LOCKOUT 9
115#endif
116#ifndef ASYNCB_CALLOUT_NOHUP
117# define ASYNCB_CALLOUT_NOHUP 10
118#endif
119#ifndef ASYNCB_SPD_SHI
120# define ASYNCB_SPD_SHI 12
121#endif
122#ifndef ASYNCB_LOW_LATENCY
123# define ASYNCB_LOW_LATENCY 13
124#endif
125#ifndef ASYNCB_BUGGY_UART
126# define ASYNCB_BUGGY_UART 14
127#endif
128
129#ifndef ASYNC_HUP_NOTIFY
130# define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY)
131#endif
132#ifndef ASYNC_FOURPORT
133# define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT)
134#endif
135#ifndef ASYNC_SAK
136# define ASYNC_SAK (1U << ASYNCB_SAK)
137#endif
138#ifndef ASYNC_SPLIT_TERMIOS
139# define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS)
140#endif
141#ifndef ASYNC_SPD_HI
142# define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI)
143#endif
144#ifndef ASYNC_SPD_VHI
145# define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI)
146#endif
147#ifndef ASYNC_SKIP_TEST
148# define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST)
149#endif
150#ifndef ASYNC_AUTO_IRQ
151# define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ)
152#endif
153#ifndef ASYNC_SESSION_LOCKOUT
154# define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT)
155#endif
156#ifndef ASYNC_PGRP_LOCKOUT
157# define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT)
158#endif
159#ifndef ASYNC_CALLOUT_NOHUP
160# define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP)
161#endif
162#ifndef ASYNC_SPD_SHI
163# define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI)
164#endif
165#ifndef ASYNC_LOW_LATENCY
166# define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY)
167#endif
168#ifndef ASYNC_BUGGY_UART
169# define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART)
170#endif
171
172#ifndef ASYNC_SPD_CUST
173# define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
174#endif
175#ifndef ASYNC_SPD_WARP
176# define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI)
177#endif
178#ifndef ASYNC_SPD_MASK
179# define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI)
180#endif
181
182#ifndef ASYNC_CLOSING_WAIT_INF
183# define ASYNC_CLOSING_WAIT_INF 0
184#endif
185#ifndef ASYNC_CLOSING_WAIT_NONE
186# define ASYNC_CLOSING_WAIT_NONE 65535
187#endif
188
189#ifndef _LINUX_SERIAL_H
190struct serial_struct {
191 int type;
192 int line;
193 unsigned int port;
194 int irq;
195 int flags;
196 int xmit_fifo_size;
197 int custom_divisor;
198 int baud_base;
199 unsigned short close_delay;
200 char io_type;
201 char reserved_char[1];
202 int hub6;
203 unsigned short closing_wait; /* time to wait before closing */
204 unsigned short closing_wait2; /* no longer used... */
205 unsigned char *iomem_base;
206 unsigned short iomem_reg_shift;
207 unsigned int port_high;
208 unsigned long iomap_base; /* cookie passed into ioremap */
209};
210#endif
211
212//usage:#define setserial_trivial_usage
213//usage: "[-gabGvzV] DEVICE [PARAMETER [ARG]]..."
214//usage:#define setserial_full_usage "\n\n"
215//usage: "Request or set Linux serial port information\n"
216//usage: "\n"
217//usage: " -g Interpret parameters as list of devices for reporting\n"
218//usage: " -a Print all available information\n"
219//usage: " -b Print summary information\n"
220//usage: " -G Print in form which can be fed back\n"
221//usage: " to setserial as command line parameters\n"
222//usage: " -z Zero out serial flags before setting\n"
223//usage: " -v Verbose\n"
224//usage: "\n"
225//usage: "Parameters: (* = takes an argument, ^ = can be turned off by preceding ^)\n"
226//usage: " *port, *irq, *divisor, *uart, *baud_base, *close_delay, *closing_wait,\n"
227//usage: " ^fourport, ^auto_irq, ^skip_test, ^sak, ^session_lockout, ^pgrp_lockout,\n"
228//usage: " ^callout_nohup, ^split_termios, ^hup_notify, ^low_latency, autoconfig,\n"
229//usage: " spd_normal, spd_hi, spd_vhi, spd_shi, spd_warp, spd_cust\n"
230//usage: "\n"
231//usage: "UART types:\n"
232//usage: " unknown, 8250, 16450, 16550, 16550A, Cirrus, 16650, 16650V2, 16750,\n"
233//usage: " 16950, 16954, 16654, 16850, RSA, NS16550A, XSCALE, RM9000, OCTEON, AR7,\n"
234//usage: " U6_16550A"
235
236#define OPT_PRINT_SUMMARY (1 << 0)
237#define OPT_PRINT_FEDBACK (1 << 1)
238#define OPT_PRINT_ALL (1 << 2)
239#define OPT_VERBOSE (1 << 3)
240#define OPT_ZERO (1 << 4)
241#define OPT_GET (1 << 5)
242
243#define OPT_MODE_MASK \
244 (OPT_PRINT_ALL | OPT_PRINT_SUMMARY | OPT_PRINT_FEDBACK)
245
246enum print_mode
247{
248 PRINT_NORMAL = 0,
249 PRINT_SUMMARY = (1 << 0),
250 PRINT_FEDBACK = (1 << 1),
251 PRINT_ALL = (1 << 2),
252};
253
254#define CTL_SET (1 << 0)
255#define CTL_CONFIG (1 << 1)
256#define CTL_GET (1 << 2)
257#define CTL_CLOSE (1 << 3)
258#define CTL_NODIE (1 << 4)
259
260static const char serial_types[] ALIGN1 =
261 "unknown\0" /* 0 */
262 "8250\0" /* 1 */
263 "16450\0" /* 2 */
264 "16550\0" /* 3 */
265 "16550A\0" /* 4 */
266 "Cirrus\0" /* 5 */
267 "16650\0" /* 6 */
268 "16650V2\0" /* 7 */
269 "16750\0" /* 8 */
270 "16950\0" /* 9 UNIMPLEMENTED: also know as "16950/954" */
271 "16954\0" /* 10 */
272 "16654\0" /* 11 */
273 "16850\0" /* 12 */
274 "RSA\0" /* 13 */
275#ifndef SETSERIAL_BASE
276 "NS16550A\0" /* 14 */
277 "XSCALE\0" /* 15 */
278 "RM9000\0" /* 16 */
279 "OCTEON\0" /* 17 */
280 "AR7\0" /* 18 */
281 "U6_16550A\0" /* 19 */
282#endif
283;
284
285#ifndef SETSERIAL_BASE
286# define MAX_SERIAL_TYPE 19
287#else
288# define MAX_SERIAL_TYPE 13
289#endif
290
291static const char commands[] ALIGN1 =
292 "spd_normal\0"
293 "spd_hi\0"
294 "spd_vhi\0"
295 "spd_shi\0"
296 "spd_warp\0"
297 "spd_cust\0"
298
299 "sak\0"
300 "fourport\0"
301 "hup_notify\0"
302 "skip_test\0"
303 "auto_irq\0"
304 "split_termios\0"
305 "session_lockout\0"
306 "pgrp_lockout\0"
307 "callout_nohup\0"
308 "low_latency\0"
309
310 "port\0"
311 "irq\0"
312 "divisor\0"
313 "uart\0"
314 "baud_base\0"
315 "close_delay\0"
316 "closing_wait\0"
317
318 "autoconfig\0"
319;
320
321enum
322{
323 CMD_SPD_NORMAL = 0,
324 CMD_SPD_HI,
325 CMD_SPD_VHI,
326 CMD_SPD_SHI,
327 CMD_SPD_WARP,
328 CMD_SPD_CUST,
329
330 CMD_FLAG_SAK,
331 CMD_FLAG_FOURPORT,
332 CMD_FLAG_NUP_NOTIFY,
333 CMD_FLAG_SKIP_TEST,
334 CMD_FLAG_AUTO_IRQ,
335 CMD_FLAG_SPLIT_TERMIOS,
336 CMD_FLAG_SESSION_LOCKOUT,
337 CMD_FLAG_PGRP_LOCKOUT,
338 CMD_FLAG_CALLOUT_NOHUP,
339 CMD_FLAG_LOW_LATENCY,
340
341 CMD_PORT,
342 CMD_IRQ,
343 CMD_DIVISOR,
344 CMD_UART,
345 CMD_BASE,
346 CMD_DELAY,
347 CMD_WAIT,
348
349 CMD_AUTOCONFIG,
350
351 CMD_FLAG_FIRST = CMD_FLAG_SAK,
352 CMD_FLAG_LAST = CMD_FLAG_LOW_LATENCY,
353};
354
355static bool cmd_noprint(int cmd)
356{
357 return (cmd >= CMD_FLAG_SKIP_TEST && cmd <= CMD_FLAG_CALLOUT_NOHUP);
358}
359
360static bool cmd_is_flag(int cmd)
361{
362 return (cmd >= CMD_FLAG_FIRST && cmd <= CMD_FLAG_LAST);
363}
364
365static bool cmd_need_arg(int cmd)
366{
367 return (cmd >= CMD_PORT && cmd <= CMD_WAIT);
368}
369
370#define ALL_SPD ( \
371 ASYNC_SPD_HI | ASYNC_SPD_VHI | ASYNC_SPD_SHI | \
372 ASYNC_SPD_WARP | ASYNC_SPD_CUST \
373 )
374
375#define ALL_FLAGS ( \
376 ASYNC_SAK | ASYNC_FOURPORT | ASYNC_HUP_NOTIFY | \
377 ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ | ASYNC_SPLIT_TERMIOS | \
378 ASYNC_SESSION_LOCKOUT | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP | \
379 ASYNC_LOW_LATENCY \
380 )
381
382#if (ALL_SPD | ALL_FLAGS) > 0xffff
383# error "Unexpected flags size"
384#endif
385
386static const uint16_t setbits[CMD_FLAG_LAST + 1] =
387{
388 0,
389 ASYNC_SPD_HI,
390 ASYNC_SPD_VHI,
391 ASYNC_SPD_SHI,
392 ASYNC_SPD_WARP,
393 ASYNC_SPD_CUST,
394
395 ASYNC_SAK,
396 ASYNC_FOURPORT,
397 ASYNC_HUP_NOTIFY,
398 ASYNC_SKIP_TEST,
399 ASYNC_AUTO_IRQ,
400 ASYNC_SPLIT_TERMIOS,
401 ASYNC_SESSION_LOCKOUT,
402 ASYNC_PGRP_LOCKOUT,
403 ASYNC_CALLOUT_NOHUP,
404 ASYNC_LOW_LATENCY
405};
406
407#define STR_INFINITE "infinite"
408#define STR_NONE "none"
409
410static const char *uart_type(int type)
411{
412 if (type > MAX_SERIAL_TYPE)
413 return "undefined";
414
415 return nth_string(serial_types, type);
416}
417
418/* libbb candidate */
419static int index_in_strings_case_insensitive(const char *strings, const char *key)
420{
421 int idx = 0;
422
423 while (*strings) {
424 if (strcasecmp(strings, key) == 0) {
425 return idx;
426 }
427 strings += strlen(strings) + 1; /* skip NUL */
428 idx++;
429 }
430 return -1;
431}
432
433static int uart_id(const char *name)
434{
435 return index_in_strings_case_insensitive(serial_types, name);
436}
437
438static const char *get_spd(int flags, enum print_mode mode)
439{
440 int idx;
441
442 switch (flags & ASYNC_SPD_MASK) {
443 case ASYNC_SPD_HI:
444 idx = CMD_SPD_HI;
445 break;
446 case ASYNC_SPD_VHI:
447 idx = CMD_SPD_VHI;
448 break;
449 case ASYNC_SPD_SHI:
450 idx = CMD_SPD_SHI;
451 break;
452 case ASYNC_SPD_WARP:
453 idx = CMD_SPD_WARP;
454 break;
455 case ASYNC_SPD_CUST:
456 idx = CMD_SPD_CUST;
457 break;
458 default:
459 if (mode < PRINT_FEDBACK)
460 return NULL;
461 idx = CMD_SPD_NORMAL;
462 }
463
464 return nth_string(commands, idx);
465}
466
467static int get_numeric(const char *arg)
468{
469 return bb_strtol(arg, NULL, 0);
470}
471
472static int get_wait(const char *arg)
473{
474 if (strcasecmp(arg, STR_NONE) == 0)
475 return ASYNC_CLOSING_WAIT_NONE;
476
477 if (strcasecmp(arg, STR_INFINITE) == 0)
478 return ASYNC_CLOSING_WAIT_INF;
479
480 return get_numeric(arg);
481}
482
483static int get_uart(const char *arg)
484{
485 int uart = uart_id(arg);
486
487 if (uart < 0)
488 bb_error_msg_and_die("illegal UART type: %s", arg);
489
490 return uart;
491}
492
493static int serial_open(const char *dev, bool quiet)
494{
495 int fd;
496
497 fd = device_open(dev, O_RDWR | O_NONBLOCK);
498 if (fd < 0 && !quiet)
499 bb_simple_perror_msg(dev);
500
501 return fd;
502}
503
504static int serial_ctl(int fd, int ops, struct serial_struct *serinfo)
505{
506 int ret = 0;
507 const char *err;
508
509 if (ops & CTL_SET) {
510 ret = ioctl(fd, TIOCSSERIAL, serinfo);
511 if (ret < 0) {
512 err = "can't set serial info";
513 goto fail;
514 }
515 }
516
517 if (ops & CTL_CONFIG) {
518 ret = ioctl(fd, TIOCSERCONFIG);
519 if (ret < 0) {
520 err = "can't autoconfigure port";
521 goto fail;
522 }
523 }
524
525 if (ops & CTL_GET) {
526 ret = ioctl(fd, TIOCGSERIAL, serinfo);
527 if (ret < 0) {
528 err = "can't get serial info";
529 goto fail;
530 }
531 }
532 nodie:
533 if (ops & CTL_CLOSE)
534 close(fd);
535
536 return ret;
537 fail:
538 bb_simple_perror_msg(err);
539 if (ops & CTL_NODIE)
540 goto nodie;
541 exit(EXIT_FAILURE);
542}
543
544static void print_flag(const char **prefix, const char *flag)
545{
546 printf("%s%s", *prefix, flag);
547 *prefix = " ";
548}
549
550static void print_serial_flags(int serial_flags, enum print_mode mode,
551 const char *prefix, const char *postfix)
552{
553 int i;
554 const char *spd, *pr;
555
556 pr = prefix;
557
558 spd = get_spd(serial_flags, mode);
559 if (spd)
560 print_flag(&pr, spd);
561
562 for (i = CMD_FLAG_FIRST; i <= CMD_FLAG_LAST; i++) {
563 if ((serial_flags & setbits[i])
564 && (mode > PRINT_SUMMARY || !cmd_noprint(i))
565 ) {
566 print_flag(&pr, nth_string(commands, i));
567 }
568 }
569
570 puts(pr == prefix ? "" : postfix);
571}
572
573static void print_closing_wait(unsigned int closing_wait)
574{
575 switch (closing_wait) {
576 case ASYNC_CLOSING_WAIT_NONE:
577 puts(STR_NONE);
578 break;
579 case ASYNC_CLOSING_WAIT_INF:
580 puts(STR_INFINITE);
581 break;
582 default:
583 printf("%u\n", closing_wait);
584 }
585}
586
587static void serial_get(const char *device, enum print_mode mode)
588{
589 int fd, ret;
590 const char *uart, *prefix, *postfix;
591 struct serial_struct serinfo;
592
593 fd = serial_open(device, /*quiet:*/ mode == PRINT_SUMMARY);
594 if (fd < 0)
595 return;
596
597 ret = serial_ctl(fd, CTL_GET | CTL_CLOSE | CTL_NODIE, &serinfo);
598 if (ret < 0)
599 return;
600
601 uart = uart_type(serinfo.type);
602 prefix = ", Flags: ";
603 postfix = "";
604
605 switch (mode) {
606 case PRINT_NORMAL:
607 printf("%s, UART: %s, Port: 0x%.4x, IRQ: %d",
608 device, uart, serinfo.port, serinfo.irq);
609 break;
610 case PRINT_SUMMARY:
611 if (!serinfo.type)
612 return;
613 printf("%s at 0x%.4x (irq = %d) is a %s",
614 device, serinfo.port, serinfo.irq, uart);
615 prefix = " (";
616 postfix = ")";
617 break;
618 case PRINT_FEDBACK:
619 printf("%s uart %s port 0x%.4x irq %d baud_base %d", device,
620 uart, serinfo.port, serinfo.irq, serinfo.baud_base);
621 prefix = " ";
622 break;
623 case PRINT_ALL:
624 printf("%s, Line %d, UART: %s, Port: 0x%.4x, IRQ: %d\n",
625 device, serinfo.line, uart, serinfo.port, serinfo.irq);
626 printf("\tBaud_base: %d, close_delay: %u, divisor: %d\n",
627 serinfo.baud_base, serinfo.close_delay,
628 serinfo.custom_divisor);
629 printf("\tclosing_wait: ");
630 print_closing_wait(serinfo.closing_wait);
631 prefix = "\tFlags: ";
632 postfix = "\n";
633 break;
634 default:
635 assert(0);
636 }
637
638 print_serial_flags(serinfo.flags, mode, prefix, postfix);
639}
640
641static int find_cmd(const char *cmd)
642{
643 int idx;
644
645 idx = index_in_strings_case_insensitive(commands, cmd);
646 if (idx < 0)
647 bb_error_msg_and_die("invalid flag: %s", cmd);
648
649 return idx;
650}
651
652static void serial_set(char **arg, int opts)
653{
654 struct serial_struct serinfo;
655 int cmd;
656 const char *word;
657 int fd;
658
659 fd = serial_open(*arg++, /*quiet:*/ false);
660 if (fd < 0)
661 exit(201);
662
663 serial_ctl(fd, CTL_GET, &serinfo);
664
665 if (opts & OPT_ZERO)
666 serinfo.flags = 0;
667
668 while (*arg) {
669 int invert;
670
671 word = *arg++;
672 invert = (*word == '^');
673 word += invert;
674
675 cmd = find_cmd(word);
676
677 if (*arg == NULL && cmd_need_arg(cmd))
678 bb_error_msg_and_die(bb_msg_requires_arg, word);
679
680 if (invert && !cmd_is_flag(cmd))
681 bb_error_msg_and_die("can't invert %s", word);
682
683 switch (cmd) {
684 case CMD_SPD_NORMAL:
685 case CMD_SPD_HI:
686 case CMD_SPD_VHI:
687 case CMD_SPD_SHI:
688 case CMD_SPD_WARP:
689 case CMD_SPD_CUST:
690 serinfo.flags &= ~ASYNC_SPD_MASK;
691 /* fallthrough */
692 case CMD_FLAG_SAK:
693 case CMD_FLAG_FOURPORT:
694 case CMD_FLAG_NUP_NOTIFY:
695 case CMD_FLAG_SKIP_TEST:
696 case CMD_FLAG_AUTO_IRQ:
697 case CMD_FLAG_SPLIT_TERMIOS:
698 case CMD_FLAG_SESSION_LOCKOUT:
699 case CMD_FLAG_PGRP_LOCKOUT:
700 case CMD_FLAG_CALLOUT_NOHUP:
701 case CMD_FLAG_LOW_LATENCY:
702 if (invert)
703 serinfo.flags &= ~setbits[cmd];
704 else
705 serinfo.flags |= setbits[cmd];
706 break;
707 case CMD_PORT:
708 serinfo.port = get_numeric(*arg++);
709 break;
710 case CMD_IRQ:
711 serinfo.irq = get_numeric(*arg++);
712 break;
713 case CMD_DIVISOR:
714 serinfo.custom_divisor = get_numeric(*arg++);
715 break;
716 case CMD_UART:
717 serinfo.type = get_uart(*arg++);
718 break;
719 case CMD_BASE:
720 serinfo.baud_base = get_numeric(*arg++);
721 break;
722 case CMD_DELAY:
723 serinfo.close_delay = get_numeric(*arg++);
724 break;
725 case CMD_WAIT:
726 serinfo.closing_wait = get_wait(*arg++);
727 break;
728 case CMD_AUTOCONFIG:
729 serial_ctl(fd, CTL_SET | CTL_CONFIG | CTL_GET, &serinfo);
730 break;
731 default:
732 assert(0);
733 }
734 }
735
736 serial_ctl(fd, CTL_SET | CTL_CLOSE, &serinfo);
737}
738
739int setserial_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
740int setserial_main(int argc UNUSED_PARAM, char **argv)
741{
742 int opts;
743
744 opt_complementary = "-1:b-aG:G-ab:a-bG";
745 opts = getopt32(argv, "bGavzg");
746 argv += optind;
747
748 if (!argv[1]) /* one arg only? */
749 opts |= OPT_GET;
750
751 if (!(opts & OPT_GET)) {
752 serial_set(argv, opts);
753 argv[1] = NULL;
754 }
755
756 if (opts & (OPT_VERBOSE | OPT_GET)) {
757 do {
758 serial_get(*argv++, opts & OPT_MODE_MASK);
759 } while (*argv);
760 }
761
762 return EXIT_SUCCESS;
763}
Note: See TracBrowser for help on using the repository browser.