[BACK]Return to uhidev.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/usb/uhidev.c between version 1.14.2.7 and 1.15

version 1.14.2.7, 2005/12/11 10:29:06 version 1.15, 2003/07/14 15:47:29
Line 67  __KERNEL_RCSID(0, "$NetBSD$");
Line 67  __KERNEL_RCSID(0, "$NetBSD$");
 /* Report descriptor for broken Wacom Graphire */  /* Report descriptor for broken Wacom Graphire */
 #include <dev/usb/ugraphire_rdesc.h>  #include <dev/usb/ugraphire_rdesc.h>
   
 #include "locators.h"  
   
 #ifdef UHIDEV_DEBUG  #ifdef UHIDEV_DEBUG
 #define DPRINTF(x)      if (uhidevdebug) logprintf x  #define DPRINTF(x)      if (uhidevdebug) logprintf x
 #define DPRINTFN(n,x)   if (uhidevdebug>(n)) logprintf x  #define DPRINTFN(n,x)   if (uhidevdebug>(n)) logprintf x
Line 80  int uhidevdebug = 0;
Line 78  int uhidevdebug = 0;
   
 Static void uhidev_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);  Static void uhidev_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
   
 Static int uhidev_maxrepid(void *, int);  Static int uhidev_maxrepid(void *buf, int len);
 Static int uhidevprint(void *, const char *);  Static int uhidevprint(void *aux, const char *pnp);
 Static int uhidevsubmatch(struct device *, struct cfdata *,  Static int uhidevsubmatch(struct device *parent, struct cfdata *cf, void *aux);
                           const int *, void *);  
   
 USB_DECLARE_DRIVER(uhidev);  USB_DECLARE_DRIVER(uhidev);
   
Line 97  USB_MATCH(uhidev)
Line 94  USB_MATCH(uhidev)
         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 110  USB_ATTACH(uhidev)
Line 109  USB_ATTACH(uhidev)
         struct uhidev *dev;          struct uhidev *dev;
         int size, nrepid, repid, repsz;          int size, nrepid, repid, repsz;
         int repsizes[256];          int repsizes[256];
         int i;  
         void *desc;          void *desc;
         const void *descptr;  
         usbd_status err;          usbd_status err;
         char *devinfop;          char devinfo[1024];
         int locs[UHIDBUSCF_NLOCS];  
   
         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);
           usbd_devinfo(uaa->device, 0, devinfo);
         devinfop = usbd_devinfo_alloc(uaa->device, 0);  
         USB_ATTACH_SETUP;          USB_ATTACH_SETUP;
         printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),          printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
                devinfop, id->bInterfaceClass, id->bInterfaceSubClass);                 devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
         usbd_devinfo_free(devinfop);  
   
         (void)usbd_set_idle(iface, 0, 0);          (void)usbd_set_idle(iface, 0, 0);
 #if 0  #if 0
