Beispiel #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;
}
Beispiel #2
0
/**
 * @brief   Default EP0 IN callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 IN events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
  size_t max;

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_TX:
    max = (size_t)get_hword(&usbp->setup[6]);
    /* If the transmitted size is less than the requested size and it is a
       multiple of the maximum packet size then a zero size packet must be
       transmitted.*/
    if ((usbp->ep0n < max) &&
        ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
      usbPrepareTransmit(usbp, 0, NULL, 0);
      osalSysLockFromISR();
      (void) usbStartTransmitI(usbp, 0);
      osalSysUnlockFromISR();
      usbp->ep0state = USB_EP0_WAITING_TX0;
      return;
    }
    /* Falls into, it is intentional.*/
  case USB_EP0_WAITING_TX0:
    /* Transmit phase over, receiving the zero sized status packet.*/
    usbp->ep0state = USB_EP0_WAITING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
    usbPrepareReceive(usbp, 0, NULL, 0);
    osalSysLockFromISR();
    (void) usbStartReceiveI(usbp, 0);
    osalSysUnlockFromISR();
#else
    usb_lld_end_setup(usbp, ep);
#endif
    return;
  case USB_EP0_SENDING_STS:
    /* Status packet sent, invoking the callback if defined.*/
    if (usbp->ep0endcb != NULL) {
      usbp->ep0endcb(usbp);
    }
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  case USB_EP0_WAITING_SETUP:
  case USB_EP0_WAITING_STS:
  case USB_EP0_RX:
    /* 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");
  }
}
Beispiel #3
0
/**
 * @brief   Stalls an OUT endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @return              The operation status.
 * @retval false        Endpoint stalled.
 * @retval true         Endpoint busy, not stalled.
 *
 * @iclass
 */
bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) {

  osalDbgCheckClassI();
  osalDbgCheck(usbp != NULL);

  if (usbGetReceiveStatusI(usbp, ep))
    return true;

  usb_lld_stall_out(usbp, ep);
  return false;
}
Beispiel #4
0
/**
 * @brief   Stalls an OUT endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @return              The operation status.
 * @retval FALSE        Endpoint stalled.
 * @retval TRUE         Endpoint busy, not stalled.
 *
 * @iclass
 */
bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) {

  chDbgCheckClassI();
  chDbgCheck(usbp != NULL, "usbStallReceiveI");

  if (usbGetReceiveStatusI(usbp, ep))
    return TRUE;

  usb_lld_stall_out(usbp, ep);
  return FALSE;
}
Beispiel #5
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");
  }
}
Beispiel #6
0
/**
 * @brief   Default EP0 IN callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 IN events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
  size_t max;

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_TX:
    max = usbFetchWord(&usbp->setup[6]);
    /* If the transmitted size is less than the requested size and it is a
       multiple of the maximum packet size then a zero size packet must be
       transmitted.*/
    if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
      usbPrepareTransmit(usbp, 0, NULL, 0);
      chSysLockFromIsr();
      usbStartTransmitI(usbp, 0);
      chSysUnlockFromIsr();
      usbp->ep0state = USB_EP0_WAITING_TX0;
      return;
    }
    /* Falls into, it is intentional.*/
  case USB_EP0_WAITING_TX0:
    /* Transmit phase over, receiving the zero sized status packet.*/
    usbp->ep0state = USB_EP0_WAITING_STS;
    usbPrepareReceive(usbp, 0, NULL, 0);
    chSysLockFromIsr();
    usbStartReceiveI(usbp, 0);
    chSysUnlockFromIsr();
    return;
  case USB_EP0_SENDING_STS:
    /* Status packet sent, invoking the callback if defined.*/
    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;
}
Beispiel #7
0
/**
 * @brief   Standard requests handler.
 * @details This is the standard requests default handler, most standard
 *          requests are handled here, the user can override the standard
 *          handling using the @p requests_hook_cb hook in the
 *          @p USBConfig structure.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @return              The request handling exit code.
 * @retval false        Request not recognized by the handler or error.
 * @retval true         Request handled.
 */
