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 extern code S_usb_hid_report_descriptor usb_hid_report_descriptor;
00073 U8 jump_bootloader=0;
00074 
00075 U8 g_u8_report_rate=0;
00076 
00077 //_____ D E C L A R A T I O N ______________________________________________
00078 
00079 void hid_get_report_descriptor(void);
00080 void usb_hid_set_report_ouput(void);
00081 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration );
00082 void usb_hid_get_idle (U8 u8_report_id);
00083 void hid_get_hid_descriptor(void);
00084 void usb_hid_set_report_feature(void);
00085 
00086 
00095 Bool usb_user_read_request(U8 type, U8 request)
00096 {
00097    U16   wInterface;
00098    U8    wValue_msb;
00099    U8    wValue_lsb;
00100 
00101    // Read wValue
00102    wValue_lsb = Usb_read_byte();
00103    wValue_msb = Usb_read_byte();
00104 
00105    //** Specific request from Class HID
00106    if( USB_SETUP_GET_STAND_INTERFACE == type )
00107    {
00108       switch( request )
00109       {
00110          case SETUP_GET_DESCRIPTOR:
00111          switch( wValue_msb ) // Descriptor ID
00112          {
00113             case DESCRIPTOR_HID:
00114             hid_get_hid_descriptor();
00115             return TRUE;
00116             break;
00117    
00118             case DESCRIPTOR_REPORT:
00119             hid_get_report_descriptor();
00120             return TRUE;
00121    
00122             case DESCRIPTOR_PHYSICAL:
00123             // TODO
00124             break;
00125          }
00126          break;
00127       }
00128    }
00129    if( USB_SETUP_SET_CLASS_INTER == type )
00130    {
00131       switch( request )
00132       {
00133          case SETUP_HID_SET_REPORT:
00134          // The MSB wValue field specifies the Report Type
00135          // The LSB wValue field specifies the Report ID
00136          switch (wValue_msb)
00137          {
00138             case REPORT_TYPE_INPUT:
00139             // TODO
00140             break;
00141             
00142             case REPORT_TYPE_OUTPUT:
00143             usb_hid_set_report_ouput();
00144             return TRUE;
00145             break;
00146 
00147             case REPORT_TYPE_FEATURE:
00148             usb_hid_set_report_feature();
00149             return TRUE;
00150             break;
00151          }
00152          break;
00153 
00154          case SETUP_HID_SET_IDLE:
00155          usb_hid_set_idle(wValue_lsb,wValue_msb);
00156          return TRUE;
00157    
00158          case SETUP_HID_SET_PROTOCOL:
00159          // TODO
00160          break;
00161       }
00162    }
00163    if( USB_SETUP_GET_CLASS_INTER == type )
00164    {
00165       switch( request )
00166       {
00167          case SETUP_HID_GET_REPORT:
00168          // TODO
00169          break;
00170          case SETUP_HID_GET_IDLE:
00171          usb_hid_get_idle(wValue_lsb);
00172          return TRUE;
00173          case SETUP_HID_GET_PROTOCOL:
00174          // TODO
00175          break;
00176       }
00177    }
00178  
00179    //** Specific request from Class MassStorage
00180    if( USB_SETUP_SET_CLASS_INTER == type )
00181    {
00182       switch( request )
00183       {
00184          case SETUP_MASS_STORAGE_RESET:
00185          // wValue must be 0
00186          // wIndex = Interface
00187          if( (0!=wValue_lsb) || (0!=wValue_msb) )
00188             break;
00189          LSB(wInterface)=Usb_read_byte();
00190          MSB(wInterface)=Usb_read_byte();
00191          if( INTERFACE_NB != wInterface )
00192             break;
00193          Usb_ack_receive_setup();
00194          Usb_send_control_in();
00195          while(!Is_usb_in_ready());
00196          return TRUE;
00197          break;
00198       }
00199    }
00200    if( USB_SETUP_GET_CLASS_INTER == type )
00201    {
00202       switch( request )
00203       {
00204          case SETUP_MASS_STORAGE_GET_MAX_LUN:
00205          // wValue must be 0
00206          // wIndex = Interface
00207          if( (0!=wValue_lsb) || (0!=wValue_msb) )
00208             break;
00209          LSB(wInterface)=Usb_read_byte();
00210          MSB(wInterface)=Usb_read_byte();
00211          if( INTERFACE_NB != wInterface )
00212             break;
00213          Usb_ack_receive_setup();
00214          Usb_write_byte( (get_nb_lun()-1) );
00215          Usb_send_control_in();
00216          while(!Is_usb_in_ready());
00217          while( !Is_usb_receive_out() );
00218          Usb_ack_receive_out();
00219          ms_multiple_drive = 1;
00220          return TRUE;
00221          break;
00222       }
00223    }
00224    
00225    return FALSE;  // No supported request
00226 }
00227 
00228 
00233 void usb_user_endpoint_init(U8 conf_nb)
00234 {
00235    usb_configure_endpoint( EP_MOUSE_IN,   \
00236                            TYPE_INTERRUPT,\
00237                            DIRECTION_IN,  \
00238                            SIZE_8,        \
00239                            ONE_BANK,      \
00240                            NYET_ENABLED);
00241 
00242    usb_configure_endpoint( EP_MS_IN,      \
00243                            TYPE_BULK,     \
00244                            DIRECTION_IN,  \
00245                            SIZE_64,       \
00246                            TWO_BANKS,     \
00247                            NYET_ENABLED);
00248 
00249    usb_configure_endpoint( EP_MS_OUT,     \
00250                            TYPE_BULK,     \
00251                            DIRECTION_OUT, \
00252                            SIZE_64,       \
00253                            TWO_BANKS,     \
00254                            NYET_ENABLED);
00255 
00256    usb_configure_endpoint( EP_HID_IN,     \
00257                            TYPE_INTERRUPT,\
00258                            DIRECTION_IN,  \
00259                            SIZE_8,        \
00260                            ONE_BANK,      \
00261                            NYET_ENABLED);
00262 
00263    usb_configure_endpoint( EP_HID_OUT,    \
00264                            TYPE_INTERRUPT,\
00265                            DIRECTION_OUT, \
00266                            SIZE_8,        \
00267                            ONE_BANK,      \
00268                            NYET_ENABLED);
00269 }
00270 
00271 
00278 U8   usb_user_interface_get( U16 wInterface )
00279 {
00280    return 0;  // Only one alternate setting possible for all interface
00281 }
00282 
00283 
00289 void usb_user_interface_reset(U16 wInterface, U8 alternate_setting)
00290 {  
00291    // default setting selected = reset data toggle
00292    if( INTERFACE_NB_MOUSE == wInterface )
00293    {
00294       // Interface mouse
00295       Usb_select_endpoint(EP_MOUSE_IN);
00296       Usb_disable_stall_handshake();
00297       Usb_reset_endpoint(EP_MOUSE_IN);
00298       Usb_reset_data_toggle();
00299    }
00300    if( INTERFACE_NB == wInterface )
00301    {
00302       // Interface Mass Storage
00303       Usb_select_endpoint(EP_MS_IN);
00304       Usb_disable_stall_handshake();
00305       Usb_reset_endpoint(EP_MS_IN);
00306       Usb_reset_data_toggle();
00307       Usb_select_endpoint(EP_MS_OUT);
00308       Usb_disable_stall_handshake();
00309       Usb_reset_endpoint(EP_MS_OUT);
00310       Usb_reset_data_toggle();
00311    }
00312    if( INTERFACE_NB_HID == wInterface )
00313    {
00314       // Interface Mass Storage
00315       Usb_select_endpoint(EP_HID_IN);
00316       Usb_disable_stall_handshake();
00317       Usb_reset_endpoint(EP_HID_IN);
00318       Usb_reset_data_toggle();
00319       Usb_select_endpoint(EP_HID_OUT);
00320       Usb_disable_stall_handshake();
00321       Usb_reset_endpoint(EP_HID_OUT);
00322       Usb_reset_data_toggle();
00323    }
00324 }
00325 
00326    
00334 Bool usb_user_get_descriptor(U8 type, U8 string)
00335 {
00336    switch(type)
00337    {
00338       case DESCRIPTOR_STRING:
00339       switch (string)
00340       {
00341          case LANG_ID:
00342          data_to_transfer = sizeof (usb_user_language_id);
00343          pbuffer = &(usb_user_language_id.bLength);
00344          return TRUE;
00345          break;
00346         
00347          case MAN_INDEX:
00348          data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
00349          pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
00350          return TRUE;
00351          break;
00352         
00353          case PROD_INDEX:
00354          data_to_transfer = sizeof (usb_user_product_string_descriptor);
00355          pbuffer = &(usb_user_product_string_descriptor.bLength);
00356          return TRUE;
00357          break;
00358            
00359 #if (USB_DEVICE_SN_USE==ENABLE)              
00360          case SN_INDEX:
00361          data_to_transfer = sizeof (usb_user_serial_number);
00362          pbuffer = &(usb_user_serial_number.bLength);
00363 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00364          f_get_serial_string=TRUE;
00365          data_to_transfer += (SN_LENGTH*4);
00366 #endif
00367          return TRUE;
00368          break;
00369 #endif
00370       }
00371       break;
00372    }
00373    return FALSE;
00374 }
00375 
00376 
00379 void hid_get_report_descriptor(void)
00380 {
00381    U16 wLength;
00382    U8  nb_byte;
00383    bit zlp = FALSE;
00384    U16 wInterface;
00385 
00386    LSB(wInterface)=Usb_read_byte();
00387    MSB(wInterface)=Usb_read_byte();
00388 
00389    if(wInterface==INTERFACE_NB_MOUSE)
00390    {
00391       data_to_transfer = sizeof(usb_hid_report_descriptor_mouse);
00392       pbuffer = &(usb_hid_report_descriptor_mouse.report[0]);
00393    }
00394    else
00395    {
00396       data_to_transfer = sizeof(usb_hid_report_descriptor);
00397       pbuffer = &(usb_hid_report_descriptor.report[0]);
00398    }
00399 
00400    LSB(wLength) = Usb_read_byte();
00401    MSB(wLength) = Usb_read_byte();
00402    Usb_ack_receive_setup();
00403 
00404    if (wLength > data_to_transfer)
00405    {
00406       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00407       else { zlp = FALSE; }
00408    }
00409    else
00410    {
00411       data_to_transfer = (U8)wLength;           // send only requested number of data
00412    }
00413 
00414    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00415    {
00416       while(!Is_usb_read_control_enabled());
00417 
00418       nb_byte=0;
00419       while(data_to_transfer != 0)              // Send data until necessary
00420       {
00421          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00422          {
00423             break;
00424          }
00425 #ifndef __GNUC__
00426          Usb_write_byte(*pbuffer++);
00427 #else    // AVRGCC does not support point to PGM space
00428 //warning with AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
00429          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00430 #endif
00431          data_to_transfer --;
00432       }
00433       Usb_send_control_in();
00434    }
00435 
00436    if(Is_usb_receive_out())
00437    { 
00438       // abort from Host
00439       Usb_ack_receive_out();
00440       return;
00441    }
00442    if(zlp == TRUE)
00443    { 
00444       while(!Is_usb_read_control_enabled());
00445       Usb_send_control_in();
00446    }
00447 
00448    while(!Is_usb_receive_out());
00449    Usb_ack_receive_out();
00450 }
00451 
00452 
00455 void usb_hid_set_report_ouput (void)
00456 {
00457    Usb_ack_receive_setup();
00458    Usb_send_control_in();
00459 
00460    while(!Is_usb_receive_out());
00461    Usb_ack_receive_out();
00462    Usb_send_control_in();
00463 }
00464 
00465 
00471 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration )
00472 {
00473    U16 wInterface;
00474    
00475    // Get interface number to put in idle mode
00476    LSB(wInterface)=Usb_read_byte();
00477    MSB(wInterface)=Usb_read_byte();
00478    Usb_ack_receive_setup();
00479   
00480    g_u8_report_rate = u8_duration;
00481    
00482    Usb_send_control_in();
00483    while(!Is_usb_in_ready());
00484 }
00485 
00486 
00491 void usb_hid_get_idle (U8 u8_report_id)
00492 {
00493    U16 wLength;
00494    U16 wInterface;
00495 
00496    // Get interface number to put in idle mode
00497    LSB(wInterface)= Usb_read_byte();
00498    MSB(wInterface)= Usb_read_byte();
00499    LSB(wLength)   = Usb_read_byte();
00500    MSB(wLength)   = Usb_read_byte();
00501    Usb_ack_receive_setup();
00502    
00503    if( wLength != 0 )
00504    {
00505       Usb_write_byte(g_u8_report_rate);
00506       Usb_send_control_in();
00507    }
00508    
00509    while(!Is_usb_receive_out());
00510    Usb_ack_receive_out();
00511 }
00512 
00513 void usb_hid_set_report_feature(void)
00514 {
00515    Usb_ack_receive_setup();
00516    Usb_send_control_in();
00517 
00518    while(!Is_usb_receive_out());
00519 
00520    if(Usb_read_byte()==0x55)
00521       if(Usb_read_byte()==0xAA)
00522          if(Usb_read_byte()==0x55)
00523             if(Usb_read_byte()==0xAA)
00524             {
00525                jump_bootloader=1;
00526             }
00527    Usb_ack_receive_out();
00528    Usb_send_control_in();
00529    while(!Is_usb_in_ready());
00530 }
00531 
00534 void hid_get_hid_descriptor(void)
00535 {
00536    U16 wLength;
00537    U8  nb_byte;
00538    bit zlp=FALSE;
00539    U16 wInterface;
00540 
00541    LSB(wInterface)=Usb_read_byte();
00542    MSB(wInterface)=Usb_read_byte();
00543 
00544    if(wInterface==INTERFACE_NB_MOUSE)
00545    {
00546       data_to_transfer = sizeof(usb_conf_desc.hid_mouse);
00547       pbuffer = &(usb_conf_desc.hid_mouse.bLength);
00548    }
00549    else
00550    {
00551       data_to_transfer = sizeof(usb_conf_desc.hid);
00552       pbuffer = &(usb_conf_desc.hid.bLength);
00553    }
00554 
00555    LSB(wLength) = Usb_read_byte();
00556    MSB(wLength) = Usb_read_byte();
00557    Usb_ack_receive_setup();
00558 
00559    if (wLength > data_to_transfer)
00560    {
00561       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00562       else { zlp = FALSE; }                     // no need of zero length packet
00563    }
00564    else
00565    {
00566       data_to_transfer = (U8)wLength;           // send only requested number of data
00567    }
00568 
00569    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00570    {
00571       while(!Is_usb_read_control_enabled());
00572 
00573       nb_byte=0;
00574       while(data_to_transfer != 0)              // Send data until necessary
00575       {
00576          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00577          {
00578             break;
00579          }
00580 #ifndef __GNUC__
00581          Usb_write_byte(*pbuffer++);
00582 #else    // AVRGCC does not support point to PGM space
00583 //warning with AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
00584          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00585 #endif
00586          data_to_transfer --;
00587       }
00588       Usb_send_control_in();
00589    }
00590 
00591    if(Is_usb_receive_out())
00592    { 
00593       // abort from Host
00594       Usb_ack_receive_out();
00595       return;
00596    }
00597    if(zlp == TRUE)
00598    { 
00599       while(!Is_usb_read_control_enabled());
00600       Usb_send_control_in();
00601    }
00602 
00603    while(!Is_usb_receive_out());
00604    Usb_ack_receive_out();
00605 }
00606 

Generated on Wed Sep 23 09:49:34 2009 for ATMEL by  doxygen 1.5.3