18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * command structure borrowed from udev 48c2ecf20Sopenharmony_ci * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git) 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 78c2ecf20Sopenharmony_ci * 2005-2007 Takahiro Hirofuchi 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <stdio.h> 118c2ecf20Sopenharmony_ci#include <stdlib.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <getopt.h> 148c2ecf20Sopenharmony_ci#include <syslog.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "usbip_common.h" 178c2ecf20Sopenharmony_ci#include "usbip_network.h" 188c2ecf20Sopenharmony_ci#include "usbip.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic int usbip_help(int argc, char *argv[]); 218c2ecf20Sopenharmony_cistatic int usbip_version(int argc, char *argv[]); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic const char usbip_version_string[] = PACKAGE_STRING; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic const char usbip_usage_string[] = 268c2ecf20Sopenharmony_ci "usbip [--debug] [--log] [--tcp-port PORT] [version]\n" 278c2ecf20Sopenharmony_ci " [help] <command> <args>\n"; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic void usbip_usage(void) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci printf("usage: %s", usbip_usage_string); 328c2ecf20Sopenharmony_ci} 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistruct command { 358c2ecf20Sopenharmony_ci const char *name; 368c2ecf20Sopenharmony_ci int (*fn)(int argc, char *argv[]); 378c2ecf20Sopenharmony_ci const char *help; 388c2ecf20Sopenharmony_ci void (*usage)(void); 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic const struct command cmds[] = { 428c2ecf20Sopenharmony_ci { 438c2ecf20Sopenharmony_ci .name = "help", 448c2ecf20Sopenharmony_ci .fn = usbip_help, 458c2ecf20Sopenharmony_ci .help = NULL, 468c2ecf20Sopenharmony_ci .usage = NULL 478c2ecf20Sopenharmony_ci }, 488c2ecf20Sopenharmony_ci { 498c2ecf20Sopenharmony_ci .name = "version", 508c2ecf20Sopenharmony_ci .fn = usbip_version, 518c2ecf20Sopenharmony_ci .help = NULL, 528c2ecf20Sopenharmony_ci .usage = NULL 538c2ecf20Sopenharmony_ci }, 548c2ecf20Sopenharmony_ci { 558c2ecf20Sopenharmony_ci .name = "attach", 568c2ecf20Sopenharmony_ci .fn = usbip_attach, 578c2ecf20Sopenharmony_ci .help = "Attach a remote USB device", 588c2ecf20Sopenharmony_ci .usage = usbip_attach_usage 598c2ecf20Sopenharmony_ci }, 608c2ecf20Sopenharmony_ci { 618c2ecf20Sopenharmony_ci .name = "detach", 628c2ecf20Sopenharmony_ci .fn = usbip_detach, 638c2ecf20Sopenharmony_ci .help = "Detach a remote USB device", 648c2ecf20Sopenharmony_ci .usage = usbip_detach_usage 658c2ecf20Sopenharmony_ci }, 668c2ecf20Sopenharmony_ci { 678c2ecf20Sopenharmony_ci .name = "list", 688c2ecf20Sopenharmony_ci .fn = usbip_list, 698c2ecf20Sopenharmony_ci .help = "List exportable or local USB devices", 708c2ecf20Sopenharmony_ci .usage = usbip_list_usage 718c2ecf20Sopenharmony_ci }, 728c2ecf20Sopenharmony_ci { 738c2ecf20Sopenharmony_ci .name = "bind", 748c2ecf20Sopenharmony_ci .fn = usbip_bind, 758c2ecf20Sopenharmony_ci .help = "Bind device to " USBIP_HOST_DRV_NAME ".ko", 768c2ecf20Sopenharmony_ci .usage = usbip_bind_usage 778c2ecf20Sopenharmony_ci }, 788c2ecf20Sopenharmony_ci { 798c2ecf20Sopenharmony_ci .name = "unbind", 808c2ecf20Sopenharmony_ci .fn = usbip_unbind, 818c2ecf20Sopenharmony_ci .help = "Unbind device from " USBIP_HOST_DRV_NAME ".ko", 828c2ecf20Sopenharmony_ci .usage = usbip_unbind_usage 838c2ecf20Sopenharmony_ci }, 848c2ecf20Sopenharmony_ci { 858c2ecf20Sopenharmony_ci .name = "port", 868c2ecf20Sopenharmony_ci .fn = usbip_port_show, 878c2ecf20Sopenharmony_ci .help = "Show imported USB devices", 888c2ecf20Sopenharmony_ci .usage = NULL 898c2ecf20Sopenharmony_ci }, 908c2ecf20Sopenharmony_ci { NULL, NULL, NULL, NULL } 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic int usbip_help(int argc, char *argv[]) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci const struct command *cmd; 968c2ecf20Sopenharmony_ci int i; 978c2ecf20Sopenharmony_ci int ret = 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (argc > 1 && argv++) { 1008c2ecf20Sopenharmony_ci for (i = 0; cmds[i].name != NULL; i++) 1018c2ecf20Sopenharmony_ci if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) { 1028c2ecf20Sopenharmony_ci cmds[i].usage(); 1038c2ecf20Sopenharmony_ci goto done; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci ret = -1; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci usbip_usage(); 1098c2ecf20Sopenharmony_ci printf("\n"); 1108c2ecf20Sopenharmony_ci for (cmd = cmds; cmd->name != NULL; cmd++) 1118c2ecf20Sopenharmony_ci if (cmd->help != NULL) 1128c2ecf20Sopenharmony_ci printf(" %-10s %s\n", cmd->name, cmd->help); 1138c2ecf20Sopenharmony_ci printf("\n"); 1148c2ecf20Sopenharmony_cidone: 1158c2ecf20Sopenharmony_ci return ret; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic int usbip_version(int argc, char *argv[]) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci (void) argc; 1218c2ecf20Sopenharmony_ci (void) argv; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci printf(PROGNAME " (%s)\n", usbip_version_string); 1248c2ecf20Sopenharmony_ci return 0; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int run_command(const struct command *cmd, int argc, char *argv[]) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci dbg("running command: `%s'", cmd->name); 1308c2ecf20Sopenharmony_ci return cmd->fn(argc, argv); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci static const struct option opts[] = { 1368c2ecf20Sopenharmony_ci { "debug", no_argument, NULL, 'd' }, 1378c2ecf20Sopenharmony_ci { "log", no_argument, NULL, 'l' }, 1388c2ecf20Sopenharmony_ci { "tcp-port", required_argument, NULL, 't' }, 1398c2ecf20Sopenharmony_ci { NULL, 0, NULL, 0 } 1408c2ecf20Sopenharmony_ci }; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci char *cmd; 1438c2ecf20Sopenharmony_ci int opt; 1448c2ecf20Sopenharmony_ci int i, rc = -1; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci usbip_use_stderr = 1; 1478c2ecf20Sopenharmony_ci opterr = 0; 1488c2ecf20Sopenharmony_ci for (;;) { 1498c2ecf20Sopenharmony_ci opt = getopt_long(argc, argv, "+dlt:", opts, NULL); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci if (opt == -1) 1528c2ecf20Sopenharmony_ci break; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci switch (opt) { 1558c2ecf20Sopenharmony_ci case 'd': 1568c2ecf20Sopenharmony_ci usbip_use_debug = 1; 1578c2ecf20Sopenharmony_ci break; 1588c2ecf20Sopenharmony_ci case 'l': 1598c2ecf20Sopenharmony_ci usbip_use_syslog = 1; 1608c2ecf20Sopenharmony_ci openlog("", LOG_PID, LOG_USER); 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci case 't': 1638c2ecf20Sopenharmony_ci usbip_setup_port_number(optarg); 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case '?': 1668c2ecf20Sopenharmony_ci printf("usbip: invalid option\n"); 1678c2ecf20Sopenharmony_ci /* Terminate after printing error */ 1688c2ecf20Sopenharmony_ci /* FALLTHRU */ 1698c2ecf20Sopenharmony_ci default: 1708c2ecf20Sopenharmony_ci usbip_usage(); 1718c2ecf20Sopenharmony_ci goto out; 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci cmd = argv[optind]; 1768c2ecf20Sopenharmony_ci if (cmd) { 1778c2ecf20Sopenharmony_ci for (i = 0; cmds[i].name != NULL; i++) 1788c2ecf20Sopenharmony_ci if (!strcmp(cmds[i].name, cmd)) { 1798c2ecf20Sopenharmony_ci argc -= optind; 1808c2ecf20Sopenharmony_ci argv += optind; 1818c2ecf20Sopenharmony_ci optind = 0; 1828c2ecf20Sopenharmony_ci rc = run_command(&cmds[i], argc, argv); 1838c2ecf20Sopenharmony_ci goto out; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* invalid command */ 1888c2ecf20Sopenharmony_ci usbip_help(0, NULL); 1898c2ecf20Sopenharmony_ciout: 1908c2ecf20Sopenharmony_ci return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE); 1918c2ecf20Sopenharmony_ci} 192