Contiki 2.6
|
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