Contiki 3.x
usb_standard_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  * This file contains the USB endpoint 0 management routines corresponding to
6  * the standard enumeration process (refer to chapter 9 of the USB
7  * specification.
8  * This file calls routines of the usb_specific_request.c file for non-standard
9  * request management.
10  * The enumeration parameters (descriptor tables) are contained in the
11  * usb_descriptors.c file.
12  *
13  * \addtogroup usbdriver
14  *
15  * \author
16  * Atmel Corporation: http://www.atmel.com \n
17  * Support email: avr@atmel.com
18  *
19  ******************************************************************************/
20 /* Copyright (c) 2008 ATMEL Corporation
21  All rights reserved.
22 
23  Redistribution and use in source and binary forms, with or without
24  modification, are permitted provided that the following conditions are met:
25 
26  * Redistributions of source code must retain the above copyright
27  notice, this list of conditions and the following disclaimer.
28  * Redistributions in binary form must reproduce the above copyright
29  notice, this list of conditions and the following disclaimer in
30  the documentation and/or other materials provided with the
31  distribution.
32  * Neither the name of the copyright holders nor the names of
33  contributors may be used to endorse or promote products derived
34  from this software without specific prior written permission.
35 
36  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
37  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
40  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46  POSSIBILITY OF SUCH DAMAGE.
47 */
48 
49 //_____ I N C L U D E S ____________________________________________________
50 
51 #include "config.h"
52 #include "usb_drv.h"
53 #include "usb_descriptors.h"
54 #include "usb_specific_request.h"
55 #include <string.h>
56 
57 //_____ M A C R O S ________________________________________________________
58 
59 
60 //_____ D E F I N I T I O N ________________________________________________
61 #define PRINTF printf
62 #define PRINTF_P printf_P
63 
64 //_____ P R I V A T E D E C L A R A T I O N ______________________________
65 
66 static void usb_get_descriptor( void);
67 static void usb_set_address( void);
68 static void usb_set_configuration(void);
69 static void usb_clear_feature( void);
70 static void usb_set_feature( void);
71 static void usb_get_status( void);
72 static void usb_get_configuration(void);
73 static void usb_get_interface (void);
74 static void usb_set_interface (void);
75 
76 
77 //_____ D E C L A R A T I O N ______________________________________________
78 
79 static bit zlp;
80 static U8 endpoint_status[NB_ENDPOINTS];
81 
82 #ifdef AVRGCC
83  PGM_VOID_P pbuffer;
84 #else
85  U8 FLASH *pbuffer;
86 #endif
87  U8 data_to_transfer;
88 
89  U16 wInterface;
90 
91 static U8 bmRequestType;
92 
94 
95  usb_mode_t usb_mode = rndis_debug;
96 
97 extern bit usb_connected;
98 extern FLASH S_usb_device_descriptor usb_user_device_descriptor_network;
99 extern FLASH S_usb_user_configuration_descriptor_network usb_user_configuration_descriptor_network;
100 extern FLASH S_usb_device_descriptor usb_user_device_descriptor_composite;
101 extern FLASH S_usb_user_configuration_descriptor_composite usb_user_configuration_descriptor_composite;
102 
103 //! usb_process_request.
104 //!
105 //! @brief This function reads the SETUP request sent to the default control endpoint
106 //! and calls the appropriate function. When exiting of the usb_read_request
107 //! function, the device is ready to manage the next request.
108 //!
109 //! @note list of supported requests:
110 //! GET_DESCRIPTOR
111 //! GET_CONFIGURATION
112 //! SET_ADDRESS
113 //! SET_CONFIGURATION
114 //! CLEAR_FEATURE
115 //! SET_FEATURE
116 //! GET_STATUS
117 //!
119 {
120  U8 bmRequest;
121 
122  bmRequestType = Usb_read_byte();
123  bmRequest = Usb_read_byte();
124 
125  switch (bmRequest)
126  {
127  case GET_DESCRIPTOR:
128  if (0x80 == bmRequestType) { usb_get_descriptor(); }
129  else goto user_read;
130  break;
131 
132  case GET_CONFIGURATION:
133  if (0x80 == bmRequestType) { usb_get_configuration(); }
134  else goto user_read;
135  break;
136 
137  case SET_ADDRESS:
138  if (0x00 == bmRequestType) { usb_set_address(); }
139  else goto user_read;
140  break;
141 
142  case SET_CONFIGURATION:
143  if (0x00 == bmRequestType) { usb_set_configuration(); }
144  else goto user_read;
145  break;
146 
147  case CLEAR_FEATURE:
148  if (0x02 >= bmRequestType) { usb_clear_feature(); }
149  else goto user_read;
150  break;
151 
152  case SET_FEATURE:
153  if (0x02 >= bmRequestType) { usb_set_feature(); }
154  else goto user_read;
155  break;
156 
157  case GET_STATUS:
158  if ((0x7F < bmRequestType) & (0x82 >= bmRequestType))
159  { usb_get_status(); }
160  else goto user_read;
161  break;
162 
163  case GET_INTERFACE:
164  if (bmRequestType == 0x81) { usb_get_interface(); }
165  else goto user_read;
166  break;
167 
168 
169  case SET_INTERFACE:
170  if (bmRequestType == 0x01) {usb_set_interface();}
171  break;
172 
173  case SET_DESCRIPTOR:
174  case SYNCH_FRAME:
175  default: //!< un-supported request => call to user read request
176  user_read:
177  usb_user_read_request(bmRequestType, bmRequest);
178  break;
179  }
180 
181  Usb_select_endpoint(EP_CONTROL);
182 
183  // If the receive setup flag hasn't been cleared
184  // by this point then we can assume that we didn't
185  // support this request and should stall.
188 
189  // Clear some flags.
193 }
194 
195 //! usb_set_address.
196 //!
197 //! This function manages the SET ADDRESS request. When complete, the device
198 //! will filter the requests using the new address.
199 //!
200 //! @warning Code:xx bytes (function code length)
201 //!
202 void usb_set_address(void)
203 {
205 
207 
208  Usb_send_control_in(); //!< send a ZLP for STATUS phase
209  while(!Is_usb_in_ready()); //!< waits for status phase done
210  //!< before using the new address
212 }
213 
214 //! usb_set_configuration.
215 //!
216 //! This function manages the SET CONFIGURATION request. If the selected
217 //! configuration is valid, this function call the usb_user_endpoint_init()
218 //! function that will configure the endpoints following the configuration
219 //! number.
220 //!
221 //! @warning Code:xx bytes (function code length)
222 //!
223 void usb_set_configuration( void )
224 {
225 U8 configuration_number;
226 
227  configuration_number = Usb_read_byte();
228 
229  // TODO: Verify configuration_number!
231  usb_configuration_nb = configuration_number;
232 
233  Usb_send_control_in(); //!< send a ZLP for STATUS phase
234  while(!Is_usb_in_ready());
235 
236  usb_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration
237  Usb_set_configuration_action();
238 }
239 
240 
241 
242 
243 
244 void usb_get_string_descriptor_sram(U8 string_type) {
245  U16 requested_length;
246  U8 dummy;
247  const char* user_str;
248 
249  user_str = usb_user_get_string_sram(string_type);
250 
251  dummy = Usb_read_byte(); //!< don't care of wIndex field
252  dummy = Usb_read_byte();
253  if (dummy) {;} //avoid gcc unused variable warning
254  requested_length = Usb_read_byte(); //!< read wLength
255  requested_length |= Usb_read_byte()<<8;
256 
257  if(!user_str)
258  return;
259 
260  const U8 actual_descriptor_size = 2+strlen(user_str)*2;
261 
262  if (requested_length > actual_descriptor_size) {
263  zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
264  requested_length = actual_descriptor_size;
265  }
266 
267  Usb_ack_receive_setup() ; //!< clear the receive setup flag
268 
269  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
271  return;
272  }
273 
274  // Output the length
275  Usb_write_byte(actual_descriptor_size);
276 
277  // Output the type
278  Usb_write_byte(STRING_DESCRIPTOR);
279 
280  requested_length -= 2;
281  U8 nb_byte = 2;
282 
283  if(!requested_length) {
285  }
286 
287  while((requested_length != 0) && (!Is_usb_receive_out()))
288  {
289  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
291  break;
292  }
293 
294  while(requested_length != 0) //!< Send data until necessary
295  {
296  if(nb_byte==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
297  {
298  nb_byte=0;
299  break;
300  }
301 
302  Usb_write_byte(*user_str);
303  Usb_write_byte(0);
304  user_str++;
305  requested_length -=2;
306  nb_byte+=2;
307  }
309  }
310 
311 //bail:
312  if(Is_usb_receive_out()) {
313  //! abort from Host
315  return;
316  }
317 
318  if(zlp == TRUE) {
319  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
321  return;
322  }
324  }
325 
326  usb_endpoint_wait_for_receive_out();
328 }
329 
330 
331 void usb_get_string_descriptor(U8 string_type) {
332  U16 requested_length;
333  U8 dummy;
334  PGM_P user_str;
335 
336  user_str = usb_user_get_string(string_type);
337 
338  if(!user_str) {
339  usb_get_string_descriptor_sram(string_type);
340  return;
341  }
342 
343  dummy = Usb_read_byte(); //!< don't care of wIndex field
344  dummy = Usb_read_byte();
345  if (dummy) {;}
346  requested_length = Usb_read_byte(); //!< read wLength
347  requested_length |= Usb_read_byte()<<8;
348 
349 
350  const U8 actual_descriptor_size = 2+strlen_P(user_str)*2;
351 
352  if (requested_length > actual_descriptor_size) {
353  zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0);
354  requested_length = actual_descriptor_size;
355  }
356 
357  Usb_ack_receive_setup() ; //!< clear the receive setup flag
358 
359  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
361  return;
362  }
363  U8 nb_byte = 0;
364 
365  // Output the length
366  if(requested_length) {
367  Usb_write_byte(actual_descriptor_size);
368  requested_length--;
369  nb_byte++;
370  }
371 
372  // Output the type
373  if(requested_length) {
374  Usb_write_byte(STRING_DESCRIPTOR);
375  requested_length--;
376  nb_byte++;
377  }
378 
379  if(!requested_length) {
381  }
382 
383  while((requested_length != 0) && (!Is_usb_receive_out()))
384  {
385  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
387  break;
388  }
389 
390  while(requested_length != 0) //!< Send data until necessary
391  {
392  if(nb_byte==EP_CONTROL_LENGTH) { //!< Check endpoint 0 size
393  nb_byte=0;
394  break;
395  }
396 
397  Usb_write_byte(pgm_read_byte_near((unsigned int)user_str++));
398  requested_length--;
399  nb_byte++;
400  if(requested_length) {
401  Usb_write_byte(0);
402  requested_length--;
403  nb_byte++;
404  }
405  }
407  }
408 
409 //bail:
410 
411  if(Is_usb_receive_out()) {
412  //! abort from Host
414  return;
415  }
416 
417  if(zlp == TRUE) {
418  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
420  return;
421  }
423  }
424 
425  usb_endpoint_wait_for_receive_out();
427 }
428 
429 
430 //! usb_get_descriptor.
431 //!
432 //! This function manages the GET DESCRIPTOR request. The device descriptor,
433 //! the configuration descriptor and the device qualifier are supported. All
434 //! other descriptors must be supported by the usb_user_get_descriptor
435 //! function.
436 //! Only 1 configuration is supported.
437 //!
438 //! @warning Code:xx bytes (function code length)
439 //!
440 void usb_get_descriptor(void)
441 {
442  U8 LSBwLength, MSBwLength;
443  U8 descriptor_type ;
444  U8 string_type ;
445  U8 dummy;
446  U8 byteswereread;
447 
448  zlp = FALSE; /* no zero length packet */
449  string_type = Usb_read_byte(); /* read LSB of wValue */
450  descriptor_type = Usb_read_byte(); /* read MSB of wValue */
451  byteswereread = 0;
452 
453  switch (descriptor_type)
454  {
455  case DEVICE_DESCRIPTOR:
456  data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
457  pbuffer = Usb_get_dev_desc_pointer();
458  break;
459  case CONFIGURATION_DESCRIPTOR:
460  data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor);
461  pbuffer = Usb_get_conf_desc_pointer(string_type);
462  break;
463 #if 1
464  case STRING_DESCRIPTOR:
465  if(string_type!=LANG_ID) {
466  usb_get_string_descriptor(string_type);
467  return;
468  }
469 #endif
470  default:
471  dummy = Usb_read_byte();
472  dummy = Usb_read_byte();
473  if (dummy) {;}
474  LSBwLength = Usb_read_byte();
475  MSBwLength = Usb_read_byte();
476  byteswereread=1;
477  if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) {
478  Usb_enable_stall_handshake(); //TODO:is this necessary, Win7 flaky without?
480  return;
481  }
482  break;
483  }
484  if (byteswereread==0) {
485  dummy = Usb_read_byte(); //!< don't care of wIndex field
486  dummy = Usb_read_byte();
487  LSBwLength = Usb_read_byte(); //!< read wLength
488  MSBwLength = Usb_read_byte();
489  }
490 
491  Usb_ack_receive_setup() ; //!< clear the receive setup flag
492 
493  if ((LSBwLength > data_to_transfer) || (MSBwLength)) {
494  if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
495  else { zlp = FALSE; } //!< no need of zero length packet
496 
497  LSBwLength = data_to_transfer;
498  MSBwLength = 0x00;
499  } else {
500  data_to_transfer = LSBwLength; //!< send only requested number of data
501  }
502 
503  while((data_to_transfer != 0) && (!Is_usb_receive_out())) {
504  U8 nb_byte = 0;
505  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
507  break;
508  }
509 
510  //! Send data until necessary
511  while(data_to_transfer != 0) {
512 // if(Is_usb_write_enabled()) //!< Check endpoint 0 size
513  if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
514  break;
515 
516  Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++));
517  data_to_transfer --;
518 
519  }
521  }
522 
523  if(Is_usb_receive_out()) {
524  //! abort from Host
526  return;
527  }
528 
529  if(zlp == TRUE) {
530  if(usb_endpoint_wait_for_read_control_enabled()!=0) {
532  return;
533  }
535  }
536 
537  usb_endpoint_wait_for_receive_out();
539 }
540 
541 //! usb_get_configuration.
542 //!
543 //! This function manages the GET CONFIGURATION request. The current
544 //! configuration number is returned.
545 //!
546 //! @warning Code:xx bytes (function code length)
547 //!
548 void usb_get_configuration(void)
549 {
551 
554 
555  usb_endpoint_wait_for_receive_out();
557 }
558 
559 //! usb_get_status.
560 //!
561 //! This function manages the GET STATUS request. The device, interface or
562 //! endpoint status is returned.
563 //!
564 //! @warning Code:xx bytes (function code length)
565 //!
566 void usb_get_status(void)
567 {
568 U8 wIndex;
569 U8 dummy;
570 
571  dummy = Usb_read_byte(); //!< dummy read
572  dummy = Usb_read_byte(); //!< dummy read
573  if (dummy) {;}
574  wIndex = Usb_read_byte();
575 
576  switch(bmRequestType)
577  {
578  case REQUEST_DEVICE_STATUS: Usb_ack_receive_setup();
579  Usb_write_byte(DEVICE_STATUS);
580  break;
581 
582  case REQUEST_INTERFACE_STATUS: Usb_ack_receive_setup();
583  Usb_write_byte(INTERFACE_STATUS);
584  break;
585 
586  case REQUEST_ENDPOINT_STATUS: Usb_ack_receive_setup();
587  wIndex = wIndex & MSK_EP_DIR;
588  Usb_write_byte(endpoint_status[wIndex]);
589  break;
590  default:
593  return;
594  }
595 
596  Usb_write_byte(0x00);
598 
599  usb_endpoint_wait_for_receive_out();
601 }
602 
603 //! usb_set_feature.
604 //!
605 //! This function manages the SET FEATURE request. The USB test modes are
606 //! supported by this function.
607 //!
608 //! @warning Code:xx bytes (function code length)
609 //!
610 void usb_set_feature(void)
611 {
612 U8 wValue;
613 U8 wIndex;
614 U8 dummy;
615 
616  if (bmRequestType == INTERFACE_TYPE)
617  {
618  return;
619  }
620  else if (bmRequestType == ENDPOINT_TYPE)
621  {
622  wValue = Usb_read_byte();
623  dummy = Usb_read_byte(); //!< dummy read
624  if (dummy) {;}
625 
626  if (wValue == FEATURE_ENDPOINT_HALT)
627  {
628  wIndex = (Usb_read_byte() & MSK_EP_DIR);
629 
630  if (wIndex == EP_CONTROL)
631  {
632  return;
633  }
634 
635  Usb_select_endpoint(wIndex);
637  {
639  Usb_select_endpoint(EP_CONTROL);
640  endpoint_status[wIndex] = 0x01;
643  }
644  else
645  {
646  Usb_select_endpoint(EP_CONTROL);
647  return;
648  }
649  }
650  else
651  {
652  return;
653  }
654  }
655 }
656 
657 //! usb_clear_feature.
658 //!
659 //! This function manages the SET FEATURE request.
660 //!
661 //! @warning Code:xx bytes (function code length)
662 //!
663 void usb_clear_feature(void)
664 {
665 U8 wValue;
666 U8 wIndex;
667 U8 dummy;
668 
669  if (bmRequestType == ZERO_TYPE)
670  {
671  return;
672  }
673  else if (bmRequestType == INTERFACE_TYPE)
674  {
675  return;
676  }
677  else if (bmRequestType == ENDPOINT_TYPE)
678  {
679  wValue = Usb_read_byte();
680  dummy = Usb_read_byte(); //!< dummy read
681  if (dummy) {;}
682 
683  if (wValue == FEATURE_ENDPOINT_HALT)
684  {
685  wIndex = (Usb_read_byte() & MSK_EP_DIR);
686 
687  Usb_select_endpoint(wIndex);
689  {
690  if(wIndex != EP_CONTROL)
691  {
693  Usb_reset_endpoint(wIndex);
695  }
696  Usb_select_endpoint(EP_CONTROL);
697  endpoint_status[wIndex] = 0x00;
700 
701  }
702  else
703  {
704  return;
705  }
706  }
707  else
708  {
709  return;
710  }
711  }
712 }
713 
714 //! usb_get_interface.
715 //!
716 //! TThis function manages the GET_INTERFACE request.
717 //!
718 //! @warning Code:xx bytes (function code length)
719 //!
720 void usb_get_interface (void)
721 {
722  // Not yet implemented.
723 }
724 
725 //! usb_set_interface.
726 //!
727 //! TThis function manages the SET_INTERFACE request.
728 //!
729 //! @warning Code:xx bytes (function code length)
730 //!
731 void usb_set_interface (void)
732 {
733  U8 alt_setting;
734  U8 dummy;
735  U8 interface;
736 
737  alt_setting = Usb_read_byte();
738  dummy = Usb_read_byte();
739  if (dummy) {;}
740  interface = Usb_read_byte();
741 
742  if(usb_user_set_alt_interface(interface, alt_setting)) {
744  Usb_send_control_in(); //!< send a ZLP for STATUS phase
745  while(!Is_usb_in_ready());
746 
747  usb_endpoint_wait_for_receive_out();
749  }
750 
751 }
#define Is_usb_endpoint_enabled()
tests if the current endpoint is enabled
Definition: usb_drv.h:481
void usb_get_string_descriptor(U8 string_type)
void usb_get_string_descriptor_sram(U8 string_type)
#define Usb_configure_address(addr)
sets the USB device address
Definition: usb_drv.h:445
#define Usb_reset_endpoint(ep)
resets the selected endpoint
Definition: usb_drv.h:466
#define Usb_read_byte()
returns FIFO byte for current endpoint
Definition: usb_drv.h:596
#define Usb_disable_stall_handshake()
disables the STALL handshake
Definition: usb_drv.h:477
This file contains the user callback functions corresponding to the application.
This file contains the USB driver routines.
Usb Device Descriptor.
#define Usb_write_byte(byte)
writes byte in FIFO for current endpoint
Definition: usb_drv.h:598
void usb_process_request(void)
usb_process_request.
#define Usb_ack_in_ready()
acks IN ready
Definition: usb_drv.h:542
U8 usb_configuration_nb
Public : (U8) usb_configuration_nb Store the number of the USB configuration used by the USB device w...
#define Usb_ack_receive_setup()
acks receive SETUP
Definition: usb_drv.h:532
#define Usb_enable_address()
enables USB device address
Definition: usb_drv.h:441
#define TRUE
An alias for one, used for clarity.
bit usb_connected
Public : (bit) usb_connected usb_connected is set to TRUE when VBUS has been detected usb_connected i...
Definition: usb_task.c:115
#define Usb_send_control_in()
sends IN on control endpoint
Definition: usb_drv.h:560
#define Is_usb_receive_setup()
tests if SETUP received
Definition: usb_drv.h:552
void usb_user_endpoint_init(U8 conf_nb)
usb_user_endpoint_init.
#define Usb_reset_data_toggle()
resets the data toggle sequence
Definition: usb_drv.h:473
#define CLEAR_FEATURE
see FEATURES below
Definition: usb_task.h:116
This file contains the usb parameters that uniquely identify the application through descriptor table...
#define Is_usb_in_ready()
tests if IN ready
Definition: usb_drv.h:556
#define FALSE
An alias for zero, used for clarity.
#define Usb_select_endpoint(ep)
selects the endpoint number to interface with the CPU
Definition: usb_drv.h:460
Bool usb_user_read_request(U8 type, U8 request)
This function is called by the standard usb read request function when the Usb request is not support...
#define Is_usb_receive_out()
tests if OUT received
Definition: usb_drv.h:554
#define SET_FEATURE
see FEATURES below
Definition: usb_task.h:118
#define Usb_ack_receive_out()
acks reveive OUT
Definition: usb_drv.h:538
#define Usb_enable_stall_handshake()
enables the STALL handshake for the next transaction
Definition: usb_drv.h:471
Bool usb_user_get_descriptor(U8 type, U8 string)
usb_user_get_descriptor.