Contiki 2.6

usb_specific_request.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00002 /*! \file *********************************************************************
00003  *
00004  * \brief
00005  *      USB Protocol-Specific Requests
00006  *
00007  * \addtogroup usbtask
00008  *
00009  * \author
00010  *      Colin O'Flynn <coflynn@newae.com>
00011  *
00012  ******************************************************************************/
00013 /* Copyright (c) 2008  Colin O'Flynn
00014    Copyright (c) Atmel Corporation 2008
00015    All rights reserved.
00016 
00017    Redistribution and use in source and binary forms, with or without
00018    modification, are permitted provided that the following conditions are met:
00019 
00020    * Redistributions of source code must retain the above copyright
00021      notice, this list of conditions and the following disclaimer.
00022    * Redistributions in binary form must reproduce the above copyright
00023      notice, this list of conditions and the following disclaimer in
00024      the documentation and/or other materials provided with the
00025      distribution.
00026    * Neither the name of the copyright holders nor the names of
00027      contributors may be used to endorse or promote products derived
00028      from this software without specific prior written permission.
00029 
00030   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00031   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00032   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00033   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00034   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00035   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00036   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00037   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00038   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00039   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00040   POSSIBILITY OF SUCH DAMAGE.
00041 */
00042 
00043 
00044 //_____ I N C L U D E S ____________________________________________________
00045 
00046 #include "radio.h"
00047 #include "contiki.h"
00048 #include "config.h"
00049 #include "usb_drv.h"
00050 #include "usb_descriptors.h"
00051 #include "usb_specific_request.h"
00052 #include "rndis/rndis_protocol.h"
00053 #include "rndis/cdc_ecm.h"
00054 #include "rndis/rndis_task.h"
00055 #include "serial/uart_usb_lib.h"
00056 #include "storage/ctrl_access.h"
00057 #include "uip.h"
00058 #include <avr/pgmspace.h>
00059 #include <avr/eeprom.h>
00060 #include <string.h>
00061 
00062 //_____ M A C R O S ________________________________________________________
00063 
00064 //_____ D E F I N I T I O N ________________________________________________
00065 #if USB_CONF_STORAGE
00066 bit  ms_multiple_drive;
00067 #endif
00068 //_____ P R I V A T E   D E C L A R A T I O N ______________________________
00069 
00070 extern PGM_VOID_P pbuffer;
00071 extern U8   data_to_transfer;
00072 
00073 //_____ D E C L A R A T I O N ______________________________________________
00074 
00075 
00076 
00077 //! This function is called by the standard usb read request function when
00078 //! the Usb request is not supported. This function returns TRUE when the
00079 //! request is processed. This function returns FALSE if the request is not
00080 //! supported. In this case, a STALL handshake will be automatically
00081 //! sent by the standard usb read request function.
00082 //!
00083 //! @param type Not used
00084 //! @param request Read request type
00085 //!
00086 //! @retval FALSE if unknown read type
00087 //! @retval TRUE if request type is processed
00088 //!
00089 Bool usb_user_read_request(U8 type, U8 request)
00090 {       
00091         U16 wLength;
00092 
00093         switch(request)
00094         {
00095                 case SEND_ENCAPSULATED_COMMAND:                 
00096                                 Usb_read_byte();
00097                                 Usb_read_byte();
00098                                 Usb_read_byte();//wIndex LSB
00099                                 Usb_read_byte();//wIndex MSB
00100 
00101                                 LSB(wLength) = Usb_read_byte();
00102                                 MSB(wLength) = Usb_read_byte();
00103                                 if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
00104                                         return rndis_send_encapsulated_command(wLength);
00105                                 else
00106                                         return FALSE;
00107                         break;
00108 
00109                 case GET_ENCAPSULATED_COMMAND:
00110                                 Usb_read_byte();
00111                                 Usb_read_byte();
00112                                 Usb_read_byte();//wIndex LSB
00113                                 Usb_read_byte();//wIndex MSB
00114 
00115                                 LSB(wLength) = Usb_read_byte();
00116                                 MSB(wLength) = Usb_read_byte();
00117                                 if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
00118                                         return rndis_get_encapsulated_command();
00119                                 else
00120                                         return FALSE;
00121                         break;
00122 
00123                 case SET_ETHERNET_PACKET_FILTER:
00124                                 if((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG)) {
00125                                         cdc_ecm_set_ethernet_packet_filter();
00126                                         return TRUE;
00127                                 } else
00128                                         return FALSE;
00129                                 break;
00130 
00131 #if USB_CONF_STORAGE
00132         case MASS_STORAGE_RESET:
00133                         Usb_ack_receive_setup();
00134                         Usb_send_control_in();
00135                         return TRUE;
00136                         break;
00137 
00138 
00139                 case GET_MAX_LUN:
00140                         Usb_ack_receive_setup();
00141                         Usb_write_byte( (get_nb_lun()-1) );
00142                         Usb_send_control_in();
00143                         ms_multiple_drive = 1;
00144                         return TRUE;
00145                         break;
00146 #endif /* USB_CONF_STORAGE */
00147 
00148 #if USB_CONF_SERIAL     
00149         /* We don't have a real serial port - so these aren't applicable. We
00150            advertise that we support nothing, so shouldn't get them anyway */
00151                 case GET_LINE_CODING:
00152                                 Usb_read_byte();
00153                                 Usb_read_byte();
00154                                 if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
00155                                         cdc_get_line_coding();
00156                                         return TRUE;
00157                                 } else {
00158                                         return FALSE;
00159                                 }
00160                         break;
00161 
00162                 case SET_LINE_CODING:
00163                                 Usb_read_byte();
00164                                 Usb_read_byte();
00165                                 if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
00166                                         cdc_set_line_coding();
00167                                         return TRUE;
00168                                 } else {
00169                                         return FALSE;
00170                                 }
00171                         break;
00172 
00173                 case SET_CONTROL_LINE_STATE:
00174                                 if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
00175                                         cdc_set_control_line_state();
00176                                         return TRUE;
00177                                 } else {
00178                                         return FALSE;
00179                                 }
00180                         break;
00181 #endif /* USB_CONF_SERIAL */
00182         default:
00183                                 break;
00184 
00185         }
00186          
00187         return FALSE;
00188 }
00189 
00190 //! usb_user_get_descriptor.
00191 //!
00192 //! @brief This function returns the size and the pointer on a user information
00193 //! structure
00194 //!
00195 //! @param type descriptor type
00196 //! @param string descriptor ID
00197 //!
00198 //! @retval FALSE
00199 //!
00200 Bool usb_user_get_descriptor(U8 type, U8 string)
00201 { 
00202         switch(type)
00203         {
00204                 case STRING_DESCRIPTOR:
00205         switch (string)
00206         {
00207                         case LANG_ID:
00208                         data_to_transfer = sizeof (usb_user_language_id);
00209                         pbuffer = &(usb_user_language_id.bLength);
00210                                         return TRUE;
00211                         break;
00212                         default:
00213                         return FALSE;
00214                         }
00215                 default:
00216                         return FALSE;
00217         }
00218 
00219         return FALSE;
00220 }
00221 static char itoh(unsigned char i) {
00222         char ret;
00223         ret = pgm_read_byte_near(PSTR("0123456789abcdef")+(i&0xF));
00224         return ret;
00225 }
00226 const char* usb_user_get_string_sram(U8 string_type) {
00227         static char serial[13];
00228         uint8_t i;
00229         
00230         switch (string_type)
00231         {
00232                 case USB_STRING_SERIAL:
00233                 case USB_STRING_MAC_ADDRESS:
00234                         {
00235                                 uint8_t mac_address[6];
00236                                 usb_eth_get_mac_address(mac_address);
00237                                 
00238                                 for(i=0;i<6;i++) {
00239                                         serial[i*2] = itoh(mac_address[i]>>4);
00240                                         serial[i*2+1] = itoh(mac_address[i]);
00241                                 }
00242                         }
00243                         break;
00244                 default:
00245                         serial[0] = 0;
00246                         break;
00247         }
00248         
00249         return serial;
00250 }
00251 
00252 PGM_P usb_user_get_string(U8 string_type) {
00253         switch (string_type)
00254         {
00255                 case USB_STRING_MAN:
00256                         return PSTR("Atmel");
00257 
00258                 case USB_STRING_PRODUCT:
00259                         return PSTR("Jackdaw 6LoWPAN Adaptor");
00260 
00261                 case USB_STRING_CONFIG_COMPOSITE:
00262                         return PSTR("RNDIS+Debug");
00263 
00264                 case USB_STRING_CONFIG_RNDIS:
00265                 case USB_STRING_INTERFACE_RNDIS:
00266                         return PSTR("RNDIS");
00267 
00268                 case USB_STRING_CONFIG_EEM:
00269                 case USB_STRING_INTERFACE_EEM:
00270                         return PSTR("CDC-EEM");
00271 
00272                 case USB_STRING_CONFIG_ECM:
00273                 case USB_STRING_INTERFACE_ECM:
00274                         return PSTR("CDC-ECM");
00275 
00276                 case USB_STRING_CONFIG_ECM_DEBUG:
00277                         return PSTR("CDC-ECM+DEBUG");
00278 
00279                 case USB_STRING_INTERFACE_SERIAL:
00280                         return PSTR("Debug Port");
00281 /*
00282                 case USB_STRING_INTERFACE_ECM_ATTACHED:
00283                         return PSTR("Attached");
00284                 case USB_STRING_INTERFACE_ECM_DETACHED:
00285                         return PSTR("Detached");
00286 */                      
00287 #if USB_CONF_STORAGE
00288                 case USB_STRING_CONFIG_MS:
00289                 case USB_STRING_INTERFACE_MS:
00290                         return PSTR("Mass Storage");
00291 #endif
00292 
00293 /*
00294                 // This is now handled by usb_user_get_string_sram.
00295                 case USB_STRING_SERIAL:
00296                         return PSTR("JD01");
00297 
00298                 case USB_STRING_MAC_ADDRESS:
00299                         return PSTR("021213141516");
00300 
00301 */
00302 
00303 
00304                 default:
00305                         return NULL;
00306         }
00307 }
00308 
00309 
00310 //! usb_user_endpoint_init.
00311 //!
00312 //! @brief This function configures the endpoints.
00313 //!
00314 //! @param conf_nb Not used
00315 void usb_user_endpoint_init(U8 conf_nb)
00316 {
00317         if(USB_CONFIG_HAS_DEBUG_PORT(conf_nb)) {
00318                 uart_usb_configure_endpoints();
00319         }
00320 
00321         switch(conf_nb) {
00322                 case USB_CONFIG_ECM:
00323                 case USB_CONFIG_ECM_DEBUG:
00324                         cdc_ecm_configure_endpoints();
00325                         break;
00326 
00327                 case USB_CONFIG_RNDIS_DEBUG:
00328                 case USB_CONFIG_RNDIS:
00329                         rndis_configure_endpoints();
00330                         break;  
00331                 case USB_CONFIG_EEM:
00332                         cdc_ecm_configure_endpoints();
00333 
00334                         break;
00335 #if USB_CONF_STORAGE
00336                 case USB_CONFIG_MS:
00337                         usb_configure_endpoint(VCP_INT_EP,      \
00338                                                                  TYPE_INTERRUPT,     \
00339                                                                  DIRECTION_IN,  \
00340                                                                  SIZE_32,       \
00341                                                                  ONE_BANK,     \
00342                                                                  NYET_ENABLED);
00343 
00344                         usb_configure_endpoint(VCP_TX_EP,      \
00345                                                                  TYPE_BULK,     \
00346                                                                  DIRECTION_IN,  \
00347                                                                  SIZE_32,       \
00348                                                                  TWO_BANKS,     \
00349                                                                  NYET_ENABLED);
00350 
00351                         usb_configure_endpoint(VCP_RX_EP,      \
00352                                                                  TYPE_BULK,     \
00353                                                                  DIRECTION_OUT,  \
00354                                                                  SIZE_32,       \
00355                                                                  TWO_BANKS,     \
00356                                                                  NYET_ENABLED);
00357                         Usb_reset_endpoint(VCP_INT_EP);
00358                         Usb_reset_endpoint(VCP_TX_EP);
00359                         Usb_reset_endpoint(VCP_RX_EP);
00360 
00361                         break;  
00362 #endif
00363         }
00364         Led0_on();
00365 }
00366 
00367 #if USB_CONF_SERIAL
00368 /******************** Virtual Serial Port ************************/
00369 
00370 extern S_line_coding   line_coding;
00371 
00372 //! cdc_get_line_coding.
00373 //!
00374 //! @brief This function manages reception of line coding parameters (baudrate...).
00375 //!
00376 void cdc_get_line_coding(void)
00377 {
00378         Usb_ack_receive_setup();
00379         Usb_write_byte(LSB0(line_coding.dwDTERate));
00380         Usb_write_byte(LSB1(line_coding.dwDTERate));
00381         Usb_write_byte(LSB2(line_coding.dwDTERate));
00382         Usb_write_byte(LSB3(line_coding.dwDTERate));
00383         Usb_write_byte(line_coding.bCharFormat);
00384         Usb_write_byte(line_coding.bParityType);
00385         Usb_write_byte(line_coding.bDataBits);
00386 
00387     Usb_send_control_in();
00388 }
00389 
00390 
00391 //! cdc_set_line_coding.
00392 //!
00393 //! @brief This function manages reception of line coding parameters (baudrate...).
00394 //!
00395 void cdc_set_line_coding (void)
00396 {
00397         Usb_ack_receive_setup();
00398         if(usb_endpoint_wait_for_receive_out()==0) {
00399                 LSB0(line_coding.dwDTERate) = Usb_read_byte();
00400                 LSB1(line_coding.dwDTERate) = Usb_read_byte();
00401                 LSB2(line_coding.dwDTERate) = Usb_read_byte();
00402                 LSB3(line_coding.dwDTERate) = Usb_read_byte();
00403                 line_coding.bCharFormat = Usb_read_byte();
00404                 line_coding.bParityType = Usb_read_byte();
00405                 line_coding.bDataBits = Usb_read_byte();
00406                 Usb_ack_receive_out();
00407 
00408                 Usb_send_control_in();                // send a ZLP for STATUS phase
00409                 usb_endpoint_wait_for_read_control_enabled();
00410         }
00411 }
00412 
00413 //! cdc_set_control_line_state.
00414 //!
00415 //! @brief This function manages the SET_CONTROL_LINE_LINE_STATE CDC request.
00416 //!
00417 //! Note: Can manage hardware flow control here...
00418 //!
00419 void cdc_set_control_line_state (void)
00420 {
00421         U8 controlLineState = Usb_read_byte();
00422 //      U8 dummy = Usb_read_byte();  //Compiler warning
00423     if (Usb_read_byte()) {};
00424         U8 interface = Usb_read_byte();
00425 
00426         Usb_ack_receive_setup();
00427         Usb_send_control_in();
00428         usb_endpoint_wait_for_read_control_enabled();
00429 
00430         if(interface == INTERFACE2_NB) {
00431                 uart_usb_set_control_line_state(controlLineState);              
00432         }
00433 }
00434 #endif /* USB_CONF_SERIAL */
00435 
00436 Bool  usb_user_set_alt_interface(U8 interface, U8 alt_setting) {
00437         return FALSE;
00438         if((interface==ECM_INTERFACE0_NB) && ((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG))) {
00439                 // The alt_setting in this case corresponds to
00440                 // if the interface is enabled or not.
00441                 usb_eth_set_active(alt_setting);
00442         }
00443         return TRUE;
00444 }
00445