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

- File List
- Globals

# 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