/********************************************************************\
 
 
 
  Name:         musbstd.c
 
  Created by:   Konstantin Olchanski, Stefan Ritt
 
 
 
  Contents:     Midas USB access
 
 
 
  $Id$
 
 
 
\********************************************************************/
 
 
 
#include <stdio.h>
 
#include <assert.h>
 
#include "musbstd.h"
 
 
 
#ifdef _MSC_VER                 // Windows includes
 
 
 
#include <windows.h>
 
#include <conio.h>
 
#include <winioctl.h>
 
 
 
#include <setupapi.h>
 
#include <initguid.h>           /* Required for GUID definition */
 
 
 
// link with SetupAPI.Lib.
 
#pragma comment (lib, "setupapi.lib")
 
 
 
// disable "deprecated" warning
 
#pragma warning( disable: 4996)
 
 
 
// {CBEB3FB1-AE9F-471c-9016-9B6AC6DCD323}
 
DEFINE_GUID(GUID_CLASS_MSCB_BULK, 0xcbeb3fb1, 0xae9f, 0x471c, 0x90, 0x16, 0x9b, 0x6a, 0xc6, 0xdc, 0xd3, 0x23);
 
 
 
#elif defined(OS_DARWIN)
 
 
 
#include <unistd.h>
 
#include <string.h>
 
#include <stdlib.h>
 
#include <ctype.h>
 
#include <sys/types.h>
 
#include <sys/ioctl.h>
 
#include <sys/time.h>
 
#include <fcntl.h>
 
 
 
#include <assert.h>
 
#include <mach/mach.h>
 
#include <IOKit/IOKitLib.h>
 
#include <IOKit/IOCFPlugIn.h>
 
#include <IOKit/usb/IOUSBLib.h>
 
 
 
#elif defined(OS_LINUX)         // Linux includes
 
 
 
#include <unistd.h>
 
#include <string.h>
 
#include <stdlib.h>
 
 
 
#endif
 
 
 
#ifdef HAVE_LIBUSB
 
#include <errno.h>
 
#include "usb.h"
 
#endif
 
 
 
#ifdef HAVE_LIBUSB10
 
#include <errno.h>
 
#include <libusb-1.0/libusb.h>
 
#endif
 
 
 
#if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUSB10)
 
#ifdef OS_DARWIN
 
 
 
IOReturn darwin_configure_device(MUSB_INTERFACE* musb)
 
{
 
   IOReturn status;
 
   io_iterator_t iter;
 
   io_service_t service;
 
   IOCFPlugInInterface **plugin;
 
   SInt32 score;
 
   IOUSBInterfaceInterface **uinterface;
 
   UInt8 numend;
 
 
 
   IOUSBDeviceInterface **device = (IOUSBDeviceInterface **)musb->device;
 
 
 
   status = (*device)->SetConfiguration(device, musb->usb_configuration);
 
   assert(status 
== kIOReturnSuccess
);  
 
 
   IOUSBFindInterfaceRequest request;
 
 
 
   request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
 
   request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
 
   request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
 
   request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
 
   
 
   status = (*device)->CreateInterfaceIterator(device, &request, &iter);
 
   assert(status 
== kIOReturnSuccess
);  
  
 
   while ((service = IOIteratorNext(iter))) {
 
      int i;
 
      status =
 
        IOCreatePlugInInterfaceForService(service, kIOUSBInterfaceUserClientTypeID,
 
                                          kIOCFPlugInInterfaceID, &plugin, &score);
 
      assert(status 
== kIOReturnSuccess
);  
      
 
      status =
 
        (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
 
                                  (void *) &uinterface);
 
      assert(status 
== kIOReturnSuccess
);  
      
 
      
 
      status = (*uinterface)->USBInterfaceOpen(uinterface);
 
      fprintf(stderr
, "musb_open: USBInterfaceOpen status 0x%x\n", status
);  
      assert(status 
== kIOReturnSuccess
);  
      
 
      status = (*uinterface)->GetNumEndpoints(uinterface, &numend);
 
      assert(status 
== kIOReturnSuccess
);  
      
 
      fprintf(stderr
, "musb_open: endpoints: %d\n", numend
);  
      
 
      for (i=1; i<=numend; i++) {
 
         status = (*uinterface)->GetPipeStatus(uinterface, i);
 
         fprintf(stderr
, "musb_open: pipe %d status: 0x%x\n", i
, status
);  
      
 
#if 0
 
         status = (*uinterface)->ClearPipeStall(uinterface, i);
 
         fprintf(stderr
, "musb_open: pipe %d ClearPipeStall() status: 0x%x\n", i
, status
);  
         status = (*uinterface)->ResetPipe(uinterface, i);
 
         fprintf(stderr
, "musb_open: pipe %d ResetPipe() status: 0x%x\n", i
, status
);  
         status = (*uinterface)->AbortPipe(uinterface, i);
 
         fprintf(stderr
, "musb_open: pipe %d AbortPipe() status: 0x%x\n", i
, status
);  
#endif
 
      }
 
 
 
      musb->interface = uinterface;
 
      return kIOReturnSuccess;
 
   }
 
 
 
   assert(!"Should never be reached!");  
   return -1;
 
}
 
    
 
