diff options
author | n_hibma <n_hibma@FreeBSD.org> | 1999-06-13 20:49:12 +0000 |
---|---|---|
committer | n_hibma <n_hibma@FreeBSD.org> | 1999-06-13 20:49:12 +0000 |
commit | ad6621b237627767b1be38fa484f011b95c9a5cd (patch) | |
tree | afa303a3fb42a9c7da6b4add7fa7a7a135825f4f /sys/dev/usb | |
parent | 05f6a4b862edd1b95e87b9206fccc6108b2940ea (diff) | |
download | FreeBSD-src-ad6621b237627767b1be38fa484f011b95c9a5cd.zip FreeBSD-src-ad6621b237627767b1be38fa484f011b95c9a5cd.tar.gz |
1) Add non-blocking I/O on read
2) Add checks to make sure we do not dereference the softc when not found
because the device has been removed.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/ums.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c index a97adb4..c8ec14e 100644 --- a/sys/dev/usb/ums.c +++ b/sys/dev/usb/ums.c @@ -397,6 +397,7 @@ ums_detach(device_t self) * the time the process gets a chance to notice. *_close and friends * should be fixed to handle this case. * Or we should do a delayed detach for this. + * Does this delay now force tsleep to exit with an error? */ #if 0 @@ -627,7 +628,7 @@ ums_close(dev_t dev, int flag, int fmt, struct proc *p) { USB_GET_SC(ums, UMSUNIT(dev), sc); - if (sc == NULL) + if (!sc) return 0; if (sc->sc_enabled) @@ -646,14 +647,18 @@ ums_read(dev_t dev, struct uio *uio, int flag) int error; s = splusb(); + if (!sc) { + splx(s); + return EIO; + } + while (sc->qcount == 0 ) { - /* NWH XXX non blocking I/O ?? - if (non blocking I/O ) { + if (flag & IO_NDELAY) { /* non-blocking I/O */ splx(s); return EWOULDBLOCK; - } else { - */ - sc->state |= UMS_ASLEEP; + } + + sc->state |= UMS_ASLEEP; /* blocking I/O */ error = tsleep(sc, PZERO | PCATCH, "umsrea", 0); if (error) { splx(s); @@ -662,8 +667,23 @@ ums_read(dev_t dev, struct uio *uio, int flag) splx(s); return EINTR; } +#if defined(__FreeBSD__) + /* check whether the device is still there */ + + sc = devclass_get_softc(ums_devclass, UMSUNIT(dev)); + if (!sc) { + splx(s); + return EIO; + } +#endif } + /* + * XXX we could optimise the use of splx/splusb somewhat. The writer + * process only extends qcount and qtail. We could copy them and use the copies + * to do the copying out of the queue. + */ + while ((sc->qcount > 0) && (uio->uio_resid > 0)) { l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid); if (l > sizeof(buf)) @@ -694,6 +714,9 @@ ums_poll(dev_t dev, int events, struct proc *p) int revents = 0; int s; + if (!sc) + return 0; + s = splusb(); if (events & (POLLIN | POLLRDNORM)) { if (sc->qcount) { @@ -716,6 +739,9 @@ ums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) int s; mousemode_t mode; + if (!sc) + return EIO; + switch(cmd) { case MOUSE_GETHWINFO: *(mousehw_t *)addr = sc->hw; |