diff options
Diffstat (limited to 'protocol/lufa/lufa.c')
| -rw-r--r-- | protocol/lufa/lufa.c | 191 |
1 files changed, 189 insertions, 2 deletions
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index cdfc7bc6a..d4c8eb169 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,51 @@ 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 | void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2); | ||
| 70 | void usb_get_midi(MidiDevice * device); | ||
| 71 | void midi_usb_init(MidiDevice * device); | ||
| 68 | host_driver_t lufa_driver = { | 72 | host_driver_t lufa_driver = { |
| 69 | keyboard_leds, | 73 | keyboard_leds, |
| 70 | send_keyboard, | 74 | send_keyboard, |
| 71 | send_mouse, | 75 | send_mouse, |
| 72 | send_system, | 76 | send_system, |
| 73 | send_consumer | 77 | send_consumer, |
| 78 | usb_send_func, | ||
| 79 | usb_get_midi, | ||
| 80 | midi_usb_init | ||
| 81 | }; | ||
| 82 | |||
| 83 | void SetupHardware(void); | ||
| 84 | |||
| 85 | USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface = | ||
| 86 | { | ||
| 87 | .Config = | ||
| 88 | { | ||
| 89 | .StreamingInterfaceNumber = 1, | ||
| 90 | .DataINEndpoint = | ||
| 91 | { | ||
| 92 | .Address = (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM), | ||
| 93 | .Size = MIDI_STREAM_EPSIZE, | ||
| 94 | .Banks = 1, | ||
| 95 | }, | ||
| 96 | .DataOUTEndpoint = | ||
| 97 | { | ||
| 98 | .Address = (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM), | ||
| 99 | .Size = MIDI_STREAM_EPSIZE, | ||
| 100 | .Banks = 1, | ||
| 101 | }, | ||
| 102 | }, | ||
| 74 | }; | 103 | }; |
| 75 | 104 | ||
| 105 | #define SYSEX_START_OR_CONT 0x40 | ||
| 106 | #define SYSEX_ENDS_IN_1 0x50 | ||
| 107 | #define SYSEX_ENDS_IN_2 0x60 | ||
| 108 | #define SYSEX_ENDS_IN_3 0x70 | ||
| 109 | |||
| 110 | #define SYS_COMMON_1 0x50 | ||
| 111 | #define SYS_COMMON_2 0x20 | ||
| 112 | #define SYS_COMMON_3 0x30 | ||
| 113 | |||
| 76 | 114 | ||
| 77 | /******************************************************************************* | 115 | /******************************************************************************* |
| 78 | * Console | 116 | * Console |
| @@ -240,8 +278,13 @@ void EVENT_USB_Device_ConfigurationChanged(void) | |||
| 240 | ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, | 278 | ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, |
| 241 | NKRO_EPSIZE, ENDPOINT_BANK_SINGLE); | 279 | NKRO_EPSIZE, ENDPOINT_BANK_SINGLE); |
| 242 | #endif | 280 | #endif |
| 281 | |||
| 282 | |||
| 283 | ConfigSuccess &= MIDI_Device_ConfigureEndpoints(&USB_MIDI_Interface); | ||
| 243 | } | 284 | } |
| 244 | 285 | ||
| 286 | |||
| 287 | |||
| 245 | /* | 288 | /* |
| 246 | Appendix G: HID Request Support Requirements | 289 | Appendix G: HID Request Support Requirements |
| 247 | 290 | ||
| @@ -263,6 +306,8 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 263 | uint8_t* ReportData = NULL; | 306 | uint8_t* ReportData = NULL; |
| 264 | uint8_t ReportSize = 0; | 307 | uint8_t ReportSize = 0; |
| 265 | 308 | ||
| 309 | MIDI_Device_ProcessControlRequest(&USB_MIDI_Interface); | ||
| 310 | |||
| 266 | /* Handle HID Class specific requests */ | 311 | /* Handle HID Class specific requests */ |
| 267 | switch (USB_ControlRequest.bRequest) | 312 | switch (USB_ControlRequest.bRequest) |
| 268 | { | 313 | { |
| @@ -541,10 +586,109 @@ int8_t sendchar(uint8_t c) | |||
| 541 | #endif | 586 | #endif |
| 542 | 587 | ||
| 543 | 588 | ||
| 589 | |||
| 590 | |||
| 591 | |||
| 592 | void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) { | ||
| 593 | MIDI_EventPacket_t event; | ||
| 594 | event.Data1 = byte0; | ||
| 595 | event.Data2 = byte1; | ||
| 596 | event.Data3 = byte2; | ||
| 597 | |||
| 598 | //if the length is undefined we assume it is a SYSEX message | ||
| 599 | if (midi_packet_length(byte0) == UNDEFINED) { | ||
| 600 | switch(cnt) { | ||
| 601 | case 3: | ||
| 602 | if (byte2 == SYSEX_END) | ||
| 603 | event.Event = MIDI_EVENT(0, SYSEX_ENDS_IN_3); | ||
| 604 | else | ||
| 605 | event.Event = MIDI_EVENT(0, SYSEX_START_OR_CONT); | ||
| 606 | break; | ||
| 607 | case 2: | ||
| 608 | if (byte1 == SYSEX_END) | ||
| 609 | event.Event = MIDI_EVENT(0, SYSEX_ENDS_IN_2); | ||
| 610 | else | ||
| 611 | event.Event = MIDI_EVENT(0, SYSEX_START_OR_CONT); | ||
| 612 | break; | ||
| 613 | case 1: | ||
| 614 | if (byte0 == SYSEX_END) | ||
| 615 | event.Event = MIDI_EVENT(0, SYSEX_ENDS_IN_1); | ||
| 616 | else | ||
| 617 | event.Event = MIDI_EVENT(0, SYSEX_START_OR_CONT); | ||
| 618 | break; | ||
| 619 | default: | ||
| 620 | return; //invalid cnt | ||
| 621 | } | ||
| 622 | } else { | ||
| 623 | //deal with 'system common' messages | ||
| 624 | //TODO are there any more? | ||
| 625 | switch(byte0 & 0xF0){ | ||
| 626 | case MIDI_SONGPOSITION: | ||
| 627 | event.Event = MIDI_EVENT(0, SYS_COMMON_3); | ||
| 628 | break; | ||
| 629 | case MIDI_SONGSELECT: | ||
| 630 | case MIDI_TC_QUARTERFRAME: | ||
| 631 | event.Event = MIDI_EVENT(0, SYS_COMMON_2); | ||
| 632 | break; | ||
| 633 | default: | ||
| 634 | event.Event = MIDI_EVENT(0, byte0); | ||
| 635 | break; | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event); | ||
| 640 | MIDI_Device_Flush(&USB_MIDI_Interface); | ||
| 641 | MIDI_Device_USBTask(&USB_MIDI_Interface); | ||
| 642 | USB_USBTask(); | ||
| 643 | } | ||
| 644 | |||
| 645 | void usb_get_midi(MidiDevice * device) { | ||
| 646 | MIDI_EventPacket_t event; | ||
| 647 | while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) { | ||
| 648 | |||
| 649 | midi_packet_length_t length = midi_packet_length(event.Data1); | ||
| 650 | uint8_t input[3]; | ||
| 651 | input[0] = event.Data1; | ||
| 652 | input[1] = event.Data2; | ||
| 653 | input[2] = event.Data3; | ||
| 654 | if (length == UNDEFINED) { | ||
| 655 | //sysex | ||
| 656 | if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) { | ||
| 657 | length = 3; | ||
| 658 | } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) { | ||
| 659 | length = 2; | ||
| 660 | } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) { | ||
| 661 | length = 1; | ||
| 662 | } else { | ||
| 663 | //XXX what to do? | ||
| 664 | } | ||
| 665 | } | ||
| 666 | |||
| 667 | //pass the data to the device input function | ||
| 668 | if (length != UNDEFINED) | ||
| 669 | midi_device_input(device, length, input); | ||
| 670 | } | ||
| 671 | MIDI_Device_USBTask(&USB_MIDI_Interface); | ||
| 672 | USB_USBTask(); | ||
| 673 | } | ||
| 674 | |||
| 675 | void midi_usb_init(MidiDevice * device){ | ||
| 676 | midi_device_init(device); | ||
| 677 | midi_device_set_send_func(device, usb_send_func); | ||
| 678 | midi_device_set_pre_input_process_func(device, usb_get_midi); | ||
| 679 | |||
| 680 | SetupHardware(); | ||
| 681 | sei(); | ||
| 682 | } | ||
| 683 | |||
| 684 | |||
| 685 | |||
| 686 | |||
| 687 | |||
| 544 | /******************************************************************************* | 688 | /******************************************************************************* |
| 545 | * main | 689 | * main |
| 546 | ******************************************************************************/ | 690 | ******************************************************************************/ |
| 547 | static void SetupHardware(void) | 691 | void SetupHardware(void) |
| 548 | { | 692 | { |
| 549 | /* Disable watchdog if enabled by bootloader/fuses */ | 693 | /* Disable watchdog if enabled by bootloader/fuses */ |
| 550 | MCUSR &= ~(1 << WDRF); | 694 | MCUSR &= ~(1 << WDRF); |
| @@ -563,12 +707,34 @@ static void SetupHardware(void) | |||
| 563 | print_set_sendchar(sendchar); | 707 | print_set_sendchar(sendchar); |
| 564 | } | 708 | } |
| 565 | 709 | ||
| 710 | void fallthrough_callback(MidiDevice * device, | ||
| 711 | uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2); | ||
| 712 | void cc_callback(MidiDevice * device, | ||
| 713 | uint8_t chan, uint8_t num, uint8_t val); | ||
| 714 | void sysex_callback(MidiDevice * device, | ||
| 715 | uint16_t start, uint8_t length, uint8_t * data); | ||
| 716 | |||
| 566 | int main(void) __attribute__ ((weak)); | 717 | int main(void) __attribute__ ((weak)); |
| 567 | int main(void) | 718 | int main(void) |
| 568 | { | 719 | { |
| 720 | //setup the device | ||
| 721 | |||
| 722 | midi_device_init(&midi_device); | ||
| 723 | midi_device_set_send_func(&midi_device, usb_send_func); | ||
| 724 | midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); | ||
| 725 | |||
| 569 | SetupHardware(); | 726 | SetupHardware(); |
| 570 | sei(); | 727 | sei(); |
| 571 | 728 | ||
| 729 | midi_register_fallthrough_callback(&midi_device, fallthrough_callback); | ||
| 730 | midi_register_cc_callback(&midi_device, cc_callback); | ||
| 731 | midi_register_sysex_callback(&midi_device, sysex_callback); | ||
| 732 | |||
| 733 | midi_send_cc(&midi_device, 0, 1, 2); | ||
| 734 | midi_send_cc(&midi_device, 15, 1, 0); | ||
| 735 | midi_send_noteon(&midi_device, 0, 64, 127); | ||
| 736 | midi_send_noteoff(&midi_device, 0, 64, 127); | ||
| 737 | |||
| 572 | /* wait for USB startup & debug output */ | 738 | /* wait for USB startup & debug output */ |
| 573 | while (USB_DeviceState != DEVICE_STATE_Configured) { | 739 | while (USB_DeviceState != DEVICE_STATE_Configured) { |
| 574 | #if defined(INTERRUPT_CONTROL_ENDPOINT) | 740 | #if defined(INTERRUPT_CONTROL_ENDPOINT) |
| @@ -598,8 +764,29 @@ int main(void) | |||
| 598 | 764 | ||
| 599 | keyboard_task(); | 765 | keyboard_task(); |
| 600 | 766 | ||
| 767 | midi_device_process(&midi_device); | ||
| 768 | |||
| 601 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) | 769 | #if !defined(INTERRUPT_CONTROL_ENDPOINT) |
| 602 | USB_USBTask(); | 770 | USB_USBTask(); |
| 603 | #endif | 771 | #endif |
| 604 | } | 772 | } |
| 605 | } | 773 | } |
| 774 | |||
| 775 | //echo data back | ||
| 776 | void fallthrough_callback(MidiDevice * device, | ||
| 777 | uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){ | ||
| 778 | //pass the data back to the device, using the general purpose send data | ||
| 779 | //function, any bytes after cnt are ignored | ||
| 780 | } | ||
| 781 | |||
| 782 | void cc_callback(MidiDevice * device, | ||
| 783 | uint8_t chan, uint8_t num, uint8_t val) { | ||
| 784 | //sending it back on the next channel | ||
| 785 | midi_send_cc(device, (chan + 1) % 16, num, val); | ||
| 786 | } | ||
| 787 | |||
| 788 | void sysex_callback(MidiDevice * device, | ||
| 789 | uint16_t start, uint8_t length, uint8_t * data) { | ||
| 790 | for (int i = 0; i < length; i++) | ||
| 791 | midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i)); | ||
| 792 | } | ||