#endif
 
 
 
#endif
 
 
 
int musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface)
 
{
 
#if defined(HAVE_LIBUSB)
 
   
 
   struct usb_bus *bus;
 
   struct usb_device *dev;
 
   int count = 0;
 
   
 
   usb_init();
 
   usb_find_busses();
 
   usb_find_devices();
 
   usb_set_debug(3);
 
   
 
   for (bus = usb_get_busses(); bus; bus = bus->next)
 
      for (dev = bus->devices; dev; dev = dev->next)
 
         if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
 
            if (count == instance) {
 
               int status;
 
               usb_dev_handle *udev;
 
 
 
               udev = usb_open(dev);
 
               if (!udev) {
 
                  fprintf(stderr
, "musb_open: usb_open() error\n");  
                  return MUSB_ACCESS_ERROR;
 
               }
 
 
 
               status = usb_set_configuration(udev, configuration);
 
               if (status < 0) {
 
                  fprintf(stderr
, "musb_open: usb_set_configuration() error %d (%s)\n", status
,  
                     "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\" and \"/dev/bus/usb/%s/%s\"\n",
 
                     vendor, product, instance, bus->dirname, dev->filename, bus->dirname, dev->filename);
 
                  return MUSB_ACCESS_ERROR;
 
               }
 
 
 
               /* see if we have write access */
 
               status = usb_claim_interface(udev, usbinterface);
 
               if (status < 0) {
 
                  fprintf(stderr
, "musb_open: usb_claim_interface() error %d (%s)\n", status
,  
 
 
#ifdef _MSC_VER
 
                     "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
 
                     vendor, product, instance);
 
#else
 
                     "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%s/%s\"\n",
 
                     vendor, product, instance, bus->dirname, dev->filename);
 
#endif
 
 
 
                  return MUSB_ACCESS_ERROR;
 
               }
 
 
 
               *musb_interface 
= (MUSB_INTERFACE
*)calloc(1, sizeof(MUSB_INTERFACE
));  
               (*musb_interface)->dev = udev;
 
               (*musb_interface)->usb_configuration = configuration;
 
               (*musb_interface)->usb_interface     = usbinterface;
 
               return MUSB_SUCCESS;
 
            }
 
 
 
            count++;
 
         }
 
   
 
   return MUSB_NOT_FOUND;
 
   
 
#elif defined(HAVE_LIBUSB10)
 
   
 
   static int first_call = 1;
 
 
 
   libusb_device **dev_list;
 
   libusb_device_handle *dev;
 
   struct libusb_device_descriptor desc;
 
   
 
   int status, i, n;
 
   int count = 0;
 
   
 
   if (first_call) {
 
      first_call = 0;
 
      libusb_init(NULL);
 
      // libusb_set_debug(NULL, 3);
 
   }
 
      
 
   n = libusb_get_device_list(NULL, &dev_list);
 
   
 
   for (i=0 ; i<n ; i++) {
 
      status = libusb_get_device_descriptor(dev_list[i], &desc);
 
      if (desc.idVendor == vendor && desc.idProduct == product) {
 
         if (count == instance) {
 
            status = libusb_open(dev_list[i], &dev);
 
            if (status < 0) {
 
               fprintf(stderr
, "musb_open: libusb_open() error %d\n", status
);  
               return MUSB_ACCESS_ERROR;
 
            }
 
 
 
            status = libusb_set_configuration(dev, configuration);
 
            if (status < 0) {
 
               fprintf(stderr
, "musb_open: usb_set_configuration() error %d\n", status
);  
                       "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\" and \"/dev/bus/usb/%d/%d\"\n",
 
                       vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]), libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
 
               return MUSB_ACCESS_ERROR;
 
            }
 
            
 
            /* see if we have write access */
 
            status = libusb_claim_interface(dev, usbinterface);
 
            if (status < 0) {
 
               fprintf(stderr
, "musb_open: libusb_claim_interface() error %d\n", status
);  
               
 
#ifdef _MSC_VER
 
                       "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
 
                       vendor, product, instance);
 
#else
 
                       "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it: please check permissions on \"/proc/bus/usb/%d/%d\"\n",
 
                       vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
 
#endif
 
               
 
               return MUSB_ACCESS_ERROR;
 
            }
 
 
 
            *musb_interface 
