Diff for /src/sys/dev/usbmisc/uhid/uhid.c between versions 1.6 and 1.7

version 1.6, 2003/08/07 21:17:14 version 1.7, 2003/12/30 01:01:47
Line 1 Line 1
/*        $NetBSD: uhid.c,v 1.38 2000/04/27 15:26:48 augustss Exp $  *//*
/*        $FreeBSD: src/sys/dev/usb/uhid.c,v 1.27.2.12 2002/11/06 20:23:50 joe Exp $  */ * $NetBSD: uhid.c,v 1.46 2001/11/13 06:24:55 lukem Exp $
/*        $DragonFly$     */ * $FreeBSD: src/sys/dev/usb/uhid.c,v 1.65 2003/11/09 09:17:22 tanimura Exp $
  * $DragonFly$
  */
 
 /* Also already merged from NetBSD:
  *      $NetBSD: uhid.c,v 1.54 2002/09/23 05:51:21 simonb Exp $
  */
   
 /*  /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.   * Copyright (c) 1998 The NetBSD Foundation, Inc.
Line 46 Line 52
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
   #include <sys/lock.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
   #if __FreeBSD_version >= 500000
   #include <sys/mutex.h>
   #endif
 #include <sys/signalvar.h>  #include <sys/signalvar.h>
 #if defined(__NetBSD__) || defined(__OpenBSD__)  #if defined(__NetBSD__) || defined(__OpenBSD__)
 #include <sys/device.h>  #include <sys/device.h>
 #include <sys/ioctl.h>  #include <sys/ioctl.h>
   #include <sys/file.h>
 #elif defined(__FreeBSD__)  #elif defined(__FreeBSD__)
 #include <sys/ioccom.h>  #include <sys/ioccom.h>
 #include <sys/filio.h>  #include <sys/filio.h>
Line 60 Line 71
 #endif  #endif
 #include <sys/conf.h>  #include <sys/conf.h>
 #include <sys/tty.h>  #include <sys/tty.h>
#include <sys/file.h>#if __FreeBSD_version >= 500014
 #include <sys/selinfo.h>
 #else
 #include <sys/select.h>  #include <sys/select.h>
   #endif
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/vnode.h>  #include <sys/vnode.h>
 #include <sys/poll.h>  #include <sys/poll.h>
Line 70 Line 84
 #include <bus/usb/usb.h>  #include <bus/usb/usb.h>
 #include <bus/usb/usbhid.h>  #include <bus/usb/usbhid.h>
   
   #include <bus/usb/usbdevs.h>
 #include <bus/usb/usbdi.h>  #include <bus/usb/usbdi.h>
 #include <bus/usb/usbdi_util.h>  #include <bus/usb/usbdi_util.h>
 #include <bus/usb/hid.h>  #include <bus/usb/hid.h>
   
#if defined(__FreeBSD__) && defined(__i386__)/* Report descriptor for broken Wacom Graphire */
#include <i386/isa/intr_machdep.h>#include <bus/usb/ugraphire_rdesc.h>
#endif 
   
 #ifdef USB_DEBUG  #ifdef USB_DEBUG
 #define DPRINTF(x)      if (uhiddebug) logprintf x  #define DPRINTF(x)      if (uhiddebug) logprintf x
Line 169  Static void uhid_intr(usbd_xfer_handle, Line 183  Static void uhid_intr(usbd_xfer_handle,
 Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int);  Static int uhid_do_read(struct uhid_softc *, struct uio *uio, int);
 Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int);  Static int uhid_do_write(struct uhid_softc *, struct uio *uio, int);
 Static int uhid_do_ioctl(struct uhid_softc *, u_long, caddr_t, int,  Static int uhid_do_ioctl(struct uhid_softc *, u_long, caddr_t, int,
                         usb_proc_ptr);                              usb_proc_ptr);
   
 USB_DECLARE_DRIVER(uhid);  USB_DECLARE_DRIVER(uhid);
   
