예제 #1
0
/**
 * @brief   Default EP0 OUT callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 OUT events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0out(USBDriver *usbp, usbep_t ep) {

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_RX:
    /* Receive phase over, sending the zero sized status packet.*/
    usbp->ep0state = USB_EP0_SENDING_STS;
    usbPrepareTransmit(usbp, 0, NULL, 0);
    chSysLockFromIsr();
    usbStartTransmitI(usbp, 0);
    chSysUnlockFromIsr();
    return;
  case USB_EP0_WAITING_STS:
    /* Status packet received, it must be zero sized, invoking the callback
       if defined.*/
    if (usbGetReceiveTransactionSizeI(usbp, 0) != 0)
      break;
    if (usbp->ep0endcb != NULL)
      usbp->ep0endcb(usbp);
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  default:
    ;
  }
  /* Error response, the state machine goes into an error state, the low
     level layer will have to reset it to USB_EP0_WAITING_SETUP after
     receiving a SETUP packet.*/
  usb_lld_stall_in(usbp, 0);
  usb_lld_stall_out(usbp, 0);
  _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
  usbp->ep0state = USB_EP0_ERROR;
}
예제 #2
0
/**
 * @brief   Default data received callback.
 * @details The application must use this function as callback for the OUT
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void mscDataReceived(USBDriver *usbp, usbep_t ep) {
  size_t n;

  n = usbGetReceiveTransactionSizeI(usbp, ep);
  switch (msc_state) {
  case MSC_IDLE:
    if ((n != sizeof(msccbw_t)) || (CBW.dCBWSignature != MSC_CBW_SIGNATURE))
      goto stall_out; /* 6.6.1 */

    /* Decoding SCSI command.*/
    if (msc_decode(usbp)) {
      if (CBW.dCBWDataTransferLength == 0) {
        CSW.bCSWStatus = MSC_CSW_STATUS_FAILED;
        CSW.dCSWDataResidue = 0;
        msc_sendstatus(usbp);
        return;
      }
      goto stall_both;
    }

    /* Commands with zero transfer length, 5.1.*/
    if (CBW.dCBWDataTransferLength == 0) {
      msc_sendstatus(usbp);
      return;
    }

    /* Transfer direction.*/
    if (CBW.bmCBWFlags & 0x80) {
      /* IN, Device to Host.*/
      msc_state = MSC_DATA_IN;
    }
    else {
      /* OUT, Host to Device.*/
      msc_state = MSC_DATA_OUT;
    }
    break;
  case MSC_DATA_OUT:
    break;
  default:
    ;
  }
  return;
stall_out:
  msc_state = MSC_ERROR;
  chSysLockFromIsr();
  usbStallReceiveI(usbp, ep);
  chSysUnlockFromIsr();
  return;
stall_both:
  msc_state = MSC_ERROR;
  chSysLockFromIsr();
  usbStallTransmitI(usbp, ep);
  usbStallReceiveI(usbp, ep);
  chSysUnlockFromIsr();
  return;
}
예제 #3
0
/**
 * @brief   Default EP0 OUT callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 OUT events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0out(USBDriver *usbp, usbep_t ep) {

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_RX:
    /* Receive phase over, sending the zero sized status packet.*/
    usbp->ep0state = USB_EP0_SENDING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
    usbPrepareTransmit(usbp, 0, NULL, 0);
    osalSysLockFromISR();
    (void) usbStartTransmitI(usbp, 0);
    osalSysUnlockFromISR();
#else
    usb_lld_end_setup(usbp, ep);
#endif
    return;
  case USB_EP0_WAITING_STS:
    /* Status packet received, it must be zero sized, invoking the callback
       if defined.*/
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
    if (usbGetReceiveTransactionSizeI(usbp, 0) != 0U) {
      break;
    }
#endif
    if (usbp->ep0endcb != NULL) {
      usbp->ep0endcb(usbp);
    }
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  case USB_EP0_WAITING_SETUP:
  case USB_EP0_TX:
  case USB_EP0_WAITING_TX0:
  case USB_EP0_SENDING_STS:
    /* All the above are invalid states in the IN phase.*/
    osalDbgAssert(false, "EP0 state machine error");
    /* Falling through is intentional.*/
  case USB_EP0_ERROR:
    /* Error response, the state machine goes into an error state, the low
       level layer will have to reset it to USB_EP0_WAITING_SETUP after
       receiving a SETUP packet.*/
    usb_lld_stall_in(usbp, 0);
    usb_lld_stall_out(usbp, 0);
    _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
    usbp->ep0state = USB_EP0_ERROR;
    return;
  default:
    osalDbgAssert(false, "EP0 state machine invalid state");
  }
}