Ejemplo n.º 1
0
void
cdc_ecm_notify_connection_speed_change(uint32_t upstream,uint32_t downstream) {
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
	Usb_select_endpoint(INT_EP);

	if(!Is_usb_endpoint_enabled())
		return;

	if(usb_endpoint_wait_for_IN_ready()!=0)
		return;

	Usb_send_control_in();

	Usb_write_byte(0x51); // 10100001b
	Usb_write_byte(CDC_NOTIFY_CONNECTION_SPEED_CHANGE);
	Usb_write_word(0x0000);
	Usb_write_word(ECM_INTERFACE0_NB);
	Usb_write_word(0x0008);

	Usb_send_in();

	if(usb_endpoint_wait_for_write_enabled()!=0)
		return;

	Usb_write_long(upstream);
	Usb_write_long(downstream);
	Usb_send_in();

	PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_CONNECTION_SPEED_CHANGE UP:%d DOWN:%d\n"),upstream,downstream);
#endif
}
Ejemplo n.º 2
0
void
cdc_ecm_notify_network_connection(uint8_t value) {
#if CDC_ECM_USES_INTERRUPT_ENDPOINT
	Usb_select_endpoint(INT_EP);

	if(!Is_usb_endpoint_enabled()) {
		//PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: endpoint not enabled\n"));
		return;
	}

	if(usb_endpoint_wait_for_IN_ready()!=0) {
		//PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: Timeout waiting for interrupt endpoint to be available\n"));
		return;
	}

	Usb_send_control_in();

	Usb_write_byte(0x51); // 10100001b
	Usb_write_byte(CDC_NOTIFY_NETWORK_CONNECTION);
	Usb_write_byte(value);
	Usb_write_byte(0x00);
	Usb_write_word(ECM_INTERFACE0_NB);
	Usb_write_word(0x0000);

	Usb_send_in();
	PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_NETWORK_CONNECTION %d\n"),value);
#endif
}
Ejemplo n.º 3
0
//! usb_get_status.
//!
//! This function manages the GET STATUS request. The device, interface or
//! endpoint status is returned.
//!
//! @warning Code:xx bytes (function code length)
//!
//! @param none
//!
//! @return none
//!
void usb_get_status(void)
{
U8 wIndex;
U8 dummy;

   dummy    = Usb_read_byte();                 //!< dummy read
   dummy    = Usb_read_byte();                 //!< dummy read
   wIndex = Usb_read_byte();

   switch(bmRequestType)
   {
    case REQUEST_DEVICE_STATUS:    Usb_ack_receive_setup();
                                   Usb_write_byte(DEVICE_STATUS);
                                   break;

    case REQUEST_INTERFACE_STATUS: Usb_ack_receive_setup();
                                   Usb_write_byte(INTERFACE_STATUS);
                                   break;

    case REQUEST_ENDPOINT_STATUS:  Usb_ack_receive_setup();
                                   wIndex = wIndex & MSK_EP_DIR;
                                   Usb_write_byte(endpoint_status[wIndex]);
                                   break;
    default:
                                   Usb_enable_stall_handshake();
                                   Usb_ack_receive_setup();
                                   return;
   }

   Usb_write_byte(0x00);
   Usb_send_control_in();

   while( !Is_usb_receive_out() );
   Usb_ack_receive_out();
}
Ejemplo n.º 4
0
//! Task which links mouse events with the USB HID mouse device
//!
void mouse_task(void)
{
   if(Is_usb_vbus_low())
   {
      Setup_power_down_mode();
      Sleep_instruction();
   }

   if(!Is_device_enumerated())
      return;  // Device not ready

#if (USB_LOW_SPEED_DEVICE==DISABLE)
   // The SOF is used to schedule the task at the same frequency that Endpoint Interrupt frequency
   // This check allow to win a CPU time
   if(g_u8_cpt_sof<NB_IDLE_POLLING_SOF)
      return;  // Wait a delay
   g_u8_cpt_sof=0;
#endif

   if(!g_b_send_report)
   {
      // No report sending on going, then check mouse event to eventualy fill a new report
      if(is_mouse_event())
      {
         // Enable sending of report
         g_b_send_report      = TRUE;
      }
   }

   if((!g_b_send_report)&&(!g_b_send_ack_report))
      return;  // No report and ack to send

   //** A report or ack must be send
   Usb_select_endpoint(EP_MOUSE_IN);
   if(!Is_usb_write_enabled())
      return;  // Endpoint no free

   Led0_on();
   if( g_b_send_report )
   {
      g_b_send_report      = FALSE;
      // Send an ack after a "clic" report only
      g_b_send_ack_report = (0!=g_hid_mouse_report[0]);
   }
   else
   {
      Hid_mouse_report_reset();     // Reset report to have a ack report
      g_b_send_ack_report  = FALSE;
   }
   // Send report
   Usb_write_byte(g_hid_mouse_report[0]);
   Usb_write_byte(g_hid_mouse_report[1]);
   Usb_write_byte(g_hid_mouse_report[2]);
   Usb_write_byte(g_hid_mouse_report[3]);
   Usb_ack_in_ready();
   Led0_off();
}
/** 
  * @brief This function transmits a ram buffer content to the USB.
  * This function is mode efficient in term of USB bandwith transfer.
  * 
  * @param U8 *buffer : the pointer to the RAM buffer to be sent 
  * @param data_to_send : the number of data to be sent
  */
