Mercurial > louis > kiibohd-controller
comparison Output/usbMuxUart/output_com.c @ 449:45feb80a2ad1
Major USB update, fixes most (if not all) known issues
USB - General
- Refactored descriptors
- Enabled/Disable USB endpoints
- Added debug flags for special features
- Code cleanup
- Interface count calculation based off of enabled endpoints
- Delayed wTotalLength calculation to simplify descriptor offsets
- Re-ordered endpoints and interfaces
- Added more debug output
- Added usbInitTime to show how long keyboard initialization took
(Useful when debugging bad init sequences)
- Added function for usb_resume() which takes care of the resume sequence
* Resume is now only called if packets are starting to timeout
USB - Special Options
- Added enableDeviceRestartOnUSBTimeout
* A last resort hammer for bad USB Chipsets/OSs, don't use if you can help it
* Disabled
- Added enableUSBResume
* Enables host resume wake-up signalling, required to wake a computer from sleep
* Enabled
- Added enableUSBLowPowerNegotiation
* Enables power negotiation hack
* Required to use firmware with an IPad and other hard-limit low-power USB hosts
* Hasn't been tested with the recent changes
* Disabled
- Added enableUSBSuspend
* Enables power down events on host USB bus suspend
* Enabled
USB - Keyboard
- Attempted to cleanup HID SET_REPORT
* Works much better
* Still has an issue under Linux which generates *a lot* of NAKs (initializes quickly regardless)
+ Not present on other keyboards
+ SETUP -> OUT -> IN : This sequence is the problem
+ Specifically during the OUT phase
- Enabled
USB - CDC Virtual Serial Port
- Code cleanup
- Added convenience struct USBCDCLineCoding for easier debugging
- Attempted to cleanup CDC_SET_LING_CODING
* Works much better
* Still has an issue under Linux which generates *a lot* of NAKs (initializes quickly regardless)
+ SETUP -> OUT -> IN : This sequence is the problem
+ Specifically during the OUT phase
+ Likely the same issues as HID SET_REPORT
- Enabled
USB - Mouse
- Enabled
USB - Joystick
- Disabled
USB - RawIO
- Initial code, API not used yet
- Disabled
DFU
- Updated load script, now faster
author | Jacob Alexander <haata@kiibohd.com> |
---|---|
date | Tue, 31 May 2016 00:19:45 -0700 |
parents | 56237ba5da6f |
children |
comparison
equal
deleted
inserted
replaced
448:077a1dfd8529 | 449:45feb80a2ad1 |
---|---|
49 | 49 |
50 | 50 |
51 // ----- Macros ----- | 51 // ----- Macros ----- |
52 | 52 |
53 // Used to build a bitmap lookup table from a byte addressable array | 53 // Used to build a bitmap lookup table from a byte addressable array |
54 #define byteLookup( byte ) case (( byte ) * ( 8 )): bytePosition = byte; byteShift = 0; break; \ | 54 #define byteLookup( byte ) \ |
55 case (( byte ) * ( 8 ) + ( 1 )): bytePosition = byte; byteShift = 1; break; \ | 55 case (( byte ) * ( 8 )): bytePosition = byte; byteShift = 0; break; \ |
56 case (( byte ) * ( 8 ) + ( 2 )): bytePosition = byte; byteShift = 2; break; \ | 56 case (( byte ) * ( 8 ) + ( 1 )): bytePosition = byte; byteShift = 1; break; \ |
57 case (( byte ) * ( 8 ) + ( 3 )): bytePosition = byte; byteShift = 3; break; \ | 57 case (( byte ) * ( 8 ) + ( 2 )): bytePosition = byte; byteShift = 2; break; \ |
58 case (( byte ) * ( 8 ) + ( 4 )): bytePosition = byte; byteShift = 4; break; \ | 58 case (( byte ) * ( 8 ) + ( 3 )): bytePosition = byte; byteShift = 3; break; \ |
59 case (( byte ) * ( 8 ) + ( 5 )): bytePosition = byte; byteShift = 5; break; \ | 59 case (( byte ) * ( 8 ) + ( 4 )): bytePosition = byte; byteShift = 4; break; \ |
60 case (( byte ) * ( 8 ) + ( 6 )): bytePosition = byte; byteShift = 6; break; \ | 60 case (( byte ) * ( 8 ) + ( 5 )): bytePosition = byte; byteShift = 5; break; \ |
61 case (( byte ) * ( 8 ) + ( 7 )): bytePosition = byte; byteShift = 7; break | 61 case (( byte ) * ( 8 ) + ( 6 )): bytePosition = byte; byteShift = 6; break; \ |
62 case (( byte ) * ( 8 ) + ( 7 )): bytePosition = byte; byteShift = 7; break | |
62 | 63 |
63 | 64 |
64 | 65 |
65 // ----- Function Declarations ----- | 66 // ----- Function Declarations ----- |
66 | 67 |
70 void cliFunc_readUART ( char* args ); | 71 void cliFunc_readUART ( char* args ); |
71 void cliFunc_sendKeys ( char* args ); | 72 void cliFunc_sendKeys ( char* args ); |
72 void cliFunc_sendUART ( char* args ); | 73 void cliFunc_sendUART ( char* args ); |
73 void cliFunc_setKeys ( char* args ); | 74 void cliFunc_setKeys ( char* args ); |
74 void cliFunc_setMod ( char* args ); | 75 void cliFunc_setMod ( char* args ); |
76 void cliFunc_usbInitTime( char* args ); | |
75 | 77 |
76 | 78 |
77 | 79 |
78 // ----- Variables ----- | 80 // ----- Variables ----- |
79 | 81 |
84 CLIDict_Entry( readUART, "Read UART buffer until empty." ); | 86 CLIDict_Entry( readUART, "Read UART buffer until empty." ); |
85 CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); | 87 CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); |
86 CLIDict_Entry( sendUART, "Send characters over UART0." ); | 88 CLIDict_Entry( sendUART, "Send characters over UART0." ); |
87 CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); | 89 CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); |
88 CLIDict_Entry( setMod, "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI" ); | 90 CLIDict_Entry( setMod, "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4 LAlt, 8 LGUI, 16 RCtrl, 32 RShft, 64 RAlt, 128 RGUI" ); |
91 CLIDict_Entry( usbInitTime, "Displays the time in ms from usb_init() till the last setup call." ); | |
89 | 92 |
90 CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { | 93 CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { |
91 CLIDict_Item( kbdProtocol ), | 94 CLIDict_Item( kbdProtocol ), |
92 CLIDict_Item( outputDebug ), | 95 CLIDict_Item( outputDebug ), |
93 CLIDict_Item( readLEDs ), | 96 CLIDict_Item( readLEDs ), |
94 CLIDict_Item( readUART ), | 97 CLIDict_Item( readUART ), |
95 CLIDict_Item( sendKeys ), | 98 CLIDict_Item( sendKeys ), |
96 CLIDict_Item( sendUART ), | 99 CLIDict_Item( sendUART ), |
97 CLIDict_Item( setKeys ), | 100 CLIDict_Item( setKeys ), |
98 CLIDict_Item( setMod ), | 101 CLIDict_Item( setMod ), |
102 CLIDict_Item( usbInitTime ), | |
99 { 0, 0, 0 } // Null entry for dictionary end | 103 { 0, 0, 0 } // Null entry for dictionary end |
100 }; | 104 }; |
101 | 105 |
102 | 106 |
103 // Which modifier keys are currently pressed | 107 // Which modifier keys are currently pressed |
165 | 169 |
166 // mA - Set by USB module (if exists) | 170 // mA - Set by USB module (if exists) |
167 // Initially 100 mA, but may be negotiated higher (e.g. 500 mA) | 171 // Initially 100 mA, but may be negotiated higher (e.g. 500 mA) |
168 uint16_t Output_USBCurrent_Available = 0; | 172 uint16_t Output_USBCurrent_Available = 0; |
169 | 173 |
174 // USB Init Time (ms) | |
175 volatile uint32_t USBInit_TimeStart; | |
176 volatile uint32_t USBInit_TimeEnd; | |
177 volatile uint16_t USBInit_Ticks; | |
178 | |
170 | 179 |
171 | 180 |
172 // ----- Capabilities ----- | 181 // ----- Capabilities ----- |
173 | 182 |
174 // Set Boot Keyboard Protocol | 183 // Set Boot Keyboard Protocol |
175 void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 184 void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
176 { | 185 { |
186 #if enableKeyboard_define == 1 | |
177 // Display capability name | 187 // Display capability name |
178 if ( stateType == 0xFF && state == 0xFF ) | 188 if ( stateType == 0xFF && state == 0xFF ) |
179 { | 189 { |
180 print("Output_kbdProtocolBoot()"); | 190 print("Output_kbdProtocolBoot()"); |
181 return; | 191 return; |
193 // Flush the key buffers | 203 // Flush the key buffers |
194 Output_flushBuffers(); | 204 Output_flushBuffers(); |
195 | 205 |
196 // Set the keyboard protocol to Boot Mode | 206 // Set the keyboard protocol to Boot Mode |
197 USBKeys_Protocol = 0; | 207 USBKeys_Protocol = 0; |
208 #endif | |
198 } | 209 } |
199 | 210 |
200 | 211 |
201 // Set NKRO Keyboard Protocol | 212 // Set NKRO Keyboard Protocol |
202 void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 213 void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
203 { | 214 { |
215 #if enableKeyboard_define == 1 | |
204 // Display capability name | 216 // Display capability name |
205 if ( stateType == 0xFF && state == 0xFF ) | 217 if ( stateType == 0xFF && state == 0xFF ) |
206 { | 218 { |
207 print("Output_kbdProtocolNKRO()"); | 219 print("Output_kbdProtocolNKRO()"); |
208 return; | 220 return; |
220 // Flush the key buffers | 232 // Flush the key buffers |
221 Output_flushBuffers(); | 233 Output_flushBuffers(); |
222 | 234 |
223 // Set the keyboard protocol to NKRO Mode | 235 // Set the keyboard protocol to NKRO Mode |
224 USBKeys_Protocol = 1; | 236 USBKeys_Protocol = 1; |
237 #endif | |
225 } | 238 } |
226 | 239 |
227 | 240 |
228 // Toggle Keyboard Protocol | 241 // Toggle Keyboard Protocol |
229 void Output_toggleKbdProtocol_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 242 void Output_toggleKbdProtocol_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
230 { | 243 { |
244 #if enableKeyboard_define == 1 | |
231 // Display capability name | 245 // Display capability name |
232 if ( stateType == 0xFF && state == 0xFF ) | 246 if ( stateType == 0xFF && state == 0xFF ) |
233 { | 247 { |
234 print("Output_toggleKbdProtocol()"); | 248 print("Output_toggleKbdProtocol()"); |
235 return; | 249 return; |
242 Output_flushBuffers(); | 256 Output_flushBuffers(); |
243 | 257 |
244 // Toggle the keyboard protocol Mode | 258 // Toggle the keyboard protocol Mode |
245 USBKeys_Protocol = !USBKeys_Protocol; | 259 USBKeys_Protocol = !USBKeys_Protocol; |
246 } | 260 } |
261 #endif | |
247 } | 262 } |
248 | 263 |
249 | 264 |
250 // Sends a Consumer Control code to the USB Output buffer | 265 // Sends a Consumer Control code to the USB Output buffer |
251 void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 266 void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
252 { | 267 { |
268 #if enableKeyboard_define == 1 | |
253 // Display capability name | 269 // Display capability name |
254 if ( stateType == 0xFF && state == 0xFF ) | 270 if ( stateType == 0xFF && state == 0xFF ) |
255 { | 271 { |
256 print("Output_consCtrlSend(consCode)"); | 272 print("Output_consCtrlSend(consCode)"); |
257 return; | 273 return; |
276 return; | 292 return; |
277 } | 293 } |
278 | 294 |
279 // Set consumer control code | 295 // Set consumer control code |
280 USBKeys_ConsCtrl = *(uint16_t*)(&args[0]); | 296 USBKeys_ConsCtrl = *(uint16_t*)(&args[0]); |
297 #endif | |
281 } | 298 } |
282 | 299 |
283 | 300 |
284 // Ignores the given key status update | 301 // Ignores the given key status update |
285 // Used to prevent fall-through, this is the None keyword in KLL | 302 // Used to prevent fall-through, this is the None keyword in KLL |
297 | 314 |
298 | 315 |
299 // Sends a System Control code to the USB Output buffer | 316 // Sends a System Control code to the USB Output buffer |
300 void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 317 void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
301 { | 318 { |
319 #if enableKeyboard_define == 1 | |
302 // Display capability name | 320 // Display capability name |
303 if ( stateType == 0xFF && state == 0xFF ) | 321 if ( stateType == 0xFF && state == 0xFF ) |
304 { | 322 { |
305 print("Output_sysCtrlSend(sysCode)"); | 323 print("Output_sysCtrlSend(sysCode)"); |
306 return; | 324 return; |
325 return; | 343 return; |
326 } | 344 } |
327 | 345 |
328 // Set system control code | 346 // Set system control code |
329 USBKeys_SysCtrl = args[0]; | 347 USBKeys_SysCtrl = args[0]; |
348 #endif | |
330 } | 349 } |
331 | 350 |
332 | 351 |
333 // Adds a single USB Code to the USB Output buffer | 352 // Adds a single USB Code to the USB Output buffer |
334 // Argument #1: USB Code | 353 // Argument #1: USB Code |
335 void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 354 void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
336 { | 355 { |
356 #if enableKeyboard_define == 1 | |
337 // Display capability name | 357 // Display capability name |
338 if ( stateType == 0xFF && state == 0xFF ) | 358 if ( stateType == 0xFF && state == 0xFF ) |
339 { | 359 { |
340 print("Output_usbCodeSend(usbCode)"); | 360 print("Output_usbCodeSend(usbCode)"); |
341 return; | 361 return; |
532 USBKeys_Sent++; | 552 USBKeys_Sent++; |
533 } | 553 } |
534 | 554 |
535 break; | 555 break; |
536 } | 556 } |
557 #endif | |
537 } | 558 } |
538 | 559 |
539 void Output_flashMode_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 560 void Output_flashMode_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
540 { | 561 { |
541 // Display capability name | 562 // Display capability name |
555 // Argument #1: USB Mouse Button (16 bit) | 576 // Argument #1: USB Mouse Button (16 bit) |
556 // Argument #2: USB X Axis (16 bit) relative | 577 // Argument #2: USB X Axis (16 bit) relative |
557 // Argument #3: USB Y Axis (16 bit) relative | 578 // Argument #3: USB Y Axis (16 bit) relative |
558 void Output_usbMouse_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 579 void Output_usbMouse_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
559 { | 580 { |
581 #if enableMouse_define == 1 | |
560 // Display capability name | 582 // Display capability name |
561 if ( stateType == 0xFF && state == 0xFF ) | 583 if ( stateType == 0xFF && state == 0xFF ) |
562 { | 584 { |
563 print("Output_usbMouse(mouseButton,relX,relY)"); | 585 print("Output_usbMouse(mouseButton,relX,relY)"); |
564 return; | 586 return; |
602 if ( mouse_button ) | 624 if ( mouse_button ) |
603 USBMouse_Changed |= USBMouseChangeState_Buttons; | 625 USBMouse_Changed |= USBMouseChangeState_Buttons; |
604 | 626 |
605 if ( mouse_x || mouse_y ) | 627 if ( mouse_x || mouse_y ) |
606 USBMouse_Changed |= USBMouseChangeState_Relative; | 628 USBMouse_Changed |= USBMouseChangeState_Relative; |
629 #endif | |
607 } | 630 } |
608 | 631 |
609 | 632 |
610 | 633 |
611 // ----- Functions ----- | 634 // ----- Functions ----- |
650 // USB status checks | 673 // USB status checks |
651 // Non-standard USB state manipulation, usually does nothing | 674 // Non-standard USB state manipulation, usually does nothing |
652 usb_device_check(); | 675 usb_device_check(); |
653 | 676 |
654 // Boot Mode Only, unset stale keys | 677 // Boot Mode Only, unset stale keys |
655 if ( USBKeys_Protocol == 0 ) | |
656 for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | |
657 USBKeys_Keys[c] = 0; | |
658 | |
659 // XXX - Behaves oddly on Mac OSX, might help with corrupted packets specific to OSX? -HaaTa | 678 // XXX - Behaves oddly on Mac OSX, might help with corrupted packets specific to OSX? -HaaTa |
660 /* | 679 /* |
661 // Check if idle count has been exceed, this forces usb_keyboard_send and usb_mouse_send to update | 680 // Check if idle count has been exceed, this forces usb_keyboard_send and usb_mouse_send to update |
662 // TODO Add joystick as well (may be endpoint specific, currently not kept track of) | 681 // TODO Add joystick as well (may be endpoint specific, currently not kept track of) |
663 if ( usb_configuration && USBKeys_Idle_Config && ( | 682 if ( usb_configuration && USBKeys_Idle_Config && ( |
667 USBKeys_Changed = USBKeyChangeState_All; | 686 USBKeys_Changed = USBKeyChangeState_All; |
668 USBMouse_Changed = USBMouseChangeState_All; | 687 USBMouse_Changed = USBMouseChangeState_All; |
669 } | 688 } |
670 */ | 689 */ |
671 | 690 |
691 #if enableMouse_define == 1 | |
672 // Process mouse actions | 692 // Process mouse actions |
673 while ( USBMouse_Changed ) | 693 while ( USBMouse_Changed ) |
674 usb_mouse_send(); | 694 usb_mouse_send(); |
695 #endif | |
696 | |
697 #if enableKeyboard_define == 1 | |
698 if ( USBKeys_Protocol == 0 ) | |
699 for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | |
700 USBKeys_Keys[c] = 0; | |
675 | 701 |
676 // Send keypresses while there are pending changes | 702 // Send keypresses while there are pending changes |
677 while ( USBKeys_Changed ) | 703 while ( USBKeys_Changed ) |
678 usb_keyboard_send(); | 704 usb_keyboard_send(); |
679 | 705 |
690 break; | 716 break; |
691 case 1: // NKRO Mode | 717 case 1: // NKRO Mode |
692 Scan_finishedWithOutput( USBKeys_Sent ); | 718 Scan_finishedWithOutput( USBKeys_Sent ); |
693 break; | 719 break; |
694 } | 720 } |
721 #endif | |
695 } | 722 } |
696 | 723 |
697 | 724 |
698 // Sets the device into firmware reload mode | 725 // Sets the device into firmware reload mode |
699 void Output_firmwareReload() | 726 void Output_firmwareReload() |
703 | 730 |
704 | 731 |
705 // USB Input buffer available | 732 // USB Input buffer available |
706 inline unsigned int Output_availablechar() | 733 inline unsigned int Output_availablechar() |
707 { | 734 { |
735 #if enableVirtualSerialPort_define == 1 | |
708 return usb_serial_available() + uart_serial_available(); | 736 return usb_serial_available() + uart_serial_available(); |
737 #else | |
738 return uart_serial_available(); | |
739 #endif | |
709 } | 740 } |
710 | 741 |
711 | 742 |
712 // USB Get Character from input buffer | 743 // USB Get Character from input buffer |
713 inline int Output_getchar() | 744 inline int Output_getchar() |
714 { | 745 { |
746 #if enableVirtualSerialPort_define == 1 | |
715 // XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes) (AVR) | 747 // XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes) (AVR) |
716 if ( usb_serial_available() > 0 ) | 748 if ( usb_serial_available() > 0 ) |
717 { | 749 { |
718 return (int)usb_serial_getchar(); | 750 return (int)usb_serial_getchar(); |
719 } | 751 } |
752 #endif | |
720 | 753 |
721 if ( uart_serial_available() > 0 ) | 754 if ( uart_serial_available() > 0 ) |
722 { | 755 { |
723 return (int)uart_serial_getchar(); | 756 return (int)uart_serial_getchar(); |
724 } | 757 } |
728 | 761 |
729 | 762 |
730 // USB Send Character to output buffer | 763 // USB Send Character to output buffer |
731 inline int Output_putchar( char c ) | 764 inline int Output_putchar( char c ) |
732 { | 765 { |
766 #if enableVirtualSerialPort_define == 1 | |
733 // First send to UART | 767 // First send to UART |
734 uart_serial_putchar( c ); | 768 uart_serial_putchar( c ); |
735 | 769 |
736 // Then send to USB | 770 // Then send to USB |
737 return usb_serial_putchar( c ); | 771 return usb_serial_putchar( c ); |
772 #else | |
773 return uart_serial_putchar( c ); | |
774 #endif | |
738 } | 775 } |
739 | 776 |
740 | 777 |
741 // USB Send String to output buffer, null terminated | 778 // USB Send String to output buffer, null terminated |
742 inline int Output_putstr( char* str ) | 779 inline int Output_putstr( char* str ) |
748 #endif | 785 #endif |
749 // Count characters until NULL character, then send the amount counted | 786 // Count characters until NULL character, then send the amount counted |
750 while ( str[count] != '\0' ) | 787 while ( str[count] != '\0' ) |
751 count++; | 788 count++; |
752 | 789 |
790 #if enableVirtualSerialPort_define == 1 | |
753 // First send to UART | 791 // First send to UART |
754 uart_serial_write( str, count ); | 792 uart_serial_write( str, count ); |
755 | 793 |
756 // Then send to USB | 794 // Then send to USB |
757 return usb_serial_write( str, count ); | 795 return usb_serial_write( str, count ); |
796 #else | |
797 return uart_serial_write( str, count ); | |
798 #endif | |
758 } | 799 } |
759 | 800 |
760 | 801 |
761 // Soft Chip Reset | 802 // Soft Chip Reset |
762 inline void Output_softReset() | 803 inline void Output_softReset() |
936 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); | 977 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); |
937 | 978 |
938 USBKeys_ModifiersCLI = numToInt( arg1Ptr ); | 979 USBKeys_ModifiersCLI = numToInt( arg1Ptr ); |
939 } | 980 } |
940 | 981 |
982 void cliFunc_usbInitTime( char* args ) | |
983 { | |
984 // Calculate overall USB initialization time | |
985 // XXX A protocol analyzer will be more accurate, however, this is built-in and easier to collect data | |
986 print(NL); | |
987 info_msg("USB Init Time: "); | |
988 printInt32( USBInit_TimeEnd - USBInit_TimeStart ); | |
989 print(" ms - "); | |
990 printInt16( USBInit_Ticks ); | |
991 print(" ticks"); | |
992 } | |
993 |