/***************************************************************************//**
 * @brief       Handle Endpoint 2 OUT transfer interrupt
 * @note        This function takes no parameters, but it uses the EP2OUT status
 *              variables stored in @ref myUsbDevice.ep2out.
 ******************************************************************************/
void handleUsbOut2Int(void)
{
  uint8_t count;

  USB_Status_TypeDef status;
  bool xferComplete = false;

  USB_SetIndex(2);

  if (USB_EpnOutGetSentStall())
  {
    USB_EpnOutClearSentStall();
  }
  else if (USB_EpnGetOutPacketReady())
  {
    count = USB_EpOutGetCount();

    // If USBD_Read() has not been called, return an error
    if (myUsbDevice.ep2out.state != D_EP_RECEIVING)
    {
      myUsbDevice.ep2out.misc.bits.outPacketPending = true;
      status = USB_STATUS_EP_ERROR;
    }
    // Check for overrun of user buffer
    else if (myUsbDevice.ep2out.remaining < count)
    {
      myUsbDevice.ep2out.state = D_EP_IDLE;
      myUsbDevice.ep2out.misc.bits.outPacketPending = true;
      status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
    }
    else
    {
      USB_ReadFIFO(2, count, myUsbDevice.ep2out.buf);

      myUsbDevice.ep2out.misc.bits.outPacketPending = false;
      myUsbDevice.ep2out.remaining -= count;
      myUsbDevice.ep2out.buf += count;

      if ((myUsbDevice.ep2out.remaining == 0) || (count != SLAB_USB_EP2OUT_MAX_PACKET_SIZE))
      {
        myUsbDevice.ep2out.state = D_EP_IDLE;
        xferComplete = true;
      }

      status = USB_STATUS_OK;
      USB_EpnClearOutPacketReady();
    }
    if (myUsbDevice.ep2out.misc.bits.callback == true)
    {
      if (xferComplete == true)
      {
        myUsbDevice.ep2out.misc.bits.callback = false;
      }

      USBD_XferCompleteCb(EP2OUT, status, count, myUsbDevice.ep2out.remaining);
    }
  }
}
Example #2
0
/***************************************************************************//**
 * @brief       Reads and formats a setup packet
 ******************************************************************************/
static void USB_ReadFIFOSetup(void)
{
  uint16_t MEM_MODEL_SEG *ptr = &myUsbDevice.setup;

  USB_ReadFIFO(0, 8, (uint8_t *)ptr);

  USB_Ep0ServicedOutPacketReady();

  // Modify for Endian-ness of the compiler
  ptr[1] = le16toh(ptr[1]);
  ptr[2] = le16toh(ptr[2]);
  ptr[3] = le16toh(ptr[3]);
}
// ----------------------------------------------------------------------------
// If Isochronous mode is enabled and the max packet size is greater than 255,
// break the FIFO reads up into multiple reads of 255 or less bytes.
// ----------------------------------------------------------------------------
void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, uint8_t *dat)
{
  uint8_t numBytesRead;

  // USB_ReadFIFO() accepts a maximum of 255 bytes. If the number of bytes to
  // send is greated than 255, call USB_ReadFIFO() multiple times.
  while (numBytes > 0)
  {
    numBytesRead = (numBytes > 255) ? 255 : numBytes;
    USB_ReadFIFO(fifoNum, numBytesRead, dat);
    numBytes -= numBytesRead;
    dat += numBytesRead;
  }
}
Example #4
0
/***************************************************************************//**
 * @brief       Handles receive data phase on Endpoint 0
 ******************************************************************************/