void uart_usb_send_buffer(U8 *buffer, U8 nb_data)
{
  U8 zlp;

  if(!Is_device_enumerated())
    return;
   
  // Compute if zlp required
  if(nb_data%TX_EP_SIZE) 
    zlp=FALSE;
  else 
    zlp=TRUE;
   
  Usb_select_endpoint(TX_EP);
  while (nb_data)
  {
    while(Is_usb_write_enabled()==FALSE); // Wait Endpoint ready
    while(Is_usb_write_enabled() && nb_data)
    {
      Usb_write_byte(*buffer);
      buffer++;
      nb_data--;
    }
    Usb_ack_in_ready();
  }
  if(zlp)
  {
    while(Is_usb_write_enabled()==FALSE); // Wait Endpoint ready
    Usb_ack_in_ready();
  }
}
Ejemplo n.º 6
0
/**
  * @brief This function fills the USB transmit buffer with the new data. This buffer
  * is sent if complete. To flush this buffer before waiting full, launch
  * the uart_usb_flush() function.
  *
  * @param data_to_send Data to send
  *
  * @return data_to_send Data that was sent
  */
int uart_usb_putchar(int data_to_send)
{
	// Preserve the currently selected endpoint
	uint8_t uenum = UENUM;

	USB_CDC_ACM_HOOK_TX_START(data_to_send);

	Usb_select_endpoint(VCP_TX_EP);

	if(usb_endpoint_wait_for_write_enabled()!=0) {
		data_to_send=-1;
		goto bail;
	}

	Usb_write_byte(data_to_send);
	tx_counter++;

	//If Endpoint full -> flush
	if(!Is_usb_write_enabled())
		uart_usb_flush();

	USB_CDC_ACM_HOOK_TX_END(data_to_send);

bail:
	// Restore previously selected endpoint
	UENUM = uenum;

	return data_to_send;
}
Ejemplo n.º 7
0
//! @breif This function checks the specific request and if known then processes it
//!
//! @param type      corresponding at bmRequestType (see USB specification)
//! @param request   corresponding at bRequest (see USB specification)
//!
//! @return TRUE,  when the request is processed
//! @return FALSE, if the request is'nt know (STALL handshake is managed by the main standard request function).
//!
Bool usb_user_read_request(U8 type, U8 request)
{
   U16   wInterface;
   U8    wValue_msb;
   U8    wValue_lsb;

   // Read wValue
   wValue_lsb = Usb_read_byte();
   wValue_msb = Usb_read_byte();

   //** Specific request from Class MassStorage
   if( USB_SETUP_SET_CLASS_INTER == type )
   {
      switch( request )
      {
         case SETUP_MASS_STORAGE_RESET:
         // wValue must be 0
         // wIndex = Interface
         if( (0!=wValue_lsb) || (0!=wValue_msb) )
            break;
         LSB(wInterface)=Usb_read_byte();
         MSB(wInterface)=Usb_read_byte();
         if( INTERFACE_NB != wInterface )
            break;
         Usb_ack_receive_setup();
         Usb_send_control_in();
         while(!Is_usb_in_ready());         
         return TRUE;
         break;
      }
   }
   if( USB_SETUP_GET_CLASS_INTER == type )
   {
      switch( request )
      {
         case SETUP_MASS_STORAGE_GET_MAX_LUN:
         // wValue must be 0
         // wIndex = Interface
         if( (0!=wValue_lsb) || (0!=wValue_msb) )
            break;
         LSB(wInterface)=Usb_read_byte();
         MSB(wInterface)=Usb_read_byte();
         if( INTERFACE_NB != wInterface )
            break;
         Usb_ack_receive_setup();
         Usb_write_byte( (get_nb_lun()-1) );
         Usb_send_control_in();
         while(!Is_usb_in_ready());
         while( !Is_usb_receive_out() );
         Usb_ack_receive_out();         
         ms_multiple_drive = 1;
         return TRUE;
         break;
      }
   }
   
   return FALSE;  // No supported request
}
//! usb_get_configuration.
//!
//! This function manages the GET CONFIGURATION request. The current
//! configuration number is returned.
//!
//! @warning Code:xx bytes (function code length)
//!
void usb_get_configuration(void)
{
   Usb_ack_receive_setup();

   Usb_write_byte(usb_configuration_nb);
   Usb_send_control_in();

   usb_endpoint_wait_for_receive_out();
   Usb_ack_receive_out();
}
Ejemplo n.º 9
0
//! usb_get_configuration.
//!
//! This function manages the GET CONFIGURATION request. The current
//! configuration number is returned.
//!
//! @warning Code:xx bytes (function code length)
//!
//! @param none
//!
//! @return none
//!
void usb_get_configuration(void)
{
   Usb_ack_receive_setup();

   Usb_write_byte(usb_configuration_nb);
   Usb_ack_in_ready();

   while( !Is_usb_receive_out() );
   Usb_ack_receive_out();
}
Ejemplo n.º 10
0
int USB::write(char* buf, int len)
{
  if(!isEnumerated())
    return 0;

  Usb_select_endpoint(EP_TEMP_IN);

  //if(!canSend())
  //  return 0;

  char* ptr = buf;
  for(int i = 0; i<len; i++)
    Usb_write_byte(*ptr++);
  for(int i; i<EP_IN_LENGTH_TEMP1; i++)
    Usb_write_byte(0);
  Usb_ack_in_ready();

  return len;
}
// this function should be continuously called
void my_uart_usb_send_to_endpoint(void){
  static uint8_t zlp=FALSE; /* zero load packet */
  static uint8_t local_buffer[TX_EP_SIZE];
  uint16_t num_read;
  bit ret;
  if(!Is_device_enumerated())
    return;


  // make atomic, this will be fixed by interrupts
  Usb_select_endpoint(TX_EP);
  if(Is_usb_write_enabled()==FALSE) // Only if endpoint ready
    return;

  if(line_status.DTR == 0){
    Usb_ack_in_ready();
    return;
  }


  // we send in chunks of TX_EP_SIZE 
  num_read = TX_EP_SIZE;
  ret = circ_buffer_get_nbytes(&my_uart_usb_tx_buffer, local_buffer, &num_read);
  if(num_read == 0 && zlp == TRUE){
    Usb_ack_in_ready();
    zlp = FALSE;
    Usb_disable_in_ready_interrupt(); // Nothing left to send, disable this until next time
    return;
  }
  // if we got exactly TX_EP_SIZE bytes, we should send zlp the next time if we send 0
  if(ret == PASS){
    zlp = TRUE;
    //Usb_enable_in_ready_interrupt(); // We don't need to do this since this is inside an interrupt.
  }
  else{ // this is the second pass and we didn't get a full TX_EP_SIZE bytes so the buffer is not full
    zlp = FALSE;
  }

  // write to the endpoint
  uint16_t nb_data = 0;
  Usb_select_endpoint(TX_EP);
  while(nb_data < num_read)
  {
    Usb_write_byte(local_buffer[nb_data]);
    nb_data++;
  }
  Usb_ack_in_ready();

  cdc_update_serial_state(); // I really do not know what this does, it could have been an old artifact from usart usb

//  if(usb_request_break_generation == TRUE)
//   usb_request_break_generation = FALSE;
}
Ejemplo n.º 12
0
uint8_t
ecm_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) {
	U8 byte_in_packet = 0;

	//Send Data
	Usb_select_endpoint(TX_EP);

	if(usb_endpoint_wait_for_write_enabled()!=0) {
		USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
		return 0;
	}

#ifdef USB_ETH_HOOK_TX_START
	USB_ETH_HOOK_TX_START();
#endif

	//Send packet
	while(sendlen) {
		Usb_write_byte(*senddata);
		senddata++;
		sendlen--;
		byte_in_packet++;
		
		//If endpoint is full, send data in
		//And then wait for data to transfer
		if (!Is_usb_write_enabled()) {
			Usb_ack_in_ready();

			if(usb_endpoint_wait_for_write_enabled()!=0) {
				USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
				return 0;
			}
			byte_in_packet=0;
		}

	}

	//Send last data in - also handles sending a ZLP if needed
	Usb_ack_in_ready();

#ifdef USB_ETH_HOOK_TX_END
	USB_ETH_HOOK_TX_END();
#endif

    //Wait for ready
	if(usb_endpoint_wait_for_IN_ready()!=0) {
		USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
		return 0;
	}

	return 1;
}
Ejemplo n.º 13
0
//! usb_send_packet.
//!
//! This function moves the data pointed by tbuf to the selected endpoint fifo
//! and sends it through the USB.
//!
//! @warning Code:xx bytes (function code length)
//!
//! @param ep_num       number of the addressed endpoint
//! @param *tbuf        address of the first data to send
//! @param data_length  number of bytes to send
//!
//! @return address of the next uint8_t to send.
//!
//! Example:
//! usb_send_packet(3,&first_data,0x20);    // send packet on the endpoint #3
//! while(!(Usb_tx_complete));              // wait packet ACK'ed by the Host
//! Usb_clear_tx_complete();                     // acknowledge the transmit
//!
//! Note:
//! tbuf is incremented of 'data_length'.
//!
uint8_t usb_send_packet(uint8_t ep_num, uint8_t* tbuf, uint8_t data_length)
{
uint8_t remaining_length;

   remaining_length = data_length;
   Usb_select_endpoint(ep_num);
   while(Is_usb_write_enabled() && (0 != remaining_length))
   {
      Usb_write_byte(*tbuf);
      remaining_length--;
      tbuf++;
   }
   return remaining_length;
}
Ejemplo n.º 14
0
//! usb_send_packet.
//!
//! This function moves the data pointed by tbuf to the selected endpoint fifo
//! and sends it through the USB.
//!
//!
//! @param ep_num       number of the addressed endpoint
//! @param *tbuf        address of the first data to send
//! @param data_length  number of bytes to send
//!
//! @return address of the next U8 to send.
//!
//! Example:
//! usb_send_packet(3,&first_data,0x20);    // send packet on the endpoint #3
//! while(!(Usb_tx_complete));              // wait packet ACK'ed by the Host
//! Usb_clear_tx_complete();                     // acknowledge the transmit
//!
//! Note:
//! tbuf is incremented of 'data_length'.
//!
U8 usb_send_packet(U8 ep_num, U8* tbuf, U8 data_length)
{
U8 remaining_length;

   remaining_length = data_length;
   Usb_select_endpoint(ep_num);
   while(Is_usb_write_enabled() && (0 != remaining_length))
   {
      Usb_write_byte(*tbuf);
      remaining_length--;
      tbuf++;
   }
   return remaining_length;
}
Ejemplo n.º 15
0
//! cdc_get_line_coding.
//!
//! @brief This function manages reception of line coding parameters (baudrate...).
//!
void cdc_get_line_coding(void)
{
  	Usb_ack_receive_setup();
  	Usb_write_byte(LSB0(line_coding.dwDTERate));
  	Usb_write_byte(LSB1(line_coding.dwDTERate));
  	Usb_write_byte(LSB2(line_coding.dwDTERate));
  	Usb_write_byte(LSB3(line_coding.dwDTERate));
  	Usb_write_byte(line_coding.bCharFormat);
  	Usb_write_byte(line_coding.bParityType);
  	Usb_write_byte(line_coding.bDataBits);

  	Usb_send_control_in();
  	while(!(Is_usb_read_control_enabled()));
  	//Usb_clear_tx_complete();

   while(!Is_usb_receive_out());
   Usb_ack_receive_out();
}
Ejemplo n.º 16
0
//! @brief This function manages hid get idle request.
//!
//! @param 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
   LSB(wInterface)= Usb_read_byte();
   MSB(wInterface)= Usb_read_byte();
   LSB(wLength)   = Usb_read_byte();
   MSB(wLength)   = Usb_read_byte();
   Usb_ack_receive_setup();
   
   if( wLength != 0 )
   {
      Usb_write_byte(g_u8_report_rate);
      Usb_send_control_in();
   }
   
   while(!Is_usb_receive_out());
   Usb_ack_receive_out();
}
Ejemplo n.º 17
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.
//!
//! @param type Not used
//! @param request Read request type
//!
//! @retval FALSE if unknown read type
//! @retval TRUE if request type is processed
//!
Bool usb_user_read_request(U8 type, U8 request)
{	
	U16 wLength;

	//Both protocols have two bytes we throw away
	Usb_read_byte();
	Usb_read_byte();

	switch(request)
	{
		case SEND_ENCAPSULATED_COMMAND:			
				Usb_read_byte();//wIndex LSB
				Usb_read_byte();//wIndex MSB

				LSB(wLength) = Usb_read_byte();
				MSB(wLength) = Usb_read_byte();
				return send_encapsulated_command(wLength);
      			break;

  		case GET_ENCAPSULATED_COMMAND:
				Usb_read_byte();//wIndex LSB
				Usb_read_byte();//wIndex MSB

				LSB(wLength) = Usb_read_byte();
				MSB(wLength) = Usb_read_byte();
				return get_encapsulated_command();
      			break;


        case MASS_STORAGE_RESET:
         		Usb_ack_receive_setup();
         		Usb_send_control_in();
         		return TRUE;
         		break;


		case GET_MAX_LUN:
         		Usb_ack_receive_setup();
         		Usb_write_byte( (get_nb_lun()-1) );
         		Usb_send_control_in();
         		ms_multiple_drive = 1;
         		return TRUE;
         		break;

	
	/* We don't have a real serial port - so these aren't applicable. We
	   advertise that we support nothing, so shouldn't get them anyway */
		case GET_LINE_CODING:
				cdc_get_line_coding();
				return TRUE;
      			break;

  		case SET_LINE_CODING:
				cdc_set_line_coding();
				return TRUE;
      			break;

		case SET_CONTROL_LINE_STATE:
				cdc_set_control_line_state();
      			return TRUE;
      			break;
     	default:
				break;

	}
	 
  	return FALSE;
}
//! 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();
   }
