diff options
Diffstat (limited to 'protocol/lufa/lufa.c')
| -rw-r--r-- | protocol/lufa/lufa.c | 226 |
1 files changed, 224 insertions, 2 deletions
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index cdfc7bc6a..03b13f404 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include "descriptor.h" | 52 | #include "descriptor.h" |
| 53 | #include "lufa.h" | 53 | #include "lufa.h" |
| 54 | 54 | ||
| 55 | |||
| 55 | uint8_t keyboard_idle = 0; | 56 | uint8_t keyboard_idle = 0; |
| 56 | uint8_t keyboard_protocol = 1; | 57 | uint8_t keyboard_protocol = 1; |
| 57 | static uint8_t keyboard_led_stats = 0; | 58 | static uint8_t keyboard_led_stats = 0; |
| @@ -65,14 +66,60 @@ static void send_keyboard(report_keyboard_t *report); | |||
| 65 | static void send_mouse(report_mouse_t *report); | 66 | static void send_mouse(report_mouse_t *report); |
| 66 | static void send_system(uint16_t data); | 67 | static void send_system(uint16_t data); |
| 67 | static void send_consumer(uint16_t data); | 68 | static void send_consumer(uint16_t data); |
| 69 | |||
| 70 | #ifdef MIDI_ENABLE | ||
| 71 | void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2); | ||
| 72 | void usb_get_midi(MidiDevice * device); | ||
| 73 | void midi_usb_init(MidiDevice * device); | ||
| 74 | #endif | ||
| 75 | |||
| 68 | host_driver_t lufa_driver = { | 76 | host_driver_t lufa_driver = { |
| 69 | keyboard_leds, | 77 | keyboard_leds, |
| 70 | send_keyboard, | 78 | send_keyboard, |
| 71 | send_mouse, | 79 | send_mouse, |
| 72 | send_system, | 80 | send_system, |
| 73 | send_consumer | 81 | send_consumer, |
| 82 | #ifdef MIDI_ENABLE | ||
| 83 | usb_send_func, | ||
| 84 | usb_get_midi, | ||
| 85 | midi_usb_init, | ||
| 86 | #endif | ||
| 87 | |||
| 88 | }; | ||
| 89 | |||
| 90 | void SetupHardware(void); | ||
| 91 | |||
| 92 | |||
| 93 | USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface = | ||
| 94 | { | ||
| 95 | .Config = | ||
| 96 | { | ||
| 97 | .StreamingInterfaceNumber = MIDI2_INTERFACE, | ||
| 98 | .DataINEndpoint = | ||
| 99 | { | ||
| 100 | .Address = (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM), | ||
| 101 | .Size = MIDI_STREAM_EPSIZE, | ||
| 102 | .Banks = 1, | ||
| 103 | }, | ||
| 104 | .DataOUTEndpoint = | ||
| 105 | { | ||
| 106 | .Address = (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM), | ||
| 107 | .Size = MIDI_STREAM_EPSIZE, | ||
| 108 | .Banks = 1, | ||
| 109 | }, | ||
| 110 | }, | ||
| 74 | }; | 111 | }; |
| 75 | 112 | ||
| 113 | #define SYSEX_START_OR_CONT 0x40 | ||
| 114 | #define SYSEX_ENDS_IN_1 0x50 | ||
| 115 | #define SYSEX_ENDS_IN_2 0x60 | ||
| 116 | #define SYSEX_ENDS_IN_3 0x70 | ||
| 117 | |||
| 118 | #define SYS_COMMON_1 0x50 | ||
| 119 | #define SYS_COMMON_2 0x20 | ||
| 120 | #define SYS_COMMON_3 0x30 | ||
| 121 | |||
| 122 | |||
| 76 | 123 | ||
| 77 | /******************************************************************************* | 124 | /******************************************************************************* |
| 78 | * Console | 125 | * Console |
| @@ -240,8 +287,20 @@ void EVENT_USB_Device_ConfigurationChanged(void) | |||
| 240 | ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 287 | ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, |
| 241 | NKRO_EPSIZE, ENDPOINT_BANK_SINGLE); | 288 | NKRO_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 242 | #endif | 289 | #endif |
| 290 | |||
| 291 | #ifdef MIDI_ENABLE | ||
| 292 | ConfigSuccess &= MIDI_Device_ConfigureEndpoints(&USB_MIDI_Interface); | ||
| 293 | |||
| 294 | // ConfigSuccess &= ENDPOINT_CONFIG(MIDI_STREAM_IN_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_IN, | ||
| 295 | // MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); | ||
| 296 | // ConfigSuccess &= ENDPOINT_CONFIG(MIDI_STREAM_OUT_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_OUT, | ||
| 297 | // MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); | ||
| 298 | #endif | ||
| 299 | |||
| 243 | } | 300 | } |
| 244 | 301 | ||
| 302 | |||
| 303 | |||
| 245 | /* | 304 | /* |
| 246 | Appendix G: HID Request Support Requirements | 305 | Appendix G: HID Request Support Requirements |
| 247 | 306 | ||
| @@ -263,6 +322,8 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 263 | uint8_t* ReportData = NULL; | 322 | uint8_t* ReportData = NULL; |
| 264 | uint8_t ReportSize = 0; | 323 | uint8_t ReportSize = 0; |
| 265 | 324 | ||
| 325 | MIDI_Device_ProcessControlRequest(&USB_MIDI_Interface); | ||
| 326 | |||
| 266 | /* Handle HID Class specific requests */ | 327 | /* Handle HID Class specific requests */ |
| 267 | switch (USB_ControlRequest.bRequest) | 328 | switch (USB_ControlRequest.bRequest) |
| 268 | { | 329 | { |
| @@ -541,10 +602,117 @@ int8_t sendchar(uint8_t c) | |||
| 541 | #endif | 602 | #endif |
| 542 | 603 | ||
| 543 | 604 | ||
| 605 | |||
| 606 | |||
| 607 | |||
| 608 | #ifdef MIDI_ENABLE | ||
| 609 | void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) { | ||
| 610 | MIDI_EventPacket_t event; | ||
| 611 | event.Data1 = byte0; | ||
| 612 | event.Data2 = byte1; | ||
| 613 | event.Data3 = byte2; | ||
| 614 | |||
| 615 | uint8_t cable = 0; | ||
| 616 | |||
| 617 | // Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM); | ||
| 618 | |||
| 619 | //if the length is undefined we assume it is a SYSEX message | ||
| 620 | if (midi_packet_length(byte0) == UNDEFINED) { | ||
| 621 | switch(cnt) { | ||
| 622 | case 3: | ||
| 623 | if (byte2 == SYSEX_END) | ||
| 624 | event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3); | ||
| 625 | else | ||
| 626 | event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT); | ||
| 627 | break; | ||
| 628 | case 2: | ||
| 629 | if (byte1 == SYSEX_END) | ||
| 630 | event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2); | ||
| 631 | else | ||
| 632 | event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT); | ||
| 633 | break; | ||
| 634 | case 1: | ||
| 635 | if (byte0 == SYSEX_END) | ||
| 636 | event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1); | ||
| 637 | else | ||
| 638 | event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT); | ||
| 639 | break; | ||
| 640 | default: | ||
| 641 | return; //invalid cnt | ||
| 642 | } | ||
| 643 | } else { | ||
| 644 | //deal with 'system common' messages | ||
| 645 | //TODO are there any more? | ||
| 646 | switch(byte0 & 0xF0){ | ||
| 647 | case MIDI_SONGPOSITION: | ||
| 648 | event.Event = MIDI_EVENT(cable, SYS_COMMON_3); | ||
| 649 | break; | ||
| 650 | case MIDI_SONGSELECT: | ||
| 651 | case MIDI_TC_QUARTERFRAME: | ||
| 652 | event.Event = MIDI_EVENT(cable, SYS_COMMON_2); | ||
| 653 | break; | ||
| 654 | default: | ||
| 655 | event.Event = MIDI_EVENT(cable, byte0); | ||
| 656 | break; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | // Endpoint_Write_Stream_LE(&event, sizeof(event), NULL); | ||
| 661 | // Endpoint_ClearIN(); | ||
| 662 | |||
| 663 | MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event); | ||
| 664 | MIDI_Device_Flush(&USB_MIDI_Interface); | ||
| 665 | MIDI_Device_USBTask(&USB_MIDI_Interface); | ||
| 666 | USB_USBTask(); | ||
| 667 | } | ||
| 668 | |||
| 669 | void usb_get_midi(MidiDevice * device) { | ||
| 670 | MIDI_EventPacket_t event; | ||
| 671 | while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) { | ||
| 672 | |||
| 673 | midi_packet_length_t length = midi_packet_length(event.Data1); | ||
| 674 | uint8_t input[3]; | ||
| 675 | input[0] = event.Data1; | ||
| 676 | input[1] = event.Data2; | ||
| 677 | input[2] = event.Data3; | ||
| 678 | if (length == UNDEFINED) { | ||
| 679 | //sysex | ||
| 680 | if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) { | ||
| 681 | length = 3; | ||
| 682 | } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) { | ||
| 683 | length = 2; | ||
| 684 | } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) { | ||
| 685 | length = 1; | ||
| 686 | } else { | ||
| 687 | //XXX what to do? | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | //pass the data to the device input function | ||
| 692 | if (length != UNDEFINED) | ||
| 693 | midi_device_input(device, length, input); | ||
| 694 | } | ||
| 695 | MIDI_Device_USBTask(&USB_MIDI_Interface); | ||
| 696 | USB_USBTask(); | ||
| 697 | } | ||
| 698 | |||
| 699 | void midi_usb_init(MidiDevice * device){ | ||
| 700 | midi_device_init(device); | ||
| 701 | midi_device_set_send_func(device, usb_send_func); | ||
| 702 | midi_device_set_pre_input_process_func(device, usb_get_midi); | ||
| 703 | |||
| 704 | SetupHardware(); | ||
| 705 | sei(); | ||
| 706 | } | ||
| 707 | #endif | ||
| 708 | |||
| 709 | |||
| 710 | |||
| 711 | |||
| 544 | /******************************************************************************* | 712 | /******************************************************************************* |
| 545 | * main | 713 | * main |
| 546 | ******************************************************************************/ | 714 | ******************************************************************************/ |
| 547 | static void SetupHardware(void) | 715 | void SetupHardware(void) |
| 548 | { | 716 | { |
| 549 | /* Disable watchdog if enabled by bootloader/fuses */ | 717 | /* Disable watchdog if enabled by bootloader/fuses */ |
| 550 | MCUSR &= ~(1 << WDRF); | 718 | MCUSR &= ~(1 << WDRF); |
| @@ -563,12 +731,41 @@ static void SetupHardware(void) | |||
| 563 | print_set_sendchar(sendchar); | 731 | print_set_sendchar(sendchar); |
| 564 | } | 732 | } |
| 565 | 733 | ||
| 734 | #ifdef MIDI_ENABLE | ||
| 735 | void fallthrough_callback(MidiDevice * device, | ||
| 736 | uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2); | ||
| 737 | void cc_callback(MidiDevice * device, | ||
| 738 | uint8_t chan, uint8_t num, uint8_t val); | ||
| 739 | void sysex_callback(MidiDevice * device, | ||
| 740 | uint16_t start, uint8_t length, uint8_t * data); | ||
| 741 | #endif | ||
| 742 | |||
| 566 | int main(void) __attribute__ ((weak)); | 743 | int main(void) __attribute__ ((weak)); |
| 567 | int main(void) | 744 | int main(void) |
| 568 | { | 745 | { |
| 746 | //setup the device | ||
| 747 | |||
| 748 | #ifdef MIDI_ENABLE | ||
| 749 | midi_device_init(&midi_device); | ||
| 750 | midi_device_set_send_func(&midi_device, usb_send_func); | ||
| 751 | midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); | ||
| 752 | #endif | ||
| 753 | |||
| 569 | SetupHardware(); | 754 | SetupHardware(); |
| 570 | sei(); | 755 | sei(); |
| 571 | 756 | ||
| 757 | #ifdef MIDI_ENABLE | ||
| 758 | midi_register_fallthrough_callback(&midi_device, fallthrough_callback); | ||
| 759 | midi_register_cc_callback(&midi_device, cc_callback); | ||
| 760 | midi_register_sysex_callback(&midi_device, sysex_callback); | ||
| 761 | |||
| 762 | midi_send_cc(&midi_device, 0, 1, 2); | ||
| 763 | midi_send_cc(&midi_device, 15, 1, 0); | ||
| 764 | midi_send_noteon(&midi_device, 0, 64, 127); | ||
| 765 | midi_send_noteoff(&midi_device, 0, 64, 127); | ||
| 766 | #endif | ||
| 767 | |||
| 768 | |||
| 572 | /* wait for USB startup & debug output */ | 769 | /* wait for USB startup & debug output */ |
| 573 | while (USB_DeviceState != DEVICE_STATE_Configured) { | 770 | while (USB_DeviceState != DEVICE_STATE_Configured) { |
| 574 | #if defined(INTERRUPT_CONTROL_ENDPOINT) | 771 | #if defined(INTERRUPT_CONTROL_ENDPOINT) |
| @@ -598,8 +795,33 @@ int main(void) | |||
| 598 | 795 | ||
| 599 | keyboard_task(); | 796 | keyboard_task(); |
| 600 | 797 | ||
| 798 | #ifdef MIDI_ENABLE | ||
| 799 | midi_device_process(&midi_device); | ||
| 800 | #endif | ||
| 801 | |||
| 601 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) | 802 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) |
| 602 | USB_USBTask(); | 803 | USB_USBTask(); |
| 603 | #endif | 804 | #endif |
| 604 | } | 805 | } |
| 605 | } | 806 | } |
| 807 | |||
| 808 | #ifdef MIDI_ENABLE | ||
| 809 | //echo data back | ||
| 810 | void fallthrough_callback(MidiDevice * device, | ||
| 811 | uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){ | ||
| 812 | //pass the data back to the device, using the general purpose send data | ||
| 813 | //function, any bytes after cnt are ignored | ||
| 814 | } | ||
| 815 | |||
| 816 | void cc_callback(MidiDevice * device, | ||
| 817 | uint8_t chan, uint8_t num, uint8_t val) { | ||
| 818 | //sending it back on the next channel | ||
| 819 | midi_send_cc(device, (chan + 1) % 16, num, val); | ||
| 820 | } | ||
| 821 | |||
| 822 | void sysex_callback(MidiDevice * device, | ||
| 823 | uint16_t start, uint8_t length, uint8_t * data) { | ||
| 824 | for (int i = 0; i < length; i++) | ||
| 825 | midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i)); | ||
| 826 | } | ||
| 827 | #endif | ||