static bool default_handler(USBDriver *usbp) {
  const USBDescriptor *dp;

  /* Decoding the request.*/
  switch (((usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK |
                              USB_RTYPE_TYPE_MASK)) |
           (usbp->setup[1] << 8))) {
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_STATUS << 8):
    /* Just returns the current status word.*/
    usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_CLEAR_FEATURE << 8):
    /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
       number is handled as an error.*/
    if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
      usbp->status &= ~2;
      usbSetupTransfer(usbp, NULL, 0, NULL);
      return true;
    }
    return false;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_FEATURE << 8):
    /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
       number is handled as an error.*/
    if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
      usbp->status |= 2;
      usbSetupTransfer(usbp, NULL, 0, NULL);
      return true;
    }
    return false;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_ADDRESS << 8):
    /* The SET_ADDRESS handling can be performed here or postponed after
       the status packed depending on the USB_SET_ADDRESS_MODE low
       driver setting.*/
#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS
    if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) &&
        (usbp->setup[1] == USB_REQ_SET_ADDRESS))
      set_address(usbp);
    usbSetupTransfer(usbp, NULL, 0, NULL);
#else
    usbSetupTransfer(usbp, NULL, 0, set_address);
#endif
    return true;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_DESCRIPTOR << 8):
    /* Handling descriptor requests from the host.*/
    dp = usbp->config->get_descriptor_cb(
           usbp, usbp->setup[3], usbp->setup[2],
           usbFetchWord(&usbp->setup[4]));
    if (dp == NULL)
      return false;
    usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_CONFIGURATION << 8):
    /* Returning the last selected configuration.*/
    usbSetupTransfer(usbp, &usbp->configuration, 1, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_CONFIGURATION << 8):
    /* Handling configuration selection from the host.*/
    usbp->configuration = usbp->setup[2];
    if (usbp->configuration == 0)
      usbp->state = USB_SELECTED;
    else
      usbp->state = USB_ACTIVE;
    _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED);
    usbSetupTransfer(usbp, NULL, 0, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_STATUS << 8):
  case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_SYNCH_FRAME << 8):
    /* Just sending two zero bytes, the application can change the behavior
       using a hook..*/
    usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_GET_STATUS << 8):
    /* Sending the EP status.*/
    if (usbp->setup[4] & 0x80) {
      switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0F)) {
      case EP_STATUS_STALLED:
        usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
        return true;
      case EP_STATUS_ACTIVE:
        usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
        return true;
      default:
        return false;
      }
    }
    else {
      switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0F)) {
      case EP_STATUS_STALLED:
        usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
        return true;
      case EP_STATUS_ACTIVE:
        usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
        return true;
      default:
        return false;
      }
    }
  case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_CLEAR_FEATURE << 8):
    /* Only ENDPOINT_HALT is handled as feature.*/
    if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT)
      return false;
    /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/
    if ((usbp->setup[4] & 0x0F) > 0) {
      if (usbp->setup[4] & 0x80)
        usb_lld_clear_in(usbp, usbp->setup[4] & 0x0F);
      else
        usb_lld_clear_out(usbp, usbp->setup[4] & 0x0F);
    }
    usbSetupTransfer(usbp, NULL, 0, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_SET_FEATURE << 8):
    /* Only ENDPOINT_HALT is handled as feature.*/
    if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT)
      return false;
    /* Stalling the EP, not valid for EP0, it is ignored in that case.*/
    if ((usbp->setup[4] & 0x0F) > 0) {
      if (usbp->setup[4] & 0x80)
        usb_lld_stall_in(usbp, usbp->setup[4] & 0x0F);
      else
        usb_lld_stall_out(usbp, usbp->setup[4] & 0x0F);
    }
    usbSetupTransfer(usbp, NULL, 0, NULL);
    return true;
  case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_DESCRIPTOR << 8):
  case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_CLEAR_FEATURE << 8):
  case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_SET_FEATURE << 8):
  case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_INTERFACE << 8):
  case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_SET_INTERFACE << 8):
    /* All the above requests are not handled here, if you need them then
       use the hook mechanism and provide handling.*/
  default:
    return false;
  }
}
Beispiel #8
0
/**
 * @brief   Default EP0 SETUP callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 SETUP events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
  size_t max;

  usbp->ep0state = USB_EP0_WAITING_SETUP;
  usbReadSetup(usbp, ep, usbp->setup);

  /* First verify if the application has an handler installed for this
     request.*/
  if (!(usbp->config->requests_hook_cb) ||
      !(usbp->config->requests_hook_cb(usbp))) {
    /* Invoking the default handler, if this fails then stalls the
       endpoint zero as error.*/
    if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) ||
        !default_handler(usbp)) {
      /* 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;
    }
  }
#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW)
  if (usbp->setup[1] == USB_REQ_SET_ADDRESS) {
    /* Zero-length packet sent by hardware */
    return;
  }