Ejemplo n.º 19
0
//! @brief This function manages hit get repport request.
//!
void hid_get_report_descriptor(void)
{
   U16 wLength;
   U8  nb_byte;
   bit zlp = FALSE;
   U16 wInterface;

   LSB(wInterface)=Usb_read_byte();
   MSB(wInterface)=Usb_read_byte();

   data_to_transfer = sizeof(usb_hid_report_descriptor);
   pbuffer = &(usb_hid_report_descriptor.report[0]);

   LSB(wLength) = Usb_read_byte();
   MSB(wLength) = Usb_read_byte();
   Usb_ack_receive_setup();

   if (wLength > data_to_transfer)
   {
      if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
      else { zlp = FALSE; }
   }
   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 __GNUC__
         Usb_write_byte(*pbuffer++);
#else    // AVRGCC does not support point to PGM space
         Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
#endif
         data_to_transfer --;
      }
      Usb_send_control_in();
   }

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

   while(!Is_usb_receive_out());
   Usb_ack_receive_out();
}
Ejemplo n.º 20
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();
}
//! 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();
}
void usb_get_string_descriptor(U8  string_type) {
	U16 requested_length;
	U8  dummy;
	PGM_P user_str;

	user_str = usb_user_get_string(string_type);

	if(!user_str) {
		usb_get_string_descriptor_sram(string_type);
		return;
	}
	
	dummy = Usb_read_byte();                     //!< don't care of wIndex field
	dummy = Usb_read_byte();
	requested_length = Usb_read_byte();              //!< read wLength
	requested_length |= Usb_read_byte()<<8;
	
	
	const U8 actual_descriptor_size = 2+strlen_P(user_str)*2;

	if (requested_length > actual_descriptor_size) {
		zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
		requested_length = actual_descriptor_size;
	}
	
	Usb_ack_receive_setup() ;                  //!< clear the receive setup flag

	if(usb_endpoint_wait_for_read_control_enabled()!=0) {
		Usb_enable_stall_handshake();
		return;
	}
	U8  nb_byte = 0;

	// Output the length
	if(requested_length) {
		Usb_write_byte(actual_descriptor_size);
		requested_length--;
		nb_byte++;
	}
	
	// Output the type
	if(requested_length) {
		Usb_write_byte(STRING_DESCRIPTOR);
		requested_length--;
		nb_byte++;
	}
	
	if(!requested_length) {
		Usb_send_control_in();
	}
		
	while((requested_length != 0) && (!Is_usb_receive_out()))
	{
		if(usb_endpoint_wait_for_read_control_enabled()!=0) {
			Usb_enable_stall_handshake();
			break;
		}

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

			Usb_write_byte(pgm_read_byte_near((unsigned int)user_str++));
			requested_length--;
			nb_byte++;
			if(requested_length) {
				Usb_write_byte(0);
				requested_length--;
				nb_byte++;
			}
		}
		Usb_send_control_in();
	}

//bail:

	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();
}
Ejemplo n.º 23
0
//! @brief This function manages hid get hid descriptor request.
//!
void hid_get_hid_descriptor(void)
{
   U16 wLength;
   U8  nb_byte;
   bit zlp=FALSE;
   U16 wInterface;

   LSB(wInterface)=Usb_read_byte();
   MSB(wInterface)=Usb_read_byte();

   data_to_transfer = sizeof(usb_conf_desc.hid_mouse);
   pbuffer = &(usb_conf_desc.hid_mouse.bLength);

   LSB(wLength) = Usb_read_byte();
   MSB(wLength) = Usb_read_byte();
   Usb_ack_receive_setup();

   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 __GNUC__
         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())
   { 
      // abort from Host
      Usb_ack_receive_out();
      return;
   }
   if(zlp == TRUE)
   { 
      while(!Is_usb_read_control_enabled());
      Usb_send_control_in();
   }

   while(!Is_usb_receive_out());
   Usb_ack_receive_out();
}