void handleUsbEp0Rx(void)
{
  uint8_t count;
  USB_Status_TypeDef status;
  bool callback = myUsbDevice.ep0.misc.bits.callback;

  // Get the number of bytes received
  count = USB_Ep0GetCount();

  // If the call to USBD_Read() did not give a large enough buffer to hold this
  // data, set the outPacketPending flag and signal an RX overrun.
  if (myUsbDevice.ep0.remaining < count)
  {
    myUsbDevice.ep0.state = D_EP_IDLE;
    myUsbDevice.ep0.misc.bits.outPacketPending = true;
    status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
  }
  else
  {
    USB_ReadFIFO(0, count, myUsbDevice.ep0.buf);
    myUsbDevice.ep0.buf += count;
    myUsbDevice.ep0.remaining -= count;
    status = USB_STATUS_OK;

    // If the last packet of the transfer is exactly the maximum EP0 packet
    // size, we will must wait to receive a ZLP (zero-length packet) after the
    // last data packet. This signals that the host has completed the transfer.
    // Check for the ZLP packet case here.
    if ((myUsbDevice.ep0.remaining == 0) && (count != USB_EP0_SIZE))
    {
      USB_Ep0SetLastOutPacketReady();
      myUsbDevice.ep0.state = D_EP_IDLE;
      myUsbDevice.ep0.misc.bits.callback = false;
    }
    else
    {
      // Do not call USB_Ep0SetLastOutPacketReady() until we get the ZLP.
      USB_Ep0ServicedOutPacketReady();
    }
  }

  // Make callback if requested
  if (callback == true)
  {
    USBD_XferCompleteCb(EP0, status, count, myUsbDevice.ep0.remaining);
  }
}
/***************************************************************************//**
 * @brief       Handle Endpoint 3 OUT transfer interrupt
 * @details     Endpoint 3 OUT is the only OUT endpoint that supports
 *              isochronous transfers.
 * @note        This function takes no parameters, but it uses the EP3OUT status
 *              variables stored in @ref myUsbDevice.ep3out.
 ******************************************************************************/
void handleUsbOut3Int(void)
{
#if (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
  uint16_t nextIdx;
#if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255)
  uint16_t count;
#else
  uint8_t count;
#endif // ( SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255 )
#else
  uint8_t count;
#endif // ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC )

  USB_Status_TypeDef status;
  bool xferComplete = false;

  USB_SetIndex(3);

  if (USB_EpnOutGetSentStall())
  {
    USB_EpnOutClearSentStall();
  }
  else if (USB_EpnGetOutPacketReady())
  {
    count = USB_EpOutGetCount();

    // If USBD_Read() has not been called, return an error
    if (myUsbDevice.ep3out.state != D_EP_RECEIVING)
    {
      myUsbDevice.ep3out.misc.bits.outPacketPending = true;
      status = USB_STATUS_EP_ERROR;
    }
#if  ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
    // Check for overrun of user buffer
    else if (myUsbDevice.ep3out.remaining < count)
    {
      myUsbDevice.ep3out.state = D_EP_IDLE;
      myUsbDevice.ep3out.misc.bits.outPacketPending = true;
      status = USB_STATUS_EP_RX_BUFFER_OVERRUN;
    }
#endif
    else
    {
#if  ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
      USB_ReadFIFO(3, count, myUsbDevice.ep3out.buf);

      myUsbDevice.ep3out.remaining -= count;
      myUsbDevice.ep3out.buf += count;

      if ((myUsbDevice.ep3out.remaining == 0) || (count != SLAB_USB_EP3OUT_MAX_PACKET_SIZE))
      {
        myUsbDevice.ep3out.state = D_EP_IDLE;
        xferComplete = true;
      }
#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)
      nextIdx = count + myUsbDevice.ep3outIsoIdx;

      // In isochronous mode, a circular buffer is used to hold the data
      // If the next index into the circular buffer passes the end of the
      // buffer, make two calls to USB_ReadFIFOIso()
      if (nextIdx > myUsbDevice.ep3out.remaining)
      {
        USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
        myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining;
        USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf);
      }
      else
      {
        USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]);
        myUsbDevice.ep3outIsoIdx = nextIdx;
      }
#endif // ( ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK ) || ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR ) )

      myUsbDevice.ep3out.misc.bits.outPacketPending = false;
      status = USB_STATUS_OK;
      USB_EpnClearOutPacketReady();
    }
    if (myUsbDevice.ep3out.misc.bits.callback == true)
    {
      if (xferComplete == true)
      {
        myUsbDevice.ep3out.misc.bits.callback = false;
      }

#if  ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR))
      USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3out.remaining);
#elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC)

      // In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes:
      //   xferred is the number of bytes received in the last packet
      //   remaining is the current index into the circular buffer
      USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx);
#endif
    }
  }
}