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

# usb_specific_request.c

Go to the documentation of this file.

    00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
    00016
    00017 /* Copyright (c) 2007, 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  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
    00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00034  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
    00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
    00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00042  */
    00043
    00044
    00045 //_____ I N C L U D E S ____________________________________________________
    00046
    00047 #include "config.h"
    00048 #include "conf_usb.h"
    00049 #include "lib_mcu/usb/usb_drv.h"
    00050 #include "usb_descriptors.h"
    00051 #include "modules/usb/device_chap9/usb_standard_request.h"
    00052 #include "usb_specific_request.h"
    00053 #if ((USB_DEVICE_SN_USE==ENABLE) && (USE_DEVICE_SN_UNIQUE==ENABLE))
    00054 #include "lib_mcu/flash/flash_drv.h"
    00055 #endif
    00056
    00057 //_____ D E F I N I T I O N ________________________________________________
    00058
    00059 #ifdef __GNUC__
    00060 extern PGM_VOID_P pbuffer;
    00061 #else
    00062 extern U8   code *pbuffer;
    00063 #endif
    00064 extern U8   data_to_transfer;
    00065 extern code S_usb_hid_report_descriptor usb_hid_report_descriptor;
    00066 U8 jump_bootloader=0;
    00067
    00068 U8 g_u8_report_rate=0;
    00069
    00070 //_____ D E C L A R A T I O N ______________________________________________
    00071
    00072 void hid_get_report_descriptor(void);
    00073 void usb_hid_set_report_ouput(void);
    00074 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration );
    00075 void usb_hid_get_idle (U8 u8_report_id);
    00076 void hid_get_hid_descriptor(void);
    00077 void usb_hid_set_report_feature(void);
    00078
    00079
    00088 Bool usb_user_read_request(U8 type, U8 request)
    00089 {
    00090    U8    wValue_msb;
    00091    U8    wValue_lsb;
    00092
    00093    // Read wValue
    00094    wValue_lsb = Usb_read_byte();
    00095    wValue_msb = Usb_read_byte();
    00096
    00097    //** Specific request from Class HID
    00098    if( USB_SETUP_GET_STAND_INTERFACE == type )
    00099    {
    00100       switch( request )
    00101       {
    00102          case SETUP_GET_DESCRIPTOR:
    00103          switch( wValue_msb ) // Descriptor ID
    00104          {
    00105             case DESCRIPTOR_HID:
    00106             hid_get_hid_descriptor();
    00107             return TRUE;
    00108             break;
    00109
    00110             case DESCRIPTOR_REPORT:
    00111             hid_get_report_descriptor();
    00112             return TRUE;
    00113
    00114             case DESCRIPTOR_PHYSICAL:
    00115             // TODO
    00116             break;
    00117          }
    00118          break;
    00119       }
    00120    }
    00121    if( USB_SETUP_SET_CLASS_INTER == type )
    00122    {
    00123       switch( request )
    00124       {
    00125          case SETUP_HID_SET_REPORT:
    00126          // The MSB wValue field specifies the Report Type
    00127          // The LSB wValue field specifies the Report ID
    00128          switch (wValue_msb)
    00129          {
    00130             case REPORT_TYPE_INPUT:
    00131             // TODO
    00132             break;
    00133
    00134             case REPORT_TYPE_OUTPUT:
    00135             usb_hid_set_report_ouput();
    00136             return TRUE;
    00137             break;
    00138
    00139             case REPORT_TYPE_FEATURE:
    00140             usb_hid_set_report_feature();
    00141             return TRUE;
    00142             break;
    00143          }
    00144          break;
    00145
    00146          case SETUP_HID_SET_IDLE:
    00147          usb_hid_set_idle(wValue_lsb,wValue_msb);
    00148          return TRUE;
    00149
    00150          case SETUP_HID_SET_PROTOCOL:
    00151          // TODO
    00152          break;
    00153       }
    00154    }
    00155    if( USB_SETUP_GET_CLASS_INTER == type )
    00156    {
    00157       switch( request )
    00158       {
    00159          case SETUP_HID_GET_REPORT:
    00160          // TODO
    00161          break;
    00162          case SETUP_HID_GET_IDLE:
    00163          usb_hid_get_idle(wValue_lsb);
    00164          return TRUE;
    00165          case SETUP_HID_GET_PROTOCOL:
    00166          // TODO
    00167          break;
    00168       }
    00169    }
    00170    return FALSE;  // No supported request
    00171 }
    00172
    00173
    00178 void usb_user_endpoint_init(U8 conf_nb)
    00179 {
    00180    usb_configure_endpoint( EP_HID_IN,   \
    00181                            TYPE_INTERRUPT,\
    00182                            DIRECTION_IN,  \
    00183                            SIZE_8,        \
    00184                            ONE_BANK,      \
    00185                            NYET_ENABLED);
    00186
    00187    usb_configure_endpoint( EP_HID_OUT,    \
    00188                            TYPE_INTERRUPT,\
    00189                            DIRECTION_OUT, \
    00190                            SIZE_8,        \
    00191                            ONE_BANK,      \
    00192                            NYET_ENABLED);
    00193 }
    00194
    00195
    00202 U8   usb_user_interface_get( U16 wInterface )
    00203 {
    00204    return 0;  // Only one alternate setting possible for all interface
    00205 }
    00206
    00207
    00213 void usb_user_interface_reset(U16 wInterface, U8 alternate_setting)
    00214 {
    00215    // default setting selected = reset data toggle
    00216    if( INTERFACE_NB == wInterface )
    00217    {
    00218       // Interface HID
    00219       Usb_select_endpoint(EP_HID_IN);
    00220       Usb_disable_stall_handshake();
    00221       Usb_reset_endpoint(EP_HID_IN);
    00222       Usb_reset_data_toggle();
    00223       Usb_select_endpoint(EP_HID_OUT);
    00224       Usb_disable_stall_handshake();
    00225       Usb_reset_endpoint(EP_HID_OUT);
    00226       Usb_reset_data_toggle();
    00227    }
    00228 }
    00229
    00230
    00238 Bool usb_user_get_descriptor(U8 type, U8 string)
    00239 {
    00240    switch(type)
    00241    {
    00242       case DESCRIPTOR_STRING:
    00243       switch (string)
    00244       {
    00245          case LANG_ID:
    00246          data_to_transfer = sizeof (usb_user_language_id);
    00247          pbuffer = &(usb_user_language_id.bLength);
    00248          return TRUE;
    00249          break;
    00250
    00251          case MAN_INDEX:
    00252          data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
    00253          pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
    00254          return TRUE;
    00255          break;
    00256
    00257          case PROD_INDEX:
    00258          data_to_transfer = sizeof (usb_user_product_string_descriptor);
    00259          pbuffer = &(usb_user_product_string_descriptor.bLength);
    00260          return TRUE;
    00261          break;
    00262
    00263 #if (USB_DEVICE_SN_USE==ENABLE)
    00264          case SN_INDEX:
    00265          data_to_transfer = sizeof (usb_user_serial_number);
    00266          pbuffer = &(usb_user_serial_number.bLength);
    00267 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
    00268          f_get_serial_string=TRUE;
    00269          data_to_transfer += (SN_LENGTH*4);
    00270 #endif
    00271          return TRUE;
    00272          break;
    00273 #endif
    00274       }
    00275       break;
    00276    }
    00277    return FALSE;
    00278 }
    00279
    00280
    00283 void hid_get_report_descriptor(void)
    00284 {
    00285    U16 wLength;
    00286    U8  nb_byte;
    00287    bit zlp = FALSE;
    00288    U16 wInterface;
    00289
    00290    LSB(wInterface)=Usb_read_byte();
    00291    MSB(wInterface)=Usb_read_byte();
    00292
    00293    data_to_transfer = sizeof(usb_hid_report_descriptor);
    00294    pbuffer = &(usb_hid_report_descriptor.report[0]);
    00295
    00296    LSB(wLength) = Usb_read_byte();
    00297    MSB(wLength) = Usb_read_byte();
    00298    Usb_ack_receive_setup();
    00299
    00300    if (wLength > data_to_transfer)
    00301    {
    00302       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
    00303       else { zlp = FALSE; }
    00304    }
    00305    else
    00306    {
    00307       data_to_transfer = (U8)wLength;           // send only requested number of data
    00308    }
    00309
    00310    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
    00311    {
    00312       while(!Is_usb_read_control_enabled());
    00313
    00314       nb_byte=0;
    00315       while(data_to_transfer != 0)              // Send data until necessary
    00316       {
    00317          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
    00318          {
    00319             break;
    00320          }
    00321 #ifndef __GNUC__
    00322          Usb_write_byte(*pbuffer++);
    00323 #else    // AVRGCC does not support point to PGM space
    00324 //warning with AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
    00325          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
    00326 #endif
    00327          data_to_transfer --;
    00328       }
    00329       Usb_send_control_in();
    00330    }
    00331
    00332    if(Is_usb_receive_out())
    00333    {
    00334       // abort from Host
    00335       Usb_ack_receive_out();
    00336       return;
    00337    }
    00338    if(zlp == TRUE)
    00339    {
    00340       while(!Is_usb_read_control_enabled());
    00341       Usb_send_control_in();
    00342    }
    00343
    00344    while(!Is_usb_receive_out());
    00345    Usb_ack_receive_out();
    00346 }
    00347
    00348
    00351 void usb_hid_set_report_ouput (void)
    00352 {
    00353    Usb_ack_receive_setup();
    00354    Usb_send_control_in();
    00355
    00356    while(!Is_usb_receive_out());
    00357    Usb_ack_receive_out();
    00358    Usb_send_control_in();
    00359 }
    00360
    00361
    00367 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration )
    00368 {
    00369    U16 wInterface;
    00370
    00371    // Get interface number to put in idle mode
    00372    LSB(wInterface)=Usb_read_byte();
    00373    MSB(wInterface)=Usb_read_byte();
    00374    Usb_ack_receive_setup();
    00375
    00376    g_u8_report_rate = u8_duration;
    00377
    00378    Usb_send_control_in();
    00379    while(!Is_usb_in_ready());
    00380 }
    00381
    00382
    00387 void usb_hid_get_idle (U8 u8_report_id)
    00388 {
    00389    U16 wLength;
    00390    U16 wInterface;
    00391
    00392    // Get interface number to put in idle mode
    00393    LSB(wInterface)= Usb_read_byte();
    00394    MSB(wInterface)= Usb_read_byte();
    00395    LSB(wLength)   = Usb_read_byte();
    00396    MSB(wLength)   = Usb_read_byte();
    00397    Usb_ack_receive_setup();
    00398
    00399    if( wLength != 0 )
    00400    {
    00401       Usb_write_byte(g_u8_report_rate);
    00402       Usb_send_control_in();
    00403    }
    00404
    00405    while(!Is_usb_receive_out());
    00406    Usb_ack_receive_out();
    00407 }
    00408
    00409 void usb_hid_set_report_feature(void)
    00410 {
    00411
    00412    Usb_ack_receive_setup();
    00413    Usb_send_control_in();
    00414
    00415    while(!Is_usb_receive_out());
    00416
    00417    if(Usb_read_byte()==0x55)
    00418       if(Usb_read_byte()==0xAA)
    00419          if(Usb_read_byte()==0x55)
    00420             if(Usb_read_byte()==0xAA)
    00421             {
    00422                jump_bootloader=1;
    00423             }
    00424    Usb_ack_receive_out();
    00425    Usb_send_control_in();
    00426    while(!Is_usb_in_ready());
    00427 }
    00428
    00431 void hid_get_hid_descriptor(void)
    00432 {
    00433    U16 wLength;
    00434    U8  nb_byte;
    00435    bit zlp=FALSE;
    00436    U16 wInterface;
    00437
    00438    LSB(wInterface)=Usb_read_byte();
    00439    MSB(wInterface)=Usb_read_byte();
    00440
    00441    data_to_transfer = sizeof(usb_conf_desc.hid);
    00442    pbuffer = &(usb_conf_desc.hid.bLength);
    00443
    00444    LSB(wLength) = Usb_read_byte();
    00445    MSB(wLength) = Usb_read_byte();
    00446    Usb_ack_receive_setup();
    00447
    00448    if (wLength > data_to_transfer)
    00449    {
    00450       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
    00451       else { zlp = FALSE; }                     // no need of zero length packet
    00452    }
    00453    else
    00454    {
    00455       data_to_transfer = (U8)wLength;           // send only requested number of data
    00456    }
    00457
    00458    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
    00459    {
    00460       while(!Is_usb_read_control_enabled());
    00461
    00462       nb_byte=0;
    00463       while(data_to_transfer != 0)              // Send data until necessary
    00464       {
    00465          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
    00466          {
    00467             break;
    00468          }
    00469 #ifndef __GNUC__
    00470          Usb_write_byte(*pbuffer++);
    00471 #else    // AVRGCC does not support point to PGM space
    00472 //warning with AVRGCC assumes devices descriptors are stored in the lower 64Kbytes of on-chip flash memory
    00473          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
    00474 #endif
    00475          data_to_transfer --;
    00476       }
    00477       Usb_send_control_in();
    00478    }
    00479
    00480    if(Is_usb_receive_out())
    00481    {
    00482       // abort from Host
    00483       Usb_ack_receive_out();
    00484       return;
    00485    }
    00486    if(zlp == TRUE)
    00487    {
    00488       while(!Is_usb_read_control_enabled());
    00489       Usb_send_control_in();
    00490    }
    00491
    00492    while(!Is_usb_receive_out());
    00493    Usb_ack_receive_out();
    00494 }
    00495