Line 136  USB_ATTACH(uhidev)
Line 130  USB_ATTACH(uhidev)
                 (void)usbd_set_protocol(iface, 1);                  (void)usbd_set_protocol(iface, 1);
 #endif  #endif
   
         sc->sc_iep_addr = sc->sc_oep_addr = -1;          ed = usbd_interface2endpoint_descriptor(iface, 0);
         for (i = 0; i < id->bNumEndpoints; i++) {          if (ed == NULL) {
                 ed = usbd_interface2endpoint_descriptor(iface, i);                  printf("%s: could not read endpoint descriptor\n",
                 if (ed == NULL) {                         USBDEVNAME(sc->sc_dev));
                         printf("%s: could not read endpoint descriptor\n",                  sc->sc_dying = 1;
                             USBDEVNAME(sc->sc_dev));                  USB_ATTACH_ERROR_RETURN;
                         sc->sc_dying = 1;  
                         USB_ATTACH_ERROR_RETURN;  
                 }  
   
                 DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d "  
                     "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"  
                     " bInterval=%d\n",  
                     ed->bLength, ed->bDescriptorType,  
                     ed->bEndpointAddress & UE_ADDR,  
                     UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",  
                     ed->bmAttributes & UE_XFERTYPE,  
                     UGETW(ed->wMaxPacketSize), ed->bInterval));  
   
                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&  
                     (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {  
                         sc->sc_iep_addr = ed->bEndpointAddress;  
                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&  
                     (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {  
                         sc->sc_oep_addr = ed->bEndpointAddress;  
                 } else {  
                         printf("%s: endpoint %d: ignored\n", USBDEVNAME(sc->sc_dev), i);  
                 }  
         }          }
   
         /*          DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d "
          * Check that we found an input interrupt endpoint. The output interrupt                       "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d"
          * endpoint is optional                       " bInterval=%d\n",
          */                       ed->bLength, ed->bDescriptorType,
         if (sc->sc_iep_addr == -1) {                       ed->bEndpointAddress & UE_ADDR,
                 printf("%s: no input interrupt endpoint\n", USBDEVNAME(sc->sc_dev));                       UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out",
                        ed->bmAttributes & UE_XFERTYPE,
                        UGETW(ed->wMaxPacketSize), ed->bInterval));
   
           if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN ||
               (ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
                   printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
                 sc->sc_dying = 1;                  sc->sc_dying = 1;
                 USB_ATTACH_ERROR_RETURN;                  USB_ATTACH_ERROR_RETURN;
         }          }
   
         /* XXX need to extend this */          sc->sc_ep_addr = ed->bEndpointAddress;
         descptr = NULL;  
         if (uaa->vendor == USB_VENDOR_WACOM) {  
                 static uByte reportbuf[] = {2, 2, 2};  
   
           /* XXX need to extend this */
           if (uaa->vendor == USB_VENDOR_WACOM &&
               uaa->product == USB_PRODUCT_WACOM_GRAPHIRE /* &&
               uaa->revision == 0x???? */) { /* XXX should use revision */
                 /* The report descriptor for the Wacom Graphire is broken. */                  /* The report descriptor for the Wacom Graphire is broken. */
                 switch (uaa->product) {                  size = sizeof uhid_graphire_report_descr;
                 case USB_PRODUCT_WACOM_GRAPHIRE:  
                         size = sizeof uhid_graphire_report_descr;  
                         descptr = uhid_graphire_report_descr;  
                         break;  
   
                 case USB_PRODUCT_WACOM_GRAPHIRE3_4X5: /* The 6x8 too? */  
                         /*  
                          * The Graphire3 needs 0x0202 to be written to  
                          * feature report ID 2 before it'll start  
                          * returning digitizer data.  
                          */  
                         usbd_set_report(uaa->iface, UHID_FEATURE_REPORT, 2,  
                             &reportbuf, sizeof reportbuf);  
   
                         size = sizeof uhid_graphire3_4x5_report_descr;  
                         descptr = uhid_graphire3_4x5_report_descr;  
                         break;  
                 default:  
                         /* Keep descriptor */  
                         break;  
                 }  
         }  
   
         if (descptr) {  
                 desc = malloc(size, M_USBDEV, M_NOWAIT);                  desc = malloc(size, M_USBDEV, M_NOWAIT);
                 if (desc == NULL)                  if (desc == NULL)
                         err = USBD_NOMEM;                          err = USBD_NOMEM;
                 else {                  else {
                         err = USBD_NORMAL_COMPLETION;                          err = USBD_NORMAL_COMPLETION;
                         memcpy(desc, descptr, size);                          memcpy(desc, uhid_graphire_report_descr, size);
                 }                  }
         } else {          } else {
                 desc = NULL;                  desc = NULL;
                 err = usbd_read_report_desc(uaa->iface, &desc, &size,                  err = usbd_read_report_desc(uaa->iface, &desc, &size, M_USBDEV);
                     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));
Line 225  USB_ATTACH(uhidev)
Line 179  USB_ATTACH(uhidev)
                 USB_ATTACH_ERROR_RETURN;                  USB_ATTACH_ERROR_RETURN;
         }          }
   
         if (uaa->vendor == USB_VENDOR_HOSIDEN &&  
             uaa->product == USB_PRODUCT_HOSIDEN_PPP) {  
                 static uByte reportbuf[] = { 1 };  
                 /*  
                  *  This device was sold by Konami with its ParaParaParadise  
                  *  game for PlayStation2.  It needs to be "turned on"  
                  *  before it will send any reports.  
                  */  
   
                 usbd_set_report(uaa->iface, UHID_FEATURE_REPORT, 0,  
                     &reportbuf, sizeof reportbuf);  
         }  
   
         sc->sc_repdesc = desc;          sc->sc_repdesc = desc;
         sc->sc_repdesc_size = size;          sc->sc_repdesc_size = size;
   
