busybox/miscutils/setserial.c
Denys Vlasenko 22542eca18 getopt32: remove opt_complementary
function                                             old     new   delta
vgetopt32                                           1318    1392     +74
runsvdir_main                                        703     713     +10
bb_make_directory                                    423     425      +2
collect_cpu                                          546     545      -1
opt_chars                                              3       -      -3
opt_complementary                                      4       -      -4
tftpd_main                                           567     562      -5
ntp_init                                             476     471      -5
zcip_main                                           1266    1256     -10
xxd_main                                             428     418     -10
whois_main                                           140     130     -10
who_main                                             463     453     -10
which_main                                           212     202     -10
wget_main                                           2535    2525     -10
watchdog_main                                        291     281     -10
watch_main                                           222     212     -10
vlock_main                                           399     389     -10
uuencode_main                                        332     322     -10
uudecode_main                                        316     306     -10
unlink_main                                           45      35     -10
udhcpd_main                                         1482    1472     -10
udhcpc_main                                         2762    2752     -10
tune2fs_main                                         290     280     -10
tunctl_main                                          366     356     -10
truncate_main                                        218     208     -10
tr_main                                              518     508     -10
time_main                                           1134    1124     -10
tftp_main                                            286     276     -10
telnetd_main                                        1873    1863     -10
tcpudpsvd_main                                      1785    1775     -10
taskset_main                                         521     511     -10
tar_main                                            1009     999     -10
tail_main                                           1644    1634     -10
syslogd_main                                        1967    1957     -10
switch_root_main                                     368     358     -10
svlogd_main                                         1454    1444     -10
sv                                                  1296    1286     -10
stat_main                                            104      94     -10
start_stop_daemon_main                              1028    1018     -10
split_main                                           542     532     -10
sort_main                                            796     786     -10
slattach_main                                        624     614     -10
shuf_main                                            504     494     -10
setsid_main                                           96      86     -10
setserial_main                                      1132    1122     -10
setfont_main                                         388     378     -10
setconsole_main                                       78      68     -10
sendmail_main                                       1209    1199     -10
sed_main                                             677     667     -10
script_main                                         1077    1067     -10
run_parts_main                                       325     315     -10
rtcwake_main                                         454     444     -10
rm_main                                              175     165     -10
reformime_main                                       119     109     -10
readlink_main                                        123     113     -10
rdate_main                                           246     236     -10
pwdx_main                                            189     179     -10
pstree_main                                          317     307     -10
pscan_main                                           663     653     -10
popmaildir_main                                      818     808     -10
pmap_main                                             80      70     -10
nc_main                                             1042    1032     -10
mv_main                                              558     548     -10
mountpoint_main                                      477     467     -10
mount_main                                          1264    1254     -10
modprobe_main                                        768     758     -10
modinfo_main                                         333     323     -10
mktemp_main                                          200     190     -10
mkswap_main                                          324     314     -10
mkfs_vfat_main                                      1489    1479     -10
microcom_main                                        715     705     -10
md5_sha1_sum_main                                    521     511     -10
man_main                                             867     857     -10
makedevs_main                                       1052    1042     -10
ls_main                                              563     553     -10
losetup_main                                         432     422     -10
loadfont_main                                         89      79     -10
ln_main                                              524     514     -10
link_main                                             75      65     -10
ipcalc_main                                          544     534     -10
iostat_main                                         2397    2387     -10
install_main                                         768     758     -10
id_main                                              480     470     -10
i2cset_main                                         1239    1229     -10
i2cget_main                                          380     370     -10
i2cdump_main                                        1482    1472     -10
i2cdetect_main                                       682     672     -10
hwclock_main                                         406     396     -10
httpd_main                                           741     731     -10
grep_main                                            837     827     -10
getty_main                                          1559    1549     -10
fuser_main                                           297     287     -10
ftpgetput_main                                       345     335     -10
ftpd_main                                           2232    2222     -10
fstrim_main                                          251     241     -10
fsfreeze_main                                         77      67     -10
fsck_minix_main                                     2921    2911     -10
flock_main                                           314     304     -10
flashcp_main                                         740     730     -10
flash_eraseall_main                                  833     823     -10
fdformat_main                                        532     522     -10
expand_main                                          680     670     -10
eject_main                                           335     325     -10
dumpleases_main                                      630     620     -10
du_main                                              314     304     -10
dos2unix_main                                        441     431     -10
diff_main                                           1350    1340     -10
df_main                                             1064    1054     -10
date_main                                           1095    1085     -10
cut_main                                             961     951     -10
cryptpw_main                                         228     218     -10
crontab_main                                         575     565     -10
crond_main                                          1149    1139     -10
cp_main                                              370     360     -10
common_traceroute_main                              3834    3824     -10
common_ping_main                                    1767    1757     -10
comm_main                                            239     229     -10
cmp_main                                             655     645     -10
chrt_main                                            379     369     -10
chpst_main                                           704     694     -10
chpasswd_main                                        308     298     -10
chown_main                                           171     161     -10
chmod_main                                           158     148     -10
cat_main                                             428     418     -10
bzip2_main                                           120     110     -10
blkdiscard_main                                      264     254     -10
base64_main                                          221     211     -10
arping_main                                         1665    1655     -10
ar_main                                              556     546     -10
adjtimex_main                                        406     396     -10
adduser_main                                         882     872     -10
addgroup_main                                        411     401     -10
acpid_main                                          1198    1188     -10
optstring                                             11       -     -11
opt_string                                            18       -     -18
OPT_STR                                               25       -     -25
ubi_tools_main                                      1288    1258     -30
ls_options                                            31       -     -31
------------------------------------------------------------------------------
(add/remove: 0/6 grow/shrink: 3/129 up/down: 86/-1383)      Total: -1297 bytes
   text	   data	    bss	    dec	    hex	filename
 915428	    485	   6876	 922789	  e14a5	busybox_old
 914629	    485	   6872	 921986	  e1182	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2017-08-08 21:55:02 +02:00

