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:
parent
a31999ca51
commit
a07e9d4af3
@ -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 ,
|
||||
|
@ -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;
|
||||
|
@ -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__)
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user