Exemplo n.º 1
0
//! This function manages the HID Get_Descriptor request.
//!
static void hid_get_descriptor(U8 size_of_report, const U8* p_usb_hid_report)
{
  bool  zlp;
  U16   wIndex;
  U16   wLength;

  zlp = false;                                              /* no zero length packet */

  data_to_transfer = size_of_report;
  pbuffer          = p_usb_hid_report;

  wIndex = Usb_read_endpoint_data(EP_CONTROL, 16);
  wIndex = usb_format_usb_to_mcu_data(16, wIndex);
  wLength = Usb_read_endpoint_data(EP_CONTROL, 16);
  wLength = usb_format_usb_to_mcu_data(16, wLength);
  Usb_ack_setup_received_free();                          //!< clear the setup received flag

  if (wLength > data_to_transfer)
  {
    zlp = !(data_to_transfer % EP_CONTROL_LENGTH);  //!< zero length packet condition
  }
  else
  {
    data_to_transfer = wLength; //!< send only requested number of data bytes
  }

  Usb_ack_nak_out(EP_CONTROL);

  while (data_to_transfer && (!Is_usb_nak_out(EP_CONTROL)))
  {
    while( !Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL) );

    if( Is_usb_nak_out(EP_CONTROL) )
       break;    // don't clear the flag now, it will be cleared after

    Usb_reset_endpoint_fifo_access(EP_CONTROL);
    data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer,
                                             data_to_transfer, &pbuffer);
    if( Is_usb_nak_out(EP_CONTROL) )
       break;
    else
       Usb_ack_control_in_ready_send();  //!< Send data until necessary
  }

  if ( zlp && (!Is_usb_nak_out(EP_CONTROL)) )
  {
    while (!Is_usb_control_in_ready());
    Usb_ack_control_in_ready_send();
  }

  while (!(Is_usb_nak_out(EP_CONTROL)));
  Usb_ack_nak_out(EP_CONTROL);
  while (!Is_usb_control_out_received());
  Usb_ack_control_out_received_free();
}
Exemplo n.º 2
0
//!
//! @brief USB Command Block Wrapper (CBW) management
//!
//! This function decodes the CBW command and stores the SCSI command.
//!
static void usb_mass_storage_cbw(void)
{
  bool cbw_error;

  Usb_reset_endpoint_fifo_access(EP_MS_OUT);

  //! Check if dCBWSignature is correct
  cbw_error = (Usb_read_endpoint_data(EP_MS_OUT, 32) != *(U32 *)&"USBC");

  //! Store CBW Tag to be repeated in CSW
  dCBWTag = Usb_read_endpoint_data(EP_MS_OUT, 32);

  g_scsi_data_remaining = Usb_read_endpoint_data(EP_MS_OUT, 32);
  g_scsi_data_remaining = usb_format_usb_to_mcu_data(32, g_scsi_data_remaining);

  //! if (bmCBWFlags.bit7 == 1) {direction = IN;}
  if (Usb_read_endpoint_data(EP_MS_OUT, 8))
  {
    ms_endpoint = EP_MS_IN;
    if (cbw_error)
    {
      Usb_ack_out_received_free(EP_MS_OUT);
      Usb_enable_stall_handshake(EP_MS_IN);
      return;
    }
  }
  else
  {
    ms_endpoint = EP_MS_OUT;
    if (cbw_error)
    {
      Usb_enable_stall_handshake(EP_MS_OUT);
      Usb_ack_out_received_free(EP_MS_OUT);
      return;
    }
  }

  usb_LUN = Usb_read_endpoint_data(EP_MS_OUT, 8);

  if (!ms_multiple_drive)
  {
    usb_LUN = get_cur_lun();
  }

  //! Dummy CBWCBLength read
  Usb_read_endpoint_data(EP_MS_OUT, 8);

  //! Store scsi_command
  usb_read_ep_rxpacket(EP_MS_OUT, g_scsi_command, sizeof(g_scsi_command), NULL);

  Usb_ack_out_received_free(EP_MS_OUT);

  // Take the USB Mutex(i.e. we're allowed to perform a ms cmd).
  /* if( ( pdFALSE == ( xGiveUsbMutex = x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ) ) || ( !scsi_decode_command() && g_scsi_data_remaining ) ) */
  if( ( pdFALSE == (xGiveUsbMutex = x_supervisor_SemaphoreTake( xUSBMutex, 0 ) ) )
      || ( !scsi_decode_command() && g_scsi_data_remaining ) )
  {
    Usb_enable_stall_handshake(ms_endpoint);
  }
}
// !
// ! @brief USB Command Block Wrapper (CBW) management
// !
// ! This function decodes the CBW command and stores the SCSI command.
// !
static void usb_mass_storage_cbw (void)
{
    Bool cbw_error;

    Usb_reset_endpoint_fifo_access (EP_MS_OUT);

    // ! Check if dCBWSignature is correct
    cbw_error = (Usb_read_endpoint_data (EP_MS_OUT, 32) != *(U32 *) & "USBC");

    // ! Store CBW Tag to be repeated in CSW
    dCBWTag = Usb_read_endpoint_data (EP_MS_OUT, 32);

    g_scsi_data_remaining = Usb_read_endpoint_data (EP_MS_OUT, 32);
    g_scsi_data_remaining = usb_format_usb_to_mcu_data (32, g_scsi_data_remaining);

    /* Show the remaining bytes { U8 Text_u8[20]; CI_StringOut (" - "); itoa ((S32)g_scsi_data_remaining,Text_u8); CI_StringOut (Text_u8);
       CI_StringOut (" - "); } */
    // ! if (bmCBWFlags.bit7 == 1) {direction = IN;}
    if (Usb_read_endpoint_data (EP_MS_OUT, 8))
    {
        ms_endpoint = EP_MS_IN;
        if (cbw_error)
        {
            Usb_ack_out_received_free (EP_MS_OUT);
            Usb_enable_stall_handshake (EP_MS_IN);
            return;
        }
    }
    else
    {
        ms_endpoint = EP_MS_OUT;
        if (cbw_error)
        {
            Usb_enable_stall_handshake (EP_MS_OUT);
            Usb_ack_out_received_free (EP_MS_OUT);
            return;
        }
    }

    usb_LUN = Usb_read_endpoint_data (EP_MS_OUT, 8);

    if (!ms_multiple_drive)
    {
        usb_LUN = get_cur_lun ();
    }

    // ! Dummy CBWCBLength read
    Usb_read_endpoint_data (EP_MS_OUT, 8);

    // ! Store scsi_command
    usb_read_ep_rxpacket (EP_MS_OUT, g_scsi_command, sizeof (g_scsi_command), NULL);

    Usb_ack_out_received_free (EP_MS_OUT);

    if (!scsi_decode_command ())
    {
        Usb_enable_stall_handshake (ms_endpoint);
    }
}
//! @brief This function manages hid get idle request.
//!
//! @param u8_report_id    0 the idle rate applies to all input reports, else only applies to the Report ID
//!
static void usb_hid_get_idle (uint8_t u8_report_id)
{
   uint16_t wLength;
   uint16_t wInterface;

   // Get interface number to put in idle mode
   wInterface=usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
   wLength   =usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
   Usb_ack_setup_received_free();

   if( (wLength != 0) && (wInterface == INTERFACE_NB_KBD) )
   {
      Usb_reset_endpoint_fifo_access(EP_CONTROL);
      Usb_write_endpoint_data(EP_CONTROL, 8, g_u8_report_rate);
      Usb_ack_control_in_ready_send();
   }

   while (!Is_usb_control_out_received());
   Usb_ack_control_out_received_free();
}
Exemplo n.º 5
0
//! This function manages the SETUP_GET_INTERFACE request.
//!
bool usb_get_interface (void)
{
   U16   wInterface;
   U16   wValue;

   // Read wValue
   wValue = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
   // wValue = Alternate Setting
   // wIndex = Interface
   wInterface=usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
   if(0!=wValue)
      return false;
   Usb_ack_setup_received_free();

   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   Usb_write_endpoint_data(EP_CONTROL, 8, usb_interface_status[wInterface] );
   Usb_ack_control_in_ready_send();

   while( !Is_usb_control_out_received() );
   Usb_ack_control_out_received_free();
   return true;
}
static void usb_hid_set_idle (uint8_t u8_report_id, uint8_t u8_duration )
{
   uint16_t wInterface;

   // Get interface number to put in idle mode
   wInterface=usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
   Usb_ack_setup_received_free();

   if( wInterface == INTERFACE_NB_KBD )
     g_u8_report_rate = u8_duration;

   Usb_ack_control_in_ready_send();
   while (!Is_usb_control_in_ready());
}
//! This function checks if the VID and the PID are supported
//! (if the VID & PID belong to the VID_PID table).
//!
//! @return bool: Status
//!
bool host_check_VID_PID(void)
{
  uint8_t c, d;

  // Rebuild VID & PID from data stage
  device_VID = usb_format_usb_to_mcu_data(16, *(uint16_t *)(data_stage + OFFSET_FIELD_VID));
  device_PID = usb_format_usb_to_mcu_data(16, *(uint16_t *)(data_stage + OFFSET_FIELD_PID));

  // Look for received VID & PID in supported table
  for (c = 0; c < REG_VID_PID_CNT; )
  {
    if (registered_VID_PID[c] == device_VID)  // VID is correct
    {
      for (c += 2, d = c + registered_VID_PID[c - 1]; c < d; c++)
      {
        if (registered_VID_PID[c] == device_PID) return true; // PID is correct
      }
    }
    else c += 2 + registered_VID_PID[c + 1];
  }

  return false;
}
Exemplo n.º 8
0
Status_t host_hid_get_descriptor(uint8_t descriptor_type, uint8_t descriptor_index, uint8_t s_interface)
{
  Status_t status;
  const hid_descriptor_t *hid_descriptor = (hid_descriptor_t *)&data_stage;
  uint8_t i;

  usb_request.bmRequestType   = 0x81;
  usb_request.bRequest        = GET_DESCRIPTOR;
  usb_request.wValue          = descriptor_type << 8 | descriptor_index;
  usb_request.wIndex          = Get_interface_number(s_interface);
  usb_request.wLength         = SIZEOF_DATA_STAGE;
  usb_request.incomplete_read = false;

  status = host_transfer_control(data_stage);

  switch (descriptor_type)
  {
  case HID_DESCRIPTOR:
    for (i = 0; i < hid_descriptor->bNumDescriptors; i++)
    {
      if (hid_descriptor->Descriptor[i].bType == HID_REPORT_DESCRIPTOR)
      {
        host_hid_report_descriptor_parser.length =
          usb_format_usb_to_mcu_data(16, hid_descriptor->Descriptor[i].wLength);
        break;
      }
    }
    break;

  case HID_REPORT_DESCRIPTOR:
    host_hid_report_descriptor_parser.item = (hid_item_t *)&data_stage;
    break;
  }

  return status;
}
Exemplo n.º 9
0
//! This function manages the SET INTERFACE request.
//!
void usb_set_interface(void)
{
   U8 u8_i;

   // wValue = Alternate Setting
   // wIndex = Interface
   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));
   Usb_ack_setup_received_free();

   // Get descriptor
