/** Read data from a USB host. This will read up to 64 bytes of data at a time, as this is the maximum USB transfer for the Make Controller internally. If you want to read more than that, keep calling read until you've got what you need. If nothing is ready to be read, this will not return until new data arrives. @param buffer Where to store the incoming data. @param length How many bytes to read. 64 is the max that can be read at one time. @param timeout The number of milliseconds to wait if no data is available. -1 means wait forever. @return The number of bytes successfully read. \b Example \code char mydata[128]; // simplest is reading a short chunk int read = UsbSerial_read(mydata, 20); // or, we can wait until we've read more than the maximum of 64 bytes int got_so_far = 0; while(got_so_far < 128) // wait until we've read 128 bytes { int read = UsbSerial_read(mydata, (128 - got_so_far)); // read some new data got_so_far += read; // add to how much we've gotten so far } \endcode */ int UsbSerial_read( char *buffer, int length, int timeout ) { if( USBD_GetState() != USBD_STATE_CONFIGURED ) return 0; int length_to_go = length; if( usbSerial.rxBufCount ) { // do we already have some lying around? int copylen = MIN(usbSerial.rxBufCount, length_to_go); memcpy( buffer, usbSerial.rxBuf, copylen ); buffer += copylen; usbSerial.rxBufCount -= copylen; length_to_go -= copylen; } if(length_to_go) { // if we still would like to get more unsigned char result = USBD_Read(CDCDSerialDriverDescriptors_DATAOUT, usbSerial.rxBuf, USBSER_MAX_READ, UsbSerial_onUsbData, 0); if(result == USBD_STATUS_SUCCESS) { if( SemaphoreTake( usbSerial.readSemaphore, timeout ) ) { int copylen = MIN(usbSerial.justGot, length_to_go); memcpy( buffer, usbSerial.rxBuf, copylen ); buffer += copylen; usbSerial.rxBufCount -= copylen; length_to_go -= copylen; usbSerial.justGot = 0; } } } return length - length_to_go; }
//------------------------------------------------------------------------------ /// Sets the current value of a particular Feature control of a channel. /// \param entity Entity number. /// \param channel Channel number. /// \param control Control selector value (see TODO). /// \param length Length of the data containing the new value. //------------------------------------------------------------------------------ static void AUDDSpeakerDriver_SetFeatureCurrentValue(unsigned char entity, unsigned char channel, unsigned char control, unsigned short length) { TRACE_INFO_WP("sFeature "); TRACE_DEBUG("\b(E%d, CS%d, CN%d, L%d) ", entity, control, channel, length); // Check the the requested control is supported // Control/channel combination not supported if ((control == AUDFeatureUnitRequest_MUTE) && (channel < (AUDDSpeakerDriver_NUMCHANNELS+1)) && (length == 1)) { unsigned int argument = channel; // Avoids compiler warning USBD_Read(0, // Endpoint #0 &muted, sizeof(muted), (TransferCallback) AUDDSpeakerDriver_MuteReceived, (void *) argument); } // Control/channel combination not supported else { USBD_Stall(0); } }
static void handle_osmosdr_write(const USBGenericRequest* request) { uint16_t func = USBGenericRequest_GetValue(request); int len = USBGenericRequest_GetLength(request); int i; /* printf("OsmoSDR SET request: type:%d, request:%d, value:%04x, index: %04x, length: %d\n\r", USBGenericRequest_GetType(request), USBGenericRequest_GetRequest(request), USBGenericRequest_GetValue(request), USBGenericRequest_GetIndex(request), len); */ for(i = 0; i < ARRAY_SIZE(g_writeRequests); i++) { if(g_writeRequests[i].func == func) break; } if(i == ARRAY_SIZE(g_writeRequests)) { USBD_Stall(0); return; } if(len != g_writeRequests[i].len) { USBD_Stall(0); return; } g_writeState.func = func; if(len > 0) USBD_Read(0, g_writeState.data, len, finalize_write, 0); else finalize_write(NULL, 0, 0, 0); }
/** Read data from a USB host. This will read up to 64 bytes of data at a time, as this is the maximum USB transfer for the Make Controller internally. If you want to read more than that, keep calling read until you've got what you need. If nothing is ready to be read, this will not return until new data arrives. @param buffer Where to store the incoming data. @param length How many bytes to read. 64 is the max that can be read at one time. @param timeout The number of milliseconds to wait if no data is available. -1 means wait forever. @return The number of bytes successfully read. \b Example \code char mydata[128]; UsbSerial* usb = UsbSerial::get(); // get a reference to the usb system // simplest is reading a short chunk int read = usb->read(mydata, 20); // or, we can wait until we've read more than the maximum of 64 bytes int got_so_far = 0; while(got_so_far < 128) // wait until we've read 128 bytes { int read = usb->read(mydata, (128 - got_so_far)); // read some new data got_so_far += read; // add to how much we've gotten so far } \endcode */ int UsbSerial::read( char *buffer, int length, int timeout ) { if( USBD_GetState() != USBD_STATE_CONFIGURED ) return 0; int length_to_go = length; if( rxBufCount ) // do we already have some lying around? { int copylen = (rxBufCount > length_to_go) ? length_to_go : rxBufCount; memcpy( buffer, rxBuf, copylen ); buffer += copylen; rxBufCount -= copylen; length_to_go -= copylen; } if(length_to_go) // if we still would like to get more { unsigned char result = USBD_Read(CDCDSerialDriverDescriptors_DATAOUT, rxBuf, USB_SER_RX_BUF_LEN, onUsbData, this); if(result == USBD_STATUS_SUCCESS) { if( readSemaphore.take( timeout ) ) { int copylen = (justGot > length_to_go) ? length_to_go : justGot; memcpy( buffer, rxBuf, copylen ); buffer += copylen; rxBufCount -= copylen; length_to_go -= copylen; justGot = 0; } } } return length - length_to_go; }
static void fastsource_set_feat_cur_val(uint8_t entity, uint8_t channel, uint8_t control, uint8_t length) { TRACE_INFO("set_feat(E%u, CO%u, CH%u, L%u) ", entity, channel, control, length); if (channel == 0 && control == AUDFeatureUnitDescriptor_MUTE && length == 1) USBD_Read(0, &usb_state.muted, sizeof(usb_state.muted), 0, 0); else USBD_Stall(0); }
static int led_set(const USB_Setup_TypeDef *setup) { int res = USB_STATUS_REQ_ERR; CHECK_SETUP_OUT(USBTHING_CMD_LED_SET_SIZE); res = USBD_Read(0, cmd_buffer, USBTHING_CMD_LED_SET_SIZE, led_set_cb); return res; }
static int gpio_config(const USB_Setup_TypeDef *setup) { int res = USB_STATUS_REQ_ERR; CHECK_SETUP_OUT(USBTHING_CMD_GPIO_CFG_SIZE); res = USBD_Read(0, cmd_buffer, USBTHING_CMD_GPIO_CFG_SIZE, gpio_config_cb); return res; }
//------------------------------------------------------------------------------ /// Receives new line coding information from the USB host. //------------------------------------------------------------------------------ static void CDCDSerialDriver_SetLineCoding(void) { TRACE_INFO_WP("sLineCoding "); USBD_Read(0, (void *) &(cdcdSerialDriver.lineCoding), sizeof(CDCLineCoding), (TransferCallback) CDCDSerialDriver_SetLineCodingCallback, 0); }
/** * Receives new line coding information from the USB host. * \param pCdcd Pointer to CDCDSerialPort instance. */ static void _SetLineCoding(CDCDSerialPort * pCdcd) { TRACE_INFO_WP("sLineCoding "); USBD_Read(0, (void *) & (lineCoding), sizeof(CDCLineCoding), (TransferCallback)_SetLineCodingCallback, (void*)pCdcd); }
static int spi_svc_config(const USB_Setup_TypeDef *setup) { int res = USB_STATUS_REQ_ERR; CHECK_SETUP_OUT(USBTHING_CMD_SPI_CONFIG_SIZE); res = USBD_Read(0, cmd_buffer, USBTHING_CMD_SPI_CONFIG_SIZE, spi_svc_config_cb); return res; }
uint32_t CDCDSerialPort_Read(const CDCDSerialPort * pCdcd, void * pData,uint32_t dwSize, TransferCallback fCallback,void * pArg) { if (pCdcd->bBulkOutPIPE == 0) return USBRC_PARAM_ERR; return USBD_Read(pCdcd->bBulkOutPIPE, pData, dwSize, fCallback, pArg); }
/** * Reads incoming audio data sent by the USB host into the provided * buffer. When the transfer is complete, an optional callback function is * invoked. * \param buffer Pointer to the data storage buffer. * \param length Size of the buffer in bytes. * \param callback Optional callback function. * \param argument Optional argument to the callback function. * \return USBD_STATUS_SUCCESS if the transfer is started successfully; * otherwise an error code. */ uint8_t AUDDSpeakerDriver_Read(void *buffer, uint32_t length, TransferCallback callback, void *argument) { AUDDSpeakerDriver *pAudd = &auddSpeakerDriver; AUDDSpeakerPhone *pAudf = &pAudd->fun; return USBD_Read(pAudf->pSpeaker->bEndpointOut, buffer, length, callback, argument); }
//------------------------------------------------------------------------------ /// Reads incoming audio data sent by the USB host into the provided /// buffer. When the transfer is complete, an optional callback function is /// invoked. /// \param buffer Pointer to the data storage buffer. /// \param length Size of the buffer in bytes. /// \param callback Optional callback function. /// \param argument Optional argument to the callback function. /// \return USBD_STATUS_SUCCESS if the transfer is started successfully; /// otherwise an error code. //------------------------------------------------------------------------------ unsigned char AUDDSpeakerDriver_Read(void *buffer, unsigned int length, TransferCallback callback, void *argument) { return USBD_Read(AUDDSpeakerDriverDescriptors_DATAOUT, buffer, length, callback, argument); }
//------------------------------------------------------------------------------ /// Receives data from the host through the virtual COM port created by /// the CDC device serial driver. This function behaves like USBD_Read. /// \param data Pointer to the data buffer to put received data. /// \param size Size of the data buffer in bytes. /// \param callback Optional callback function to invoke when the transfer /// finishes. /// \param argument Optional argument to the callback function. /// \return USBD_STATUS_SUCCESS if the read operation has been started normally; /// otherwise, the corresponding error code. //------------------------------------------------------------------------------ unsigned char CDCDSerialDriver_Read(void *data, unsigned int size, TransferCallback callback, void *argument) { return USBD_Read(CDCDSerialDriverDescriptors_DATAOUT, data, size, callback, argument); }
/** * Receives data from the host through the audio function (as speaker). * This function behaves like USBD_Read. * \param pAuds Pointer to AUDDStream instance. * \param pData Pointer to the data buffer to put received data. * \param dwSize Size of the data buffer in bytes. * \param fCallback Optional callback function to invoke when the transfer * finishes. * \param pArg Optional argument to the callback function. * \return USBD_STATUS_SUCCESS if the read operation has been started normally; * otherwise, the corresponding error code. */ uint32_t AUDDStream_Read( AUDDStream *pAuds, void * pData,uint32_t dwSize, TransferCallback fCallback,void * pArg) { if (pAuds->bEndpointOut == 0) return USBRC_PARAM_ERR; return USBD_Read(pAuds->bEndpointOut, pData, dwSize, fCallback, pArg); }
//----------------------------------------------------------------------------- /// Reads from host through MSD defined bulk OUT pipe. Act as USBD_Read but by /// a fixed OUT endpoint. /// \param data Pointer to the data buffer that contains data read from host. /// \param size The number of bytes should be read (buffer size). /// \param callback Pointer to the function invoked on end of reading. /// \param argument Pointer to additional argument data struct. //----------------------------------------------------------------------------- char MSDD_Read(void *data, unsigned int size, TransferCallback callback, void *argument) { return USBD_Read(MSDDriverDescriptors_BULKOUT, data, size, callback, argument); }
/**************************************************************************//** * @brief * Start a USB bulk-in or bulk-out transfer to transfer a data payload * to/from host. * * @param[in] data * Pointer to data payload. * * @param[in] len * Number of bytes to transfer. * * @param[in] cb * Transfer completion callback. *****************************************************************************/ static void UsbXferBotData(uint8_t *data, uint32_t len, USB_XferCompleteCb_TypeDef cb) { if (pCmdStatus->direction) { USBD_Write(BULK_IN, data, len, cb); } else { USBD_Read(BULK_OUT, data, len, cb); } }
//----------------------------------------------------------------------------- /// Receives new line coding information from the USB host. /// \param request Pointer to a USBGenericRequest instance. //----------------------------------------------------------------------------- static void CDCD_SetLineCoding(const USBGenericRequest *request) { unsigned char serial; serial = CDCD_GetSerialPort(request); TRACE_INFO_WP("sLineCoding_%d ", serial); USBD_Read(0, (void *) &(cdcFunDriver.pCdcPorts[serial].lineCoding), sizeof(CDCLineCoding), (TransferCallback) CDCD_SetLineCodingCallback, 0); }
/** * Receives data from the host through the audio function (as speaker). * This function behaves like USBD_Read. * \param pAudf Pointer to AUDDSpeakerPhone instance. * \param pData Pointer to the data buffer to put received data. * \param dwSize Size of the data buffer in bytes. * \param fCallback Optional callback function to invoke when the transfer * finishes. * \param pArg Optional argument to the callback function. * \return USBD_STATUS_SUCCESS if the read operation has been started normally; * otherwise, the corresponding error code. */ uint32_t AUDDSpeakerPhone_Read( AUDDSpeakerPhone *pAudf, void * pData,uint32_t dwSize, TransferCallback fCallback,void * pArg) { if (pAudf->pSpeaker == 0) return USBRC_PARAM_ERR; if (pAudf->pSpeaker->bEndpointOut == 0) return USBRC_PARAM_ERR; return USBD_Read(pAudf->pSpeaker->bEndpointOut, pData, dwSize, fCallback, pArg); }
void stateChange(USBD_State_TypeDef oldState, USBD_State_TypeDef newState) { /* Print state transition to debug output */ // emberSerialPrintf(SER232,"%s => %s\r\n", USBD_GetUsbStateName(oldState), USBD_GetUsbStateName(newState)); if (newState == USBD_STATE_CONFIGURED) { /* Start waiting for the 'tick' messages */ // emberSerialPrintf(SER232,"starting read\r\n"); uint8_t t='\r'; USBD_Read(EP_DATA_OUT, &t, 1, NULL); } }
/** * Handle the SET_CUR request. * \param pAudf Pointer to AUDDSpeakerPhone instance. * \param pReq Pointer to USBGenericRequest instance. */ static void AUDD_SetCUR( AUDDSpeakerPhone *pAudf, const USBGenericRequest* pReq) { uint8_t bIf = AUDGenericRequest_GetInterface(pReq); uint8_t bEntity = AUDGenericRequest_GetEntity(pReq); uint8_t bLength = USBGenericRequest_GetLength(pReq); uint8_t bCh = AUDFeatureUnitRequest_GetChannel(pReq); uint8_t bCtrl = AUDFeatureUnitRequest_GetControl(pReq); uint8_t bSet = 1; AUDDStream *pAuds = AUDD_GetCtlStream(pAudf, bIf, bEntity, bCh); TransferCallback fCallback; TRACE_INFO_WP("sCUR "); TRACE_DEBUG("\b(E%d, CtlS%d, Ch%d, L%d) ", bEntity, bCtrl, bCh, bLength); /* Set Mute to AC, 1 byte */ if (bCtrl == AUDFeatureUnitRequest_MUTE && bLength == 1 && pAuds) { fCallback = (TransferCallback) AUDD_MuteReceived; } else if (bCtrl == AUDFeatureUnitRequest_VOLUME && bLength == 2 && pAuds && pAuds->pwVolumes) { fCallback = (TransferCallback) AUDD_VolumeReceived; } else bSet = 0; if (bSet) { auddXfrData.pStream = pAuds; auddXfrData.bEntity = bEntity; auddXfrData.bCh = bCh; USBD_Read(0, &auddXfrData.usbBuffer, bLength, fCallback, (void *) &auddXfrData); } else { USBD_Stall(0); } }
//----------------------------------------------------------------------------- /// Receives data from the host through the virtual COM port created by /// the CDC function serial driver. This function behaves like <USBD_Read>. /// \param Port Port index to receive. /// \param Pointer to the data buffer to send. /// \param Size of the data buffer in bytes. /// \param callback Optional callback function to invoke when the transfer /// finishes. /// \param argument Optional argument to the callback function. /// \return <USBD_STATUS_SUCCESS> if the read operation started normally; /// otherwise, the corresponding error code. //----------------------------------------------------------------------------- unsigned char CDCDSerialDriver_Read(unsigned char port, void *data, unsigned int size, TransferCallback callback, void *argument) { unsigned char ep = cdcFunDriver.pCdcPorts[port].bulkOutEndpoint; if (port > cdcFunDriver.numPorts) return USBD_STATUS_INVALID_PARAMETER; return USBD_Read(ep, data, size, callback, argument); }
static int spi_svc_data_sent_cb(USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining) { int res; /* Remove warnings for unused variables */ (void)xferred; (void)remaining; if ( status != USB_STATUS_OK ) { /* Handle error */ return status; } //if ((xferred != 0) && (xferred % USB_MAX_EP_SIZE == 0)) { // //Send zero length packet to signify completion // res = USBD_Write(EP1_IN, NULL, 0, spi_svc_data_sent_cb); //} //Restart EP_OUT res = USBD_Read(EP1_OUT, spi_svc_receive_buffer, SPI_BUFF_SIZE, spi_svc_data_receive_cb); return res; }
void USBDEP_Ep0Handler( USBD_Device_TypeDef *device ) { int status; USBD_Ep_TypeDef *ep; static uint32_t xferred; static USB_XferCompleteCb_TypeDef callback; #ifdef __MBED__ (void)xferred; (void)status; ep = &device->ep[ 0 ]; if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) ) { ep->state = D_EP_IDLE; if ( ep->xferCompleteCb ) { callback = ep->xferCompleteCb; ep->xferCompleteCb = NULL; callback( USB_STATUS_OK, ep->xferred, ep->remaining ); } USBDHAL_StartEp0Setup( dev ); } else { device->callbacks->setupCmd(device->setup); } #else ep = &device->ep[ 0 ]; switch ( ep->state ) { case D_EP_IDLE: ep->zlp = 0; ep->remaining = 0; callback = NULL; status = USBDCH9_SetupCmd( device ); if ( status == USB_STATUS_REQ_ERR ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP packet*/ } else /* ( Status == USB_STATUS_OK ) */ { if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) ) { callback = ep->xferCompleteCb; } if ( ep->state != D_EP_RECEIVING ) { if ( ep->remaining ) { /* Data will be sent to host, check if a ZLP must be appended */ if ( ( ep->remaining < device->setup->wLength ) && ( ep->remaining % ep->packetSize == 0 ) ) { ep->zlp = 1; } } else { /* No data stage, a ZLP may have been sent. If not, send one */ xferred = 0; if ( ep->zlp == 0 ) { ep->state = D_EP_IDLE; USBD_Write( 0, NULL, 0, NULL ); /* ACK to host */ ep->state = D_EP0_IN_STATUS; } } } } break; case D_EP_RECEIVING: if ( ep->remaining ) { ep->in = false; USBD_ReArmEp0( ep ); } else { status = USB_STATUS_OK; if ( callback != NULL ) { status = callback( USB_STATUS_OK, ep->xferred, 0 ); callback = NULL; } if ( status != USB_STATUS_OK ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP pkt. */ ep->state = D_EP_IDLE; } else { USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP packet*/ ep->state = D_EP_IDLE; /* USBD_Write() sets state back */ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); ep->state = D_EP0_IN_STATUS; } } break; case D_EP_TRANSMITTING: if ( ep->remaining ) { ep->in = true; USBD_ReArmEp0( ep ); } else { if ( ep->zlp == 1 ) { xferred = ep->xferred; ep->state = D_EP_IDLE; /* USBD_Write() sets state back */ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP */ ep->zlp = 2; } else { if ( ep->zlp == 0 ) { xferred = ep->xferred; } ep->state = D_EP_IDLE; USBD_Read( 0, NULL, 0, NULL ); /* Get ZLP packet (ACK) from host */ ep->state = D_EP0_OUT_STATUS; } } break; case D_EP0_IN_STATUS: if ( ( USB->DOEP0CTL & USB_DOEP0CTL_EPENA ) == 0 ) { /* Prepare for more SETUP Packets */ USBDHAL_StartEp0Setup( dev ); } if ( callback != NULL ) { callback( USB_STATUS_OK, xferred, 0 ); } ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ break; case D_EP0_OUT_STATUS: USBDHAL_StartEp0Setup( dev ); /* Prepare for more SETUP Packets */ if ( callback != NULL ) { callback( USB_STATUS_OK, xferred, 0 ); } ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ break; } #endif /* __MBED__ */ }
void USBDEP_Ep0Handler( USBD_Device_TypeDef *device ) { int status; USBD_Ep_TypeDef *ep; static bool statusIn; static uint32_t xferred; static USB_XferCompleteCb_TypeDef callback; ep = &device->ep[ 0 ]; #ifdef __MBED__ (void)xferred; (void)statusIn; (void)status; USB_PRINTF("USBDEP: ep0 %s, rem %ld, z %d\n", epStatusStr[ep->state], ep->remaining, ep->zlp); if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) ) { ep->state = D_EP_IDLE; if ( ep->xferCompleteCb ) { callback = ep->xferCompleteCb; ep->xferCompleteCb = NULL; callback( USB_STATUS_OK, ep->xferred, ep->remaining ); } USBDHAL_ReenableEp0Setup(device); } else { device->callbacks->setupCmd(device->setup); } #else /* not __MBED__ */ switch ( ep->state ) { case D_EP_IDLE: ep->remaining = 0; ep->zlp = 0; callback = NULL; statusIn = false; status = USBDCH9_SetupCmd( device ); if ( status == USB_STATUS_REQ_ERR ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP packet*/ } else /* ( Status == USB_STATUS_OK ) */ { if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) ) { callback = ep->xferCompleteCb; } if ( ep->state != D_EP_RECEIVING ) { if ( ep->remaining ) { /* Data will be sent to host, check if a ZLP must be appended */ if ( ( ep->remaining < device->setup->wLength ) && ( ep->remaining % ep->packetSize == 0 ) ) { ep->zlp = 1; } } else { /* Prepare for next SETUP packet*/ USBDHAL_ReenableEp0Setup( device ); /* No data stage, a ZLP may have been sent. If not, send one */ xferred = 0; if ( ep->zlp == 0 ) { USBD_Write( 0, NULL, 0, NULL ); /* ACK to host */ ep->state = D_EP0_IN_STATUS; } else { ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ } } } } break; case D_EP_RECEIVING: if ( ep->remaining ) { /* There is more data to receive */ USBD_ReArmEp0( ep ); } else { status = USB_STATUS_OK; if ( callback != NULL ) { status = callback( USB_STATUS_OK, ep->xferred, 0 ); callback = NULL; } if ( status != USB_STATUS_OK ) { ep->in = true; USBDHAL_StallEp( ep ); /* Stall Ep0 IN */ ep->in = false; /* OUT for next SETUP */ USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */ USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP pkt. */ ep->state = D_EP_IDLE; } else /* Everything OK, send a ZLP (ACK) to host */ { USBDHAL_ReenableEp0Setup( device );/* Prepare for next SETUP packet*/ ep->state = D_EP_IDLE; /* USBD_Write() sets state back*/ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); ep->state = D_EP0_IN_STATUS; } } break; case D_EP_TRANSMITTING: if ( ep->remaining ) { /* There is more data to transmit */ USBD_ReArmEp0( ep ); } else { /* All data transferred, is a ZLP packet needed ? */ if ( ep->zlp == 1 ) { xferred = ep->xferred; ep->state = D_EP_IDLE; /* USBD_Write() sets state back */ /* to EP_TRANSMITTING */ USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP */ ep->zlp = 2; } else { if ( ep->zlp == 0 ) { xferred = ep->xferred; } ep->state = D_EP_IDLE; USBD_Read( 0, NULL, 0, NULL ); /* Get ZLP packet (ACK) from host */ statusIn = true; ep->state = D_EP0_OUT_STATUS; } } break; case D_EP0_IN_STATUS: case D_EP0_OUT_STATUS: if ( statusIn ) { USBDHAL_ReenableEp0Setup( device ); } if ( callback != NULL ) { callback( USB_STATUS_OK, xferred, 0 ); } ep->state = D_EP_IDLE; ep->in = false; /* OUT for next SETUP */ break; default: EFM_ASSERT( false ); break; } #endif /* __MBED__ */ }
/** * Handles HID-specific SETUP request sent by the host. * \param request Pointer to a USBGenericRequest instance */ void HIDDTransferDriver_RequestHandler(const USBGenericRequest *request) { HIDDTransferDriver *pDrv = &hiddTransferDriver; HIDDFunction *pHidd = &pDrv->hidFunction; TRACE_INFO("NewReq "); /* Check if this is a standard request */ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) { /* This is a standard request */ switch (USBGenericRequest_GetRequest(request)) { case USBGenericRequest_GETDESCRIPTOR: /* Check if this is a HID descriptor, otherwise forward it to the standard driver */ if (!HIDDTransferDriver_GetDescriptor( USBGetDescriptorRequest_GetDescriptorType(request), USBGenericRequest_GetLength(request))) { USBDDriver_RequestHandler(pHidd->pUsbd, request); } return; /* Handled, no need to do others */ case USBGenericRequest_CLEARFEATURE: /* Check which is the requested feature */ switch (USBFeatureRequest_GetFeatureSelector(request)) { case USBFeatureRequest_ENDPOINTHALT: { uint8_t ep = USBGenericRequest_GetEndpointNumber(request); if (USBD_IsHalted(ep)) { /* Unhalt endpoint restart OUT EP */ USBD_Unhalt(ep); if (ep == pHidd->bPipeOUT) { HIDDFunction_StartPollingOutputs(pHidd); } } /* and send a zero-length packet */ USBD_Write(0, 0, 0, 0, 0); return; /* Handled, no need to do others */ } } break; } } /* We use different buffer for SetReport */ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) { switch (USBGenericRequest_GetRequest(request)) { case HIDGenericRequest_SETREPORT: { uint16_t length = USBGenericRequest_GetLength(request); uint8_t type = HIDReportRequest_GetReportType(request); if (type == HIDReportRequest_OUTPUT) { if (length > HIDDTransferDriver_REPORTSIZE) length = HIDDTransferDriver_REPORTSIZE; USBD_Read(0, pDrv->iReportBuf, length, HIDDTransferDriver_ReportReceived, 0); /* No argument to the callback function */ } else { USBD_Stall(0); } } return; /* Handled, no need do others */ } } /* Process HID requests */ if (USBRC_SUCCESS == HIDDFunction_RequestHandler(pHidd, request)) { return; } else USBDDriver_RequestHandler(pHidd->pUsbd, request); }
/** * State machine for the MSD %device driver * \param pMsdDriver Pointer to a MSDDriver instance */ void MSDD_StateMachine(MSDDriver * pMsdDriver) { MSDCommandState *commandState = &(pMsdDriver->commandState); MSCbw *cbw = &(commandState->cbw); MSCsw *csw = &(commandState->csw); MSDTransfer *transfer = &(commandState->transfer); unsigned char status; /* Identify current driver state */ switch (pMsdDriver->state) { /*---------------------- */ case MSDD_STATE_READ_CBW: /*---------------------- */ /* Start the CBW read operation */ transfer->semaphore = 0; #if 1 status = USBD_Read(commandState->pipeOUT, cbw, MSD_CBW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #else status = MSDD_Read(cbw, MSD_CBW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #endif /* Check operation result code */ if (status == USBD_STATUS_SUCCESS) { /* If the command was successful, wait for transfer */ pMsdDriver->state = MSDD_STATE_WAIT_CBW; } break; /*---------------------- */ case MSDD_STATE_WAIT_CBW: /*---------------------- */ /* Check transfer semaphore */ if (transfer->semaphore > 0) { /* Take semaphore and terminate transfer */ transfer->semaphore--; /* Check if transfer was successful */ if (transfer->status == USBD_STATUS_SUCCESS) { TRACE_INFO_WP("\n\r------------------------------\n\r"); /* Process received command */ pMsdDriver->state = MSDD_STATE_PROCESS_CBW; } else if (transfer->status == USBD_STATUS_RESET) { TRACE_INFO("MSDD_StateMachine: EP resetted\n\r"); pMsdDriver->state = MSDD_STATE_READ_CBW; } else { TRACE_WARNING( "MSDD_StateMachine: Failed to read CBW\n\r"); pMsdDriver->state = MSDD_STATE_READ_CBW; } } break; /*------------------------- */ case MSDD_STATE_PROCESS_CBW: /*------------------------- */ /* Check if this is a new command */ if (commandState->state == 0) { /* Copy the CBW tag */ csw->dCSWTag = cbw->dCBWTag; /* Check that the CBW is 31 bytes long */ if ((transfer->transferred != MSD_CBW_SIZE) || (transfer->remaining != 0)) { TRACE_WARNING( "MSDD_StateMachine: Invalid CBW (len %d)\n\r", (int)transfer->transferred); /* Wait for a reset recovery */ pMsdDriver->waitResetRecovery = 1; /* Halt the Bulk-IN and Bulk-OUT pipes */ //MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN); USBD_Halt(commandState->pipeIN); USBD_Halt(commandState->pipeOUT); csw->bCSWStatus = MSD_CSW_COMMAND_FAILED; pMsdDriver->state = MSDD_STATE_READ_CBW; } /* Check the CBW Signature */ else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) { TRACE_WARNING( "MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r"); /* Wait for a reset recovery */ pMsdDriver->waitResetRecovery = 1; /* Halt the Bulk-IN and Bulk-OUT pipes */ //MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN); USBD_Halt(commandState->pipeIN); USBD_Halt(commandState->pipeOUT); csw->bCSWStatus = MSD_CSW_COMMAND_FAILED; pMsdDriver->state = MSDD_STATE_READ_CBW; } else { /* Pre-process command */ MSDD_PreProcessCommand(pMsdDriver); } } /* Process command */ if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) { if (MSDD_ProcessCommand(pMsdDriver)) { /* Post-process command if it is finished */ if (MSDD_PostProcessCommand(pMsdDriver)) { TRACE_INFO_WP("WaitHALT "); pMsdDriver->state = MSDD_STATE_WAIT_HALT; } else { pMsdDriver->state = MSDD_STATE_SEND_CSW; } } TRACE_INFO_WP("\n\r"); } break; /*---------------------- */ case MSDD_STATE_SEND_CSW: /*---------------------- */ /* Set signature */ csw->dCSWSignature = MSD_CSW_SIGNATURE; /* Start the CSW write operation */ #if 1 status = USBD_Write(commandState->pipeIN, csw, MSD_CSW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #else status = MSDD_Write(csw, MSD_CSW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #endif /* Check operation result code */ if (status == USBD_STATUS_SUCCESS) { TRACE_INFO_WP("SendCSW "); /* Wait for end of transfer */ pMsdDriver->state = MSDD_STATE_WAIT_CSW; } break; /*---------------------- */ case MSDD_STATE_WAIT_CSW: /*---------------------- */ /* Check transfer semaphore */ if (transfer->semaphore > 0) { /* Take semaphore and terminate transfer */ transfer->semaphore--; /* Check if transfer was successful */ if (transfer->status == USBD_STATUS_RESET) { TRACE_INFO("MSDD_StateMachine: EP resetted\n\r"); } else if (transfer->status == USBD_STATUS_ABORTED) { TRACE_WARNING( "MSDD_StateMachine: Failed to send CSW\n\r"); } else { TRACE_INFO_WP("ok"); } /* Read new CBW */ pMsdDriver->state = MSDD_STATE_READ_CBW; } break; /*---------------------- */ case MSDD_STATE_WAIT_HALT: /*---------------------- */ //if (MSDD_IsHalted() == 0) { if (!USBD_IsHalted(commandState->pipeIN)) { pMsdDriver->state = MSDD_STATE_SEND_CSW; } break; } }
/**************************************************************************//** * @brief * Start a USB bulk-out transfer to get next CBW. *****************************************************************************/ __STATIC_INLINE void EnableNextCbw(void) { USBD_Read(BULK_OUT, (void*) &cbw, USB_MAX_EP_SIZE, CbwCallback); }
void spi_svc_start() { //Start listening on SPI endpoint USBD_Read(EP1_OUT, spi_svc_receive_buffer, SPI_BUFF_SIZE, spi_svc_data_receive_cb); }