aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/lufa/lufa.c
diff options
context:
space:
mode:
authorJames Laird-Wah <james@laird-wah.net>2018-11-16 17:22:05 +1100
committerDrashna Jaelre <drashna@live.com>2018-11-15 22:22:05 -0800
commit39bd760faf2666e91d6dc5b199f02fa3206c6acd (patch)
tree12db265881a0d358bb0e186689a7b20a81c37bc6 /tmk_core/protocol/lufa/lufa.c
parent46cf8cc9b33a3c8bdbb0ce7df7f48f28e4d979a5 (diff)
downloadqmk_firmware-39bd760faf2666e91d6dc5b199f02fa3206c6acd.tar.gz
qmk_firmware-39bd760faf2666e91d6dc5b199f02fa3206c6acd.zip
Use a single endpoint for HID reports (#3951)
* Unify multiple HID interfaces into one This reduces the number of USB endpoints required, which frees them up for other things. NKRO and EXTRAKEY always use the shared endpoint. By default, MOUSEKEY also uses it. This means it won't work as a Boot Procotol mouse in some BIOSes, etc. If you really think your keyboard needs to work as a mouse in your BIOS, set MOUSE_SHARED_EP = no in your rules.mk. By default, the core keyboard does not use the shared endpoint, as not all BIOSes are standards compliant and that's one place you don't want to find out your keyboard doesn't work.. If you are really confident, you can set KEYBOARD_SHARED_EP = yes to use the shared endpoint here too. * unify endpoints: ChibiOS protocol implementation * fixup: missing #ifdef EXTRAKEY_ENABLEs broke build on AVR with EXTRAKEY disabled * endpoints: restore error when too many endpoints required * lufa: wait up to 10ms to send keyboard input This avoids packets being dropped when two reports are sent in quick succession (eg. releasing a dual role key). * endpoints: fix compile on ARM_ATSAM * endpoint: ARM_ATSAM fixes No longer use wrong or unexpected endpoint IDs * endpoints: accommodate VUSB protocol V-USB has its own, understandably simple ideas about the report formats. It already blasts the mouse and extrakeys through one endpoint with report IDs. We just stay out of its way. * endpoints: document new endpoint configuration options * endpoints: respect keyboard_report->mods in NKRO The caller(s) of host_keyboard_send expect to be able to just drop modifiers in the mods field and not worry about whether NKRO is in use. This is a good thing. So we just shift it over if needs be. * endpoints: report.c: update for new keyboard_report format
Diffstat (limited to 'tmk_core/protocol/lufa/lufa.c')
-rw-r--r--tmk_core/protocol/lufa/lufa.c92
1 files changed, 50 insertions, 42 deletions
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 95e0b95b2..e88e6f34a 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -409,19 +409,21 @@ void EVENT_USB_Device_ConfigurationChanged(void)
409 bool ConfigSuccess = true; 409 bool ConfigSuccess = true;
410 410
411 /* Setup Keyboard HID Report Endpoints */ 411 /* Setup Keyboard HID Report Endpoints */
412#ifndef KEYBOARD_SHARED_EP
412 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, 413 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
413 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE); 414 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
415#endif
414 416
415#ifdef MOUSE_ENABLE 417#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
416 /* Setup Mouse HID Report Endpoint */ 418 /* Setup Mouse HID Report Endpoint */
417 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, 419 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
418 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE); 420 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
419#endif 421#endif
420 422
421#ifdef EXTRAKEY_ENABLE 423#ifdef SHARED_EP_ENABLE
422 /* Setup Extra HID Report Endpoint */ 424 /* Setup Shared HID Report Endpoint */
423 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, 425 ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
424 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE); 426 SHARED_EPSIZE, ENDPOINT_BANK_SINGLE);
425#endif 427#endif
426 428
427#ifdef RAW_ENABLE 429#ifdef RAW_ENABLE
@@ -442,12 +444,6 @@ void EVENT_USB_Device_ConfigurationChanged(void)
442#endif 444#endif
443#endif 445#endif
444 446
445#ifdef NKRO_ENABLE
446 /* Setup NKRO HID Report Endpoints */
447 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
448 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
449#endif
450
451#ifdef MIDI_ENABLE 447#ifdef MIDI_ENABLE
452 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 448 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
453 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); 449 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
@@ -512,8 +508,8 @@ void EVENT_USB_Device_ControlRequest(void)
512 // Interface 508 // Interface
513 switch (USB_ControlRequest.wIndex) { 509 switch (USB_ControlRequest.wIndex) {
514 case KEYBOARD_INTERFACE: 510 case KEYBOARD_INTERFACE:
515#ifdef NKRO_ENABLE 511#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
516 case NKRO_INTERFACE: 512 case SHARED_INTERFACE:
517#endif 513#endif
518 Endpoint_ClearSETUP(); 514 Endpoint_ClearSETUP();
519 515
@@ -521,7 +517,17 @@ void EVENT_USB_Device_ControlRequest(void)
521 if (USB_DeviceState == DEVICE_STATE_Unattached) 517 if (USB_DeviceState == DEVICE_STATE_Unattached)
522 return; 518 return;
523 } 519 }
520#if defined(SHARED_EP_ENABLE)
521 uint8_t report_id = REPORT_ID_KEYBOARD;
522 if (keyboard_protocol) {
523 report_id = Endpoint_Read_8();
524 }
525 if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
526 keyboard_led_stats = Endpoint_Read_8();
527 }
528#else
524 keyboard_led_stats = Endpoint_Read_8(); 529 keyboard_led_stats = Endpoint_Read_8();
530#endif
525 531
526 Endpoint_ClearOUT(); 532 Endpoint_ClearOUT();
527 Endpoint_ClearStatusStage(); 533 Endpoint_ClearStatusStage();
@@ -612,16 +618,20 @@ static void send_keyboard(report_keyboard_t *report)
612 #ifdef MODULE_ADAFRUIT_BLE 618 #ifdef MODULE_ADAFRUIT_BLE
613 adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys)); 619 adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
614 #elif MODULE_RN42 620 #elif MODULE_RN42
615 bluefruit_serial_send(0xFD); 621 bluefruit_serial_send(0xFD);
616 bluefruit_serial_send(0x09); 622 bluefruit_serial_send(0x09);
617 bluefruit_serial_send(0x01); 623 bluefruit_serial_send(0x01);
618 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) { 624 bluefruit_serial_send(report->mods);
619 bluefruit_serial_send(report->raw[i]); 625 bluefruit_serial_send(report->reserved);
620 } 626 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
627 bluefruit_serial_send(report->keys[i]);
628 }
621 #else 629 #else
622 bluefruit_serial_send(0xFD); 630 bluefruit_serial_send(0xFD);
623 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) { 631 bluefruit_serial_send(report->mods);
624 bluefruit_serial_send(report->raw[i]); 632 bluefruit_serial_send(report->reserved);
633 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
634 bluefruit_serial_send(report->keys[i]);
625 } 635 }
626 #endif 636 #endif
627 } 637 }
@@ -632,30 +642,24 @@ static void send_keyboard(report_keyboard_t *report)
632 } 642 }
633 643
634 /* Select the Keyboard Report Endpoint */ 644 /* Select the Keyboard Report Endpoint */
645 uint8_t ep = KEYBOARD_IN_EPNUM;
646 uint8_t size = KEYBOARD_REPORT_SIZE;
635#ifdef NKRO_ENABLE 647#ifdef NKRO_ENABLE
636 if (keyboard_protocol && keymap_config.nkro) { 648 if (keyboard_protocol && keymap_config.nkro) {
637 /* Report protocol - NKRO */ 649 ep = SHARED_IN_EPNUM;
638 Endpoint_SelectEndpoint(NKRO_IN_EPNUM); 650 size = sizeof(struct nkro_report);
639
640 /* Check if write ready for a polling interval around 1ms */
641 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
642 if (!Endpoint_IsReadWriteAllowed()) return;
643
644 /* Write Keyboard Report Data */
645 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
646 } 651 }
647 else
648#endif 652#endif
649 { 653 Endpoint_SelectEndpoint(ep);
650 /* Boot protocol */ 654 /* Check if write ready for a polling interval around 10ms */
651 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); 655 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
652 656 if (!Endpoint_IsReadWriteAllowed()) return;
653 /* Check if write ready for a polling interval around 10ms */
654 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
655 if (!Endpoint_IsReadWriteAllowed()) return;
656 657
657 /* Write Keyboard Report Data */ 658 /* If we're in Boot Protocol, don't send any report ID or other funky fields */
658 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); 659 if (!keyboard_protocol) {
660 Endpoint_Write_Stream_LE(&report->mods, 8, NULL);
661 } else {
662 Endpoint_Write_Stream_LE(report, size, NULL);
659 } 663 }
660 664
661 /* Finalize the stream transfer to send the last packet */ 665 /* Finalize the stream transfer to send the last packet */
@@ -718,6 +722,7 @@ static void send_mouse(report_mouse_t *report)
718 */ 722 */
719static void send_system(uint16_t data) 723static void send_system(uint16_t data)
720{ 724{
725#ifdef EXTRAKEY_ENABLE
721 uint8_t timeout = 255; 726 uint8_t timeout = 255;
722 727
723 if (USB_DeviceState != DEVICE_STATE_Configured) 728 if (USB_DeviceState != DEVICE_STATE_Configured)
@@ -727,7 +732,7 @@ static void send_system(uint16_t data)
727 .report_id = REPORT_ID_SYSTEM, 732 .report_id = REPORT_ID_SYSTEM,
728 .usage = data - SYSTEM_POWER_DOWN + 1 733 .usage = data - SYSTEM_POWER_DOWN + 1
729 }; 734 };
730 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); 735 Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
731 736
732 /* Check if write ready for a polling interval around 10ms */ 737 /* Check if write ready for a polling interval around 10ms */
733 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); 738 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
@@ -735,6 +740,7 @@ static void send_system(uint16_t data)
735 740
736 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); 741 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
737 Endpoint_ClearIN(); 742 Endpoint_ClearIN();
743#endif
738} 744}
739 745
740/** \brief Send Consumer 746/** \brief Send Consumer
@@ -743,6 +749,7 @@ static void send_system(uint16_t data)
743 */ 749 */
744static void send_consumer(uint16_t data) 750static void send_consumer(uint16_t data)
745{ 751{
752#ifdef EXTRAKEY_ENABLE
746 uint8_t timeout = 255; 753 uint8_t timeout = 255;
747 uint8_t where = where_to_send(); 754 uint8_t where = where_to_send();
748 755
@@ -786,7 +793,7 @@ static void send_consumer(uint16_t data)
786 .report_id = REPORT_ID_CONSUMER, 793 .report_id = REPORT_ID_CONSUMER,
787 .usage = data 794 .usage = data
788 }; 795 };
789 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); 796 Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
790 797
791 /* Check if write ready for a polling interval around 10ms */ 798 /* Check if write ready for a polling interval around 10ms */
792 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); 799 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
@@ -794,6 +801,7 @@ static void send_consumer(uint16_t data)
794 801
795 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); 802 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
796 Endpoint_ClearIN(); 803 Endpoint_ClearIN();
804#endif
797} 805}
798 806
799 807