#if (USB_HIGH_SPEED_SUPPORT==true)
   if( Is_usb_full_speed_mode() )
   {
      data_to_transfer = Usb_get_conf_desc_fs_length();  //!< sizeof(usb_conf_desc_fs);
      pbuffer          = Usb_get_conf_desc_fs_pointer();
   }else{
      data_to_transfer = Usb_get_conf_desc_hs_length();  //!< sizeof(usb_conf_desc_hs);
      pbuffer          = Usb_get_conf_desc_hs_pointer();
   }
#else
   data_to_transfer = Usb_get_conf_desc_length();  //!< sizeof(usb_conf_desc);
   pbuffer          = Usb_get_conf_desc_pointer();
#endif

   //** Scan descriptor

   //* Find configuration selected
   if( usb_configuration_nb == 0 )
   {
      // No configuration selected then no interface enable
      Usb_enable_stall_handshake(EP_CONTROL);
      Usb_ack_setup_received_free();
      return;
   }
   u8_i = usb_configuration_nb;
   while( u8_i != 0 )
   {
      if( CONFIGURATION_DESCRIPTOR != ((S_usb_configuration_descriptor*)pbuffer)->bDescriptorType )
      {
         data_to_transfer -=  ((S_usb_configuration_descriptor*)pbuffer)->bLength;
         pbuffer =  (U8*)pbuffer + ((S_usb_configuration_descriptor*)pbuffer)->bLength;
         continue;
      }
      u8_i--;
      if( u8_i != 0 )
      {
         data_to_transfer -=  ((S_usb_configuration_descriptor*)pbuffer)->wTotalLength;
         pbuffer =  (U8*)pbuffer + ((S_usb_configuration_descriptor*)pbuffer)->wTotalLength;
      }
   }

   // Find interface selected
   if( wIndex >= ((S_usb_configuration_descriptor*)pbuffer)->bNumInterfaces )
   {
      // Interface number unknown
      Usb_enable_stall_handshake(EP_CONTROL);
      Usb_ack_setup_received_free();
      return;
   }
   while( 1 )
   {
      if( data_to_transfer <= ((S_usb_interface_descriptor*)pbuffer)->bLength )
      {
         // Interface unknown
         Usb_enable_stall_handshake(EP_CONTROL);
         Usb_ack_setup_received_free();
         return;
      }
      data_to_transfer -=  ((S_usb_interface_descriptor*)pbuffer)->bLength;
      pbuffer =  (U8*)pbuffer + ((S_usb_interface_descriptor*)pbuffer)->bLength;
      if( INTERFACE_DESCRIPTOR != ((S_usb_interface_descriptor*)pbuffer)->bDescriptorType )
         continue;
      if( wIndex != ((S_usb_interface_descriptor*)pbuffer)->bInterfaceNumber )
         continue;
      if( wValue != ((S_usb_interface_descriptor*)pbuffer)->bAlternateSetting )
         continue;
      usb_interface_status[wIndex] = wValue;
      break;
   }

   //* Find endpoints of interface and reset it
   while( 1 )
   {
      if( data_to_transfer <= ((S_usb_endpoint_descriptor*)pbuffer)->bLength )
         break;    // End of interface
      data_to_transfer -=  ((S_usb_endpoint_descriptor*)pbuffer)->bLength;
      pbuffer =  (U8*)pbuffer + ((S_usb_endpoint_descriptor*)pbuffer)->bLength;
      if( INTERFACE_DESCRIPTOR == ((S_usb_endpoint_descriptor*)pbuffer)->bDescriptorType )
         break;    // End of interface
      if( ENDPOINT_DESCRIPTOR == ((S_usb_endpoint_descriptor*)pbuffer)->bDescriptorType )
      {
         // Reset endpoint
         u8_i = ((S_usb_endpoint_descriptor*)pbuffer)->bEndpointAddress & (~MSK_EP_DIR);
         Usb_disable_stall_handshake(u8_i);
         Usb_reset_endpoint(u8_i);
         Usb_reset_data_toggle(u8_i);
      }
   }

   // send a ZLP for STATUS phase
   Usb_ack_control_in_ready_send();
   while (!Is_usb_control_in_ready());
}
Exemplo n.º 10
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();
}
Exemplo n.º 11
0
//! This function manages the GET DESCRIPTOR request. The device descriptor,
//! the configuration descriptor and the device qualifier are supported. All
//! other descriptors must be supported by the usb_user_get_descriptor
//! function.
//! Only 1 configuration is supported.
//!
void usb_get_descriptor(void)
{
  bool    zlp;
  U16     wLength;
  U8      descriptor_type;
  U8      string_type;
  Union32 temp;
#if (USB_HIGH_SPEED_SUPPORT==true)
  bool    b_first_data = true;
#endif

  zlp             = false;                                  /* no zero length packet */
  string_type     = Usb_read_endpoint_data(EP_CONTROL, 8);  /* read LSB of wValue    */
  descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8);  /* read MSB of wValue    */

  switch (descriptor_type)
  {
  case DEVICE_DESCRIPTOR:
    data_to_transfer = Usb_get_dev_desc_length();   //!< sizeof(usb_dev_desc);
    pbuffer          = Usb_get_dev_desc_pointer();
    break;

#if (USB_HIGH_SPEED_SUPPORT==false)
  case CONFIGURATION_DESCRIPTOR:
    data_to_transfer = Usb_get_conf_desc_length();  //!< sizeof(usb_conf_desc);
    pbuffer          = Usb_get_conf_desc_pointer();
    break;

#else
  case CONFIGURATION_DESCRIPTOR:
    if( Is_usb_full_speed_mode() )
    {
       data_to_transfer = Usb_get_conf_desc_fs_length();  //!< sizeof(usb_conf_desc_fs);
       pbuffer          = Usb_get_conf_desc_fs_pointer();
    }else{
       data_to_transfer = Usb_get_conf_desc_hs_length();  //!< sizeof(usb_conf_desc_hs);
       pbuffer          = Usb_get_conf_desc_hs_pointer();
    }
    break;

  case OTHER_SPEED_CONFIGURATION_DESCRIPTOR:
    if( !Is_usb_full_speed_mode() )
    {
       data_to_transfer = Usb_get_conf_desc_fs_length();  //!< sizeof(usb_conf_desc_fs);
       pbuffer          = Usb_get_conf_desc_fs_pointer();
    }else{
       data_to_transfer = Usb_get_conf_desc_hs_length();  //!< sizeof(usb_conf_desc_hs);
       pbuffer          = Usb_get_conf_desc_hs_pointer();
    }
    break;

  case DEVICE_QUALIFIER_DESCRIPTOR:
    data_to_transfer = Usb_get_qualifier_desc_length();  //!< sizeof(usb_qualifier_desc);
    pbuffer          = Usb_get_qualifier_desc_pointer();
    break;

#endif

  default:
    if (!usb_user_get_descriptor(descriptor_type, string_type))
    {
      Usb_enable_stall_handshake(EP_CONTROL);
      Usb_ack_setup_received_free();
      return;
    }
    break;
  }

  temp.u32 = Usb_read_endpoint_data(EP_CONTROL, 32);      //!< read wIndex and wLength with a 32-bit access
                                                          //!< since this access is aligned with a 32-bit
                                                          //!< boundary from the beginning of the endpoint
  wLength = usb_format_usb_to_mcu_data(16, temp.u16[1]);  //!< ignore wIndex, keep and format wLength
  Usb_ack_setup_received_free();                          //!< clear the setup received flag

  if (wLength > data_to_transfer)
  {
    zlp = !(data_to_transfer % EP_CONTROL_LENGTH);  //!< zero length packet condition
  }
  else
  {
    // No need to test ZLP sending since we send the exact number of bytes as
    // expected by the host.
    data_to_transfer = wLength; //!< send only requested number of data bytes
  }

  Usb_ack_nak_out(EP_CONTROL);

  while (data_to_transfer && !Is_usb_nak_out(EP_CONTROL))
  {
    while (!Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL));

    if (Is_usb_nak_out(EP_CONTROL))
      break;  // don't clear the flag now, it will be cleared after

    Usb_reset_endpoint_fifo_access(EP_CONTROL);

