//! 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();
}
Exemple #2
0
//! usb_get_descriptor.
//!
//! 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.
//!
//! @warning Code:xx bytes (function code length)
//!
//! @param none
//!
//! @return none
//!
void usb_get_descriptor(void)
{
U16  wLength         ;
U8  descriptor_type ;
U8  string_type     ;
U8  dummy;
U8  nb_byte;

   zlp             = FALSE;                  /* no zero length packet */
   string_type     = Usb_read_byte();        /* read LSB of wValue    */
   descriptor_type = Usb_read_byte();        /* read MSB of wValue    */

   switch (descriptor_type)
   {
    case DEVICE_DESCRIPTOR:
      data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
      pbuffer          = Usb_get_dev_desc_pointer();
      break;
    case CONFIGURATION_DESCRIPTOR:
      data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor);
      pbuffer          = Usb_get_conf_desc_pointer();
      break;
    default:
      if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE )
      {
         Usb_enable_stall_handshake();
         Usb_ack_receive_setup();
         return;
      }
      break;
   }

   dummy = Usb_read_byte();                     //!< don't care of wIndex field
   dummy = Usb_read_byte();
   LSB(wLength) = Usb_read_byte();              //!< read wLength
   MSB(wLength) = Usb_read_byte();
   Usb_ack_receive_setup() ;                  //!< clear the receive setup flag

   if (wLength > data_to_transfer)
   {
      if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
      else { zlp = FALSE; }                   //!< no need of zero length packet
   }
   else
   {
      data_to_transfer = (U8)wLength;         //!< send only requested number of data
   }

   while((data_to_transfer != 0) && (!Is_usb_receive_out()))
   {
      while(!Is_usb_read_control_enabled());

      nb_byte=0;
      while(data_to_transfer != 0)        //!< Send data until necessary
      {
         if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
         {
            break;
         }
#ifndef AVRGCC
         Usb_write_byte(*pbuffer++);
#else    // AVRGCC does not support point to PGM space
#warning with avrgcc assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
         Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
#endif
         data_to_transfer --;
      }
      Usb_send_control_in();
   }


   if(Is_usb_receive_out()) { Usb_ack_receive_out(); return; } //!< abort from Host
   if(zlp == TRUE)
   {
     while(!Is_usb_read_control_enabled());
     Usb_send_control_in();
   }


   while(!Is_usb_receive_out());
   Usb_ack_receive_out();
}
//! 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();
}
//! usb_get_descriptor.
//!
//! 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.
//!
//! @warning Code:xx bytes (function code length)
//!
void usb_get_descriptor(void)
{
	U8  LSBwLength, MSBwLength;
	U8  descriptor_type ;
	U8  string_type     ;
	U8  dummy;
	U8  byteswereread;

	zlp             = FALSE;                  /* no zero length packet */
	string_type     = Usb_read_byte();        /* read LSB of wValue    */
	descriptor_type = Usb_read_byte();        /* read MSB of wValue    */
	byteswereread   = 0;

	switch (descriptor_type)
	{
	case DEVICE_DESCRIPTOR:
	  data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
	  pbuffer          = Usb_get_dev_desc_pointer();
	  break;
	case CONFIGURATION_DESCRIPTOR:
		data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor);
		pbuffer          = Usb_get_conf_desc_pointer(string_type);
	  break;
#if 1 
	case STRING_DESCRIPTOR:
	  if(string_type!=LANG_ID) {
		usb_get_string_descriptor(string_type);
		return;
	  }
#endif
	default:
		dummy = Usb_read_byte();
		dummy = Usb_read_byte();
		LSBwLength = Usb_read_byte();
		MSBwLength = Usb_read_byte();
		byteswereread=1;
		if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) {
		    Usb_enable_stall_handshake(); //TODO:is this necessary, Win7 flaky without?
			Usb_ack_receive_setup();
			return;
		}
	  break;
	}
	if (byteswereread==0) {
		dummy = Usb_read_byte();                     //!< don't care of wIndex field
		dummy = Usb_read_byte();
		LSBwLength = Usb_read_byte();              //!< read wLength
		MSBwLength = Usb_read_byte();
	}

	Usb_ack_receive_setup() ;                  //!< clear the receive setup flag

	if ((LSBwLength > data_to_transfer) || (MSBwLength)) {
		if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
		else { zlp = FALSE; }                   //!< no need of zero length packet

		LSBwLength = data_to_transfer;
		MSBwLength = 0x00;
	} else {
		data_to_transfer = LSBwLength;         //!< send only requested number of data
	}
	
	while((data_to_transfer != 0) && (!Is_usb_receive_out())) {
		U8  nb_byte = 0;
		if(usb_endpoint_wait_for_read_control_enabled()!=0) {
			Usb_enable_stall_handshake();
			break;
		}

        //! Send data until necessary
		while(data_to_transfer != 0) {
//			if(Is_usb_write_enabled()) //!< Check endpoint 0 size
			if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
				break;

			Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
			data_to_transfer --;

		}
		Usb_send_control_in();
	}

	if(Is_usb_receive_out()) {
		//! abort from Host
		Usb_ack_receive_out();
		return;
	}
	
	if(zlp == TRUE) {
		if(usb_endpoint_wait_for_read_control_enabled()!=0) {
			Usb_enable_stall_handshake();
			return;
		}
		Usb_send_control_in();
	}

	usb_endpoint_wait_for_receive_out();
	Usb_ack_receive_out();
}
//! 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.
//!
Bool usb_get_descriptor(void)
{
   Bool zlp;
   U16  wLength;
   U8   descriptor_type ;
   U8   string_type;
   U8   dummy;
   U8   nb_byte;
   U8   byte_to_send;
#if (USE_DEVICE_SN_UNIQUE==ENABLE)
   U16  sn_index=0;
   U8   initial_data_to_transfer;
#endif
    
   zlp             = FALSE;                  /* no zero length packet */
   string_type     = Usb_read_byte();        /* read LSB of wValue    */
   descriptor_type = Usb_read_byte();        /* read MSB of wValue    */

   switch (descriptor_type)
   {
      case DESCRIPTOR_DEVICE:
      data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
      pbuffer          = Usb_get_dev_desc_pointer();
      break;
      
      case DESCRIPTOR_CONFIGURATION:
      data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor);
      pbuffer          = Usb_get_conf_desc_pointer();
      break;
      
      default:
      if( !usb_user_get_descriptor(descriptor_type, string_type))
         return FALSE;  // Unknow descriptor then stall request
      break;
   }

   dummy = Usb_read_byte();                     //!< don't care of wIndex field
   dummy = Usb_read_byte();
   LSB(wLength) = Usb_read_byte();              //!< read wLength
   MSB(wLength) = Usb_read_byte();
   Usb_ack_receive_setup() ;                  //!< clear the receive setup flag

   if (wLength > data_to_transfer)
   {
      if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
      else { zlp = FALSE; }                   //!< no need of zero length packet
   }
   else
   {
      data_to_transfer = (U8)wLength;         //!< send only requested number of data
   }

   Usb_ack_nak_out();
    
   byte_to_send=0;
