Diff below adds support for printing USB ports status. It includes an
ABI change as we currently do not export port status/change to userland.
I'd really like to export the current cached value to userland via the
USB_DEVICEINFO ioctl(2) to reduce the numbers of I/O.
Note that this diff also fixes some link-status defines in usb.h
Since it includes an ABI break I cranked devel/libusb1.
$ usbdevs -dvv
Controller /dev/usb0:
addr 01: 8086:0000 Intel, xHCI root hub
super speed, self powered, config 1, rev 1.00
driver: uhub0
port 01: 0000.02a0 power Rx.detect
port 02: 0000.02a0 power Rx.detect
port 03: 0000.02a0 power Rx.detect
port 04: 0000.0503 connect enabled recovery
port 05: 0000.02a0 power Rx.detect
...
addr 02: 04f2:b45d Chicony Electronics Co.,Ltd., Integrated Camera
high speed, power 500 mA, config 1, rev 0.29, iSerialNumber 0x0001
driver: uvideo0
ok?
Index: src/usr.sbin/usbdevs/usbdevs.c
===================================================================
RCS file: /cvs/src/usr.sbin/usbdevs/usbdevs.c,v
retrieving revision 1.27
diff -u -p -r1.27 usbdevs.c
--- src/usr.sbin/usbdevs/usbdevs.c 3 Jul 2018 13:21:31 -0000 1.27
+++ src/usr.sbin/usbdevs/usbdevs.c 4 Jul 2018 14:46:08 -0000
@@ -54,7 +54,7 @@ int verbose = 0;
int showdevs = 0;
void usage(void);
-void usbdev(int f, uint8_t, int rec);
+void usbdev(int f, uint8_t);
void usbdump(int f);
void dumpone(char *name, int f, int addr);
int main(int, char **);
@@ -69,13 +69,13 @@ usage(void)
}
char done[USB_MAX_DEVICES];
-int indent;
void
-usbdev(int f, uint8_t addr, int rec)
+usbdev(int f, uint8_t addr)
{
struct usb_device_info di;
- int e, p, i, s, nports;
+ int e, i, port, nports;
+ uint16_t change, status;
di.udi_addr = addr;
e = ioctl(f, USB_DEVICEINFO, &di);
@@ -89,6 +89,7 @@ usbdev(int f, uint8_t addr, int rec)
done[addr] = 1;
printf("%04x:%04x %s, %s", di.udi_vendorNo, di.udi_productNo,
di.udi_vendor, di.udi_product);
+
if (verbose) {
printf("\n\t ");
switch (di.udi_speed) {
@@ -122,48 +123,96 @@ usbdev(int f, uint8_t addr, int rec)
printf(", iSerialNumber %s", di.udi_serial);
}
printf("\n");
+
if (showdevs) {
for (i = 0; i < USB_MAX_DEVNAMES; i++)
if (di.udi_devnames[i][0])
- printf("%*s %s\n", indent, "",
- di.udi_devnames[i]);
+ printf("\t driver: %s\n", di.udi_devnames[i]);
}
- if (!rec)
- return;
- nports = MINIMUM(di.udi_nports, nitems(di.udi_ports));
if (verbose > 1) {
- for (p = 0; p < nports; p++) {
- s = di.udi_ports[p];
- printf("\t port %02u:", p+1);
- if (s < USB_MAX_DEVICES)
- printf(" addr %02u\n", s);
- else {
- printf(" %s\n",
- s == USB_PORT_ENABLED ? "enabled" :
- s == USB_PORT_SUSPENDED ? "suspended" :
- s == USB_PORT_POWERED ? "powered" :
- s == USB_PORT_DISABLED ? "disabled" :
- "???");
+ nports = MINIMUM(di.udi_nports, nitems(di.udi_ports));
+ for (port = 0; port < nports; port++) {
+ status = di.udi_ports[port] & 0xffff;
+ change = di.udi_ports[port] >> 16;
+ printf("\t port %02u: %04x.%04x", port+1, change,
+ status);
+
+ if (status & UPS_CURRENT_CONNECT_STATUS)
+ printf(" connect");
+
+ if (status & UPS_PORT_ENABLED)
+ printf(" enabled");
+
+ if (status & UPS_SUSPEND)
+ printf(" supsend");
+
+ if (status & UPS_OVERCURRENT_INDICATOR)
+ printf(" overcurrent");
+
+ if (di.udi_speed < USB_SPEED_SUPER) {
+ if (status & UPS_PORT_L1)
+ printf(" l1");
+
+ if (status & UPS_PORT_POWER)
+ printf(" power");
+ } else {
+ if (status & UPS_PORT_POWER_SS)
+ printf(" power");
+
+ switch (UPS_PORT_LS_GET(status)) {
+ case UPS_PORT_LS_U0:
+ printf(" U0");
+ break;
+ case UPS_PORT_LS_U1:
+ printf(" U1");
+ break;
+ case UPS_PORT_LS_U2:
+ printf(" U2");
+ break;
+ case UPS_PORT_LS_U3:
+ printf(" U3");
+ break;
+ case UPS_PORT_LS_SS_DISABLED:
+ printf(" SS.disabled");
+ break;
+ case UPS_PORT_LS_RX_DETECT:
+ printf(" Rx.detect");
+ break;
+ case UPS_PORT_LS_SS_INACTIVE:
+ printf(" ss.inactive");
+ break;
+ case UPS_PORT_LS_POLLING:
+ printf(" polling");
+ break;
+ case UPS_PORT_LS_RECOVERY:
+ printf(" recovery");
+ break;
+ case UPS_PORT_LS_HOT_RESET:
+ printf(" hot.reset");
+ break;
+ case UPS_PORT_LS_COMP_MOD:
+ printf(" comp.mod");
+ break;
+ case UPS_PORT_LS_LOOPBACK:
+ printf(" loopback");
+ break;
+ }
}
- }
- }
- for (p = 0; p < nports ; p++) {
- s = di.udi_ports[p];
- if (s < USB_MAX_DEVICES)
- usbdev(f, s, 1);
+ printf("\n");
+ }
}
}
void
usbdump(int f)
{
- int a;
+ uint8_t addr;
- for (a = 1; a < USB_MAX_DEVICES; a++) {
- if (!done[a])
- usbdev(f, a, 1);
+ for (addr = 1; addr < USB_MAX_DEVICES; addr++) {
+ if (!done[addr])
+ usbdev(f, addr);
}
}
@@ -172,10 +221,9 @@ dumpone(char *name, int f, int addr)
{
if (!addr)
printf("Controller %s:\n", name);
- indent = 0;
memset(done, 0, sizeof done);
if (addr)
- usbdev(f, addr, 0);
+ usbdev(f, addr);
else
usbdump(f);
}
Index: src/sys/dev/usb/usb.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb.h,v
retrieving revision 1.59
diff -u -p -r1.59 usb.h
--- src/sys/dev/usb/usb.h 1 Sep 2017 16:38:14 -0000 1.59
+++ src/sys/dev/usb/usb.h 4 Jul 2018 14:52:02 -0000
@@ -442,18 +442,19 @@ struct usb_port_status {
#define UPS_PORT_L1 0x0020 /* USB 2.0 only */
/* Super-Speed port link state values. */
-#define UPS_PORT_LS_U0 0x0000
-#define UPS_PORT_LS_U1 0x0020
-#define UPS_PORT_LS_U2 0x0040
-#define UPS_PORT_LS_U3 0x0060
-#define UPS_PORT_LS_SS_DISABLED 0x0080
-#define UPS_PORT_LS_RX_DETECT 0x00a0
-#define UPS_PORT_LS_SS_INACTIVE 0x00c0
-#define UPS_PORT_LS_POLLING 0x00e0
-#define UPS_PORT_LS_RECOVERY 0x0100
-#define UPS_PORT_LS_HOT_RESET 0x0120
-#define UPS_PORT_LS_COMP_MOD 0x0140
-#define UPS_PORT_LS_LOOPBACK 0x0160
+#define UPS_PORT_LS_U0 0x00
+#define UPS_PORT_LS_U1 0x01
+#define UPS_PORT_LS_U2 0x02
+#define UPS_PORT_LS_U3 0x03
+#define UPS_PORT_LS_SS_DISABLED 0x04
+#define UPS_PORT_LS_RX_DETECT 0x05
+#define UPS_PORT_LS_SS_INACTIVE 0x06
+#define UPS_PORT_LS_POLLING 0x07
+#define UPS_PORT_LS_RECOVERY 0x08
+#define UPS_PORT_LS_HOT_RESET 0x09
+#define UPS_PORT_LS_COMP_MOD 0x0a
+#define UPS_PORT_LS_LOOPBACK 0x0b
+#define UPS_PORT_LS_RESUME 0x0f
#define UPS_PORT_LS_GET(x) (((x) >> 5) & 0xf)
#define UPS_PORT_LS_SET(x) (((x) & 0xf) << 5)
@@ -739,11 +740,7 @@ struct usb_device_info {
int udi_power; /* power consumption in mA, 0 if
selfpowered */
int udi_nports;
char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
- u_int8_t udi_ports[16];/* hub only: addresses of devices on
ports */
-#define USB_PORT_ENABLED 0xff
-#define USB_PORT_SUSPENDED 0xfe
-#define USB_PORT_POWERED 0xfd
-#define USB_PORT_DISABLED 0xfc
+ u_int32_t udi_ports[16]; /* hub only: ports status/change */
char udi_serial[USB_MAX_STRING_LEN];
};
Index: src/sys/dev/usb/usb_subr.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.136
diff -u -p -r1.136 usb_subr.c
--- src/sys/dev/usb/usb_subr.c 1 May 2018 18:14:46 -0000 1.136
+++ src/sys/dev/usb/usb_subr.c 4 Jul 2018 14:18:36 -0000
@@ -1304,7 +1304,7 @@ void
usbd_fill_deviceinfo(struct usbd_device *dev, struct usb_device_info *di)
{
struct usbd_port *p;
- int i, err, s;
+ int i;
di->udi_bus = dev->bus->usbctl->dv_unit;
di->udi_addr = dev->address;
@@ -1338,20 +1338,8 @@ usbd_fill_deviceinfo(struct usbd_device
for (i = 0;
i < nitems(di->udi_ports) && i < dev->hub->nports; i++) {
p = &dev->hub->ports[i];
- if (p->device)
- err = p->device->address;
- else {
- s = UGETW(p->status.wPortStatus);
- if (s & UPS_PORT_ENABLED)
- err = USB_PORT_ENABLED;
- else if (s & UPS_SUSPEND)
- err = USB_PORT_SUSPENDED;
- else if (s & UPS_PORT_POWER)
- err = USB_PORT_POWERED;
- else
- err = USB_PORT_DISABLED;
- }
- di->udi_ports[i] = err;
+ di->udi_ports[i] = UGETW(p->status.wPortChange) << 16 |
+ UGETW(p->status.wPortStatus);
}
di->udi_nports = dev->hub->nports;
} else
Index: ports/devel/libusb1/Makefile
===================================================================
RCS file: /cvs/ports/devel/libusb1/Makefile,v
retrieving revision 1.27
diff -u -p -r1.27 Makefile
--- ports/devel/libusb1/Makefile 19 Apr 2017 06:09:02 -0000 1.27
+++ ports/devel/libusb1/Makefile 4 Jul 2018 14:16:36 -0000
@@ -3,6 +3,7 @@
COMMENT = library for USB device access from userspace
VERSION = 1.0.21
+REVISION = 0
DISTNAME = libusb-${VERSION}
PKGNAME = libusb1-${VERSION}