Line 281  USB_ATTACH(uhidev)
Line 222  USB_ATTACH(uhidev)
                         ;       /* already NULL in sc->sc_subdevs[repid] */                          ;       /* already NULL in sc->sc_subdevs[repid] */
                 } else {                  } else {
                         uha.reportid = repid;                          uha.reportid = repid;
                         locs[UHIDBUSCF_REPORTID] = repid;                          dev = (struct uhidev *)config_found_sm(self, &uha,
                                                      uhidevprint, uhidevsubmatch);
                         dev = (struct uhidev *)config_found_sm_loc(self,  
                                 "uhidbus", locs, &uha,  
                                 uhidevprint, uhidevsubmatch);  
                         sc->sc_subdevs[repid] = dev;                          sc->sc_subdevs[repid] = dev;
                         if (dev != NULL) {                          if (dev != NULL) {
                                 dev->sc_in_rep_size = repsizes[repid];                                  dev->sc_in_rep_size = repsizes[repid];
Line 299  USB_ATTACH(uhidev)
Line 237  USB_ATTACH(uhidev)
                                 }                                  }
 #endif  #endif
 #if NRND > 0  #if NRND > 0
                                 rnd_attach_source(&dev->rnd_source,                                  rnd_attach_source(&dev->rnd_source,
                                                   USBDEVNAME(dev->sc_dev),                                                    USBDEVNAME(dev->sc_dev),
                                                   RND_TYPE_TTY, 0);                                                    RND_TYPE_TTY, 0);
 #endif  #endif
                         }                          }
Line 339  uhidevprint(void *aux, const char *pnp)
Line 277  uhidevprint(void *aux, const char *pnp)
 }  }
   
 int  int
 uhidevsubmatch(struct device *parent, struct cfdata *cf,  uhidevsubmatch(struct device *parent, struct cfdata *cf, void *aux)
                const int *locs, void *aux)  
 {  {
         if (cf->cf_loc[UHIDBUSCF_REPORTID] != UHIDBUSCF_REPORTID_DEFAULT &&          struct uhidev_attach_arg *uha = aux;
             cf->cf_loc[UHIDBUSCF_REPORTID] != locs[UHIDBUSCF_REPORTID])  
                 return (0);  
   
           if (cf->uhidevcf_reportid != UHIDEV_UNK_REPORTID &&
               cf->uhidevcf_reportid != uha->reportid)
                   return (0);
           if (cf->uhidevcf_reportid == uha->reportid)
                   uha->matchlvl = UMATCH_VENDOR_PRODUCT;
           else
                   uha->matchlvl = 0;
         return (config_match(parent, cf, aux));          return (config_match(parent, cf, aux));
 }  }
   
Line 367  uhidev_activate(device_ptr_t self, enum 
Line 309  uhidev_activate(device_ptr_t self, enum 
                                         &sc->sc_subdevs[i]->sc_dev);                                          &sc->sc_subdevs[i]->sc_dev);
                 sc->sc_dying = 1;                  sc->sc_dying = 1;
                 break;                  break;
         default:  
                 rv = 0;  
                 break;  
         }          }
         return (rv);          return (rv);
 }  }
Line 382  USB_DETACH(uhidev)
Line 321  USB_DETACH(uhidev)
         DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags));          DPRINTF(("uhidev_detach: sc=%p flags=%d\n", sc, flags));
   
         sc->sc_dying = 1;          sc->sc_dying = 1;
         if (sc->sc_ipipe != NULL)          if (sc->sc_intrpipe != NULL)
                 usbd_abort_pipe(sc->sc_ipipe);                  usbd_abort_pipe(sc->sc_intrpipe);
   
         if (sc->sc_repdesc != NULL)          if (sc->sc_repdesc != NULL)
                 free(sc->sc_repdesc, M_USBDEV);                  free(sc->sc_repdesc, M_USBDEV);
