Example #1
0
//! This function manages the CLEAR FEATURE request.
//!
void usb_clear_feature(void)
{
   U8 wValue;
   U8 wIndex;

   switch (bmRequestType)
   {
#if (USB_REMOTE_WAKEUP_FEATURE == true)
      case  USB_SETUP_SET_STAND_DEVICE:
      wValue = Usb_read_endpoint_data(EP_CONTROL, 8);
      if (wValue != FEATURE_DEVICE_REMOTE_WAKEUP)
         break;              // Invalid request
      device_status &= ~USB_DEV_STATUS_REMOTEWAKEUP;
      remote_wakeup_feature = false;
      Usb_ack_setup_received_free();
      Usb_ack_control_in_ready_send();
      return;
#endif

      case USB_SETUP_SET_STAND_INTERFACE:
      break;

      case USB_SETUP_SET_STAND_ENDPOINT:
      wValue = Usb_read_endpoint_data(EP_CONTROL, 8);
      if (wValue != FEATURE_ENDPOINT_HALT)
         break;
      Usb_read_endpoint_data(EP_CONTROL, 8);  //!< dummy read (MSB of wValue)
      wIndex = Usb_read_endpoint_data(EP_CONTROL, 8);
      wIndex = Get_desc_ep_nbr(wIndex);

      if (!Is_usb_endpoint_enabled(wIndex))
         break;
      if (wIndex != EP_CONTROL)
      {
        Usb_disable_stall_handshake(wIndex);
        Usb_reset_endpoint(wIndex);
        Usb_reset_data_toggle(wIndex);
      }
      Usb_ack_setup_received_free();
      Usb_ack_control_in_ready_send();
      return;

      default:
      break;
   }
   Usb_enable_stall_handshake(EP_CONTROL);
   Usb_ack_setup_received_free();
}
//! This function manages the CLEAR FEATURE request.
//!
void usb_clear_feature(void)
{
  U8 wValue;
  U8 wIndex;

  if (bmRequestType == DEVICE_TYPE || bmRequestType == INTERFACE_TYPE)
  {
    //!< keep that order (set StallRq/clear RxSetup) or a
    //!< OUT request following the SETUP may be acknowledged
    Usb_enable_stall_handshake(EP_CONTROL);
    Usb_ack_setup_received_free();
  }
  else if (bmRequestType == ENDPOINT_TYPE)
  {
    wValue = Usb_read_endpoint_data(EP_CONTROL, 8);

    if (wValue == FEATURE_ENDPOINT_HALT)
    {
      Usb_read_endpoint_data(EP_CONTROL, 8);  //!< dummy read (MSB of wValue)
      wIndex = Usb_read_endpoint_data(EP_CONTROL, 8);
      wIndex = Get_desc_ep_nbr(wIndex);

      if (Is_usb_endpoint_enabled(wIndex))
      {
        if (wIndex != EP_CONTROL)
        {
          Usb_disable_stall_handshake(wIndex);
          Usb_reset_endpoint(wIndex);
          Usb_reset_data_toggle(wIndex);
        }
        endpoint_status[wIndex] = 0;  // Halt feature flag
        Usb_ack_setup_received_free();
        Usb_ack_control_in_ready_send();
      }
      else
      {
        Usb_enable_stall_handshake(EP_CONTROL);
        Usb_ack_setup_received_free();
      }
    }
    else
    {
      Usb_enable_stall_handshake(EP_CONTROL);
      Usb_ack_setup_received_free();
    }
  }
}
Example #3
0
//! This function manages the GET STATUS request. The device, interface or
//! endpoint status is returned.
//!
void usb_get_status(void)
{
  U8 wIndex;

  switch (bmRequestType)
  {
  case REQUEST_DEVICE_STATUS:
    Usb_ack_setup_received_free();
    Usb_reset_endpoint_fifo_access(EP_CONTROL);
    Usb_write_endpoint_data(EP_CONTROL, 8, device_status);
    break;

  case REQUEST_INTERFACE_STATUS:
    Usb_ack_setup_received_free();
    Usb_reset_endpoint_fifo_access(EP_CONTROL);
    Usb_write_endpoint_data(EP_CONTROL, 8, INTERFACE_STATUS);
    break;

  case REQUEST_ENDPOINT_STATUS:
    Usb_read_endpoint_data(EP_CONTROL, 16); //!< dummy read (wValue)
    wIndex = Usb_read_endpoint_data(EP_CONTROL, 8);
    wIndex = Get_desc_ep_nbr(wIndex);
    Usb_ack_setup_received_free();
    Usb_reset_endpoint_fifo_access(EP_CONTROL);
    Usb_write_endpoint_data(EP_CONTROL, 8, Is_usb_endpoint_stall_requested(wIndex) );
    break;

  default:
    Usb_enable_stall_handshake(EP_CONTROL);
    Usb_ack_setup_received_free();
    return;
  }

  Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
  Usb_ack_control_in_ready_send();

  while (!Is_usb_control_out_received());
  Usb_ack_control_out_received_free();
}
Example #4
0
//! This function manages the SET FEATURE request. The USB test modes are
//! supported by this function.
//!
void usb_set_feature(void)
{
  U16 wValue  = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
  U16 wIndex  = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
  U16 wLength = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));

  if (wLength)
    goto unsupported_request;

   if (bmRequestType==USB_SETUP_SET_STAND_DEVICE) {
#if (USB_REMOTE_WAKEUP_FEATURE == true)
      if (FEATURE_DEVICE_REMOTE_WAKEUP == wValue)
      {
         device_status |= USB_DEV_STATUS_REMOTEWAKEUP;
         remote_wakeup_feature = true;
         Usb_ack_setup_received_free();
         Usb_ack_control_in_ready_send();
         return;
      }
#endif
      goto unsupported_request;
   }

  switch (wValue)
  {
  case FEATURE_ENDPOINT_HALT:
    wIndex = Get_desc_ep_nbr(wIndex);  // clear direction flag
    if (bmRequestType != ENDPOINT_TYPE ||
        wIndex == EP_CONTROL ||
        !Is_usb_endpoint_enabled(wIndex))
      goto unsupported_request;

    Usb_enable_stall_handshake(wIndex);
    Usb_ack_setup_received_free();
    Usb_ack_control_in_ready_send();
    break;

#if (USB_HIGH_SPEED_SUPPORT==true)
  case FEATURE_TEST_MODE:
    if (bmRequestType != DEVICE_TYPE ||
        wIndex & 0x00FF)
      goto unsupported_request;

    switch (wIndex >> 8)
    {
    case TEST_J:
      Usb_ack_setup_received_free();
      Usb_ack_control_in_ready_send();
      while (!Is_usb_control_in_ready());
      Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2);
      Set_bits(AVR32_USBB_udcon, AVR32_USBB_UDCON_TSTJ_MASK);
      break;

    case TEST_K:
      Usb_ack_setup_received_free();
      Usb_ack_control_in_ready_send();
      while (!Is_usb_control_in_ready());
      Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2);
      Set_bits(AVR32_USBB_udcon, AVR32_USBB_UDCON_TSTK_MASK);
      break;

    case TEST_SE0_NAK:
      Usb_ack_setup_received_free();
      Usb_ack_control_in_ready_send();
      while (!Is_usb_control_in_ready());
      Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2);
      break;

    case TEST_PACKET:
      {
        static const U8 test_packet[] =
        {
          // 00000000 * 9
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          // 01010101 * 8
          0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
          // 01110111 * 8
          0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
          // 0, {111111S * 15}, 111111
          0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
          // S, 111111S, {0111111S * 7}
          0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
          // 00111111, {S0111111 * 9}, S0
          0xFC, 0x7E, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0x7E
        };

        Usb_ack_setup_received_free();
        Usb_ack_control_in_ready_send();
        while (!Is_usb_control_in_ready());
        Wr_bitfield(AVR32_USBB_udcon, AVR32_USBB_UDCON_SPDCONF_MASK, 2);
        Usb_disable_endpoint(EP_CONTROL);
        Usb_unallocate_memory(EP_CONTROL);
        (void)Usb_configure_endpoint(EP_CONTROL,
                                     TYPE_BULK,
                                     DIRECTION_IN,
                                     64,
                                     SINGLE_BANK);
        Usb_reset_endpoint(EP_CONTROL);
        Set_bits(AVR32_USBB_udcon, AVR32_USBB_UDCON_TSTPCKT_MASK);
        usb_write_ep_txpacket(EP_CONTROL, &test_packet, sizeof(test_packet), NULL);
        Usb_send_in(EP_CONTROL);
      }
      break;

    case TEST_FORCE_ENABLE: // Only for downstream facing hub ports
    default:
      goto unsupported_request;
    }
    break;