Line 177  USB_MATCH(uhid) Line 191  USB_MATCH(uhid)
 {  {
         USB_MATCH_START(uhid, uaa);          USB_MATCH_START(uhid, uaa);
         usb_interface_descriptor_t *id;          usb_interface_descriptor_t *id;
        
         if (uaa->iface == NULL)          if (uaa->iface == NULL)
                 return (UMATCH_NONE);                  return (UMATCH_NONE);
         id = usbd_get_interface_descriptor(uaa->iface);          id = usbd_get_interface_descriptor(uaa->iface);
         if (id == NULL || id->bInterfaceClass != UICLASS_HID)          if (id == NULL || id->bInterfaceClass != UICLASS_HID)
                 return (UMATCH_NONE);                  return (UMATCH_NONE);
           if (uaa->matchlvl)
                   return (uaa->matchlvl);
         return (UMATCH_IFACECLASS_GENERIC);          return (UMATCH_IFACECLASS_GENERIC);
 }  }
   
Line 196  USB_ATTACH(uhid) Line 212  USB_ATTACH(uhid)
         void *desc;          void *desc;
         usbd_status err;          usbd_status err;
         char devinfo[1024];          char devinfo[1024];
        
         sc->sc_udev = uaa->device;          sc->sc_udev = uaa->device;
         sc->sc_iface = iface;          sc->sc_iface = iface;
         id = usbd_get_interface_descriptor(iface);          id = usbd_get_interface_descriptor(iface);
Line 216  USB_ATTACH(uhid) Line 232  USB_ATTACH(uhid)
         DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "          DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "
                      "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"                       "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
                      " bInterval=%d\n",                       " bInterval=%d\n",
                     ed->bLength, ed->bDescriptorType,                      ed->bLength, ed->bDescriptorType,
                      ed->bEndpointAddress & UE_ADDR,                       ed->bEndpointAddress & UE_ADDR,
                      UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",                       UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
                      ed->bmAttributes & UE_XFERTYPE,                       ed->bmAttributes & UE_XFERTYPE,
Line 231  USB_ATTACH(uhid) Line 247  USB_ATTACH(uhid)
   
         sc->sc_ep_addr = ed->bEndpointAddress;          sc->sc_ep_addr = ed->bEndpointAddress;
   
        desc = 0;        if (uaa->vendor == USB_VENDOR_WACOM &&
        err = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USBDEV);            uaa->product == USB_PRODUCT_WACOM_GRAPHIRE /* &&
             uaa->revision == 0x???? */) { /* XXX should use revision */
                 /* The report descriptor for the Wacom Graphire is broken. */
                 size = sizeof uhid_graphire_report_descr;
                 desc = malloc(size, M_USBDEV, M_NOWAIT);
                 if (desc == NULL)
                         err = USBD_NOMEM;
                 else {
                         err = USBD_NORMAL_COMPLETION;
                         memcpy(desc, uhid_graphire_report_descr, size);
                 }
         } else {
                 desc = NULL;
                 err = usbd_read_report_desc(uaa->iface, &desc, &size,M_USBDEV);
         }
 
         if (err) {          if (err) {
                 printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));                  printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
                 sc->sc_dying = 1;                  sc->sc_dying = 1;
                 USB_ATTACH_ERROR_RETURN;                  USB_ATTACH_ERROR_RETURN;
         }          }
        
         (void)usbd_set_idle(iface, 0, 0);          (void)usbd_set_idle(iface, 0, 0);
   
         sc->sc_isize = hid_report_size(desc, size, hid_input,   &sc->sc_iid);          sc->sc_isize = hid_report_size(desc, size, hid_input,   &sc->sc_iid);