765 lines
16 KiB
C

/* 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 (6.6 kb)"
//config: default y
//config: select PLATFORM_LINUX
//config: help
//config: Retrieve or set Linux serial port.
//applet:IF_SETSERIAL(APPLET_NOEXEC(setserial, setserial, BB_DIR_BIN, BB_SUID_DROP, setserial))
//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: "[-abGvz] { DEVICE [PARAMETER [ARG]]... | -g DEVICE... }"
//usage:#define setserial_full_usage "\n\n"
//usage: "Print or set serial port parameters"
//usage: "\n"
//usage: "\n"" -a Print all"
//usage: "\n"" -b Print summary"
//usage: "\n"" -G Print as setserial PARAMETERs"
//usage: "\n"" -v Verbose"
//usage: "\n"" -z Zero out serial flags before setting"
//usage: "\n"" -g All args are device names"
//usage: "\n"
//usage: "\n""PARAMETERs: (* = takes ARG, ^ = can be turned off by preceding ^)"
//usage: "\n"" *port, *irq, *divisor, *uart, *baud_base, *close_delay, *closing_wait,"
//usage: "\n"" ^fourport, ^auto_irq, ^skip_test, ^sak, ^session_lockout, ^pgrp_lockout,"
//usage: "\n"" ^callout_nohup, ^split_termios, ^hup_notify, ^low_latency, autoconfig,"
//usage: "\n"" spd_normal, spd_hi, spd_vhi, spd_shi, spd_warp, spd_cust"
//usage: "\n""ARG for uart:"
//usage: "\n"" unknown, 8250, 16450, 16550, 16550A, Cirrus, 16650, 16650V2, 16750,"
//usage: "\n"" 16950, 16954, 16654, 16850, RSA, NS16550A, XSCALE, RM9000, OCTEON, AR7,"
//usage: "\n"" U6_16550A"
// option string is "bGavzgq". "q" is accepted but ignored.
#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_LIST_OF_DEVS (1 << 5)
/*#define OPT_QUIET (1 << 6)*/
#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_needs_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 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) {
const char *word;
int invert;
int cmd;
word = *arg;
invert = (word[0] == '^');
word += invert;
cmd = find_cmd(word);
if (cmd_needs_arg(cmd))
if (*++arg == NULL)
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;
opts = getopt32(argv, "^" "bGavzgq" "\0" "-1:b-aG:G-ab:a-bG");
argv += optind;
if (!argv[1]) /* one arg only? (nothing to change?) */
opts |= OPT_LIST_OF_DEVS; /* force display */
if (!(opts & OPT_LIST_OF_DEVS)) {
serial_set(argv, opts);
argv[1] = NULL;
}
/* -v effect: "after setting params, do not be silent, show them" */
if (opts & (OPT_VERBOSE | OPT_LIST_OF_DEVS)) {
do {
serial_get(*argv, opts & OPT_MODE_MASK);
} while (*++argv);
}
return EXIT_SUCCESS;
}