Line 434  uhidev_intr(usbd_xfer_handle xfer, usbd_
Line 373  uhidev_intr(usbd_xfer_handle xfer, usbd_
         if (status != USBD_NORMAL_COMPLETION) {          if (status != USBD_NORMAL_COMPLETION) {
                 DPRINTF(("%s: interrupt status=%d\n", USBDEVNAME(sc->sc_dev),                  DPRINTF(("%s: interrupt status=%d\n", USBDEVNAME(sc->sc_dev),
                          status));                           status));
                 usbd_clear_endpoint_stall_async(sc->sc_ipipe);                  usbd_clear_endpoint_stall_async(sc->sc_intrpipe);
                 return;                  return;
         }          }
   
Line 452  uhidev_intr(usbd_xfer_handle xfer, usbd_
Line 391  uhidev_intr(usbd_xfer_handle xfer, usbd_
                     rep, scd, scd ? scd->sc_state : 0));                      rep, scd, scd ? scd->sc_state : 0));
         if (scd == NULL || !(scd->sc_state & UHIDEV_OPEN))          if (scd == NULL || !(scd->sc_state & UHIDEV_OPEN))
                 return;                  return;
         if (scd->sc_in_rep_size != cc) {  #ifdef DIAGNOSTIC
                 printf("%s: bad input length %d != %d\n",          if (scd->sc_in_rep_size != cc)
                        USBDEVNAME(sc->sc_dev), scd->sc_in_rep_size, cc);                  printf("%s: bad input length %d != %d\n",USBDEVNAME(sc->sc_dev),
                 return;                         scd->sc_in_rep_size, cc);
         }  #endif
 #if NRND > 0  #if NRND > 0
         rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf));          rnd_add_uint32(&scd->rnd_source, (uintptr_t)(sc->sc_ibuf));
 #endif  #endif
Line 475  uhidev_open(struct uhidev *scd)
Line 414  uhidev_open(struct uhidev *scd)
 {  {
         struct uhidev_softc *sc = scd->sc_parent;          struct uhidev_softc *sc = scd->sc_parent;
         usbd_status err;          usbd_status err;
         int error;  
   
         DPRINTF(("uhidev_open: open pipe, state=%d refcnt=%d\n",          DPRINTF(("uhidev_open: open pipe, state=%d refcnt=%d\n",
                  scd->sc_state, sc->sc_refcnt));                   scd->sc_state, sc->sc_refcnt));
Line 491  uhidev_open(struct uhidev *scd)
Line 429  uhidev_open(struct uhidev *scd)
   
         sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);          sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);
   
         /* Set up input interrupt pipe. */          /* Set up interrupt pipe. */
         DPRINTF(("uhidev_open: isize=%d, ep=0x%02x\n", sc->sc_isize,          DPRINTF(("uhidev_open: isize=%d, ep=0x%02x\n", sc->sc_isize,
                  sc->sc_iep_addr));                   sc->sc_ep_addr));
           err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
         err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr,                    USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
                   USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf,  
                   sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL);                    sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL);
         if (err != USBD_NORMAL_COMPLETION) {          if (err) {
                 DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "                  DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
                     "error=%d\n", err));                           "error=%d\n",err));
                 error = EIO;                  free(sc->sc_ibuf, M_USBDEV);
                 goto out1;                  scd->sc_state &= ~UHIDEV_OPEN;
         }                  sc->sc_refcnt = 0;
                   sc->sc_intrpipe = NULL;
         /*                  return (EIO);
          * Set up output interrupt pipe if an output interrupt endpoint  
          * exists.  
          */  
         if (sc->sc_oep_addr != -1) {  
                 DPRINTF(("uhidev_open: oep=0x%02x\n", sc->sc_oep_addr));  
   
                 err = usbd_open_pipe(sc->sc_iface, sc->sc_oep_addr,  
                     0, &sc->sc_opipe);  
   
                 if (err != USBD_NORMAL_COMPLETION) {  
                         DPRINTF(("uhidev_open: usbd_open_pipe failed, "  
                             "error=%d\n", err));  
                         error = EIO;  
                         goto out2;  
                 }  
                 DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe));  
   
                 sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);  
                 if (sc->sc_oxfer == NULL) {  
                         DPRINTF(("uhidev_open: couldn't allocate an xfer\n"));  
                         error = ENOMEM;  
                         goto out3;  
                 }  
         }          }
   
         return (0);          return (0);
 out3:  
         /* Abort output pipe */  
         usbd_close_pipe(sc->sc_opipe);  
 out2:  
         /* Abort input pipe */  
         usbd_close_pipe(sc->sc_ipipe);  
 out1:  
         DPRINTF(("uhidev_open: failed in someway"));  
         free(sc->sc_ibuf, M_USBDEV);  
         scd->sc_state &= ~UHIDEV_OPEN;  
         sc->sc_refcnt = 0;  
         sc->sc_ipipe = NULL;  
         sc->sc_opipe = NULL;  
         sc->sc_oxfer = NULL;  
         return error;  
 }  }
   
 void  void
