2 * Copyright 2012 Jun Wako <wakojun@gmail.com>
3 * This file is based on:
4 * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
5 * LUFA-120219/Demos/Device/Lowlevel/GenericHID
10 Copyright (C) Dean Camera, 2012.
12 dean [at] fourwalledcubicle [dot] com
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
20 Permission to use, copy, modify, distribute, and sell this
21 software and its documentation for any purpose is hereby granted
22 without fee, provided that the above copyright notice appear in
23 all copies and that both that the copyright notice and this
24 permission notice and warranty disclaimer appear in supporting
25 documentation, and that the name of the author not be used in
26 advertising or publicity pertaining to distribution of the
27 software without specific, written prior permission.
29 The author disclaim all warranties with regard to this
30 software, including all implied warranties of merchantability
31 and fitness. In no event shall the author be liable for any
32 special, indirect or consequential damages or any damages
33 whatsoever resulting from loss of use, data or profits, whether
34 in an action of contract, negligence or other tortious action,
35 arising out of or in connection with the use or performance of
41 #include "host_driver.h"
47 #ifdef SLEEP_LED_ENABLE
48 #include "sleep_led.h"
52 #include "descriptor.h"
57 #include "keycode_config.h"
59 extern keymap_config_t keymap_config;
67 #ifdef BLUETOOTH_ENABLE
68 #include "bluetooth.h"
75 #if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
80 #include "sysex_tools.h"
87 uint8_t keyboard_idle = 0;
88 /* 0: Boot Protocol, 1: Report Protocol(default) */
89 uint8_t keyboard_protocol = 1;
90 static uint8_t keyboard_led_stats = 0;
92 static report_keyboard_t keyboard_report_sent;
95 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
96 static void usb_get_midi(MidiDevice * device);
97 static void midi_usb_init(MidiDevice * device);
101 static uint8_t keyboard_leds(void);
102 static void send_keyboard(report_keyboard_t *report);
103 static void send_mouse(report_mouse_t *report);
104 static void send_system(uint16_t data);
105 static void send_consumer(uint16_t data);
106 host_driver_t lufa_driver = {
119 /*******************************************************************************
121 ******************************************************************************/
124 USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
128 .StreamingInterfaceNumber = AS_INTERFACE,
131 .Address = MIDI_STREAM_IN_EPADDR,
132 .Size = MIDI_STREAM_EPSIZE,
137 .Address = MIDI_STREAM_OUT_EPADDR,
138 .Size = MIDI_STREAM_EPSIZE,
144 #define SYSEX_START_OR_CONT 0x40
145 #define SYSEX_ENDS_IN_1 0x50
146 #define SYSEX_ENDS_IN_2 0x60
147 #define SYSEX_ENDS_IN_3 0x70
149 #define SYS_COMMON_1 0x50
150 #define SYS_COMMON_2 0x20
151 #define SYS_COMMON_3 0x30
154 #ifdef VIRTSER_ENABLE
155 USB_ClassInfo_CDC_Device_t cdc_device =
159 .ControlInterfaceNumber = CCI_INTERFACE,
162 .Address = CDC_IN_EPADDR,
168 .Address = CDC_OUT_EPADDR,
172 .NotificationEndpoint =
174 .Address = CDC_NOTIFICATION_EPADDR,
175 .Size = CDC_NOTIFICATION_EPSIZE,
184 void raw_hid_send( uint8_t *data, uint8_t length )
186 // TODO: implement variable size packet
187 if ( length != RAW_EPSIZE )
192 if (USB_DeviceState != DEVICE_STATE_Configured)
197 // TODO: decide if we allow calls to raw_hid_send() in the middle
198 // of other endpoint usage.
199 uint8_t ep = Endpoint_GetCurrentEndpoint();
201 Endpoint_SelectEndpoint(RAW_IN_EPNUM);
203 // Check to see if the host is ready to accept another packet
204 if (Endpoint_IsINReady())
207 Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL);
208 // Finalize the stream transfer to send the last packet
212 Endpoint_SelectEndpoint(ep);
215 __attribute__ ((weak))
216 void raw_hid_receive( uint8_t *data, uint8_t length )
218 // Users should #include "raw_hid.h" in their own code
219 // and implement this function there. Leave this as weak linkage
220 // so users can opt to not handle data coming in.
223 static void raw_hid_task(void)
225 // Create a temporary buffer to hold the read in data from the host
226 uint8_t data[RAW_EPSIZE];
227 bool data_read = false;
229 // Device must be connected and configured for the task to run
230 if (USB_DeviceState != DEVICE_STATE_Configured)
233 Endpoint_SelectEndpoint(RAW_OUT_EPNUM);
235 // Check to see if a packet has been sent from the host
236 if (Endpoint_IsOUTReceived())
238 // Check to see if the packet contains data
239 if (Endpoint_IsReadWriteAllowed())
242 Endpoint_Read_Stream_LE(data, sizeof(data), NULL);
246 // Finalize the stream transfer to receive the last packet
251 raw_hid_receive( data, sizeof(data) );
257 /*******************************************************************************
259 ******************************************************************************/
260 #ifdef CONSOLE_ENABLE
261 static void Console_Task(void)
263 /* Device must be connected and configured for the task to run */
264 if (USB_DeviceState != DEVICE_STATE_Configured)
267 uint8_t ep = Endpoint_GetCurrentEndpoint();
270 // TODO: impl receivechar()/recvchar()
271 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
273 /* Check to see if a packet has been sent from the host */
274 if (Endpoint_IsOUTReceived())
276 /* Check to see if the packet contains data */
277 if (Endpoint_IsReadWriteAllowed())
279 /* Create a temporary buffer to hold the read in report from the host */
280 uint8_t ConsoleData[CONSOLE_EPSIZE];
282 /* Read Console Report Data */
283 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
285 /* Process Console Report Data */
286 //ProcessConsoleHIDReport(ConsoleData);
289 /* Finalize the stream transfer to send the last packet */
295 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
296 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
297 Endpoint_SelectEndpoint(ep);
302 while (Endpoint_IsReadWriteAllowed())
305 // flash senchar packet
306 if (Endpoint_IsINReady()) {
310 Endpoint_SelectEndpoint(ep);
315 /*******************************************************************************
317 ******************************************************************************/
319 * Event Order of Plug in:
320 * 0) EVENT_USB_Device_Connect
321 * 1) EVENT_USB_Device_Suspend
322 * 2) EVENT_USB_Device_Reset
323 * 3) EVENT_USB_Device_Wake
325 void EVENT_USB_Device_Connect(void)
328 /* For battery powered device */
329 if (!USB_IsInitialized) {
332 USB_Device_EnableSOFEvents();
336 void EVENT_USB_Device_Disconnect(void)
339 /* For battery powered device */
340 USB_IsInitialized = false;
341 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
342 if (USB_IsInitialized) {
343 USB_Disable(); // Disable all interrupts
344 USB_Controller_Enable();
345 USB_INT_Enable(USB_INT_VBUSTI);
350 void EVENT_USB_Device_Reset(void)
355 void EVENT_USB_Device_Suspend()
358 #ifdef SLEEP_LED_ENABLE
363 void EVENT_USB_Device_WakeUp()
366 suspend_wakeup_init();
368 #ifdef SLEEP_LED_ENABLE
370 // NOTE: converters may not accept this
371 led_set(host_keyboard_leds());
377 #ifdef CONSOLE_ENABLE
378 static bool console_flush = false;
379 #define CONSOLE_FLUSH_SET(b) do { \
380 uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
384 void EVENT_USB_Device_StartOfFrame(void)
386 static uint8_t count;
387 if (++count % 50) return;
390 if (!console_flush) return;
392 console_flush = false;
397 /** Event handler for the USB_ConfigurationChanged event.
398 * This is fired when the host sets the current configuration of the USB device after enumeration.
400 * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
401 * it is safe to use singl bank for all endpoints.
403 void EVENT_USB_Device_ConfigurationChanged(void)
405 bool ConfigSuccess = true;
407 /* Setup Keyboard HID Report Endpoints */
408 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
409 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
412 /* Setup Mouse HID Report Endpoint */
413 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
414 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
417 #ifdef EXTRAKEY_ENABLE
418 /* Setup Extra HID Report Endpoint */
419 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
420 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
424 /* Setup Raw HID Report Endpoints */
425 ConfigSuccess &= ENDPOINT_CONFIG(RAW_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
426 RAW_EPSIZE, ENDPOINT_BANK_SINGLE);
427 ConfigSuccess &= ENDPOINT_CONFIG(RAW_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
428 RAW_EPSIZE, ENDPOINT_BANK_SINGLE);
431 #ifdef CONSOLE_ENABLE
432 /* Setup Console HID Report Endpoints */
433 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
434 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
436 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
437 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
442 /* Setup NKRO HID Report Endpoints */
443 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
444 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
448 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_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);
452 #ifdef VIRTSER_ENABLE
453 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE);
454 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
455 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
460 Appendix G: HID Request Support Requirements
462 The following table enumerates the requests that need to be supported by various types of HID class devices.
464 Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
465 ------------------------------------------------------------------------------------------
466 Boot Mouse Required Optional Optional Optional Required Required
467 Non-Boot Mouse Required Optional Optional Optional Optional Optional
468 Boot Keyboard Required Optional Required Required Required Required
469 Non-Boot Keybrd Required Optional Required Required Optional Optional
470 Other Device Required Optional Optional Optional Optional Optional
472 /** Event handler for the USB_ControlRequest event.
473 * This is fired before passing along unhandled control requests to the library for processing internally.
475 void EVENT_USB_Device_ControlRequest(void)
477 uint8_t* ReportData = NULL;
478 uint8_t ReportSize = 0;
480 /* Handle HID Class specific requests */
481 switch (USB_ControlRequest.bRequest)
483 case HID_REQ_GetReport:
484 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
486 Endpoint_ClearSETUP();
489 switch (USB_ControlRequest.wIndex) {
490 case KEYBOARD_INTERFACE:
492 ReportData = (uint8_t*)&keyboard_report_sent;
493 ReportSize = sizeof(keyboard_report_sent);
497 /* Write the report data to the control endpoint */
498 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
503 case HID_REQ_SetReport:
504 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
508 switch (USB_ControlRequest.wIndex) {
509 case KEYBOARD_INTERFACE:
513 Endpoint_ClearSETUP();
515 while (!(Endpoint_IsOUTReceived())) {
516 if (USB_DeviceState == DEVICE_STATE_Unattached)
519 keyboard_led_stats = Endpoint_Read_8();
522 Endpoint_ClearStatusStage();
530 case HID_REQ_GetProtocol:
531 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
533 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
534 Endpoint_ClearSETUP();
535 while (!(Endpoint_IsINReady()));
536 Endpoint_Write_8(keyboard_protocol);
538 Endpoint_ClearStatusStage();
543 case HID_REQ_SetProtocol:
544 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
546 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
547 Endpoint_ClearSETUP();
548 Endpoint_ClearStatusStage();
550 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
556 case HID_REQ_SetIdle:
557 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
559 Endpoint_ClearSETUP();
560 Endpoint_ClearStatusStage();
562 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
566 case HID_REQ_GetIdle:
567 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
569 Endpoint_ClearSETUP();
570 while (!(Endpoint_IsINReady()));
571 Endpoint_Write_8(keyboard_idle);
573 Endpoint_ClearStatusStage();
579 #ifdef VIRTSER_ENABLE
580 CDC_Device_ProcessControlRequest(&cdc_device);
584 /*******************************************************************************
587 ******************************************************************************/
588 static uint8_t keyboard_leds(void)
590 return keyboard_led_stats;
593 static void send_keyboard(report_keyboard_t *report)
596 #ifdef BLUETOOTH_ENABLE
597 bluefruit_serial_send(0xFD);
598 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
599 bluefruit_serial_send(report->raw[i]);
603 uint8_t timeout = 255;
605 if (USB_DeviceState != DEVICE_STATE_Configured)
608 /* Select the Keyboard Report Endpoint */
610 if (keyboard_protocol && keymap_config.nkro) {
611 /* Report protocol - NKRO */
612 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
614 /* Check if write ready for a polling interval around 1ms */
615 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
616 if (!Endpoint_IsReadWriteAllowed()) return;
618 /* Write Keyboard Report Data */
619 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
625 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
627 /* Check if write ready for a polling interval around 10ms */
628 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
629 if (!Endpoint_IsReadWriteAllowed()) return;
631 /* Write Keyboard Report Data */
632 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
635 /* Finalize the stream transfer to send the last packet */
638 keyboard_report_sent = *report;
641 static void send_mouse(report_mouse_t *report)
645 #ifdef BLUETOOTH_ENABLE
646 bluefruit_serial_send(0xFD);
647 bluefruit_serial_send(0x00);
648 bluefruit_serial_send(0x03);
649 bluefruit_serial_send(report->buttons);
650 bluefruit_serial_send(report->x);
651 bluefruit_serial_send(report->y);
652 bluefruit_serial_send(report->v); // should try sending the wheel v here
653 bluefruit_serial_send(report->h); // should try sending the wheel h here
654 bluefruit_serial_send(0x00);
657 uint8_t timeout = 255;
659 if (USB_DeviceState != DEVICE_STATE_Configured)
662 /* Select the Mouse Report Endpoint */
663 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
665 /* Check if write ready for a polling interval around 10ms */
666 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
667 if (!Endpoint_IsReadWriteAllowed()) return;
669 /* Write Mouse Report Data */
670 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
672 /* Finalize the stream transfer to send the last packet */
677 static void send_system(uint16_t data)
679 uint8_t timeout = 255;
681 if (USB_DeviceState != DEVICE_STATE_Configured)
685 .report_id = REPORT_ID_SYSTEM,
688 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
690 /* Check if write ready for a polling interval around 10ms */
691 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
692 if (!Endpoint_IsReadWriteAllowed()) return;
694 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
698 static void send_consumer(uint16_t data)
701 #ifdef BLUETOOTH_ENABLE
702 static uint16_t last_data = 0;
703 if (data == last_data) return;
705 uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
706 bluefruit_serial_send(0xFD);
707 bluefruit_serial_send(0x00);
708 bluefruit_serial_send(0x02);
709 bluefruit_serial_send((bitmap>>8)&0xFF);
710 bluefruit_serial_send(bitmap&0xFF);
711 bluefruit_serial_send(0x00);
712 bluefruit_serial_send(0x00);
713 bluefruit_serial_send(0x00);
714 bluefruit_serial_send(0x00);
717 uint8_t timeout = 255;
719 if (USB_DeviceState != DEVICE_STATE_Configured)
723 .report_id = REPORT_ID_CONSUMER,
726 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
728 /* Check if write ready for a polling interval around 10ms */
729 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
730 if (!Endpoint_IsReadWriteAllowed()) return;
732 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
737 /*******************************************************************************
739 ******************************************************************************/
740 #ifdef CONSOLE_ENABLE
741 #define SEND_TIMEOUT 5
742 int8_t sendchar(uint8_t c)
744 // Not wait once timeouted.
745 // Because sendchar() is called so many times, waiting each call causes big lag.
746 static bool timeouted = false;
748 // prevents Console_Task() from running during sendchar() runs.
749 // or char will be lost. These two function is mutually exclusive.
750 CONSOLE_FLUSH_SET(false);
752 if (USB_DeviceState != DEVICE_STATE_Configured)
755 uint8_t ep = Endpoint_GetCurrentEndpoint();
756 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
757 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
761 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
767 uint8_t timeout = SEND_TIMEOUT;
768 while (!Endpoint_IsReadWriteAllowed()) {
769 if (USB_DeviceState != DEVICE_STATE_Configured) {
772 if (Endpoint_IsStalled()) {
784 // send when bank is full
785 if (!Endpoint_IsReadWriteAllowed()) {
786 while (!(Endpoint_IsINReady()));
789 CONSOLE_FLUSH_SET(true);
792 Endpoint_SelectEndpoint(ep);
795 Endpoint_SelectEndpoint(ep);
799 int8_t sendchar(uint8_t c)
805 /*******************************************************************************
807 ******************************************************************************/
810 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
811 MIDI_EventPacket_t event;
818 // Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
820 //if the length is undefined we assume it is a SYSEX message
821 if (midi_packet_length(byte0) == UNDEFINED) {
824 if (byte2 == SYSEX_END)
825 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
827 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
830 if (byte1 == SYSEX_END)
831 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
833 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
836 if (byte0 == SYSEX_END)
837 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
839 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
842 return; //invalid cnt
845 //deal with 'system common' messages
846 //TODO are there any more?
847 switch(byte0 & 0xF0){
848 case MIDI_SONGPOSITION:
849 event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
851 case MIDI_SONGSELECT:
852 case MIDI_TC_QUARTERFRAME:
853 event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
856 event.Event = MIDI_EVENT(cable, byte0);
861 // Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
862 // Endpoint_ClearIN();
864 MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
865 MIDI_Device_Flush(&USB_MIDI_Interface);
866 MIDI_Device_USBTask(&USB_MIDI_Interface);
870 static void usb_get_midi(MidiDevice * device) {
871 MIDI_EventPacket_t event;
872 while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
874 midi_packet_length_t length = midi_packet_length(event.Data1);
876 input[0] = event.Data1;
877 input[1] = event.Data2;
878 input[2] = event.Data3;
879 if (length == UNDEFINED) {
881 if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
883 } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
885 } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
892 //pass the data to the device input function
893 if (length != UNDEFINED)
894 midi_device_input(device, length, input);
896 MIDI_Device_USBTask(&USB_MIDI_Interface);
900 static void midi_usb_init(MidiDevice * device){
901 midi_device_init(device);
902 midi_device_set_send_func(device, usb_send_func);
903 midi_device_set_pre_input_process_func(device, usb_get_midi);
912 /* Device must be connected and configured for the task to run */
913 dprint("in MIDI_TASK\n");
914 if (USB_DeviceState != DEVICE_STATE_Configured)
916 dprint("continuing in MIDI_TASK\n");
918 Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
920 if (Endpoint_IsINReady())
923 dprint("Endpoint is ready\n");
925 uint8_t MIDICommand = 0;
928 /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
929 uint8_t Channel = MIDI_CHANNEL(1);
931 MIDICommand = MIDI_COMMAND_NOTE_ON;
934 /* Check if a MIDI command is to be sent */
937 dprint("Command exists\n");
938 MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
940 .Event = MIDI_EVENT(0, MIDICommand),
942 .Data1 = MIDICommand | Channel,
944 .Data3 = MIDI_STANDARD_VELOCITY,
947 /* Write the MIDI event packet to the endpoint */
948 Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
950 /* Send the data in the endpoint to the host */
956 /* Select the MIDI OUT stream */
957 Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
959 /* Check if a MIDI command has been received */
960 if (Endpoint_IsOUTReceived())
962 MIDI_EventPacket_t MIDIEvent;
964 /* Read the MIDI event packet from the endpoint */
965 Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
967 /* If the endpoint is now empty, clear the bank */
968 if (!(Endpoint_BytesInEndpoint()))
970 /* Clear the endpoint ready for new packet */
978 /*******************************************************************************
980 ******************************************************************************/
982 #ifdef VIRTSER_ENABLE
983 void virtser_init(void)
985 cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ;
986 CDC_Device_SendControlLineStateChange(&cdc_device);
989 void virtser_recv(uint8_t c) __attribute__ ((weak));
990 void virtser_recv(uint8_t c)
995 void virtser_task(void)
997 uint16_t count = CDC_Device_BytesReceived(&cdc_device);
1001 ch = CDC_Device_ReceiveByte(&cdc_device);
1005 void virtser_send(const uint8_t byte)
1007 uint8_t timeout = 255;
1008 uint8_t ep = Endpoint_GetCurrentEndpoint();
1010 if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR)
1013 Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address);
1015 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
1016 Endpoint_SelectEndpoint(ep);
1020 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
1022 Endpoint_Write_8(byte);
1023 CDC_Device_Flush(&cdc_device);
1025 if (Endpoint_IsINReady()) {
1029 Endpoint_SelectEndpoint(ep);
1034 /*******************************************************************************
1036 ******************************************************************************/
1037 static void setup_mcu(void)
1039 /* Disable watchdog if enabled by bootloader/fuses */
1040 MCUSR &= ~(1 << WDRF);
1043 /* Disable clock division */
1044 // clock_prescale_set(clock_div_1);
1046 CLKPR = (1 << CLKPCE);
1047 CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
1050 static void setup_usb(void)
1052 // Leonardo needs. Without this USB device is not recognized.
1058 USB_Device_EnableSOFEvents();
1059 print_set_sendchar(sendchar);
1064 void fallthrough_callback(MidiDevice * device,
1065 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
1066 void cc_callback(MidiDevice * device,
1067 uint8_t chan, uint8_t num, uint8_t val);
1068 void sysex_callback(MidiDevice * device,
1069 uint16_t start, uint8_t length, uint8_t * data);
1072 int main(void) __attribute__ ((weak));
1077 midi_device_init(&midi_device);
1078 midi_device_set_send_func(&midi_device, usb_send_func);
1079 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
1088 midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
1089 midi_register_cc_callback(&midi_device, cc_callback);
1090 midi_register_sysex_callback(&midi_device, sysex_callback);
1093 // midi_send_cc(&midi_device, 0, 1, 2);
1094 // midi_send_cc(&midi_device, 15, 1, 0);
1095 // midi_send_noteon(&midi_device, 0, 64, 127);
1096 // midi_send_noteoff(&midi_device, 0, 64, 127);
1099 #ifdef BLUETOOTH_ENABLE
1103 /* wait for USB startup & debug output */
1106 while (USB_DeviceState != DEVICE_STATE_Configured) {
1107 #if defined(INTERRUPT_CONTROL_ENDPOINT)
1113 print("USB configured.\n");
1119 host_set_driver(&lufa_driver);
1120 #ifdef SLEEP_LED_ENABLE
1124 #ifdef VIRTSER_ENABLE
1128 print("Keyboard start.\n");
1130 #ifndef BLUETOOTH_ENABLE
1131 while (USB_DeviceState == DEVICE_STATE_Suspended) {
1133 suspend_power_down();
1134 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
1135 USB_Device_SendRemoteWakeup();
1143 midi_device_process(&midi_device);
1147 #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
1151 #ifdef VIRTSER_ENABLE
1153 CDC_Device_USBTask(&cdc_device);
1160 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
1168 void fallthrough_callback(MidiDevice * device,
1169 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
1173 switch (byte0 & 0xF0) {
1175 play_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
1178 stop_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0));
1182 if (byte0 == MIDI_STOP) {
1189 void cc_callback(MidiDevice * device,
1190 uint8_t chan, uint8_t num, uint8_t val) {
1191 //sending it back on the next channel
1192 // midi_send_cc(device, (chan + 1) % 16, num, val);
1195 uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
1197 void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
1198 #ifdef API_SYSEX_ENABLE
1199 // SEND_STRING("\n");
1200 // send_word(start);
1201 // SEND_STRING(": ");
1202 for (uint8_t place = 0; place < length; place++) {
1203 // send_byte(*data);
1204 midi_buffer[start + place] = *data;
1205 if (*data == 0xF7) {
1206 // SEND_STRING("\nRD: ");
1207 // for (uint8_t i = 0; i < start + place + 1; i++){
1208 // send_byte(midi_buffer[i]);
1209 // SEND_STRING(" ");
1211 uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4)));
1212 uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4);
1213 process_api(decode_length, decoded);
1215 // SEND_STRING(" ");