All pastes #95654 Raw Edit

Anonymous

public text v1 · immutable
#95654 ·published 2006-07-22 05:54 UTC
rendered paste body
/*C**************************************************************************
* NAME:         usb_kbd_enum.c
*----------------------------------------------------------------------------
* Copyright (c) 2003 Atmel.
*----------------------------------------------------------------------------
* RELEASE:      c5131-usb-kbd-light-1_0_2      
* REVISION:     1.2     
*----------------------------------------------------------------------------
* PURPOSE: 
* This file contains the USB Endpoint 0 management routines corresponding
* to a USB HID keyboard implementation.
*****************************************************************************/

/*_____ I N C L U D E S ____________________________________________________*/

#include "config.h"
#include "lib_mcu\usb\usb_drv.h"
#include "usb_kbd_enum.h"

/*_____ M A C R O S ________________________________________________________*/


/*_____ D E F I N I T I O N ________________________________________________*/

code struct usb_st_device_descriptor usb_device_descriptor =
{
  sizeof(usb_device_descriptor), DEVICE, USB_SPECIFICATION, DEVICE_CLASS,
  DEVICE_SUB_CLASS, DEVICE_PROTOCOL, EP_CONTROL_LENGTH, VENDOR_ID, PRODUCT_ID,
  RELEASE_NUMBER, MAN_INDEX, PROD_INDEX, SN_INDEX, NB_CONFIGURATION
};

code struct usb_st_manufacturer usb_manufacturer =
{ sizeof(usb_manufacturer),  STRING, USB_MANUFACTURER_NAME };

code struct usb_st_product usb_product =
{ sizeof(usb_product),       STRING, USB_PRODUCT_NAME };

code struct usb_st_serial_number usb_serial_number =
{ sizeof(usb_serial_number), STRING, USB_SERIAL_NUMBER };

code struct usb_st_language_descriptor usb_language =
{ sizeof(usb_language),      STRING, LANGUAGE_ID };

code struct  
{ struct usb_st_configuration_descriptor  cfg;
  struct usb_st_interface_descriptor      ifc;
  struct usb_st_hid_descriptor            hid ;
  struct usb_st_endpoint_descriptor       ep1 ;
  Uchar                                   rep[SIZE_OF_REPORT] ;
}
  usb_configuration =
  {
    { 9, CONFIGURATION, CONF_LENGTH, NB_INTERFACE, CONF_NB,
      CONF_INDEX, CONF_ATTRIBUTES, MAX_POWER},
    { 9, INTERFACE, INTERFACE_NB, ALTERNATE, NB_ENDPOINT, INTERFACE_CLASS,
      INTERFACE_SUB_CLASS, INTERFACE_PROTOCOL, INTERFACE_INDEX },
    { 9, HID, 0x1101, 8, 1, REPORT, 0x3B00 },
    { 7, ENDPOINT, ENDPOINT_NB_1, EP_ATTRIBUTES_1, EP_SIZE_1, EP_INTERVAL_1 },
    { 0x05,0x01,          /* Usage Page (Generic Desktop)      */        
      0x09,0x04,          /* Usage (Keyboard)                  */
      0xA1,0x01,          /* Collection (Application)          */
      0x05,0x07,          /* Usage Page (Keyboard)             */
   	
	  0x19,224,           /* Usage Minimum (224)               */
      0x29,231,           /* Usage Maximum (231)               */
      0x15,0x00,          /* Logical Minimum (0)               */
      0x25,0x01,          /* Logical Maximum (1)               */
      0x75,0x01,          /* Report Size (1)                   */
      0x95,0x08,          /* Report Count (8)                  */
      0x81,0x02,          /* Input (Data, Variable, Absolute)  */
      0x81,0x01,          /* Input (Constant)                  */
      0x19,0x00,          /* Usage Minimum (0)                 */
      0x29,101,           /* Usage Maximum (101)               */
      0x15,0x00,          /* Logical Minimum (0)               */
      0x25,101,           /* Logical Maximum (101)             */
      0x75,0x08,          /* Report Size (8)                   */
      0x95,0x06,          /* Report Count (6)                  */
      0x81,0x00,          /* Input (Data, Array)               */
      0x05,0x08,          /* Usage Page (LED)                  */
      0x19,0x01,          /* Usage Minimum (1)                 */
      0x29,0x05,          /* Usage Maximum (5)                 */
      0x15,0x00,          /* Logical Minimum (0)               */
      0x25,0x01,          /* Logical Maximum (1)               */
      0x75,0x01,          /* Report Size (1)                   */
      0x95,0x05,          /* Report Count (5)                  */
      0x91,0x02,          /* Output (Data, Variable, Absolute) */
      0x95,0x03,          /* Report Count (3)                  */
      0x91,0x01,          /* Output (Constant)                 */
      0xC0                /* End Collection                    */  
      }
  };

