Mercurial > louis > kiibohd-controller
comparison Output/pjrcUSB/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 |
---|---|
69 void cliFunc_outputDebug( char* args ); | 69 void cliFunc_outputDebug( char* args ); |
70 void cliFunc_readLEDs ( char* args ); | 70 void cliFunc_readLEDs ( char* args ); |
71 void cliFunc_sendKeys ( char* args ); | 71 void cliFunc_sendKeys ( char* args ); |
72 void cliFunc_setKeys ( char* args ); | 72 void cliFunc_setKeys ( char* args ); |
73 void cliFunc_setMod ( char* args ); | 73 void cliFunc_setMod ( char* args ); |
74 void cliFunc_usbInitTime( char* args ); | |
74 | 75 |
75 | 76 |
76 | 77 |
77 // ----- Variables ----- | 78 // ----- Variables ----- |
78 | 79 |
81 CLIDict_Entry( outputDebug, "Toggle Output Debug mode." ); | 82 CLIDict_Entry( outputDebug, "Toggle Output Debug mode." ); |
82 CLIDict_Entry( readLEDs, "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." ); | 83 CLIDict_Entry( readLEDs, "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." ); |
83 CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); | 84 CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." ); |
84 CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); | 85 CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." ); |
85 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" ); | 86 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" ); |
87 CLIDict_Entry( usbInitTime, "Displays the time in ms from usb_init() till the last setup call." ); | |
86 | 88 |
87 CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { | 89 CLIDict_Def( outputCLIDict, "USB Module Commands" ) = { |
88 CLIDict_Item( kbdProtocol ), | 90 CLIDict_Item( kbdProtocol ), |
89 CLIDict_Item( outputDebug ), | 91 CLIDict_Item( outputDebug ), |
90 CLIDict_Item( readLEDs ), | 92 CLIDict_Item( readLEDs ), |
91 CLIDict_Item( sendKeys ), | 93 CLIDict_Item( sendKeys ), |
92 CLIDict_Item( setKeys ), | 94 CLIDict_Item( setKeys ), |
93 CLIDict_Item( setMod ), | 95 CLIDict_Item( setMod ), |
96 CLIDict_Item( usbInitTime ), | |
94 { 0, 0, 0 } // Null entry for dictionary end | 97 { 0, 0, 0 } // Null entry for dictionary end |
95 }; | 98 }; |
96 | 99 |
97 | 100 |
98 // Which modifier keys are currently pressed | 101 // Which modifier keys are currently pressed |
160 | 163 |
161 // mA - Set by USB module (if exists) | 164 // mA - Set by USB module (if exists) |
162 // Initially 100 mA, but may be negotiated higher (e.g. 500 mA) | 165 // Initially 100 mA, but may be negotiated higher (e.g. 500 mA) |
163 uint16_t Output_USBCurrent_Available = 0; | 166 uint16_t Output_USBCurrent_Available = 0; |
164 | 167 |
168 // USB Init Time (ms) - usb_init() | |
169 volatile uint32_t USBInit_TimeStart; | |
170 volatile uint32_t USBInit_TimeEnd; | |
171 volatile uint16_t USBInit_Ticks; | |
172 | |
165 | 173 |
166 | 174 |
167 // ----- Capabilities ----- | 175 // ----- Capabilities ----- |
168 | 176 |
169 // Set Boot Keyboard Protocol | 177 // Set Boot Keyboard Protocol |
170 void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 178 void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
171 { | 179 { |
180 #if enableKeyboard_define == 1 | |
172 // Display capability name | 181 // Display capability name |
173 if ( stateType == 0xFF && state == 0xFF ) | 182 if ( stateType == 0xFF && state == 0xFF ) |
174 { | 183 { |
175 print("Output_kbdProtocolBoot()"); | 184 print("Output_kbdProtocolBoot()"); |
176 return; | 185 return; |
188 // Flush the key buffers | 197 // Flush the key buffers |
189 Output_flushBuffers(); | 198 Output_flushBuffers(); |
190 | 199 |
191 // Set the keyboard protocol to Boot Mode | 200 // Set the keyboard protocol to Boot Mode |
192 USBKeys_Protocol = 0; | 201 USBKeys_Protocol = 0; |
202 #endif | |
193 } | 203 } |
194 | 204 |
195 | 205 |
196 // Set NKRO Keyboard Protocol | 206 // Set NKRO Keyboard Protocol |
197 void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 207 void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
198 { | 208 { |
209 #if enableKeyboard_define == 1 | |
199 // Display capability name | 210 // Display capability name |
200 if ( stateType == 0xFF && state == 0xFF ) | 211 if ( stateType == 0xFF && state == 0xFF ) |
201 { | 212 { |
202 print("Output_kbdProtocolNKRO()"); | 213 print("Output_kbdProtocolNKRO()"); |
203 return; | 214 return; |
215 // Flush the key buffers | 226 // Flush the key buffers |
216 Output_flushBuffers(); | 227 Output_flushBuffers(); |
217 | 228 |
218 // Set the keyboard protocol to NKRO Mode | 229 // Set the keyboard protocol to NKRO Mode |
219 USBKeys_Protocol = 1; | 230 USBKeys_Protocol = 1; |
231 #endif | |
220 } | 232 } |
221 | 233 |
222 | 234 |
223 // Toggle Keyboard Protocol | 235 // Toggle Keyboard Protocol |
224 void Output_toggleKbdProtocol_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 236 void Output_toggleKbdProtocol_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
225 { | 237 { |
238 #if enableKeyboard_define == 1 | |
226 // Display capability name | 239 // Display capability name |
227 if ( stateType == 0xFF && state == 0xFF ) | 240 if ( stateType == 0xFF && state == 0xFF ) |
228 { | 241 { |
229 print("Output_toggleKbdProtocol()"); | 242 print("Output_toggleKbdProtocol()"); |
230 return; | 243 return; |
237 Output_flushBuffers(); | 250 Output_flushBuffers(); |
238 | 251 |
239 // Toggle the keyboard protocol Mode | 252 // Toggle the keyboard protocol Mode |
240 USBKeys_Protocol = !USBKeys_Protocol; | 253 USBKeys_Protocol = !USBKeys_Protocol; |
241 } | 254 } |
255 #endif | |
242 } | 256 } |
243 | 257 |
244 | 258 |
245 // Sends a Consumer Control code to the USB Output buffer | 259 // Sends a Consumer Control code to the USB Output buffer |
246 void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 260 void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
247 { | 261 { |
262 #if enableKeyboard_define == 1 | |
248 // Display capability name | 263 // Display capability name |
249 if ( stateType == 0xFF && state == 0xFF ) | 264 if ( stateType == 0xFF && state == 0xFF ) |
250 { | 265 { |
251 print("Output_consCtrlSend(consCode)"); | 266 print("Output_consCtrlSend(consCode)"); |
252 return; | 267 return; |
271 return; | 286 return; |
272 } | 287 } |
273 | 288 |
274 // Set consumer control code | 289 // Set consumer control code |
275 USBKeys_ConsCtrl = *(uint16_t*)(&args[0]); | 290 USBKeys_ConsCtrl = *(uint16_t*)(&args[0]); |
291 #endif | |
276 } | 292 } |
277 | 293 |
278 | 294 |
279 // Ignores the given key status update | 295 // Ignores the given key status update |
280 // Used to prevent fall-through, this is the None keyword in KLL | 296 // Used to prevent fall-through, this is the None keyword in KLL |
292 | 308 |
293 | 309 |
294 // Sends a System Control code to the USB Output buffer | 310 // Sends a System Control code to the USB Output buffer |
295 void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 311 void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
296 { | 312 { |
313 #if enableKeyboard_define == 1 | |
297 // Display capability name | 314 // Display capability name |
298 if ( stateType == 0xFF && state == 0xFF ) | 315 if ( stateType == 0xFF && state == 0xFF ) |
299 { | 316 { |
300 print("Output_sysCtrlSend(sysCode)"); | 317 print("Output_sysCtrlSend(sysCode)"); |
301 return; | 318 return; |
320 return; | 337 return; |
321 } | 338 } |
322 | 339 |
323 // Set system control code | 340 // Set system control code |
324 USBKeys_SysCtrl = args[0]; | 341 USBKeys_SysCtrl = args[0]; |
342 #endif | |
325 } | 343 } |
326 | 344 |
327 | 345 |
328 // Adds a single USB Code to the USB Output buffer | 346 // Adds a single USB Code to the USB Output buffer |
329 // Argument #1: USB Code | 347 // Argument #1: USB Code |
330 void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 348 void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
331 { | 349 { |
350 #if enableKeyboard_define == 1 | |
332 // Display capability name | 351 // Display capability name |
333 if ( stateType == 0xFF && state == 0xFF ) | 352 if ( stateType == 0xFF && state == 0xFF ) |
334 { | 353 { |
335 print("Output_usbCodeSend(usbCode)"); | 354 print("Output_usbCodeSend(usbCode)"); |
336 return; | 355 return; |
527 USBKeys_Sent++; | 546 USBKeys_Sent++; |
528 } | 547 } |
529 | 548 |
530 break; | 549 break; |
531 } | 550 } |
551 #endif | |
532 } | 552 } |
533 | 553 |
534 void Output_flashMode_capability( uint8_t state, uint8_t stateType, uint8_t *args ) | 554 void Output_flashMode_capability( uint8_t state, uint8_t stateType, uint8_t *args ) |
535 { | 555 { |
536 // Display capability name | 556 // Display capability name |
542 | 562 |
543 // Start flash mode | 563 // Start flash mode |
544 Output_firmwareReload(); | 564 Output_firmwareReload(); |
545 } | 565 } |
546 | 566 |
567 #if enableMouse_define == 1 | |
547 // Sends a mouse command over the USB Output buffer | 568 // Sends a mouse command over the USB Output buffer |
548 // XXX This function *will* be changing in the future | 569 // XXX This function *will* be changing in the future |
549 // If you use it, be prepared that your .kll files will break in the future (post KLL 0.5) | 570 // If you use it, be prepared that your .kll files will break in the future (post KLL 0.5) |
550 // Argument #1: USB Mouse Button (16 bit) | 571 // Argument #1: USB Mouse Button (16 bit) |
551 // Argument #2: USB X Axis (16 bit) relative | 572 // Argument #2: USB X Axis (16 bit) relative |
598 USBMouse_Changed |= USBMouseChangeState_Buttons; | 619 USBMouse_Changed |= USBMouseChangeState_Buttons; |
599 | 620 |
600 if ( mouse_x || mouse_y ) | 621 if ( mouse_x || mouse_y ) |
601 USBMouse_Changed |= USBMouseChangeState_Relative; | 622 USBMouse_Changed |= USBMouseChangeState_Relative; |
602 } | 623 } |
624 #endif | |
603 | 625 |
604 | 626 |
605 | 627 |
606 // ----- Functions ----- | 628 // ----- Functions ----- |
607 | 629 |
640 inline void Output_send() | 662 inline void Output_send() |
641 { | 663 { |
642 // USB status checks | 664 // USB status checks |
643 // Non-standard USB state manipulation, usually does nothing | 665 // Non-standard USB state manipulation, usually does nothing |
644 usb_device_check(); | 666 usb_device_check(); |
645 | |
646 // Boot Mode Only, unset stale keys | |
647 if ( USBKeys_Protocol == 0 ) | |
648 for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | |
649 USBKeys_Keys[c] = 0; | |
650 | 667 |
651 // XXX - Behaves oddly on Mac OSX, might help with corrupted packets specific to OSX? -HaaTa | 668 // XXX - Behaves oddly on Mac OSX, might help with corrupted packets specific to OSX? -HaaTa |
652 /* | 669 /* |
653 // Check if idle count has been exceed, this forces usb_keyboard_send and usb_mouse_send to update | 670 // Check if idle count has been exceed, this forces usb_keyboard_send and usb_mouse_send to update |
654 // TODO Add joystick as well (may be endpoint specific, currently not kept track of) | 671 // TODO Add joystick as well (may be endpoint specific, currently not kept track of) |
659 USBKeys_Changed = USBKeyChangeState_All; | 676 USBKeys_Changed = USBKeyChangeState_All; |
660 USBMouse_Changed = USBMouseChangeState_All; | 677 USBMouse_Changed = USBMouseChangeState_All; |
661 } | 678 } |
662 */ | 679 */ |
663 | 680 |
681 #if enableMouse_define == 1 | |
664 // Process mouse actions | 682 // Process mouse actions |
665 while ( USBMouse_Changed ) | 683 while ( USBMouse_Changed ) |
666 usb_mouse_send(); | 684 usb_mouse_send(); |
685 #endif | |
686 | |
687 #if enableKeyboard_define == 1 | |
688 // Boot Mode Only, unset stale keys | |
689 if ( USBKeys_Protocol == 0 ) | |
690 for ( uint8_t c = USBKeys_Sent; c < USB_BOOT_MAX_KEYS; c++ ) | |
691 USBKeys_Keys[c] = 0; | |
667 | 692 |
668 // Send keypresses while there are pending changes | 693 // Send keypresses while there are pending changes |
669 while ( USBKeys_Changed ) | 694 while ( USBKeys_Changed ) |
670 usb_keyboard_send(); | 695 usb_keyboard_send(); |
671 | 696 |
682 break; | 707 break; |
683 case 1: // NKRO Mode | 708 case 1: // NKRO Mode |
684 Scan_finishedWithOutput( USBKeys_Sent ); | 709 Scan_finishedWithOutput( USBKeys_Sent ); |
685 break; | 710 break; |
686 } | 711 } |
712 #endif | |
687 } | 713 } |
688 | 714 |
689 | 715 |
690 // Sets the device into firmware reload mode | 716 // Sets the device into firmware reload mode |
691 inline void Output_firmwareReload() | 717 inline void Output_firmwareReload() |
695 | 721 |
696 | 722 |
697 // USB Input buffer available | 723 // USB Input buffer available |
698 inline unsigned int Output_availablechar() | 724 inline unsigned int Output_availablechar() |
699 { | 725 { |
726 #if enableVirtualSerialPort_define == 1 | |
700 return usb_serial_available(); | 727 return usb_serial_available(); |
728 #else | |
729 return 0; | |
730 #endif | |
701 } | 731 } |
702 | 732 |
703 | 733 |
704 // USB Get Character from input buffer | 734 // USB Get Character from input buffer |
705 inline int Output_getchar() | 735 inline int Output_getchar() |
706 { | 736 { |
737 #if enableVirtualSerialPort_define == 1 | |
707 // XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes) (AVR) | 738 // XXX Make sure to check output_availablechar() first! Information is lost with the cast (error codes) (AVR) |
708 return (int)usb_serial_getchar(); | 739 return (int)usb_serial_getchar(); |
740 #else | |
741 return 0; | |
742 #endif | |
709 } | 743 } |
710 | 744 |
711 | 745 |
712 // USB Send Character to output buffer | 746 // USB Send Character to output buffer |
713 inline int Output_putchar( char c ) | 747 inline int Output_putchar( char c ) |
714 { | 748 { |
749 #if enableVirtualSerialPort_define == 1 | |
715 return usb_serial_putchar( c ); | 750 return usb_serial_putchar( c ); |
751 #else | |
752 return 0; | |
753 #endif | |
716 } | 754 } |
717 | 755 |
718 | 756 |
719 // USB Send String to output buffer, null terminated | 757 // USB Send String to output buffer, null terminated |
720 inline int Output_putstr( char* str ) | 758 inline int Output_putstr( char* str ) |
721 { | 759 { |
760 #if enableVirtualSerialPort_define == 1 | |
722 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | 761 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR |
723 uint16_t count = 0; | 762 uint16_t count = 0; |
724 #elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM | 763 #elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM |
725 uint32_t count = 0; | 764 uint32_t count = 0; |
726 #endif | 765 #endif |
727 // Count characters until NULL character, then send the amount counted | 766 // Count characters until NULL character, then send the amount counted |
728 while ( str[count] != '\0' ) | 767 while ( str[count] != '\0' ) |
729 count++; | 768 count++; |
730 | 769 |
731 return usb_serial_write( str, count ); | 770 return usb_serial_write( str, count ); |
771 #else | |
772 return 0; | |
773 #endif | |
732 } | 774 } |
733 | 775 |
734 | 776 |
735 // Soft Chip Reset | 777 // Soft Chip Reset |
736 inline void Output_softReset() | 778 inline void Output_softReset() |
737 { | 779 { |
738 usb_device_software_reset(); | 780 usb_device_software_reset(); |
781 } | |
782 | |
783 | |
784 // USB RawIO buffer available | |
785 inline unsigned int Output_rawio_availablechar() | |
786 { | |
787 #if enableRawIO_define == 1 | |
788 return usb_rawio_available(); | |
789 #else | |
790 return 0; | |
791 #endif | |
792 } | |
793 | |
794 | |
795 // USB RawIO get buffer | |
796 // XXX Must be a 64 byte buffer | |
797 inline int Output_rawio_getbuffer( char* buffer ) | |
798 { | |
799 #if enableRawIO_define == 1 | |
800 // No timeout, fail immediately | |
801 return usb_rawio_rx( (void*)buffer, 0 ); | |
802 #else | |
803 return 0; | |
804 #endif | |
805 } | |
806 | |
807 | |
808 // USB RawIO send buffer | |
809 // XXX Must be a 64 byte buffer | |
810 inline int Output_rawio_sendbuffer( char* buffer ) | |
811 { | |
812 #if enableRawIO_define == 1 | |
813 // No timeout, fail immediately | |
814 return usb_rawio_tx( (void*)buffer, 0 ); | |
815 #else | |
816 return 0; | |
817 #endif | |
739 } | 818 } |
740 | 819 |
741 | 820 |
742 // Update USB current (mA) | 821 // Update USB current (mA) |
743 // Triggers power change event | 822 // Triggers power change event |
890 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); | 969 CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr ); |
891 | 970 |
892 USBKeys_ModifiersCLI = numToInt( arg1Ptr ); | 971 USBKeys_ModifiersCLI = numToInt( arg1Ptr ); |
893 } | 972 } |
894 | 973 |
974 void cliFunc_usbInitTime( char* args ) | |
975 { | |
976 // Calculate overall USB initialization time | |
977 // XXX A protocol analyzer will be more accurate, however, this is built-in and easier to collect data | |
978 print(NL); | |
979 info_msg("USB Init Time: "); | |
980 printInt32( USBInit_TimeEnd - USBInit_TimeStart ); | |
981 print(" ms - "); | |
982 printInt16( USBInit_Ticks ); | |
983 print(" ticks"); | |
984 } | |
985 |