aboutsummaryrefslogtreecommitdiff
path: root/protocol/lufa
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2015-08-20 00:42:08 -0400
committerJack Humbert <jack.humb@gmail.com>2015-08-20 00:42:08 -0400
commite528087ee539fda2f13795d4a6c03403faef44d5 (patch)
tree6f80bd86bdd5e5a044deee9bb195c0ecc9bfd670 /protocol/lufa
parent2d76b5c3d421c984f6b4b9da757383cc87e3f808 (diff)
downloadqmk_firmware-e528087ee539fda2f13795d4a6c03403faef44d5.tar.gz
qmk_firmware-e528087ee539fda2f13795d4a6c03403faef44d5.zip
midi
Diffstat (limited to 'protocol/lufa')
-rw-r--r--protocol/lufa/descriptor.c158
-rw-r--r--protocol/lufa/descriptor.h23
-rw-r--r--protocol/lufa/lufa.c191
-rw-r--r--protocol/lufa/lufa.h3
4 files changed, 371 insertions, 4 deletions
diff --git a/protocol/lufa/descriptor.c b/protocol/lufa/descriptor.c
index c13a81bda..6eedd5700 100644
--- a/protocol/lufa/descriptor.c
+++ b/protocol/lufa/descriptor.c
@@ -486,6 +486,164 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
486 .PollingIntervalMS = 0x01 486 .PollingIntervalMS = 0x01
487 }, 487 },
488#endif 488#endif
489
490 .Audio_ControlInterface =
491 {
492 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
493
494 .InterfaceNumber = (NKRO_INTERFACE + 1),
495 .AlternateSetting = 0,
496
497 .TotalEndpoints = 0,
498
499 .Class = AUDIO_CSCP_AudioClass,
500 .SubClass = AUDIO_CSCP_ControlSubclass,
501 .Protocol = AUDIO_CSCP_ControlProtocol,
502
503 .InterfaceStrIndex = NO_DESCRIPTOR
504 },
505
506 .Audio_ControlInterface_SPC =
507 {
508 .Header = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = DTYPE_CSInterface},
509 .Subtype = AUDIO_DSUBTYPE_CSInterface_Header,
510
511 .ACSpecification = VERSION_BCD(1,1,1),
512 .TotalLength = sizeof(USB_Audio_Descriptor_Interface_AC_t),
513
514 .InCollection = 1,
515 .InterfaceNumber = (NKRO_INTERFACE + 2),
516 },
517
518 .Audio_StreamInterface =
519 {
520 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
521
522 .InterfaceNumber = (NKRO_INTERFACE + 2),
523 .AlternateSetting = 0,
524
525 .TotalEndpoints = 2,
526
527 .Class = AUDIO_CSCP_AudioClass,
528 .SubClass = AUDIO_CSCP_MIDIStreamingSubclass,
529 .Protocol = AUDIO_CSCP_StreamingProtocol,
530
531 .InterfaceStrIndex = NO_DESCRIPTOR
532 },
533
534 .Audio_StreamInterface_SPC =
535 {
536 .Header = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = DTYPE_CSInterface},
537 .Subtype = AUDIO_DSUBTYPE_CSInterface_General,
538
539 .AudioSpecification = VERSION_BCD(1,1,1),
540
541 .TotalLength = (sizeof(USB_Descriptor_Configuration_t) -
542 offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC))
543 },
544
545 .MIDI_In_Jack_Emb =
546 {
547 .Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
548 .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
549
550 .JackType = MIDI_JACKTYPE_Embedded,
551 .JackID = 0x01,
552
553 .JackStrIndex = NO_DESCRIPTOR
554 },
555
556 .MIDI_In_Jack_Ext =
557 {
558 .Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
559 .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
560
561 .JackType = MIDI_JACKTYPE_External,
562 .JackID = 0x02,
563
564 .JackStrIndex = NO_DESCRIPTOR
565 },
566
567 .MIDI_Out_Jack_Emb =
568 {
569 .Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
570 .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
571
572 .JackType = MIDI_JACKTYPE_Embedded,
573 .JackID = 0x03,
574
575 .NumberOfPins = 1,
576 .SourceJackID = {0x02},
577 .SourcePinID = {0x01},
578
579 .JackStrIndex = NO_DESCRIPTOR
580 },
581
582 .MIDI_Out_Jack_Ext =
583 {
584 .Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
585 .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
586
587 .JackType = MIDI_JACKTYPE_External,
588 .JackID = 0x04,
589
590 .NumberOfPins = 1,
591 .SourceJackID = {0x01},
592 .SourcePinID = {0x01},
593
594 .JackStrIndex = NO_DESCRIPTOR
595 },
596
597 .MIDI_In_Jack_Endpoint =
598 {
599 .Endpoint =
600 {
601 .Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
602
603 .EndpointAddress = (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM),
604 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
605 .EndpointSize = MIDI_STREAM_EPSIZE,
606 .PollingIntervalMS = 0x01
607 },
608
609 .Refresh = 0,
610 .SyncEndpointNumber = 0
611 },
612
613 .MIDI_In_Jack_Endpoint_SPC =
614 {
615 .Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
616 .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
617
618 .TotalEmbeddedJacks = 0x01,
619 .AssociatedJackID = {0x01}
620 },
621
622 .MIDI_Out_Jack_Endpoint =
623 {
624 .Endpoint =
625 {
626 .Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
627
628 .EndpointAddress = (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM),
629 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
630 .EndpointSize = MIDI_STREAM_EPSIZE,
631 .PollingIntervalMS = 0x01
632 },
633
634 .Refresh = 0,
635 .SyncEndpointNumber = 0
636 },
637
638 .MIDI_Out_Jack_Endpoint_SPC =
639 {
640 .Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
641 .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
642
643 .TotalEmbeddedJacks = 0x01,
644 .AssociatedJackID = {0x03}
645 }
646
489}; 647};
490 648
491 649
diff --git a/protocol/lufa/descriptor.h b/protocol/lufa/descriptor.h
index 42af07917..58a7df440 100644
--- a/protocol/lufa/descriptor.h
+++ b/protocol/lufa/descriptor.h
@@ -85,6 +85,23 @@ typedef struct
85 USB_HID_Descriptor_HID_t NKRO_HID; 85 USB_HID_Descriptor_HID_t NKRO_HID;
86 USB_Descriptor_Endpoint_t NKRO_INEndpoint; 86 USB_Descriptor_Endpoint_t NKRO_INEndpoint;
87#endif 87#endif
88
89 // MIDI Audio Control Interface
90 USB_Descriptor_Interface_t Audio_ControlInterface;
91 USB_Audio_Descriptor_Interface_AC_t Audio_ControlInterface_SPC;
92
93 // MIDI Audio Streaming Interface
94 USB_Descriptor_Interface_t Audio_StreamInterface;
95 USB_MIDI_Descriptor_AudioInterface_AS_t Audio_StreamInterface_SPC;
96 USB_MIDI_Descriptor_InputJack_t MIDI_In_Jack_Emb;
97 USB_MIDI_Descriptor_InputJack_t MIDI_In_Jack_Ext;
98 USB_MIDI_Descriptor_OutputJack_t MIDI_Out_Jack_Emb;
99 USB_MIDI_Descriptor_OutputJack_t MIDI_Out_Jack_Ext;
100 USB_Audio_Descriptor_StreamEndpoint_Std_t MIDI_In_Jack_Endpoint;
101 USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_In_Jack_Endpoint_SPC;
102 USB_Audio_Descriptor_StreamEndpoint_Std_t MIDI_Out_Jack_Endpoint;
103 USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_Out_Jack_Endpoint_SPC;
104
88} USB_Descriptor_Configuration_t; 105} USB_Descriptor_Configuration_t;
89 106
90 107
@@ -117,7 +134,7 @@ typedef struct
117 134
118 135
119/* nubmer of interfaces */ 136/* nubmer of interfaces */
120#define TOTAL_INTERFACES (NKRO_INTERFACE + 1) 137#define TOTAL_INTERFACES (NKRO_INTERFACE + 3)
121 138
122 139
123// Endopoint number and size 140// Endopoint number and size
@@ -150,12 +167,16 @@ typedef struct
150# endif 167# endif
151#endif 168#endif
152 169
170#define MIDI_STREAM_IN_EPNUM (NKRO_IN_EPNUM + 1)
171#define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 1)
172
153 173
154#define KEYBOARD_EPSIZE 8 174#define KEYBOARD_EPSIZE 8
155#define MOUSE_EPSIZE 8 175#define MOUSE_EPSIZE 8
156#define EXTRAKEY_EPSIZE 8 176#define EXTRAKEY_EPSIZE 8
157#define CONSOLE_EPSIZE 32 177#define CONSOLE_EPSIZE 32
158#define NKRO_EPSIZE 16 178#define NKRO_EPSIZE 16
179#define MIDI_STREAM_EPSIZE 64
159 180
160 181
161uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, 182uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
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
55uint8_t keyboard_idle = 0; 56uint8_t keyboard_idle = 0;
56uint8_t keyboard_protocol = 1; 57uint8_t keyboard_protocol = 1;
57static uint8_t keyboard_led_stats = 0; 58static uint8_t keyboard_led_stats = 0;
@@ -65,14 +66,51 @@ static void send_keyboard(report_keyboard_t *report);
65static void send_mouse(report_mouse_t *report); 66static void send_mouse(report_mouse_t *report);
66static void send_system(uint16_t data); 67static void send_system(uint16_t data);
67static void send_consumer(uint16_t data); 68static void send_consumer(uint16_t data);
69void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
70void usb_get_midi(MidiDevice * device);
71void midi_usb_init(MidiDevice * device);
68host_driver_t lufa_driver = { 72host_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
83void SetupHardware(void);
84
85USB_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/*
246Appendix G: HID Request Support Requirements 289Appendix 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
592void 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
645void 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
675void 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 ******************************************************************************/
547static void SetupHardware(void) 691void 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
710void fallthrough_callback(MidiDevice * device,
711 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
712void cc_callback(MidiDevice * device,
713 uint8_t chan, uint8_t num, uint8_t val);
714void sysex_callback(MidiDevice * device,
715 uint16_t start, uint8_t length, uint8_t * data);
716
566int main(void) __attribute__ ((weak)); 717int main(void) __attribute__ ((weak));
567int main(void) 718int 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
776void 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
782void 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
788void 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}
diff --git a/protocol/lufa/lufa.h b/protocol/lufa/lufa.h
index 195123c0f..505cb3279 100644
--- a/protocol/lufa/lufa.h
+++ b/protocol/lufa/lufa.h
@@ -48,7 +48,7 @@
48#include <LUFA/Version.h> 48#include <LUFA/Version.h>
49#include <LUFA/Drivers/USB/USB.h> 49#include <LUFA/Drivers/USB/USB.h>
50#include "host.h" 50#include "host.h"
51 51#include "midi/midi.h"
52 52
53#ifdef __cplusplus 53#ifdef __cplusplus
54extern "C" { 54extern "C" {
@@ -66,6 +66,7 @@ typedef struct {
66 uint16_t usage; 66 uint16_t usage;
67} __attribute__ ((packed)) report_extra_t; 67} __attribute__ ((packed)) report_extra_t;
68 68
69MidiDevice midi_device;
69 70
70#if LUFA_VERSION_INTEGER < 0x120730 71#if LUFA_VERSION_INTEGER < 0x120730
71 /* old API 120219 */ 72 /* old API 120219 */