/*Api will reset the spi module*/ CY_RETURN_STATUS CySpiReset (CY_HANDLE handle) { int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT16 wValue, wIndex, wLength, bmRequestType, bmRequest;; UINT16 scbIndex = 0; UINT32 ioTimeout = CY_USB_SERIAL_TIMEOUT; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_SPI) { CY_DEBUG_PRINT_ERROR ("CY:Error device type is not spi ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } scbIndex = device->interfaceNum; if (scbIndex > 0) scbIndex = 1; bmRequestType = CY_VENDOR_REQUEST_DEVICE_TO_HOST; bmRequest = CY_SPI_RESET_CMD; wValue = ((scbIndex << CY_SCB_INDEX_POS)); wIndex = 0; wLength = 0; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest,wValue, wIndex, NULL, wLength, ioTimeout); if (rStatus < 0){ CY_DEBUG_PRINT_ERROR ("CY:Error in sending spi reset command...Libusb error is %d\n", rStatus); return rStatus; } return CY_SUCCESS; }
/* The API is used to programme user flash area */ CYWINEXPORT CY_RETURN_STATUS WINCALLCONVEN CyReadUserFlash ( CY_HANDLE handle, /*Valid device handle*/ CY_DATA_BUFFER *readBuffer, /*data buffer containing buffer address, length to write*/ UINT32 flashAddress, /*Address to the data is written*/ UINT32 ioTimeout /*Timeout value of the API*/ ) { UINT16 wValue, wIndex, wLength; UINT8 bmRequestType, bmRequest; int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; if ((readBuffer == NULL) || (readBuffer == NULL)) return CY_ERROR_INVALID_PARAMETER; device = (CY_DEVICE *)handle; devHandle = device->devHandle; bmRequestType = CY_VENDOR_REQUEST_DEVICE_TO_HOST; bmRequest = CY_READ_USER_FLASH_CMD; wValue = 0; wIndex = flashAddress; wLength = readBuffer->length; CY_DEBUG_PRINT_INFO ("CY:The Length is %d , Value is %d and index is %d\n", wLength, wValue, wIndex); rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, readBuffer->buffer, wLength, ioTimeout); if (rStatus > 0){ (readBuffer->transferCount) = rStatus; return CY_SUCCESS; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error ..function is %s \n", __func__); (readBuffer->transferCount) = 0; return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function %s ...libusb error is %d!\n", __func__, rStatus); (readBuffer->transferCount) = 0; return CY_ERROR_REQUEST_FAILED; } }
CYWINEXPORT CY_RETURN_STATUS WINCALLCONVEN CyGetGpioValue ( CY_HANDLE handle, /*Valid device handle*/ UINT8 gpioNumber, /*GPIO configuration value*/ UINT8 *value /*Value that needs to be set*/ ) { UINT16 wValue, wIndex, wLength; UINT8 bmRequestType, bmRequest, buffer[CY_GPIO_GET_LEN]; int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT32 ioTimeout = CY_USB_SERIAL_TIMEOUT; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; bmRequestType = CY_VENDOR_REQUEST_DEVICE_TO_HOST; bmRequest = CY_GPIO_GET_VALUE_CMD; wValue = gpioNumber; wIndex = 0x00; wLength = CY_GPIO_GET_LEN; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, buffer, wLength, ioTimeout); if (rStatus == CY_GPIO_GET_LEN){ CY_DEBUG_PRINT_INFO ("CY: Get GPIO Configuration succedded...size is %d \n", rStatus); //return buffer will tell the status of the command if (buffer[0] == 0){ (*value) = buffer[1]; return CY_SUCCESS; } else return CY_ERROR_REQUEST_FAILED; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error ..function is %s \n", __func__); return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function %s ...libusb error is %d!\n", __func__, rStatus); return CY_ERROR_REQUEST_FAILED; } }
/*The API is used to cancel the uart Event notification*/ CYWINEXPORT CY_RETURN_STATUS WINCALLCONVEN CyAbortEventNotification( CY_HANDLE handle /*Valid handle to communicate with device*/ ) { CY_DEVICE *device; device = (CY_DEVICE*)handle; pthread_mutex_lock (&device->notificationLock); if (device->deviceType == CY_TYPE_UART){ if ((device->uartThreadId == 0)){ CY_DEBUG_PRINT_ERROR ("CY:Error uart event notification not created ....function is %s \n", __func__); pthread_mutex_unlock (&device->notificationLock); return CY_ERROR_REQUEST_FAILED; } device->uartCancelEvent = true; libusb_cancel_transfer (device->uartTransfer); pthread_join (device->uartThreadId, NULL); device->uartThreadId = 0; device->uartCancelEvent = false; pthread_mutex_unlock (&device->notificationLock); return CY_SUCCESS; } else if (device->deviceType == CY_TYPE_SPI){ if ((device->spiThreadId == 0)){ CY_DEBUG_PRINT_ERROR ("CY:Error spi event notification not created ....function is %s \n", __func__); pthread_mutex_unlock (&device->notificationLock); return CY_ERROR_REQUEST_FAILED; } device->spiCancelEvent = true; libusb_cancel_transfer (device->spiTransfer); pthread_join (device->spiThreadId, NULL); device->spiThreadId = 0; device->spiCancelEvent = false; pthread_mutex_unlock (&device->notificationLock); return CY_SUCCESS; } else { CY_DEBUG_PRINT_ERROR ("CY:Error.. unknown device type ....function is %s \n", __func__); pthread_mutex_unlock (&device->notificationLock); return CY_ERROR_REQUEST_FAILED; } }
/* * This API disables the Jtag module */ CY_RETURN_STATUS CyJtagDisable ( CY_HANDLE handle ) { UINT16 wValue, wIndex, wLength; UINT16 bmRequestType, bmRequest; int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT32 ioTimeout = CY_USB_SERIAL_TIMEOUT; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle.. Function is %s \n", __func__); return CY_ERROR_INVALID_HANDLE; } device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_JTAG) { CY_DEBUG_PRINT_ERROR ("CY:Error device type is not jtag ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } bmRequestType = CY_VENDOR_REQUEST_HOST_TO_DEVICE; bmRequest = CY_JTAG_DISABLE_CMD; wValue = 0x00; wIndex = 0; wLength = 0; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, NULL, wLength, ioTimeout); if (rStatus >= 0){ CY_DEBUG_PRINT_INFO ("CY: JTAG disable successfully \n"); return CY_SUCCESS; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error while enabling JTAG ..\n"); return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY:Error while enabling JTAG ...libusb error is %d function is %s!\n", rStatus, __func__); return CY_ERROR_REQUEST_FAILED; } }
/* The API resets the device */ CYWINEXPORT CY_RETURN_STATUS WINCALLCONVEN CyResetDevice ( CY_HANDLE handle /*Valid device handle*/ ) { UINT16 wValue, wIndex, wLength; UINT8 bmRequestType, bmRequest; int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT32 ioTimeout = CY_USB_SERIAL_TIMEOUT; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle \n"); return CY_ERROR_INVALID_HANDLE; } device = (CY_DEVICE *)handle; devHandle = device->devHandle; bmRequestType = CY_VENDOR_REQUEST_DEVICE_TO_HOST; bmRequest = CY_DEVICE_RESET_CMD; wValue = 0xA6B6; wIndex = 0xADBA; wLength = 0; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, NULL, wLength, ioTimeout); //return buffer will tell the status of the command if (rStatus == LIBUSB_SUCCESS) return CY_SUCCESS; else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error ..function is %s \n", __func__); return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function %s ...libusb error is %d!\n", __func__, rStatus); return CY_ERROR_REQUEST_FAILED; } }
/* This API is used to Read the Bootloder version */ CY_RETURN_STATUS CyGetFirmwareVersion( CY_HANDLE handle, CY_FIRMWARE_VERSION *firmwareVersion ) { UINT16 wValue, wIndex, wLength; UINT8 bmRequestType, bmRequest; int rStatus, ioTimeout = CY_USB_SERIAL_TIMEOUT; CY_DEVICE *device; libusb_device_handle *devHandle; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; bmRequestType = CY_VENDOR_REQUEST_DEVICE_TO_HOST; bmRequest = CY_GET_VERSION_CMD; wValue = 0x00; wIndex = 0x00; wLength = CY_GET_FIRMWARE_VERSION_LEN; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, (unsigned char*)firmwareVersion, wLength, ioTimeout); if (rStatus > 0){ return CY_SUCCESS; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error ..function is %s \n", __func__); return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function %s ...libusb error is %d!\n", __func__, rStatus); return CY_ERROR_REQUEST_FAILED; } }
CYWINEXPORT CY_RETURN_STATUS WINCALLCONVEN CySetEventNotification( CY_HANDLE handle, /*Valid handle to communicate with device*/ CY_EVENT_NOTIFICATION_CB_FN notificationCbFn /*Call back function in case on error during Uart data transfers*/ ) { CY_DEVICE *device; NOTIFICATION_CB_PARAM *args = NULL; int ret; pthread_t threadID; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle.. Function is %s \n", __func__); return CY_ERROR_INVALID_HANDLE; } if (notificationCbFn == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid parameter.. Function is %s \n", __func__); return CY_ERROR_INVALID_PARAMETER; } device = (CY_DEVICE*)handle; pthread_mutex_lock (&device->notificationLock); args = (NOTIFICATION_CB_PARAM *)malloc (sizeof (NOTIFICATION_CB_PARAM)); args->handle = handle; args->notificationCbFn = notificationCbFn; if (device->deviceType == CY_TYPE_SPI){ if (device->spiThreadId != 0) { CY_DEBUG_PRINT_ERROR ("CY:Error already notification thread exists ... Function is %s \n", __func__); pthread_mutex_unlock (&device->notificationLock); return CY_ERROR_STATUS_MONITOR_EXIST; } ret = pthread_create (&threadID, NULL, spiSetEventNotifcation, (void *) args); if (ret == 0){ device->spiThreadId = threadID; pthread_mutex_unlock (&device->notificationLock); return CY_SUCCESS; } else { device->spiThreadId = 0; free (args); pthread_mutex_unlock (&device->notificationLock); CY_DEBUG_PRINT_ERROR ("CY:Error creating spi notification thread ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } } else if (device->deviceType == CY_TYPE_UART){ if (device->uartThreadId != 0) { CY_DEBUG_PRINT_ERROR ("CY:Error already notification thread exists ... Function is %s \n", __func__); pthread_mutex_unlock (&device->notificationLock); return CY_ERROR_STATUS_MONITOR_EXIST; } ret = pthread_create (&threadID, NULL, uartSetEventNotifcation, (void *) args); if (ret == 0){ device->uartThreadId = threadID; pthread_mutex_unlock (&device->notificationLock); return CY_SUCCESS; } else { device->uartThreadId = 0; free (args); pthread_mutex_unlock (&device->notificationLock); CY_DEBUG_PRINT_ERROR ("CY:Error creating uart notification thread ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } } else { CY_DEBUG_PRINT_ERROR ("CY:Error unknown device type ....Function is %s \n", __func__); pthread_mutex_unlock (&device->notificationLock); return CY_ERROR_REQUEST_FAILED; } }
void* spiSetEventNotifcation (void *inputParameters) { int transferCompleted = 0, length = CY_SPI_EVENT_NOTIFICATION_LEN; CY_DEVICE *device; libusb_device_handle *devHandle; struct libusb_transfer *transfer; UINT8 spiStatus = 0; UINT16 errorStatus = 0; struct timeval time; CY_EVENT_NOTIFICATION_CB_FN callbackFn; NOTIFICATION_CB_PARAM *cbParameters = (NOTIFICATION_CB_PARAM*)inputParameters; callbackFn = cbParameters->notificationCbFn; device = (CY_DEVICE *)cbParameters->handle; devHandle = device->devHandle; callbackFn = cbParameters->notificationCbFn; device->spiTransfer = transfer = libusb_alloc_transfer(0); if (transfer == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error in allocating trasnfer \n"); errorStatus |= CY_ERROR_EVENT_FAILED_BIT; callbackFn (errorStatus); goto END; } libusb_fill_interrupt_transfer (transfer, devHandle, device->interruptEndpoint, &spiStatus, length, spi_notification_cb, &transferCompleted, CY_EVENT_NOTIFICATION_TIMEOUT); while (device->spiCancelEvent == false){ if (libusb_submit_transfer (transfer)){ CY_DEBUG_PRINT_ERROR ("CY:Error submitting spi interrupt token ... \n"); errorStatus |= CY_ERROR_EVENT_FAILED_BIT; callbackFn(errorStatus); break; } time.tv_sec = 0; time.tv_usec = 50;//polling timeout. while (transferCompleted == 0){ libusb_handle_events_timeout (NULL, &time); } transferCompleted = 0; if (transfer->status == LIBUSB_TRANSFER_COMPLETED){ CY_DEBUG_PRINT_INFO ("Successfully read and recieved data %d \n", transfer->actual_length); if (spiStatus & CY_SPI_UNDERFLOW_ERROR){ errorStatus |= (CY_SPI_TX_UNDERFLOW_BIT); } if (spiStatus & CY_SPI_BUS_ERROR){ errorStatus |= (CY_SPI_BUS_ERROR_BIT); } callbackFn (errorStatus); errorStatus = 0; } else{ spiStatus |= CY_ERROR_EVENT_FAILED_BIT; if (device->spiCancelEvent == false){ device->spiThreadId = 0; CY_DEBUG_PRINT_ERROR ("CY:Error spi interrupt thread was cancelled... Libusb transmission error is %d \n", transfer->status); callbackFn (spiStatus); } break; } } libusb_free_transfer (transfer); END: free (inputParameters); pthread_exit (NULL); return NULL; }
void* uartSetEventNotifcation (void *inputParameters) { int rStatus, transferCompleted = 0, length = CY_UART_EVENT_NOTIFICATION_LEN; CY_DEVICE *device; libusb_device_handle *devHandle; struct libusb_transfer *transfer; UINT16 errorStatus = 0; UCHAR uartStatus[CY_UART_EVENT_NOTIFICATION_LEN]; struct timeval time; CY_EVENT_NOTIFICATION_CB_FN callbackFn; NOTIFICATION_CB_PARAM *cbParameters = (NOTIFICATION_CB_PARAM*)inputParameters; callbackFn = cbParameters->notificationCbFn; device = (CY_DEVICE *)cbParameters->handle; devHandle = device->devHandle; callbackFn = cbParameters->notificationCbFn; device->uartTransfer = transfer = libusb_alloc_transfer(0); if (transfer == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error in allocating trasnfer \n"); errorStatus |= CY_ERROR_EVENT_FAILED_BIT; callbackFn(errorStatus); goto END; } while (device->uartCancelEvent == false){ libusb_fill_interrupt_transfer (transfer, devHandle, device->interruptEndpoint, uartStatus, length, uart_notification_cb, &transferCompleted, CY_EVENT_NOTIFICATION_TIMEOUT); rStatus = libusb_submit_transfer (transfer); if (rStatus){ CY_DEBUG_PRINT_ERROR ("CY:Error submitting uart interrupt token ... Libusb error is %d\n", rStatus); errorStatus |= CY_ERROR_EVENT_FAILED_BIT; callbackFn(errorStatus); break; } time.tv_sec = 0; time.tv_usec = 50;//polling timeout. while (transferCompleted == 0){ libusb_handle_events_timeout (NULL, &time); } transferCompleted = 0; if (transfer->status == LIBUSB_TRANSFER_COMPLETED){ CY_DEBUG_PRINT_INFO ("Successfully read and recieved data %d \n", transfer->actual_length); memcpy (&errorStatus, &uartStatus[8], 2); printf ("%x %x ", uartStatus[8], uartStatus[9]); callbackFn (errorStatus); errorStatus = 0; } else{ errorStatus |= CY_ERROR_EVENT_FAILED_BIT; if (device->uartCancelEvent == false){ CY_DEBUG_PRINT_ERROR ("CY:Error uart interrupt thread encountered error... Libusb transmission error is %d \n", transfer->status); device->uartThreadId = 0; callbackFn(errorStatus); } break; } } CY_DEBUG_PRINT_INFO ("Exiting notification thread \n"); libusb_free_transfer (transfer); END: free (inputParameters); return NULL; }
/* This API gets the current SPI config for the particluar interface of the device */ CY_RETURN_STATUS CyGetSpiConfig ( CY_HANDLE handle, CY_SPI_CONFIG *spiConfig ) { UINT16 wValue, wIndex, wLength; UINT16 bmRequestType, bmRequest; CyUsSpiConfig_t localSpiConfig; int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT32 ioTimeout = CY_USB_SERIAL_TIMEOUT; UINT8 scbIndex = 0; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle.. Function is %s \n", __func__); return CY_ERROR_INVALID_HANDLE; } if (spiConfig == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid parameter.. Function is %s \n", __func__); return CY_ERROR_INVALID_PARAMETER; } device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_SPI) { CY_DEBUG_PRINT_ERROR ("CY:Error opened device is not spi ..Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } if (device->interfaceNum > 0) scbIndex = 1; bmRequestType = CY_VENDOR_REQUEST_DEVICE_TO_HOST; bmRequest = CY_SPI_GET_CONFIG_CMD; wValue = (scbIndex << CY_SCB_INDEX_POS); wIndex = 0; wLength = CY_SPI_CONFIG_LEN; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, (unsigned char*)&localSpiConfig, wLength, ioTimeout); if (rStatus == CY_SPI_CONFIG_LEN){ //CY_DUMP_DATA ((unsigned char*)&localSpiConfig, wLength); CY_DEBUG_PRINT_INFO ("CY: Read SPI config successfully %d\n", rStatus); spiConfig->frequency = localSpiConfig.frequency; spiConfig->dataWidth = localSpiConfig.dataWidth; spiConfig->protocol = localSpiConfig.mode; spiConfig->isMsbFirst = localSpiConfig.isMsbFirst; spiConfig->isMaster = localSpiConfig.isMaster; spiConfig->isContinuousMode = localSpiConfig.isContinuous; spiConfig->isSelectPrecede = localSpiConfig.isSelectPrecede; spiConfig->isCpha = localSpiConfig.cpha; spiConfig->isCpol = localSpiConfig.cpol; return CY_SUCCESS; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error ... Function is %s\n", __func__); return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function %s...libusb error is %d !\n", __func__, rStatus); return CY_ERROR_REQUEST_FAILED; } }
/* * Api used to do read as well as write on spi */ CY_RETURN_STATUS CySpiReadWrite (CY_HANDLE handle, CY_DATA_BUFFER *readBuffer, CY_DATA_BUFFER *writeBuffer, UINT32 ioTimeout) { struct args threadParameter; UINT32 ret; pthread_t readThreadID = (pthread_t)0; CY_DEVICE *device; libusb_device_handle *devHandle; CY_RETURN_STATUS rStatus; unsigned short spiTransferMode = 0, scbIndex = 0; UINT16 wValue, wIndex = 0, wLength; UINT16 bmRequestType, bmRequest; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle.. Function is %s \n", __func__); return CY_ERROR_INVALID_HANDLE; } if (readBuffer == NULL && writeBuffer == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid parameter.. Function is %s \n", __func__); return CY_ERROR_INVALID_PARAMETER; } device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_SPI) { CY_DEBUG_PRINT_ERROR ("CY:Error opened device is not spi .. \n"); return CY_ERROR_REQUEST_FAILED; } //Set both the bits and change it accordingly based on parameters parameters spiTransferMode |= ((CY_SPI_READ_BIT) | (CY_SPI_WRITE_BIT)); if ((readBuffer == NULL || readBuffer->length == 0 || readBuffer->buffer == NULL)) spiTransferMode &= ~(CY_SPI_READ_BIT); if ((writeBuffer == NULL || writeBuffer->length == 0 || writeBuffer->buffer == NULL)) spiTransferMode &= ~(CY_SPI_WRITE_BIT); //if none of the bit is set it implies parameters sent is wrong if (spiTransferMode == 0){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid parameter.. Function is %s \n", __func__); return CY_ERROR_INVALID_PARAMETER; } if (device->interfaceNum > 0) scbIndex = 1; //In read only case we take length to be equal to readBuffer length. //But in write or in write/read case we take length = writeBuffer length. if (spiTransferMode == 0x1) wIndex = readBuffer->length; else wIndex = writeBuffer->length; spiTransferMode |= (scbIndex << 15); bmRequestType = CY_VENDOR_REQUEST_HOST_TO_DEVICE; bmRequest = CY_SPI_READ_WRITE_CMD; wValue = (spiTransferMode); wLength = 0; if (pthread_mutex_trylock (&device->writeLock) == 0){ rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, NULL, wLength, 5000); if (rStatus){ CY_DEBUG_PRINT_ERROR ("CY:Error Sending spi read write vendor command failed ... Libusb error is %d\n", rStatus); pthread_mutex_unlock (&device->writeLock); return CY_ERROR_REQUEST_FAILED; } //Read Bit is not set then write Only if (!(spiTransferMode & CY_SPI_READ_BIT)) { writeBuffer->transferCount = 0; if (readBuffer) readBuffer->transferCount = 0; rStatus = CySpiWrite (handle, writeBuffer, ioTimeout); pthread_mutex_unlock (&device->writeLock); return rStatus; } //Write Bit is not set then read only if (!(spiTransferMode & CY_SPI_WRITE_BIT)) { // We are starting a thread so that we can collect all the data // FIX for short length packet issue on SPI. readBuffer->transferCount = 0; if (writeBuffer) writeBuffer->transferCount = 0; threadParameter.handle = handle; threadParameter.readBuffer = readBuffer->buffer; threadParameter.length = readBuffer->length; threadParameter.ioTimeout = ioTimeout; ret = pthread_create (&readThreadID, NULL, (void *)spiCollectData, (void *)&threadParameter); if (ret){ CY_DEBUG_PRINT_ERROR ("CY:Error in creating read thread ... Reading failed \n"); pthread_mutex_unlock (&device->writeLock); readBuffer->transferCount = 0; return CY_ERROR_REQUEST_FAILED; } pthread_join (readThreadID, NULL); readBuffer->transferCount = threadParameter.transferCount; pthread_mutex_unlock (&device->writeLock); return threadParameter.rStatus; } writeBuffer->transferCount = 0; readBuffer->transferCount = 0; threadParameter.handle = handle; threadParameter.readBuffer = readBuffer->buffer; threadParameter.length = readBuffer->length; threadParameter.ioTimeout = ioTimeout; ret = pthread_create (&readThreadID, NULL, (void *)spiCollectData, (void *)&threadParameter); if (ret){ CY_DEBUG_PRINT_ERROR ("CY:Error in creating read thread ... Reading failed \n"); readBuffer->transferCount = 0; pthread_mutex_unlock (&device->writeLock); return CY_ERROR_REQUEST_FAILED; } rStatus = CySpiWrite (handle, writeBuffer, ioTimeout); if (rStatus == CY_SUCCESS) { pthread_join (readThreadID, NULL); rStatus = threadParameter.rStatus; readBuffer->transferCount = threadParameter.transferCount; } else { pthread_join (readThreadID, NULL); readBuffer->transferCount = threadParameter.transferCount; } pthread_mutex_unlock (&device->writeLock); return rStatus; } else{ CY_DEBUG_PRINT_ERROR ("CY:Error API busy in service previous request ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } return rStatus; }
/* Function to write on to SPI alone*/ CY_RETURN_STATUS CySpiWrite ( CY_HANDLE handle, CY_DATA_BUFFER *writeBuffer, UINT32 ioTimeout ) { int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; int spiStatus = 1; UINT32 newIoTimeout = ioTimeout, elapsedTime = 0, loopCount = 1; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_SPI) { CY_DEBUG_PRINT_ERROR ("CY:Error device type is not spi ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } startSpiTick (true); rStatus = libusb_bulk_transfer (devHandle, device->outEndpoint, writeBuffer->buffer, writeBuffer->length, (int*)&(writeBuffer->transferCount), newIoTimeout); elapsedTime = getSpiLapsedTime(true); newIoTimeout = ioTimeout - elapsedTime; //because we have a sleep of 1 msec after every getstatus if (newIoTimeout) loopCount = (newIoTimeout); if (rStatus == LIBUSB_SUCCESS){ CY_DEBUG_PRINT_INFO ("CY: Successfully written SPI data.. %d bytes Read ...\n", writeBuffer->transferCount); while (loopCount){ usleep (1000); rStatus = CyGetSpiStatus (handle, &spiStatus); if (rStatus == CY_SUCCESS){ if (spiStatus == 0){ return CY_SUCCESS; } } else { //Should never hit this case CY_DEBUG_PRINT_ERROR ("CY:Error in getting spi status \n"); return CY_ERROR_REQUEST_FAILED; } if (ioTimeout) loopCount--; } if (loopCount == 0 && spiStatus > 0){ writeBuffer->length = 0; CySpiReset (handle); return CY_ERROR_IO_TIMEOUT; } } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Error TimeOut ...function is %s\n", __func__); CySpiReset (handle); return CY_ERROR_IO_TIMEOUT; } else if (rStatus == LIBUSB_ERROR_PIPE){ CY_DEBUG_PRINT_ERROR ("CY:Error Pipe error..function is %s\n", __func__); CySpiReset (handle); CyResetPipe (handle, device->outEndpoint); return CY_ERROR_PIPE_HALTED; } else if (rStatus == LIBUSB_ERROR_OVERFLOW){ CY_DEBUG_PRINT_ERROR ("CY:Error Buffer Overflow...function is %s\n", __func__); return CY_ERROR_BUFFER_OVERFLOW; } else if (rStatus == LIBUSB_ERROR_NO_DEVICE) { CY_DEBUG_PRINT_ERROR ("CY:Error Device Disconnected ...function is %s\n", __func__); return CY_ERROR_DEVICE_NOT_FOUND; } else { CY_DEBUG_PRINT_ERROR ("CY:Error in writing SPI data ...Libusb Error is %d and bytes read is %d!\n", rStatus, writeBuffer->transferCount); return CY_ERROR_REQUEST_FAILED; } return CY_ERROR_REQUEST_FAILED; }/*
//We adopted for async method here because there are 2 thread polling same fd // i.e both read and write are polling same fd when one event triggers and other one is //not completed then another thread will wait for more than 60sec. CY_RETURN_STATUS CySpiRead ( CY_HANDLE handle, CY_DATA_BUFFER *readBuffer, UINT32 ioTimeout ) { struct libusb_transfer *readTransfer; CY_DEVICE *device; libusb_device_handle *devHandle; int readCompleted = 0; struct timeval time; int r; if (handle == NULL) return CY_ERROR_INVALID_HANDLE; device = (CY_DEVICE *)handle; devHandle = device->devHandle; readBuffer->transferCount = 0; readTransfer = libusb_alloc_transfer(0); if (readTransfer == NULL){ CY_DEBUG_PRINT_ERROR("CY:Error in allocating transfers \n"); return CY_ERROR_ALLOCATION_FAILED; } libusb_fill_bulk_transfer(readTransfer, devHandle, device->inEndpoint, readBuffer->buffer, readBuffer->length, spi_read_cb, &readCompleted, ioTimeout); libusb_submit_transfer (readTransfer); time.tv_sec = (ioTimeout / 1000); time.tv_usec = ((ioTimeout % 1000) * 1000);//polling timeout. while (readCompleted == 0){ r = libusb_handle_events_timeout_completed(glContext, &time, &readCompleted); if (r < 0) { if (r == LIBUSB_ERROR_INTERRUPTED) continue; libusb_cancel_transfer(readTransfer); while (!readCompleted) if (libusb_handle_events_completed(glContext, &readCompleted) < 0) break; readBuffer->transferCount = readTransfer->actual_length; libusb_free_transfer(readTransfer); return r; } } if (readTransfer->status == LIBUSB_TRANSFER_COMPLETED){ readBuffer->transferCount = readTransfer->actual_length; libusb_free_transfer (readTransfer); return CY_SUCCESS; } else{ if (readTransfer->status == LIBUSB_TRANSFER_TIMED_OUT){ //We should not be hitting this case.. As the time out is infinite!! CY_DEBUG_PRINT_ERROR ("CY:Timeout error in doing SPI read/write .... %d Libusb errors %d\n", readTransfer->actual_length,readTransfer->status); readBuffer->transferCount = readTransfer->actual_length; CySpiReset (handle); libusb_free_transfer (readTransfer); return CY_ERROR_IO_TIMEOUT; } if (readTransfer->status == LIBUSB_TRANSFER_OVERFLOW){ //Need to handle this properly! CY_DEBUG_PRINT_ERROR ("CY:OverFlow error in doing SPI read/write .... Libusb errors %d %d \n", readTransfer->status, readTransfer->actual_length); readBuffer->transferCount = readTransfer->actual_length; CySpiReset (handle); libusb_free_transfer (readTransfer); return CY_ERROR_BUFFER_OVERFLOW; } if (readTransfer->status != LIBUSB_TRANSFER_COMPLETED){ CY_DEBUG_PRINT_ERROR ("CY:Error in doing SPI read/write .... Libusb errors are %d %d\n", readTransfer->status, readTransfer->actual_length); readBuffer->transferCount = readTransfer->actual_length; CySpiReset (handle); libusb_free_transfer (readTransfer); //If timer is not completed then it implies we have timeout error return CY_ERROR_REQUEST_FAILED; } } return CY_ERROR_REQUEST_FAILED; }
/* This API sets SPI config of the device for that interface */ CY_RETURN_STATUS CySetSpiConfig ( CY_HANDLE handle, CY_SPI_CONFIG *spiConfig ) { UINT16 wValue, wIndex, wLength; UINT8 bmRequestType, bmRequest; CyUsSpiConfig_t localSpiConfig; int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT32 ioTimeout = CY_USB_SERIAL_TIMEOUT; UINT8 scbIndex = 0; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle.. Function is %s \n", __func__); return CY_ERROR_INVALID_HANDLE; } if (spiConfig == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid parameter.. Function is %s \n", __func__); return CY_ERROR_INVALID_PARAMETER; } device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_SPI) { CY_DEBUG_PRINT_ERROR ("CY:Error device type is not spi ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } if (spiConfig->frequency < 1000 || spiConfig->frequency > 3000000){ CY_DEBUG_PRINT_ERROR ("CY:Error frequency trying to set in out of range ... Function is %s\n", __func__); return CY_ERROR_INVALID_PARAMETER; } if (spiConfig->protocol == CY_SPI_TI){ if (!(spiConfig->isCpol == false && spiConfig->isCpha == true && spiConfig->isContinuousMode == false)){ CY_DEBUG_PRINT_ERROR ("CY:Error ... Wrong configuration for SPI TI mode \n"); return CY_ERROR_REQUEST_FAILED; } } if (spiConfig->protocol == CY_SPI_NS){ if (!(spiConfig->isCpol == false && spiConfig->isCpha == false && spiConfig->isSelectPrecede == false)){ CY_DEBUG_PRINT_ERROR ("CY:Error ... Wrong configuration for SPI ti mode \n"); return CY_ERROR_REQUEST_FAILED; } } else{ if (spiConfig->isSelectPrecede != false){ CY_DEBUG_PRINT_ERROR ("CY:Error ... Wrong configuration for SPI motorola mode \n"); return CY_ERROR_REQUEST_FAILED; } } if (device->interfaceNum > 0) scbIndex = 1; bmRequestType = CY_VENDOR_REQUEST_HOST_TO_DEVICE; bmRequest = CY_SPI_SET_CONFIG_CMD; wValue = (scbIndex << CY_SCB_INDEX_POS); wIndex = 0; wLength = CY_SPI_CONFIG_LEN; //We will not expose all the spi config structure elements to user. //Fill in rest of the values. memset (&localSpiConfig, 0, CY_SPI_CONFIG_LEN); localSpiConfig.frequency = spiConfig->frequency; localSpiConfig.dataWidth = spiConfig->dataWidth; localSpiConfig.mode = spiConfig->protocol; localSpiConfig.isMsbFirst = spiConfig->isMsbFirst; localSpiConfig.isMaster = spiConfig->isMaster; localSpiConfig.isContinuous = spiConfig->isContinuousMode; localSpiConfig.isSelectPrecede = spiConfig->isSelectPrecede; localSpiConfig.cpha = spiConfig->isCpha; localSpiConfig.cpol = spiConfig->isCpol; //CY_DUMP_DATA ((unsigned char*)&localSpiConfig, wLength); rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, (unsigned char*)&localSpiConfig, wLength, ioTimeout); if (rStatus == CY_SPI_CONFIG_LEN){ CY_DEBUG_PRINT_INFO ("CY: Setting SPI config success ...\n"); return CY_SUCCESS; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:Time out error ..Function is %s\n", __func__); return CY_ERROR_IO_TIMEOUT; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function %s ... !libusb error is %d\n", __func__, rStatus); return CY_ERROR_REQUEST_FAILED; } }
/* This API is used to read JTAG data from device interface */ CY_RETURN_STATUS CyJtagRead ( CY_HANDLE handle, CY_DATA_BUFFER *readBuffer, UINT32 ioTimeout ) { int rStatus; CY_DEVICE *device; libusb_device_handle *devHandle; UINT16 wValue, wIndex, wLength; UINT16 bmRequestType, bmRequest; bmRequestType = CY_VENDOR_REQUEST_HOST_TO_DEVICE; bmRequest = CY_JTAG_READ_CMD; wValue = readBuffer->length; wIndex = 0; wLength = 0; if (handle == NULL){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid handle.. Function is %s \n", __func__); return CY_ERROR_INVALID_HANDLE; } if ((readBuffer == NULL) || (readBuffer->buffer == NULL) || (readBuffer->length == 0)){ CY_DEBUG_PRINT_ERROR ("CY:Error invalid parameter.. Function is %s \n", __func__); return CY_ERROR_INVALID_PARAMETER; } device = (CY_DEVICE *)handle; devHandle = device->devHandle; if (device->deviceType != CY_TYPE_JTAG) { CY_DEBUG_PRINT_ERROR ("CY:Error device type is not jtag ... Function is %s \n", __func__); return CY_ERROR_REQUEST_FAILED; } readBuffer->transferCount = 0; rStatus = libusb_control_transfer (devHandle, bmRequestType, bmRequest, wValue, wIndex, NULL, wLength, ioTimeout); if (rStatus < 0){ CY_DEBUG_PRINT_INFO ("CY: JTAG Vendor Command failed %d.. Function is %s \n", rStatus, __func__); return CY_ERROR_REQUEST_FAILED; } rStatus = libusb_bulk_transfer (devHandle, CY_JTAG_IN_EP, readBuffer->buffer, readBuffer->length, (int*)&(readBuffer->transferCount), ioTimeout); if (rStatus == CY_SUCCESS){ CY_DEBUG_PRINT_ERROR ("CY: Number of bytes read is .... %d \n", readBuffer->transferCount); return CY_SUCCESS; } else if (rStatus == LIBUSB_ERROR_TIMEOUT){ CY_DEBUG_PRINT_ERROR ("CY:TimeOut error ...Function is %s \n", __func__); return CY_ERROR_IO_TIMEOUT; } else if (rStatus == LIBUSB_ERROR_PIPE){ CY_DEBUG_PRINT_ERROR ("CY:Pipe error Function is %s \n", __func__); CyResetPipe (handle, CY_JTAG_IN_EP); return CY_ERROR_PIPE_HALTED; } else if (rStatus == LIBUSB_ERROR_OVERFLOW){ CY_DEBUG_PRINT_ERROR ("CY:Error Buffer Overflow..Function is %s \n", __func__); return CY_ERROR_BUFFER_OVERFLOW; } else if (rStatus == LIBUSB_ERROR_NO_DEVICE) { CY_DEBUG_PRINT_ERROR ("CY: Device Disconnected ....Function is %s \n", __func__); return CY_ERROR_DEVICE_NOT_FOUND; } else { CY_DEBUG_PRINT_ERROR ("CY: Error in function is %s ...Libusb Error is %d!\n", __func__, rStatus); return CY_ERROR_REQUEST_FAILED; } }