$OpenBSD: patch-bsd_c,v 1.12 2011/01/25 21:04:16 jakemsr Exp $

usb_os_find_busses(): don't access to the bus.  just say there
  is one.

usb_os_find_devices(): only ugen(4) are supported, so just probe
  /dev/ugen*.


--- bsd.c.orig	Fri Mar  3 18:52:46 2006
+++ bsd.c	Mon Jan 24 23:46:26 2011
@@ -361,7 +361,7 @@ int usb_bulk_read(usb_dev_handle *dev, int ep, char *b
 int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
                         int timeout)
 {
-  int fd, ret, sent = 0;
+  int fd, ret;
 
   /* Ensure the endpoint address is correct */
   ep &= ~USB_ENDPOINT_IN;
@@ -383,8 +383,7 @@ int usb_interrupt_write(usb_dev_handle *dev, int ep, c
     USB_ERROR_STR(-errno, "error setting timeout: %s",
                   strerror(errno));
 
-  do {
-    ret = write(fd, bytes+sent, size-sent);
+  ret = write(fd, bytes, size);
     if (ret < 0)
 #ifdef __FreeBSD_kernel__
       USB_ERROR_STR(-errno, "error writing to interrupt endpoint %s.%d: %s",
@@ -394,16 +393,13 @@ int usb_interrupt_write(usb_dev_handle *dev, int ep, c
                   dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
 #endif
 
-    sent += ret;
-  } while (ret > 0 && sent < size);
-
-  return sent;
+  return ret;
 }
 
 int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
                        int timeout)
 {
-  int fd, ret, retrieved = 0, one = 1;
+  int fd, ret, one = 1;
 
   /* Ensure the endpoint address is correct */
   ep |= USB_ENDPOINT_IN;
@@ -428,8 +424,7 @@ int usb_interrupt_read(usb_dev_handle *dev, int ep, ch
   if (ret < 0)
     USB_ERROR_STR(-errno, "error setting short xfer: %s", strerror(errno));
 
-  do {
-    ret = read(fd, bytes+retrieved, size-retrieved);
+  ret = read(fd, bytes, size);
     if (ret < 0)
 #ifdef __FreeBSD_kernel__
       USB_ERROR_STR(-errno, "error reading from interrupt endpoint %s.%d: %s",
@@ -438,10 +433,7 @@ int usb_interrupt_read(usb_dev_handle *dev, int ep, ch
       USB_ERROR_STR(-errno, "error reading from interrupt endpoint %s.%02d: %s",
                   dev->device->filename, UE_GET_ADDR(ep), strerror(errno));
 #endif
-    retrieved += ret;
-  } while (ret > 0 && retrieved < size);
-
-  return retrieved;
+  return ret;
 }
 
 int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
@@ -477,45 +469,28 @@ int usb_control_msg(usb_dev_handle *dev, int requestty
     USB_ERROR_STR(-errno, "error sending control message: %s",
                   strerror(errno));
 
-  return UGETW(req.ucr_request.wLength);
+  return req.ucr_actlen;
 }
 
 int usb_os_find_busses(struct usb_bus **busses)
 {
   struct usb_bus *fbus = NULL;
-  int controller;
-  int fd;
-  char buf[20];
+  struct usb_bus *bus;
 
-  for (controller = 0; controller < MAX_CONTROLLERS; controller++) {
-    struct usb_bus *bus;
+  /* just one bus that always exists.  this is faked, so we don't have
+   * to give access to the bus.
+   */
 
-    snprintf(buf, sizeof(buf) - 1, "/dev/usb%d", controller);
-    fd = open(buf, O_RDWR);
-    if (fd < 0) {
-      if (usb_debug >= 2)
-        if (errno != ENXIO && errno != ENOENT)
-          fprintf(stderr, "usb_os_find_busses: can't open %s: %s\n",
-                  buf, strerror(errno));
-      continue;
-    }
-    close(fd);
+  bus = malloc(sizeof(*bus));
+  if (!bus)
+    USB_ERROR(-ENOMEM);
 
-    bus = malloc(sizeof(*bus));
-    if (!bus)
-      USB_ERROR(-ENOMEM);
+  memset((void *)bus, 0, sizeof(*bus));
 
-    memset((void *)bus, 0, sizeof(*bus));
+  snprintf(bus->dirname, sizeof(bus->dirname), "/dev/usb");
 
-    strncpy(bus->dirname, buf, sizeof(bus->dirname) - 1);
-    bus->dirname[sizeof(bus->dirname) - 1] = 0;
+  LIST_ADD(fbus, bus);
 
-    LIST_ADD(fbus, bus);
-
-    if (usb_debug >= 2)
-      fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
-  }
-
   *busses = fbus;
 
   return 0;
@@ -523,43 +498,27 @@ int usb_os_find_busses(struct usb_bus **busses)
 
 int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
 {
+  struct usb_device *dev;
+  unsigned char device_desc[DEVICE_DESC_LENGTH];
+  char devnode[USB_MAX_DEVNAMELEN];
+  char devname[USB_MAX_DEVNAMELEN];
   struct usb_device *fdev = NULL;
-  int cfd, dfd;
-  int device;
+  int fd, i;
 
-  cfd = open(bus->dirname, O_RDONLY);
-  if (cfd < 0)
-    USB_ERROR_STR(-errno, "couldn't open(%s): %s", bus->dirname,
-                  strerror(errno));
+  /* USB_MAX_DEVICES is the max # of all devices per bus.  this is
+   * only for ugen(4) devices, but on all buses.  is 32 enough?
+   */
+  for (i = 0; i < 32 /* USB_MAX_DEVICES */; i++) {
+    snprintf(devname, sizeof(devname), "/dev/ugen%d", i);
 
-  for (device = 1; device < USB_MAX_DEVICES; device++) {
-    struct usb_device_info di;
-    struct usb_device *dev;
-    unsigned char device_desc[DEVICE_DESC_LENGTH];
-    char buf[20];
+    /* device control node */
+    snprintf(devnode, sizeof(devnode), "%s.00", devname);
 
-    di.udi_addr = device;
-    if (ioctl(cfd, USB_DEVICEINFO, &di) < 0)
-      continue;
-
-    /* There's a device; is it one we should mess with? */
-
-    if (strncmp(di.udi_devnames[0], "ugen", 4) != 0)
-      /* best not to play with things we don't understand */
-      continue;
-
-#ifdef __FreeBSD_kernel__
-    snprintf(buf, sizeof(buf) - 1, "/dev/%s", di.udi_devnames[0]);
-#else
-    snprintf(buf, sizeof(buf) - 1, "/dev/%s.00", di.udi_devnames[0]);
-#endif
-
-    /* Open its control endpoint */
-    dfd = open(buf, O_RDONLY);
-    if (dfd < 0) {
+    fd = open(devnode, O_RDONLY);
+    if (fd < 0) {
       if (usb_debug >= 2)
         fprintf(stderr, "usb_os_find_devices: couldn't open device %s: %s\n",
-                buf, strerror(errno));
+                devname, strerror(errno));
       continue;
     }
 
@@ -571,21 +530,13 @@ int usb_os_find_devices(struct usb_bus *bus, struct us
 
     dev->bus = bus;
 
-    /* we need to report the device name as /dev/ugenx NOT /dev/ugenx.00
-     * This seemed easier than having 2 variables...
-     */
-#if (__NetBSD__ || __OpenBSD__)
-    snprintf(buf, sizeof(buf) - 1, "/dev/%s", di.udi_devnames[0]);
-#endif
+    strlcpy(dev->filename, devname, sizeof(dev->filename));
 
-    strncpy(dev->filename, buf, sizeof(dev->filename) - 1);
-    dev->filename[sizeof(dev->filename) - 1] = 0;
-
-    if (ioctl(dfd, USB_GET_DEVICE_DESC, device_desc) < 0)
+    if (ioctl(fd, USB_GET_DEVICE_DESC, device_desc) < 0)
       USB_ERROR_STR(-errno, "couldn't get device descriptor for %s: %s",
-                    buf, strerror(errno));
+                    devname, strerror(errno));
 
-    close(dfd);
+    close(fd);
 
     usb_parse_descriptor(device_desc, "bbwbbbbwwwbbbb", &dev->descriptor);
 
@@ -596,8 +547,6 @@ int usb_os_find_devices(struct usb_bus *bus, struct us
               dev->filename, bus->dirname);
   }
 
-  close(cfd);
-
   *devices = fdev;
 
   return 0;
@@ -623,9 +572,21 @@ int usb_resetep(usb_dev_handle *dev, unsigned int ep)
 
 int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
 {
-  /* Not yet done, because I haven't needed it. */
+  int ret;
+  struct usb_ctl_request ctl_req;
 
-  USB_ERROR_STR(-ENOSYS, "usb_clear_halt called, unimplemented on BSD");
+  ctl_req.ucr_addr = 0; // Not used for this type of request
+  ctl_req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
+  ctl_req.ucr_request.bRequest = UR_CLEAR_FEATURE;
+  USETW(ctl_req.ucr_request.wValue, UF_ENDPOINT_HALT);
+  USETW(ctl_req.ucr_request.wIndex, ep);
+  USETW(ctl_req.ucr_request.wLength, 0);
+  ctl_req.ucr_flags = 0;
+
+  if ((ret = ioctl(dev->fd, USB_DO_REQUEST, &ctl_req)) < 0)
+      USB_ERROR_STR(-errno, "clear_halt:  failed for %d", ep);
+
+  return ret;
 }
 
 int usb_reset(usb_dev_handle *dev)