usb_specific_request.c

Go to the documentation of this file.
00001 /*This file is prepared for Doxygen automatic documentation generation.*/
00016 
00017 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms, with or without
00020  * modification, are permitted provided that the following conditions are met:
00021  *
00022  * 1. Redistributions of source code must retain the above copyright notice,
00023  * this list of conditions and the following disclaimer.
00024  *
00025  * 2. Redistributions in binary form must reproduce the above copyright notice,
00026  * this list of conditions and the following disclaimer in the documentation
00027  * and/or other materials provided with the distribution.
00028  *
00029  * 3. The name of Atmel may not be used to endorse or promote products derived
00030  * from this software without specific prior written permission.
00031  *
00032  * 4. This software may only be redistributed and used in connection with an Atmel
00033  * AVR product.
00034  *
00035  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00036  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00037  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00038  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00039  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00040  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00041  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00042  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00043  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00044  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00045  */
00046 
00047 
00048 //_____ I N C L U D E S ____________________________________________________
00049 
00050 #include "config.h"
00051 #include "conf_usb.h"
00052 #include "lib_mcu/usb/usb_drv.h"
00053 #include "usb_descriptors.h"
00054 #include "modules/usb/device_chap9/usb_standard_request.h"
00055 #include "usb_specific_request.h"
00056 #if ((USB_DEVICE_SN_USE==ENABLE) && (USE_DEVICE_SN_UNIQUE==ENABLE))
00057 #include "lib_mcu/flash/flash_drv.h"
00058 #endif
00059 
00060 //_____ D E F I N I T I O N ________________________________________________
00061 
00062 #ifdef __GNUC__
00063 extern PGM_VOID_P pbuffer;
00064 #else
00065 extern U8   code *pbuffer;
00066 #endif
00067 extern U8   data_to_transfer;
00068 extern code S_usb_hid_report_descriptor_mouse usb_hid_report_descriptor_mouse;
00069 
00070 U8 g_u8_report_rate=0;
00071 
00072 //_____ D E C L A R A T I O N ______________________________________________
00073 
00074 void hid_get_report_descriptor(void);
00075 void usb_hid_set_report_ouput(void);
00076 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration );
00077 void usb_hid_get_idle (U8 u8_report_id);
00078 void hid_get_hid_descriptor(void);
00079 
00080 
00089 Bool usb_user_read_request(U8 type, U8 request)
00090 {
00091    U8    wValue_msb;
00092    U8    wValue_lsb;
00093 
00094    // Read wValue
00095    wValue_lsb = Usb_read_byte();
00096    wValue_msb = Usb_read_byte();
00097 
00098    //** Specific request from Class HID
00099    if( USB_SETUP_GET_STAND_INTERFACE == type )
00100    {
00101       switch( request )
00102       {
00103          case SETUP_GET_DESCRIPTOR:
00104          switch( wValue_msb ) // Descriptor ID
00105          {
00106             case DESCRIPTOR_HID:
00107             hid_get_hid_descriptor();
00108             return TRUE;
00109             break;
00110    
00111             case DESCRIPTOR_REPORT:
00112             hid_get_report_descriptor();
00113             return TRUE;
00114    
00115             case DESCRIPTOR_PHYSICAL:
00116             // TODO
00117             break;
00118          }
00119          break;
00120       }
00121    }
00122    if( USB_SETUP_SET_CLASS_INTER == type )
00123    {
00124       switch( request )
00125       {
00126          case SETUP_HID_SET_REPORT:
00127          // The MSB wValue field specifies the Report Type
00128          // The LSB wValue field specifies the Report ID
00129          switch (wValue_msb)
00130          {
00131             case REPORT_TYPE_INPUT:
00132             // TODO
00133             break;
00134             
00135             case REPORT_TYPE_OUTPUT:
00136             usb_hid_set_report_ouput();
00137             return TRUE;
00138             break;
00139 
00140             case REPORT_TYPE_FEATURE:
00141             break;
00142          }
00143          break;
00144 
00145          case SETUP_HID_SET_IDLE:
00146          usb_hid_set_idle(wValue_lsb,wValue_msb);
00147          return TRUE;
00148    
00149          case SETUP_HID_SET_PROTOCOL:
00150          // TODO
00151          break;
00152       }
00153    }
00154    if( USB_SETUP_GET_CLASS_INTER == type )
00155    {
00156       switch( request )
00157       {
00158          case SETUP_HID_GET_REPORT:
00159          // TODO
00160          break;
00161          case SETUP_HID_GET_IDLE:
00162          usb_hid_get_idle(wValue_lsb);
00163          return TRUE;
00164          case SETUP_HID_GET_PROTOCOL:
00165          // TODO
00166          break;
00167       }
00168    }
00169    return FALSE;  // No supported request
00170 }
00171 
00172 
00177 void usb_user_endpoint_init(U8 conf_nb)
00178 {
00179    usb_configure_endpoint( EP_MOUSE_IN,   \
00180                            TYPE_INTERRUPT,\
00181                            DIRECTION_IN,  \
00182                            SIZE_8,        \
00183                            ONE_BANK,      \
00184                            NYET_ENABLED);
00185 }
00186 
00187 
00194 U8   usb_user_interface_get( U16 wInterface )
00195 {
00196    return 0;  // Only one alternate setting possible for all interface
00197 }
00198 
00199 
00205 void usb_user_interface_reset(U16 wInterface, U8 alternate_setting)
00206 {  
00207    // default setting selected = reset data toggle
00208    if( INTERFACE_NB_MOUSE == wInterface )
00209    {
00210       // Interface mouse
00211       Usb_select_endpoint(EP_MOUSE_IN);
00212       Usb_disable_stall_handshake();
00213       Usb_reset_endpoint(EP_MOUSE_IN);
00214       Usb_reset_data_toggle();
00215    }
00216 }
00217 
00218    
00226 Bool usb_user_get_descriptor(U8 type, U8 string)
00227 {
00228    switch(type)
00229    {
00230       case DESCRIPTOR_STRING:
00231       switch (string)
00232       {
00233          case LANG_ID:
00234          data_to_transfer = sizeof (usb_user_language_id);
00235          pbuffer = &(usb_user_language_id.bLength);
00236          return TRUE;
00237          break;
00238         
00239          case MAN_INDEX:
00240          data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
00241          pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
00242          return TRUE;
00243          break;
00244         
00245          case PROD_INDEX:
00246          data_to_transfer = sizeof (usb_user_product_string_descriptor);
00247          pbuffer = &(usb_user_product_string_descriptor.bLength);
00248          return TRUE;
00249          break;
00250            
00251 #if (USB_DEVICE_SN_USE==ENABLE)              
00252          case SN_INDEX:
00253          data_to_transfer = sizeof (usb_user_serial_number);
00254          pbuffer = &(usb_user_serial_number.bLength);
00255 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00256          f_get_serial_string=TRUE;
00257          data_to_transfer += (SN_LENGTH*4);
00258 #endif
00259          return TRUE;
00260          break;
00261 #endif
00262       }
00263       break;
00264    }
00265    return FALSE;
00266 }
00267 
00268 
00271 void hid_get_report_descriptor(void)
00272 {
00273    U16 wLength;
00274    U8  nb_byte;
00275    bit zlp = FALSE;
00276    U16 wInterface;
00277 
00278    LSB(wInterface)=Usb_read_byte();
00279    MSB(wInterface)=Usb_read_byte();
00280 
00281    data_to_transfer = sizeof(usb_hid_report_descriptor_mouse);
00282    pbuffer = &(usb_hid_report_descriptor_mouse.report[0]);
00283 
00284    LSB(wLength) = Usb_read_byte();
00285    MSB(wLength) = Usb_read_byte();
00286    Usb_ack_receive_setup();
00287 
00288    if (wLength > data_to_transfer)
00289    {
00290       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00291       else { zlp = FALSE; }
00292    }
00293    else
00294    {
00295       data_to_transfer = (U8)wLength;           // send only requested number of data
00296    }
00297 
00298    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00299    {
00300       while(!Is_usb_read_control_enabled());
00301 
00302       nb_byte=0;
00303       while(data_to_transfer != 0)              // Send data until necessary
00304       {
00305          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00306          {
00307             break;
00308          }
00309 #ifndef __GNUC__
00310          Usb_write_byte(*pbuffer++);
00311 #else    // AVRGCC does not support point to PGM space
00312          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00313 #endif
00314          data_to_transfer --;
00315       }
00316       Usb_send_control_in();
00317    }
00318 
00319    if(Is_usb_receive_out())
00320    { 
00321       // abort from Host
00322       Usb_ack_receive_out();
00323       return;
00324    }
00325    if(zlp == TRUE)
00326    { 
00327       while(!Is_usb_read_control_enabled());
00328       Usb_send_control_in();
00329    }
00330 
00331    while(!Is_usb_receive_out());
00332    Usb_ack_receive_out();
00333 }
00334 
00335 
00338 void usb_hid_set_report_ouput (void)
00339 {
00340    Usb_ack_receive_setup();
00341    Usb_send_control_in();
00342 
00343    while(!Is_usb_receive_out());
00344    Usb_ack_receive_out();
00345    Usb_send_control_in();
00346 }
00347 
00348 
00354 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration )
00355 {
00356    U16 wInterface;
00357    
00358    // Get interface number to put in idle mode
00359    LSB(wInterface)=Usb_read_byte();
00360    MSB(wInterface)=Usb_read_byte();
00361    Usb_ack_receive_setup();
00362   
00363    g_u8_report_rate = u8_duration;
00364    
00365    Usb_send_control_in();
00366    while(!Is_usb_in_ready());
00367 }
00368 
00369 
00374 void usb_hid_get_idle (U8 u8_report_id)
00375 {
00376    U16 wLength;
00377    U16 wInterface;
00378 
00379    // Get interface number to put in idle mode
00380    LSB(wInterface)= Usb_read_byte();
00381    MSB(wInterface)= Usb_read_byte();
00382    LSB(wLength)   = Usb_read_byte();
00383    MSB(wLength)   = Usb_read_byte();
00384    Usb_ack_receive_setup();
00385    
00386    if( wLength != 0 )
00387    {
00388       Usb_write_byte(g_u8_report_rate);
00389       Usb_send_control_in();
00390    }
00391    
00392    while(!Is_usb_receive_out());
00393    Usb_ack_receive_out();
00394 }
00395 
00396 
00399 void hid_get_hid_descriptor(void)
00400 {
00401    U16 wLength;
00402    U8  nb_byte;
00403    bit zlp=FALSE;
00404    U16 wInterface;
00405 
00406    LSB(wInterface)=Usb_read_byte();
00407    MSB(wInterface)=Usb_read_byte();
00408 
00409    data_to_transfer = sizeof(usb_conf_desc.hid_mouse);
00410    pbuffer = &(usb_conf_desc.hid_mouse.bLength);
00411 
00412    LSB(wLength) = Usb_read_byte();
00413    MSB(wLength) = Usb_read_byte();
00414    Usb_ack_receive_setup();
00415 
00416    if (wLength > data_to_transfer)
00417    {
00418       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00419       else { zlp = FALSE; }                     // no need of zero length packet
00420    }
00421    else
00422    {
00423       data_to_transfer = (U8)wLength;           // send only requested number of data
00424    }
00425 
00426    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00427    {
00428       while(!Is_usb_read_control_enabled());
00429 
00430       nb_byte=0;
00431       while(data_to_transfer != 0)              // Send data until necessary
00432       {
00433          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00434          {
00435             break;
00436          }
00437 #ifndef __GNUC__
00438          Usb_write_byte(*pbuffer++);
00439 #else    // AVRGCC does not support point to PGM space
00440          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00441 #endif
00442          data_to_transfer --;
00443       }
00444       Usb_send_control_in();
00445    }
00446 
00447    if(Is_usb_receive_out())
00448    { 
00449       // abort from Host
00450       Usb_ack_receive_out();
00451       return;
00452    }
00453    if(zlp == TRUE)
00454    { 
00455       while(!Is_usb_read_control_enabled());
00456       Usb_send_control_in();
00457    }
00458 
00459    while(!Is_usb_receive_out());
00460    Usb_ack_receive_out();
00461 }
00462 

Generated on Fri Sep 11 14:41:51 2009 for ATMEL by  doxygen 1.5.3