static  bit     zlp;
static  Uchar   endpoint_status[2];
static  Uchar   hid_idle_duration;
static  Uchar   *pbuffer;
static  Uchar   bmRequestType;

        Uchar   usb_configuration_nb;
extern  bit     usb_connected;
/*_____ D E C L A R A T I O N ______________________________________________*/

static  void    usb_get_descriptor (void);
static  void    usb_read_request (void);
static  void    usb_set_address (void);
static  void    usb_set_configuration (void);
static  void    usb_clear_feature (void);
static  void    usb_set_feature (void);
static  void    usb_get_status (void);
static  void    usb_get_configuration (void);
static  void    usb_get_interface (void);
static  void    usb_hid_set_report (void);
static  void    usb_hid_set_idle (void);
static  void    usb_hid_get_idle (void);

/*F**************************************************************************
* NAME: usb_var_init
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function initializes the USB controller and resets the endpoints FIFOs.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_var_init (void)
{
  endpoint_status[EP_CONTROL] = 0x00;
  endpoint_status[EP_IN] = 0x00;
  usb_connected = FALSE;
  usb_configuration_nb = 0x00;
}


/*F**************************************************************************
* NAME: usb_ep_init
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function configures the endpoints.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_ep_init (void)
{
  usb_configure_endpoint(EP_IN , INTERRUPT_IN);
  usb_reset_endpoint(EP_IN);
}



/*F**************************************************************************
* NAME: usb_enumeration_process
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the enumeration process
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: 
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_enumeration_process (void)
{ 
  Usb_select_ep(EP_CONTROL);
  usb_read_request();
}


/*F**************************************************************************
* NAME: usb_read_request
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function reads the SETUP request sent to the default control endpoint
* and  the appropriate function. When exiting of the usb_read_request
* function, the device is ready to manage the next request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE: list of supported requests:
*               GET_DESCRIPTOR
*               GET_CONFIGURATION
*               SET_ADDRESS
*               SET_CONFIGURATION or SET_REPORT
*               CLEAR_FEATURE
*               SET_FEATURE
*               GET_STATUS
*               GET_MAX_LUN
*               MASS_STORAGE_RESET
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_read_request (void)
{ 
  bmRequestType = Usb_read_byte();          /* read bmRequestType */

  switch (Usb_read_byte())                  /* test the bRequest value */
  {
    case GET_DESCRIPTOR:
      usb_get_descriptor();
      break;
    case GET_CONFIGURATION:
      usb_get_configuration();
      break;
    case SET_ADDRESS:
      usb_set_address();
      break;
    case SET_CONFIGURATION:  /* or SET_REPORT */
      if (bmRequestType == 0) { usb_set_configuration(); }
      else { usb_hid_set_report(); }
      break;
    case CLEAR_FEATURE:
      usb_clear_feature();
      break;
    case SET_FEATURE:
      usb_set_feature();
      break;
    case GET_STATUS:
      usb_get_status();
      break;
    case GET_INTERFACE:      /* HID_SET_IDLE */
      if (bmRequestType == 0x81) { usb_get_interface(); } 
      else { usb_hid_set_idle(); }
      break;
    case HID_GET_IDLE:
      usb_hid_get_idle();
      break;
    case SET_DESCRIPTOR:
    case SET_INTERFACE:
    case SYNCH_FRAME:
    default:
      Usb_clear_rx_setup();
      
	  Usb_set_stall_request();
      while (!Usb_stall_sent());
      Usb_clear_stall_request();
      Usb_clear_stalled();
      break;
    }
    Usb_clear_DIR();
}


/*F**************************************************************************
* NAME: usb_set_address
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the SET_ADDRESS request. The new address is stored
* in the USBADDR register
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_set_address (void)
{
Uchar add;

  add = Usb_read_byte();                    /* store the LSB of wValue = address */
  Usb_clear_rx_setup();
  Usb_set_tx_ready();                          /* send a ZLP for STATUS phase */
  Usb_set_FADDEN();	   					/* The FEN bit and the FADDEN bit in the USBCON register will
be set to allow the USB controller to answer only to requests sent at the new
address */

  while (!(Usb_tx_complete()));
  Usb_clear_tx_complete();
  Usb_configure_address(add); 			/* FEN bit is set in USBADDR Register	*/
}


