PERFORCE change 120885 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Mon Jun 4 07:17:21 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=120885
Change 120885 by hselasky at hselasky_mini_itx on 2007/06/04 07:16:51
This is the start of a completely new /dev/usbX backend
that can be used to access any USB device on the USB bus.
"/dev/usbX" now uses the "usb_cdev" system that makes it
detach safe among other things. Remove support for "usbd",
"/dev/usb" hence this utility has been replaced by "devd".
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb.c#13 edit
.. //depot/projects/usb/src/sys/dev/usb/usb.h#10 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_requests.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#37 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb.c#13 (text+ko) ====
@@ -50,11 +50,8 @@
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/uio.h> /* UIO_XXX */
#include <sys/proc.h>
#include <sys/unistd.h>
-#include <sys/filio.h> /* FXXX */
-#include <sys/ioccom.h> /* IOR()/IOW()/IORW() */
#include <sys/kthread.h>
#include <sys/poll.h>
#include <sys/signalvar.h>
@@ -63,13 +60,7 @@
#include <dev/usb/usb_port.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_subr.h>
-#include <dev/usb/usb_quirks.h>
-
-#define DEV2UNIT(d) (minor(d))
-#define DEV2BUS(d) (*((struct usbd_bus **)&((d)->si_drv1)))
-#define USB_DEV_MINOR 255 /* event queue device */
-
MALLOC_DEFINE(M_USB, "USB", "USB");
MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
@@ -83,58 +74,82 @@
int usbdebug = 0;
SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
&usbdebug, 0, "usb debug level");
+#endif
-/*
- * 0 - do usual exploration
- * 1 - do not use timeout exploration
- * >1 - do no exploration
- */
-int usb_noexplore = 0;
+#if ((__FreeBSD_version >= 700001) || (__FreeBSD_version == 0) || \
+ ((__FreeBSD_version >= 600034) && (__FreeBSD_version < 700000)))
+#define USB_UCRED struct ucred *ucred,
+#else
+#define USB_UCRED
#endif
-#define USB_MAX_EVENTS 100
-struct usb_event_wrapper
-{
- struct usb_event ue;
- TAILQ_ENTRY(usb_event_wrapper) next;
-};
+uint8_t usb_driver_added_refcount;
-static TAILQ_HEAD(, usb_event_wrapper) usb_events =
- TAILQ_HEAD_INITIALIZER(usb_events);
+static uint8_t usb_post_init_called = 0;
-#ifndef usb_global_lock
-struct mtx usb_global_lock;
-#endif
-
static device_probe_t usb_probe;
static device_attach_t usb_attach;
static device_detach_t usb_detach;
-/* these variables are protected by "usb_global_lock" */
-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 int usb_dummy_open(struct cdev *dev, int oflags, int devtype, struct thread *td);
+static void usb_discover(struct usbd_bus *bus);
+static void usb_event_thread(struct usbd_bus *bus);
+static void usb_create_event_thread(struct usbd_bus *bus);
+static void __usb_attach(device_t dev, struct usbd_bus *bus);
+static void usb_post_init(void *arg);
+static struct usbd_clone *usb_clone_sub(struct usbd_bus *bus);
+static void usb_clone_remove(struct usbd_bus *bus);
+static void usb_clone(void *arg, USB_UCRED char *name, int namelen, struct cdev **dev);
+static int usb_ioctl(struct usb_cdev *dev, u_long cmd, caddr_t addr, int32_t fflags, struct thread *td);
+static void usb_init(void *arg);
+static void usb_uninit(void *arg);
+
+static devclass_t usb_devclass;
+static driver_t usb_driver =
+{
+ .name = "usb",
+ .methods = (device_method_t [])
+ {
+ DEVMETHOD(device_probe, usb_probe),
+ DEVMETHOD(device_attach, usb_attach),
+ DEVMETHOD(device_detach, usb_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ {0,0}
+ },
+ .size = 0, /* the softc must be set by the attacher! */
+};
+
+DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, 0, 0);
+
+MODULE_DEPEND(usb, usb, 1, 1, 1);
+MODULE_VERSION(usb, 1);
+
+static cdevsw_t usb_dummy_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = usb_dummy_open,
+ .d_name = "usb_dummy_cdev",
+};
-/**/
-static const char * const usbrev_str[] = USBREV_STR;
+static int
+usb_dummy_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ return ENODEV;
+}
-/*
- * usb_discover - explore the device tree from the root
- *
- * usb_discover device nodes, kthread
- */
+/*------------------------------------------------------------------------*
+ * usb_discover - explore the device tree from the root
+ *------------------------------------------------------------------------*/
static void
usb_discover(struct usbd_bus *bus)
{
+ int32_t error;
+
PRINTFN(2,("\n"));
-#ifdef USB_DEBUG
- if(usb_noexplore > 1)
- {
- return;
- }
-#endif
mtx_assert(&usb_global_lock, MA_OWNED);
/* check that only one thread is exploring
@@ -144,8 +159,8 @@
{
bus->wait_explore = 1;
- mtx_sleep(&bus->wait_explore, &usb_global_lock, PWAIT,
- "usb wait explore", 0);
+ error = mtx_sleep(&bus->wait_explore, &usb_global_lock, 0,
+ "usb wait explore", 0);
}
bus->is_exploring = 1;
@@ -179,6 +194,8 @@
static void
usb_event_thread(struct usbd_bus *bus)
{
+ int32_t error;
+
mtx_lock(&usb_global_lock);
while(1)
@@ -188,20 +205,11 @@
break;
}
-#ifdef USB_DEBUG
- if(usb_noexplore < 2)
-#endif
- {
- usb_discover(bus);
- }
+ usb_discover(bus);
+
+ error = mtx_sleep(&bus->needs_explore, &usb_global_lock,
+ 0, "usbevt", hz * 60);
-#ifdef USB_DEBUG
- mtx_sleep(&bus->needs_explore, &usb_global_lock, PWAIT,
- "usbevt", usb_noexplore ? 0 : hz * 60);
-#else
- mtx_sleep(&bus->needs_explore, &usb_global_lock, PWAIT,
- "usbevt", hz * 60);
-#endif
PRINTFN(2,("woke up\n"));
}
@@ -231,8 +239,6 @@
return;
}
-u_int8_t usb_driver_added_refcount;
-
void
usb_needs_probe_and_attach(void)
{
@@ -286,128 +292,8 @@
return;
}
-static int
-usb_event_get_next(struct usb_event *ue)
-{
- struct usb_event_wrapper *uew;
- int err;
-
- mtx_lock(&usb_global_lock);
-
- uew = TAILQ_FIRST(&usb_events);
-
- if(uew == NULL)
- {
- usb_nevents = 0;
- err = 0;
- }
- else
- {
- *ue = uew->ue;
-
- TAILQ_REMOVE(&usb_events, uew, next);
-
- free(uew, M_USBDEV);
-
- if(usb_nevents)
- {
- usb_nevents--;
- }
- err = 1;
- }
- mtx_unlock(&usb_global_lock);
- return (err);
-}
-
-static void
-usb_event_add(int type, struct usb_event *uep)
-{
- struct usb_event_wrapper *uew;
- struct timeval thetime;
+/* called from "{ehci,ohci,uhci}_pci_attach()" */
- uew = malloc(sizeof *uew, M_USBDEV, M_WAITOK|M_ZERO);
- if(uew == NULL)
- {
- return;
- }
- uew->ue = *uep;
- uew->ue.ue_type = type;
- microtime(&thetime);
- TIMEVAL_TO_TIMESPEC(&thetime, &uew->ue.ue_time);
-
- mtx_lock(&usb_global_lock);
-
- if(USB_EVENT_IS_DETACH(type))
- {
- struct usb_event_wrapper *uewi, *uewi_next;
-
- for (uewi = TAILQ_FIRST(&usb_events);
- uewi;
- uewi = uewi_next)
- {
- uewi_next = TAILQ_NEXT(uewi, next);
- if(uewi->ue.u.ue_driver.ue_cookie.cookie ==
- uep->u.ue_device.udi_cookie.cookie)
- {
- TAILQ_REMOVE(&usb_events, uewi, next);
- free(uewi, M_USBDEV);
- usb_nevents--;
- uewi_next = TAILQ_FIRST(&usb_events);
- }
- }
- }
- if(usb_nevents >= USB_MAX_EVENTS)
- {
- /* too many queued events, drop an old one */
- PRINTF(("event dropped\n"));
-
- struct usb_event ue;
- (void)usb_event_get_next(&ue);
- }
- TAILQ_INSERT_TAIL(&usb_events, uew, next);
- usb_nevents++;
- wakeup(&usb_events);
- selwakeuppri(&usb_selevent, PZERO);
- if(usb_async_proc != NULL)
- {
- PROC_LOCK(usb_async_proc);
- psignal(usb_async_proc, SIGIO);
- PROC_UNLOCK(usb_async_proc);
- }
-
- mtx_unlock(&usb_global_lock);
- return;
-}
-
-void
-usbd_add_dev_event(int type, struct usbd_device *udev)
-{
- struct usb_event ue;
-
- bzero(&ue, sizeof(ue));
-
- usbd_fill_deviceinfo(udev, &ue.u.ue_device,
- USB_EVENT_IS_ATTACH(type));
- usb_event_add(type, &ue);
- return;
-}
-
-void
-usbd_add_drv_event(int type, struct usbd_device *udev, device_t dev)
-{
- struct usb_event ue;
-
- bzero(&ue, sizeof(ue));
-
- ue.u.ue_driver.ue_cookie = udev->cookie;
- strncpy(ue.u.ue_driver.ue_devname, device_get_nameunit(dev),
- sizeof ue.u.ue_driver.ue_devname);
- usb_event_add(type, &ue);
- return;
-}
-
-/* called from uhci_pci_attach */
-
static int
usb_probe(device_t dev)
{
@@ -415,15 +301,12 @@
return (UMATCH_GENERIC);
}
-extern cdevsw_t usb_cdevsw;
-
static void
__usb_attach(device_t dev, struct usbd_bus *bus)
{
+ dev_clone_fn usb_clone_ptr = &usb_clone;
usbd_status err;
u_int8_t speed;
- struct usb_event ue;
- struct cdev *cdev;
PRINTF(("\n"));
@@ -431,36 +314,38 @@
bus->root_port.power = USB_MAX_POWER;
- device_printf(bus->bdev, "USB revision %s",
- usbrev_str[bus->usbrev]);
+ switch (bus->usbrev) {
+ case USBREV_1_0:
+ speed = USB_SPEED_FULL;
+ device_printf(bus->bdev, "12MBps Full Speed USB v1.0\n");
+ break;
- switch (bus->usbrev)
- {
- case USBREV_1_0:
case USBREV_1_1:
speed = USB_SPEED_FULL;
+ device_printf(bus->bdev, "12MBps Full Speed USB v1.1\n");
break;
case USBREV_2_0:
speed = USB_SPEED_HIGH;
+ device_printf(bus->bdev, "480MBps High Speed USB v2.0\n");
+ break;
+
+ case USBREV_2_5:
+ speed = USB_SPEED_VARIABLE;
+ device_printf(bus->bdev, "Wireless USB v2.5\n");
break;
default:
- printf(", not supported\n");
+ device_printf(bus->bdev, "Unsupported USB revision!\n");
return;
}
- printf("\n");
-
/* make sure not to use tsleep() if we are cold booting */
if(cold)
{
bus->use_polling++;
}
- ue.u.ue_ctrlr.ue_bus = device_get_unit(bus->bdev);
- usb_event_add(USB_EVENT_CTRLR_ATTACH, &ue);
-
err = usbd_new_device(bus->bdev, bus, 0, speed, 0,
&bus->root_port);
if(!err)
@@ -495,20 +380,24 @@
usb_create_event_thread(bus);
- /* the per controller devices (used for usb_discover) */
- /* XXX This is redundant now, but old usbd's will want it */
- cdev = make_dev(&usb_cdevsw, device_get_unit(dev), UID_ROOT, GID_OPERATOR,
- 0660, "usb%d", device_get_unit(dev));
+ snprintf(bus->usb_name, sizeof(bus->usb_name), "usb%u", device_get_unit(dev));
+
+ bus->usb_clone_tag = EVENTHANDLER_REGISTER(dev_clone, usb_clone_ptr, bus, 1000);
+ if (bus->usb_clone_tag == NULL) {
+ device_printf(dev, "Registering clone handler failed!\n");
+ }
+
+ /* create a dummy device so that we are visible */
+ bus->usb_cdev =
+ make_dev(&usb_dummy_cdevsw, device_get_unit(dev),
+ UID_ROOT, GID_OPERATOR, 0660, "%s ", bus->usb_name);
- if(cdev)
- {
- DEV2BUS(cdev) = bus;
+ if (bus->usb_cdev == NULL) {
+ device_printf(dev, "Creating dummy device failed!\n");
}
return;
}
-static u_int8_t usb_post_init_called = 0;
-
static int
usb_attach(device_t dev)
{
@@ -572,7 +461,7 @@
usb_detach(device_t dev)
{
struct usbd_bus *bus = device_get_softc(dev);
- struct usb_event ue;
+ int32_t error;
PRINTF(("start\n"));
@@ -583,8 +472,8 @@
{
bus->wait_explore = 1;
- mtx_sleep(&bus->wait_explore, &usb_global_lock, PWAIT,
- "usb wait explore", 0);
+ mtx_sleep(&bus->wait_explore, &usb_global_lock, 0,
+ "usb wait explore", 0);
}
/* detach children first */
@@ -604,19 +493,13 @@
{
wakeup(&bus->needs_explore);
- if(mtx_sleep(bus, &usb_global_lock, PWAIT, "usbdet", hz * 60))
- {
- device_printf(bus->bdev,
- "event thread didn't die\n");
- }
+ error = mtx_sleep(bus, &usb_global_lock, 0, "usbdet", 0);
+
PRINTF(("event thread dead\n"));
}
mtx_unlock(&usb_global_lock);
- ue.u.ue_ctrlr.ue_bus = device_get_unit(bus->bdev);
- usb_event_add(USB_EVENT_CTRLR_DETACH, &ue);
-
mtx_lock(&bus->mtx);
if(bus->bdev == dev)
{
@@ -632,351 +515,345 @@
device_printf(dev, "unexpected bus->bdev value!\n");
}
mtx_unlock(&bus->mtx);
+
+ if (bus->usb_cdev) {
+ destroy_dev(bus->usb_cdev);
+ bus->usb_cdev = NULL;
+ }
+
+ if (bus->usb_clone_tag) {
+ EVENTHANDLER_DEREGISTER(dev_clone, bus->usb_clone_tag);
+ bus->usb_clone_tag = NULL;
+ }
+
+ usb_clone_remove(bus);
+
return (0);
}
-static int
-usbopen(struct cdev *dev, int flag, int mode, struct thread *proc)
+static struct usbd_clone *
+usb_clone_sub(struct usbd_bus *bus)
{
- int error = 0;
+ struct usbd_clone *sub;
+ int32_t error;
+ const char *p_name[2];
+ char n_name[64];
+
+ mtx_lock(&(bus->mtx));
+ sub = bus->usb_clone_root;
+ mtx_unlock(&(bus->mtx));
+
+ while (sub) {
+ if (!usb_cdev_opened(&(sub->cdev))) {
+ return sub;
+ }
+ sub = sub->next;
+ }
+
+ sub = malloc(sizeof(*sub), M_USBDEV, M_ZERO|M_WAITOK);
+ if (sub == NULL) {
+ return NULL;
+ }
- mtx_lock(&usb_global_lock);
+ mtx_lock(&(bus->mtx));
+ sub->unit = bus->usb_clone_count;
+ if (bus->usb_clone_count < USB_BUS_MAX_CLONES) {
+ bus->usb_clone_count ++;
+ }
+ mtx_unlock(&(bus->mtx));
- if(DEV2UNIT(dev) == USB_DEV_MINOR)
- {
- if(usb_dev_open)
- {
- error = EBUSY;
- goto done;
- }
- usb_dev_open = 1;
- usb_async_proc = 0;
+ if (sub->unit >= USB_BUS_MAX_CLONES) {
+ /* limit reached */
+ goto error;
}
- else
- {
- struct usbd_bus *bus = DEV2BUS(dev);
+
+ snprintf(n_name, sizeof(n_name), "%s.%02x", bus->usb_name, sub->unit);
+
+ mtx_init(&(sub->mtx), "usb_clone", NULL, MTX_DEF|MTX_RECURSE);
+
+ p_name[0] = n_name;
+ p_name[1] = NULL;
+
+ sub->cdev.sc_ioctl = &usb_ioctl;
+ sub->bus = bus;
- if(bus->root_port.device == NULL)
- {
- /* device is beeing detached */
- error = EIO;
- goto done;
- }
+ error = usb_cdev_attach(&(sub->cdev), sub, &(sub->mtx),
+ p_name, UID_ROOT, GID_OPERATOR, 0660,
+ 0, 0, 0, 0);
+ if (error) {
+ goto error;
}
- done:
- mtx_unlock(&usb_global_lock);
- return (error);
+ /* insert sub-device into a one-way linked list */
+
+ mtx_lock(&(bus->mtx));
+ sub->next = bus->usb_clone_root;
+ bus->usb_clone_root = sub;
+ mtx_unlock(&(bus->mtx));
+ return sub;
+
+ error:
+ free(sub, M_USBDEV);
+ return NULL;
}
-static int
-usbread(struct cdev *dev, struct uio *uio, int flag)
+static void
+usb_clone_remove(struct usbd_bus *bus)
{
- struct usb_event ue;
- int error = 0;
+ struct usbd_clone *sub;
+ struct usbd_clone *next;
+ uint8_t done = 0;
- if(DEV2UNIT(dev) != USB_DEV_MINOR)
- {
- return (ENODEV);
- }
+ while (1) {
- if(uio->uio_resid != sizeof(struct usb_event))
- {
- return (EINVAL);
- }
+ /* first prevent any further clones from
+ * being created:
+ */
+ mtx_lock(&(bus->mtx));
+ bus->usb_clone_count = USB_BUS_MAX_CLONES;
+ sub = bus->usb_clone_root;
+ bus->usb_clone_root = NULL;
+ mtx_unlock(&(bus->mtx));
- mtx_lock(&usb_global_lock);
+ /* XXX wait for any leftover VOP_LOOKUP() calls
+ * to finish. Really we should lock some lock
+ * here to lock that problem out! --hps
+ */
+ usb_delay_ms(bus, 500);
- for(;;)
- {
- if(usb_event_get_next(&ue) != 0)
- {
- break;
+ if (sub == NULL) {
+ if (done) {
+ break;
+ } else {
+ done = 1;
}
- if(flag & IO_NDELAY)
- {
- error = EWOULDBLOCK;
- break;
- }
- error = mtx_sleep(&usb_events, &usb_global_lock,
- (PZERO|PCATCH), "usbrea", 0);
- if(error)
- {
- break;
- }
- }
+ } else {
+ done = 0;
+ }
+
+ /* teardown all cloned devices */
+ while (sub) {
+
+ usb_cdev_detach(&(sub->cdev));
+
+ next = sub->next;
+
+ mtx_destroy(&(sub->mtx));
- mtx_unlock(&usb_global_lock);
+ free(sub, M_USBDEV);
- if(!error)
- {
- error = uiomove((void *)&ue, uio->uio_resid, uio);
+ sub = next;
+ }
}
- return (error);
+ return;
}
-static int
-usbclose(struct cdev *dev, int flag, int mode, struct thread *proc)
+static void
+usb_clone(void *arg, USB_UCRED char *name, int namelen, struct cdev **dev)
{
- if(DEV2UNIT(dev) == USB_DEV_MINOR)
- {
- mtx_lock(&usb_global_lock);
+ struct usbd_bus *bus = arg;
+ struct usbd_clone *sub;
+
+ if (*dev) {
+ return;
+ }
- usb_async_proc = 0;
- usb_dev_open = 0;
+ if (strcmp(name, bus->usb_name) != 0) {
+ return;
+ }
- mtx_unlock(&usb_global_lock);
+ sub = usb_clone_sub(bus);
+ if (sub == NULL) {
+ return;
}
- return (0);
+
+ *dev = sub->cdev.sc_cdev[0];
+
+ dev_ref(*dev);
+ return;
}
static int
-usbioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *p)
+usb_ioctl(struct usb_cdev *dev, u_long cmd, caddr_t addr,
+ int32_t fflags, struct thread *td)
{
+ struct usbd_clone *sub = dev->sc_priv_ptr;
+ struct usbd_bus *bus = sub->bus;
+ struct usbd_device *udev = 0;
int error = 0;
- mtx_lock(&usb_global_lock);
+ usb_cdev_unlock(dev, fflags);
- if(DEV2UNIT(dev) == USB_DEV_MINOR)
- {
- switch (cmd)
- {
- case FIONBIO:
- /* all handled in the upper FS layer */
- break;
+ switch (cmd) {
+ /* this part should be deleted */
+ case USB_DISCOVER:
+ break;
- case FIOASYNC:
- if(*(int *)data)
- usb_async_proc = p->td_proc;
- else
- usb_async_proc = 0;
-
- break;
-
- default:
- error = EINVAL;
- break;
- }
- }
- else
+ case USB_REQUEST:
{
- struct usbd_bus *bus = DEV2BUS(dev);
+ struct usb_ctl_request *ur = (void *)addr;
+ uint16_t len = UGETW(ur->ucr_request.wLength);
+ uint8_t isread = (ur->ucr_request.bmRequestType & UT_READ) ? 1 : 0;
+ void *ptr = 0;
- if(bus->root_port.device == NULL)
- {
- /* detached */
- error = EIO;
+ udev = usbd_ref_device(bus, ur->ucr_addr);
+ if (udev == NULL) {
+ error = ENXIO;
goto done;
}
- switch (cmd)
- {
- /* this part should be deleted */
- case USB_DISCOVER:
- break;
- case USB_REQUEST:
- {
- struct usb_ctl_request *ur = (void *)data;
- int len = UGETW(ur->ucr_request.wLength);
- struct iovec iov;
- struct uio uio;
- void *ptr = 0;
- int addr = ur->ucr_addr;
- usbd_status err;
- int error = 0;
+ PRINTF(("USB_REQUEST addr=%d len=%d\n", ur->ucr_addr, len));
- PRINTF(("USB_REQUEST addr=%d len=%d\n", addr, len));
- if((len < 0) ||
- (len > 32768))
- {
- error = EINVAL;
- goto done;
+ if (len != 0) {
+ ptr = malloc(len, M_TEMP, M_WAITOK);
+ if (ptr == NULL) {
+ error = ENOMEM;
+ goto ret001;
}
-
- if((addr < 0) ||
- (addr >= USB_MAX_DEVICES) ||
- (bus->devices[addr] == 0 /* might be checked by usbd_do_request_flags */))
- {
- error = EINVAL;
- goto done;
- }
-
- if(len != 0)
- {
- iov.iov_base = (caddr_t)ur->ucr_data;
- iov.iov_len = len;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_resid = len;
- uio.uio_offset = 0;
- uio.uio_segflg = UIO_USERSPACE;
- uio.uio_rw =
- ur->ucr_request.bmRequestType & UT_READ ?
- UIO_READ : UIO_WRITE;
- uio.uio_procp = p;
- ptr = malloc(len, M_TEMP, M_WAITOK);
- if(uio.uio_rw == UIO_WRITE)
- {
- error = uiomove(ptr, len, &uio);
- if(error)
- {
- goto ret;
- }
- }
- }
- err = usbd_do_request_flags
- (bus->devices[addr], &ur->ucr_request, ptr,
- ur->ucr_flags, &ur->ucr_actlen,
- USBD_DEFAULT_TIMEOUT);
- if(err)
- {
- error = EIO;
- goto ret;
- }
- if(len != 0)
- {
- if(uio.uio_rw == UIO_READ)
- {
- error = uiomove(ptr, len, &uio);
- if(error)
- {
- goto ret;
- }
+ if (isread == 0) {
+ error = copyin(ur->ucr_data, ptr, len);
+ if (error) {
+ goto ret001;
}
}
- ret:
- if(ptr)
- {
- free(ptr, M_TEMP);
- }
- goto done;
}
- case USB_DEVICEINFO:
- {
- struct usb_device_info *di = (void *)data;
- int addr = di->udi_addr;
+ mtx_lock(dev->sc_mtx_ptr);
+ error = usbd_do_request_flags_mtx
+ (udev, dev->sc_mtx_ptr, &ur->ucr_request, ptr, ur->ucr_flags,
+ &ur->ucr_actlen, USBD_DEFAULT_TIMEOUT);
+ mtx_unlock(dev->sc_mtx_ptr);
+
+ if (error) {
+ error = EIO;
+ goto ret001;
+ }
- if((addr < 1) ||
- (addr >= USB_MAX_DEVICES))
- {
- error = EINVAL;
- goto done;
+ if (len != 0) {
+ if (isread) {
+ error = copyout(ptr, ur->ucr_data, len);
+ if (error) {
+ goto ret001;
+ }
}
+ }
+ ret001:
+ if (ptr) {
+ free(ptr, M_TEMP);
+ }
+ usbd_unref_device(udev);
+ goto done;
+ }
- if (bus->devices[addr] == 0)
- {
- error = ENXIO;
- goto done;
- }
+ case USB_DEVICEINFO:
+ {
+ struct usb_device_info *di = (void *)addr;
- error = usbd_fill_deviceinfo(bus->devices[addr], di, 1);
- goto done;
+ udev = usbd_ref_device(bus, di->udi_addr);
+ if (udev == NULL) {
+ error = ENXIO;
+ goto done;
}
- case USB_DEVICESTATS:
- *(struct usb_device_stats *)data = bus->stats;
- break;
+ error = usbd_fill_deviceinfo(udev, di, 1);
- default:
- error = EINVAL;
- break;
- }
+ usbd_unref_device(udev);
+ goto done;
}
- done:
- mtx_unlock(&usb_global_lock);
- return (error);
-}
+ case USB_DEVICESTATS:
+ *(struct usb_device_stats *)addr = bus->stats;
+ break;
-static int
-usbpoll(struct cdev *dev, int events, struct thread *td)
-{
- int revents, mask;
- int unit = DEV2UNIT(dev);
+ case USB_DEVICEENUMERATE:
+ {
+ struct usb_device_enumerate *ude = (void *)addr;
+ struct usbd_port *pp;
+ usb_port_status_t ps;
+ uint8_t old_addr;
+ uint8_t buf[8];
- if(unit == USB_DEV_MINOR)
- {
- revents = 0;
- mask = POLLIN | POLLRDNORM;
+ udev = usbd_ref_device(bus, ude->ude_addr);
+ if (udev == NULL) {
+ error = ENXIO;
+ goto done;
+ }
- mtx_lock(&usb_global_lock);
+ old_addr = udev->address;
+ pp = udev->powersrc;
+ if (pp == NULL) {
+ error = EINVAL;
+ goto ret002;
+ }
- if((events & mask) && (usb_nevents > 0))
- {
- revents |= events & mask;
+ error = usbreq_reset_port(pp->parent, pp->portno, &ps);
+ if (error) {
+ error = ENXIO;
+ goto ret002;
}
- if((revents == 0) && (events & mask))
- {
- selrecord(td, &usb_selevent);
+
+ /* After that the port has been reset
+ * our device should be at address
+ * zero:
+ */
+ udev->address = 0;
+
+ /* It should be allowed to read some descriptors
+ * from address zero:
+ */
+ error = usbreq_get_desc(udev, UDESC_DEVICE, 0, 8, buf, 0);
+ if (error) {
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list