= (MUSB_INTERFACE
*)calloc(1, sizeof(MUSB_INTERFACE
));  
            (*musb_interface)->dev = dev;
 
            (*musb_interface)->usb_configuration = configuration;
 
            (*musb_interface)->usb_interface     = usbinterface;
 
            return MUSB_SUCCESS;
 
 
 
         }
 
         count++;
 
      }
 
   }
 
   
 
   libusb_free_device_list(dev_list, 1);
 
   
 
   return MUSB_NOT_FOUND;
 
     
 
#elif defined(OS_DARWIN)
 
   
 
   kern_return_t status;
 
   io_iterator_t iter;
 
   io_service_t service;
 
   IOCFPlugInInterface **plugin;
 
   SInt32 score;
 
   IOUSBDeviceInterface **device;
 
   UInt16 xvendor, xproduct;
 
   int count = 0;
 
 
 
   *musb_interface 
= calloc(1, sizeof(MUSB_INTERFACE
));  
   
 
   status = IORegistryCreateIterator(kIOMasterPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &iter);
 
   assert(status 
== kIOReturnSuccess
);  
 
 
   while ((service = IOIteratorNext(iter))) {
 
      status =
 
          IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
 
                                            &plugin, &score);
 
      assert(status 
== kIOReturnSuccess
);  
 
 
      status = IOObjectRelease(service);
 
      assert(status 
== kIOReturnSuccess
);  
 
 
      status =
 
          (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void *) &device);
 
      assert(status 
== kIOReturnSuccess
);  
 
 
      status = (*plugin)->Release(plugin);
 
 
 
      status = (*device)->GetDeviceVendor(device, &xvendor);
 
      assert(status 
== kIOReturnSuccess
);  
      status = (*device)->GetDeviceProduct(device, &xproduct);
 
      assert(status 
== kIOReturnSuccess
);  
 
 
      //fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x\n", xvendor, xproduct);
 
 
 
      if (xvendor == vendor && xproduct == product) {
 
         if (count == instance) {
 
 
 
            fprintf(stderr
, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x, instance %d\n", xvendor
, xproduct
, instance
);  
 
 
            status = (*device)->USBDeviceOpen(device);
 
            fprintf(stderr
, "musb_open: USBDeviceOpen status 0x%x\n", status
);  
 
 
            assert(status 
== kIOReturnSuccess
);  
 
 
            (*musb_interface)->usb_configuration = configuration;
 
            (*musb_interface)->usb_interface     = usbinterface;
 
            (*musb_interface)->device = (void*)device;
 
            (*musb_interface)->interface = NULL;
 
 
 
            status = darwin_configure_device(*musb_interface);
 
 
 
            if (status == kIOReturnSuccess)
 
               return MUSB_SUCCESS;
 
 
 
            fprintf(stderr
, "musb_open: USB device exists, but configuration fails!");  
            return MUSB_NOT_FOUND;
 
         }
 
 
 
         count++;
 
      }
 
 
 
      (*device)->Release(device);
 
   }
 
 
 
   return MUSB_NOT_FOUND;
 
#elif defined(_MSC_VER)
 
   GUID guid;
 
   HDEVINFO hDevInfoList;
 
   SP_DEVICE_INTERFACE_DATA deviceInfoData;
 
   PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData;
 
   ULONG predictedLength, requiredLength;
 
   int status;
 
   char device_name[256], str[256];
 
 
 
   *musb_interface 