#if (USE_DEVICE_SN_UNIQUE==ENABLE)
   initial_data_to_transfer = data_to_transfer;
#endif
   while((data_to_transfer != 0) && (!Is_usb_nak_out_sent()))
   {
      while(!Is_usb_read_control_enabled())
      {
         if (Is_usb_nak_out_sent())
            break;    // don't clear the flag now, it will be cleared after
      }
              
      nb_byte=0;
      while(data_to_transfer != 0)        //!< Send data until necessary
      {
         if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
            break;         
         
#if (USE_DEVICE_SN_UNIQUE==ENABLE)

         if(f_get_serial_string && (data_to_transfer < (initial_data_to_transfer-1)))    //if we are sending the signature characters (third byte and more...)
         {                                                                              //(The first two bytes are the length and the descriptor)
            
            switch (byte_to_send)
            {
               case 0:
               Usb_write_byte(bin_to_ascii((Flash_read_sn(sn_index)>>4) & 0x0F)); //sends the fist part (MSB) of the signature hex number, converted in ascii
               break;
              
               case 1:
               Usb_write_byte(0);                                                   //then, sends a null character (Usb_unicode)                    
               break;
    
               case 2:
               Usb_write_byte(bin_to_ascii(Flash_read_sn(sn_index) & 0x0F));      //sends the second part (LSB) of the signature hex number, converted in ascii 
               break;
    
               case 3:
               Usb_write_byte(0);                                                   //then, sends a null character (Usb_unicode)  
               sn_index++;                                                         //increments the signature address pointer.
               break;
            }
            byte_to_send = (byte_to_send+1)%4;     
         }
         else
         {
            Usb_write_PGM_byte(pbuffer++);                                                 //Write a flash byte to USB        
         }        
#else          
         Usb_write_PGM_byte(pbuffer++);          
#endif
         data_to_transfer --;                                                             //decrements the number of bytes to transmit.
      }
      
      if (Is_usb_nak_out_sent())
         break;
      else
         Usb_send_control_in();
   }