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"
83 uint8_t keyboard_idle = 0;
84 /* 0: Boot Protocol, 1: Report Protocol(default) */
85 uint8_t keyboard_protocol = 1;
86 static uint8_t keyboard_led_stats = 0;
88 static report_keyboard_t keyboard_report_sent;
91 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
92 static void usb_get_midi(MidiDevice * device);
93 static void midi_usb_init(MidiDevice * device);
97 static uint8_t keyboard_leds(void);
98 static void send_keyboard(report_keyboard_t *report);
99 static void send_mouse(report_mouse_t *report);
100 static void send_system(uint16_t data);
101 static void send_consumer(uint16_t data);
102 host_driver_t lufa_driver = {
115 /*******************************************************************************
117 ******************************************************************************/
120 USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
124 .StreamingInterfaceNumber = AS_INTERFACE,
127 .Address = MIDI_STREAM_IN_EPADDR,
128 .Size = MIDI_STREAM_EPSIZE,
133 .Address = MIDI_STREAM_OUT_EPADDR,
134 .Size = MIDI_STREAM_EPSIZE,
140 #define SYSEX_START_OR_CONT 0x40
141 #define SYSEX_ENDS_IN_1 0x50
142 #define SYSEX_ENDS_IN_2 0x60
143 #define SYSEX_ENDS_IN_3 0x70
145 #define SYS_COMMON_1 0x50
146 #define SYS_COMMON_2 0x20
147 #define SYS_COMMON_3 0x30
150 #ifdef VIRTSER_ENABLE
151 USB_ClassInfo_CDC_Device_t cdc_device =
155 .ControlInterfaceNumber = CCI_INTERFACE,
158 .Address = CDC_IN_EPADDR,
164 .Address = CDC_OUT_EPADDR,
168 .NotificationEndpoint =
170 .Address = CDC_NOTIFICATION_EPADDR,
171 .Size = CDC_NOTIFICATION_EPSIZE,
179 /*******************************************************************************
181 ******************************************************************************/
182 #ifdef CONSOLE_ENABLE
183 static void Console_Task(void)
185 /* Device must be connected and configured for the task to run */
186 if (USB_DeviceState != DEVICE_STATE_Configured)
189 uint8_t ep = Endpoint_GetCurrentEndpoint();
192 // TODO: impl receivechar()/recvchar()
193 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
195 /* Check to see if a packet has been sent from the host */
196 if (Endpoint_IsOUTReceived())
198 /* Check to see if the packet contains data */
199 if (Endpoint_IsReadWriteAllowed())
201 /* Create a temporary buffer to hold the read in report from the host */
202 uint8_t ConsoleData[CONSOLE_EPSIZE];
204 /* Read Console Report Data */
205 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
207 /* Process Console Report Data */
208 //ProcessConsoleHIDReport(ConsoleData);
211 /* Finalize the stream transfer to send the last packet */
217 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
218 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
219 Endpoint_SelectEndpoint(ep);
224 while (Endpoint_IsReadWriteAllowed())
227 // flash senchar packet
228 if (Endpoint_IsINReady()) {
232 Endpoint_SelectEndpoint(ep);
237 /*******************************************************************************
239 ******************************************************************************/
241 * Event Order of Plug in:
242 * 0) EVENT_USB_Device_Connect
243 * 1) EVENT_USB_Device_Suspend
244 * 2) EVENT_USB_Device_Reset
245 * 3) EVENT_USB_Device_Wake
247 void EVENT_USB_Device_Connect(void)
250 /* For battery powered device */
251 if (!USB_IsInitialized) {
254 USB_Device_EnableSOFEvents();
258 void EVENT_USB_Device_Disconnect(void)
261 /* For battery powered device */
262 USB_IsInitialized = false;
263 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
264 if (USB_IsInitialized) {
265 USB_Disable(); // Disable all interrupts
266 USB_Controller_Enable();
267 USB_INT_Enable(USB_INT_VBUSTI);
272 void EVENT_USB_Device_Reset(void)
277 void EVENT_USB_Device_Suspend()
280 #ifdef SLEEP_LED_ENABLE
285 void EVENT_USB_Device_WakeUp()
288 suspend_wakeup_init();
290 #ifdef SLEEP_LED_ENABLE
292 // NOTE: converters may not accept this
293 led_set(host_keyboard_leds());
297 #ifdef CONSOLE_ENABLE
298 static bool console_flush = false;
299 #define CONSOLE_FLUSH_SET(b) do { \
300 uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
304 void EVENT_USB_Device_StartOfFrame(void)
306 static uint8_t count;
307 if (++count % 50) return;
310 if (!console_flush) return;
312 console_flush = false;
316 /** Event handler for the USB_ConfigurationChanged event.
317 * This is fired when the host sets the current configuration of the USB device after enumeration.
319 * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
320 * it is safe to use singl bank for all endpoints.
322 void EVENT_USB_Device_ConfigurationChanged(void)
324 bool ConfigSuccess = true;
326 /* Setup Keyboard HID Report Endpoints */
327 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
328 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
331 /* Setup Mouse HID Report Endpoint */
332 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
333 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
336 #ifdef EXTRAKEY_ENABLE
337 /* Setup Extra HID Report Endpoint */
338 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
339 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
342 #ifdef CONSOLE_ENABLE
343 /* Setup Console HID Report Endpoints */
344 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
345 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
347 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
348 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
353 /* Setup NKRO HID Report Endpoints */
354 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
355 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
359 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
360 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
363 #ifdef VIRTSER_ENABLE
364 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE);
365 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
366 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
371 Appendix G: HID Request Support Requirements
373 The following table enumerates the requests that need to be supported by various types of HID class devices.
375 Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
376 ------------------------------------------------------------------------------------------
377 Boot Mouse Required Optional Optional Optional Required Required
378 Non-Boot Mouse Required Optional Optional Optional Optional Optional
379 Boot Keyboard Required Optional Required Required Required Required
380 Non-Boot Keybrd Required Optional Required Required Optional Optional
381 Other Device Required Optional Optional Optional Optional Optional
383 /** Event handler for the USB_ControlRequest event.
384 * This is fired before passing along unhandled control requests to the library for processing internally.
386 void EVENT_USB_Device_ControlRequest(void)
388 uint8_t* ReportData = NULL;
389 uint8_t ReportSize = 0;
391 /* Handle HID Class specific requests */
392 switch (USB_ControlRequest.bRequest)
394 case HID_REQ_GetReport:
395 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
397 Endpoint_ClearSETUP();
400 switch (USB_ControlRequest.wIndex) {
401 case KEYBOARD_INTERFACE:
403 ReportData = (uint8_t*)&keyboard_report_sent;
404 ReportSize = sizeof(keyboard_report_sent);
408 /* Write the report data to the control endpoint */
409 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
414 case HID_REQ_SetReport:
415 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
419 switch (USB_ControlRequest.wIndex) {
420 case KEYBOARD_INTERFACE:
424 Endpoint_ClearSETUP();
426 while (!(Endpoint_IsOUTReceived())) {
427 if (USB_DeviceState == DEVICE_STATE_Unattached)
430 keyboard_led_stats = Endpoint_Read_8();
433 Endpoint_ClearStatusStage();
441 case HID_REQ_GetProtocol:
442 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
444 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
445 Endpoint_ClearSETUP();
446 while (!(Endpoint_IsINReady()));
447 Endpoint_Write_8(keyboard_protocol);
449 Endpoint_ClearStatusStage();
454 case HID_REQ_SetProtocol:
455 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
457 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
458 Endpoint_ClearSETUP();
459 Endpoint_ClearStatusStage();
461 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
467 case HID_REQ_SetIdle:
468 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
470 Endpoint_ClearSETUP();
471 Endpoint_ClearStatusStage();
473 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
477 case HID_REQ_GetIdle:
478 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
480 Endpoint_ClearSETUP();
481 while (!(Endpoint_IsINReady()));
482 Endpoint_Write_8(keyboard_idle);
484 Endpoint_ClearStatusStage();
490 #ifdef VIRTSER_ENABLE
491 CDC_Device_ProcessControlRequest(&cdc_device);
495 /*******************************************************************************
498 ******************************************************************************/
499 static uint8_t keyboard_leds(void)
501 return keyboard_led_stats;
504 static void send_keyboard(report_keyboard_t *report)
507 #ifdef BLUETOOTH_ENABLE
508 bluefruit_serial_send(0xFD);
509 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
510 bluefruit_serial_send(report->raw[i]);
514 uint8_t timeout = 255;
516 if (USB_DeviceState != DEVICE_STATE_Configured)
519 /* Select the Keyboard Report Endpoint */
521 if (keyboard_protocol && keymap_config.nkro) {
522 /* Report protocol - NKRO */
523 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
525 /* Check if write ready for a polling interval around 1ms */
526 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
527 if (!Endpoint_IsReadWriteAllowed()) return;
529 /* Write Keyboard Report Data */
530 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
536 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
538 /* Check if write ready for a polling interval around 10ms */
539 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
540 if (!Endpoint_IsReadWriteAllowed()) return;
542 /* Write Keyboard Report Data */
543 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
546 /* Finalize the stream transfer to send the last packet */
549 keyboard_report_sent = *report;
552 static void send_mouse(report_mouse_t *report)
556 #ifdef BLUETOOTH_ENABLE
557 bluefruit_serial_send(0xFD);
558 bluefruit_serial_send(0x00);
559 bluefruit_serial_send(0x03);
560 bluefruit_serial_send(report->buttons);
561 bluefruit_serial_send(report->x);
562 bluefruit_serial_send(report->y);
563 bluefruit_serial_send(report->v); // should try sending the wheel v here
564 bluefruit_serial_send(report->h); // should try sending the wheel h here
565 bluefruit_serial_send(0x00);
568 uint8_t timeout = 255;
570 if (USB_DeviceState != DEVICE_STATE_Configured)
573 /* Select the Mouse Report Endpoint */
574 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
576 /* Check if write ready for a polling interval around 10ms */
577 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
578 if (!Endpoint_IsReadWriteAllowed()) return;
580 /* Write Mouse Report Data */
581 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
583 /* Finalize the stream transfer to send the last packet */
588 static void send_system(uint16_t data)
590 uint8_t timeout = 255;
592 if (USB_DeviceState != DEVICE_STATE_Configured)
596 .report_id = REPORT_ID_SYSTEM,
599 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
601 /* Check if write ready for a polling interval around 10ms */
602 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
603 if (!Endpoint_IsReadWriteAllowed()) return;
605 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
609 static void send_consumer(uint16_t data)
612 #ifdef BLUETOOTH_ENABLE
613 static uint16_t last_data = 0;
614 if (data == last_data) return;
616 uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
617 bluefruit_serial_send(0xFD);
618 bluefruit_serial_send(0x00);
619 bluefruit_serial_send(0x02);
620 bluefruit_serial_send((bitmap>>8)&0xFF);
621 bluefruit_serial_send(bitmap&0xFF);
622 bluefruit_serial_send(0x00);
623 bluefruit_serial_send(0x00);
624 bluefruit_serial_send(0x00);
625 bluefruit_serial_send(0x00);
628 uint8_t timeout = 255;
630 if (USB_DeviceState != DEVICE_STATE_Configured)
634 .report_id = REPORT_ID_CONSUMER,
637 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
639 /* Check if write ready for a polling interval around 10ms */
640 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
641 if (!Endpoint_IsReadWriteAllowed()) return;
643 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
648 /*******************************************************************************
650 ******************************************************************************/
651 #ifdef CONSOLE_ENABLE
652 #define SEND_TIMEOUT 5
653 int8_t sendchar(uint8_t c)
655 // Not wait once timeouted.
656 // Because sendchar() is called so many times, waiting each call causes big lag.
657 static bool timeouted = false;
659 // prevents Console_Task() from running during sendchar() runs.
660 // or char will be lost. These two function is mutually exclusive.
661 CONSOLE_FLUSH_SET(false);
663 if (USB_DeviceState != DEVICE_STATE_Configured)
666 uint8_t ep = Endpoint_GetCurrentEndpoint();
667 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
668 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
672 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
678 uint8_t timeout = SEND_TIMEOUT;
679 while (!Endpoint_IsReadWriteAllowed()) {
680 if (USB_DeviceState != DEVICE_STATE_Configured) {
683 if (Endpoint_IsStalled()) {
695 // send when bank is full
696 if (!Endpoint_IsReadWriteAllowed()) {
697 while (!(Endpoint_IsINReady()));
700 CONSOLE_FLUSH_SET(true);
703 Endpoint_SelectEndpoint(ep);
706 Endpoint_SelectEndpoint(ep);
710 int8_t sendchar(uint8_t c)
716 /*******************************************************************************
718 ******************************************************************************/
721 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
722 MIDI_EventPacket_t event;
729 // Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
731 //if the length is undefined we assume it is a SYSEX message
732 if (midi_packet_length(byte0) == UNDEFINED) {
735 if (byte2 == SYSEX_END)
736 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
738 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
741 if (byte1 == SYSEX_END)
742 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
744 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
747 if (byte0 == SYSEX_END)
748 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
750 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
753 return; //invalid cnt
756 //deal with 'system common' messages
757 //TODO are there any more?
758 switch(byte0 & 0xF0){
759 case MIDI_SONGPOSITION:
760 event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
762 case MIDI_SONGSELECT:
763 case MIDI_TC_QUARTERFRAME:
764 event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
767 event.Event = MIDI_EVENT(cable, byte0);
772 // Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
773 // Endpoint_ClearIN();
775 MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
776 MIDI_Device_Flush(&USB_MIDI_Interface);
777 MIDI_Device_USBTask(&USB_MIDI_Interface);
781 static void usb_get_midi(MidiDevice * device) {
782 MIDI_EventPacket_t event;
783 while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
785 midi_packet_length_t length = midi_packet_length(event.Data1);
787 input[0] = event.Data1;
788 input[1] = event.Data2;
789 input[2] = event.Data3;
790 if (length == UNDEFINED) {
792 if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
794 } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
796 } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
803 //pass the data to the device input function
804 if (length != UNDEFINED)
805 midi_device_input(device, length, input);
807 MIDI_Device_USBTask(&USB_MIDI_Interface);
811 static void midi_usb_init(MidiDevice * device){
812 midi_device_init(device);
813 midi_device_set_send_func(device, usb_send_func);
814 midi_device_set_pre_input_process_func(device, usb_get_midi);
823 /* Device must be connected and configured for the task to run */
824 dprint("in MIDI_TASK\n");
825 if (USB_DeviceState != DEVICE_STATE_Configured)
827 dprint("continuing in MIDI_TASK\n");
829 Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
831 if (Endpoint_IsINReady())
834 dprint("Endpoint is ready\n");
836 uint8_t MIDICommand = 0;
839 /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
840 uint8_t Channel = MIDI_CHANNEL(1);
842 MIDICommand = MIDI_COMMAND_NOTE_ON;
845 /* Check if a MIDI command is to be sent */
848 dprint("Command exists\n");
849 MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
851 .Event = MIDI_EVENT(0, MIDICommand),
853 .Data1 = MIDICommand | Channel,
855 .Data3 = MIDI_STANDARD_VELOCITY,
858 /* Write the MIDI event packet to the endpoint */
859 Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
861 /* Send the data in the endpoint to the host */
867 /* Select the MIDI OUT stream */
868 Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
870 /* Check if a MIDI command has been received */
871 if (Endpoint_IsOUTReceived())
873 MIDI_EventPacket_t MIDIEvent;
875 /* Read the MIDI event packet from the endpoint */
876 Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
878 /* If the endpoint is now empty, clear the bank */
879 if (!(Endpoint_BytesInEndpoint()))
881 /* Clear the endpoint ready for new packet */
889 /*******************************************************************************
891 ******************************************************************************/
893 #ifdef VIRTSER_ENABLE
894 void virtser_init(void)
896 cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ;
897 CDC_Device_SendControlLineStateChange(&cdc_device);
900 void virtser_recv(uint8_t c) __attribute__ ((weak));
901 void virtser_recv(uint8_t c)
906 void virtser_task(void)
908 uint16_t count = CDC_Device_BytesReceived(&cdc_device);
912 ch = CDC_Device_ReceiveByte(&cdc_device);
916 void virtser_send(const uint8_t byte)
918 uint8_t timeout = 255;
919 uint8_t ep = Endpoint_GetCurrentEndpoint();
921 if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR)
924 Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address);
926 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
927 Endpoint_SelectEndpoint(ep);
931 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
933 Endpoint_Write_8(byte);
934 CDC_Device_Flush(&cdc_device);
936 if (Endpoint_IsINReady()) {
940 Endpoint_SelectEndpoint(ep);
945 /*******************************************************************************
947 ******************************************************************************/
948 static void setup_mcu(void)
950 /* Disable watchdog if enabled by bootloader/fuses */
951 MCUSR &= ~(1 << WDRF);
954 /* Disable clock division */
955 // clock_prescale_set(clock_div_1);
957 CLKPR = (1 << CLKPCE);
958 CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
961 static void setup_usb(void)
963 // Leonardo needs. Without this USB device is not recognized.
969 USB_Device_EnableSOFEvents();
970 print_set_sendchar(sendchar);
975 void fallthrough_callback(MidiDevice * device,
976 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
977 void cc_callback(MidiDevice * device,
978 uint8_t chan, uint8_t num, uint8_t val);
979 void sysex_callback(MidiDevice * device,
980 uint16_t start, uint8_t length, uint8_t * data);
983 int main(void) __attribute__ ((weak));
988 midi_device_init(&midi_device);
989 midi_device_set_send_func(&midi_device, usb_send_func);
990 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
999 midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
1000 midi_register_cc_callback(&midi_device, cc_callback);
1001 midi_register_sysex_callback(&midi_device, sysex_callback);
1004 // midi_send_cc(&midi_device, 0, 1, 2);
1005 // midi_send_cc(&midi_device, 15, 1, 0);
1006 // midi_send_noteon(&midi_device, 0, 64, 127);
1007 // midi_send_noteoff(&midi_device, 0, 64, 127);
1010 #ifdef BLUETOOTH_ENABLE
1014 /* wait for USB startup & debug output */
1017 while (USB_DeviceState != DEVICE_STATE_Configured) {
1018 #if defined(INTERRUPT_CONTROL_ENDPOINT)
1024 print("USB configured.\n");
1030 host_set_driver(&lufa_driver);
1031 #ifdef SLEEP_LED_ENABLE
1035 #ifdef VIRTSER_ENABLE
1039 print("Keyboard start.\n");
1041 #ifndef BLUETOOTH_ENABLE
1042 while (USB_DeviceState == DEVICE_STATE_Suspended) {
1044 suspend_power_down();
1045 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
1046 USB_Device_SendRemoteWakeup();
1054 midi_device_process(&midi_device);
1058 #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
1062 #ifdef VIRTSER_ENABLE
1064 CDC_Device_USBTask(&cdc_device);
1067 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
1074 void fallthrough_callback(MidiDevice * device,
1075 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
1079 switch (byte0 & 0xF0) {
1081 play_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
1084 stop_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0));
1088 if (byte0 == MIDI_STOP) {
1095 void cc_callback(MidiDevice * device,
1096 uint8_t chan, uint8_t num, uint8_t val) {
1097 //sending it back on the next channel
1098 // midi_send_cc(device, (chan + 1) % 16, num, val);
1101 uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
1103 void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
1104 #ifdef API_SYSEX_ENABLE
1105 // SEND_STRING("\n");
1106 // send_word(start);
1107 // SEND_STRING(": ");
1108 for (uint8_t place = 0; place < length; place++) {
1109 // send_byte(*data);
1110 midi_buffer[start + place] = *data;
1111 if (*data == 0xF7) {
1112 // SEND_STRING("\nRD: ");
1113 // for (uint8_t i = 0; i < start + place + 1; i++){
1114 // send_byte(midi_buffer[i]);
1115 // SEND_STRING(" ");
1117 uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4)));
1118 uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4);
1119 process_api(decode_length, decoded);
1121 // SEND_STRING(" ");