/***************************************************************************//** * @brief * Query the stall state of an endpoint * * @param[in] epAddr * The address of the endpoint to query. * * @return * True if endpoint is stalled, false otherwise ******************************************************************************/ int USBD_EpIsStalled(int epAddr) { USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); if( !ep ) { return false; } return USBDHAL_EpIsStalled(ep); }
/***************************************************************************//** * @brief * Start a write (IN) transfer on an endpoint. * * @param[in] epAddr * Endpoint address. * * @param[in] data * Pointer to transfer data buffer. This buffer must be WORD (4 byte) aligned. * * @param[in] byteCount * Transfer length. * * @param[in] callback * Function to be called on transfer completion. Supply NULL if no callback * is needed. See @ref USB_XferCompleteCb_TypeDef. * * @return * @ref USB_STATUS_OK on success, else an appropriate error code. ******************************************************************************/ int USBD_Write( int epAddr, void *data, int byteCount, USB_XferCompleteCb_TypeDef callback ) { USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); CORE_DECLARE_IRQ_STATE; USB_PRINTF("USBD: Write addr %x, data %p, size %d, cb 0x%lx\n", epAddr, data, byteCount, (uint32_t)callback); if ( ep == NULL ) { DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal endpoint" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( ( byteCount > MAX_XFER_LEN ) || ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER ) ) { DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal transfer size" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( (uint32_t)data & 3 ) { DEBUG_USB_API_PUTS( "\nUSBD_Write(), Misaligned data buffer" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } CORE_ENTER_CRITICAL(); if ( USBDHAL_EpIsStalled( ep ) ) { CORE_EXIT_CRITICAL(); DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is halted" ); return USB_STATUS_EP_STALLED; } if ( ep->state != D_EP_IDLE ) { CORE_EXIT_CRITICAL(); DEBUG_USB_API_PUTS( "\nUSBD_Write(), Endpoint is busy" ); return USB_STATUS_EP_BUSY; } if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) ) { CORE_EXIT_CRITICAL(); DEBUG_USB_API_PUTS( "\nUSBD_Write(), Device not configured" ); return USB_STATUS_DEVICE_UNCONFIGURED; } ep->buf = (uint8_t*)data; ep->remaining = byteCount; ep->xferred = 0; if ( ep->num == 0 ) { ep->in = true; } else if ( ep->in != true ) { CORE_EXIT_CRITICAL(); DEBUG_USB_API_PUTS( "\nUSBD_Write(), Illegal EP direction" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } ep->state = D_EP_TRANSMITTING; ep->xferCompleteCb = callback; USBD_ArmEp( ep ); CORE_EXIT_CRITICAL(); return USB_STATUS_OK; }
/***************************************************************************//** * @brief * Start a read (OUT) transfer on an endpoint. * * @note * The transfer buffer length must be a multiple of 4 bytes in length and * WORD (4 byte) aligned. When allocating the buffer, round buffer length up. * If it is possible that the host will send more data than your device * expects, round buffer size up to the next multiple of maxpacket size. * * @param[in] epAddr * Endpoint address. * * @param[in] data * Pointer to transfer data buffer. * * @param[in] byteCount * Transfer length. * * @param[in] callback * Function to be called on transfer completion. Supply NULL if no callback * is needed. See @ref USB_XferCompleteCb_TypeDef. * * @return * @ref USB_STATUS_OK on success, else an appropriate error code. ******************************************************************************/ int USBD_Read( int epAddr, void *data, int byteCount, USB_XferCompleteCb_TypeDef callback ) { USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr ); if ( ep == NULL ) { DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal endpoint" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } if ( ( byteCount > MAX_XFER_LEN ) || ( ( byteCount / ep->packetSize ) > MAX_PACKETS_PR_XFER ) ) { DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal transfer size" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } #if !defined( USB_SLAVEMODE ) if ( (uint32_t)data & 3 ) { DEBUG_USB_API_PUTS( "\nUSBD_Read(), Misaligned data buffer" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } #endif INT_Disable(); if ( USBDHAL_EpIsStalled( ep ) ) { INT_Enable(); DEBUG_USB_API_PUTS( "\nUSBD_Read(), Endpoint is halted" ); return USB_STATUS_EP_STALLED; } if ( ep->state != D_EP_IDLE ) { INT_Enable(); DEBUG_USB_API_PUTS( "\nUSBD_Read(), Endpoint is busy" ); return USB_STATUS_EP_BUSY; } if ( ( ep->num > 0 ) && ( USBD_GetUsbState() != USBD_STATE_CONFIGURED ) ) { INT_Enable(); DEBUG_USB_API_PUTS( "\nUSBD_Read(), Device not configured" ); return USB_STATUS_DEVICE_UNCONFIGURED; } ep->buf = (uint8_t*)data; ep->remaining = byteCount; ep->xferred = 0; if ( ep->num == 0 ) { ep->in = false; } else if ( ep->in != false ) { INT_Enable(); DEBUG_USB_API_PUTS( "\nUSBD_Read(), Illegal EP direction" ); EFM_ASSERT( false ); return USB_STATUS_ILLEGAL; } ep->state = D_EP_RECEIVING; ep->xferCompleteCb = callback; USBD_ArmEp( ep ); INT_Enable(); return USB_STATUS_OK; }