bool LJUSB_IsHandleValid(HANDLE hDevice) { uint8_t config = 0; int r = 1; if (LJUSB_isNullHandle(hDevice)) { #if LJ_DEBUG fprintf(stderr, "LJUSB_IsHandleValid: returning false. hDevice is NULL.\n"); #endif return false; } // If we can call get configuration without getting an error, // the handle is still valid. // Note that libusb_get_configuration() will return a cached value, // so we replace this call // r = libusb_get_configuration(hDevice, &config); // to the actual control tranfser, from the libusb source r = libusb_control_transfer(hDevice, LIBUSB_ENDPOINT_IN, LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, &config, 1, LJ_LIBUSB_TIMEOUT_DEFAULT); if (r < 0) { #if LJ_DEBUG fprintf(stderr, "LJUSB_IsHandleValid: returning false. Return value from libusb_get_configuration was: %d\n", r); #endif LJUSB_libusbError(r); return false; } else { #if LJ_DEBUG fprintf(stderr, "LJUSB_IsHandleValid: returning true.\n"); #endif return true; } }
unsigned int LJUSB_GetDevCount(unsigned long ProductID) { libusb_device **devs = NULL; ssize_t cnt = 0; int r = 1; unsigned int i = 0; unsigned int ljFoundCount = 0; if (!gIsLibUSBInitialized) { r = libusb_init(&gLJContext); if (r < 0) { fprintf(stderr, "failed to initialize libusb\n"); LJUSB_libusbError(r); return 0; } gIsLibUSBInitialized = true; } cnt = libusb_get_device_list(gLJContext, &devs); if (cnt < 0) { fprintf(stderr, "failed to get device list\n"); LJUSB_libusbError(cnt); LJUSB_libusb_exit(); return 0; } libusb_device *dev = NULL; // Loop over all USB devices and count the ones with the LabJack // vendor ID and the passed in product ID. while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor\n"); LJUSB_libusbError(r); LJUSB_libusb_exit(); return 0; } if (LJ_VENDOR_ID == desc.idVendor && ProductID == desc.idProduct) { ljFoundCount++; } } libusb_free_device_list(devs, 1); return ljFoundCount; }
unsigned long LJUSB_GetHIDReportDescriptor(HANDLE hDevice, BYTE *pBuff, unsigned long count) { libusb_device *dev = NULL; struct libusb_device_descriptor desc; int r = 0; if (LJUSB_isNullHandle(hDevice)) { #if LJ_DEBUG fprintf(stderr, "LJUSB_GetHIDReportDescriptor: returning 0. hDevice is NULL.\n"); #endif return 0; } //Determine the device from handle. dev = libusb_get_device(hDevice); r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { LJUSB_libusbError(r); return 0; } if (desc.idProduct != U12_PRODUCT_ID) { //Only U12 supported errno = EINVAL; return 0; } r = libusb_control_transfer(hDevice, 0x81, 0x06, 0x2200, 0x0000, pBuff, count, LJ_LIBUSB_TIMEOUT_DEFAULT); if (r < 0) { LJUSB_libusbError(r); return 0; } #if LJ_DEBUG fprintf(stderr, "LJUSB_GetHIDReportDescriptor: returning control transferred = %d.\n", r); #endif return r; }
unsigned long LJUSB_GetHIDReportDescriptor(HANDLE hDevice, BYTE *pBuff, unsigned long count) { libusb_device *dev; struct libusb_device_descriptor desc; int r = 0; if (LJUSB_IsHandleValid(hDevice) == false) { if (LJ_DEBUG) { fprintf(stderr, "Calling LJUSB_GetHIDReportDescriptor returning 0 because handle is invalid. errno = %d.\n", errno); } return 0; } //Determine the device from handle. dev = libusb_get_device(hDevice); r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { LJUSB_libusbError(r); return 0; } if (desc.idProduct != U12_PRODUCT_ID) { //Only U12 supported errno = EINVAL; return 0; } r = libusb_control_transfer(hDevice, 0x81 , 0x06, 0x2200, 0x0000, pBuff, count, LJ_LIBUSB_TIMEOUT_DEFAULT); if (r < 0) { LJUSB_libusbError(r); return 0; } if (LJ_DEBUG) { fprintf(stderr, "LJUSB_GetHIDReportDescriptor: returning control transferred = %d.\n", r); } return r; }
bool LJUSB_ResetConnection(HANDLE hDevice) { int r; if (LJUSB_isNullHandle(hDevice)) { #if LJ_DEBUG fprintf(stderr, "LJUSB_ResetConnection: returning false. hDevice is NULL.\n"); #endif return false; } r = libusb_reset_device(hDevice); if (r != 0) { LJUSB_libusbError(r); return false; } return true; //Success }
unsigned short LJUSB_GetDeviceDescriptorReleaseNumber(HANDLE hDevice) { libusb_device *dev = NULL; struct libusb_device_descriptor desc; int r = 0; if (LJUSB_isNullHandle(hDevice)) { #if LJ_DEBUG fprintf(stderr, "LJUSB_GetDeviceDescriptorReleaseNumber: returning 0. hDevice is NULL.\n"); #endif return 0; } dev = libusb_get_device(hDevice); r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { LJUSB_libusbError(r); return 0; } return desc.bcdDevice; }
unsigned short LJUSB_GetDeviceDescriptorReleaseNumber(HANDLE hDevice) { libusb_device *dev; struct libusb_device_descriptor desc; int r = 0; if (LJUSB_IsHandleValid(hDevice) == false) { if (LJ_DEBUG) { fprintf(stderr, "Calling LJUSB_GetDeviceDescriptorReleaseNumber returning 0 because handle is invalid. errno = %d.\n", errno); } return 0; } dev = libusb_get_device(hDevice); r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { LJUSB_libusbError(r); return 0; } return desc.bcdDevice; }
// Automatically uses the correct endpoint and transfer method (bulk or interrupt) static unsigned long LJUSB_SetupTransfer(HANDLE hDevice, BYTE *pBuff, unsigned long count, unsigned int timeout, enum LJUSB_TRANSFER_OPERATION operation) { libusb_device *dev = NULL; struct libusb_device_descriptor desc; bool isBulk = true; unsigned char endpoint = 0; int r = 0; #if LJ_DEBUG fprintf(stderr, "Calling LJUSB_SetupTransfer with count = %lu and operation = %d.\n", count, operation); #endif if (LJUSB_isNullHandle(hDevice)) { #if LJ_DEBUG fprintf(stderr, "LJUSB_SetupTransfer: returning 0. hDevice is NULL.\n"); #endif return 0; } //First determine the device from handle. dev = libusb_get_device(hDevice); r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { LJUSB_libusbError(r); return 0; } switch (desc.idProduct) { /* These devices use bulk transfers */ case UE9_PRODUCT_ID: isBulk = true; switch (operation) { case LJUSB_WRITE: endpoint = UE9_PIPE_EP1_OUT; break; case LJUSB_READ: endpoint = UE9_PIPE_EP1_IN; break; case LJUSB_STREAM: endpoint = UE9_PIPE_EP2_IN; break; default: errno = EINVAL; return 0; } break; case U3_PRODUCT_ID: isBulk = true; switch (operation) { case LJUSB_WRITE: endpoint = U3_PIPE_EP1_OUT; break; case LJUSB_READ: endpoint = U3_PIPE_EP2_IN; break; case LJUSB_STREAM: endpoint = U3_PIPE_EP3_IN; break; default: errno = EINVAL; return 0; } break; case U6_PRODUCT_ID: isBulk = true; switch (operation) { case LJUSB_WRITE: endpoint = U6_PIPE_EP1_OUT; break; case LJUSB_READ: endpoint = U6_PIPE_EP2_IN; break; case LJUSB_STREAM: endpoint = U6_PIPE_EP3_IN; break; default: errno = EINVAL; return 0; } break; case BRIDGE_PRODUCT_ID: isBulk = true; switch (operation) { case LJUSB_WRITE: endpoint = BRIDGE_PIPE_EP1_OUT; break; case LJUSB_READ: endpoint = BRIDGE_PIPE_EP2_IN; break; case LJUSB_STREAM: endpoint = BRIDGE_PIPE_EP3_IN; break; default: errno = EINVAL; return 0; } break; case T7_PRODUCT_ID: isBulk = true; switch (operation) { case LJUSB_WRITE: endpoint = T7_PIPE_EP1_OUT; break; case LJUSB_READ: endpoint = T7_PIPE_EP2_IN; break; case LJUSB_STREAM: endpoint = T7_PIPE_EP3_IN; break; default: errno = EINVAL; return 0; } break; case DIGIT_PRODUCT_ID: isBulk = true; switch (operation) { case LJUSB_WRITE: endpoint = DIGIT_PIPE_EP1_OUT; break; case LJUSB_READ: endpoint = DIGIT_PIPE_EP2_IN; break; case LJUSB_STREAM: default: //No streaming interface errno = EINVAL; return 0; } break; /* These devices use interrupt transfers */ case U12_PRODUCT_ID: isBulk = false; switch (operation) { case LJUSB_READ: endpoint = U12_PIPE_EP1_IN; break; case LJUSB_WRITE: endpoint = U12_PIPE_EP2_OUT; break; case LJUSB_STREAM: endpoint = U12_PIPE_EP0; break; default: errno = EINVAL; return 0; } break; default: // Error, not a labjack device errno = EINVAL; return 0; } return LJUSB_DoTransfer(hDevice, endpoint, pBuff, count, timeout, isBulk); }
static unsigned long LJUSB_DoTransfer(HANDLE hDevice, unsigned char endpoint, BYTE *pBuff, unsigned long count, unsigned int timeout, bool isBulk) { int r = 0; int transferred = 0; #if LJ_DEBUG fprintf(stderr, "Calling LJUSB_DoTransfer with endpoint = 0x%x, count = %lu, and isBulk = %d.\n", endpoint, count, isBulk); #endif if (LJUSB_isNullHandle(hDevice)) { #if LJ_DEBUG fprintf(stderr, "LJUSB_DoTransfer: returning 0. hDevice is NULL.\n"); #endif return 0; } if (isBulk && endpoint != 1 && endpoint < 0x81 ) { fprintf(stderr, "LJUSB_DoTransfer warning: Got endpoint = %d, however this not a known endpoint. Please verify you are using the header file provided in /usr/local/include/labjackusb.h and not an older header file.\n", endpoint); } if (isBulk) { r = libusb_bulk_transfer(hDevice, endpoint, pBuff, (int)count, &transferred, timeout); } else { if (endpoint == 0) { //HID feature request. r = libusb_control_transfer(hDevice, 0xa1 , 0x01, 0x0300, 0x0000, pBuff, count, timeout); if (r < 0) { LJUSB_libusbError(r); return 0; } #if LJ_DEBUG fprintf(stderr, "LJUSB_DoTransfer: returning control transferred = %d.\n", r); #endif return r; } else { r = libusb_interrupt_transfer(hDevice, endpoint, pBuff, count, &transferred, timeout); } } if (r == LIBUSB_ERROR_TIMEOUT) { //Timeout occured but may have received partial data. Setting errno but //returning the number of bytes transferred which may be > 0. #if LJ_DEBUG fprintf(stderr, "LJUSB_DoTransfer: Transfer timed out. Returning.\n"); #endif errno = ETIMEDOUT; return transferred; } else if (r != 0) { LJUSB_libusbError(r); return 0; } #if LJ_DEBUG fprintf(stderr, "LJUSB_DoTransfer: returning transferred = %d.\n", transferred); #endif return transferred; }
int LJUSB_OpenAllDevices(HANDLE* devHandles, UINT* productIds, UINT maxDevices) { libusb_device **devs = NULL, *dev = NULL; struct libusb_device_handle *devh = NULL; struct libusb_device_descriptor desc; ssize_t cnt = 0; int r = 1; unsigned int i = 0, ljFoundCount = 0; HANDLE handle = NULL; if (!gIsLibUSBInitialized) { r = libusb_init(&gLJContext); if (r < 0) { fprintf(stderr, "failed to initialize libusb\n"); LJUSB_libusbError(r); return -1; } gIsLibUSBInitialized = true; } cnt = libusb_get_device_list(gLJContext, &devs); if (cnt < 0) { fprintf(stderr, "failed to get device list\n"); LJUSB_libusbError(cnt); LJUSB_libusb_exit(); return -1; } while ((dev = devs[i++]) != NULL) { #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: calling libusb_get_device_descriptor\n"); #endif r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor"); LJUSB_libusbError(r); LJUSB_libusb_exit(); return -1; } if (LJ_VENDOR_ID == desc.idVendor) { // Found a LabJack device r = libusb_open(dev, &devh); if (r < 0) { LJUSB_libusbError(r); continue; } // Test if the kernel driver has the device. // Should only be true for HIDs. if (libusb_kernel_driver_active(devh, 0) ) { #if LJ_DEBUG fprintf(stderr, "Kernel Driver was active, detaching...\n"); #endif // Detaches U12s from kernel driver. r = libusb_detach_kernel_driver(devh, 0); // Check the return value if ( r != 0 ) { fprintf(stderr, "failed to detach from kernel driver. Error Number: %i", r); libusb_close(devh); continue; } } r = libusb_claim_interface(devh, 0); if (r < 0) { //LJUSB_libusbError(r); libusb_close(devh); continue; } handle = (HANDLE) devh; if (handle == NULL) { // Not a valid handle continue; } else if (ljFoundCount < maxDevices) { if (LJUSB_isMinFirmware(handle, desc.idProduct)) { devHandles[ljFoundCount] = handle; productIds[ljFoundCount] = desc.idProduct; ljFoundCount++; } else { // Not high enough firmware, keep moving. libusb_close(devh); ljFoundCount--; } } else { // Too many devices have been found. libusb_close(devh); break; } } } libusb_free_device_list(devs, 1); return ljFoundCount; }
HANDLE LJUSB_OpenDevice(UINT DevNum, unsigned int dwReserved, unsigned long ProductID) { (void)dwReserved; libusb_device **devs = NULL, *dev = NULL; struct libusb_device_handle *devh = NULL; struct libusb_device_descriptor desc; ssize_t cnt = 0; int r = 1; unsigned int i = 0; unsigned int ljFoundCount = 0; HANDLE handle = NULL; if (!gIsLibUSBInitialized) { r = libusb_init(&gLJContext); if (r < 0) { fprintf(stderr, "failed to initialize libusb\n"); LJUSB_libusbError(r); return NULL; } gIsLibUSBInitialized = true; } cnt = libusb_get_device_list(gLJContext, &devs); if (cnt < 0) { fprintf(stderr, "failed to get device list\n"); LJUSB_libusbError(cnt); LJUSB_libusb_exit(); return NULL; } while ((dev = devs[i++]) != NULL) { #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: calling libusb_get_device_descriptor\n"); #endif r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor"); LJUSB_libusbError(r); LJUSB_libusb_exit(); return NULL; } if (LJ_VENDOR_ID == desc.idVendor && ProductID == desc.idProduct) { ljFoundCount++; if (ljFoundCount == DevNum) { // Found the one requested r = libusb_open(dev, &devh); if (r < 0) { LJUSB_libusbError(r); return NULL; } // Test if the kernel driver has the device. // Should only be true for HIDs. if (libusb_kernel_driver_active(devh, 0)) { #if LJ_DEBUG fprintf(stderr, "Kernel Driver was active, detaching...\n"); #endif // Detaches U12s from kernel driver. r = libusb_detach_kernel_driver(devh, 0); // Check the return value if ( r != 0 ) { fprintf(stderr, "failed to detach from kernel driver. Error Number: %i", r); return NULL; } } r = libusb_claim_interface(devh, 0); if (r < 0) { LJUSB_libusbError(r); libusb_close(devh); return NULL; } handle = (HANDLE) devh; #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: Found handle for product ID %ld\n", ProductID); #endif break; } } } libusb_free_device_list(devs, 1); if (handle != NULL) { //We found a device, now check if it meets the minimum firmware requirement if (!LJUSB_isMinFirmware(handle, ProductID)) { //Does not meet the requirement. Close device and return an invalid handle. LJUSB_CloseDevice(handle); return NULL; } } #if LJ_DEBUG fprintf(stderr, "LJUSB_OpenDevice: Returning handle\n"); #endif return handle; }
unsigned int LJUSB_GetDevCounts(UINT *productCounts, UINT * productIds, UINT n) { libusb_device **devs = NULL, *dev = NULL; ssize_t cnt = 0; int r = 1; unsigned int i = 0; unsigned int u3ProductCount = 0, u6ProductCount = 0; unsigned int ue9ProductCount = 0, u12ProductCount = 0; unsigned int bridgeProductCount = 0, t7ProductCount = 0; unsigned int digitProductCount = 0, allProductCount = 0; if (!gIsLibUSBInitialized) { r = libusb_init(&gLJContext); if (r < 0) { fprintf(stderr, "failed to initialize libusb\n"); LJUSB_libusbError(r); return 0; } gIsLibUSBInitialized = true; } cnt = libusb_get_device_list(gLJContext, &devs); if (cnt < 0) { fprintf(stderr, "failed to get device list\n"); LJUSB_libusbError(cnt); LJUSB_libusb_exit(); return 0; } // Loop over all USB devices and count the ones with the LabJack // vendor ID and the passed in product ID. while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { fprintf(stderr, "failed to get device descriptor\n"); LJUSB_libusbError(r); LJUSB_libusb_exit(); return 0; } if (LJ_VENDOR_ID == desc.idVendor) { switch (desc.idProduct) { case U3_PRODUCT_ID: u3ProductCount++; break; case U6_PRODUCT_ID: u6ProductCount++; break; case UE9_PRODUCT_ID: ue9ProductCount++; break; case U12_PRODUCT_ID: u12ProductCount++; break; case BRIDGE_PRODUCT_ID: bridgeProductCount++; break; case T7_PRODUCT_ID: t7ProductCount++; break; case DIGIT_PRODUCT_ID: digitProductCount++; break; } } } libusb_free_device_list(devs, 1); for (i = 0; i < n; i++) { switch (i) { case 0: productCounts[i] = u3ProductCount; productIds[i] = U3_PRODUCT_ID; allProductCount += u3ProductCount; break; case 1: productCounts[i] = u6ProductCount; productIds[i] = U6_PRODUCT_ID; allProductCount += u6ProductCount; break; case 2: productCounts[i] = ue9ProductCount; productIds[i] = UE9_PRODUCT_ID; allProductCount += ue9ProductCount; break; case 3: productCounts[i] = u12ProductCount; productIds[i] = U12_PRODUCT_ID; allProductCount += u12ProductCount; break; case 4: productCounts[i] = bridgeProductCount; productIds[i] = BRIDGE_PRODUCT_ID; allProductCount += bridgeProductCount; break; case 5: productCounts[i] = t7ProductCount; productIds[i] = T7_PRODUCT_ID; allProductCount += t7ProductCount; break; case 6: productCounts[i] = digitProductCount; productIds[i] = DIGIT_PRODUCT_ID; allProductCount += digitProductCount; break; } } return allProductCount; }