void audio_speaker_set_volume(void)
{
   while(!Is_usb_control_out_received())
   {
     TASKS_SCHEDULE();
   }
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   LSB(s16_usb_speaker_volume)=Usb_read_endpoint_data(EP_CONTROL, 8);
   MSB(s16_usb_speaker_volume)=Usb_read_endpoint_data(EP_CONTROL, 8);

   // Convert USB range volume into the volume range of the application.
   s16_speaker_volume = volume_usb_to_appli(s16_usb_speaker_volume) ;

   Usb_ack_control_out_received_free();
   Usb_ack_control_in_ready_send();  // send a ZLP

   // Ensures good limits of the parameter
   s16_speaker_volume = min( s16_speaker_volume, SPEAKER_VOL_MAX);
   s16_speaker_volume = max( s16_speaker_volume, SPEAKER_VOL_MIN);
   audio_mixer_dacs_set_volume_direct(s16_speaker_volume);
   while (!Is_usb_control_in_ready())
   {
     TASKS_SCHEDULE();
   }
}
//******* Speaker control
void audio_speaker_set_mute(void)
{
   while(!Is_usb_control_out_received())
   {
     TASKS_SCHEDULE();
   }
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   b_speaker_mute=Usb_read_endpoint_data(EP_CONTROL, 8);
   audio_mixer_mute_audio(b_speaker_mute);

   if( b_speaker_mute )
   {
     audio_mixer_dacs_set_volume_direct((uint8_t)SPEAKER_VOL_MIN);
   }
   else
   {
     audio_mixer_dacs_set_volume_direct(s16_speaker_volume);
   }

   Usb_ack_control_out_received_free();
   Usb_ack_control_in_ready_send();  // send a ZLP
   while (!Is_usb_control_in_ready())
   {
     TASKS_SCHEDULE();
   }
}
//! This function manages the GET INTERFACE request.
//!
void usb_get_interface(void)
{
  Usb_ack_setup_received_free();
  Usb_ack_control_in_ready_send();  //!< send a ZLP for STATUS phase

  while (!Is_usb_control_out_received());
  Usb_ack_control_out_received_free();
}
Beispiel #4
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 usb_user_read_request(U8 type, U8 request)
{
  Usb_read_endpoint_data(EP_CONTROL, 8); // string_type
  Usb_read_endpoint_data(EP_CONTROL, 8); // descriptor_type

  switch (request)
  {
#if( EVK1101_CTRL_PANEL_PID==EVK1101_CTRL_PANEL_DEMO_HID_MS_PID )
  case MASS_STORAGE_RESET:
    Usb_ack_setup_received_free();
    Usb_ack_control_in_ready_send();
    return true;

  case GET_MAX_LUN:
    Usb_ack_setup_received_free();
    Usb_reset_endpoint_fifo_access(EP_CONTROL);
    Usb_write_endpoint_data(EP_CONTROL, 8, get_nb_lun() - 1);
    Usb_ack_control_in_ready_send();
    while (!Is_usb_control_in_ready());

    while(!Is_usb_control_out_received());
    Usb_ack_control_out_received_free();
    ms_multiple_drive = true;
    return true;
#endif

  /*
  case HID_SET_REPORT:
    switch (descriptor_type)
    {
    case HID_REPORT_OUTPUT:
      Usb_ack_setup_received_free();
      while (!Is_usb_control_out_received());
      Usb_ack_control_out_received_free();
      Usb_ack_control_in_ready_send();
      while (!Is_usb_control_in_ready());
      return true;

    default:
      break;
    }
    break;

  case HID_SET_IDLE:
    Usb_ack_setup_received_free();
    Usb_ack_control_in_ready_send();
    while (!Is_usb_control_in_ready());
    return true;
*/

  default:
    break;
  }

  return false;
}
Beispiel #5
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();
}
//! 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 usb_user_read_request(uint8_t type, uint8_t request)
{
   uint16_t wInterface;
   uint8_t wValue_msb;
   uint8_t wValue_lsb;

   wValue_lsb = Usb_read_endpoint_data(EP_CONTROL, 8);
   wValue_msb = Usb_read_endpoint_data(EP_CONTROL, 8);

   //** Specific request from Class MassStorage
   if( USB_SETUP_SET_CLASS_INTER == type )
   {
      switch( request )
      {
         case MASS_STORAGE_RESET:
         // wValue must be 0
         // wIndex = Interface
         if( (0!=wValue_lsb) || (0!=wValue_msb) )
            break;
         wInterface=Usb_read_endpoint_data(EP_CONTROL, 16);
         if( INTERFACE_NB != wInterface )
            break;
         Usb_ack_setup_received_free();
         Usb_ack_control_in_ready_send();
         return true;
      }
   }
   if( USB_SETUP_GET_CLASS_INTER == type )
   {
      switch( request )
      {
         case GET_MAX_LUN:
         // wValue must be 0
         // wIndex = Interface
         if( (0!=wValue_lsb) || (0!=wValue_msb) )
            break;
         wInterface=Usb_read_endpoint_data(EP_CONTROL, 16);
         if( INTERFACE_NB != wInterface )
            break;
         Usb_ack_setup_received_free();
         Usb_reset_endpoint_fifo_access(EP_CONTROL);
         Usb_write_endpoint_data(EP_CONTROL, 8, get_nb_lun() - 1);
         Usb_ack_control_in_ready_send();
         while (!Is_usb_control_in_ready());

         while(!Is_usb_control_out_received());
         Usb_ack_control_out_received_free();

         ms_multiple_drive = true;
         return true;
      }
   }

   return false;
}
void audio_micro_get_mute(void)
{
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   Usb_write_endpoint_data(EP_CONTROL, 8, b_micro_mute);
   Usb_ack_control_in_ready_send();
   while(!Is_usb_control_out_received()) // send a ZLP
   {
     TASKS_SCHEDULE();
   }
   Usb_ack_control_out_received_free();
}
Beispiel #8
0
//! This function manages the GET CONFIGURATION request. The current
//! configuration number is returned.
//!
void usb_get_configuration(void)
{
  Usb_ack_setup_received_free();

  Usb_reset_endpoint_fifo_access(EP_CONTROL);
  Usb_write_endpoint_data(EP_CONTROL, 8, usb_configuration_nb);
  Usb_ack_control_in_ready_send();

  while (!Is_usb_control_out_received());
  Usb_ack_control_out_received_free();
}
void audio_micro_get_vol_res(void)
{
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   Usb_write_endpoint_data(EP_CONTROL, 16, Usb_format_mcu_to_usb_data(16, MICRO_VOL_RES));
   Usb_ack_control_in_ready_send();
   while(!Is_usb_control_out_received()) // send a ZLP
   {
     TASKS_SCHEDULE();
   }
   Usb_ack_control_out_received_free();
}
void audio_speaker_get_vol_max(void)
{
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   Usb_write_endpoint_data(EP_CONTROL, 16, Usb_format_mcu_to_usb_data(16, USB_SPEAKER_VOL_MAX));
   Usb_ack_control_in_ready_send();
   while(!Is_usb_control_out_received()) // send a ZLP
   {
     TASKS_SCHEDULE();
   }
   Usb_ack_control_out_received_free();
}
//! @brief This function manages hit set report request.
//!
static void usb_hid_set_report_ouput (void)
{
   //Usb_ack_receive_setup();
   Usb_ack_setup_received_free();
   //Usb_send_control_in();
   Usb_ack_control_in_ready_send();

   //while(!Is_usb_receive_out());
   while (!Is_usb_control_out_received());
   //Usb_ack_receive_out();
   Usb_ack_control_out_received_free();
   //Usb_send_control_in();
   Usb_ack_control_in_ready_send();
}
//******* Micro control
void audio_micro_set_mute(void)
{
   while(!Is_usb_control_out_received())
   {
     TASKS_SCHEDULE();
   }
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   b_micro_mute=Usb_read_endpoint_data(EP_CONTROL, 8);
   Usb_ack_control_out_received_free();
   Usb_ack_control_in_ready_send();  // send a ZLP
   while (!Is_usb_control_in_ready())
   {
     TASKS_SCHEDULE();
   }
}
Beispiel #13
0
void cdc_set_line_coding (void)
{
   Usb_ack_setup_received_free();

   while(!Is_usb_control_out_received());
   Usb_reset_endpoint_fifo_access(EP_CONTROL);

   LSB0(line_coding.dwDTERate) = Usb_read_endpoint_data(EP_CONTROL, 8);
   LSB1(line_coding.dwDTERate) = Usb_read_endpoint_data(EP_CONTROL, 8);
   LSB2(line_coding.dwDTERate) = Usb_read_endpoint_data(EP_CONTROL, 8);
   LSB3(line_coding.dwDTERate) = Usb_read_endpoint_data(EP_CONTROL, 8);
   line_coding.bCharFormat = Usb_read_endpoint_data(EP_CONTROL, 8);
   line_coding.bParityType = Usb_read_endpoint_data(EP_CONTROL, 8);
   line_coding.bDataBits = Usb_read_endpoint_data(EP_CONTROL, 8);
   Usb_ack_control_out_received_free();

   Usb_ack_control_in_ready_send();
   while (!Is_usb_control_in_ready());

   // Set the baudrate of the USART
   {
      static usart_options_t dbg_usart_options;
      uint32_t stopbits, parity;

      if     ( line_coding.bCharFormat==0 )   stopbits = USART_1_STOPBIT;
      else if( line_coding.bCharFormat==1 )   stopbits = USART_1_5_STOPBITS;
      else                                    stopbits = USART_2_STOPBITS;

      if     ( line_coding.bParityType==0 )   parity = USART_NO_PARITY;
      else if( line_coding.bParityType==1 )   parity = USART_ODD_PARITY;
      else if( line_coding.bParityType==2 )   parity = USART_EVEN_PARITY;
      else if( line_coding.bParityType==3 )   parity = USART_MARK_PARITY;
      else                                    parity = USART_SPACE_PARITY;

      // Options for debug USART.
      dbg_usart_options.baudrate    = line_coding.dwDTERate;
      dbg_usart_options.charlength  = line_coding.bDataBits;
      dbg_usart_options.paritytype  = parity;
      dbg_usart_options.stopbits    = stopbits;
      dbg_usart_options.channelmode = USART_NORMAL_CHMODE;

      // Initialize it in RS232 mode.
      usart_init_rs232(DBG_USART, &dbg_usart_options, pcl_freq_param.pba_f);

      // Enable Rx interrupts
      DBG_USART->ier = AVR32_USART_IER_RXRDY_MASK;
   }
}
Beispiel #14
0
void cdc_get_line_coding(void)
{
   Usb_ack_setup_received_free();

   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   Usb_write_endpoint_data(EP_CONTROL, 8, LSB0(line_coding.dwDTERate));
   Usb_write_endpoint_data(EP_CONTROL, 8, LSB1(line_coding.dwDTERate));
   Usb_write_endpoint_data(EP_CONTROL, 8, LSB2(line_coding.dwDTERate));
   Usb_write_endpoint_data(EP_CONTROL, 8, LSB3(line_coding.dwDTERate));
   Usb_write_endpoint_data(EP_CONTROL, 8, line_coding.bCharFormat);
   Usb_write_endpoint_data(EP_CONTROL, 8, line_coding.bParityType);
   Usb_write_endpoint_data(EP_CONTROL, 8, line_coding.bDataBits  );

   Usb_ack_control_in_ready_send();
   while (!Is_usb_control_in_ready());

   while(!Is_usb_control_out_received());
   Usb_ack_control_out_received_free();
}
Beispiel #15
0
void usb_hid_set_report_feature(void)
{

   Usb_ack_setup_received_free();
   Usb_ack_control_in_ready_send();// send a ZLP

   while(!Is_usb_control_out_received());

   if(Usb_read_endpoint_data(EP_CONTROL, 8)==0x55)
      if(Usb_read_endpoint_data(EP_CONTROL, 8)==0xAA)
         if(Usb_read_endpoint_data(EP_CONTROL, 8)==0x55)
            if(Usb_read_endpoint_data(EP_CONTROL, 8)==0xAA)
            {
               jump_bootloader=1; // Specific Request with 0x55AA55AA code
            }
   Usb_ack_control_out_received_free();
   Usb_ack_control_in_ready_send();    //!< send a ZLP for STATUS phase
   while(!Is_usb_control_in_ready());
}
Beispiel #16
0
//! @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
//!
void usb_hid_get_idle (U8 u8_report_id)
{
   U16 wLength;
   U16 wInterface;

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

   if( (wLength != 0) && (wInterface == INTERFACE_NB) )
   {
      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();
}
//! @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();
}
Beispiel #18
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();
}
Beispiel #19
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;
}
void audio_speaker_set_sample_freq(void)
{
   uint32_t sample_freq=0;
   Usb_ack_setup_received_free();
   while(!Is_usb_control_out_received())
   {
     TASKS_SCHEDULE();
   }
   Usb_reset_endpoint_fifo_access(EP_CONTROL);
   LSB0(sample_freq)=Usb_read_endpoint_data(EP_CONTROL, 8);
   LSB1(sample_freq)=Usb_read_endpoint_data(EP_CONTROL, 8);
   LSB2(sample_freq)=Usb_read_endpoint_data(EP_CONTROL, 8);
   Usb_ack_control_out_received_free();
   Usb_ack_control_in_ready_send();  // send a ZLP
   while (!Is_usb_control_in_ready())
   {
     TASKS_SCHEDULE();
   }

#if (defined BOARD) && (BOARD==EVK1105) && (defined DEFAULT_DACS) && (DEFAULT_DACS==AUDIO_MIXER_DAC_AIC23B)
   // Disable microphone callback interrupt in order for the flush to not be blocked.
   // TODO: audio_mixer_dacs_flush_direct flushes Rx and Tw part of the DAC.
   //       Should we separate them? Here, we want to flash the output only.
   device_audio_disable_microphone();
#endif
   audio_mixer_dacs_flush_direct(false);
   usb_stream_init(
     sample_freq
   , 2
   , 16
   , false
   );
#if (defined BOARD) && (BOARD==EVK1105) && (defined DEFAULT_DACS) && (DEFAULT_DACS==AUDIO_MIXER_DAC_AIC23B)
   // Enable microphone call back interrupts.
   device_audio_enable_microphone();
#endif
}
Beispiel #21
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 usb_user_read_request(U8 type, U8 request)
{
   U8    wValue_msb;
   U8    wValue_lsb;

   // Read wValue
   wValue_lsb = Usb_read_endpoint_data(EP_CONTROL, 8);
   wValue_msb = Usb_read_endpoint_data(EP_CONTROL, 8);
/*
   U8 descriptor_type;

  Usb_read_endpoint_data(EP_CONTROL, 8); // string_type
  descriptor_type = Usb_read_endpoint_data(EP_CONTROL, 8);
*/

   //** Specific request from Class HID
   if( 0x81 == type )   // USB_SETUP_GET_STAND_INTERFACE
   {
      switch( request )
      {
         case GET_DESCRIPTOR:
         switch( wValue_msb ) // Descriptor ID
         {
#if (USB_HIGH_SPEED_SUPPORT==false)
            case HID_DESCRIPTOR:
            hid_get_descriptor(
               sizeof(usb_conf_desc_fs.hid)
            ,  (const U8*)&usb_conf_desc_fs.hid);
            return true;
#else
            case HID_DESCRIPTOR:
            if( Is_usb_full_speed_mode() )
            {
               hid_get_descriptor(
                  sizeof(usb_conf_desc_fs.hid)
               ,  (const U8*)&usb_conf_desc_fs.hid);
            }else{
               hid_get_descriptor(
                  sizeof(usb_conf_desc_hs.hid_mouse)
               ,  (const U8*)&usb_conf_desc_hs.hid);
            }
            return true;
#endif

            case HID_REPORT_DESCRIPTOR:
            hid_get_descriptor(
               sizeof(usb_hid_report_descriptor)
            ,  usb_hid_report_descriptor);
            return true;

            case HID_PHYSICAL_DESCRIPTOR:
            // TODO
            break;
         }
         break;
      }
   }
   if( 0x21 == type ) // USB_SETUP_SET_CLASS_INTER
   {
      switch( request )
      {
         case HID_SET_REPORT:
         // The MSB wValue field specifies the Report Type
         // The LSB wValue field specifies the Report ID
         switch (wValue_msb)
         {
            case HID_REPORT_INPUT:
            // TODO
            break;

            case HID_REPORT_OUTPUT:
            Usb_ack_setup_received_free();
            while (!Is_usb_control_out_received());
            Usb_ack_control_out_received_free();
            Usb_ack_control_in_ready_send();
            while (!Is_usb_control_in_ready());
            return true;

            case HID_REPORT_FEATURE:
            usb_hid_set_report_feature();
            return true;
            break;
         }
         break;

         case HID_SET_IDLE:
         usb_hid_set_idle(wValue_lsb, wValue_msb);
         return true;

         case HID_SET_PROTOCOL:
         // TODO
         break;
      }
   }
   if( 0xA1 == type ) // USB_SETUP_GET_CLASS_INTER
   {
      switch( request )
      {
         case HID_GET_REPORT:
         // TODO
         break;
         case HID_GET_IDLE:
         usb_hid_get_idle(wValue_lsb);
         return true;
         case HID_GET_PROTOCOL:
         // TODO
         break;
      }
   }
   return false;  // No supported request
}
//! 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();
}
//! 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
}
Beispiel #24
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();
}