any way to detect usb detached from a device driver ?

Hans Petter Selasky hselasky at c2i.net
Thu Jan 11 08:57:05 UTC 2007


On Thursday 11 January 2007 00:39, Luigi Rizzo wrote:
> On Wed, Jan 10, 2007 at 11:34:54PM +0100, Hans Petter Selasky wrote:
> > Hi Luigi,
> >
> > On Wednesday 10 January 2007 13:46, Luigi Rizzo wrote:
> > > On Tue, Jan 09, 2007 at 09:37:21PM +0100, Hans Petter Selasky wrote:
> > > > On Tuesday 09 January 2007 17:34, Luigi Rizzo wrote:
> >
> > [...]
> >
> > > sorry but i cannot figure out how the above helps in the
> > > detach case e.g. when a process is waiting for an ioctl
> > > or read operation to complete - can you give more details ?
> >
> > "usb_cdev" is an abstraction layer for pluggable devices that wants to
> > create a device under /dev, to read/write some data. It does not help
> > unless you port your PWC driver over to using the "usb_cdev" system,
> > instead of devfs directly.
> >
> > > In my case, i did the following:
> > >
> > >     USB_DETACH(pwc)
> > >     {
> > >         USB_DETACH_START(pwc, sc);
> > >     again:
> > >         if(sc->sc_videopipe != NULL) {
> > >                 usbd_abort_pipe(sc->sc_videopipe);
> > >                 usbd_close_pipe(sc->sc_videopipe);
> > >                 sc->sc_videopipe = NULL;
> > >         }
> > >         sc->error_status = EPIPE;
> > >         if(sc->vopen) {
> > >                 if(sc->state & PWC_ASLEEP)
> > >                         wakeup(sc);
> > >                 if(sc->state & PWC_POLL) {
> > >                         sc->state &= ~PWC_POLL;
> > >                         selwakeuppri(&sc->rsel,PZERO);
> > >                 }
> > >                 device_printf(sc->sc_dev, "Disconnected while webcam is
> > > in use!\n"); usb_detach_wait(USBDEV(sc->sc_dev));
> > >                 goto again;
> > >         }
> > >
> > >         if(sc->sc_dev_t != NULL)
> > >                 destroy_dev(sc->sc_dev_t);
> > >
> > >         mtx_destroy(&sc->ptrlock);
> > >         pwc_free_buffers(sc,1);
> > >
> > > usbd_add_drv_event(USB_EVENT_DRIVER_DETACH,sc->udev,USBDEV(sc->sc_dev))
> > >; return 0;
> > >     }
> > >
> > > and at the end of the close routine
> > >
> > >  ...
> > >         sc->vopen = 0;
> > >         usb_detach_wakeup(USBDEV(sc->sc_dev));
> > >     }
> > >
> > > so the USB_DETACH() will wake up any process blocked,
> > > the sc->error_status = EPIPE; should force an error and
> > > cause the process to call close().
> > >
> > > The down side is that you are still in the hands
> > > of the process to let the detach complete. Ideally one
> > > would just flag the descriptor as 'detach_pending'
> > > and get rid of it at the end of the close(), while the
> > > DETACH() could terminate without doing the free()
> >
> > What I do is to ensure that no thread is executing in any of the devfs
> > callbacks. This might imply some waiting. Then I simply destroy the
> > device using destroy_dev(). This way you don't have to wait for the
> > userland process to call close(), which might not happen right away.
>
> ok... so if i understand well, once all processes have exited
> the callbacks you destroy, which means that afterwards they will
> not be able to invoke the callbacks anymore (nor crash the machine)
> even if they retain a handle ?

Yes, devfs will overwrite the callbacks with dummy ones when the device is 
destroyed so that they are not called back any more. Hence devfs uses 
refcounts, the devfs structure itself will not dissappear immediately if a 
device is using it. The devfs structure will be freed when then refcount 
reaches zero.

--HPS


More information about the freebsd-usb mailing list