/* * USB routines of Cypress USB Serial * Copyright (C) 2013 Cypress Semiconductor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "CyUSBCommon.h" static bool glDriverInit = false; static libusb_device **glDeviceList; static UINT32 glNumDevices; /*The API initializes the Libusb library */ pthread_mutex_t criticalSection; CY_RETURN_STATUS CyLibraryInit () { UINT32 rStatus; rStatus = libusb_init (NULL); if (glDriverInit != true){ if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Driver Init Failed ...\n"); return CY_ERROR_DRIVER_INIT_FAILED; } glNumDevices = libusb_get_device_list (NULL, &glDeviceList); if (glNumDevices < 0){ CY_DEBUG_PRINT_ERROR ("CY:Building device list Failed ...\n"); glNumDevices = -1; return CY_ERROR_DRIVER_INIT_FAILED; } pthread_mutex_init (&criticalSection, NULL); glDriverInit = true; return CY_SUCCESS; } else{ CY_DEBUG_PRINT_ERROR ("CY:Error ... library already initialized \n"); return CY_ERROR_DRIVER_INIT_FAILED; } } /* This API needs to be called after Calling CyGetListofDevices. */ CY_RETURN_STATUS CyLibraryExit () { if (glDriverInit == true){ if (glNumDevices >= 0) libusb_free_device_list (glDeviceList, 1); libusb_exit (NULL); glDriverInit = false; pthread_mutex_destroy (&criticalSection); return CY_SUCCESS; } CY_DEBUG_PRINT_ERROR ("CY:Error ... Library not initialized \n"); return CY_ERROR_REQUEST_FAILED; } /* * This function Gets the number of all the devices currently * Connected to the host (It includes Cypress Device as well as * no Cypress Devices connected) */ CY_RETURN_STATUS CyGetListofDevices ( UINT8 *numDevices ) { // Use this variable to call libusb_close and exit of the application if (numDevices == NULL) return CY_ERROR_INVALID_PARAMETER; if (!glDriverInit){ CY_DEBUG_PRINT_ERROR ("CY:Error Library not initialised ...function is %s\n", __func__); return CY_ERROR_REQUEST_FAILED; } pthread_mutex_lock (&criticalSection); libusb_free_device_list (glDeviceList, 1); glNumDevices = (*numDevices) = libusb_get_device_list (NULL, &glDeviceList); pthread_mutex_unlock (&criticalSection); if (glNumDevices < 0){ CY_DEBUG_PRINT_ERROR ("CY:Building device list Failed ...function is %s\n", __func__); glNumDevices = -1; (*numDevices) = -1; return CY_ERROR_REQUEST_FAILED; } return CY_SUCCESS; } /* This function gets all the neccessary info such as VID,PID, String Descriptors and if is a cypress serial device you will get the info on class and device type */ CY_RETURN_STATUS CyGetDeviceInfo ( UINT8 deviceNumber, CY_DEVICE_INFO *deviceInfo ) { struct libusb_device_descriptor deviceDesc; UINT32 rStatus, numInterfaces; UINT8 iManufacturer, iProduct, iSerial; libusb_device *usbDevice;; struct libusb_config_descriptor *configDesc; libusb_device_handle *devHandle; // Get the list of descriptor info for the device if (glDriverInit == false){ CY_DEBUG_PRINT_ERROR ("CY:Error Library not initialised ...function is %s\n", __func__); return CY_ERROR_REQUEST_FAILED; } if (deviceInfo == NULL) return CY_ERROR_INVALID_PARAMETER; pthread_mutex_lock (&criticalSection); if (deviceNumber >= glNumDevices){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid device number... \n"); pthread_mutex_unlock (&criticalSection); return CY_ERROR_INVALID_PARAMETER; } usbDevice = glDeviceList[deviceNumber]; rStatus = libusb_get_device_descriptor (usbDevice, &deviceDesc); if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error ... unable to retrieve device descriptor \n"); pthread_mutex_unlock (&criticalSection); return CY_ERROR_DEVICE_INFO_FETCH_FAILED; } deviceInfo->vidPid.vid = deviceDesc.idVendor; deviceInfo->vidPid.pid = deviceDesc.idProduct; // Get the all the index of the String descriptors so that it can be used // to retrieve the string descriptor info. iManufacturer = deviceDesc.iManufacturer; iProduct = deviceDesc.iProduct; iSerial = deviceDesc.iSerialNumber; //Get the Device handle so that we can communicate with the device retreiving // descriptor info deviceInfo->manufacturerName[0] = '\0'; deviceInfo->productName[0] = '\0'; deviceInfo->serialNum[0] = '\0'; rStatus = libusb_open (usbDevice, &devHandle); if (rStatus == LIBUSB_ERROR_ACCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error ...Insufficient permission... Libusb error is %d \n", rStatus); pthread_mutex_unlock (&criticalSection); return CY_ERROR_ACCESS_DENIED; } else if (rStatus != CY_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in opening the device... Libusb error is %d \n", rStatus); pthread_mutex_unlock (&criticalSection); return CY_ERROR_DEVICE_INFO_FETCH_FAILED; } if (iManufacturer > 0){ rStatus = libusb_get_string_descriptor_ascii (devHandle, iManufacturer, deviceInfo->manufacturerName, 256); if (rStatus <= LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in Getting Manufacturer name Error is <%x> \n", rStatus); } } if (iProduct > 0){ rStatus = libusb_get_string_descriptor_ascii (devHandle, iProduct, deviceInfo->productName, 256); if (rStatus <= LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in Getting product name Error is <%d> \n", rStatus); } } if (iSerial > 0){ rStatus = libusb_get_string_descriptor_ascii (devHandle, iSerial, deviceInfo->serialNum, 256); if (rStatus <= LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in Getting Serial name <%d>\n", rStatus); } } rStatus = libusb_get_config_descriptor (usbDevice, 0, &configDesc); if (rStatus == LIBUSB_SUCCESS){ UINT32 index_i = 0; const struct libusb_interface *interface; numInterfaces = configDesc->bNumInterfaces; deviceInfo->numInterfaces = numInterfaces; interface = configDesc->interface; while ((numInterfaces) && (index_i < CY_MAX_DEVICE_INTERFACE)){ deviceInfo->deviceClass[index_i] = (CY_DEVICE_CLASS)interface->altsetting->bInterfaceClass; if (deviceInfo->deviceClass[index_i] == CY_CLASS_VENDOR){ deviceInfo->deviceType[index_i] = (CY_DEVICE_CLASS)interface->altsetting->bInterfaceSubClass; } else deviceInfo->deviceType[index_i] = CY_TYPE_DISABLED; index_i++; numInterfaces--; interface++; } libusb_free_config_descriptor(configDesc); } else { CY_DEBUG_PRINT_ERROR ("CY: Error in Getting config descriptor ...Libusb error is %d \n", rStatus); if (devHandle) libusb_close (devHandle); pthread_mutex_unlock (&criticalSection); return CY_ERROR_DEVICE_INFO_FETCH_FAILED; } if (devHandle) libusb_close (devHandle); pthread_mutex_unlock (&criticalSection); return CY_SUCCESS; } /* This function gets all the neccessary info such as VID,PID, String Descriptors and if is a cypress serial device you will get the info on class and device type */ CY_RETURN_STATUS CyGetDeviceInfoVidPid ( CY_VID_PID vidPid, UINT8 *deviceNumber, PCY_DEVICE_INFO deviceInfoList, UINT8 *deviceCount, UINT8 infoListLength ) { struct libusb_device_descriptor deviceDesc; UINT32 rStatus = CY_ERROR_DRIVER_INIT_FAILED, numInterfaces, index = 0, devNum; uint8_t iManufacturer, iProduct, iSerial; libusb_device *usbDevice; struct libusb_config_descriptor *configDesc; libusb_device_handle *devHandle = NULL; PCY_DEVICE_INFO deviceInfo; if (glDriverInit == false){ CY_DEBUG_PRINT_ERROR ("CY:Error Library not initialised ...function is %s\n", __func__); return CY_ERROR_REQUEST_FAILED; } if ((infoListLength) < 1){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid device info list length specified should be > 0 .. function is %s\n", __func__); return CY_ERROR_INVALID_PARAMETER; } if (deviceNumber == NULL || deviceInfoList == NULL || deviceCount == NULL) return CY_ERROR_INVALID_PARAMETER; // Get the list of descriptor info for the device (*deviceCount) = 0; pthread_mutex_lock (&criticalSection); for (devNum = 0; devNum < glNumDevices; devNum++) { //We are making sure that we do not overrun //the list. deviceInfo = &(deviceInfoList [index]); usbDevice = glDeviceList[devNum]; rStatus = libusb_get_device_descriptor (usbDevice, &deviceDesc); if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in getting device descriptor for device-%d... Libusb Error is %d \n", devNum, rStatus); pthread_mutex_unlock (&criticalSection); return CY_ERROR_DEVICE_INFO_FETCH_FAILED; } if ((deviceDesc.idVendor != vidPid.vid) || (deviceDesc.idProduct != vidPid.pid)){ continue; } (*deviceCount)++; if (index > infoListLength){ continue; } rStatus = libusb_open (usbDevice, &devHandle); if (rStatus == LIBUSB_ERROR_ACCESS){ CY_DEBUG_PRINT_ERROR ("CY:Insufficient permission ... Libusb error is %d \n", rStatus); pthread_mutex_unlock (&criticalSection); return CY_ERROR_ACCESS_DENIED; } else if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in Opening the Device ...Error is %d \n", rStatus); pthread_mutex_unlock (&criticalSection); return CY_ERROR_DEVICE_INFO_FETCH_FAILED; } deviceNumber[index] = devNum; index++; deviceInfo->vidPid.vid = deviceDesc.idVendor; deviceInfo->vidPid.pid = deviceDesc.idProduct; // Get all the index of the String descriptors so that it can be used // to retrieve the string descriptor info. iManufacturer = deviceDesc.iManufacturer; iProduct = deviceDesc.iProduct; iSerial = deviceDesc.iSerialNumber; //Get the Device handle so that we can communicate with the device retreiving // descriptor info //Initialise manufacturer, product and serial names deviceInfo->manufacturerName[0] = '\0'; deviceInfo->productName[0] = '\0'; deviceInfo->serialNum[0] = '\0'; if (iManufacturer > 0) { rStatus = libusb_get_string_descriptor_ascii (devHandle, iManufacturer, deviceInfo->manufacturerName, 256); if (rStatus <= LIBUSB_SUCCESS){ CY_DEBUG_PRINT_INFO ("CY:Error in Getting Manufacturer name Error is <%d> \n",rStatus); } } if (iProduct > 0){ rStatus = libusb_get_string_descriptor_ascii (devHandle, iProduct, deviceInfo->productName, 256); if (rStatus <= LIBUSB_SUCCESS){ CY_DEBUG_PRINT_INFO ("CY:Error in Getting product name Error is <%d> \n", rStatus); } } if (iSerial > 0){ rStatus = libusb_get_string_descriptor_ascii (devHandle, iSerial, deviceInfo->serialNum, 256); if (rStatus <= LIBUSB_SUCCESS){ CY_DEBUG_PRINT_INFO ("CY:Error in Getting Serial name <%d>\n", rStatus); } } CY_DEBUG_PRINT_INFO ("Manufacturer name <%s> \nProduct Name <%s> \nserial number <%s> \n", deviceInfo->manufacturerName,deviceInfo->productName,deviceInfo->serialNum); rStatus = libusb_get_config_descriptor (usbDevice, 0, &configDesc); if (rStatus == LIBUSB_SUCCESS){ int index_i = 0; const struct libusb_interface *interfaceDesc; numInterfaces = configDesc->bNumInterfaces; deviceInfo->numInterfaces = numInterfaces; interfaceDesc = configDesc->interface; while ((numInterfaces) && (index_i < CY_MAX_DEVICE_INTERFACE)){ deviceInfo->deviceClass[index_i] = (CY_DEVICE_CLASS)interfaceDesc->altsetting->bInterfaceClass; if (deviceInfo->deviceClass[index_i] == CY_CLASS_VENDOR) deviceInfo->deviceType[index_i] = (CY_DEVICE_CLASS)interfaceDesc->altsetting->bInterfaceSubClass; else deviceInfo->deviceType[index_i] = CY_TYPE_DISABLED; index_i++; numInterfaces--; interfaceDesc++; } } else { CY_DEBUG_PRINT_ERROR ("CY: Error in Getting config descriptor ... Libusb Error is %d\n", rStatus); pthread_mutex_unlock (&criticalSection); return CY_ERROR_DEVICE_INFO_FETCH_FAILED; } libusb_free_config_descriptor (configDesc); libusb_close (devHandle); } if ((*deviceCount) == 0) rStatus = CY_ERROR_DEVICE_NOT_FOUND; pthread_mutex_unlock (&criticalSection); return rStatus; } /* This API will claim the interface in the device To make sure only claimed application speaks to device. */ CY_RETURN_STATUS CySelectInterface ( CY_HANDLE handle, UINT8 interfaceNum ) { UINT32 rStatus, numEP; CY_DEVICE *device; libusb_device_handle *devHandle; libusb_device *usbDev; struct libusb_config_descriptor *configDesc; const struct libusb_interface *interfaceDesc; const struct libusb_endpoint_descriptor *epDesc; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; usbDev = libusb_get_device (devHandle); if (usbDev == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error Invalide handle ..function is %s\n", __func__); return CY_ERROR_REQUEST_FAILED; } //Get the config descriptor and parse it to get the //interface and endpoint descriptor rStatus = libusb_get_config_descriptor (usbDev, 0, &configDesc); if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in Getting Config Desc ...function is %s\n", __func__); printf("\n rstatus10= %d",rStatus); return CY_ERROR_REQUEST_FAILED; } interfaceDesc = configDesc->interface; //Interface Number should be a valid one and should not exceed // total number of interfaces if (interfaceNum >= configDesc->bNumInterfaces){ CY_DEBUG_PRINT_ERROR ("CY:Interface Number not valid... \n"); libusb_free_config_descriptor (configDesc); printf("\n rstatus11= %d",rStatus); return CY_ERROR_REQUEST_FAILED; } if (libusb_kernel_driver_active (devHandle, interfaceNum)){ CY_DEBUG_PRINT_ERROR ("CY:Kernel driver active on the interface number %d \n", interfaceNum);; /*User can uncomment this section if needed. #ifdef CY_DETACH_KERNEL_DRIVER if (!libusb_detach_kernel_driver (devHandle, interfaceNum)){ CY_DEBUG_PRINT_ERROR ("CY:Kernel driver detach failed %d\n", interfaceNum); printf("\n rstatus12= %d",rStatus); return CY_ERROR_REQUEST_FAILED; } #else printf("\n rstatus13= %d",rStatus); return CY_ERROR_REQUEST_FAILED; #endif } rStatus = libusb_claim_interface (devHandle, interfaceNum); if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in claiming interface -interface num %d... Libusb error is %d \n", interfaceNum, rStatus); printf("\n rstatus14= %d",rStatus); return CY_ERROR_REQUEST_FAILED; }*/ } device->interfaceNum = interfaceNum; while (interfaceNum--) interfaceDesc++; epDesc = interfaceDesc->altsetting->endpoint; numEP = interfaceDesc->altsetting->bNumEndpoints; device->numEndpoints = numEP; // Check the total number of endpoints interface has // and get all the endpoint add CY_DEBUG_PRINT_INFO ("CY:Info The total number of endpoints are %d \n", numEP); while (numEP){ if (epDesc->bmAttributes == 0x2){ //Bulk EP checking if (epDesc->bEndpointAddress & 0x80) device->inEndpoint = epDesc->bEndpointAddress; else device->outEndpoint = epDesc->bEndpointAddress; } else if (epDesc->bmAttributes == 0x3) //Interrupt EP checking (We have only one interrupt EP) device->interruptEndpoint = epDesc->bEndpointAddress; epDesc++; numEP--; } CY_DEBUG_PRINT_INFO ("CY:Info The Endpoints are in %d and out %d and interrup %d\n", device->inEndpoint, device->outEndpoint, device->interruptEndpoint); libusb_free_config_descriptor (configDesc); return CY_SUCCESS; } /* * This API selects the type of the device */ void CySelectDeviceType (CY_DEVICE *device, libusb_device *libUsbdev, unsigned char interfaceNum) { int rStatus, numInterfaces; struct libusb_config_descriptor *configDesc; int index = 0; const struct libusb_interface *interfaceDesc; device->deviceType = CY_TYPE_DISABLED; rStatus = libusb_get_config_descriptor (libUsbdev, 0, &configDesc); if (0 == rStatus){ interfaceDesc = configDesc->interface; numInterfaces = configDesc->bNumInterfaces; if (interfaceNum >= numInterfaces) return; while (index != interfaceNum) { index++; interfaceDesc++; } if (interfaceDesc->altsetting->bInterfaceClass == CY_CLASS_VENDOR) device->deviceType = (CY_DEVICE_CLASS)interfaceDesc->altsetting->bInterfaceSubClass; libusb_free_config_descriptor (configDesc); } CY_DEBUG_PRINT_INFO ("CY:Info The device type is %d \n", device->deviceType); } /* The Api Gets the handle for the specified device number (refer to usage guide and example for usage) and this handle should be called for further communication with the device */ CY_RETURN_STATUS CyOpen ( unsigned char deviceNumber, unsigned char interfaceNum, CY_HANDLE *handle ) { libusb_device_handle *devHandle; libusb_device *dev; CY_DEVICE *device; UINT32 rStatus; if (glDriverInit == false){ CY_DEBUG_PRINT_ERROR ("CY:Error Library not initialised ...function is %s\n", __func__); return CY_ERROR_REQUEST_FAILED; } pthread_mutex_lock (&criticalSection); if (glDriverInit == true){ if (deviceNumber >= glNumDevices){ CY_DEBUG_PRINT_ERROR ("CY:Error ... Invalid device number ... \n"); pthread_mutex_unlock (&criticalSection); return CY_ERROR_INVALID_PARAMETER; } dev = glDeviceList [deviceNumber]; rStatus = libusb_open (dev, &devHandle); if (rStatus == LIBUSB_ERROR_ACCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in opening the device ..Access denied \n"); handle = NULL; pthread_mutex_unlock (&criticalSection); return CY_ERROR_ACCESS_DENIED; } if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in Opening the Device ...Error is %d \n", rStatus); printf("rstatus1 %d", rStatus); handle = NULL; pthread_mutex_unlock (&criticalSection); return CY_ERROR_DRIVER_OPEN_FAILED; } device = (CY_DEVICE *)malloc(sizeof (CY_DEVICE)); if (device == NULL){ pthread_mutex_unlock (&criticalSection); return CY_ERROR_ALLOCATION_FAILED; } device->devHandle = devHandle; (*handle) = device; rStatus = CySelectInterface (device, interfaceNum); if (rStatus != CY_SUCCESS){ libusb_close (devHandle); free (device); pthread_mutex_unlock (&criticalSection); printf("rstatus2 %d", rStatus); return CY_ERROR_DRIVER_OPEN_FAILED; } CySelectDeviceType (device, dev, interfaceNum); if (device->deviceType == CY_TYPE_UART) { CyUartSetRts (*handle); CyUartSetDtr (*handle); if (!CyUartSetHwFlowControl (*handle, CY_UART_FLOW_CONTROL_DISABLE)) device->uartFlowControlMode = CY_UART_FLOW_CONTROL_DISABLE; } //initialising structure elements device->spiThreadId = (pthread_t)0; device->uartThreadId = (pthread_t)0; device->spiCancelEvent = false; device->uartCancelEvent = false; device->spiTransfer = NULL; device->uartTransfer = NULL; if (pthread_mutex_init (&device->readLock, NULL)){ CY_DEBUG_PRINT_ERROR ("CY:Error initializing the read mutex .. Function is %s \n", __func__); libusb_close (devHandle); free (device); pthread_mutex_unlock (&criticalSection); printf("rstatus3 %d", rStatus); return CY_ERROR_DRIVER_OPEN_FAILED; } if (pthread_mutex_init (&device->writeLock, NULL)){ CY_DEBUG_PRINT_ERROR ("CY:Error initializing the write mutex .. Function is %s \n", __func__); libusb_close (devHandle); free (device); pthread_mutex_unlock (&criticalSection); printf("rstatus4 %d", rStatus); return CY_ERROR_DRIVER_OPEN_FAILED; } if (pthread_mutex_init (&device->notificationLock, NULL)){ CY_DEBUG_PRINT_ERROR ("CY:Error initializing the write mutex .. Function is %s \n", __func__); libusb_close (devHandle); free (device); pthread_mutex_unlock (&criticalSection); printf("rstatus5 %d", rStatus); return CY_ERROR_DRIVER_OPEN_FAILED; } pthread_mutex_unlock (&criticalSection); return CY_SUCCESS; } else{ CY_DEBUG_PRINT_ERROR ("CY:Error iniitalise library by calling CyLibraryInit()....function is %s\n", __func__); printf("rstatus6 %d", rStatus); return CY_ERROR_DRIVER_OPEN_FAILED; } } /* The Api Closes the handle and needs to be called only if CyGetNumDevices or CyOpen is called */ CY_RETURN_STATUS CyClose ( CY_HANDLE handle ) { CY_DEVICE *device; libusb_device_handle *devHandle; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType == CY_TYPE_UART) { CyUartClearRts (handle); CyUartClearDtr (handle); CyUartSetHwFlowControl (handle, CY_UART_FLOW_CONTROL_DISABLE); } if (glDriverInit == true){ if (device->deviceType == CY_TYPE_SPI || device->deviceType == CY_TYPE_UART){ if (device->spiThreadId != 0 || device->uartThreadId != 0){ CyAbortEventNotification(handle); } } if (pthread_mutex_destroy (&device->readLock)){ CY_DEBUG_PRINT_ERROR ("CY:Error de initializing the read mutex .. Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } if (pthread_mutex_destroy (&device->writeLock)){ CY_DEBUG_PRINT_ERROR ("CY:Error de initializing the write mutex .. Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } if (pthread_mutex_destroy (&device->notificationLock)){ CY_DEBUG_PRINT_ERROR ("CY:Error de initializing the write mutex .. Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } libusb_close ((libusb_device_handle*)devHandle); free (device); } return CY_SUCCESS; } /* This Api will reset the pipe and clears the endpoint */ CY_RETURN_STATUS CyResetPipe ( CY_HANDLE handle, UINT8 endPointAddress ) { UINT32 rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; rStatus = libusb_clear_halt ((libusb_device_handle *)devHandle, endPointAddress); if (rStatus != LIBUSB_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY:Error in resetting the pipe ... \n"); return CY_ERROR_REQUEST_FAILED; } return CY_SUCCESS; } /* This Api will get the library version,patch and build number */ CY_RETURN_STATUS CyGetLibraryVersion ( CY_HANDLE handle, PCY_LIBRARY_VERSION version ) { version->majorVersion = CY_US_VERSION_MAJOR; version->minorVersion = CY_US_VERSION_MINOR; version->patch = CY_US_VERSION_PATCH; version->buildNumber = CY_US_VERSION_BUILD; return CY_SUCCESS; }