Merge from NetBSD.

uhub.c:     revision 1.37
    usb.4:      revision 1.30
    usb.c:      revision 1.38
    usb.h:      revision 1.40
    usb_port.h: revision 1.21
    usb_subr.c: revision 1.65
    usbdi.h:    revision 1.40

Split the attach/detach events up into device, driver and controller
attach and detach events.

The commit message from NetBSD was:
        date: 2000/02/02 07:34:00;  author: augustss;  state: Exp;
        Change the USB event mechanism to include more information
        about devices and drivers.  Partly from FreeBSD.

Also rework usbd to take these new event types into account.
This commit is contained in:
Josef Karthauser 2002-01-28 01:03:19 +00:00
parent a31999ca51
commit a07e9d4af3
8 changed files with 179 additions and 43 deletions

View File

@ -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 ,

View File

@ -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;

View File

@ -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__)

View File

@ -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 {

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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("%c%s", c, devinfo->devnames[i]);
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("\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);