aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/usb.469
-rw-r--r--sys/dev/usb/uhub.c5
-rw-r--r--sys/dev/usb/usb.c57
-rw-r--r--sys/dev/usb/usb.h1
-rw-r--r--sys/dev/usb/usb_port.h3
-rw-r--r--sys/dev/usb/usb_subr.c7
-rw-r--r--sys/dev/usb/usbdi.h3
-rw-r--r--usr.sbin/usbd/usbd.c77
8 files changed, 179 insertions, 43 deletions
diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4
index 0b63d965aea3..0fb22094ce56 100644
--- a/share/man/man4/usb.4
+++ b/share/man/man4/usb.4
@@ -291,11 +291,78 @@ The include file
similarly contains the definitions for
Human Interface Devices
.Pq Tn HID .
+.Sh USB EVENT INTERFACE
+All
+.Tn USB
+events are reported via the
+.Pa /dev/usb
+device. This devices can be opened for reading and each
+.Xr read 2
+will yield an event record (if something has happened).
+The
+.Xr poll 2
+system call can be used to determine if an event record is available
+for reading.
+.Pp
+The event record has the following definition:
+.Bd -literal
+struct usb_event {
+ int ue_type;
+#define USB_EVENT_CTRLR_ATTACH 1
+#define USB_EVENT_CTRLR_DETACH 2
+#define USB_EVENT_DEVICE_ATTACH 3
+#define USB_EVENT_DEVICE_DETACH 4
+#define USB_EVENT_DRIVER_ATTACH 5
+#define USB_EVENT_DRIVER_DETACH 6
+ struct timespec ue_time;
+ union {
+ struct {
+ int ue_bus;
+ } ue_ctrlr;
+ struct usb_device_info ue_device;
+ struct {
+ usb_event_cookie_t ue_cookie;
+ char ue_devname[16];
+ } ue_driver;
+ } u;
+};
+.Ed
+The
+.Va ue_type
+field identifies the type of event that is described.
+The possible events are attach/detach of a host controller,
+a device, or a device driver. The union contains information
+pertinent to the different types of events.
+.br
+The
+.Va ue_bus
+contains the number of the
+.Tn USB
+bus for host controller events.
+.br
+The
+.Va ue_device
+record contains information about the device in a device event event.
+.br
+The
+.Va ue_cookie
+is an opaque value that uniquely determines which which
+device a device driver has been attached to (i.e., it equals
+the cookie value in the device that the driver attached to).
+The
+.Va ue_devname
+contains the name of the device (driver) as seen in, e.g.,
+kernel messages.
+.Pp
+Note that that there is a separation between device and device
+driver events. A device event is generated when a physical
+USB device is attached or detached. A single USB device may
+have zero, one, or many device drivers associated with it.
.Sh SEE ALSO
The
.Tn USB
specifications can be found at:
-.D1 http://www.usb.org/developers/docs.htm .
+.D1 http://www.usb.org/developers/docs.html
.Pp
.Xr usb 3 ,
.Xr aue 4 ,
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 0533249aab8d..05a19729e8e2 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -263,6 +263,8 @@ USB_ATTACH(uhub)
/* Wait with power off for a while. */
usbd_delay_ms(dev, USB_POWER_DOWN_TIME);
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev));
+
/*
* To have the best chance of success we do things in the exact same
* order as Windoze98. This should not be necessary, but some
@@ -525,7 +527,8 @@ USB_DETACH(uhub)
if (rup->device)
usb_disconnect_port(rup, self);
}
-
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, dev, USBDEV(sc->sc_dev));
free(dev->hub, M_USBDEV);
dev->hub = NULL;
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 545d35c97ec3..0798248809df 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usb.c,v 1.37 2000/01/24 18:35:51 thorpej Exp $ */
+/* $NetBSD: usb.c,v 1.38 2000/02/02 07:33:59 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -163,6 +163,7 @@ Static int usb_nevents = 0;
Static struct selinfo usb_selevent;
Static struct proc *usb_async_proc; /* process that wants USB SIGIO */
Static int usb_dev_open = 0;
+Static void usb_add_event(int, struct usb_event *);
Static int usb_get_next_event(struct usb_event *);
@@ -201,6 +202,7 @@ USB_ATTACH(usb)
usbd_device_handle dev;
usbd_status err;
int usbrev;
+ struct usb_event ue;
sc->sc_dev = self;
@@ -226,6 +228,9 @@ USB_ATTACH(usb)
if (cold)
sc->sc_bus->use_polling++;
+ ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
+ usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
+
err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, 0, 0,
&sc->sc_port);
if (!err) {
@@ -631,18 +636,45 @@ usb_get_next_event(struct usb_event *ue)
}
void
-usbd_add_event(int type, usbd_device_handle dev)
+usbd_add_dev_event(int type, usbd_device_handle udev)
+{
+ struct usb_event ue;
+
+ usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type));
+ usb_add_event(type, &ue);
+}
+
+void
+usbd_add_drv_event(int type, usbd_device_handle udev, device_ptr_t dev)
+{
+ struct usb_event ue;
+
+ ue.u.ue_driver.ue_cookie = udev->cookie;
+ strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev),
+ sizeof ue.u.ue_driver.ue_devname);
+ usb_add_event(type, &ue);
+}
+
+void
+usb_add_event(int type, struct usb_event *uep)
{
struct usb_event_q *ueq, *ueq_next;
struct usb_event ue;
struct timeval thetime;
int s;
+ ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK);
+ ueq->ue = *uep;
+ ueq->ue.ue_type = type;
+ microtime(&thetime);
+ TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
+
s = splusb();
- if (type == USB_EVENT_CTRLR_DETACH) {
+ if (USB_EVENT_IS_DETACH(type)) {
for (ueq = TAILQ_FIRST(&usb_events); ueq; ueq = ueq_next) {
ueq_next = TAILQ_NEXT(ueq, next);
- if (ueq->ue.u.ue_driver.ue_cookie.cookie == dev->cookie.cookie) {
+ if (ueq->ue.u.ue_driver.ue_cookie.cookie ==
+ uep->u.ue_device.cookie.cookie) {
TAILQ_REMOVE(&usb_events, ueq, next);
free(ueq, M_USBDEV);
usb_nevents--;
@@ -655,18 +687,6 @@ usbd_add_event(int type, usbd_device_handle dev)
DPRINTF(("usb: event dropped\n"));
(void)usb_get_next_event(&ue);
}
- /* Don't want to wait here inside splusb() */
- ueq = malloc(sizeof *ueq, M_USBDEV, M_NOWAIT);
- if (ueq == NULL) {
- printf("usb: no memory, event dropped\n");
- splx(s);
- return;
- }
- ueq->ue.ue_type = type;
- ueq->ue.u.ue_driver.ue_cookie = dev->cookie;
- usbd_fill_deviceinfo(dev, &ueq->ue.u.ue_device, 0);
- microtime(&thetime);
- TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
TAILQ_INSERT_TAIL(&usb_events, ueq, next);
usb_nevents++;
wakeup(&usb_events);
@@ -713,6 +733,7 @@ int
usb_detach(device_ptr_t self, int flags)
{
struct usb_softc *sc = (struct usb_softc *)self;
+ struct usb_event ue;
DPRINTF(("usb_detach: start\n"));
@@ -732,6 +753,10 @@ usb_detach(device_ptr_t self, int flags)
}
usbd_finish();
+
+ ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
+ usb_add_event(USB_EVENT_CTRLR_DETACH, &ue);
+
return (0);
}
#elif defined(__FreeBSD__)
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 21c733f33831..8d5a3da94d1e 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -627,6 +627,7 @@ struct usb_event {
#define USB_EVENT_DRIVER_ATTACH 5
#define USB_EVENT_DRIVER_DETACH 6
#define USB_EVENT_IS_ATTACH(n) ((n) == USB_EVENT_CTRLR_ATTACH || (n) == USB_EVENT_DEVICE_ATTACH || (n) == USB_EVENT_DRIVER_ATTACH)
+#define USB_EVENT_IS_DETACH(n) ((n) == USB_EVENT_CTRLR_DETACH || (n) == USB_EVENT_DEVICE_DETACH || (n) == USB_EVENT_DRIVER_DETACH)
struct timespec ue_time;
union {
struct {
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 3f7842250bc9..e2ac72f97e0e 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -70,6 +70,7 @@ typedef struct device *device_ptr_t;
#define USBBASEDEVICE struct device
#define USBDEV(bdev) (&(bdev))
#define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVUNIT(bdev) ((bdev).dv_unit)
#define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
#define USBDEVUNIT(bdev) ((bdev).dv_unit)
@@ -191,6 +192,7 @@ typedef struct device device_ptr_t;
#define USBBASEDEVICE struct device
#define USBDEV(bdev) (&(bdev))
#define USBDEVNAME(bdev) ((bdev).dv_xname)
+#define USBDEVUNIT(bdev) ((bdev).dv_unit)
#define USBDEVPTRNAME(bdevptr) ((bdevptr)->dv_xname)
#define USBDEVUNIT(bdev) ((bdev).dv_unit)
@@ -290,6 +292,7 @@ __CONCAT(dname,_detach)(self, flags) \
#define USBBASEDEVICE device_t
#define USBDEV(bdev) (bdev)
#define USBDEVNAME(bdev) device_get_nameunit(bdev)
+#define USBDEVUNIT(bdev) device_get_unit(bdev)
#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev)
#define USBDEVUNIT(bdev) device_get_unit(bdev)
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index f17e5155cf03..2565c44a8e59 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1031,9 +1031,9 @@ usbd_new_device(device_ptr_t parent, usbd_bus_handle bus, int depth,
usbd_remove_device(dev, up);
return (err);
}
-
- usbd_add_event(USB_EVENT_CTRLR_ATTACH, dev);
+ usbd_add_dev_event(USB_EVENT_DEVICE_ATTACH, dev);
+
return (USBD_NORMAL_COMPLETION);
}
@@ -1158,6 +1158,7 @@ usbd_fill_deviceinfo(usbd_device_handle dev, struct usb_device_info *di,
di->bus = USBDEVUNIT(dev->bus->bdev);
di->addr = dev->address;
+ di->cookie = dev->cookie;
usbd_devinfo_vp(dev, di->vendor, di->product, usedev);
usbd_printBCD(di->release, UGETW(dev->ddesc.bcdDevice));
di->vendorNo = UGETW(dev->ddesc.idVendor);
@@ -1281,7 +1282,7 @@ usb_disconnect_port(struct usbd_port *up, device_ptr_t parent)
}
}
- /*usbd_add_event(USB_EVENT_DETACH, dev);*/
+ /*usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);*/
dev->bus->devices[dev->address] = NULL;
up->device = NULL;
usb_free_device(dev);
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index bb5bfbf7fbe3..7a184e7b87e7 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -176,7 +176,8 @@ void usbd_set_polling(usbd_interface_handle iface, int on);
const char *usbd_errstr(usbd_status err);
-void usbd_add_event(int, usbd_device_handle);
+void usbd_add_dev_event (int, usbd_device_handle);
+void usbd_add_drv_event (int, usbd_device_handle, device_ptr_t);
void usbd_devinfo(usbd_device_handle, int, char *);
const struct usbd_quirks *usbd_get_quirks(usbd_device_handle);
diff --git a/usr.sbin/usbd/usbd.c b/usr.sbin/usbd/usbd.c
index 967a80b9b1a2..ff5387d85fe4 100644
--- a/usr.sbin/usbd/usbd.c
+++ b/usr.sbin/usbd/usbd.c
@@ -109,8 +109,12 @@ typedef struct event_name_s {
} event_name_t;
event_name_t event_names[] = {
- {USB_EVENT_CTRLR_ATTACH, "attach"},
- {USB_EVENT_CTRLR_DETACH, "detach"},
+ {USB_EVENT_CTRLR_ATTACH, "ctrlr-attach"},
+ {USB_EVENT_CTRLR_DETACH, "ctrlr-detach"},
+ {USB_EVENT_DRIVER_ATTACH, "driver-attach"},
+ {USB_EVENT_DRIVER_DETACH, "driver-detach"},
+ {USB_EVENT_DEVICE_ATTACH, "device-attach"},
+ {USB_EVENT_DEVICE_DETACH, "device-detach"},
{0, NULL} /* NULL indicates end of list, not 0 */
};
@@ -572,28 +576,42 @@ print_event(struct usb_event *event)
if (event_names[i].name == NULL)
printf("unknown event %d", event->ue_type);
- printf(" at %ld.%09ld, %s, %s:\n",
- timespec->tv_sec, timespec->tv_nsec,
- devinfo->product, devinfo->vendor);
+ if (event->ue_type == USB_EVENT_DEVICE_ATTACH ||
+ event->ue_type == USB_EVENT_DEVICE_DETACH) {
+ devinfo = &event->u.ue_device;
- printf(" vndr=0x%04x prdct=0x%04x rlse=0x%04x "
- "clss=0x%04x subclss=0x%04x prtcl=0x%04x\n",
- devinfo->vendorNo, devinfo->productNo, devinfo->releaseNo,
- devinfo->class, devinfo->subclass, devinfo->protocol);
+ printf(" at %ld.%09ld, %s, %s:\n",
+ timespec->tv_sec, timespec->tv_nsec,
+ devinfo->product, devinfo->vendor);
- if (devinfo->devnames[0][0] != '\0') {
- char c = ' ';
+ printf(" vndr=0x%04x prdct=0x%04x rlse=0x%04x "
+ "clss=0x%04x subclss=0x%04x prtcl=0x%04x\n",
+ devinfo->vendorNo, devinfo->productNo,
+ devinfo->releaseNo,
+ devinfo->class, devinfo->subclass, devinfo->protocol);
- printf(" device names:");
- for (i = 0; i < USB_MAX_DEVNAMES; i++) {
- if (devinfo->devnames[i][0] == '\0')
- break;
+ if (devinfo->devnames[0][0] != '\0') {
+ char c = ' ';
+
+ printf(" device names:");
+ for (i = 0; i < USB_MAX_DEVNAMES; i++) {
+ if (devinfo->devnames[i][0] == '\0')
+ break;
- printf("%c%s", c, devinfo->devnames[i]);
- c = ',';
+ printf("%c%s", c, devinfo->devnames[i]);
+ c = ',';
+ }
}
- printf("\n");
+ } else if (event->ue_type == USB_EVENT_CTRLR_ATTACH ||
+ event->ue_type == USB_EVENT_CTRLR_DETACH) {
+ printf(" bus=%d", &event->u.ue_ctrlr.ue_bus);
+ } else if (event->ue_type == USB_EVENT_DRIVER_ATTACH ||
+ event->ue_type == USB_EVENT_DRIVER_DETACH) {
+ printf(" cookie=%u devname=%s",
+ &event->u.ue_driver.ue_cookie.cookie,
+ &event->u.ue_driver.ue_devname);
}
+ printf("\n");
}
void
@@ -854,7 +872,15 @@ process_event_queue(int fd)
/* handle the event appropriately */
switch (event.ue_type) {
case USB_EVENT_CTRLR_ATTACH:
+ if (verbose)
+ printf("USB_EVENT_CTRLR_ATTACH\n");
+ break;
case USB_EVENT_CTRLR_DETACH:
+ if (verbose)
+ printf("USB_EVENT_CTRLR_DETACH\n");
+ break;
+ case USB_EVENT_DEVICE_ATTACH:
+ case USB_EVENT_DEVICE_DETACH:
if (find_action(&event.u.ue_device, &action_match) == 0)
/* nothing found */
break;
@@ -873,11 +899,20 @@ process_event_queue(int fd)
__progname, action_match.devname, strerror(errno));
}
- if (event.ue_type == USB_EVENT_CTRLR_ATTACH && action_match.action->attach)
+ if (USB_EVENT_IS_ATTACH(event.ue_type) &&
+ action_match.action->attach)
execute_command(action_match.action->attach);
- if (event.ue_type == USB_EVENT_CTRLR_DETACH && action_match.action->detach)
+ if (USB_EVENT_IS_DETACH(event.ue_type) &&
+ action_match.action->detach)
execute_command(action_match.action->detach);
-
+ break;
+ case USB_EVENT_DRIVER_ATTACH:
+ if (verbose)
+ printf("USB_EVENT_DRIVER_DETACH\n");
+ break;
+ case USB_EVENT_DRIVER_DETACH:
+ if (verbose)
+ printf("USB_EVENT_DRIVER_DETACH\n");
break;
default:
printf("Unknown USB event %d\n", event.ue_type);