Line 266  uhid_activate(device_ptr_t self, enum de Line 297  uhid_activate(device_ptr_t self, enum de
         switch (act) {          switch (act) {
         case DVACT_ACTIVATE:          case DVACT_ACTIVATE:
                 return (EOPNOTSUPP);                  return (EOPNOTSUPP);
                 break;  
   
         case DVACT_DEACTIVATE:          case DVACT_DEACTIVATE:
                 sc->sc_dying = 1;                  sc->sc_dying = 1;
Line 282  USB_DETACH(uhid) Line 312  USB_DETACH(uhid)
         int s;          int s;
 #if defined(__NetBSD__) || defined(__OpenBSD__)  #if defined(__NetBSD__) || defined(__OpenBSD__)
         int maj, mn;          int maj, mn;
 #elif defined(__FreeBSD__)  
         struct vnode *vp;  
 #endif  #endif
   
 #if defined(__NetBSD__) || defined(__OpenBSD__)  #if defined(__NetBSD__) || defined(__OpenBSD__)
Line 317  USB_DETACH(uhid) Line 345  USB_DETACH(uhid)
         mn = self->dv_unit;          mn = self->dv_unit;
         vdevgone(maj, mn, mn, VCHR);          vdevgone(maj, mn, mn, VCHR);
 #elif defined(__FreeBSD__)  #elif defined(__FreeBSD__)
         vp = SLIST_FIRST(&sc->dev->si_hlist);  
         if (vp)  
                 VOP_REVOKE(vp, REVOKEALL);  
   
         destroy_dev(sc->dev);          destroy_dev(sc->dev);
 #endif  #endif
   
        free(sc->sc_repdesc, M_USBDEV);        if (sc->sc_repdesc)
                 free(sc->sc_repdesc, M_USBDEV);
   
         return (0);          return (0);
 }  }
Line 337  uhid_intr(usbd_xfer_handle xfer, usbd_pr Line 362  uhid_intr(usbd_xfer_handle xfer, usbd_pr
 #ifdef USB_DEBUG  #ifdef USB_DEBUG
         if (uhiddebug > 5) {          if (uhiddebug > 5) {
                 u_int32_t cc, i;                  u_int32_t cc, i;
                
                 usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);                  usbd_get_xfer_status(xfer, NULL, NULL, &cc, NULL);
                 DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc));                  DPRINTF(("uhid_intr: status=%d cc=%d\n", status, cc));
                 DPRINTF(("uhid_intr: data ="));                  DPRINTF(("uhid_intr: data ="));
Line 352  uhid_intr(usbd_xfer_handle xfer, usbd_pr Line 377  uhid_intr(usbd_xfer_handle xfer, usbd_pr
   
         if (status != USBD_NORMAL_COMPLETION) {          if (status != USBD_NORMAL_COMPLETION) {
                 DPRINTF(("uhid_intr: status=%d\n", status));                  DPRINTF(("uhid_intr: status=%d\n", status));
                sc->sc_state |= UHID_NEEDCLEAR;                if (status == USBD_STALLED)
                     sc->sc_state |= UHID_NEEDCLEAR;
                 return;                  return;
         }          }
   
         (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q);          (void) b_to_q(sc->sc_ibuf, sc->sc_isize, &sc->sc_q);
                
         if (sc->sc_state & UHID_ASLP) {          if (sc->sc_state & UHID_ASLP) {
                 sc->sc_state &= ~UHID_ASLP;                  sc->sc_state &= ~UHID_ASLP;
                DPRINTFN(5, ("uhid_intr: waking %p\n", sc));                DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
                 wakeup(&sc->sc_q);                  wakeup(&sc->sc_q);
         }          }
        selwakeup(&sc->sc_rsel);        selwakeuppri(&sc->sc_rsel, PZERO);
         if (sc->sc_async != NULL) {          if (sc->sc_async != NULL) {
                 DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));                  DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));
                   PROC_LOCK(sc->sc_async);
                 psignal(sc->sc_async, SIGIO);                  psignal(sc->sc_async, SIGIO);
                   PROC_UNLOCK(sc->sc_async);
         }          }
 }  }
   
Line 375  uhidopen(dev_t dev, int flag, int mode, Line 403  uhidopen(dev_t dev, int flag, int mode,
 {  {
         struct uhid_softc *sc;          struct uhid_softc *sc;
         usbd_status err;          usbd_status err;
 #if defined(__FreeBSD__) && defined(__i386__)  
         static int hid_opened;  
   
         if (hid_opened == 0) {  
                 int s;  
                 s = splhigh();  
                 tty_imask |= bio_imask;  
                 update_intr_masks();  
                 splx(s);  
                 hid_opened = 1;  
         }  
 #endif  
   
         USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);          USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
   
Line 408  uhidopen(dev_t dev, int flag, int mode, Line 424  uhidopen(dev_t dev, int flag, int mode,
         sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);          sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
   
         /* Set up interrupt pipe. */          /* Set up interrupt pipe. */
        err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,         err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
                  USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,                   USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
                   sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);                    sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);
         if (err) {          if (err) {
                 DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "                  DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
                          "error=%d\n",err));                           "error=%d\n",err));
                 free(sc->sc_ibuf, M_USBDEV);                  free(sc->sc_ibuf, M_USBDEV);
                 free(sc->sc_obuf, M_USBDEV);                  free(sc->sc_obuf, M_USBDEV);
                   sc->sc_ibuf = sc->sc_obuf = NULL;
   
                 sc->sc_state &= ~UHID_OPEN;                  sc->sc_state &= ~UHID_OPEN;
                 return (EIO);                  return (EIO);
         }          }