#endif
  /* Transfer preparation. The request handler must have populated
     correctly the fields ep0next, ep0n and ep0endcb using the macro
     usbSetupTransfer().*/
  max = usbFetchWord(&usbp->setup[6]);
  /* The transfer size cannot exceed the specified amount.*/
  if (usbp->ep0n > max)
    usbp->ep0n = max;
  if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) {
    /* IN phase.*/
    if (usbp->ep0n > 0) {
      /* Starts the transmit phase.*/
      usbp->ep0state = USB_EP0_TX;
      usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n);
      osalSysLockFromISR();
      usbStartTransmitI(usbp, 0);
      osalSysUnlockFromISR();
    }
    else {
      /* No transmission phase, directly receiving the zero sized status
         packet.*/
      usbp->ep0state = USB_EP0_WAITING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
      usbPrepareReceive(usbp, 0, NULL, 0);
      osalSysLockFromISR();
      usbStartReceiveI(usbp, 0);
      osalSysUnlockFromISR();
#else
      usb_lld_end_setup(usbp, ep);
#endif
    }
  }
  else {
    /* OUT phase.*/
    if (usbp->ep0n > 0) {
      /* Starts the receive phase.*/
      usbp->ep0state = USB_EP0_RX;
      usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n);
      osalSysLockFromISR();
      usbStartReceiveI(usbp, 0);
      osalSysUnlockFromISR();
    }
    else {
      /* No receive phase, directly 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();
      usbStartTransmitI(usbp, 0);
      osalSysUnlockFromISR();
#else
      usb_lld_end_setup(usbp, ep);
#endif
    }
  }
}
Beispiel #9
0
/**
 * @brief   Standard requests handler.
 * @details This is the standard requests default handler, most standard
 *          requests are handled here, the user can override the standard
 *          handling using the @p requests_hook_cb hook in the
 *          @p USBConfig structure.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @return              The request handling exit code.
 * @retval false        Request not recognized by the handler or error.
 * @retval true         Request handled.
 */
static bool default_handler(USBDriver *usbp) {
  const USBDescriptor *dp;

  /* Decoding the request.*/
  switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK |
                                        USB_RTYPE_TYPE_MASK)) |
           ((uint32_t)usbp->setup[1] << 8U))) {
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_STATUS << 8):
    /* Just returns the current status word.*/
    usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL);
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
    /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
       number is handled as an error.*/
    if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
      usbp->status &= ~2U;
      usbSetupTransfer(usbp, NULL, 0, NULL);
      return true;
    }
    return false;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_FEATURE << 8):
    /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
       number is handled as an error.*/
    if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
      usbp->status |= 2U;
      usbSetupTransfer(usbp, NULL, 0, NULL);
      return true;
    }
    return false;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_ADDRESS << 8):
    /* The SET_ADDRESS handling can be performed here or postponed after
       the status packed depending on the USB_SET_ADDRESS_MODE low
       driver setting.*/
#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS
    if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) &&
        (usbp->setup[1] == USB_REQ_SET_ADDRESS)) {
      set_address(usbp);
    }
    usbSetupTransfer(usbp, NULL, 0, NULL);
#else
    usbSetupTransfer(usbp, NULL, 0, set_address);
