예제 #1
0
파일: em_usbd.c 프로젝트: Archcady/mbed-os
/***************************************************************************//**
 * @brief
 *   Reset stall state on a stalled (halted) endpoint.
 *
 * @param[in] epAddr
 *   The address of the endpoint to un-stall.
 *
 * @return
 *   @ref USB_STATUS_OK on success, else an appropriate error code.
 ******************************************************************************/
int USBD_UnStallEp( int epAddr )
{
  USB_Status_TypeDef retVal;
  CORE_DECLARE_IRQ_STATE;
  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );

  if ( ep == NULL )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal request" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( ep->num == 0 )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal endpoint" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  CORE_ENTER_CRITICAL();
  retVal = USBDHAL_UnStallEp( ep );
  CORE_EXIT_CRITICAL();

  if ( retVal != USB_STATUS_OK )
  {
    retVal = USB_STATUS_ILLEGAL;
  }

  return retVal;
}
예제 #2
0
/***************************************************************************//**
 * @brief
 *   Reset stall state on a stalled (halted) endpoint.
 *
 * @param[in] epAddr
 *   The address of the endpoint to un-stall.
 *
 * @return
 *   @ref USB_STATUS_OK on success, else an appropriate error code.
 ******************************************************************************/
int USBD_UnStallEp( int epAddr )
{
  USB_Status_TypeDef retVal;
  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );

  if ( ep == NULL )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal request" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( ep->num == 0 )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_UnStallEp(), Illegal endpoint" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  INT_Disable();
  retVal = USBDHAL_UnStallEp( ep );
  INT_Enable();

  if ( retVal != USB_STATUS_OK )
  {
    retVal = USB_STATUS_ILLEGAL;
  }

  return retVal;
}
예제 #3
0
/*
 * Handle IN endpoint transfer interrupt.
 */
static void Handle_USB_GINTSTS_IEPINT( void )
{
  int epnum;
  uint16_t epint;
  uint16_t epmask;
  uint32_t status;
  USBD_Ep_TypeDef *ep;

  DEBUG_USB_INT_HI_PUTCHAR( 'i' );

  epint = USBDHAL_GetAllInEpInts();
  for ( epnum = 0,                epmask = 1;
        epnum <= MAX_NUM_IN_EPS;
        epnum++,                  epmask <<= 1 )
  {
    if ( epint & epmask )
    {
      ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | epnum );
      status = USBDHAL_GetInEpInts( ep );

      if ( status & USB_DIEP_INT_XFERCOMPL )
      {
        USB_DINEPS[ epnum ].INT = USB_DIEP_INT_XFERCOMPL;

        DEBUG_USB_INT_HI_PUTCHAR( 'c' );

        if ( epnum == 0 )
        {
          if ( ep->remaining > ep->packetSize )
          {
            ep->remaining -= ep->packetSize;
            ep->xferred += ep->packetSize;
          }
          else
          {
            ep->xferred += ep->remaining;
            ep->remaining = 0;
          }
          USBDEP_Ep0Handler( dev );
        }
        else
        {
          ep->xferred = ep->remaining -
                        ( ( USB_DINEPS[ epnum ].TSIZ      &
                            _USB_DIEP_TSIZ_XFERSIZE_MASK    ) >>
                          _USB_DIEP_TSIZ_XFERSIZE_SHIFT          );
          ep->remaining -= ep->xferred;

          USBDEP_EpHandler( ep->addr );
#if defined( USB_DOEP0INT_STUPPKTRCVD )
          if ( USB_DINEPS[ ep->num ].INT & USB_DIEP_INT_NAKINTRPT )
          {
            USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_NAKINTRPT;
          }
#endif
        }
      }
    }
예제 #4
0
파일: em_usbd.c 프로젝트: Archcady/mbed-os
/***************************************************************************//**
 * @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);
}
예제 #5
0
파일: em_usbd.c 프로젝트: Archcady/mbed-os
/***************************************************************************//**
 * @brief
 *   Set an endpoint0 in the stalled (halted) state.
 *
 * @details
 *   Temporarily stalls endpoint 0. Used to signal a failure to respond to
 *   the host's setup packet.
 ******************************************************************************/
void USBD_StallEp0()
{
    int const epAddr = 0;
    USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
    ep->in = true;
    USBDHAL_StallEp( ep ); /* Stall Ep0 IN */
    ep->in = false; /* OUT for next SETUP */
    USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */
#if !defined( USB_DOEP0INT_STUPPKTRCVD )
    USBDHAL_ReenableEp0Setup( dev ); /* Prepare for next SETUP pkt. */
#else
    USBDHAL_StartEp0Setup( dev );
#endif
    ep->state = D_EP_IDLE;
}
예제 #6
0
파일: em_usbd.c 프로젝트: Archcady/mbed-os
/***************************************************************************//**
 * @brief
 *   Abort a pending transfer on a specific endpoint.
 *
 * @param[in] epAddr
 *   The address of the endpoint to abort.
 ******************************************************************************/
int USBD_AbortTransfer( int epAddr )
{
  USB_XferCompleteCb_TypeDef callback;
  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
  CORE_DECLARE_IRQ_STATE;

  if ( ep == NULL )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_AbortTransfer(), Illegal endpoint" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( ep->num == 0 )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_AbortTransfer(), Illegal endpoint" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  CORE_ENTER_CRITICAL();
  if ( ep->state == D_EP_IDLE )
  {
    CORE_EXIT_CRITICAL();
    return USB_STATUS_OK;
  }

  USBD_AbortEp( ep );

  ep->state = D_EP_IDLE;
  if ( ep->xferCompleteCb )
  {
    callback = ep->xferCompleteCb;
    ep->xferCompleteCb = NULL;

    if ( ( dev->lastState == USBD_STATE_CONFIGURED ) &&
         ( dev->state     == USBD_STATE_ADDRESSED  )    )
    {
      USBDHAL_DeactivateEp( ep );
    }

    DEBUG_TRACE_ABORT( USB_STATUS_EP_ABORTED );
    callback( USB_STATUS_EP_ABORTED, ep->xferred, ep->remaining );
  }

  CORE_EXIT_CRITICAL();
  return USB_STATUS_OK;
}
예제 #7
0
파일: em_usbd.c 프로젝트: Archcady/mbed-os
/***************************************************************************//**
 * @brief
 *   Check if an endpoint is busy doing a transfer.
 *
 * @param[in] epAddr
 *   The address of the endpoint to check.
 *
 * @return
 *   True if endpoint is busy, false otherwise.
 ******************************************************************************/
bool USBD_EpIsBusy( int epAddr )
{
  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );

  if ( ep == NULL )
  {
    DEBUG_USB_API_PUTS( "\nUSBD_EpIsBusy(), Illegal endpoint" );
    EFM_ASSERT( false );
    return USB_STATUS_ILLEGAL;
  }

  if ( ep->state == D_EP_IDLE )
    return false;

  return true;
}
예제 #8
0
/*
 * USBDEP_EpHandler() is called each time a packet has been transmitted
 * or recieved on an endpoint other than the default endpoint.
 */
void USBDEP_EpHandler( uint8_t epAddr )
{
  USB_XferCompleteCb_TypeDef callback;
  USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );

  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 );
    }
  }
  else
  {
    EFM_ASSERT( false );
  }
}
예제 #9
0
파일: em_usbd.c 프로젝트: Archcady/mbed-os
/***************************************************************************//**
 * @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;
}
예제 #10
0
/***************************************************************************//**
 * @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;
}