= (MUSB_INTERFACE 
*)calloc(1, sizeof(MUSB_INTERFACE
));  
 
 
   guid = GUID_CLASS_MSCB_BULK;
 
 
 
   // Retrieve device list for GUID that has been specified.
 
   hDevInfoList = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
 
 
 
   status = FALSE;
 
   if (hDevInfoList != NULL) {
 
 
 
      // Clear data structure
 
      memset(&deviceInfoData
, 0, sizeof(deviceInfoData
));  
      deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 
 
 
      // retrieves a context structure for a device interface of a device information set.
 
      if (SetupDiEnumDeviceInterfaces(hDevInfoList, 0, &guid, instance, &deviceInfoData)) {
 
         // Must get the detailed information in two steps
 
         // First get the length of the detailed information and allocate the buffer
 
         // retrieves detailed information about a specified device interface.
 
         functionClassDeviceData = NULL;
 
 
 
         predictedLength = requiredLength = 0;
 
 
 
         SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, NULL,   // Not yet allocated
 
                                         0,     // Set output buffer length to zero
 
                                         &requiredLength,       // Find out memory requirement
 
                                         NULL);
 
 
 
         predictedLength = requiredLength;
 
         functionClassDeviceData 
= (PSP_DEVICE_INTERFACE_DETAIL_DATA
) malloc(predictedLength
); 
         functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 
 
 
         // Second, get the detailed information
 
         if (SetupDiGetDeviceInterfaceDetail(hDevInfoList,
 
                                             &deviceInfoData, functionClassDeviceData,
 
                                             predictedLength, &requiredLength, NULL)) {
 
 
 
            // Save the device name for subsequent pipe open calls
 
            strcpy(device_name
, functionClassDeviceData
->DevicePath
);  
            free(functionClassDeviceData
);  
 
 
            // Signal device found
 
            status = TRUE;
 
         } else
 
            free(functionClassDeviceData
);  
      }
 
   }
 
   // SetupDiDestroyDeviceInfoList() destroys a device information set
 
   // and frees all associated memory.
 
   SetupDiDestroyDeviceInfoList(hDevInfoList);
 
 
 
   if (status) {
 
 
 
      // Get the read handle
 
      sprintf(str
, "%s\\PIPE00", device_name
);  
      (*musb_interface)->rhandle = CreateFile(str,
 
                                    GENERIC_WRITE | GENERIC_READ,
 
                                    FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
 
                                    OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
 
 
 
      if ((*musb_interface)->rhandle == INVALID_HANDLE_VALUE)
 
         return MUSB_ACCESS_ERROR;
 
 
 
      // Get the write handle
 
      sprintf(str
, "%s\\PIPE01", device_name
);  
      (*musb_interface)->whandle = CreateFile(str,
 
                                    GENERIC_WRITE | GENERIC_READ,
 
                                    FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
 
 
 
      if ((*musb_interface)->whandle == INVALID_HANDLE_VALUE)
 
         return MUSB_ACCESS_ERROR;
 
 
 
      return MUSB_SUCCESS;
 
   } 
 
     
 
   return MUSB_NOT_FOUND;
 
#endif
 
}
 
 
 
int musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index)
 
{
 
#if defined (HAVE_LIBUSB)
 
   int status;
 
 
 
   status = usb_set_altinterface(musb_interface->dev, index);
 
   if (status < 0)
 
      fprintf(stderr
, "musb_set_altinterface: usb_set_altinterface() error %d\n", status
);  
 
 
   return status;
 
#else
 
   return -1;
 
#endif
 
}
 
 
 
int musb_close(MUSB_INTERFACE *musb_interface)
 