#endif
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8):
    /* Handling descriptor requests from the host.*/
    dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3],
                                         usbp->setup[2],
                                         get_hword(&usbp->setup[4]));
    if (dp == NULL) {
      return false;
    }
    /*lint -save -e9005 [11.8] Removing const is fine.*/
    usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
    /*lint -restore*/
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_CONFIGURATION << 8):
    /* Returning the last selected configuration.*/
    usbSetupTransfer(usbp, &usbp->configuration, 1, NULL);
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_CONFIGURATION << 8):
    /* Handling configuration selection from the host only if it is different
       from the current configuration.*/
    if (usbp->configuration != usbp->setup[2]) {
      /* If the USB device is already active then we have to perform the clear
         procedure on the current configuration.*/
      if (usbp->state == USB_ACTIVE) {
        /* Current configuration cleared.*/
        osalSysLockFromISR ();
        usbDisableEndpointsI(usbp);
        osalSysUnlockFromISR ();
        usbp->configuration = 0U;
        usbp->state = USB_SELECTED;
        _usb_isr_invoke_event_cb(usbp, USB_EVENT_UNCONFIGURED);
      }
      if (usbp->setup[2] != 0U) {
        /* New configuration.*/
        usbp->configuration = usbp->setup[2];
        usbp->state = USB_ACTIVE;
        _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED);
      }
    }
    usbSetupTransfer(usbp, NULL, 0, NULL);
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_STATUS << 8):
  case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SYNCH_FRAME << 8):
    /* Just sending two zero bytes, the application can change the behavior
       using a hook..*/
    /*lint -save -e9005 [11.8] Removing const is fine.*/
    usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL);
    /*lint -restore*/
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_GET_STATUS << 8):
    /* Sending the EP status.*/
    if ((usbp->setup[4] & 0x80U) != 0U) {
      switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) {
      case EP_STATUS_STALLED:
        /*lint -save -e9005 [11.8] Removing const is fine.*/
        usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
        /*lint -restore*/
        return true;
      case EP_STATUS_ACTIVE:
        /*lint -save -e9005 [11.8] Removing const is fine.*/
        usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
        /*lint -restore*/
        return true;
      case EP_STATUS_DISABLED:
      default:
        return false;
      }
    }
    else {
      switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) {
      case EP_STATUS_STALLED:
        /*lint -save -e9005 [11.8] Removing const is fine.*/
        usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
        /*lint -restore*/
        return true;
      case EP_STATUS_ACTIVE:
        /*lint -save -e9005 [11.8] Removing const is fine.*/
        usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
        /*lint -restore*/
        return true;
      case EP_STATUS_DISABLED:
      default:
        return false;
      }
    }
  case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
    /* Only ENDPOINT_HALT is handled as feature.*/
    if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) {
      return false;
    }
    /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/
    if ((usbp->setup[4] & 0x0FU) != 0U) {
      if ((usbp->setup[4] & 0x80U) != 0U) {
        usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU);
      }
      else {
        usb_lld_clear_out(usbp, usbp->setup[4] & 0x0FU);
      }
    }
    usbSetupTransfer(usbp, NULL, 0, NULL);
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SET_FEATURE << 8):
    /* Only ENDPOINT_HALT is handled as feature.*/
    if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) {
      return false;
    }
    /* Stalling the EP, not valid for EP0, it is ignored in that case.*/
    if ((usbp->setup[4] & 0x0FU) != 0U) {
      if ((usbp->setup[4] & 0x80U) != 0U) {
        usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU);
      }
      else {
        usb_lld_stall_out(usbp, usbp->setup[4] & 0x0FU);
      }
    }
    usbSetupTransfer(usbp, NULL, 0, NULL);
    return true;
  case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_DESCRIPTOR << 8):
  case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
  case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_FEATURE << 8):
  case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_INTERFACE << 8):
  case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_INTERFACE << 8):
    /* All the above requests are not handled here, if you need them then
       use the hook mechanism and provide handling.*/
  default:
    return false;
  }
}
Beispiel #10
0
/**
 * @brief   Brings an IN endpoint in the stalled state.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @notapi
 */
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep) {
  usb_lld_stall_out(usbp, ep);
}