Index: head/usr.sbin/usbconfig/usbconfig.8 =================================================================== --- head/usr.sbin/usbconfig/usbconfig.8 (revision 351145) +++ head/usr.sbin/usbconfig/usbconfig.8 (revision 351146) @@ -1,167 +1,172 @@ .\" $FreeBSD$ .\" .\" Copyright (c) 2008-2010 Hans Petter Selasky. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 29, 2018 +.Dd August 16, 2019 .Dt USBCONFIG 8 .Os .Sh NAME .Nm usbconfig .Nd configure the USB subsystem .Sh SYNOPSIS .Nm .Op Fl u Ar unit .Op Fl a Ar addr .Op cmds... .Nm .Op Oo Fl d Oc Ar [ugen]. .Op cmds... .Sh DESCRIPTION The .Nm utility is used to configure and dump information about the USB subsystem. .Pp The options are as follows: .Bl -tag -width " " .It Fl u Ar unit Limit device range to USB devices connected to the given USBUS unit. .It Fl a Ar addr Limit device range to the given USB device index. Should only be used in conjunction with the unit argument. .It Fl d Ar [ugen]. Limit device range to USB devices connected to the given unit and address. The unit and address coordinates may be prefixed by the lowercased word "ugen". +.It Fl i Ar interface_index +Specify interface index as indicated by the command description. +If this argument is not specified a value of zero will be used for the interface index. .It Fl h Show help and available commands. .El .Pp The following commands may be used with .Nm : .Bl -tag -width indent .It Cm set_config Ar cfg_index Choose the configuration for the USB device. Valid values range from zero to the number reported as the .Ar bNumConfigurations in .Cm dump_device_desc output. The special value of 255 unconfigures the device, detaching the interface drivers and reducing the power consumption to minimum, but without going into power saving mode or detaching from the bus. In some cases, it prevents the device from charging. .It Cm set_alt Ar alt_index -Choose the alternate interface for the USB device. +Choose the alternate interface for the selected interface and USB device. Alternative settings for the current configuration are available as the .Ar bAlternateSetting in .Cm dump_curr_config_desc output. Usually there is no need to adjust this setting. .It Cm set_template Ar template Set the global USB device side template. See .Xr usb_template 4 for more information. .It Cm get_template Get the current USB device side template. .It Cm add_dev_quirk_vplh Ar vid Ar pid Ar lo_rev Ar hi_rev Ar quirk_name Add a quirk by specifying the Vendor ID, Product ID, low and high revision numbers, and the quirk name. See .Xr usb_quirk 4 for more information. .It Cm remove_dev_quirk_vplh Ar vid Ar pid Ar lo_rev Ar hi_rev Ar quirk_name Remove a quirk. .It Cm add_quirk Ar quirk_name Add quirk for the currently selected USB device. .It Cm remove_quirk Ar quirk_name Remove a quirk for the currently selected USB device. .It Cm dump_all_desc Display the device and configuration descriptors. .It Cm dump_quirk_names Display the list of supported quirk names. .It Cm dump_device_quirks Display the list of current device quirks. .It Cm dump_device_desc Display the device descriptor. .It Cm dump_curr_config_desc Display current configuration descriptor. .It Cm dump_all_config_desc Display all the configuration descriptors. .It Cm dump_string Ar index Display string descriptor at selected index. .It Cm dump_info Display summary information about the device. .It Cm show_ifdrv Display the list of interface drivers (such as .Xr ukbd 4 or .Xr u3g 4 ) currently attached to the device. +.It Cm detach_kernel_driver +Detach kernel driver for the selected interface and USB device. .It Cm suspend Force the device to suspend. .It Cm resume Force the device to resume. .It Cm power_off Turn the device off. .It Cm power_save Turn the automatic suspend and resume on. This is the default for USB hubs. .It Cm power_on Turn the device on and disable automatic suspend and resume. This is the default for non-hub devices. .It Cm reset Reset the device. This forces the USB stack to reenumerate the bus. .It Cm list List all available USB devices. This is the default if .Nm is called without specifying a command. .It Cm do_request Ar bmReqTyp Ar bReq Ar wVal Ar wIdx Ar wLen Ar data... Perform a synchronous control request on the specified device. See .Xr libusb20_dev_request_sync 3 for more information. .El .Sh EXAMPLES List all connected USB devices and their attached interface drivers: .Pp .Dl usbconfig show_ifdrv .Pp Dump device and configuration descriptors for device on USB bus 1 at address 2: .Pp .Dl usbconfig ugen1.2 dump_all_desc .Pp Dump HID descriptor for device on USB bus 1 at address 2: .Pp .Dl usbconfig ugen1.2 do_request 0x81 0x06 0x2200 0 0x100 .Pp Power off the device on USB bus 1 at address 2: .Pp .Dl usbconfig ugen1.2 power_off .Sh SEE ALSO .Xr usb 4 , .Xr usb_quirk 4 , .Xr usb_template 4 Index: head/usr.sbin/usbconfig/usbconfig.c =================================================================== --- head/usr.sbin/usbconfig/usbconfig.c (revision 351145) +++ head/usr.sbin/usbconfig/usbconfig.c (revision 351146) @@ -1,863 +1,879 @@ /* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dump.h" struct options { const char *quirkname; void *buffer; int template; gid_t gid; uid_t uid; mode_t mode; uint32_t got_any; struct LIBUSB20_CONTROL_SETUP_DECODED setup; uint16_t bus; uint16_t addr; uint16_t iface; uint16_t vid; uint16_t pid; uint16_t lo_rev; /* inclusive */ uint16_t hi_rev; /* inclusive */ uint8_t string_index; uint8_t config_index; uint8_t alt_index; uint8_t got_list:1; uint8_t got_bus:1; uint8_t got_addr:1; uint8_t got_iface:1; uint8_t got_set_config:1; uint8_t got_set_alt:1; uint8_t got_set_template:1; uint8_t got_get_template:1; uint8_t got_suspend:1; uint8_t got_resume:1; uint8_t got_reset:1; uint8_t got_power_off:1; uint8_t got_power_save:1; uint8_t got_power_on:1; uint8_t got_dump_device_quirks:1; uint8_t got_dump_quirk_names:1; uint8_t got_dump_all_desc:1; uint8_t got_dump_device_desc:1; uint8_t got_dump_curr_config:1; uint8_t got_dump_all_config:1; uint8_t got_dump_info:1; uint8_t got_show_iface_driver:1; uint8_t got_remove_device_quirk:1; uint8_t got_add_device_quirk:1; uint8_t got_remove_quirk:1; uint8_t got_add_quirk:1; uint8_t got_dump_string:1; uint8_t got_do_request:1; + uint8_t got_detach_kernel_driver:1; }; struct token { const char *name; uint8_t value; uint8_t narg; }; enum { T_UNIT, T_ADDR, T_UGEN, T_IFACE, T_SET_CONFIG, T_SET_ALT, T_SET_TEMPLATE, T_GET_TEMPLATE, T_ADD_DEVICE_QUIRK, T_REMOVE_DEVICE_QUIRK, T_ADD_QUIRK, T_REMOVE_QUIRK, T_SHOW_IFACE_DRIVER, + T_DETACH_KERNEL_DRIVER, T_DUMP_QUIRK_NAMES, T_DUMP_DEVICE_QUIRKS, T_DUMP_ALL_DESC, T_DUMP_DEVICE_DESC, T_DUMP_CURR_CONFIG_DESC, T_DUMP_ALL_CONFIG_DESC, T_DUMP_STRING, T_DUMP_INFO, T_SUSPEND, T_RESUME, T_POWER_OFF, T_POWER_SAVE, T_POWER_ON, T_RESET, T_LIST, T_DO_REQUEST, }; static struct options options; static const struct token token[] = { {"-u", T_UNIT, 1}, {"-a", T_ADDR, 1}, {"-d", T_UGEN, 1}, {"-i", T_IFACE, 1}, {"set_config", T_SET_CONFIG, 1}, {"set_alt", T_SET_ALT, 1}, {"set_template", T_SET_TEMPLATE, 1}, {"get_template", T_GET_TEMPLATE, 0}, {"add_dev_quirk_vplh", T_ADD_DEVICE_QUIRK, 5}, {"remove_dev_quirk_vplh", T_REMOVE_DEVICE_QUIRK, 5}, {"add_quirk", T_ADD_QUIRK, 1}, {"remove_quirk", T_REMOVE_QUIRK, 1}, + {"detach_kernel_driver", T_DETACH_KERNEL_DRIVER, 0}, {"dump_quirk_names", T_DUMP_QUIRK_NAMES, 0}, {"dump_device_quirks", T_DUMP_DEVICE_QUIRKS, 0}, {"dump_all_desc", T_DUMP_ALL_DESC, 0}, {"dump_device_desc", T_DUMP_DEVICE_DESC, 0}, {"dump_curr_config_desc", T_DUMP_CURR_CONFIG_DESC, 0}, {"dump_all_config_desc", T_DUMP_ALL_CONFIG_DESC, 0}, {"dump_string", T_DUMP_STRING, 1}, {"dump_info", T_DUMP_INFO, 0}, {"show_ifdrv", T_SHOW_IFACE_DRIVER, 0}, {"suspend", T_SUSPEND, 0}, {"resume", T_RESUME, 0}, {"power_off", T_POWER_OFF, 0}, {"power_save", T_POWER_SAVE, 0}, {"power_on", T_POWER_ON, 0}, {"reset", T_RESET, 0}, {"list", T_LIST, 0}, {"do_request", T_DO_REQUEST, 5}, }; static void be_dev_remove_quirk(struct libusb20_backend *pbe, uint16_t vid, uint16_t pid, uint16_t lorev, uint16_t hirev, const char *str) { struct libusb20_quirk q; int error; memset(&q, 0, sizeof(q)); q.vid = vid; q.pid = pid; q.bcdDeviceLow = lorev; q.bcdDeviceHigh = hirev; strlcpy(q.quirkname, str, sizeof(q.quirkname)); error = libusb20_be_remove_dev_quirk(pbe, &q); if (error) { fprintf(stderr, "Removing quirk '%s' failed, continuing.\n", str); } return; } static void be_dev_add_quirk(struct libusb20_backend *pbe, uint16_t vid, uint16_t pid, uint16_t lorev, uint16_t hirev, const char *str) { struct libusb20_quirk q; int error; memset(&q, 0, sizeof(q)); q.vid = vid; q.pid = pid; q.bcdDeviceLow = lorev; q.bcdDeviceHigh = hirev; strlcpy(q.quirkname, str, sizeof(q.quirkname)); error = libusb20_be_add_dev_quirk(pbe, &q); if (error) { fprintf(stderr, "Adding quirk '%s' failed, continuing.\n", str); } return; } static uint8_t get_token(const char *str, uint8_t narg) { uint8_t n; for (n = 0; n != (sizeof(token) / sizeof(token[0])); n++) { if (strcasecmp(str, token[n].name) == 0) { if (token[n].narg > narg) { /* too few arguments */ break; } return (token[n].value); } } return (0 - 1); } static uid_t num_id(const char *name, const char *type) { uid_t val; char *ep; errno = 0; val = strtoul(name, &ep, 0); if (errno) { err(1, "%s", name); } if (*ep != '\0') { errx(1, "%s: illegal %s name", name, type); } return (val); } static int get_int(const char *s) { int val; char *ep; errno = 0; val = strtoul(s, &ep, 0); if (errno) { err(1, "%s", s); } if (*ep != '\0') { errx(1, "illegal number: %s", s); } return val; } static void duplicate_option(const char *ptr) { fprintf(stderr, "Syntax error: " "Duplicate option: '%s'\n", ptr); exit(1); } static void usage(void) { fprintf(stderr, "" "usbconfig - configure the USB subsystem" "\n" "usage: usbconfig -u -a -i [cmds...]" "\n" "usage: usbconfig -d [ugen]. -i [cmds...]" "\n" "commands:" "\n" " set_config " "\n" " set_alt " "\n" " set_template