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 #include "modules/control_access/ctrl_access.h"
00057 #if ((USB_DEVICE_SN_USE==ENABLE) && (USE_DEVICE_SN_UNIQUE==ENABLE))
00058 #include "lib_mcu/flash/flash_drv.h"
00059 #endif
00060 
00061 //_____ D E F I N I T I O N ________________________________________________
00062 
00063 bit  ms_multiple_drive;
00064 
00065 #ifdef __GNUC__
00066 extern PGM_VOID_P pbuffer;
00067 #else
00068 extern U8   code *pbuffer;
00069 #endif
00070 extern U8   data_to_transfer;
00071 extern code S_usb_hid_report_descriptor_mouse usb_hid_report_descriptor_mouse;
00072 
00073 U8 g_u8_report_rate=0;
00074 
00075 //_____ D E C L A R A T I O N ______________________________________________
00076 
00077 void hid_get_report_descriptor(void);
00078 void usb_hid_set_report_ouput(void);
00079 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration );
00080 void usb_hid_get_idle (U8 u8_report_id);
00081 void hid_get_hid_descriptor(void);
00082 
00083 
00092 Bool usb_user_read_request(U8 type, U8 request)
00093 {
00094    U16   wInterface;
00095    U8    wValue_msb;
00096    U8    wValue_lsb;
00097 
00098    // Read wValue
00099    wValue_lsb = Usb_read_byte();
00100    wValue_msb = Usb_read_byte();
00101 
00102    //** Specific request from Class HID
00103    if( USB_SETUP_GET_STAND_INTERFACE == type )
00104    {
00105       switch( request )
00106       {
00107          case SETUP_GET_DESCRIPTOR:
00108          switch( wValue_msb ) // Descriptor ID
00109          {
00110             case DESCRIPTOR_HID:
00111             hid_get_hid_descriptor();
00112             return TRUE;
00113             break;
00114    
00115             case DESCRIPTOR_REPORT:
00116             hid_get_report_descriptor();
00117             return TRUE;
00118    
00119             case DESCRIPTOR_PHYSICAL:
00120             // TODO
00121             break;
00122          }
00123          break;
00124       }
00125    }
00126    if( USB_SETUP_SET_CLASS_INTER == type )
00127    {
00128       switch( request )
00129       {
00130          case SETUP_HID_SET_REPORT:
00131          // The MSB wValue field specifies the Report Type
00132          // The LSB wValue field specifies the Report ID
00133          switch (wValue_msb)
00134          {
00135             case REPORT_TYPE_INPUT:
00136             // TODO
00137             break;
00138             
00139             case REPORT_TYPE_OUTPUT:
00140             usb_hid_set_report_ouput();
00141             return TRUE;
00142             break;
00143 
00144             case REPORT_TYPE_FEATURE:
00145             break;
00146          }
00147          break;
00148 
00149          case SETUP_HID_SET_IDLE:
00150          usb_hid_set_idle(wValue_lsb,wValue_msb);
00151          return TRUE;
00152    
00153          case SETUP_HID_SET_PROTOCOL:
00154          // TODO
00155          break;
00156       }
00157    }
00158    if( USB_SETUP_GET_CLASS_INTER == type )
00159    {
00160       switch( request )
00161       {
00162          case SETUP_HID_GET_REPORT:
00163          // TODO
00164          break;
00165          case SETUP_HID_GET_IDLE:
00166          usb_hid_get_idle(wValue_lsb);
00167          return TRUE;
00168          case SETUP_HID_GET_PROTOCOL:
00169          // TODO
00170          break;
00171       }
00172    }
00173  
00174    //** Specific request from Class MassStorage
00175    if( USB_SETUP_SET_CLASS_INTER == type )
00176    {
00177       switch( request )
00178       {
00179          case SETUP_MASS_STORAGE_RESET:
00180          // wValue must be 0
00181          // wIndex = Interface
00182          if( (0!=wValue_lsb) || (0!=wValue_msb) )
00183             break;
00184          LSB(wInterface)=Usb_read_byte();
00185          MSB(wInterface)=Usb_read_byte();
00186          if( INTERFACE_NB != wInterface )
00187             break;
00188          Usb_ack_receive_setup();
00189          Usb_send_control_in();
00190          while(!Is_usb_in_ready());
00191          return TRUE;
00192          break;
00193       }
00194    }
00195    if( USB_SETUP_GET_CLASS_INTER == type )
00196    {
00197       switch( request )
00198       {
00199          case SETUP_MASS_STORAGE_GET_MAX_LUN:
00200          // wValue must be 0
00201          // wIndex = Interface
00202          if( (0!=wValue_lsb) || (0!=wValue_msb) )
00203             break;
00204          LSB(wInterface)=Usb_read_byte();
00205          MSB(wInterface)=Usb_read_byte();
00206          if( INTERFACE_NB != wInterface )
00207             break;
00208          Usb_ack_receive_setup();
00209          Usb_write_byte( (get_nb_lun()-1) );
00210          Usb_send_control_in();
00211          while(!Is_usb_in_ready());
00212          while( !Is_usb_receive_out() );
00213          Usb_ack_receive_out();
00214          ms_multiple_drive = 1;
00215          return TRUE;
00216          break;
00217       }
00218    }
00219    
00220    return FALSE;  // No supported request
00221 }
00222 
00223 
00228 void usb_user_endpoint_init(U8 conf_nb)
00229 {
00230    usb_configure_endpoint( EP_MOUSE_IN,   \
00231                            TYPE_INTERRUPT,\
00232                            DIRECTION_IN,  \
00233                            SIZE_8,        \
00234                            ONE_BANK,      \
00235                            NYET_ENABLED);
00236 
00237    usb_configure_endpoint( EP_MS_IN,      \
00238                            TYPE_BULK,     \
00239                            DIRECTION_IN,  \
00240                            SIZE_64,       \
00241                            ONE_BANK,      \
00242                            NYET_ENABLED);
00243 
00244    usb_configure_endpoint( EP_MS_OUT,     \
00245                            TYPE_BULK,     \
00246                            DIRECTION_OUT, \
00247                            SIZE_64,       \
00248                            ONE_BANK,      \
00249                            NYET_ENABLED);
00250 }
00251 
00252 
00259 U8   usb_user_interface_get( U16 wInterface )
00260 {
00261    return 0;  // Only one alternate setting possible for all interface
00262 }
00263 
00264 
00270 void usb_user_interface_reset(U16 wInterface, U8 alternate_setting)
00271 {  
00272    // default setting selected = reset data toggle
00273    if( INTERFACE_NB_MOUSE == wInterface )
00274    {
00275       // Interface mouse
00276       Usb_select_endpoint(EP_MOUSE_IN);
00277       Usb_disable_stall_handshake();
00278       Usb_reset_endpoint(EP_MOUSE_IN);
00279       Usb_reset_data_toggle();
00280    }
00281    if( INTERFACE_NB == wInterface )
00282    {
00283       // Interface Mass Storage
00284       Usb_select_endpoint(EP_MS_IN);
00285       Usb_disable_stall_handshake();
00286       Usb_reset_endpoint(EP_MS_IN);
00287       Usb_reset_data_toggle();
00288       Usb_select_endpoint(EP_MS_OUT);
00289       Usb_disable_stall_handshake();
00290       Usb_reset_endpoint(EP_MS_OUT);
00291       Usb_reset_data_toggle();
00292    }
00293 }
00294 
00295    
00303 Bool usb_user_get_descriptor(U8 type, U8 string)
00304 {
00305    switch(type)
00306    {
00307       case DESCRIPTOR_STRING:
00308       switch (string)
00309       {
00310          case LANG_ID:
00311          data_to_transfer = sizeof (usb_user_language_id);
00312          pbuffer = &(usb_user_language_id.bLength);
00313          return TRUE;
00314          break;
00315         
00316          case MAN_INDEX:
00317          data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
00318          pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
00319          return TRUE;
00320          break;
00321         
00322          case PROD_INDEX:
00323          data_to_transfer = sizeof (usb_user_product_string_descriptor);
00324          pbuffer = &(usb_user_product_string_descriptor.bLength);
00325          return TRUE;
00326          break;
00327            
00328 #if (USB_DEVICE_SN_USE==ENABLE)              
00329          case SN_INDEX:
00330          data_to_transfer = sizeof (usb_user_serial_number);
00331          pbuffer = &(usb_user_serial_number.bLength);
00332 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00333          f_get_serial_string=TRUE;
00334          data_to_transfer += (SN_LENGTH*4);
00335 #endif
00336          return TRUE;
00337          break;
00338 #endif
00339       }
00340       break;
00341    }
00342    return FALSE;
00343 }
00344 
00345 
00348 void hid_get_report_descriptor(void)
00349 {
00350    U16 wLength;
00351    U8  nb_byte;
00352    bit zlp = FALSE;
00353    U16 wInterface;
00354 
00355    LSB(wInterface)=Usb_read_byte();
00356    MSB(wInterface)=Usb_read_byte();
00357 
00358    data_to_transfer = sizeof(usb_hid_report_descriptor_mouse);
00359    pbuffer = &(usb_hid_report_descriptor_mouse.report[0]);
00360 
00361    LSB(wLength) = Usb_read_byte();
00362    MSB(wLength) = Usb_read_byte();
00363    Usb_ack_receive_setup();
00364 
00365    if (wLength > data_to_transfer)
00366    {
00367       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00368       else { zlp = FALSE; }
00369    }
00370    else
00371    {
00372       data_to_transfer = (U8)wLength;           // send only requested number of data
00373    }
00374 
00375    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00376    {
00377       while(!Is_usb_read_control_enabled());
00378 
00379       nb_byte=0;
00380       while(data_to_transfer != 0)              // Send data until necessary
00381       {
00382          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00383          {
00384             break;
00385          }
00386 #ifndef __GNUC__
00387          Usb_write_byte(*pbuffer++);
00388 #else    // AVRGCC does not support point to PGM space
00389          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00390 #endif
00391          data_to_transfer --;
00392       }
00393       Usb_send_control_in();
00394    }
00395 
00396    if(Is_usb_receive_out())
00397    { 
00398       // abort from Host
00399       Usb_ack_receive_out();
00400       return;
00401    }
00402    if(zlp == TRUE)
00403    { 
00404       while(!Is_usb_read_control_enabled());
00405       Usb_send_control_in();
00406    }
00407 
00408    while(!Is_usb_receive_out());
00409    Usb_ack_receive_out();
00410 }
00411 
00412 
00415 void usb_hid_set_report_ouput (void)
00416 {
00417    Usb_ack_receive_setup();
00418    Usb_send_control_in();
00419 
00420    while(!Is_usb_receive_out());
00421    Usb_ack_receive_out();
00422    Usb_send_control_in();
00423 }
00424 
00425 
00431 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration )
00432 {
00433    U16 wInterface;
00434    
00435    // Get interface number to put in idle mode
00436    LSB(wInterface)=Usb_read_byte();
00437    MSB(wInterface)=Usb_read_byte();
00438    Usb_ack_receive_setup();
00439   
00440    g_u8_report_rate = u8_duration;
00441    
00442    Usb_send_control_in();
00443    while(!Is_usb_in_ready());
00444 }
00445 
00446 
00451 void usb_hid_get_idle (U8 u8_report_id)
00452 {
00453    U16 wLength;
00454    U16 wInterface;
00455 
00456    // Get interface number to put in idle mode
00457    LSB(wInterface)= Usb_read_byte();
00458    MSB(wInterface)= Usb_read_byte();
00459    LSB(wLength)   = Usb_read_byte();
00460    MSB(wLength)   = Usb_read_byte();
00461    Usb_ack_receive_setup();
00462    
00463    if( wLength != 0 )
00464    {
00465       Usb_write_byte(g_u8_report_rate);
00466       Usb_send_control_in();
00467    }
00468    
00469    while(!Is_usb_receive_out());
00470    Usb_ack_receive_out();
00471 }
00472 
00473 
00476 void hid_get_hid_descriptor(void)
00477 {
00478    U16 wLength;
00479    U8  nb_byte;
00480    bit zlp=FALSE;
00481    U16 wInterface;
00482 
00483    LSB(wInterface)=Usb_read_byte();
00484    MSB(wInterface)=Usb_read_byte();
00485 
00486    data_to_transfer = sizeof(usb_conf_desc.hid_mouse);
00487    pbuffer = &(usb_conf_desc.hid_mouse.bLength);
00488 
00489    LSB(wLength) = Usb_read_byte();
00490    MSB(wLength) = Usb_read_byte();
00491    Usb_ack_receive_setup();
00492 
00493    if (wLength > data_to_transfer)
00494    {
00495       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00496       else { zlp = FALSE; }                     // no need of zero length packet
00497    }
00498    else
00499    {
00500       data_to_transfer = (U8)wLength;           // send only requested number of data
00501    }
00502 
00503    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00504    {
00505       while(!Is_usb_read_control_enabled());
00506 
00507       nb_byte=0;
00508       while(data_to_transfer != 0)              // Send data until necessary
00509       {
00510          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00511          {
00512             break;
00513          }
00514 #ifndef __GNUC__
00515          Usb_write_byte(*pbuffer++);
00516 #else    // AVRGCC does not support point to PGM space
00517          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00518 #endif
00519          data_to_transfer --;
00520       }
00521       Usb_send_control_in();
00522    }
00523 
00524    if(Is_usb_receive_out())
00525    { 
00526       // abort from Host
00527       Usb_ack_receive_out();
00528       return;
00529    }
00530    if(zlp == TRUE)
00531    { 
00532       while(!Is_usb_read_control_enabled());
00533       Usb_send_control_in();
00534    }
00535 
00536    while(!Is_usb_receive_out());
00537    Usb_ack_receive_out();
00538 }
00539 

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