#if (USB_HIGH_SPEED_SUPPORT==true) // To support other descriptors like OTHER_SPEED_CONFIGURATION_DESCRIPTOR
    if( b_first_data ) {
      b_first_data = false;
      if( 0!= data_to_transfer ) {
        usb_write_ep_txpacket(EP_CONTROL, pbuffer, 1, &pbuffer);
        data_to_transfer--;
      }
      if( 0!= data_to_transfer ) {
        usb_write_ep_txpacket(EP_CONTROL, &descriptor_type, 1, NULL);
        pbuffer = ((const U8*)pbuffer)+1;
        data_to_transfer--;
      }
    }
#endif
    if( 0!= data_to_transfer ) {
       data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer,
                                                data_to_transfer, &pbuffer);
    }
    if (Is_usb_nak_out(EP_CONTROL))
      break;

    Usb_ack_control_in_ready_send();  //!< Send data until necessary
  }

  if (zlp && !Is_usb_nak_out(EP_CONTROL))
  {
    while (!Is_usb_control_in_ready());
    Usb_ack_control_in_ready_send();
  }

  while (!Is_usb_nak_out(EP_CONTROL));
  Usb_ack_nak_out(EP_CONTROL);
  while (!Is_usb_control_out_received());
  Usb_ack_control_out_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);
}
Exemplo n.º 13
0
Status_bool_t host_hid_get_item(host_hid_item_t *item)
{
  const hid_item_t *hid_item = host_hid_report_descriptor_parser.item;
  uint8_t size;

  if (host_hid_report_descriptor_parser.length <
      (uint8_t *)&hid_item->header - (uint8_t *)hid_item +
      sizeof(hid_item->header))
    return false;

  item->type = hid_item->header.bType;

  if (hid_item->header.bTag == HID_ITEM_TAG_LONG_ITEM)
  {
    if (host_hid_report_descriptor_parser.length <
        (uint8_t *)&hid_item->long_format.bDataSize - (uint8_t *)hid_item +
        sizeof(hid_item->long_format.bDataSize))
      return false;

    size = hid_item->long_format.bDataSize;

    if (host_hid_report_descriptor_parser.length <
        (uint8_t *)&hid_item->long_format.data - (uint8_t *)hid_item +
        size)
      return false;

    item->tag = hid_item->long_format.bLongItemTag;

    item->long_format = true;

    item->long_data.size = size;
    item->long_data.data = &hid_item->long_format.data;

    host_hid_report_descriptor_parser.length -=
      (uint8_t *)&hid_item->long_format.data - (uint8_t *)hid_item +
      size;

    host_hid_report_descriptor_parser.item =
      (hid_item_t *)&hid_item->long_format.data[size];
  }
  else
  {
    uint8_t i;

    size = (hid_item->short_format.bSize) ?
             1 << (hid_item->short_format.bSize - 1) :
             0;

    if (host_hid_report_descriptor_parser.length <
        (uint8_t *)&hid_item->short_format.data - (uint8_t *)hid_item +
        size)
      return false;

    item->tag = hid_item->short_format.bTag;

    item->long_format = false;

    item->short_data.value = 0x00000000;
    for (i = 0; i < size; i++)
    {
      item->short_data.value = item->short_data.value << 8 |
                               hid_item->short_format.data[i];
    }
    item->short_data.value =
      usb_format_usb_to_mcu_data(32, item->short_data.value <<
                                     ((sizeof(uint32_t) - size) << 3));

    host_hid_report_descriptor_parser.length -=
      (uint8_t *)&hid_item->short_format.data - (uint8_t *)hid_item +
      size;

    host_hid_report_descriptor_parser.item =
      (hid_item_t *)&hid_item->short_format.data[size];
  }

  return true;
}
Exemplo n.º 14
0
//! This function is called by the standard USB read request function when
//! the USB request is not supported. This function returns TRUE when the
//! request is processed. This function returns FALSE if the request is not
//! supported. In this case, a STALL handshake will be automatically
//! sent by the standard USB read request function.
//!
Bool uac2_user_read_request(U8 type, U8 request)
{   int i;

	// Read wValue
	// why are these file statics?
	wValue_lsb = Usb_read_endpoint_data(EP_CONTROL, 8);
	wValue_msb = Usb_read_endpoint_data(EP_CONTROL, 8);
	wIndex = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));
	wLength = usb_format_usb_to_mcu_data(16, Usb_read_endpoint_data(EP_CONTROL, 16));

	if (type == IN_CL_INTERFACE || type == OUT_CL_INTERFACE){    // process Class Specific Interface


		//  request for AUDIO interfaces

		if (wIndex == DSC_INTERFACE_AS){				// Audio Streaming Interface
			if (type == IN_CL_INTERFACE){			// get controls

				if (wValue_msb == AUDIO_AS_VAL_ALT_SETTINGS && wValue_lsb == 0
					&& request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();

					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x01);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0b00000011); // alt 0 and 1 valid
					Usb_ack_control_in_ready_send();

					while (!Is_usb_control_out_received());
					Usb_ack_control_out_received_free();
					return TRUE;
				} else if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS && wValue_lsb == 0
 						   && request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();
					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					Usb_write_endpoint_data(EP_CONTROL, 8, usb_alternate_setting);
					Usb_ack_control_in_ready_send();
					while (!Is_usb_control_out_received());
					Usb_ack_control_out_received_free();
					return TRUE;
				} else if (wValue_msb == AUDIO_AS_AUDIO_DATA_FORMAT && wValue_lsb == 0
 						   && request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();
					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x01);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);	// only PCM format
					Usb_ack_control_in_ready_send();
					while (!Is_usb_control_out_received());
					Usb_ack_control_out_received_free();
					return TRUE;
				} else return FALSE;

			} else if (type == OUT_CL_INTERFACE){		// set controls
				if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS
					&& request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();
					while (!Is_usb_control_out_received());
					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					usb_alternate_setting = Usb_read_endpoint_data(EP_CONTROL, 8);
					usb_alternate_setting_changed = TRUE;
					Usb_ack_control_out_received_free();
					Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
					while (!Is_usb_control_in_ready()); //!< waits for status phase done
					return FALSE;
				}
			} // end OUT_CL_INTERFACE
		} // end DSC_INTERFACE_AS

		if (wIndex == DSC_INTERFACE_AS_OUT){				// Playback Audio Streaming Interface
			if (type == IN_CL_INTERFACE){			// get controls

				if (wValue_msb == AUDIO_AS_VAL_ALT_SETTINGS && wValue_lsb == 0
					&& request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();

					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x01);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0b00000011); // alt 0 and 1 valid
					Usb_ack_control_in_ready_send();

					while (!Is_usb_control_out_received());
					Usb_ack_control_out_received_free();
					return TRUE;
				} else if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS && wValue_lsb == 0
 						   && request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();
					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					Usb_write_endpoint_data(EP_CONTROL, 8, usb_alternate_setting_out);
					Usb_ack_control_in_ready_send();
					while (!Is_usb_control_out_received());
					Usb_ack_control_out_received_free();
					return TRUE;
				} else if (wValue_msb == AUDIO_AS_AUDIO_DATA_FORMAT && wValue_lsb == 0
 						   && request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();
					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x01);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
					Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);	// only PCM format
					Usb_ack_control_in_ready_send();
					while (!Is_usb_control_out_received());
					Usb_ack_control_out_received_free();
					return TRUE;
				} else return FALSE;

			} else if (type == OUT_CL_INTERFACE){		// set controls
				if (wValue_msb == AUDIO_AS_ACT_ALT_SETTINGS
					&& request == AUDIO_CS_REQUEST_CUR){
					Usb_ack_setup_received_free();
					while (!Is_usb_control_out_received());
					Usb_reset_endpoint_fifo_access(EP_CONTROL);
					usb_alternate_setting_out = Usb_read_endpoint_data(EP_CONTROL, 8);
					usb_alternate_setting_out_changed = TRUE;
					Usb_ack_control_out_received_free();
					Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
					while (!Is_usb_control_in_ready()); //!< waits for status phase done
					return FALSE;
				}
			} // end OUT_CL_INTERFACE
		} // end DSC_INTERFACE_AS_OUT

		if ( (wIndex % 256) == DSC_INTERFACE_AUDIO){// low byte wIndex is Interface number
													// high byte is for EntityID

			if (type == IN_CL_INTERFACE){			// get controls
				switch (wIndex /256){
				case CSD_ID_1:
					if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();

						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[3]); // 0x0000bb80 is 48khz
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[2]); // 0x00017700 is 96khz
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[1]); // 0x0002ee00 is 192khz
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[0]);
						Usb_ack_control_in_ready_send();

						while (!Is_usb_control_out_received());
						Usb_ack_control_out_received_free();
						return TRUE;
					}
					else if (wValue_msb == AUDIO_CS_CONTROL_CLOCK_VALID && wValue_lsb == 0
							 && request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();

						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						Usb_write_endpoint_data(EP_CONTROL, 8, TRUE);	// always valid
						// temp hack to give total # of bytes requested
						for (i = 0; i < (wLength - 1); i++)
							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();
						return TRUE;
					}
					else if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0
							 && request == AUDIO_CS_REQUEST_RANGE){
						Usb_ack_setup_received_free();

						Usb_reset_endpoint_fifo_access(EP_CONTROL);

						// give total # of bytes requested
						for (i = 0; i < (wLength); i++){
							if (FEATURE_DAC_ES9022)
								Usb_write_endpoint_data(EP_CONTROL, 8, Speedx_1[i]);
							else Usb_write_endpoint_data(EP_CONTROL, 8, Speedx_2[i]);
							}
						Usb_ack_control_in_ready_send();

						while (!Is_usb_control_out_received());
						Usb_ack_control_out_received_free();
						return TRUE;

					} else return FALSE;

				case CSD_ID_2:
					if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[3]); // 0x0000bb80 is 48khz
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[2]); // 0x00017700 is 96khz
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[1]); // 0x0002ee00 is 192khz
						Usb_write_endpoint_data(EP_CONTROL, 8, current_freq.freq_bytes[0]);
						Usb_ack_control_in_ready_send();
						while (!Is_usb_control_out_received());
						Usb_ack_control_out_received_free();
						return TRUE;
					}
					else if (wValue_msb == AUDIO_CS_CONTROL_CLOCK_VALID && wValue_lsb == 0
							 && request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						Usb_write_endpoint_data(EP_CONTROL, 8, TRUE);	// always valid
						// temp hack to give total # of bytes requested
						for (i = 0; i < (wLength - 1); i++)
							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();
						return TRUE;
					}
					else if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0
							 && request == AUDIO_CS_REQUEST_RANGE){
						Usb_ack_setup_received_free();

						Usb_reset_endpoint_fifo_access(EP_CONTROL);

						// give total # of bytes requested
						for (i = 0; i < (wLength); i++)
							Usb_write_endpoint_data(EP_CONTROL, 8, Speedx_2[i]);
						//							  LED_Toggle(LED0);
						Usb_ack_control_in_ready_send();

						while (!Is_usb_control_out_received());
						Usb_ack_control_out_received_free();
						return TRUE;



					} else return FALSE;


				case CSX_ID:
					if (wValue_msb == AUDIO_CX_CLOCK_SELECTOR && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						Usb_write_endpoint_data(EP_CONTROL, 8, clock_selected);
						// temp hack to give total # of bytes requested
						for (i = 0; i < (wLength - 1); i++)
							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();
						return TRUE;
					} else return FALSE;

				case MIC_FEATURE_UNIT_ID:
					if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);

						Usb_write_endpoint_data(EP_CONTROL, 8, mute);
						// temp hack to give total # of bytes requested
						for (i = 0; i < (wLength - 1); i++)
							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();
						return TRUE;
					} else return FALSE;

				case SPK_FEATURE_UNIT_ID:
					if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);

						Usb_write_endpoint_data(EP_CONTROL, 8, spk_mute);
						// temp hack to give total # of bytes requested
						for (i = 0; i < (wLength - 1); i++)
							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();
						return TRUE;
					} else return FALSE;


				case INPUT_TERMINAL_ID:
					if (wValue_msb == AUDIO_TE_CONTROL_CS_CLUSTER && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						if (usb_alternate_setting == 1) {
							Usb_write_endpoint_data(EP_CONTROL, 8, INPUT_TERMINAL_NB_CHANNELS);
							Usb_write_endpoint_data(EP_CONTROL, 8, (U8) INPUT_TERMINAL_CHANNEL_CONF);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, INPUT_TERMINAL_STRING_DESC);
						}
						else {			// zero's at startup alt setting 0
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							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();
						return TRUE;
					} else return FALSE;

				case SPK_INPUT_TERMINAL_ID:
					if (wValue_msb == AUDIO_TE_CONTROL_CS_CLUSTER && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						if (usb_alternate_setting_out == 1) {
							Usb_write_endpoint_data(EP_CONTROL, 8, SPK_INPUT_TERMINAL_NB_CHANNELS);
							Usb_write_endpoint_data(EP_CONTROL, 8, (U8) SPK_INPUT_TERMINAL_CHANNEL_CONF);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, INPUT_TERMINAL_STRING_DESC);
						}
						else {			// zero's at startup alt setting 0
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							Usb_write_endpoint_data(EP_CONTROL, 8, 0x00);
							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();
						return TRUE;
					} else return FALSE;
				default:
					return FALSE;
				} // end switch EntityID
			} else if (type == OUT_CL_INTERFACE){		// set controls
				switch (wIndex /256){
				case CSD_ID_1:							// set CUR freq
				case CSD_ID_2:
					if (wValue_msb == AUDIO_CS_CONTROL_SAM_FREQ && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						while (!Is_usb_control_out_received());
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						current_freq.freq_bytes[3]=Usb_read_endpoint_data(EP_CONTROL, 8);		// read 4 bytes freq to set
						current_freq.freq_bytes[2]=Usb_read_endpoint_data(EP_CONTROL, 8);
						current_freq.freq_bytes[1]=Usb_read_endpoint_data(EP_CONTROL, 8);
						current_freq.freq_bytes[0]=Usb_read_endpoint_data(EP_CONTROL, 8);
						freq_changed = TRUE;
						Usb_ack_control_out_received_free();
						Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
						while (!Is_usb_control_in_ready()); //!< waits for status phase done
						return TRUE;
					}
					else return FALSE;
				case CSX_ID:
					if (wValue_msb == AUDIO_CX_CLOCK_SELECTOR && wValue_lsb == 0
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						while (!Is_usb_control_out_received());
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						clock_selected = Usb_read_endpoint_data(EP_CONTROL, 8);
						clock_changed = TRUE;
						Usb_ack_control_out_received_free();
						Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
						while (!Is_usb_control_in_ready()); //!< waits for status phase done
						if (clock_selected < 1 || clock_selected > CSX_INPUT_PINS)
							clock_selected = 1;
						return TRUE;
					} else return FALSE;
				case MIC_FEATURE_UNIT_ID:
					if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						while (!Is_usb_control_out_received());
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						mute = Usb_read_endpoint_data(EP_CONTROL, 8);
						Usb_ack_control_out_received_free();
						Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
						while (!Is_usb_control_in_ready()); //!< waits for status phase done
						return TRUE;
					} else return FALSE;
				case SPK_FEATURE_UNIT_ID:
					if (wValue_msb == AUDIO_FU_CONTROL_CS_MUTE
						&& request == AUDIO_CS_REQUEST_CUR){
						Usb_ack_setup_received_free();
						while (!Is_usb_control_out_received());
						Usb_reset_endpoint_fifo_access(EP_CONTROL);
						spk_mute = Usb_read_endpoint_data(EP_CONTROL, 8);
						Usb_ack_control_out_received_free();
						Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
						while (!Is_usb_control_in_ready()); //!< waits for status phase done
						return TRUE;
					} else return FALSE;
				default:
					return FALSE;
				}
			} // end OUT_CL_INTERFACE

		} // end Audio Control Interface


	} // end CL_INTERFACE

	return FALSE;  // No supported request
}
Exemplo n.º 15
0
//! This function manages the GET DESCRIPTOR request. The device descriptor,
//! the configuration descriptor and the device qualifier are supported. All
//! other descriptors must be supported by the usb_user_get_descriptor
//! function.
//! Only 1 configuration is supported.
//!
void usb_get_descriptor(void)
{
  Bool    zlp;
  U16     wLength;
  U8      descriptor_type;
  U8      string_type;
  Union32 temp;

  zlp             = FALSE;                                  /* no zero length packet */
  string_type     = Usb_read_endpoint_data(EP_CONTROL, 8);  /* read LSB of wValue    */
  descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8);  /* read MSB of wValue    */

  switch (descriptor_type)
  {
  case DEVICE_DESCRIPTOR:
    data_to_transfer = Usb_get_dev_desc_length();   //!< sizeof(usb_dev_desc);
    pbuffer          = Usb_get_dev_desc_pointer();
    break;

  case CONFIGURATION_DESCRIPTOR:
    data_to_transfer = Usb_get_conf_desc_length();  //!< sizeof(usb_conf_desc);
    pbuffer          = Usb_get_conf_desc_pointer();
    break;

  default:
    if (!usb_user_get_descriptor(descriptor_type, string_type))
    {
      Usb_enable_stall_handshake(EP_CONTROL);
      Usb_ack_setup_received_free();
      return;
    }
    break;
  }

  temp.u32 = Usb_read_endpoint_data(EP_CONTROL, 32);      //!< read wIndex and wLength with a 32-bit access
                                                          //!< since this access is aligned with a 32-bit
                                                          //!< boundary from the beginning of the endpoint
  wLength = usb_format_usb_to_mcu_data(16, temp.u16[1]);  //!< ignore wIndex, keep and format wLength
  Usb_ack_setup_received_free();                          //!< clear the setup received flag

  if (wLength > data_to_transfer)
  {
    zlp = !(data_to_transfer % EP_CONTROL_LENGTH);  //!< zero length packet condition
  }
  else
  {
    // No need to test ZLP sending since we send the exact number of bytes as
    // expected by the host.
    data_to_transfer = (U8)wLength; //!< send only requested number of data bytes
  }

  Usb_ack_nak_out(EP_CONTROL);

  while (data_to_transfer && !Is_usb_nak_out(EP_CONTROL))
  {
    while (!Is_usb_control_in_ready() && !Is_usb_nak_out(EP_CONTROL));

    if (Is_usb_nak_out(EP_CONTROL))
      break;  // don't clear the flag now, it will be cleared after

    Usb_reset_endpoint_fifo_access(EP_CONTROL);
    data_to_transfer = usb_write_ep_txpacket(EP_CONTROL, pbuffer,
                                             data_to_transfer, &pbuffer);
    if (Is_usb_nak_out(EP_CONTROL))
      break;
    else
      Usb_ack_control_in_ready_send();  //!< Send data until necessary
  }

  if (zlp && !Is_usb_nak_out(EP_CONTROL))
  {
    while (!Is_usb_control_in_ready());
    Usb_ack_control_in_ready_send();
  }

  while (!Is_usb_nak_out(EP_CONTROL));
  Usb_ack_nak_out(EP_CONTROL);
  while (!Is_usb_control_out_received());
  Usb_ack_control_out_received_free();
}