/*F**************************************************************************
* NAME: usb_set_configuration
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the SET_CONFIGURATION request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_set_configuration (void)
{
 Uchar configuration_number;
  configuration_number = Usb_read_byte();   /* read the conf. num. in wValue */
  Usb_clear_DIR();
  Usb_clear_rx_setup();
/*  switch (configuration_number)
  {
    case 0:
      Usb_clear_CONFG();
      usb_configurion = 0x00;
      break;
    case CONF_NB:
      Usb_set_CONFG();
      Usb_set_usb_configured();
      break;
    default:
      Usb_set_stall_request();
      while (!Usb_stall_sent());
      Usb_clear_stall_request();
      Usb_clear_stalled();
      return;
  }*/
  if (configuration_number <= CONF_NB)
  {
    usb_configuration_nb = configuration_number;
  }
  else
  {
    Usb_set_stall_request();
    while (!Usb_stall_sent());
    Usb_clear_stall_request();
    Usb_clear_stalled();
    return;
  }

  Usb_set_tx_ready();                          /* send a ZLP for STATUS phase */
  while (!Usb_tx_complete());
  Usb_clear_tx_complete();
  usb_ep_init();                            /* endpoints configuration */
}


/*F**************************************************************************
* NAME: usb_get_descriptor
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the GET_DESCRIPTOR request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_get_descriptor (void)
{
Uchar   data_to_transfer;
Uint16  wLength;
Uchar   descriptor_type;
Uchar   string_type;

  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:
    {
      data_to_transfer = sizeof (usb_device_descriptor); 			  
      pbuffer = &(usb_device_descriptor.bLength);
      break;
    }

    case CONFIGURATION:
    {
      data_to_transfer = sizeof (usb_configuration);
      pbuffer = &(usb_configuration.cfg.bLength);
      break;
    }

    case REPORT:
    {
      data_to_transfer = SIZE_OF_REPORT;
      pbuffer = &(usb_configuration.rep[0]);
      break;
    }

    case HID:
    {
      data_to_transfer = sizeof(usb_configuration.hid);
      pbuffer = &(usb_configuration.hid.bLength);
      break;
    }
    case STRING:
    {
      switch (string_type)
      {
        case LANG_ID:
        {
          data_to_transfer = sizeof (usb_language);
          pbuffer = &(usb_language.bLength);
          break;
        }
        case MAN_INDEX:
        {
          data_to_transfer = sizeof (usb_manufacturer);
          pbuffer = &(usb_manufacturer.bLength);
          break;
        }
        case PROD_INDEX:
        {
          data_to_transfer = sizeof (usb_product);
          pbuffer = &(usb_product.bLength);
          break;
        }
        case SN_INDEX:
        {
          data_to_transfer = sizeof (usb_serial_number);
          pbuffer = &(usb_serial_number.bLength);
          break;
        }
        default:
        {
          Usb_clear_rx_setup();
          Usb_set_stall_request(); 
          while ((!(Usb_stall_sent())) && (Usb_setup_received()));
          Usb_clear_stalled();
          Usb_clear_stall_request();
          Usb_clear_DIR();
          return;
        }
      }
      break;
    }

    default:
    {
      Usb_clear_rx_setup();
      Usb_set_stall_request();
      while ((!(Usb_stall_sent())) && (Usb_setup_received()));
      Usb_clear_stalled();
      Usb_clear_stall_request();
      Usb_clear_DIR();
      return;
    }
  }

  ACC = Usb_read_byte();                    /* don't care of wIndex field */
  ACC = Usb_read_byte();
  ((Uchar*)&wLength)[1] = Usb_read_byte();   /* read wLength */
  ((Uchar*)&wLength)[0] = Usb_read_byte();
  if (wLength > data_to_transfer)
  {
    if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }  /*EP_CONTROL_LENGTH IS bMaxPacketSizeO */
  																	 	/*zlp = zero length packet = success*/				
    else { zlp = FALSE; }                        /* no need of zero length packet */
  }
  else
  {
    data_to_transfer = (Uchar)wLength;       /* send only requested number of data */
  }
  Usb_clear_rx_setup() ;                     /* clear the receive setup flag */
  Usb_set_DIR();                            /* set out on EP0 */

  while (data_to_transfer > EP_CONTROL_LENGTH)	  /* data_to_transfer = size of the descriptor structure */
  {
    pbuffer = usb_send_ep0_packet(pbuffer, EP_CONTROL_LENGTH);
    data_to_transfer -= EP_CONTROL_LENGTH;		   		/*	Data = Data - EP  */
						/* if 3 transactions eg: on 3rd loop, descriptor structure - 2*ep_control_length	/*
												  	
    while ((!(Usb_rx_complete())) && (!(Usb_tx_complete())));
    Usb_clear_tx_complete();
    if ((Usb_rx_complete()))                /* if cancel from USB Host */
    {
      Usb_clear_tx_ready();
      Usb_clear_rx();
      return;
    }
  }
  /* send last data packet */
  pbuffer = usb_send_ep0_packet(pbuffer, data_to_transfer);
  data_to_transfer = 0;
  while ((!(Usb_rx_complete())) && (!(Usb_tx_complete())));
  Usb_clear_tx_complete();
  if ((Usb_rx_complete()))                  /* if cancel from USB Host */
  {
    Usb_clear_tx_ready();
    Usb_clear_rx();
    return;
  }

  if (zlp == TRUE)
  {
    usb_send_ep0_packet(pbuffer, 0);
    while ((!(Usb_rx_complete())) && (!(Usb_tx_complete())));
    Usb_clear_tx_complete();
    if ((Usb_rx_complete()))              /* if cancel from USB Host */
    {
      Usb_clear_tx_ready();
      Usb_clear_rx();
      return;
    }

  }
  while ((!(Usb_rx_complete())) && (!(Usb_setup_received())));
  if (Usb_setup_received())
  {
    return;
  }

  if (Usb_rx_complete())
  {
    Usb_clear_DIR();                        /* set in on EP0 */
    Usb_clear_rx();
  }
}