Line 561  uhidev_close(struct uhidev *scd)
Line 459  uhidev_close(struct uhidev *scd)
                 return;                  return;
         DPRINTF(("uhidev_close: close pipe\n"));          DPRINTF(("uhidev_close: close pipe\n"));
   
         if (sc->sc_oxfer != NULL)  
                 usbd_free_xfer(sc->sc_oxfer);  
   
         /* Disable interrupts. */          /* Disable interrupts. */
         if (sc->sc_opipe != NULL) {          if (sc->sc_intrpipe != NULL) {
                 usbd_abort_pipe(sc->sc_opipe);                  usbd_abort_pipe(sc->sc_intrpipe);
                 usbd_close_pipe(sc->sc_opipe);                  usbd_close_pipe(sc->sc_intrpipe);
                 sc->sc_opipe = NULL;                  sc->sc_intrpipe = NULL;
         }  
   
         if (sc->sc_ipipe != NULL) {  
                 usbd_abort_pipe(sc->sc_ipipe);  
                 usbd_close_pipe(sc->sc_ipipe);  
                 sc->sc_ipipe = NULL;  
         }          }
   
         if (sc->sc_ibuf != NULL) {          if (sc->sc_ibuf != NULL) {
Line 598  uhidev_set_report(struct uhidev *scd, in
Line 487  uhidev_set_report(struct uhidev *scd, in
         memcpy(buf+1, data, len);          memcpy(buf+1, data, len);
   
         retstat = usbd_set_report(scd->sc_parent->sc_iface, type,          retstat = usbd_set_report(scd->sc_parent->sc_iface, type,
                                   scd->sc_report_id, buf, len + 1);                                    scd->sc_report_id, data, len + 1);
   
         free(buf, M_TEMP);          free(buf, M_TEMP);
   
Line 627  uhidev_get_report(struct uhidev *scd, in
Line 516  uhidev_get_report(struct uhidev *scd, in
         return usbd_get_report(scd->sc_parent->sc_iface, type,          return usbd_get_report(scd->sc_parent->sc_iface, type,
                                scd->sc_report_id, data, len);                                 scd->sc_report_id, data, len);
 }  }
   
 usbd_status  
 uhidev_write(struct uhidev_softc *sc, void *data, int len)  
 {  
   
         DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len));  
   
         if (sc->sc_opipe == NULL)  
                 return USBD_INVAL;  
   
 #ifdef UHIDEV_DEBUG  
         if (uhidevdebug > 50) {  
   
                 u_int32_t i;  
                 u_int8_t *d = data;  
   
                 DPRINTF(("uhidev_write: data ="));  
                 for (i = 0; i < len; i++)  
                         DPRINTF((" %02x", d[i]));  
                 DPRINTF(("\n"));  
         }  
 #endif  
         return usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0,  
             USBD_NO_TIMEOUT, data, &len, "uhidevwi");  
 }  

Legend:
Removed from v.1.14.2.7  
changed lines
  Added in v.1.15

CVSweb <webmaster@jp.NetBSD.org>