123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763 |
- /* vi: set sw=4 ts=4: */
- /*
- * setserial implementation for busybox
- *
- *
- * Copyright (C) 2011 Marek Bečka <yuen@klacno.sk>
- *
- * Licensed under GPLv2 or later, see file LICENSE in this source tree.
- */
- //config:config SETSERIAL
- //config: bool "setserial"
- //config: default y
- //config: select PLATFORM_LINUX
- //config: help
- //config: Retrieve or set Linux serial port.
- //applet:IF_SETSERIAL(APPLET(setserial, BB_DIR_BIN, BB_SUID_DROP))
- //kbuild:lib-$(CONFIG_SETSERIAL) += setserial.o
- #include "libbb.h"
- #include <assert.h>
- #ifndef PORT_UNKNOWN
- # define PORT_UNKNOWN 0
- #endif
- #ifndef PORT_8250
- # define PORT_8250 1
- #endif
- #ifndef PORT_16450
- # define PORT_16450 2
- #endif
- #ifndef PORT_16550
- # define PORT_16550 3
- #endif
- #ifndef PORT_16550A
- # define PORT_16550A 4
- #endif
- #ifndef PORT_CIRRUS
- # define PORT_CIRRUS 5
- #endif
- #ifndef PORT_16650
- # define PORT_16650 6
- #endif
- #ifndef PORT_16650V2
- # define PORT_16650V2 7
- #endif
- #ifndef PORT_16750
- # define PORT_16750 8
- #endif
- #ifndef PORT_STARTECH
- # define PORT_STARTECH 9
- #endif
- #ifndef PORT_16C950
- # define PORT_16C950 10
- #endif
- #ifndef PORT_16654
- # define PORT_16654 11
- #endif
- #ifndef PORT_16850
- # define PORT_16850 12
- #endif
- #ifndef PORT_RSA
- # define PORT_RSA 13
- #endif
- #ifndef PORT_NS16550A
- # define PORT_NS16550A 14
- #endif
- #ifndef PORT_XSCALE
- # define PORT_XSCALE 15
- #endif
- #ifndef PORT_RM9000
- # define PORT_RM9000 16
- #endif
- #ifndef PORT_OCTEON
- # define PORT_OCTEON 17
- #endif
- #ifndef PORT_AR7
- # define PORT_AR7 18
- #endif
- #ifndef PORT_U6_16550A
- # define PORT_U6_16550A 19
- #endif
- #ifndef ASYNCB_HUP_NOTIFY
- # define ASYNCB_HUP_NOTIFY 0
- #endif
- #ifndef ASYNCB_FOURPORT
- # define ASYNCB_FOURPORT 1
- #endif
- #ifndef ASYNCB_SAK
- # define ASYNCB_SAK 2
- #endif
- #ifndef ASYNCB_SPLIT_TERMIOS
- # define ASYNCB_SPLIT_TERMIOS 3
- #endif
- #ifndef ASYNCB_SPD_HI
- # define ASYNCB_SPD_HI 4
- #endif
- #ifndef ASYNCB_SPD_VHI
- # define ASYNCB_SPD_VHI 5
- #endif
- #ifndef ASYNCB_SKIP_TEST
- # define ASYNCB_SKIP_TEST 6
- #endif
- #ifndef ASYNCB_AUTO_IRQ
- # define ASYNCB_AUTO_IRQ 7
- #endif
- #ifndef ASYNCB_SESSION_LOCKOUT
- # define ASYNCB_SESSION_LOCKOUT 8
- #endif
- #ifndef ASYNCB_PGRP_LOCKOUT
- # define ASYNCB_PGRP_LOCKOUT 9
- #endif
- #ifndef ASYNCB_CALLOUT_NOHUP
- # define ASYNCB_CALLOUT_NOHUP 10
- #endif
- #ifndef ASYNCB_SPD_SHI
- # define ASYNCB_SPD_SHI 12
- #endif
- #ifndef ASYNCB_LOW_LATENCY
- # define ASYNCB_LOW_LATENCY 13
- #endif
- #ifndef ASYNCB_BUGGY_UART
- # define ASYNCB_BUGGY_UART 14
- #endif
- #ifndef ASYNC_HUP_NOTIFY
- # define ASYNC_HUP_NOTIFY (1U << ASYNCB_HUP_NOTIFY)
- #endif
- #ifndef ASYNC_FOURPORT
- # define ASYNC_FOURPORT (1U << ASYNCB_FOURPORT)
- #endif
- #ifndef ASYNC_SAK
- # define ASYNC_SAK (1U << ASYNCB_SAK)
- #endif
- #ifndef ASYNC_SPLIT_TERMIOS
- # define ASYNC_SPLIT_TERMIOS (1U << ASYNCB_SPLIT_TERMIOS)
- #endif
- #ifndef ASYNC_SPD_HI
- # define ASYNC_SPD_HI (1U << ASYNCB_SPD_HI)
- #endif
- #ifndef ASYNC_SPD_VHI
- # define ASYNC_SPD_VHI (1U << ASYNCB_SPD_VHI)
- #endif
- #ifndef ASYNC_SKIP_TEST
- # define ASYNC_SKIP_TEST (1U << ASYNCB_SKIP_TEST)
- #endif
- #ifndef ASYNC_AUTO_IRQ
- # define ASYNC_AUTO_IRQ (1U << ASYNCB_AUTO_IRQ)
- #endif
- #ifndef ASYNC_SESSION_LOCKOUT
- # define ASYNC_SESSION_LOCKOUT (1U << ASYNCB_SESSION_LOCKOUT)
- #endif
- #ifndef ASYNC_PGRP_LOCKOUT
- # define ASYNC_PGRP_LOCKOUT (1U << ASYNCB_PGRP_LOCKOUT)
- #endif
- #ifndef ASYNC_CALLOUT_NOHUP
- # define ASYNC_CALLOUT_NOHUP (1U << ASYNCB_CALLOUT_NOHUP)
- #endif
- #ifndef ASYNC_SPD_SHI
- # define ASYNC_SPD_SHI (1U << ASYNCB_SPD_SHI)
- #endif
- #ifndef ASYNC_LOW_LATENCY
- # define ASYNC_LOW_LATENCY (1U << ASYNCB_LOW_LATENCY)
- #endif
- #ifndef ASYNC_BUGGY_UART
- # define ASYNC_BUGGY_UART (1U << ASYNCB_BUGGY_UART)
- #endif
- #ifndef ASYNC_SPD_CUST
- # define ASYNC_SPD_CUST (ASYNC_SPD_HI|ASYNC_SPD_VHI)
- #endif
- #ifndef ASYNC_SPD_WARP
- # define ASYNC_SPD_WARP (ASYNC_SPD_HI|ASYNC_SPD_SHI)
- #endif
- #ifndef ASYNC_SPD_MASK
- # define ASYNC_SPD_MASK (ASYNC_SPD_HI|ASYNC_SPD_VHI|ASYNC_SPD_SHI)
- #endif
- #ifndef ASYNC_CLOSING_WAIT_INF
- # define ASYNC_CLOSING_WAIT_INF 0
- #endif
- #ifndef ASYNC_CLOSING_WAIT_NONE
- # define ASYNC_CLOSING_WAIT_NONE 65535
- #endif
- #ifndef _LINUX_SERIAL_H
- struct serial_struct {
- int type;
- int line;
- unsigned int port;
- int irq;
- int flags;
- int xmit_fifo_size;
- int custom_divisor;
- int baud_base;
- unsigned short close_delay;
- char io_type;
- char reserved_char[1];
- int hub6;
- unsigned short closing_wait; /* time to wait before closing */
- unsigned short closing_wait2; /* no longer used... */
- unsigned char *iomem_base;
- unsigned short iomem_reg_shift;
- unsigned int port_high;
- unsigned long iomap_base; /* cookie passed into ioremap */
- };
- #endif
- //usage:#define setserial_trivial_usage
- //usage: "[-gabGvzV] DEVICE [PARAMETER [ARG]]..."
- //usage:#define setserial_full_usage "\n\n"
- //usage: "Request or set Linux serial port information\n"
- //usage: "\n"
- //usage: " -g Interpret parameters as list of devices for reporting\n"
- //usage: " -a Print all available information\n"
- //usage: " -b Print summary information\n"
- //usage: " -G Print in form which can be fed back\n"
- //usage: " to setserial as command line parameters\n"
- //usage: " -z Zero out serial flags before setting\n"
- //usage: " -v Verbose\n"
- //usage: "\n"
- //usage: "Parameters: (* = takes an argument, ^ = can be turned off by preceding ^)\n"
- //usage: " *port, *irq, *divisor, *uart, *baud_base, *close_delay, *closing_wait,\n"
- //usage: " ^fourport, ^auto_irq, ^skip_test, ^sak, ^session_lockout, ^pgrp_lockout,\n"
- //usage: " ^callout_nohup, ^split_termios, ^hup_notify, ^low_latency, autoconfig,\n"
- //usage: " spd_normal, spd_hi, spd_vhi, spd_shi, spd_warp, spd_cust\n"
- //usage: "\n"
- //usage: "UART types:\n"
- //usage: " unknown, 8250, 16450, 16550, 16550A, Cirrus, 16650, 16650V2, 16750,\n"
- //usage: " 16950, 16954, 16654, 16850, RSA, NS16550A, XSCALE, RM9000, OCTEON, AR7,\n"
- //usage: " U6_16550A"
- #define OPT_PRINT_SUMMARY (1 << 0)
- #define OPT_PRINT_FEDBACK (1 << 1)
- #define OPT_PRINT_ALL (1 << 2)
- #define OPT_VERBOSE (1 << 3)
- #define OPT_ZERO (1 << 4)
- #define OPT_GET (1 << 5)
- #define OPT_MODE_MASK \
- (OPT_PRINT_ALL | OPT_PRINT_SUMMARY | OPT_PRINT_FEDBACK)
- enum print_mode
- {
- PRINT_NORMAL = 0,
- PRINT_SUMMARY = (1 << 0),
- PRINT_FEDBACK = (1 << 1),
- PRINT_ALL = (1 << 2),
- };
- #define CTL_SET (1 << 0)
- #define CTL_CONFIG (1 << 1)
- #define CTL_GET (1 << 2)
- #define CTL_CLOSE (1 << 3)
- #define CTL_NODIE (1 << 4)
- static const char serial_types[] ALIGN1 =
- "unknown\0" /* 0 */
- "8250\0" /* 1 */
- "16450\0" /* 2 */
- "16550\0" /* 3 */
- "16550A\0" /* 4 */
- "Cirrus\0" /* 5 */
- "16650\0" /* 6 */
- "16650V2\0" /* 7 */
- "16750\0" /* 8 */
- "16950\0" /* 9 UNIMPLEMENTED: also know as "16950/954" */
- "16954\0" /* 10 */
- "16654\0" /* 11 */
- "16850\0" /* 12 */
- "RSA\0" /* 13 */
- #ifndef SETSERIAL_BASE
- "NS16550A\0" /* 14 */
- "XSCALE\0" /* 15 */
- "RM9000\0" /* 16 */
- "OCTEON\0" /* 17 */
- "AR7\0" /* 18 */
- "U6_16550A\0" /* 19 */
- #endif
- ;
- #ifndef SETSERIAL_BASE
- # define MAX_SERIAL_TYPE 19
- #else
- # define MAX_SERIAL_TYPE 13
- #endif
- static const char commands[] ALIGN1 =
- "spd_normal\0"
- "spd_hi\0"
- "spd_vhi\0"
- "spd_shi\0"
- "spd_warp\0"
- "spd_cust\0"
- "sak\0"
- "fourport\0"
- "hup_notify\0"
- "skip_test\0"
- "auto_irq\0"
- "split_termios\0"
- "session_lockout\0"
- "pgrp_lockout\0"
- "callout_nohup\0"
- "low_latency\0"
- "port\0"
- "irq\0"
- "divisor\0"
- "uart\0"
- "baud_base\0"
- "close_delay\0"
- "closing_wait\0"
- "autoconfig\0"
- ;
- enum
- {
- CMD_SPD_NORMAL = 0,
- CMD_SPD_HI,
- CMD_SPD_VHI,
- CMD_SPD_SHI,
- CMD_SPD_WARP,
- CMD_SPD_CUST,
- CMD_FLAG_SAK,
- CMD_FLAG_FOURPORT,
- CMD_FLAG_NUP_NOTIFY,
- CMD_FLAG_SKIP_TEST,
- CMD_FLAG_AUTO_IRQ,
- CMD_FLAG_SPLIT_TERMIOS,
- CMD_FLAG_SESSION_LOCKOUT,
- CMD_FLAG_PGRP_LOCKOUT,
- CMD_FLAG_CALLOUT_NOHUP,
- CMD_FLAG_LOW_LATENCY,
- CMD_PORT,
- CMD_IRQ,
- CMD_DIVISOR,
- CMD_UART,
- CMD_BASE,
- CMD_DELAY,
- CMD_WAIT,
- CMD_AUTOCONFIG,
- CMD_FLAG_FIRST = CMD_FLAG_SAK,
- CMD_FLAG_LAST = CMD_FLAG_LOW_LATENCY,
- };
- static bool cmd_noprint(int cmd)
- {
- return (cmd >= CMD_FLAG_SKIP_TEST && cmd <= CMD_FLAG_CALLOUT_NOHUP);
- }
- static bool cmd_is_flag(int cmd)
- {
- return (cmd >= CMD_FLAG_FIRST && cmd <= CMD_FLAG_LAST);
- }
- static bool cmd_need_arg(int cmd)
- {
- return (cmd >= CMD_PORT && cmd <= CMD_WAIT);
- }
- #define ALL_SPD ( \
- ASYNC_SPD_HI | ASYNC_SPD_VHI | ASYNC_SPD_SHI | \
- ASYNC_SPD_WARP | ASYNC_SPD_CUST \
- )
- #define ALL_FLAGS ( \
- ASYNC_SAK | ASYNC_FOURPORT | ASYNC_HUP_NOTIFY | \
- ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ | ASYNC_SPLIT_TERMIOS | \
- ASYNC_SESSION_LOCKOUT | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP | \
- ASYNC_LOW_LATENCY \
- )
- #if (ALL_SPD | ALL_FLAGS) > 0xffff
- # error "Unexpected flags size"
- #endif
- static const uint16_t setbits[CMD_FLAG_LAST + 1] =
- {
- 0,
- ASYNC_SPD_HI,
- ASYNC_SPD_VHI,
- ASYNC_SPD_SHI,
- ASYNC_SPD_WARP,
- ASYNC_SPD_CUST,
- ASYNC_SAK,
- ASYNC_FOURPORT,
- ASYNC_HUP_NOTIFY,
- ASYNC_SKIP_TEST,
- ASYNC_AUTO_IRQ,
- ASYNC_SPLIT_TERMIOS,
- ASYNC_SESSION_LOCKOUT,
- ASYNC_PGRP_LOCKOUT,
- ASYNC_CALLOUT_NOHUP,
- ASYNC_LOW_LATENCY
- };
- #define STR_INFINITE "infinite"
- #define STR_NONE "none"
- static const char *uart_type(int type)
- {
- if (type > MAX_SERIAL_TYPE)
- return "undefined";
- return nth_string(serial_types, type);
- }
- /* libbb candidate */
- static int index_in_strings_case_insensitive(const char *strings, const char *key)
- {
- int idx = 0;
- while (*strings) {
- if (strcasecmp(strings, key) == 0) {
- return idx;
- }
- strings += strlen(strings) + 1; /* skip NUL */
- idx++;
- }
- return -1;
- }
- static int uart_id(const char *name)
- {
- return index_in_strings_case_insensitive(serial_types, name);
- }
- static const char *get_spd(int flags, enum print_mode mode)
- {
- int idx;
- switch (flags & ASYNC_SPD_MASK) {
- case ASYNC_SPD_HI:
- idx = CMD_SPD_HI;
- break;
- case ASYNC_SPD_VHI:
- idx = CMD_SPD_VHI;
- break;
- case ASYNC_SPD_SHI:
- idx = CMD_SPD_SHI;
- break;
- case ASYNC_SPD_WARP:
- idx = CMD_SPD_WARP;
- break;
- case ASYNC_SPD_CUST:
- idx = CMD_SPD_CUST;
- break;
- default:
- if (mode < PRINT_FEDBACK)
- return NULL;
- idx = CMD_SPD_NORMAL;
- }
- return nth_string(commands, idx);
- }
- static int get_numeric(const char *arg)
- {
- return bb_strtol(arg, NULL, 0);
- }
- static int get_wait(const char *arg)
- {
- if (strcasecmp(arg, STR_NONE) == 0)
- return ASYNC_CLOSING_WAIT_NONE;
- if (strcasecmp(arg, STR_INFINITE) == 0)
- return ASYNC_CLOSING_WAIT_INF;
- return get_numeric(arg);
- }
- static int get_uart(const char *arg)
- {
- int uart = uart_id(arg);
- if (uart < 0)
- bb_error_msg_and_die("illegal UART type: %s", arg);
- return uart;
- }
- static int serial_open(const char *dev, bool quiet)
- {
- int fd;
- fd = device_open(dev, O_RDWR | O_NONBLOCK);
- if (fd < 0 && !quiet)
- bb_simple_perror_msg(dev);
- return fd;
- }
- static int serial_ctl(int fd, int ops, struct serial_struct *serinfo)
- {
- int ret = 0;
- const char *err;
- if (ops & CTL_SET) {
- ret = ioctl(fd, TIOCSSERIAL, serinfo);
- if (ret < 0) {
- err = "can't set serial info";
- goto fail;
- }
- }
- if (ops & CTL_CONFIG) {
- ret = ioctl(fd, TIOCSERCONFIG);
- if (ret < 0) {
- err = "can't autoconfigure port";
- goto fail;
- }
- }
- if (ops & CTL_GET) {
- ret = ioctl(fd, TIOCGSERIAL, serinfo);
- if (ret < 0) {
- err = "can't get serial info";
- goto fail;
- }
- }
- nodie:
- if (ops & CTL_CLOSE)
- close(fd);
- return ret;
- fail:
- bb_simple_perror_msg(err);
- if (ops & CTL_NODIE)
- goto nodie;
- exit(EXIT_FAILURE);
- }
- static void print_flag(const char **prefix, const char *flag)
- {
- printf("%s%s", *prefix, flag);
- *prefix = " ";
- }
- static void print_serial_flags(int serial_flags, enum print_mode mode,
- const char *prefix, const char *postfix)
- {
- int i;
- const char *spd, *pr;
- pr = prefix;
- spd = get_spd(serial_flags, mode);
- if (spd)
- print_flag(&pr, spd);
- for (i = CMD_FLAG_FIRST; i <= CMD_FLAG_LAST; i++) {
- if ((serial_flags & setbits[i])
- && (mode > PRINT_SUMMARY || !cmd_noprint(i))
- ) {
- print_flag(&pr, nth_string(commands, i));
- }
- }
- puts(pr == prefix ? "" : postfix);
- }
- static void print_closing_wait(unsigned int closing_wait)
- {
- switch (closing_wait) {
- case ASYNC_CLOSING_WAIT_NONE:
- puts(STR_NONE);
- break;
- case ASYNC_CLOSING_WAIT_INF:
- puts(STR_INFINITE);
- break;
- default:
- printf("%u\n", closing_wait);
- }
- }
- static void serial_get(const char *device, enum print_mode mode)
- {
- int fd, ret;
- const char *uart, *prefix, *postfix;
- struct serial_struct serinfo;
- fd = serial_open(device, /*quiet:*/ mode == PRINT_SUMMARY);
- if (fd < 0)
- return;
- ret = serial_ctl(fd, CTL_GET | CTL_CLOSE | CTL_NODIE, &serinfo);
- if (ret < 0)
- return;
- uart = uart_type(serinfo.type);
- prefix = ", Flags: ";
- postfix = "";
- switch (mode) {
- case PRINT_NORMAL:
- printf("%s, UART: %s, Port: 0x%.4x, IRQ: %d",
- device, uart, serinfo.port, serinfo.irq);
- break;
- case PRINT_SUMMARY:
- if (!serinfo.type)
- return;
- printf("%s at 0x%.4x (irq = %d) is a %s",
- device, serinfo.port, serinfo.irq, uart);
- prefix = " (";
- postfix = ")";
- break;
- case PRINT_FEDBACK:
- printf("%s uart %s port 0x%.4x irq %d baud_base %d", device,
- uart, serinfo.port, serinfo.irq, serinfo.baud_base);
- prefix = " ";
- break;
- case PRINT_ALL:
- printf("%s, Line %d, UART: %s, Port: 0x%.4x, IRQ: %d\n",
- device, serinfo.line, uart, serinfo.port, serinfo.irq);
- printf("\tBaud_base: %d, close_delay: %u, divisor: %d\n",
- serinfo.baud_base, serinfo.close_delay,
- serinfo.custom_divisor);
- printf("\tclosing_wait: ");
- print_closing_wait(serinfo.closing_wait);
- prefix = "\tFlags: ";
- postfix = "\n";
- break;
- default:
- assert(0);
- }
- print_serial_flags(serinfo.flags, mode, prefix, postfix);
- }
- static int find_cmd(const char *cmd)
- {
- int idx;
- idx = index_in_strings_case_insensitive(commands, cmd);
- if (idx < 0)
- bb_error_msg_and_die("invalid flag: %s", cmd);
- return idx;
- }
- static void serial_set(char **arg, int opts)
- {
- struct serial_struct serinfo;
- int cmd;
- const char *word;
- int fd;
- fd = serial_open(*arg++, /*quiet:*/ false);
- if (fd < 0)
- exit(201);
- serial_ctl(fd, CTL_GET, &serinfo);
- if (opts & OPT_ZERO)
- serinfo.flags = 0;
- while (*arg) {
- int invert;
- word = *arg++;
- invert = (*word == '^');
- word += invert;
- cmd = find_cmd(word);
- if (*arg == NULL && cmd_need_arg(cmd))
- bb_error_msg_and_die(bb_msg_requires_arg, word);
- if (invert && !cmd_is_flag(cmd))
- bb_error_msg_and_die("can't invert %s", word);
- switch (cmd) {
- case CMD_SPD_NORMAL:
- case CMD_SPD_HI:
- case CMD_SPD_VHI:
- case CMD_SPD_SHI:
- case CMD_SPD_WARP:
- case CMD_SPD_CUST:
- serinfo.flags &= ~ASYNC_SPD_MASK;
- /* fallthrough */
- case CMD_FLAG_SAK:
- case CMD_FLAG_FOURPORT:
- case CMD_FLAG_NUP_NOTIFY:
- case CMD_FLAG_SKIP_TEST:
- case CMD_FLAG_AUTO_IRQ:
- case CMD_FLAG_SPLIT_TERMIOS:
- case CMD_FLAG_SESSION_LOCKOUT:
- case CMD_FLAG_PGRP_LOCKOUT:
- case CMD_FLAG_CALLOUT_NOHUP:
- case CMD_FLAG_LOW_LATENCY:
- if (invert)
- serinfo.flags &= ~setbits[cmd];
- else
- serinfo.flags |= setbits[cmd];
- break;
- case CMD_PORT:
- serinfo.port = get_numeric(*arg++);
- break;
- case CMD_IRQ:
- serinfo.irq = get_numeric(*arg++);
- break;
- case CMD_DIVISOR:
- serinfo.custom_divisor = get_numeric(*arg++);
- break;
- case CMD_UART:
- serinfo.type = get_uart(*arg++);
- break;
- case CMD_BASE:
- serinfo.baud_base = get_numeric(*arg++);
- break;
- case CMD_DELAY:
- serinfo.close_delay = get_numeric(*arg++);
- break;
- case CMD_WAIT:
- serinfo.closing_wait = get_wait(*arg++);
- break;
- case CMD_AUTOCONFIG:
- serial_ctl(fd, CTL_SET | CTL_CONFIG | CTL_GET, &serinfo);
- break;
- default:
- assert(0);
- }
- }
- serial_ctl(fd, CTL_SET | CTL_CLOSE, &serinfo);
- }
- int setserial_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
- int setserial_main(int argc UNUSED_PARAM, char **argv)
- {
- int opts;
- opt_complementary = "-1:b-aG:G-ab:a-bG";
- opts = getopt32(argv, "bGavzg");
- argv += optind;
- if (!argv[1]) /* one arg only? */
- opts |= OPT_GET;
- if (!(opts & OPT_GET)) {
- serial_set(argv, opts);
- argv[1] = NULL;
- }
- if (opts & (OPT_VERBOSE | OPT_GET)) {
- do {
- serial_get(*argv++, opts & OPT_MODE_MASK);
- } while (*argv);
- }
- return EXIT_SUCCESS;
- }
|