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 usb_hid_report_descriptor;
00069 U8 jump_bootloader=0;
00070 
00071 U8 g_u8_report_rate=0;
00072 
00073 //_____ D E C L A R A T I O N ______________________________________________
00074 
00075 void hid_get_report_descriptor(void);
00076 void usb_hid_set_report_ouput(void);
00077 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration );
00078 void usb_hid_get_idle (U8 u8_report_id);
00079 void hid_get_hid_descriptor(void);
00080 void usb_hid_set_report_feature(void);
00081 
00082 
00091 Bool usb_user_read_request(U8 type, U8 request)
00092 {
00093    U8    wValue_msb;
00094    U8    wValue_lsb;
00095 
00096    // Read wValue
00097    wValue_lsb = Usb_read_byte();
00098    wValue_msb = Usb_read_byte();
00099 
00100    //** Specific request from Class HID
00101    if( USB_SETUP_GET_STAND_INTERFACE == type )
00102    {
00103       switch( request )
00104       {
00105          case SETUP_GET_DESCRIPTOR:
00106          switch( wValue_msb ) // Descriptor ID
00107          {
00108             case DESCRIPTOR_HID:
00109             hid_get_hid_descriptor();
00110             return TRUE;
00111             break;
00112    
00113             case DESCRIPTOR_REPORT:
00114             hid_get_report_descriptor();
00115             return TRUE;
00116    
00117             case DESCRIPTOR_PHYSICAL:
00118             // TODO
00119             break;
00120          }
00121          break;
00122       }
00123    }
00124    if( USB_SETUP_SET_CLASS_INTER == type )
00125    {
00126       switch( request )
00127       {
00128          case SETUP_HID_SET_REPORT:
00129          // The MSB wValue field specifies the Report Type
00130          // The LSB wValue field specifies the Report ID
00131          switch (wValue_msb)
00132          {
00133             case REPORT_TYPE_INPUT:
00134             // TODO
00135             break;
00136             
00137             case REPORT_TYPE_OUTPUT:
00138             usb_hid_set_report_ouput();
00139             return TRUE;
00140             break;
00141 
00142             case REPORT_TYPE_FEATURE:
00143             usb_hid_set_report_feature();
00144             return TRUE;
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    return FALSE;  // No supported request
00174 }
00175 
00176 
00181 void usb_user_endpoint_init(U8 conf_nb)
00182 {
00183    usb_configure_endpoint( EP_HID_IN,   \
00184                            TYPE_INTERRUPT,\
00185                            DIRECTION_IN,  \
00186                            SIZE_8,        \
00187                            ONE_BANK,      \
00188                            NYET_ENABLED);
00189 
00190    usb_configure_endpoint( EP_HID_OUT,    \
00191                            TYPE_INTERRUPT,\
00192                            DIRECTION_OUT, \
00193                            SIZE_8,        \
00194                            ONE_BANK,      \
00195                            NYET_ENABLED);
00196 }
00197 
00198 
00205 U8   usb_user_interface_get( U16 wInterface )
00206 {
00207    return 0;  // Only one alternate setting possible for all interface
00208 }
00209 
00210 
00216 void usb_user_interface_reset(U16 wInterface, U8 alternate_setting)
00217 {  
00218    // default setting selected = reset data toggle
00219    if( INTERFACE_NB == wInterface )
00220    {
00221       // Interface HID
00222       Usb_select_endpoint(EP_HID_IN);
00223       Usb_disable_stall_handshake();
00224       Usb_reset_endpoint(EP_HID_IN);
00225       Usb_reset_data_toggle();
00226       Usb_select_endpoint(EP_HID_OUT);
00227       Usb_disable_stall_handshake();
00228       Usb_reset_endpoint(EP_HID_OUT);
00229       Usb_reset_data_toggle();
00230    }
00231 }
00232 
00233    
00241 Bool usb_user_get_descriptor(U8 type, U8 string)
00242 {
00243    switch(type)
00244    {
00245       case DESCRIPTOR_STRING:
00246       switch (string)
00247       {
00248          case LANG_ID:
00249          data_to_transfer = sizeof (usb_user_language_id);
00250          pbuffer = &(usb_user_language_id.bLength);
00251          return TRUE;
00252          break;
00253         
00254          case MAN_INDEX:
00255          data_to_transfer = sizeof (usb_user_manufacturer_string_descriptor);
00256          pbuffer = &(usb_user_manufacturer_string_descriptor.bLength);
00257          return TRUE;
00258          break;
00259         
00260          case PROD_INDEX:
00261          data_to_transfer = sizeof (usb_user_product_string_descriptor);
00262          pbuffer = &(usb_user_product_string_descriptor.bLength);
00263          return TRUE;
00264          break;
00265            
00266 #if (USB_DEVICE_SN_USE==ENABLE)              
00267          case SN_INDEX:
00268          data_to_transfer = sizeof (usb_user_serial_number);
00269          pbuffer = &(usb_user_serial_number.bLength);
00270 #if (USE_DEVICE_SN_UNIQUE==ENABLE)
00271          f_get_serial_string=TRUE;
00272          data_to_transfer += (SN_LENGTH*4);
00273 #endif
00274          return TRUE;
00275          break;
00276 #endif
00277       }
00278       break;
00279    }
00280    return FALSE;
00281 }
00282 
00283 
00286 void hid_get_report_descriptor(void)
00287 {
00288    U16 wLength;
00289    U8  nb_byte;
00290    bit zlp = FALSE;
00291    U16 wInterface;
00292 
00293    LSB(wInterface)=Usb_read_byte();
00294    MSB(wInterface)=Usb_read_byte();
00295 
00296    data_to_transfer = sizeof(usb_hid_report_descriptor);
00297    pbuffer = &(usb_hid_report_descriptor.report[0]);
00298 
00299    LSB(wLength) = Usb_read_byte();
00300    MSB(wLength) = Usb_read_byte();
00301    Usb_ack_receive_setup();
00302 
00303    if (wLength > data_to_transfer)
00304    {
00305       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00306       else { zlp = FALSE; }
00307    }
00308    else
00309    {
00310       data_to_transfer = (U8)wLength;           // send only requested number of data
00311    }
00312 
00313    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00314    {
00315       while(!Is_usb_read_control_enabled());
00316 
00317       nb_byte=0;
00318       while(data_to_transfer != 0)              // Send data until necessary
00319       {
00320          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00321          {
00322             break;
00323          }
00324 #ifndef __GNUC__
00325          Usb_write_byte(*pbuffer++);
00326 #else    // AVRGCC does not support point to PGM space
00327          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00328 #endif
00329          data_to_transfer --;
00330       }
00331       Usb_send_control_in();
00332    }
00333 
00334    if(Is_usb_receive_out())
00335    { 
00336       // abort from Host
00337       Usb_ack_receive_out();
00338       return;
00339    }
00340    if(zlp == TRUE)
00341    { 
00342       while(!Is_usb_read_control_enabled());
00343       Usb_send_control_in();
00344    }
00345 
00346    while(!Is_usb_receive_out());
00347    Usb_ack_receive_out();
00348 }
00349 
00350 
00353 void usb_hid_set_report_ouput (void)
00354 {
00355    Usb_ack_receive_setup();
00356    Usb_send_control_in();
00357 
00358    while(!Is_usb_receive_out());
00359    Usb_ack_receive_out();
00360    Usb_send_control_in();
00361 }
00362 
00363 
00369 void usb_hid_set_idle (U8 u8_report_id, U8 u8_duration )
00370 {
00371    U16 wInterface;
00372    
00373    // Get interface number to put in idle mode
00374    LSB(wInterface)=Usb_read_byte();
00375    MSB(wInterface)=Usb_read_byte();
00376    Usb_ack_receive_setup();
00377   
00378    g_u8_report_rate = u8_duration;
00379    
00380    Usb_send_control_in();
00381    while(!Is_usb_in_ready());
00382 }
00383 
00384 
00389 void usb_hid_get_idle (U8 u8_report_id)
00390 {
00391    U16 wLength;
00392    U16 wInterface;
00393 
00394    // Get interface number to put in idle mode
00395    LSB(wInterface)= Usb_read_byte();
00396    MSB(wInterface)= Usb_read_byte();
00397    LSB(wLength)   = Usb_read_byte();
00398    MSB(wLength)   = Usb_read_byte();
00399    Usb_ack_receive_setup();
00400    
00401    if( wLength != 0 )
00402    {
00403       Usb_write_byte(g_u8_report_rate);
00404       Usb_send_control_in();
00405    }
00406    
00407    while(!Is_usb_receive_out());
00408    Usb_ack_receive_out();
00409 }
00410 
00411 void usb_hid_set_report_feature(void)
00412 {
00413 
00414    Usb_ack_receive_setup();
00415    Usb_send_control_in();
00416 
00417    while(!Is_usb_receive_out());
00418 
00419    if(Usb_read_byte()==0x55)
00420       if(Usb_read_byte()==0xAA)
00421          if(Usb_read_byte()==0x55)
00422             if(Usb_read_byte()==0xAA)
00423             {
00424                jump_bootloader=1;
00425             }
00426    Usb_ack_receive_out();
00427    Usb_send_control_in();
00428    while(!Is_usb_in_ready());
00429 }
00430 
00433 void hid_get_hid_descriptor(void)
00434 {
00435    U16 wLength;
00436    U8  nb_byte;
00437    bit zlp=FALSE;
00438    U16 wInterface;
00439 
00440    LSB(wInterface)=Usb_read_byte();
00441    MSB(wInterface)=Usb_read_byte();
00442 
00443    data_to_transfer = sizeof(usb_conf_desc.hid);
00444    pbuffer = &(usb_conf_desc.hid.bLength);
00445 
00446    LSB(wLength) = Usb_read_byte();
00447    MSB(wLength) = Usb_read_byte();
00448    Usb_ack_receive_setup();
00449 
00450    if (wLength > data_to_transfer)
00451    {
00452       if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
00453       else { zlp = FALSE; }                     // no need of zero length packet
00454    }
00455    else
00456    {
00457       data_to_transfer = (U8)wLength;           // send only requested number of data
00458    }
00459 
00460    while((data_to_transfer != 0) && (!Is_usb_receive_out()))
00461    {
00462       while(!Is_usb_read_control_enabled());
00463 
00464       nb_byte=0;
00465       while(data_to_transfer != 0)              // Send data until necessary
00466       {
00467          if(nb_byte++==EP_CONTROL_LENGTH)       // Check endpoint 0 size
00468          {
00469             break;
00470          }
00471 #ifndef __GNUC__
00472          Usb_write_byte(*pbuffer++);
00473 #else    // AVRGCC does not support point to PGM space
00474          Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
00475 #endif
00476          data_to_transfer --;
00477       }
00478       Usb_send_control_in();
00479    }
00480 
00481    if(Is_usb_receive_out())
00482    { 
00483       // abort from Host
00484       Usb_ack_receive_out();
00485       return;
00486    }
00487    if(zlp == TRUE)
00488    { 
00489       while(!Is_usb_read_control_enabled());
00490       Usb_send_control_in();
00491    }
00492 
00493    while(!Is_usb_receive_out());
00494    Usb_ack_receive_out();
00495 }
00496 

Generated on Fri Sep 11 14:27:17 2009 for ATMEL by  doxygen 1.5.3