/** * @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; }
/** * @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; }
/** * @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"); } }