{
 
#if defined(HAVE_LIBUSB)
 
 
 
   int status;
 
   status = usb_release_interface(musb_interface->dev, musb_interface->usb_interface);
 
   if (status < 0)
 
      fprintf(stderr
, "musb_close: usb_release_interface() error %d\n", status
);  
   
 
#ifdef OS_LINUX   // linux wants a reset, otherwise the device cannot be accessed next time
 
   musb_reset(musb_interface);
 
#endif
 
 
 
   status = usb_close(musb_interface->dev);
 
   if (status < 0)
 
      fprintf(stderr
, "musb_close: usb_close() error %d\n", status
);  
   
 
#elif defined(HAVE_LIBUSB10)   
 
 
 
   int status;
 
   status = libusb_release_interface(musb_interface->dev, musb_interface->usb_interface);
 
   if (status < 0)
 
      fprintf(stderr
, "musb_close: libusb_release_interface() error %d\n", status
);  
   
 
#ifdef OS_LINUX   // linux wants a reset, otherwise the device cannot be accessed next time
 
   musb_reset(musb_interface);
 
#endif
 
   
 
   libusb_close(musb_interface->dev);
 
 
 
#elif defined(OS_DARWIN)
 
 
 
   IOReturn status;
 
   IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **)musb_interface->interface;
 
 
 
   status = (*interface)->USBInterfaceClose(interface);
 
   if (status != kIOReturnSuccess)
 
      fprintf(stderr
, "musb_close: USBInterfaceClose() status %d 0x%x\n", status
, status
);  
 
 
   status = (*interface)->Release(interface);
 
   if (status != kIOReturnSuccess)
 
      fprintf(stderr
, "musb_close: USB Interface Release() status %d 0x%x\n", status
, status
);  
 
 
   IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
 
   status = (*device)->USBDeviceClose(device);
 
   if (status != kIOReturnSuccess)
 
      fprintf(stderr
, "musb_close: USBDeviceClose() status %d 0x%x\n", status
, status
);  
 
 
   status = (*device)->Release(device);
 
   if (status != kIOReturnSuccess)
 
      fprintf(stderr
, "musb_close: USB Device Release() status %d 0x%x\n", status
, status
);  
 
 
#elif defined(_MSC_VER)
 
 
 
   CloseHandle(musb_interface->rhandle);
 
   CloseHandle(musb_interface->whandle);
 
 
 
#else
 
   assert(!"musb_close() is not implemented");  
#endif
 
 
 
   /* free memory allocated in musb_open() */
 
   return 0;
 
}
 
 
 
int musb_write(MUSB_INTERFACE *musb_interface, int endpoint, const void *buf, int count, int timeout)
 
{
 
   int n_written;
 
 
 
#if defined(HAVE_LIBUSB)
 
   n_written = usb_bulk_write(musb_interface->dev, endpoint, (char*)buf, count, timeout);
 
   if (n_written != count) {
 
      fprintf(stderr
, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count
, n_written
, errno
, strerror(errno
));  
   }
 
#elif defined(HAVE_LIBUSB10)
 
   int status = libusb_bulk_transfer(musb_interface->dev, endpoint, (unsigned char*)buf, count, &n_written, timeout);
 
   if (n_written != count) {
 
      fprintf(stderr
, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count
, n_written
, status
, strerror(status
));  
   }
 
#elif defined(OS_DARWIN)
 
   IOReturn status;
 
   IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
 
   status = (*interface)->WritePipeTO(interface, endpoint, buf, count, 0, timeout);
 
   if (status != 0) {
 
      fprintf(stderr
, "musb_write: WritePipe() status %d 0x%x\n", status
, status
);  
      return -1;
 
   }
 
   n_written = count;
 
#elif defined(_MSC_VER)
 
   WriteFile(musb_interface->whandle, buf, count, &n_written, NULL);
 
#endif
 
 
 
   //fprintf(stderr, "musb_write(ep %d, %d bytes) (%s) returns %d\n", endpoint, count, buf, n_written); 
 
 
 
   return n_written;
 
}
 
 
 
int musb_read(MUSB_INTERFACE *musb_interface, int endpoint, void *buf, int count, int timeout)
 
{
 
   int n_read = 0;
 
 
 
#if defined(HAVE_LIBUSB)
 
 
 
   n_read = usb_bulk_read(musb_interface->dev, endpoint | 0x80, (char*)buf, count, timeout);
 
   /* errors should be handled in upper layer ....
 
   if (n_read <= 0) {
 
      fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, errno, strerror(errno));
 
   }
 
   */
 
 
 
#elif defined(HAVE_LIBUSB10)
 
   
 
   libusb_bulk_transfer(musb_interface->dev, endpoint | 0x80, (unsigned char*)buf, count, &n_read, timeout);
 
   /* errors should be handled in upper layer ....
 
    if (n_read <= 0) {
 
    fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, status, strerror(status));
 
    }
 
    */
 
   
 
#elif defined(OS_DARWIN)
 
 
 
   UInt32 xcount = count;
 
   IOReturn status;
 
   IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
 
 
 
   status = (*interface)->ReadPipeTO(interface, endpoint, buf, &xcount, 0, timeout);
 
   if (status != kIOReturnSuccess) {
 
      fprintf(stderr
, "musb_read: requested %d, read %d, ReadPipe() status %d 0x%x (%s)\n", count
, n_read
, status
, status
, strerror(status
));  
      return -1;
 
   }
 
 
 
   n_read = xcount;
 
 
 
#elif defined(_MSC_VER)
 
 
 
   OVERLAPPED overlapped;
 
   int status;
 
 
 
   memset(&overlapped
, 0, sizeof(overlapped
));  
   overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 
   n_read = 0;
 
 
 
   status = ReadFile(musb_interface->rhandle, buf, count, &n_read, &overlapped);
 
   
 
   if (!status) {
 
 
 
      status = GetLastError();
 
      if (status != ERROR_IO_PENDING)
 
         return 0;
 
 
 
      /* wait for completion with timeout */
 
      status = WaitForSingleObject(overlapped.hEvent, timeout);
 
      if (status == WAIT_TIMEOUT)
 
         CancelIo(musb_interface->rhandle);
 
      else
 
         GetOverlappedResult(musb_interface->rhandle, &overlapped, &n_read, FALSE);
 
   }
 
 
 
   CloseHandle(overlapped.hEvent);
 
 
 
#endif
 
 
 
   //fprintf(stderr, "musb_read(ep %d, %d bytes) returns %d (%s)\n", endpoint, count, n_read, buf); 
 
 
 
   return n_read;
 
}
 
 
 