/*F**************************************************************************
* NAME: usb_get_configuration
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the GET_CONFIGURATION request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_get_configuration (void)
{
  Usb_clear_rx_setup();
  Usb_set_DIR();

/*  if (Usb_get_usb_configured()) { Usb_write_byte(1); }
  else { Usb_write_byte(0); }
*/
  Usb_write_byte(usb_configuration_nb);

  Usb_set_tx_ready();
  while (!(Usb_tx_complete()));
  Usb_clear_tx_complete();
  while (!(Usb_rx_complete()));
  Usb_clear_rx();
  Usb_clear_DIR();
}

/*F**************************************************************************
* NAME: usb_get_interface
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the GET_INTERFACE request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_get_interface (void)
{
  Usb_clear_rx_setup();
  Usb_set_DIR();
  Usb_set_stall_request();			 /* send STALL if only one interface configuration  */
  while (!Usb_stall_sent());
  Usb_clear_stall_request();
  Usb_clear_stalled();
  Usb_clear_DIR();
}


/*F**************************************************************************
* NAME: usb_get_status
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the GET_STATUS request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_get_status (void)
{
Uchar wIndex;

  ACC = Usb_read_byte();                    /* dummy read */
  ACC = Usb_read_byte();                    /* dummy read */
  wIndex = Usb_read_byte();
  Usb_clear_rx_setup();
  Usb_set_DIR();
  switch(bmRequestType) 
  {
    case REQUEST_DEVICE_STATUS:    Usb_write_byte(SELF_POWERED);  break;
    
    case REQUEST_INTERFACE_STATUS: Usb_write_byte(0x00);          break;
    
    case REQUEST_ENDPOINT_STATUS:  wIndex = wIndex & MSK_EP_DIR;
                                   Usb_write_byte(endpoint_status[wIndex]);
                                   break;
  }
  Usb_write_byte(0x00);

  Usb_set_tx_ready();
  while ((!(Usb_tx_complete())) || (Usb_setup_received()));
  Usb_clear_tx_complete();
  while ((!(Usb_rx_complete())) || (Usb_setup_received()));
  Usb_clear_rx();
  Usb_clear_DIR();
}


