/************************************************************************************ * this module is represents the access layer to USB STACK DRIVER * used to communication over USB protocol * the USB protocol implementation is inside the module no need for another includes * ======== USBCDCD.c ======== ************************************************************************************/ /* XDCtools Header files */ #include "include.h" #include #include #include /* BIOS Header files */ #include #include #include #include #include #include #include /* driverlib Header files */ #include #include #include #include #include #include #include /* usblib Header files */ #include #include #include #include #include #include #include #include "Drivers/USB_Communication/USBCDCD.h" #include #include "Common/Utilities/Utils.h" #include "Common/SWUpdate/FileSystem.h" #include "Communication/CommunicationTask.h" #if defined(TIVAWARE) typedef uint32_t USBCDCDEventType; #else #define eUSBModeForceDevice USB_MODE_FORCE_DEVICE typedef unsigned long USBCDCDEventType; #endif unsigned int gateUSBWaitkey,gateRxSerialkey; /* Defines */ //**************************************************************************** // // A buffer into which the composite device can write the combined config // descriptor. // //**************************************************************************** #define DESCRIPTOR_BUFFER_SIZE (COMPOSITE_DDFU_SIZE + COMPOSITE_DCDC_SIZE) extern Semaphore_Handle updateSem; extern Semaphore_Handle ReconnectSem; uint8_t g_pui8DescriptorBuffer[DESCRIPTOR_BUFFER_SIZE]; /* Typedefs */ typedef volatile enum { USBCDCD_STATE_IDLE = 0, USBCDCD_STATE_INIT, USBCDCD_STATE_UNCONFIGURED } USBCDCD_USBState; /* Static variables and handles */ static volatile USBCDCD_USBState state; static unsigned char UsbRxBuffer[COMM_MAX_BUFFER_SIZE]; static unsigned char transmitBuffer[COMM_MAX_BUFFER_SIZE]; int expected_message_size,keep_expected_message_size; int current_message_size; static volatile uint32_t g_RxCount; //static GateMutex_Handle gateTxSerial; static GateMutex_Handle gateRxSerial; static GateMutex_Handle gateUSBWait; //static Semaphore_Handle semTxSerial; //static Semaphore_Handle semRxSerial; static Semaphore_Handle semUSBConnected; extern Semaphore_Handle initConnectionSem; #define FLAG_STATUS_UPDATE 0 #define FLAG_USB_CONFIGURED 1 #define FLAG_SENDING_BREAK 2 static volatile uint32_t g_ui32Flags; /* Function prototypes */ /* static USBCDCDEventType cbRxHandler(void *cbData, USBCDCDEventType event, USBCDCDEventType _eventMsgData, void *eventMsgPtr); static USBCDCDEventType cbSerialHandler(void *cbData, USBCDCDEventType event, USBCDCDEventType _eventMsgData, void *eventMsgPtr); static USBCDCDEventType cbTxHandler(void *cbData, USBCDCDEventType event, USBCDCDEventType _eventMsgData, void *eventMsgPtr); */ uint32_t TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData); uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,void *pvMsgData); uint32_t ControlHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData); void USBCDCD_hwiHandler(UArg arg0); void USBCDCD_init(void); unsigned int USBCDCD_receiveData(unsigned char *_pBuff, unsigned int _length, unsigned int _timeout); bool USBCDCD_waitForConnect(unsigned int _timeout); uint32_t DFUDetachCallback(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgData, void *pvMsgData); /* The languages supported by this device. */ const unsigned char langDescriptor[] = { 4, USB_DTYPE_STRING, USBShort(USB_LANG_EN_US) }; /* The manufacturer string. */ const unsigned char manufacturerString[] = { (17 + 1) * 2, USB_DTYPE_STRING, 'T', 0, 'e', 0, 'x', 0, 'a', 0, 's', 0, ' ', 0, 'I', 0, 'n', 0, 's', 0, 't', 0, 'r', 0, 'u', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, 's', 0, }; /* The product string. */ const unsigned char productString[] = { 2 + (15 * 2), USB_DTYPE_STRING, 'T', 0, 'w', 0, 'i', 0, 'n', 0, 'e', 0, ' ', 0, 'T', 0, 'a', 0, 'n', 0, 'g', 0, 'o', 0, ' ', 0, 'U', 0, 'S', 0, 'B', 0, }; /* The serial number string. */ const unsigned char serialNumberString[] = { (8 + 1) * 2, USB_DTYPE_STRING, '2', 0, '2', 0, '2', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0 }; /* The interface description string. */ const unsigned char controlInterfaceString[] = { 2 + (21 * 2), USB_DTYPE_STRING, 'J', 0, 'i', 0, 'g', 0, ' ', 0, 'C', 0, '2', 0, 'n', 0, 't', 0, 'r', 0, 'o', 0, 'l', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0, 'a', 0, 'c', 0, 'e', 0 }; /* The configuration description string. */ const unsigned char configString[] = { 2 + (26 * 2), USB_DTYPE_STRING, 'S', 0, 'e', 0, 'l', 0, 'f', 0, ' ', 0, 'P', 0, 'o', 0, 'w', 0, 'e', 0, 'r', 0, 'e', 0, 'd', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0, 'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0 }; //***************************************************************************** // // The descriptor string table. // //***************************************************************************** const uint8_t * const g_ppui8StringDescriptors[] = { langDescriptor, manufacturerString, productString, serialNumberString, controlInterfaceString, configString }; #define NUM_STRING_DESCRIPTORS (sizeof(g_ppui8StringDescriptors) / \ sizeof(g_ppui8StringDescriptors[0])) /* The descriptor string table. */ const unsigned char * const stringDescriptors[] = { langDescriptor, manufacturerString, productString, serialNumberString, controlInterfaceString, configString }; #define STRINGDESCRIPTORSCOUNT (sizeof(stringDescriptors) / \ sizeof(unsigned char *)) tUSBBuffer txBuffer; tUSBBuffer rxBuffer; static tUSBDCDCDevice g_sCDCDevice; tUSBBuffer rxBuffer = { false, /* This is a receive buffer. */ RxHandler, /* pfnCallback */ (void *)&g_sCDCDevice, /* Callback data is our device pointer. */ USBDCDCPacketRead, /* pfnTransfer */ USBDCDCRxPacketAvailable, /* pfnAvailable */ (void *)&g_sCDCDevice, /* pvHandle */ UsbRxBuffer, /* pcBuffer */ COMM_MAX_BUFFER_SIZE, /* ulBufferSize */ {{0, 0, 0, 0}, 0, 0} /* private data workspace */ }; tUSBBuffer txBuffer = { true, /* This is a transmit buffer. */ TxHandler, /* pfnCallback */ (void *)&g_sCDCDevice, /* Callback data is our device pointer. */ USBDCDCPacketWrite, /* pfnTransfer */ USBDCDCTxPacketAvailable, /* pfnAvailable */ (void *)&g_sCDCDevice, /* pvHandle */ transmitBuffer, /* pcBuffer */ COMM_MAX_BUFFER_SIZE, /* ulBufferSize */ {{0, 0, 0, 0}, 0, 0} /* private data workspace */ }; static tUSBDCDCDevice g_sCDCDevice = { USB_VID_TI_1CBE, USB_PID_SERIAL, 0, USB_CONF_ATTR_SELF_PWR, ControlHandler, (void *)&g_sCDCDevice, USBBufferEventCallback, (void *)&rxBuffer, USBBufferEventCallback, (void *)&txBuffer, stringDescriptors, STRINGDESCRIPTORSCOUNT }; //***************************************************************************** // // The DFU runtime interface initialization and customization structures // //***************************************************************************** tUSBDDFUDevice g_sDFUDevice = { DFUDetachCallback, (void *)&g_sDFUDevice }; //**************************************************************************** // // The number of device class instances that this composite device will // use. // //**************************************************************************** #define NUM_DEVICES 2 //**************************************************************************** // // The array of devices supported by this composite device. // //**************************************************************************** tCompositeEntry g_psCompDevices[NUM_DEVICES]; //**************************************************************************** // // Additional workspace required by the composite driver to hold a lookup // table allowing mapping of composite interface and endpoint numbers to // individual device class instances. // //**************************************************************************** uint32_t g_pui32CompWorkspace[NUM_DEVICES]; //**************************************************************************** // // The instance data for this composite device. // //**************************************************************************** tCompositeInstance g_sCompInstance; //**************************************************************************** // // Allocate the Device Data for the top level composite device class. // //**************************************************************************** tUSBDCompositeDevice g_sCompDevice = { // // Stellaris VID. // USB_VID_TI_1CBE, // // Stellaris PID for composite SERIAL/DFU device. // USB_PID_COMP_SERIAL, // // This is in milliamps. // 250, // // Bus powered device. // USB_CONF_ATTR_BUS_PWR, // // Device event handler function pointer (receives connect, disconnect // and other device-level notifications). // ControlHandler, // // The string table. // g_ppui8StringDescriptors, NUM_STRING_DESCRIPTORS, // // The Composite device array. // NUM_DEVICES, g_psCompDevices, }; //static tLineCoding g_sLineCoding = { // 115200, /* 115200 baud rate. */ // 1, /* 1 Stop Bit. */ // 0, /* No Parity. */ // 8 /* 8 Bits of data. */ //}; bool USB_Reinit = false; //***************************************************************************** // //! Waits for a character from the USB port. //! //! This function gets a character from the USB receive buffer. //! If there are no characters available, this function waits until a //! character is received before returning. //! //! \return Returns the character read from the USB port. // //***************************************************************************** /*char USBGetChar(void) { uint8_t ucChar; int len = 0; len = USBCDCD_receiveData(&ucChar, 1, BIOS_WAIT_FOREVER); if (len !=1) { Task_sleep(1); len = USBCDCD_receiveData(&ucChar, 1, BIOS_WAIT_FOREVER); } // // Now return the char. // return (ucChar); } */ void USBFlush(void) { USBBufferFlush(&rxBuffer); } //***************************************************************************** // // Set the state of the RS232 RTS and DTR signals. // //***************************************************************************** void SetControlLineState(uint16_t ui16State) { // // TODO: If configured with GPIOs controlling the handshake lines, // set them appropriately depending upon the flags passed in the wValue // field of the request structure passed. // } //***************************************************************************** // // Get the communication parameters in use on the UART. // //***************************************************************************** void GetLineCoding(tLineCoding *psLineCoding) { psLineCoding->ui32Rate = 9600; psLineCoding->ui8Databits = 8; psLineCoding->ui8Parity = USB_CDC_PARITY_NONE; psLineCoding->ui8Stop = USB_CDC_STOP_BITS_1; } /******************************************************************** * ======== USBCDCD_hwiHandler ======== * This function calls the USB library's device interrupt handler. ********************************************************************/ void USBCDCD_hwiHandler(UArg arg0) { USB0DeviceIntHandler(); } //***************************************************************************** // // This is the callback from the USB DFU runtime interface driver. // // \param pvCBData is ignored by this function. // \param ui32Event is one of the valid events for a DFU device. // \param ui32MsgParam is defined by the event that occurs. // \param pvMsgData is a pointer to data that is defined by the event that // occurs. // // This function will be called to inform the application when a change occurs // during operation as a DFU device. Currently, the only event passed to this // callback is USBD_DFU_EVENT_DETACH which tells the recipient that they should // pass control to the boot loader at the earliest, non-interrupt context // point. // // \return This function will return 0. // //***************************************************************************** uint32_t DFUDetachCallback(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgData, void *pvMsgData) { if(ui32Event == USBD_DFU_EVENT_DETACH) { // // Set the flag that the main loop uses to determine when it is time // to transfer control back to the boot loader. Note that we // absolutely DO NOT call USBDDFUUpdateBegin() here since we are // currently in interrupt context and this would cause bad things to // happen (and the boot loader to not work). // // // Release updateSem // UpdateFlag = true; Semaphore_post(updateSem); } return(0); } #define MAX_USB_LOG 100 //uint16_t UsbEventId[MAX_USB_LOG+1] = {0}; //uint32_t UsbTime[MAX_USB_LOG+1] = {0}; //uint16_t Usbindex = 0; //***************************************************************************** // // Handles CDC driver notifications related to control and setup of the device. // // \param pvCBData is the client-supplied callback pointer for this channel. // \param ulEvent identifies the event we are being notified about. // \param ulMsgValue is an event-specific value. // \param pvMsgData is an event-specific pointer. // // This function is called by the CDC driver to perform control-related // operations on behalf of the USB host. These functions include setting // and querying the serial communication parameters, setting handshake line // states and sending break conditions. // // \return The return value is event-specific. // //***************************************************************************** uint32_t USBConn = 0, USBDisc = 0; uint32_t ControlHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData) { /*UsbEventId[Usbindex] = ui32Event; UsbTime[Usbindex] = msec_millisecondCounter; if (Usbindex++ >= MAX_USB_LOG) Usbindex = 0;*/ // // Which event are we being asked to process? // switch(ui32Event) { // // We are connected to a host and communication is now possible. // case USB_EVENT_CONNECTED: { // // Now connected and ready for normal operation. // HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 1; SetCommunicationPath(isUSB); USBConn++; // // Flush our buffers. // USBBufferFlush(&txBuffer); USBBufferFlush(&rxBuffer); //TODO: Notify connection! // // Set the command status update flag. // HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1; break; } // // The host has disconnected. // case USB_EVENT_DISCONNECTED: { // // No longer connected. // HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 0; //TODO: Notify disconnection! USBDisc++; // // Set the command status update flag. // HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1; break; } // // Return the current serial communication parameters. // case USBD_CDC_EVENT_GET_LINE_CODING: { GetLineCoding(pvMsgData); break; } // // Set the current serial communication parameters. // case USBD_CDC_EVENT_SET_LINE_CODING: { GetLineCoding(pvMsgData); break; } // // Set the current serial communication parameters. // case USBD_CDC_EVENT_SET_CONTROL_LINE_STATE: { SetControlLineState((uint16_t)ui32MsgValue); break; } // // Send a break condition on the serial line. // case USBD_CDC_EVENT_SEND_BREAK: { break; } // // Clear the break condition on the serial line. // case USBD_CDC_EVENT_CLEAR_BREAK: { break; } // // Ignore SUSPEND and RESUME for now. // case USB_EVENT_SUSPEND: case USB_EVENT_RESUME: { break; } // // We don't expect to receive any other events. Ignore any that show // up in a release build or hang in a debug build. // default: { //#ifdef DEBUG // while(1); //#else break; //#endif } } return(0); } uint32_t buffId = 0xFF; /*#define MAX_USB_LOG 3 uint32_t ULength[MAX_USB_LOG+1] = {0}; uint32_t UDataLength[MAX_USB_LOG] = {0}; byte URxIndex = 0; */ uint8_t size[4]; int size_bar = 0; void handleRx(void) { uint32_t ui32Read; uint8_t ui8Char; if (expected_message_size == 0) { while (size_bar < 4) { ui32Read = USBBufferRead((tUSBBuffer *)&rxBuffer, &ui8Char, 1); if(ui32Read) { size[size_bar++] = ui8Char; } //else // return; } if (size_bar == 4) { expected_message_size = *(int *)size; size_bar = 0; //ULength[URxIndex] = expected_message_size; if (expected_message_size) { buffId = initArray( expected_message_size); if (buffId == 0xFF) { //LOG_ERROR(expected_message_size,"usb message length error"); Report("usb message length error", __FILE__, __LINE__, expected_message_size, RpWarning, (int)buffId, 0); keep_expected_message_size = expected_message_size; expected_message_size = 0; size_bar = 0; FileChunkUploadError(); } } } } if (expected_message_size) { do { ui32Read = USBBufferRead((tUSBBuffer *)&rxBuffer, &ui8Char, 1); // Did we get a character? if(ui32Read) { if (insertArray(buffId,ui8Char) == false) { expected_message_size = 0; current_message_size = 0; LOG_ERROR(buffId,"usb message aborted"); ui32Read = 0; break; } current_message_size++; //UDataLength[URxIndex] = current_message_size; } if (current_message_size >= expected_message_size) { g_RxCount += current_message_size; /*UDataLength[URxIndex] = current_message_size; if (URxIndex++>= MAX_USB_LOG) URxIndex = 0;*/ CommunicationTaskMessageReceived(buffId,current_message_size); expected_message_size = 0; current_message_size = 0; size_bar = 0; break; } } while(ui32Read); } } //***************************************************************************** // // Handles CDC driver notifications related to the transmit channel (data to // the USB host). // // \param pvCBData is the client-supplied callback pointer for this channel. // \param ui32Event identifies the event we are being notified about. // \param ui32MsgValue is an event-specific value. // \param pvMsgData is an event-specific pointer. // // This function is called by the CDC driver to notify us of any events // related to operation of the transmit data channel (the IN channel carrying // data to the USB host). // // \return The return value is event-specific. // //***************************************************************************** uint32_t TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData) { // // Which event have we been sent? // switch(ui32Event) { case USB_EVENT_TX_COMPLETE: { // // Since we are using the USBBuffer, we don't need to do anything // here. // break; } // // We don't expect to receive any other events. Ignore any that show // up in a release build or hang in a debug build. // default: { #ifdef DEBUG while(1); #else break; #endif } } return(0); } //***************************************************************************** // // Handles CDC driver notifications related to the receive channel (data from // the USB host). // // \param pvCBData is the client-supplied callback data value for this channel. // \param ui32Event identifies the event we are being notified about. // \param ui32MsgValue is an event-specific value. // \param pvMsgData is an event-specific pointer. // // This function is called by the CDC driver to notify us of any events // related to operation of the receive data channel (the OUT channel carrying // data from the USB host). // // \return The return value is event-specific. // //***************************************************************************** uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,void *pvMsgData) { // // Which event are we being sent? // switch(ui32Event) { // // A new packet has been received. // case USB_EVENT_RX_AVAILABLE: { // // Feed some characters into the UART TX FIFO and enable the // interrupt so we are told when there is more space. // handleRx(); break; } // // We are being asked how much unprocessed data we have still to // process. We return 0 if the UART is currently idle or 1 if it is // in the process of transmitting something. The actual number of // bytes in the UART FIFO is not important here, merely whether or // not everything previously sent to us has been transmitted. // case USB_EVENT_DATA_REMAINING: { // // Get the number of bytes in the buffer and add 1 if some data // still has to clear the transmitter. return(0); } // // We are being asked to provide a buffer into which the next packet // can be read. We do not support this mode of receiving data so let // the driver know by returning 0. The CDC driver should not be sending // this message but this is included just for illustration and // completeness. // case USB_EVENT_REQUEST_BUFFER: { return(0); } // // We don't expect to receive any other events. Ignore any that show // up in a release build or hang in a debug build. // default: #ifdef DEBUG while(1); #else break; #endif } return(0); } void * USBDComposite = NULL; /******************************************************************* * ======== USBCDCD_init ======== *******************************************************************/ void USBCDCD_init(void) { Error_Block eb; Error_init(&eb); /* Install interrupt handler */ Hwi_Handle hwi; hwi = Hwi_create(INT_USB0, USBCDCD_hwiHandler, NULL, &eb); if (hwi == NULL) { System_abort("Can't create USB Hwi"); } /* State specific variables */ state = USBCDCD_STATE_UNCONFIGURED; /*added lines for drivers version 4.178*/ uint32_t g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |SYSCTL_OSC_MAIN |SYSCTL_USE_PLL |SYSCTL_CFG_VCO_480), 120000000); USBDCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &g_ui32SysClock); //uint32_t ui32PLLRate; //SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate); //USBDCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate); /* Set the USB stack mode to Device mode with VBUS monitoring */ USBStackModeSet(0, eUSBModeForceDevice, 0); //should be done here only once for supporting firmware upgrade as composite devise //if done several times in different places doesn't work in the upgrade. USBBufferInit(&txBuffer); USBBufferInit(&rxBuffer); if (!USBDCDCCompositeInit(0, &g_sCDCDevice, &(g_sCompDevice.psDevices[0]))) { System_abort("Error initializing the serial device"); } if (!USBDDFUCompositeInit(0, &g_sDFUDevice, &(g_sCompDevice.psDevices[1]))) { System_abort("Error initializing the DFU device"); } // // Pass the USB library our device information, initialize the USB // controller and connect the device to the bus. // g_sCompDevice.sPrivateData.sDeviceDescriptor.bcdUSB = 0X200; USBDComposite = USBDCompositeInit(0, &g_sCompDevice, DESCRIPTOR_BUFFER_SIZE, g_pui8DescriptorBuffer); if (!USBDComposite) { System_abort("Error initializing the composite device"); } /* //if (!USBDCDCCompositeInit(0, &g_sCDCDevice, &(g_sCompDevice.psDevices[0]))) USBDComposite = USBDCDCInit(0, &g_sCDCDevice); if (!USBDComposite) { System_abort("Error initializing the serial device"); } */ } //----------------------------------------------------------- void USBCDCD_Reinit(void) { USB_Reinit = true; USBDCompositeTerm(USBDComposite); /* State specific variables */ state = USBCDCD_STATE_UNCONFIGURED; if (gateRxSerialkey) GateMutex_leave(gateRxSerial, gateRxSerialkey); if (gateUSBWaitkey) GateMutex_leave(gateUSBWait, gateUSBWaitkey); /* Set the USB stack mode to Device mode with VBUS monitoring */ //USBStackModeSet(0, eUSBModeForceDevice, 0); HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 0; //TODO: Notify disconnection! USBDisc++; // // Set the command status update flag. // HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1; USBBufferInit(&txBuffer); USBBufferInit(&rxBuffer); USBDComposite = USBDCompositeInit(0, &g_sCompDevice, DESCRIPTOR_BUFFER_SIZE, g_pui8DescriptorBuffer); if (!USBDComposite) { System_abort("Error initializing the composite device"); } USB_Reinit = false; } //----------------------------------------------------------- /************************************************************** * ======== USBCDCD_receiveData ======== ************************************************************* */ unsigned int USBCDCD_receiveData(unsigned char *_pBuff, unsigned int _length, unsigned int _timeout) { unsigned int retValue = 0; switch (state) { case USBCDCD_STATE_UNCONFIGURED: { USBCDCD_waitForConnect(_timeout); break; } case USBCDCD_STATE_INIT: { /* Acquire lock */ gateRxSerialkey = GateMutex_enter(gateRxSerial); state = USBCDCD_STATE_IDLE; handleRx(); //retValue = rxData(_pBuff, _length, _timeout); /* Release lock */ GateMutex_leave(gateRxSerial, gateRxSerialkey); break; } case USBCDCD_STATE_IDLE: { /* Acquire lock */ gateRxSerialkey = GateMutex_enter(gateRxSerial); handleRx(); //retValue = rxData(_pBuff, _length, _timeout); /* Release lock */ GateMutex_leave(gateRxSerial, gateRxSerialkey); break; } default: break; } return (retValue); } /******************************************************* * ======== USBCDCD_sendData ======== *******************************************************/ unsigned int USBCDCD_sendData(const unsigned char *_pBuff, unsigned int _length, unsigned int _timeout) { //int len = 0; uint8_t size[4]; size[3] = (_length>>24) & 0xFF; size[2] = (_length>>16) & 0xFF; size[1] = (_length>>8) & 0xFF; size[0] = _length & 0xFF; if (USB_Reinit ==true) return OK; /*len = */USBBufferWrite((tUSBBuffer *)&txBuffer, size, 4); /*if (len == 0) { USBRingBufFlush(&(txBuffer.sPrivateData.sRingBuf)); len = USBBufferWrite((tUSBBuffer *)&txBuffer, size, 4); }*/ return USBBufferWrite((tUSBBuffer *)&txBuffer, (uint8_t*)_pBuff, _length); } /************************************************ * ======== USBCDCD_waitForConnect ======== *************************************************/ bool USBCDCD_waitForConnect(unsigned int _timeout) { bool ret = true; // Need exclusive access to prevent a race condition gateUSBWaitkey = GateMutex_enter(gateUSBWait); if (state == USBCDCD_STATE_UNCONFIGURED) { if (!Semaphore_pend(semUSBConnected, _timeout)) { ret = false; } } GateMutex_leave(gateUSBWait, gateUSBWaitkey); return (ret); }