Contiki 2.5
usb_specific_request.c
Go to the documentation of this file.
1 /* This file has been prepared for Doxygen automatic documentation generation.*/
2 /*! \file *********************************************************************
3  *
4  * \brief
5  * USB Protocol-Specific Requests
6  *
7  * \addtogroup usbtask
8  *
9  * \author
10  * Colin O'Flynn <coflynn@newae.com>
11  *
12  ******************************************************************************/
13 /* Copyright (c) 2008 Colin O'Flynn
14  Copyright (c) Atmel Corporation 2008
15  All rights reserved.
16 
17  Redistribution and use in source and binary forms, with or without
18  modification, are permitted provided that the following conditions are met:
19 
20  * Redistributions of source code must retain the above copyright
21  notice, this list of conditions and the following disclaimer.
22  * Redistributions in binary form must reproduce the above copyright
23  notice, this list of conditions and the following disclaimer in
24  the documentation and/or other materials provided with the
25  distribution.
26  * Neither the name of the copyright holders nor the names of
27  contributors may be used to endorse or promote products derived
28  from this software without specific prior written permission.
29 
30  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  POSSIBILITY OF SUCH DAMAGE.
41 */
42 
43 
44 //_____ I N C L U D E S ____________________________________________________
45 
46 #include "radio.h"
47 #include "contiki.h"
48 #include "config.h"
49 #include "usb_drv.h"
50 #include "usb_descriptors.h"
51 #include "usb_specific_request.h"
52 #include "rndis/rndis_protocol.h"
53 #include "rndis/cdc_ecm.h"
54 #include "rndis/rndis_task.h"
55 #include "serial/uart_usb_lib.h"
56 #include "storage/ctrl_access.h"
57 #include "uip.h"
58 #include <avr/pgmspace.h>
59 #include <avr/eeprom.h>
60 #include <string.h>
61 
62 //_____ M A C R O S ________________________________________________________
63 
64 //_____ D E F I N I T I O N ________________________________________________
65 #if USB_CONF_STORAGE
66 bit ms_multiple_drive;
67 #endif
68 //_____ P R I V A T E D E C L A R A T I O N ______________________________
69 
70 extern PGM_VOID_P pbuffer;
71 extern U8 data_to_transfer;
72 
73 //_____ D E C L A R A T I O N ______________________________________________
74 
75 
76 
77 //! This function is called by the standard usb read request function when
78 //! the Usb request is not supported. This function returns TRUE when the
79 //! request is processed. This function returns FALSE if the request is not
80 //! supported. In this case, a STALL handshake will be automatically
81 //! sent by the standard usb read request function.
82 //!
83 //! @param type Not used
84 //! @param request Read request type
85 //!
86 //! @retval FALSE if unknown read type
87 //! @retval TRUE if request type is processed
88 //!
89 Bool usb_user_read_request(U8 type, U8 request)
90 {
91  U16 wLength;
92 
93  switch(request)
94  {
95  case SEND_ENCAPSULATED_COMMAND:
96  Usb_read_byte();
97  Usb_read_byte();
98  Usb_read_byte();//wIndex LSB
99  Usb_read_byte();//wIndex MSB
100 
101  LSB(wLength) = Usb_read_byte();
102  MSB(wLength) = Usb_read_byte();
103  if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
104  return rndis_send_encapsulated_command(wLength);
105  else
106  return FALSE;
107  break;
108 
109  case GET_ENCAPSULATED_COMMAND:
110  Usb_read_byte();
111  Usb_read_byte();
112  Usb_read_byte();//wIndex LSB
113  Usb_read_byte();//wIndex MSB
114 
115  LSB(wLength) = Usb_read_byte();
116  MSB(wLength) = Usb_read_byte();
117  if((usb_configuration_nb==USB_CONFIG_RNDIS)||(usb_configuration_nb==USB_CONFIG_RNDIS_DEBUG))
119  else
120  return FALSE;
121  break;
122 
123  case SET_ETHERNET_PACKET_FILTER:
124  if((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG)) {
125  cdc_ecm_set_ethernet_packet_filter();
126  return TRUE;
127  } else
128  return FALSE;
129  break;
130 
131 #if USB_CONF_STORAGE
132  case MASS_STORAGE_RESET:
135  return TRUE;
136  break;
137 
138 
139  case GET_MAX_LUN:
141  Usb_write_byte( (get_nb_lun()-1) );
143  ms_multiple_drive = 1;
144  return TRUE;
145  break;
146 #endif /* USB_CONF_STORAGE */
147 
148 #if USB_CONF_SERIAL
149  /* We don't have a real serial port - so these aren't applicable. We
150  advertise that we support nothing, so shouldn't get them anyway */
151  case GET_LINE_CODING:
152  Usb_read_byte();
153  Usb_read_byte();
154  if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
155  cdc_get_line_coding();
156  return TRUE;
157  } else {
158  return FALSE;
159  }
160  break;
161 
162  case SET_LINE_CODING:
163  Usb_read_byte();
164  Usb_read_byte();
165  if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
166  cdc_set_line_coding();
167  return TRUE;
168  } else {
169  return FALSE;
170  }
171  break;
172 
173  case SET_CONTROL_LINE_STATE:
174  if(USB_CONFIG_HAS_DEBUG_PORT(usb_configuration_nb)) {
175  cdc_set_control_line_state();
176  return TRUE;
177  } else {
178  return FALSE;
179  }
180  break;
181 #endif /* USB_CONF_SERIAL */
182  default:
183  break;
184 
185  }
186 
187  return FALSE;
188 }
189 
190 //! usb_user_get_descriptor.
191 //!
192 //! @brief This function returns the size and the pointer on a user information
193 //! structure
194 //!
195 //! @param type descriptor type
196 //! @param string descriptor ID
197 //!
198 //! @retval FALSE
199 //!
200 Bool usb_user_get_descriptor(U8 type, U8 string)
201 {
202  switch(type)
203  {
204  case STRING_DESCRIPTOR:
205  switch (string)
206  {
207  case LANG_ID:
208  data_to_transfer = sizeof (usb_user_language_id);
209  pbuffer = &(usb_user_language_id.bLength);
210  return TRUE;
211  break;
212  default:
213  return FALSE;
214  }
215  default:
216  return FALSE;
217  }
218 
219  return FALSE;
220 }
221 static char itoh(unsigned char i) {
222  char ret;
223  ret = pgm_read_byte_near(PSTR("0123456789abcdef")+(i&0xF));
224  return ret;
225 }
226 const char* usb_user_get_string_sram(U8 string_type) {
227  static char serial[13];
228  uint8_t i;
229 
230  switch (string_type)
231  {
232  case USB_STRING_SERIAL:
233  case USB_STRING_MAC_ADDRESS:
234  {
235  uint8_t mac_address[6];
236  usb_eth_get_mac_address(mac_address);
237 
238  for(i=0;i<6;i++) {
239  serial[i*2] = itoh(mac_address[i]>>4);
240  serial[i*2+1] = itoh(mac_address[i]);
241  }
242  }
243  break;
244  default:
245  serial[0] = 0;
246  break;
247  }
248 
249  return serial;
250 }
251 
252 PGM_P usb_user_get_string(U8 string_type) {
253  switch (string_type)
254  {
255  case USB_STRING_MAN:
256  return PSTR("Atmel");
257 
258  case USB_STRING_PRODUCT:
259  return PSTR("Jackdaw 6LoWPAN Adaptor");
260 
261  case USB_STRING_CONFIG_COMPOSITE:
262  return PSTR("RNDIS+Debug");
263 
264  case USB_STRING_CONFIG_RNDIS:
265  case USB_STRING_INTERFACE_RNDIS:
266  return PSTR("RNDIS");
267 
268  case USB_STRING_CONFIG_EEM:
269  case USB_STRING_INTERFACE_EEM:
270  return PSTR("CDC-EEM");
271 
272  case USB_STRING_CONFIG_ECM:
273  case USB_STRING_INTERFACE_ECM:
274  return PSTR("CDC-ECM");
275 
276  case USB_STRING_CONFIG_ECM_DEBUG:
277  return PSTR("CDC-ECM+DEBUG");
278 
279  case USB_STRING_INTERFACE_SERIAL:
280  return PSTR("Debug Port");
281 /*
282  case USB_STRING_INTERFACE_ECM_ATTACHED:
283  return PSTR("Attached");
284  case USB_STRING_INTERFACE_ECM_DETACHED:
285  return PSTR("Detached");
286 */
287 #if USB_CONF_STORAGE
288  case USB_STRING_CONFIG_MS:
289  case USB_STRING_INTERFACE_MS:
290  return PSTR("Mass Storage");
291 #endif
292 
293 /*
294  // This is now handled by usb_user_get_string_sram.
295  case USB_STRING_SERIAL:
296  return PSTR("JD01");
297 
298  case USB_STRING_MAC_ADDRESS:
299  return PSTR("021213141516");
300 
301 */
302 
303 
304  default:
305  return NULL;
306  }
307 }
308 
309 
310 //! usb_user_endpoint_init.
311 //!
312 //! @brief This function configures the endpoints.
313 //!
314 //! @param conf_nb Not used
315 void usb_user_endpoint_init(U8 conf_nb)
316 {
317  if(USB_CONFIG_HAS_DEBUG_PORT(conf_nb)) {
318  uart_usb_configure_endpoints();
319  }
320 
321  switch(conf_nb) {
322  case USB_CONFIG_ECM:
323  case USB_CONFIG_ECM_DEBUG:
324  cdc_ecm_configure_endpoints();
325  break;
326 
327  case USB_CONFIG_RNDIS_DEBUG:
328  case USB_CONFIG_RNDIS:
329  rndis_configure_endpoints();
330  break;
331  case USB_CONFIG_EEM:
332  cdc_ecm_configure_endpoints();
333 
334  break;
335 #if USB_CONF_STORAGE
336  case USB_CONFIG_MS:
337  usb_configure_endpoint(VCP_INT_EP, \
338  TYPE_INTERRUPT, \
339  DIRECTION_IN, \
340  SIZE_32, \
341  ONE_BANK, \
342  NYET_ENABLED);
343 
344  usb_configure_endpoint(VCP_TX_EP, \
345  TYPE_BULK, \
346  DIRECTION_IN, \
347  SIZE_32, \
348  TWO_BANKS, \
349  NYET_ENABLED);
350 
351  usb_configure_endpoint(VCP_RX_EP, \
352  TYPE_BULK, \
353  DIRECTION_OUT, \
354  SIZE_32, \
355  TWO_BANKS, \
356  NYET_ENABLED);
357  Usb_reset_endpoint(VCP_INT_EP);
358  Usb_reset_endpoint(VCP_TX_EP);
359  Usb_reset_endpoint(VCP_RX_EP);
360 
361  break;
362 #endif
363  }
364  Led0_on();
365 }
366 
367 #if USB_CONF_SERIAL
368 /******************** Virtual Serial Port ************************/
369 
370 extern S_line_coding line_coding;
371 
372 //! cdc_get_line_coding.
373 //!
374 //! @brief This function manages reception of line coding parameters (baudrate...).
375 //!
376 void cdc_get_line_coding(void)
377 {
379  Usb_write_byte(LSB0(line_coding.dwDTERate));
380  Usb_write_byte(LSB1(line_coding.dwDTERate));
381  Usb_write_byte(LSB2(line_coding.dwDTERate));
382  Usb_write_byte(LSB3(line_coding.dwDTERate));
383  Usb_write_byte(line_coding.bCharFormat);
384  Usb_write_byte(line_coding.bParityType);
385  Usb_write_byte(line_coding.bDataBits);
386 
388 }
389 
390 
391 //! cdc_set_line_coding.
392 //!
393 //! @brief This function manages reception of line coding parameters (baudrate...).
394 //!
395 void cdc_set_line_coding (void)
396 {
398  if(usb_endpoint_wait_for_receive_out()==0) {
399  LSB0(line_coding.dwDTERate) = Usb_read_byte();
400  LSB1(line_coding.dwDTERate) = Usb_read_byte();
401  LSB2(line_coding.dwDTERate) = Usb_read_byte();
402  LSB3(line_coding.dwDTERate) = Usb_read_byte();
403  line_coding.bCharFormat = Usb_read_byte();
404  line_coding.bParityType = Usb_read_byte();
405  line_coding.bDataBits = Usb_read_byte();
407 
408  Usb_send_control_in(); // send a ZLP for STATUS phase
409  usb_endpoint_wait_for_read_control_enabled();
410  }
411 }
412 
413 //! cdc_set_control_line_state.
414 //!
415 //! @brief This function manages the SET_CONTROL_LINE_LINE_STATE CDC request.
416 //!
417 //! Note: Can manage hardware flow control here...
418 //!
419 void cdc_set_control_line_state (void)
420 {
421  U8 controlLineState = Usb_read_byte();
422 // U8 dummy = Usb_read_byte(); //Compiler warning
423  if (Usb_read_byte()) {};
424  U8 interface = Usb_read_byte();
425 
428  usb_endpoint_wait_for_read_control_enabled();
429 
430  if(interface == INTERFACE2_NB) {
431  uart_usb_set_control_line_state(controlLineState);
432  }
433 }
434 #endif /* USB_CONF_SERIAL */
435 
436 Bool usb_user_set_alt_interface(U8 interface, U8 alt_setting) {
437  return FALSE;
438  if((interface==ECM_INTERFACE0_NB) && ((usb_configuration_nb==USB_CONFIG_ECM) || (usb_configuration_nb==USB_CONFIG_ECM_DEBUG))) {
439  // The alt_setting in this case corresponds to
440  // if the interface is enabled or not.
441  usb_eth_set_active(alt_setting);
442  }
443  return TRUE;
444 }
445