Contiki 2.6
|
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/ 00002 /*! \file ********************************************************************* 00003 * 00004 * \brief 00005 * This file contains the USB endpoint 0 management routines corresponding to 00006 * the standard enumeration process (refer to chapter 9 of the USB 00007 * specification. 00008 * This file calls routines of the usb_specific_request.c file for non-standard 00009 * request management. 00010 * The enumeration parameters (descriptor tables) are contained in the 00011 * usb_descriptors.c file. 00012 * 00013 * \addtogroup usbdriver 00014 * 00015 * \author 00016 * Atmel Corporation: http://www.atmel.com \n 00017 * Support email: avr@atmel.com 00018 * 00019 ******************************************************************************/ 00020 /* Copyright (c) 2008 ATMEL Corporation 00021 All rights reserved. 00022 00023 Redistribution and use in source and binary forms, with or without 00024 modification, are permitted provided that the following conditions are met: 00025 00026 * Redistributions of source code must retain the above copyright 00027 notice, this list of conditions and the following disclaimer. 00028 * Redistributions in binary form must reproduce the above copyright 00029 notice, this list of conditions and the following disclaimer in 00030 the documentation and/or other materials provided with the 00031 distribution. 00032 * Neither the name of the copyright holders nor the names of 00033 contributors may be used to endorse or promote products derived 00034 from this software without specific prior written permission. 00035 00036 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00037 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00038 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00039 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00040 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00041 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00042 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00043 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00044 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00045 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00046 POSSIBILITY OF SUCH DAMAGE. 00047 */ 00048 00049 //_____ I N C L U D E S ____________________________________________________ 00050 00051 #include "config.h" 00052 #include "usb_drv.h" 00053 #include "usb_descriptors.h" 00054 #include "usb_specific_request.h" 00055 #include <string.h> 00056 00057 //_____ M A C R O S ________________________________________________________ 00058 00059 00060 //_____ D E F I N I T I O N ________________________________________________ 00061 #define PRINTF printf 00062 #define PRINTF_P printf_P 00063 00064 //_____ P R I V A T E D E C L A R A T I O N ______________________________ 00065 00066 static void usb_get_descriptor( void); 00067 static void usb_set_address( void); 00068 static void usb_set_configuration(void); 00069 static void usb_clear_feature( void); 00070 static void usb_set_feature( void); 00071 static void usb_get_status( void); 00072 static void usb_get_configuration(void); 00073 static void usb_get_interface (void); 00074 static void usb_set_interface (void); 00075 00076 00077 //_____ D E C L A R A T I O N ______________________________________________ 00078 00079 static bit zlp; 00080 static U8 endpoint_status[NB_ENDPOINTS]; 00081 00082 #ifdef AVRGCC 00083 PGM_VOID_P pbuffer; 00084 #else 00085 U8 FLASH *pbuffer; 00086 #endif 00087 U8 data_to_transfer; 00088 00089 U16 wInterface; 00090 00091 static U8 bmRequestType; 00092 00093 U8 usb_configuration_nb; 00094 00095 usb_mode_t usb_mode = rndis_debug; 00096 00097 extern bit usb_connected; 00098 extern FLASH S_usb_device_descriptor usb_user_device_descriptor_network; 00099 extern FLASH S_usb_user_configuration_descriptor_network usb_user_configuration_descriptor_network; 00100 extern FLASH S_usb_device_descriptor usb_user_device_descriptor_composite; 00101 extern FLASH S_usb_user_configuration_descriptor_composite usb_user_configuration_descriptor_composite; 00102 00103 //! usb_process_request. 00104 //! 00105 //! @brief This function reads the SETUP request sent to the default control endpoint 00106 //! and calls the appropriate function. When exiting of the usb_read_request 00107 //! function, the device is ready to manage the next request. 00108 //! 00109 //! @note list of supported requests: 00110 //! GET_DESCRIPTOR 00111 //! GET_CONFIGURATION 00112 //! SET_ADDRESS 00113 //! SET_CONFIGURATION 00114 //! CLEAR_FEATURE 00115 //! SET_FEATURE 00116 //! GET_STATUS 00117 //! 00118 void usb_process_request(void) 00119 { 00120 U8 bmRequest; 00121 00122 bmRequestType = Usb_read_byte(); 00123 bmRequest = Usb_read_byte(); 00124 00125 switch (bmRequest) 00126 { 00127 case GET_DESCRIPTOR: 00128 if (0x80 == bmRequestType) { usb_get_descriptor(); } 00129 else goto user_read; 00130 break; 00131 00132 case GET_CONFIGURATION: 00133 if (0x80 == bmRequestType) { usb_get_configuration(); } 00134 else goto user_read; 00135 break; 00136 00137 case SET_ADDRESS: 00138 if (0x00 == bmRequestType) { usb_set_address(); } 00139 else goto user_read; 00140 break; 00141 00142 case SET_CONFIGURATION: 00143 if (0x00 == bmRequestType) { usb_set_configuration(); } 00144 else goto user_read; 00145 break; 00146 00147 case CLEAR_FEATURE: 00148 if (0x02 >= bmRequestType) { usb_clear_feature(); } 00149 else goto user_read; 00150 break; 00151 00152 case SET_FEATURE: 00153 if (0x02 >= bmRequestType) { usb_set_feature(); } 00154 else goto user_read; 00155 break; 00156 00157 case GET_STATUS: 00158 if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) 00159 { usb_get_status(); } 00160 else goto user_read; 00161 break; 00162 00163 case GET_INTERFACE: 00164 if (bmRequestType == 0x81) { usb_get_interface(); } 00165 else goto user_read; 00166 break; 00167 00168 00169 case SET_INTERFACE: 00170 if (bmRequestType == 0x01) {usb_set_interface();} 00171 break; 00172 00173 case SET_DESCRIPTOR: 00174 case SYNCH_FRAME: 00175 default: //!< un-supported request => call to user read request 00176 user_read: 00177 usb_user_read_request(bmRequestType, bmRequest); 00178 break; 00179 } 00180 00181 Usb_select_endpoint(EP_CONTROL); 00182 00183 // If the receive setup flag hasn't been cleared 00184 // by this point then we can assume that we didn't 00185 // support this request and should stall. 00186 if(Is_usb_receive_setup()) 00187 Usb_enable_stall_handshake(); 00188 00189 // Clear some flags. 00190 Usb_ack_receive_setup(); 00191 Usb_ack_receive_out(); 00192 Usb_ack_in_ready(); 00193 } 00194 00195 //! usb_set_address. 00196 //! 00197 //! This function manages the SET ADDRESS request. When complete, the device 00198 //! will filter the requests using the new address. 00199 //! 00200 //! @warning Code:xx bytes (function code length) 00201 //! 00202 void usb_set_address(void) 00203 { 00204 Usb_configure_address(Usb_read_byte()); 00205 00206 Usb_ack_receive_setup(); 00207 00208 Usb_send_control_in(); //!< send a ZLP for STATUS phase 00209 while(!Is_usb_in_ready()); //!< waits for status phase done 00210 //!< before using the new address 00211 Usb_enable_address(); 00212 } 00213 00214 //! usb_set_configuration. 00215 //! 00216 //! This function manages the SET CONFIGURATION request. If the selected 00217 //! configuration is valid, this function call the usb_user_endpoint_init() 00218 //! function that will configure the endpoints following the configuration 00219 //! number. 00220 //! 00221 //! @warning Code:xx bytes (function code length) 00222 //! 00223 void usb_set_configuration( void ) 00224 { 00225 U8 configuration_number; 00226 00227 configuration_number = Usb_read_byte(); 00228 00229 // TODO: Verify configuration_number! 00230 Usb_ack_receive_setup(); 00231 usb_configuration_nb = configuration_number; 00232 00233 Usb_send_control_in(); //!< send a ZLP for STATUS phase 00234 while(!Is_usb_in_ready()); 00235 00236 usb_user_endpoint_init(usb_configuration_nb); //!< endpoint configuration 00237 Usb_set_configuration_action(); 00238 } 00239 00240 00241 00242 00243 00244 void usb_get_string_descriptor_sram(U8 string_type) { 00245 U16 requested_length; 00246 U8 dummy; 00247 const char* user_str; 00248 00249 user_str = usb_user_get_string_sram(string_type); 00250 00251 dummy = Usb_read_byte(); //!< don't care of wIndex field 00252 dummy = Usb_read_byte(); 00253 if (dummy) {;} //avoid gcc unused variable warning 00254 requested_length = Usb_read_byte(); //!< read wLength 00255 requested_length |= Usb_read_byte()<<8; 00256 00257 if(!user_str) 00258 return; 00259 00260 const U8 actual_descriptor_size = 2+strlen(user_str)*2; 00261 00262 if (requested_length > actual_descriptor_size) { 00263 zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0); 00264 requested_length = actual_descriptor_size; 00265 } 00266 00267 Usb_ack_receive_setup() ; //!< clear the receive setup flag 00268 00269 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00270 Usb_enable_stall_handshake(); 00271 return; 00272 } 00273 00274 // Output the length 00275 Usb_write_byte(actual_descriptor_size); 00276 00277 // Output the type 00278 Usb_write_byte(STRING_DESCRIPTOR); 00279 00280 requested_length -= 2; 00281 U8 nb_byte = 2; 00282 00283 if(!requested_length) { 00284 Usb_send_control_in(); 00285 } 00286 00287 while((requested_length != 0) && (!Is_usb_receive_out())) 00288 { 00289 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00290 Usb_enable_stall_handshake(); 00291 break; 00292 } 00293 00294 while(requested_length != 0) //!< Send data until necessary 00295 { 00296 if(nb_byte==EP_CONTROL_LENGTH) //!< Check endpoint 0 size 00297 { 00298 nb_byte=0; 00299 break; 00300 } 00301 00302 Usb_write_byte(*user_str); 00303 Usb_write_byte(0); 00304 user_str++; 00305 requested_length -=2; 00306 nb_byte+=2; 00307 } 00308 Usb_send_control_in(); 00309 } 00310 00311 //bail: 00312 if(Is_usb_receive_out()) { 00313 //! abort from Host 00314 Usb_ack_receive_out(); 00315 return; 00316 } 00317 00318 if(zlp == TRUE) { 00319 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00320 Usb_enable_stall_handshake(); 00321 return; 00322 } 00323 Usb_send_control_in(); 00324 } 00325 00326 usb_endpoint_wait_for_receive_out(); 00327 Usb_ack_receive_out(); 00328 } 00329 00330 00331 void usb_get_string_descriptor(U8 string_type) { 00332 U16 requested_length; 00333 U8 dummy; 00334 PGM_P user_str; 00335 00336 user_str = usb_user_get_string(string_type); 00337 00338 if(!user_str) { 00339 usb_get_string_descriptor_sram(string_type); 00340 return; 00341 } 00342 00343 dummy = Usb_read_byte(); //!< don't care of wIndex field 00344 dummy = Usb_read_byte(); 00345 if (dummy) {;} 00346 requested_length = Usb_read_byte(); //!< read wLength 00347 requested_length |= Usb_read_byte()<<8; 00348 00349 00350 const U8 actual_descriptor_size = 2+strlen_P(user_str)*2; 00351 00352 if (requested_length > actual_descriptor_size) { 00353 zlp = ((actual_descriptor_size % EP_CONTROL_LENGTH) == 0); 00354 requested_length = actual_descriptor_size; 00355 } 00356 00357 Usb_ack_receive_setup() ; //!< clear the receive setup flag 00358 00359 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00360 Usb_enable_stall_handshake(); 00361 return; 00362 } 00363 U8 nb_byte = 0; 00364 00365 // Output the length 00366 if(requested_length) { 00367 Usb_write_byte(actual_descriptor_size); 00368 requested_length--; 00369 nb_byte++; 00370 } 00371 00372 // Output the type 00373 if(requested_length) { 00374 Usb_write_byte(STRING_DESCRIPTOR); 00375 requested_length--; 00376 nb_byte++; 00377 } 00378 00379 if(!requested_length) { 00380 Usb_send_control_in(); 00381 } 00382 00383 while((requested_length != 0) && (!Is_usb_receive_out())) 00384 { 00385 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00386 Usb_enable_stall_handshake(); 00387 break; 00388 } 00389 00390 while(requested_length != 0) //!< Send data until necessary 00391 { 00392 if(nb_byte==EP_CONTROL_LENGTH) { //!< Check endpoint 0 size 00393 nb_byte=0; 00394 break; 00395 } 00396 00397 Usb_write_byte(pgm_read_byte_near((unsigned int)user_str++)); 00398 requested_length--; 00399 nb_byte++; 00400 if(requested_length) { 00401 Usb_write_byte(0); 00402 requested_length--; 00403 nb_byte++; 00404 } 00405 } 00406 Usb_send_control_in(); 00407 } 00408 00409 //bail: 00410 00411 if(Is_usb_receive_out()) { 00412 //! abort from Host 00413 Usb_ack_receive_out(); 00414 return; 00415 } 00416 00417 if(zlp == TRUE) { 00418 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00419 Usb_enable_stall_handshake(); 00420 return; 00421 } 00422 Usb_send_control_in(); 00423 } 00424 00425 usb_endpoint_wait_for_receive_out(); 00426 Usb_ack_receive_out(); 00427 } 00428 00429 00430 //! usb_get_descriptor. 00431 //! 00432 //! This function manages the GET DESCRIPTOR request. The device descriptor, 00433 //! the configuration descriptor and the device qualifier are supported. All 00434 //! other descriptors must be supported by the usb_user_get_descriptor 00435 //! function. 00436 //! Only 1 configuration is supported. 00437 //! 00438 //! @warning Code:xx bytes (function code length) 00439 //! 00440 void usb_get_descriptor(void) 00441 { 00442 U8 LSBwLength, MSBwLength; 00443 U8 descriptor_type ; 00444 U8 string_type ; 00445 U8 dummy; 00446 U8 byteswereread; 00447 00448 zlp = FALSE; /* no zero length packet */ 00449 string_type = Usb_read_byte(); /* read LSB of wValue */ 00450 descriptor_type = Usb_read_byte(); /* read MSB of wValue */ 00451 byteswereread = 0; 00452 00453 switch (descriptor_type) 00454 { 00455 case DEVICE_DESCRIPTOR: 00456 data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor); 00457 pbuffer = Usb_get_dev_desc_pointer(); 00458 break; 00459 case CONFIGURATION_DESCRIPTOR: 00460 data_to_transfer = Usb_get_conf_desc_length(string_type); //!< sizeof (usb_user_configuration_descriptor); 00461 pbuffer = Usb_get_conf_desc_pointer(string_type); 00462 break; 00463 #if 1 00464 case STRING_DESCRIPTOR: 00465 if(string_type!=LANG_ID) { 00466 usb_get_string_descriptor(string_type); 00467 return; 00468 } 00469 #endif 00470 default: 00471 dummy = Usb_read_byte(); 00472 dummy = Usb_read_byte(); 00473 if (dummy) {;} 00474 LSBwLength = Usb_read_byte(); 00475 MSBwLength = Usb_read_byte(); 00476 byteswereread=1; 00477 if( usb_user_get_descriptor(descriptor_type, string_type)==FALSE ) { 00478 Usb_enable_stall_handshake(); //TODO:is this necessary, Win7 flaky without? 00479 Usb_ack_receive_setup(); 00480 return; 00481 } 00482 break; 00483 } 00484 if (byteswereread==0) { 00485 dummy = Usb_read_byte(); //!< don't care of wIndex field 00486 dummy = Usb_read_byte(); 00487 LSBwLength = Usb_read_byte(); //!< read wLength 00488 MSBwLength = Usb_read_byte(); 00489 } 00490 00491 Usb_ack_receive_setup() ; //!< clear the receive setup flag 00492 00493 if ((LSBwLength > data_to_transfer) || (MSBwLength)) { 00494 if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } 00495 else { zlp = FALSE; } //!< no need of zero length packet 00496 00497 LSBwLength = data_to_transfer; 00498 MSBwLength = 0x00; 00499 } else { 00500 data_to_transfer = LSBwLength; //!< send only requested number of data 00501 } 00502 00503 while((data_to_transfer != 0) && (!Is_usb_receive_out())) { 00504 U8 nb_byte = 0; 00505 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00506 Usb_enable_stall_handshake(); 00507 break; 00508 } 00509 00510 //! Send data until necessary 00511 while(data_to_transfer != 0) { 00512 // if(Is_usb_write_enabled()) //!< Check endpoint 0 size 00513 if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size 00514 break; 00515 00516 Usb_write_byte(pgm_read_byte_near((unsigned int)pbuffer++)); 00517 data_to_transfer --; 00518 00519 } 00520 Usb_send_control_in(); 00521 } 00522 00523 if(Is_usb_receive_out()) { 00524 //! abort from Host 00525 Usb_ack_receive_out(); 00526 return; 00527 } 00528 00529 if(zlp == TRUE) { 00530 if(usb_endpoint_wait_for_read_control_enabled()!=0) { 00531 Usb_enable_stall_handshake(); 00532 return; 00533 } 00534 Usb_send_control_in(); 00535 } 00536 00537 usb_endpoint_wait_for_receive_out(); 00538 Usb_ack_receive_out(); 00539 } 00540 00541 //! usb_get_configuration. 00542 //! 00543 //! This function manages the GET CONFIGURATION request. The current 00544 //! configuration number is returned. 00545 //! 00546 //! @warning Code:xx bytes (function code length) 00547 //! 00548 void usb_get_configuration(void) 00549 { 00550 Usb_ack_receive_setup(); 00551 00552 Usb_write_byte(usb_configuration_nb); 00553 Usb_send_control_in(); 00554 00555 usb_endpoint_wait_for_receive_out(); 00556 Usb_ack_receive_out(); 00557 } 00558 00559 //! usb_get_status. 00560 //! 00561 //! This function manages the GET STATUS request. The device, interface or 00562 //! endpoint status is returned. 00563 //! 00564 //! @warning Code:xx bytes (function code length) 00565 //! 00566 void usb_get_status(void) 00567 { 00568 U8 wIndex; 00569 U8 dummy; 00570 00571 dummy = Usb_read_byte(); //!< dummy read 00572 dummy = Usb_read_byte(); //!< dummy read 00573 if (dummy) {;} 00574 wIndex = Usb_read_byte(); 00575 00576 switch(bmRequestType) 00577 { 00578 case REQUEST_DEVICE_STATUS: Usb_ack_receive_setup(); 00579 Usb_write_byte(DEVICE_STATUS); 00580 break; 00581 00582 case REQUEST_INTERFACE_STATUS: Usb_ack_receive_setup(); 00583 Usb_write_byte(INTERFACE_STATUS); 00584 break; 00585 00586 case REQUEST_ENDPOINT_STATUS: Usb_ack_receive_setup(); 00587 wIndex = wIndex & MSK_EP_DIR; 00588 Usb_write_byte(endpoint_status[wIndex]); 00589 break; 00590 default: 00591 Usb_enable_stall_handshake(); 00592 Usb_ack_receive_setup(); 00593 return; 00594 } 00595 00596 Usb_write_byte(0x00); 00597 Usb_send_control_in(); 00598 00599 usb_endpoint_wait_for_receive_out(); 00600 Usb_ack_receive_out(); 00601 } 00602 00603 //! usb_set_feature. 00604 //! 00605 //! This function manages the SET FEATURE request. The USB test modes are 00606 //! supported by this function. 00607 //! 00608 //! @warning Code:xx bytes (function code length) 00609 //! 00610 void usb_set_feature(void) 00611 { 00612 U8 wValue; 00613 U8 wIndex; 00614 U8 dummy; 00615 00616 if (bmRequestType == INTERFACE_TYPE) 00617 { 00618 return; 00619 } 00620 else if (bmRequestType == ENDPOINT_TYPE) 00621 { 00622 wValue = Usb_read_byte(); 00623 dummy = Usb_read_byte(); //!< dummy read 00624 if (dummy) {;} 00625 00626 if (wValue == FEATURE_ENDPOINT_HALT) 00627 { 00628 wIndex = (Usb_read_byte() & MSK_EP_DIR); 00629 00630 if (wIndex == EP_CONTROL) 00631 { 00632 return; 00633 } 00634 00635 Usb_select_endpoint(wIndex); 00636 if(Is_usb_endpoint_enabled()) 00637 { 00638 Usb_enable_stall_handshake(); 00639 Usb_select_endpoint(EP_CONTROL); 00640 endpoint_status[wIndex] = 0x01; 00641 Usb_ack_receive_setup(); 00642 Usb_send_control_in(); 00643 } 00644 else 00645 { 00646 Usb_select_endpoint(EP_CONTROL); 00647 return; 00648 } 00649 } 00650 else 00651 { 00652 return; 00653 } 00654 } 00655 } 00656 00657 //! usb_clear_feature. 00658 //! 00659 //! This function manages the SET FEATURE request. 00660 //! 00661 //! @warning Code:xx bytes (function code length) 00662 //! 00663 void usb_clear_feature(void) 00664 { 00665 U8 wValue; 00666 U8 wIndex; 00667 U8 dummy; 00668 00669 if (bmRequestType == ZERO_TYPE) 00670 { 00671 return; 00672 } 00673 else if (bmRequestType == INTERFACE_TYPE) 00674 { 00675 return; 00676 } 00677 else if (bmRequestType == ENDPOINT_TYPE) 00678 { 00679 wValue = Usb_read_byte(); 00680 dummy = Usb_read_byte(); //!< dummy read 00681 if (dummy) {;} 00682 00683 if (wValue == FEATURE_ENDPOINT_HALT) 00684 { 00685 wIndex = (Usb_read_byte() & MSK_EP_DIR); 00686 00687 Usb_select_endpoint(wIndex); 00688 if(Is_usb_endpoint_enabled()) 00689 { 00690 if(wIndex != EP_CONTROL) 00691 { 00692 Usb_disable_stall_handshake(); 00693 Usb_reset_endpoint(wIndex); 00694 Usb_reset_data_toggle(); 00695 } 00696 Usb_select_endpoint(EP_CONTROL); 00697 endpoint_status[wIndex] = 0x00; 00698 Usb_ack_receive_setup(); 00699 Usb_send_control_in(); 00700 00701 } 00702 else 00703 { 00704 return; 00705 } 00706 } 00707 else 00708 { 00709 return; 00710 } 00711 } 00712 } 00713 00714 //! usb_get_interface. 00715 //! 00716 //! TThis function manages the GET_INTERFACE request. 00717 //! 00718 //! @warning Code:xx bytes (function code length) 00719 //! 00720 void usb_get_interface (void) 00721 { 00722 // Not yet implemented. 00723 } 00724 00725 //! usb_set_interface. 00726 //! 00727 //! TThis function manages the SET_INTERFACE request. 00728 //! 00729 //! @warning Code:xx bytes (function code length) 00730 //! 00731 void usb_set_interface (void) 00732 { 00733 U8 alt_setting; 00734 U8 dummy; 00735 U8 interface; 00736 00737 alt_setting = Usb_read_byte(); 00738 dummy = Usb_read_byte(); 00739 if (dummy) {;} 00740 interface = Usb_read_byte(); 00741 00742 if(usb_user_set_alt_interface(interface, alt_setting)) { 00743 Usb_ack_receive_setup(); 00744 Usb_send_control_in(); //!< send a ZLP for STATUS phase 00745 while(!Is_usb_in_ready()); 00746 00747 usb_endpoint_wait_for_receive_out(); 00748 Usb_ack_receive_out(); 00749 } 00750 00751 }