Line 446  uhidclose(dev_t dev, int flag, int mode, Line 464  uhidclose(dev_t dev, int flag, int mode,
   
         free(sc->sc_ibuf, M_USBDEV);          free(sc->sc_ibuf, M_USBDEV);
         free(sc->sc_obuf, M_USBDEV);          free(sc->sc_obuf, M_USBDEV);
           sc->sc_ibuf = sc->sc_obuf = NULL;
   
         sc->sc_state &= ~UHID_OPEN;          sc->sc_state &= ~UHID_OPEN;
   
Line 466  uhid_do_read(struct uhid_softc *sc, stru Line 485  uhid_do_read(struct uhid_softc *sc, stru
         DPRINTFN(1, ("uhidread\n"));          DPRINTFN(1, ("uhidread\n"));
         if (sc->sc_state & UHID_IMMED) {          if (sc->sc_state & UHID_IMMED) {
                 DPRINTFN(1, ("uhidread immed\n"));                  DPRINTFN(1, ("uhidread immed\n"));
                
                 err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,                  err = usbd_get_report(sc->sc_iface, UHID_INPUT_REPORT,
                           sc->sc_iid, buffer, sc->sc_isize);                            sc->sc_iid, buffer, sc->sc_isize);
                 if (err)                  if (err)
Line 481  uhid_do_read(struct uhid_softc *sc, stru Line 500  uhid_do_read(struct uhid_softc *sc, stru
                         return (EWOULDBLOCK);                          return (EWOULDBLOCK);
                 }                  }
                 sc->sc_state |= UHID_ASLP;                  sc->sc_state |= UHID_ASLP;
                DPRINTFN(5, ("uhidread: sleep on %p\n", sc));                DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
                 error = tsleep(&sc->sc_q, PCATCH, "uhidrea", 0);                  error = tsleep(&sc->sc_q, PCATCH, "uhidrea", 0);
                 DPRINTFN(5, ("uhidread: woke, error=%d\n", error));                  DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
                 if (sc->sc_dying)                  if (sc->sc_dying)
Line 539  uhid_do_write(struct uhid_softc *sc, str Line 558  uhid_do_write(struct uhid_softc *sc, str
         usbd_status err;          usbd_status err;
   
         DPRINTFN(1, ("uhidwrite\n"));          DPRINTFN(1, ("uhidwrite\n"));
        
         if (sc->sc_dying)          if (sc->sc_dying)
                 return (EIO);                  return (EIO);
   
Line 600  uhid_do_ioctl(struct uhid_softc *sc, u_l Line 619  uhid_do_ioctl(struct uhid_softc *sc, u_l
                 if (*(int *)addr) {                  if (*(int *)addr) {
                         if (sc->sc_async != NULL)                          if (sc->sc_async != NULL)
                                 return (EBUSY);                                  return (EBUSY);
   #if defined(__DragonFly__)
                           sc->sc_async = p->td_proc;
   #elif __FreeBSD_version >= 500000
                         sc->sc_async = p->td_proc;                          sc->sc_async = p->td_proc;
                        DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p));#else
                         sc->sc_async = p;
 #endif
                         DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", sc->sc_async));
                 } else                  } else
                         sc->sc_async = NULL;                          sc->sc_async = NULL;
                 break;                  break;
Line 682  uhid_do_ioctl(struct uhid_softc *sc, u_l Line 707  uhid_do_ioctl(struct uhid_softc *sc, u_l
                         return (EIO);                          return (EIO);
                 break;                  break;
   
           case USB_GET_REPORT_ID:
                   *(int *)addr = 0;       /* XXX: we only support reportid 0? */
                   break;
   
         default:          default:
                 return (EINVAL);                  return (EINVAL);
         }          }

Removed from v.1.6  
changed lines
  Added in v.1.7