#endif

  case FEATURE_DEVICE_REMOTE_WAKEUP:
  default:
    goto unsupported_request;
  }

  return;

unsupported_request:
  Usb_enable_stall_handshake(EP_CONTROL);
  Usb_ack_setup_received_free();
}
//! This function checks if the device class is supported.
//! The function looks in all interfaces declared in the received descriptors if
//! one of them matches an entry of the CLASS/SUB_CLASS/PROTOCOL table.
//! If HOST_AUTO_CFG_ENDPOINT is enabled, a pipe is configured for each endpoint
//! of supported interfaces.
//!
//! @return bool: Status
//!
bool host_check_class(void)
{
  uint8_t *descriptor, *conf_end;
  uint8_t device_class, device_subclass, device_protocol;
  uint8_t c;
#if HOST_AUTO_CFG_ENDPOINT == ENABLE
  uint8_t nb_endpoint_to_configure = 0;
  uint8_t ep_index = 0;
  uint8_t physical_pipe = P_1;   // P_1 because physical pipe 0 is reserved for control
  uint16_t ep_size;

  // By default, the host is configured when returning
  Host_set_configured();
#endif

  // First, assume no interface is supported
  nb_interface_supported = 0;

  // Check if configuration descriptor
  if (data_stage[OFFSET_FIELD_DESCRIPTOR_TYPE] != CONFIGURATION_DESCRIPTOR) return false;

  bmattributes = data_stage[OFFSET_FIELD_BMATTRIBUTES];
  maxpower     = data_stage[OFFSET_FIELD_MAXPOWER];

  conf_end = data_stage +
             min(usb_format_usb_to_mcu_data(16, *(uint16_t *)(data_stage + OFFSET_FIELD_TOTAL_LENGTH)),
                 SIZEOF_DATA_STAGE - OFFSET_FIELD_PROTOCOL);

  // Look in all interfaces declared in the configuration
  for (descriptor = data_stage + data_stage[OFFSET_DESCRIPTOR_LENGTH]; descriptor < conf_end;
       descriptor += descriptor[OFFSET_DESCRIPTOR_LENGTH])
  {
    // Find next interface descriptor
    switch (descriptor[OFFSET_FIELD_DESCRIPTOR_TYPE])
    {
    case INTERFACE_DESCRIPTOR:
      // Check the number of supported interfaces does not exceed the maximum
      if (nb_interface_supported >= MAX_INTERFACE_SUPPORTED) return true;

#if HOST_AUTO_CFG_ENDPOINT == ENABLE
      // If there are still endpoints to configure although a new interface descriptor has been found
      if (nb_endpoint_to_configure)
      {
        // Mark the host as not configured
        Host_clear_configured();

        // Reset the number of endpoints to configure
        nb_endpoint_to_configure = 0;
      }
#endif

      // Found an interface descriptor
      // Get characteristics of this interface
      device_class    = descriptor[OFFSET_FIELD_CLASS];
      device_subclass = descriptor[OFFSET_FIELD_SUB_CLASS];
      device_protocol = descriptor[OFFSET_FIELD_PROTOCOL];

      // Look in registered class table for match
      for (c = 0; c < REG_CLASS_CNT; c += 3)
      {
        if (registered_class[c]     == device_class    &&   // Class is correct
            registered_class[c + 1] == device_subclass &&   // Subclass is correct
            registered_class[c + 2] == device_protocol)     // Protocol is correct
        {
          // Store this interface as supported interface
          // Memorize its interface nb
          interface_supported[nb_interface_supported].interface_nb = descriptor[OFFSET_FIELD_INTERFACE_NB];
          //          its alternate setting
          interface_supported[nb_interface_supported].altset_nb    = descriptor[OFFSET_FIELD_ALT];
          //          its USB class
          interface_supported[nb_interface_supported].uclass        = device_class;
          //          its USB subclass
          interface_supported[nb_interface_supported].subclass     = device_subclass;
          //          its USB protocol
          interface_supported[nb_interface_supported].protocol     = device_protocol;
          //          the number of endpoints associated with this interface
#if HOST_AUTO_CFG_ENDPOINT == ENABLE
          ep_index = 0;
          nb_endpoint_to_configure =
#endif
          interface_supported[nb_interface_supported].nb_ep        = min(descriptor[OFFSET_FIELD_NB_OF_EP], MAX_EP_PER_INTERFACE);

          // Update the number of supported interfaces
          nb_interface_supported++;

          // Class/subclass/protocol is registered, so look for next interface descriptor
          break;
        }
      }
      break;

#if HOST_AUTO_CFG_ENDPOINT == ENABLE
    case ENDPOINT_DESCRIPTOR:
      // If there are still endpoints to configure while there are free pipes
      if (physical_pipe < MAX_PEP_NB && nb_endpoint_to_configure)
      {
        nb_endpoint_to_configure--;

        // Reconfigure the new physical pipe to get rid of any previous configuration
  #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
        cpu_irq_disable();
  #endif
        Host_disable_pipe(physical_pipe);
  #if USB_HOST_PIPE_INTERRUPT_TRANSFER == ENABLE
        (void)Is_host_pipe_enabled(physical_pipe);
        cpu_irq_enable();
  #endif
        Host_unallocate_memory(physical_pipe);
        Host_enable_pipe(physical_pipe);

        // Fix HW, set freq at 0 in case of no interrupt endpoint
        if( TYPE_INTERRUPT != descriptor[OFFSET_FIELD_EP_TYPE] ) descriptor[OFFSET_FIELD_EP_INTERVAL] = 0;

        ep_size = descriptor[OFFSET_FIELD_EP_SIZE] |
                  descriptor[OFFSET_FIELD_EP_SIZE + 1] << 8;
#if BOARD != EVK1104
        if (ep_size <= 64)
        {
#endif
          // Build the pipe configuration according to the endpoint descriptor fields received
          (void)Host_configure_pipe(
                  physical_pipe,                                      // Pipe nb in USB interface
                  descriptor[OFFSET_FIELD_EP_INTERVAL],               // Interrupt period (for interrupt pipe)
                  Get_desc_ep_nbr(descriptor[OFFSET_FIELD_EP_ADDR]),  // Pipe endpoint number
                  descriptor[OFFSET_FIELD_EP_TYPE],                   // Pipe type (isochronous/bulk/interrupt)
                  Get_pipe_token(descriptor[OFFSET_FIELD_EP_ADDR]),   // Pipe token (IN/OUT)
                  ep_size,                                            // Pipe size
                  (descriptor[OFFSET_FIELD_EP_TYPE] == TYPE_BULK) ? SINGLE_BANK : DOUBLE_BANK // Number of banks to allocate for pipe
                );

          // Update endpoint pipe table in supported interface structure
          interface_supported[nb_interface_supported - 1].ep_pipe[ep_index++] = physical_pipe++;
        }
#if BOARD != EVK1104
        else
        {
          // Build the pipe configuration according to the endpoint descriptor fields received
          (void)Host_configure_pipe(
                  MAX_PEP_NB - 1,                                     // Pipe nb in USB interface
                  descriptor[OFFSET_FIELD_EP_INTERVAL],               // Interrupt period (for interrupt pipe)
                  Get_desc_ep_nbr(descriptor[OFFSET_FIELD_EP_ADDR]),  // Pipe endpoint number
                  descriptor[OFFSET_FIELD_EP_TYPE],                   // Pipe type (isochronous/bulk/interrupt)
                  Get_pipe_token(descriptor[OFFSET_FIELD_EP_ADDR]),   // Pipe token (IN/OUT)
                  ep_size,                                            // Pipe size
                  (descriptor[OFFSET_FIELD_EP_TYPE] == TYPE_BULK) ? SINGLE_BANK : DOUBLE_BANK // Number of banks to allocate for pipe
                );

          // Update endpoint pipe table in supported interface structure
          interface_supported[nb_interface_supported - 1].ep_pipe[ep_index++] = MAX_PEP_NB - 1;
        }
      }
#endif
      break;
#endif
    }

    // Call user callback to look more deeply into the configuration descriptor
    Host_user_check_class_action(descriptor);
  }

#if HOST_AUTO_CFG_ENDPOINT == ENABLE
  // If there are still endpoints to configure although all descriptors have been parsed
  if (nb_endpoint_to_configure)
  {
    // Mark the host as not configured
    Host_clear_configured();
  }
#endif

  return (nb_interface_supported > 0);
}