/*F**************************************************************************
* NAME: usb_set_feature
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the SET_FEATURE request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_set_feature (void)
{
  if (bmRequestType == ZERO_TYPE)
  {
    Usb_clear_rx_setup();
    Usb_set_stall_request();
    while (!(Usb_stall_sent()));
    Usb_clear_stall_request();
  }
  if (bmRequestType == INTERFACE_TYPE)
  {
    Usb_clear_rx_setup();
    Usb_set_stall_request();
    while (!(Usb_stall_sent()));
    Usb_clear_stall_request();
  }
  if (bmRequestType == ENDPOINT_TYPE)
  {
    if (Usb_read_byte() == 0x00)
    {
      ACC = Usb_read_byte();                /* dummy read */
      switch (Usb_read_byte())              /* check wIndex */
      {
        case ENDPOINT_1:
        {
          Usb_select_ep(EP_IN);
          Usb_set_stall_request();
          Usb_select_ep(EP_CONTROL);
          endpoint_status[EP_IN] = 0x01;
          Usb_clear_rx_setup();
          Usb_set_tx_ready();
          while (!(Usb_tx_complete()));
          Usb_clear_tx_complete();
          break;
        }
        default:
        {
          Usb_clear_rx_setup();
          Usb_set_stall_request();
          while (!(Usb_stall_sent()));
          Usb_clear_stall_request();
          Usb_clear_stalled();
          break;
        }
      }
    }
  }
}


/*F**************************************************************************
* NAME: usb_clear_feature
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the SET_FEATURE request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_clear_feature (void)
{
  if (bmRequestType == ZERO_TYPE)
  {
    Usb_clear_rx_setup();
    Usb_set_stall_request();
    while (!(Usb_stall_sent()));
    Usb_clear_stall_request();
  }
  if (bmRequestType == INTERFACE_TYPE)
  {
    Usb_clear_rx_setup();
    Usb_set_stall_request();
    while (!(Usb_stall_sent()));
    Usb_clear_stall_request();
  }
  if (bmRequestType == ENDPOINT_TYPE)
  {
    if (Usb_read_byte() == 0x00)
    {
      ACC = Usb_read_byte();                /* dummy read */
      switch (Usb_read_byte())              /* check wIndex */
      {
        case ENDPOINT_1:
        {
          Usb_select_ep(EP_IN);
          Usb_clear_stall_request();
          usb_reset_endpoint(EP_IN);
          Usb_select_ep(EP_CONTROL);
          endpoint_status[EP_IN] = 0x00;
          Usb_clear_rx_setup();
          Usb_set_tx_ready();
          while (!(Usb_tx_complete()));
          Usb_clear_tx_complete();
          break;
        }
        case ENDPOINT_0:
        {
          Usb_clear_rx_setup();
          Usb_set_tx_ready();
          while (!(Usb_tx_complete()));
          Usb_clear_tx_complete();
          break;
        }
        default:
        {
          Usb_clear_rx_setup();
          Usb_set_stall_request();
          while (!(Usb_stall_sent()));
          Usb_clear_stall_request();
          break;
        }
      }
    }
  }
}
/*F**************************************************************************
* NAME: usb_hid_set_report
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the SET_REPORT request (HID Class)
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_hid_set_report (void)
{
  Usb_clear_rx_setup();
  
  while(!Usb_rx_complete() );
  Usb_clear_rx();
  Usb_set_tx_ready();                          /* send a ZLP for STATUS phase */
  while(!(Usb_tx_complete()));
  Usb_clear_tx_complete();
}



/*F**************************************************************************
* NAME: usb_hid_set_idle
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the HID_SET_IDLE request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_hid_set_idle (void)
{
  ACC = Usb_read_byte();
  hid_idle_duration = Usb_read_byte();      /* wValue contains the duration */
  Usb_clear_rx_setup();

  Usb_set_tx_ready();                          /* send a ZLP for STATUS phase */
  while(!(Usb_tx_complete()));
  Usb_clear_tx_complete();
}

/*F**************************************************************************
* NAME: usb_hid_get_idle
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE: 
* This function manages the GET_IDLE request.
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS: 
*****************************************************************************/
void usb_hid_get_idle (void)
{
  Usb_clear_rx_setup();
  Usb_set_DIR();
  Usb_write_byte(hid_idle_duration);
  Usb_set_tx_ready();                          /* send a ZLP for STATUS phase */
  while(!(Usb_tx_complete()));
  Usb_clear_tx_complete();
  
  while (!(Usb_rx_complete()));
  Usb_clear_rx();
  Usb_clear_DIR();
}

/*_____ E N D  O F  F I L E  _________________________________________________*/