ATMEL: usb_specific_request.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# 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