int musb_reset(MUSB_INTERFACE *musb_interface)
 
{
 
#if defined(HAVE_LIBUSB)
 
 
 
   /* Causes re-enumeration: After calling usb_reset, the device will need 
 
      to re-enumerate and thusly, requires you to find the new device and 
 
      open a new handle. The handle used to call usb_reset will no longer work */
 
 
 
   int status;
 
   status = usb_reset(musb_interface->dev);
 
   if (status < 0)
 
      fprintf(stderr
, "musb_reset: usb_reset() status %d\n", status
);  
 
 
#elif defined(HAVE_LIBUSB10)
 
   
 
   int status;
 
   status = libusb_reset_device(musb_interface->dev);
 
   if (status < 0)
 
      fprintf(stderr
, "musb_reset: usb_reset() status %d\n", status
);  
   
 
#elif defined(OS_DARWIN)
 
 
 
   IOReturn status;
 
   IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
 
 
 
   status = (*device)->ResetDevice(device);
 
   fprintf(stderr
, "musb_reset: ResetDevice() status 0x%x\n", status
);  
 
 
   status = darwin_configure_device(musb_interface);
 
   assert(status 
== kIOReturnSuccess
);  
 
 
#elif defined(_MSC_VER)
 
 
 
#define IOCTL_BULKUSB_RESET_DEVICE          CTL_CODE(FILE_DEVICE_UNKNOWN,     \
 
                                                     1,                       \
 
                                                     METHOD_BUFFERED,         \
 
                                                     FILE_ANY_ACCESS)
 
#define IOCTL_BULKUSB_RESET_PIPE            CTL_CODE(FILE_DEVICE_UNKNOWN,     \
 
                                                     2,                       \
 
                                                     METHOD_BUFFERED,         \
 
                                                     FILE_ANY_ACCESS)
 
 
 
   int status, n_bytes;
 
 
 
   status =  DeviceIoControl(musb_interface->rhandle,
 
                  IOCTL_BULKUSB_RESET_DEVICE,
 
                  NULL, 0, NULL, 0, &n_bytes, NULL);
 
   status =  DeviceIoControl(musb_interface->whandle,
 
                  IOCTL_BULKUSB_RESET_DEVICE,
 
                  NULL, 0, NULL, 0, &n_bytes, NULL);
 
   status =  DeviceIoControl(musb_interface->rhandle,
 
                  IOCTL_BULKUSB_RESET_PIPE,
 
                  NULL, 0, NULL, 0, &n_bytes, NULL);
 
   status =  DeviceIoControl(musb_interface->whandle,
 
                  IOCTL_BULKUSB_RESET_PIPE,
 
                  NULL, 0, NULL, 0, &n_bytes, NULL);
 
   return status;
 
 
 
#endif
 
   return 0;
 
}
 
 
 
int musb_get_device(MUSB_INTERFACE *usb_interface)
 
{
 
#ifdef HAVE_LIBUSB
 
   struct usb_device_descriptor d;
 
   usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d));
 
   return d.bcdDevice;
 
#elif HAVE_LIBUSB10
 
   struct libusb_device_descriptor d;
 
   libusb_get_descriptor(usb_interface->dev, LIBUSB_DT_DEVICE, 0, (unsigned char *)&d, sizeof(d));
 
   return d.bcdDevice;
 
#else
 
   return 0;
 
#endif
 
}
 
 
 
/* end */