Subversion Repositories f9daq

Rev

Rev 195 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /********************************************************************\
  2.  
  3.   Name:         musbstd.c
  4.   Created by:   Konstantin Olchanski, Stefan Ritt
  5.  
  6.   Contents:     Midas USB access
  7.  
  8.   $Id$
  9.  
  10. \********************************************************************/
  11.  
  12. #include <stdio.h>
  13. #include <assert.h>
  14. #include "musbstd.h"
  15.  
  16. #ifdef _MSC_VER                 // Windows includes
  17.  
  18. #include <windows.h>
  19. #include <conio.h>
  20. #include <winioctl.h>
  21.  
  22. #include <setupapi.h>
  23. #include <initguid.h>           /* Required for GUID definition */
  24.  
  25. // link with SetupAPI.Lib.
  26. #pragma comment (lib, "setupapi.lib")
  27.  
  28. // disable "deprecated" warning
  29. #pragma warning( disable: 4996)
  30.  
  31. // {CBEB3FB1-AE9F-471c-9016-9B6AC6DCD323}
  32. DEFINE_GUID(GUID_CLASS_MSCB_BULK, 0xcbeb3fb1, 0xae9f, 0x471c, 0x90, 0x16, 0x9b, 0x6a, 0xc6, 0xdc, 0xd3, 0x23);
  33.  
  34. #elif defined(OS_DARWIN)
  35.  
  36. #include <unistd.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <ctype.h>
  40. #include <sys/types.h>
  41. #include <sys/ioctl.h>
  42. #include <sys/time.h>
  43. #include <fcntl.h>
  44.  
  45. #include <assert.h>
  46. #include <mach/mach.h>
  47. #include <IOKit/IOKitLib.h>
  48. #include <IOKit/IOCFPlugIn.h>
  49. #include <IOKit/usb/IOUSBLib.h>
  50.  
  51. #elif defined(OS_LINUX)         // Linux includes
  52.  
  53. #include <unistd.h>
  54. #include <string.h>
  55. #include <stdlib.h>
  56.  
  57. #endif
  58.  
  59. #ifdef HAVE_LIBUSB
  60. #include <errno.h>
  61. #include "usb.h"
  62. #endif
  63.  
  64. #ifdef HAVE_LIBUSB10
  65. #include <errno.h>
  66. #include <libusb-1.0/libusb.h>
  67. #endif
  68.  
  69. #if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBUSB10)
  70. #ifdef OS_DARWIN
  71.  
  72. IOReturn darwin_configure_device(MUSB_INTERFACE* musb)
  73. {
  74.    IOReturn status;
  75.    io_iterator_t iter;
  76.    io_service_t service;
  77.    IOCFPlugInInterface **plugin;
  78.    SInt32 score;
  79.    IOUSBInterfaceInterface **uinterface;
  80.    UInt8 numend;
  81.  
  82.    IOUSBDeviceInterface **device = (IOUSBDeviceInterface **)musb->device;
  83.  
  84.    status = (*device)->SetConfiguration(device, musb->usb_configuration);
  85.    assert(status == kIOReturnSuccess);
  86.  
  87.    IOUSBFindInterfaceRequest request;
  88.  
  89.    request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
  90.    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
  91.    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
  92.    request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
  93.    
  94.    status = (*device)->CreateInterfaceIterator(device, &request, &iter);
  95.    assert(status == kIOReturnSuccess);
  96.  
  97.    while ((service = IOIteratorNext(iter))) {
  98.       int i;
  99.       status =
  100.         IOCreatePlugInInterfaceForService(service, kIOUSBInterfaceUserClientTypeID,
  101.                                           kIOCFPlugInInterfaceID, &plugin, &score);
  102.       assert(status == kIOReturnSuccess);
  103.      
  104.       status =
  105.         (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
  106.                                   (void *) &uinterface);
  107.       assert(status == kIOReturnSuccess);
  108.      
  109.      
  110.       status = (*uinterface)->USBInterfaceOpen(uinterface);
  111.       fprintf(stderr, "musb_open: USBInterfaceOpen status 0x%x\n", status);
  112.       assert(status == kIOReturnSuccess);
  113.      
  114.       status = (*uinterface)->GetNumEndpoints(uinterface, &numend);
  115.       assert(status == kIOReturnSuccess);
  116.      
  117.       fprintf(stderr, "musb_open: endpoints: %d\n", numend);
  118.      
  119.       for (i=1; i<=numend; i++) {
  120.          status = (*uinterface)->GetPipeStatus(uinterface, i);
  121.          fprintf(stderr, "musb_open: pipe %d status: 0x%x\n", i, status);
  122.      
  123. #if 0
  124.          status = (*uinterface)->ClearPipeStall(uinterface, i);
  125.          fprintf(stderr, "musb_open: pipe %d ClearPipeStall() status: 0x%x\n", i, status);
  126.          status = (*uinterface)->ResetPipe(uinterface, i);
  127.          fprintf(stderr, "musb_open: pipe %d ResetPipe() status: 0x%x\n", i, status);
  128.          status = (*uinterface)->AbortPipe(uinterface, i);
  129.          fprintf(stderr, "musb_open: pipe %d AbortPipe() status: 0x%x\n", i, status);
  130. #endif
  131.       }
  132.  
  133.       musb->interface = uinterface;
  134.       return kIOReturnSuccess;
  135.    }
  136.  
  137.    assert(!"Should never be reached!");
  138.    return -1;
  139. }
  140.    
  141. #endif
  142.  
  143. #endif
  144.  
  145. int musb_open(MUSB_INTERFACE **musb_interface, int vendor, int product, int instance, int configuration, int usbinterface)
  146. {
  147. #if defined(HAVE_LIBUSB)
  148.    
  149.    struct usb_bus *bus;
  150.    struct usb_device *dev;
  151.    int count = 0;
  152.    
  153.    usb_init();
  154.    usb_find_busses();
  155.    usb_find_devices();
  156.    usb_set_debug(3);
  157.    
  158.    for (bus = usb_get_busses(); bus; bus = bus->next)
  159.       for (dev = bus->devices; dev; dev = dev->next)
  160.          if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) {
  161.             if (count == instance) {
  162.                int status;
  163.                usb_dev_handle *udev;
  164.  
  165.                udev = usb_open(dev);
  166.                if (!udev) {
  167.                   fprintf(stderr, "musb_open: usb_open() error\n");
  168.                   return MUSB_ACCESS_ERROR;
  169.                }
  170.  
  171.                status = usb_set_configuration(udev, configuration);
  172.                if (status < 0) {
  173.                   fprintf(stderr, "musb_open: usb_set_configuration() error %d (%s)\n", status,
  174.                      strerror(-status));
  175.                   fprintf(stderr,
  176.                      "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",
  177.                      vendor, product, instance, bus->dirname, dev->filename, bus->dirname, dev->filename);
  178.                   return MUSB_ACCESS_ERROR;
  179.                }
  180.  
  181.                /* see if we have write access */
  182.                status = usb_claim_interface(udev, usbinterface);
  183.                if (status < 0) {
  184.                   fprintf(stderr, "musb_open: usb_claim_interface() error %d (%s)\n", status,
  185.                      strerror(-status));
  186.  
  187. #ifdef _MSC_VER
  188.                   fprintf(stderr,
  189.                      "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
  190.                      vendor, product, instance);
  191. #else
  192.                   fprintf(stderr,
  193.                      "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",
  194.                      vendor, product, instance, bus->dirname, dev->filename);
  195. #endif
  196.  
  197.                   return MUSB_ACCESS_ERROR;
  198.                }
  199.  
  200.                *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE));
  201.                (*musb_interface)->dev = udev;
  202.                (*musb_interface)->usb_configuration = configuration;
  203.                (*musb_interface)->usb_interface     = usbinterface;
  204.                return MUSB_SUCCESS;
  205.             }
  206.  
  207.             count++;
  208.          }
  209.    
  210.    return MUSB_NOT_FOUND;
  211.    
  212. #elif defined(HAVE_LIBUSB10)
  213.    
  214.    static int first_call = 1;
  215.  
  216.    libusb_device **dev_list;
  217.    libusb_device_handle *dev;
  218.    struct libusb_device_descriptor desc;
  219.    
  220.    int status, i, n;
  221.    int count = 0;
  222.    
  223.    if (first_call) {
  224.       first_call = 0;
  225.       libusb_init(NULL);
  226.       // libusb_set_debug(NULL, 3);
  227.    }
  228.      
  229.    n = libusb_get_device_list(NULL, &dev_list);
  230.    
  231.    for (i=0 ; i<n ; i++) {
  232.       status = libusb_get_device_descriptor(dev_list[i], &desc);
  233.       if (desc.idVendor == vendor && desc.idProduct == product) {
  234.          if (count == instance) {
  235.             status = libusb_open(dev_list[i], &dev);
  236.             if (status < 0) {
  237.                fprintf(stderr, "musb_open: libusb_open() error %d\n", status);
  238.                return MUSB_ACCESS_ERROR;
  239.             }
  240.  
  241.             status = libusb_set_configuration(dev, configuration);
  242.             if (status < 0) {
  243.                fprintf(stderr, "musb_open: usb_set_configuration() error %d\n", status);
  244.                fprintf(stderr,
  245.                        "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",
  246.                        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]));
  247.                return MUSB_ACCESS_ERROR;
  248.             }
  249.            
  250.             /* see if we have write access */
  251.             status = libusb_claim_interface(dev, usbinterface);
  252.             if (status < 0) {
  253.                fprintf(stderr, "musb_open: libusb_claim_interface() error %d\n", status);
  254.                
  255. #ifdef _MSC_VER
  256.                fprintf(stderr,
  257.                        "musb_open: Found USB device 0x%04x:0x%04x instance %d, but cannot initialize it:\nDevice is probably used by another program\n",
  258.                        vendor, product, instance);
  259. #else
  260.                fprintf(stderr,
  261.                        "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",
  262.                        vendor, product, instance, libusb_get_bus_number(dev_list[i]), libusb_get_device_address(dev_list[i]));
  263. #endif
  264.                
  265.                return MUSB_ACCESS_ERROR;
  266.             }
  267.  
  268.             *musb_interface = (MUSB_INTERFACE*)calloc(1, sizeof(MUSB_INTERFACE));
  269.             (*musb_interface)->dev = dev;
  270.             (*musb_interface)->usb_configuration = configuration;
  271.             (*musb_interface)->usb_interface     = usbinterface;
  272.             return MUSB_SUCCESS;
  273.  
  274.          }
  275.          count++;
  276.       }
  277.    }
  278.    
  279.    libusb_free_device_list(dev_list, 1);
  280.    
  281.    return MUSB_NOT_FOUND;
  282.      
  283. #elif defined(OS_DARWIN)
  284.    
  285.    kern_return_t status;
  286.    io_iterator_t iter;
  287.    io_service_t service;
  288.    IOCFPlugInInterface **plugin;
  289.    SInt32 score;
  290.    IOUSBDeviceInterface **device;
  291.    UInt16 xvendor, xproduct;
  292.    int count = 0;
  293.  
  294.    *musb_interface = calloc(1, sizeof(MUSB_INTERFACE));
  295.    
  296.    status = IORegistryCreateIterator(kIOMasterPortDefault, kIOUSBPlane, kIORegistryIterateRecursively, &iter);
  297.    assert(status == kIOReturnSuccess);
  298.  
  299.    while ((service = IOIteratorNext(iter))) {
  300.       status =
  301.           IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
  302.                                             &plugin, &score);
  303.       assert(status == kIOReturnSuccess);
  304.  
  305.       status = IOObjectRelease(service);
  306.       assert(status == kIOReturnSuccess);
  307.  
  308.       status =
  309.           (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (void *) &device);
  310.       assert(status == kIOReturnSuccess);
  311.  
  312.       status = (*plugin)->Release(plugin);
  313.  
  314.       status = (*device)->GetDeviceVendor(device, &xvendor);
  315.       assert(status == kIOReturnSuccess);
  316.       status = (*device)->GetDeviceProduct(device, &xproduct);
  317.       assert(status == kIOReturnSuccess);
  318.  
  319.       //fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x\n", xvendor, xproduct);
  320.  
  321.       if (xvendor == vendor && xproduct == product) {
  322.          if (count == instance) {
  323.  
  324.             fprintf(stderr, "musb_open: Found USB device: vendor 0x%04x, product 0x%04x, instance %d\n", xvendor, xproduct, instance);
  325.  
  326.             status = (*device)->USBDeviceOpen(device);
  327.             fprintf(stderr, "musb_open: USBDeviceOpen status 0x%x\n", status);
  328.  
  329.             assert(status == kIOReturnSuccess);
  330.  
  331.             (*musb_interface)->usb_configuration = configuration;
  332.             (*musb_interface)->usb_interface     = usbinterface;
  333.             (*musb_interface)->device = (void*)device;
  334.             (*musb_interface)->interface = NULL;
  335.  
  336.             status = darwin_configure_device(*musb_interface);
  337.  
  338.             if (status == kIOReturnSuccess)
  339.                return MUSB_SUCCESS;
  340.  
  341.             fprintf(stderr, "musb_open: USB device exists, but configuration fails!");
  342.             return MUSB_NOT_FOUND;
  343.          }
  344.  
  345.          count++;
  346.       }
  347.  
  348.       (*device)->Release(device);
  349.    }
  350.  
  351.    return MUSB_NOT_FOUND;
  352. #elif defined(_MSC_VER)
  353.    GUID guid;
  354.    HDEVINFO hDevInfoList;
  355.    SP_DEVICE_INTERFACE_DATA deviceInfoData;
  356.    PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData;
  357.    ULONG predictedLength, requiredLength;
  358.    int status;
  359.    char device_name[256], str[256];
  360.  
  361.    *musb_interface = (MUSB_INTERFACE *)calloc(1, sizeof(MUSB_INTERFACE));
  362.  
  363.    guid = GUID_CLASS_MSCB_BULK;
  364.  
  365.    // Retrieve device list for GUID that has been specified.
  366.    hDevInfoList = SetupDiGetClassDevs(&guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
  367.  
  368.    status = FALSE;
  369.    if (hDevInfoList != NULL) {
  370.  
  371.       // Clear data structure
  372.       memset(&deviceInfoData, 0, sizeof(deviceInfoData));
  373.       deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  374.  
  375.       // retrieves a context structure for a device interface of a device information set.
  376.       if (SetupDiEnumDeviceInterfaces(hDevInfoList, 0, &guid, instance, &deviceInfoData)) {
  377.          // Must get the detailed information in two steps
  378.          // First get the length of the detailed information and allocate the buffer
  379.          // retrieves detailed information about a specified device interface.
  380.          functionClassDeviceData = NULL;
  381.  
  382.          predictedLength = requiredLength = 0;
  383.  
  384.          SetupDiGetDeviceInterfaceDetail(hDevInfoList, &deviceInfoData, NULL,   // Not yet allocated
  385.                                          0,     // Set output buffer length to zero
  386.                                          &requiredLength,       // Find out memory requirement
  387.                                          NULL);
  388.  
  389.          predictedLength = requiredLength;
  390.          functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(predictedLength);
  391.          functionClassDeviceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  392.  
  393.          // Second, get the detailed information
  394.          if (SetupDiGetDeviceInterfaceDetail(hDevInfoList,
  395.                                              &deviceInfoData, functionClassDeviceData,
  396.                                              predictedLength, &requiredLength, NULL)) {
  397.  
  398.             // Save the device name for subsequent pipe open calls
  399.             strcpy(device_name, functionClassDeviceData->DevicePath);
  400.             free(functionClassDeviceData);
  401.  
  402.             // Signal device found
  403.             status = TRUE;
  404.          } else
  405.             free(functionClassDeviceData);
  406.       }
  407.    }
  408.    // SetupDiDestroyDeviceInfoList() destroys a device information set
  409.    // and frees all associated memory.
  410.    SetupDiDestroyDeviceInfoList(hDevInfoList);
  411.  
  412.    if (status) {
  413.  
  414.       // Get the read handle
  415.       sprintf(str, "%s\\PIPE00", device_name);
  416.       (*musb_interface)->rhandle = CreateFile(str,
  417.                                     GENERIC_WRITE | GENERIC_READ,
  418.                                     FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
  419.                                     OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
  420.  
  421.       if ((*musb_interface)->rhandle == INVALID_HANDLE_VALUE)
  422.          return MUSB_ACCESS_ERROR;
  423.  
  424.       // Get the write handle
  425.       sprintf(str, "%s\\PIPE01", device_name);
  426.       (*musb_interface)->whandle = CreateFile(str,
  427.                                     GENERIC_WRITE | GENERIC_READ,
  428.                                     FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  429.  
  430.       if ((*musb_interface)->whandle == INVALID_HANDLE_VALUE)
  431.          return MUSB_ACCESS_ERROR;
  432.  
  433.       return MUSB_SUCCESS;
  434.    }
  435.      
  436.    return MUSB_NOT_FOUND;
  437. #endif
  438. }
  439.  
  440. int musb_set_altinterface(MUSB_INTERFACE *musb_interface, int index)
  441. {
  442. #if defined (HAVE_LIBUSB)
  443.    int status;
  444.  
  445.    status = usb_set_altinterface(musb_interface->dev, index);
  446.    if (status < 0)
  447.       fprintf(stderr, "musb_set_altinterface: usb_set_altinterface() error %d\n", status);
  448.  
  449.    return status;
  450. #else
  451.    return -1;
  452. #endif
  453. }
  454.  
  455. int musb_close(MUSB_INTERFACE *musb_interface)
  456. {
  457. #if defined(HAVE_LIBUSB)
  458.  
  459.    int status;
  460.    status = usb_release_interface(musb_interface->dev, musb_interface->usb_interface);
  461.    if (status < 0)
  462.       fprintf(stderr, "musb_close: usb_release_interface() error %d\n", status);
  463.    
  464. #ifdef OS_LINUX   // linux wants a reset, otherwise the device cannot be accessed next time
  465.    musb_reset(musb_interface);
  466. #endif
  467.  
  468.    status = usb_close(musb_interface->dev);
  469.    if (status < 0)
  470.       fprintf(stderr, "musb_close: usb_close() error %d\n", status);
  471.    
  472. #elif defined(HAVE_LIBUSB10)  
  473.  
  474.    int status;
  475.    status = libusb_release_interface(musb_interface->dev, musb_interface->usb_interface);
  476.    if (status < 0)
  477.       fprintf(stderr, "musb_close: libusb_release_interface() error %d\n", status);
  478.    
  479. #ifdef OS_LINUX   // linux wants a reset, otherwise the device cannot be accessed next time
  480.    musb_reset(musb_interface);
  481. #endif
  482.    
  483.    libusb_close(musb_interface->dev);
  484.  
  485. #elif defined(OS_DARWIN)
  486.  
  487.    IOReturn status;
  488.    IOUSBInterfaceInterface **interface = (IOUSBInterfaceInterface **)musb_interface->interface;
  489.  
  490.    status = (*interface)->USBInterfaceClose(interface);
  491.    if (status != kIOReturnSuccess)
  492.       fprintf(stderr, "musb_close: USBInterfaceClose() status %d 0x%x\n", status, status);
  493.  
  494.    status = (*interface)->Release(interface);
  495.    if (status != kIOReturnSuccess)
  496.       fprintf(stderr, "musb_close: USB Interface Release() status %d 0x%x\n", status, status);
  497.  
  498.    IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
  499.    status = (*device)->USBDeviceClose(device);
  500.    if (status != kIOReturnSuccess)
  501.       fprintf(stderr, "musb_close: USBDeviceClose() status %d 0x%x\n", status, status);
  502.  
  503.    status = (*device)->Release(device);
  504.    if (status != kIOReturnSuccess)
  505.       fprintf(stderr, "musb_close: USB Device Release() status %d 0x%x\n", status, status);
  506.  
  507. #elif defined(_MSC_VER)
  508.  
  509.    CloseHandle(musb_interface->rhandle);
  510.    CloseHandle(musb_interface->whandle);
  511.  
  512. #else
  513.    assert(!"musb_close() is not implemented");
  514. #endif
  515.  
  516.    /* free memory allocated in musb_open() */
  517.    free(musb_interface);
  518.    return 0;
  519. }
  520.  
  521. int musb_write(MUSB_INTERFACE *musb_interface, int endpoint, const void *buf, int count, int timeout)
  522. {
  523.    int n_written;
  524.  
  525. #if defined(HAVE_LIBUSB)
  526.    n_written = usb_bulk_write(musb_interface->dev, endpoint, (char*)buf, count, timeout);
  527.    if (n_written != count) {
  528.       fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, errno, strerror(errno));
  529.    }
  530. #elif defined(HAVE_LIBUSB10)
  531.    int status = libusb_bulk_transfer(musb_interface->dev, endpoint, (unsigned char*)buf, count, &n_written, timeout);
  532.    if (n_written != count) {
  533.       fprintf(stderr, "musb_write: requested %d, wrote %d, errno %d (%s)\n", count, n_written, status, strerror(status));
  534.    }
  535. #elif defined(OS_DARWIN)
  536.    IOReturn status;
  537.    IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
  538.    status = (*interface)->WritePipeTO(interface, endpoint, buf, count, 0, timeout);
  539.    if (status != 0) {
  540.       fprintf(stderr, "musb_write: WritePipe() status %d 0x%x\n", status, status);
  541.       return -1;
  542.    }
  543.    n_written = count;
  544. #elif defined(_MSC_VER)
  545.    WriteFile(musb_interface->whandle, buf, count, &n_written, NULL);
  546. #endif
  547.  
  548.    //fprintf(stderr, "musb_write(ep %d, %d bytes) (%s) returns %d\n", endpoint, count, buf, n_written);
  549.  
  550.    return n_written;
  551. }
  552.  
  553. int musb_read(MUSB_INTERFACE *musb_interface, int endpoint, void *buf, int count, int timeout)
  554. {
  555.    int n_read = 0;
  556.  
  557. #if defined(HAVE_LIBUSB)
  558.  
  559.    n_read = usb_bulk_read(musb_interface->dev, endpoint | 0x80, (char*)buf, count, timeout);
  560.    /* errors should be handled in upper layer ....
  561.    if (n_read <= 0) {
  562.       fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, errno, strerror(errno));
  563.    }
  564.    */
  565.  
  566. #elif defined(HAVE_LIBUSB10)
  567.    
  568.    libusb_bulk_transfer(musb_interface->dev, endpoint | 0x80, (unsigned char*)buf, count, &n_read, timeout);
  569.    /* errors should be handled in upper layer ....
  570.     if (n_read <= 0) {
  571.     fprintf(stderr, "musb_read: requested %d, read %d, errno %d (%s)\n", count, n_read, status, strerror(status));
  572.     }
  573.     */
  574.    
  575. #elif defined(OS_DARWIN)
  576.  
  577.    UInt32 xcount = count;
  578.    IOReturn status;
  579.    IOUSBInterfaceInterface182 **interface = (IOUSBInterfaceInterface182 **)musb_interface->interface;
  580.  
  581.    status = (*interface)->ReadPipeTO(interface, endpoint, buf, &xcount, 0, timeout);
  582.    if (status != kIOReturnSuccess) {
  583.       fprintf(stderr, "musb_read: requested %d, read %d, ReadPipe() status %d 0x%x (%s)\n", count, n_read, status, status, strerror(status));
  584.       return -1;
  585.    }
  586.  
  587.    n_read = xcount;
  588.  
  589. #elif defined(_MSC_VER)
  590.  
  591.    OVERLAPPED overlapped;
  592.    int status;
  593.  
  594.    memset(&overlapped, 0, sizeof(overlapped));
  595.    overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  596.    n_read = 0;
  597.  
  598.    status = ReadFile(musb_interface->rhandle, buf, count, &n_read, &overlapped);
  599.    
  600.    if (!status) {
  601.  
  602.       status = GetLastError();
  603.       if (status != ERROR_IO_PENDING)
  604.          return 0;
  605.  
  606.       /* wait for completion with timeout */
  607.       status = WaitForSingleObject(overlapped.hEvent, timeout);
  608.       if (status == WAIT_TIMEOUT)
  609.          CancelIo(musb_interface->rhandle);
  610.       else
  611.          GetOverlappedResult(musb_interface->rhandle, &overlapped, &n_read, FALSE);
  612.    }
  613.  
  614.    CloseHandle(overlapped.hEvent);
  615.  
  616. #endif
  617.  
  618.    //fprintf(stderr, "musb_read(ep %d, %d bytes) returns %d (%s)\n", endpoint, count, n_read, buf);
  619.  
  620.    return n_read;
  621. }
  622.  
  623. int musb_reset(MUSB_INTERFACE *musb_interface)
  624. {
  625. #if defined(HAVE_LIBUSB)
  626.  
  627.    /* Causes re-enumeration: After calling usb_reset, the device will need
  628.       to re-enumerate and thusly, requires you to find the new device and
  629.       open a new handle. The handle used to call usb_reset will no longer work */
  630.  
  631.    int status;
  632.    status = usb_reset(musb_interface->dev);
  633.    if (status < 0)
  634.       fprintf(stderr, "musb_reset: usb_reset() status %d\n", status);
  635.  
  636. #elif defined(HAVE_LIBUSB10)
  637.    
  638.    int status;
  639.    status = libusb_reset_device(musb_interface->dev);
  640.    if (status < 0)
  641.       fprintf(stderr, "musb_reset: usb_reset() status %d\n", status);
  642.    
  643. #elif defined(OS_DARWIN)
  644.  
  645.    IOReturn status;
  646.    IOUSBDeviceInterface **device = (IOUSBDeviceInterface**)musb_interface->device;
  647.  
  648.    status = (*device)->ResetDevice(device);
  649.    fprintf(stderr, "musb_reset: ResetDevice() status 0x%x\n", status);
  650.  
  651.    status = darwin_configure_device(musb_interface);
  652.    assert(status == kIOReturnSuccess);
  653.  
  654. #elif defined(_MSC_VER)
  655.  
  656. #define IOCTL_BULKUSB_RESET_DEVICE          CTL_CODE(FILE_DEVICE_UNKNOWN,     \
  657.                                                      1,                       \
  658.                                                      METHOD_BUFFERED,         \
  659.                                                      FILE_ANY_ACCESS)
  660. #define IOCTL_BULKUSB_RESET_PIPE            CTL_CODE(FILE_DEVICE_UNKNOWN,     \
  661.                                                      2,                       \
  662.                                                      METHOD_BUFFERED,         \
  663.                                                      FILE_ANY_ACCESS)
  664.  
  665.    int status, n_bytes;
  666.  
  667.    status =  DeviceIoControl(musb_interface->rhandle,
  668.                   IOCTL_BULKUSB_RESET_DEVICE,
  669.                   NULL, 0, NULL, 0, &n_bytes, NULL);
  670.    status =  DeviceIoControl(musb_interface->whandle,
  671.                   IOCTL_BULKUSB_RESET_DEVICE,
  672.                   NULL, 0, NULL, 0, &n_bytes, NULL);
  673.    status =  DeviceIoControl(musb_interface->rhandle,
  674.                   IOCTL_BULKUSB_RESET_PIPE,
  675.                   NULL, 0, NULL, 0, &n_bytes, NULL);
  676.    status =  DeviceIoControl(musb_interface->whandle,
  677.                   IOCTL_BULKUSB_RESET_PIPE,
  678.                   NULL, 0, NULL, 0, &n_bytes, NULL);
  679.    return status;
  680.  
  681. #endif
  682.    return 0;
  683. }
  684.  
  685. int musb_get_device(MUSB_INTERFACE *usb_interface)
  686. {
  687. #ifdef HAVE_LIBUSB
  688.    struct usb_device_descriptor d;
  689.    usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d));
  690.    return d.bcdDevice;
  691. #elif HAVE_LIBUSB10
  692.    struct libusb_device_descriptor d;
  693.    libusb_get_descriptor(usb_interface->dev, LIBUSB_DT_DEVICE, 0, (unsigned char *)&d, sizeof(d));
  694.    return d.bcdDevice;
  695. #else
  696.    return 0;
  697. #endif
  698. }
  699.  
  700. /* end */
  701.