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"
55 #include <util/atomic.h>
56 #include "outputselect.h"
59 #include "keycode_config.h"
61 extern keymap_config_t keymap_config;
69 #ifdef BLUETOOTH_ENABLE
70 #include "bluetooth.h"
72 #ifdef ADAFRUIT_BLE_ENABLE
73 #include "adafruit_ble.h"
80 #if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
85 #include "sysex_tools.h"
92 uint8_t keyboard_idle = 0;
93 /* 0: Boot Protocol, 1: Report Protocol(default) */
94 uint8_t keyboard_protocol = 1;
95 static uint8_t keyboard_led_stats = 0;
97 static report_keyboard_t keyboard_report_sent;
100 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
101 static void usb_get_midi(MidiDevice * device);
102 static void midi_usb_init(MidiDevice * device);
106 static uint8_t keyboard_leds(void);
107 static void send_keyboard(report_keyboard_t *report);
108 static void send_mouse(report_mouse_t *report);
109 static void send_system(uint16_t data);
110 static void send_consumer(uint16_t data);
111 host_driver_t lufa_driver = {
124 /*******************************************************************************
126 ******************************************************************************/
129 USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
133 .StreamingInterfaceNumber = AS_INTERFACE,
136 .Address = MIDI_STREAM_IN_EPADDR,
137 .Size = MIDI_STREAM_EPSIZE,
142 .Address = MIDI_STREAM_OUT_EPADDR,
143 .Size = MIDI_STREAM_EPSIZE,
149 #define SYSEX_START_OR_CONT 0x40
150 #define SYSEX_ENDS_IN_1 0x50
151 #define SYSEX_ENDS_IN_2 0x60
152 #define SYSEX_ENDS_IN_3 0x70
154 #define SYS_COMMON_1 0x50
155 #define SYS_COMMON_2 0x20
156 #define SYS_COMMON_3 0x30
159 #ifdef VIRTSER_ENABLE
160 USB_ClassInfo_CDC_Device_t cdc_device =
164 .ControlInterfaceNumber = CCI_INTERFACE,
167 .Address = CDC_IN_EPADDR,
173 .Address = CDC_OUT_EPADDR,
177 .NotificationEndpoint =
179 .Address = CDC_NOTIFICATION_EPADDR,
180 .Size = CDC_NOTIFICATION_EPSIZE,
189 void raw_hid_send( uint8_t *data, uint8_t length )
191 // TODO: implement variable size packet
192 if ( length != RAW_EPSIZE )
197 if (USB_DeviceState != DEVICE_STATE_Configured)
202 // TODO: decide if we allow calls to raw_hid_send() in the middle
203 // of other endpoint usage.
204 uint8_t ep = Endpoint_GetCurrentEndpoint();
206 Endpoint_SelectEndpoint(RAW_IN_EPNUM);
208 // Check to see if the host is ready to accept another packet
209 if (Endpoint_IsINReady())
212 Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL);
213 // Finalize the stream transfer to send the last packet
217 Endpoint_SelectEndpoint(ep);
220 __attribute__ ((weak))
221 void raw_hid_receive( uint8_t *data, uint8_t length )
223 // Users should #include "raw_hid.h" in their own code
224 // and implement this function there. Leave this as weak linkage
225 // so users can opt to not handle data coming in.
228 static void raw_hid_task(void)
230 // Create a temporary buffer to hold the read in data from the host
231 uint8_t data[RAW_EPSIZE];
232 bool data_read = false;
234 // Device must be connected and configured for the task to run
235 if (USB_DeviceState != DEVICE_STATE_Configured)
238 Endpoint_SelectEndpoint(RAW_OUT_EPNUM);
240 // Check to see if a packet has been sent from the host
241 if (Endpoint_IsOUTReceived())
243 // Check to see if the packet contains data
244 if (Endpoint_IsReadWriteAllowed())
247 Endpoint_Read_Stream_LE(data, sizeof(data), NULL);
251 // Finalize the stream transfer to receive the last packet
256 raw_hid_receive( data, sizeof(data) );
262 /*******************************************************************************
264 ******************************************************************************/
265 #ifdef CONSOLE_ENABLE
266 static void Console_Task(void)
268 /* Device must be connected and configured for the task to run */
269 if (USB_DeviceState != DEVICE_STATE_Configured)
272 uint8_t ep = Endpoint_GetCurrentEndpoint();
275 // TODO: impl receivechar()/recvchar()
276 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
278 /* Check to see if a packet has been sent from the host */
279 if (Endpoint_IsOUTReceived())
281 /* Check to see if the packet contains data */
282 if (Endpoint_IsReadWriteAllowed())
284 /* Create a temporary buffer to hold the read in report from the host */
285 uint8_t ConsoleData[CONSOLE_EPSIZE];
287 /* Read Console Report Data */
288 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
290 /* Process Console Report Data */
291 //ProcessConsoleHIDReport(ConsoleData);
294 /* Finalize the stream transfer to send the last packet */
300 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
301 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
302 Endpoint_SelectEndpoint(ep);
307 while (Endpoint_IsReadWriteAllowed())
310 // flash senchar packet
311 if (Endpoint_IsINReady()) {
315 Endpoint_SelectEndpoint(ep);
320 /*******************************************************************************
322 ******************************************************************************/
324 * Event Order of Plug in:
325 * 0) EVENT_USB_Device_Connect
326 * 1) EVENT_USB_Device_Suspend
327 * 2) EVENT_USB_Device_Reset
328 * 3) EVENT_USB_Device_Wake
330 void EVENT_USB_Device_Connect(void)
333 /* For battery powered device */
334 if (!USB_IsInitialized) {
337 USB_Device_EnableSOFEvents();
341 void EVENT_USB_Device_Disconnect(void)
344 /* For battery powered device */
345 USB_IsInitialized = false;
346 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
347 if (USB_IsInitialized) {
348 USB_Disable(); // Disable all interrupts
349 USB_Controller_Enable();
350 USB_INT_Enable(USB_INT_VBUSTI);
355 void EVENT_USB_Device_Reset(void)
360 void EVENT_USB_Device_Suspend()
363 #ifdef SLEEP_LED_ENABLE
368 void EVENT_USB_Device_WakeUp()
371 suspend_wakeup_init();
373 #ifdef SLEEP_LED_ENABLE
375 // NOTE: converters may not accept this
376 led_set(host_keyboard_leds());
382 #ifdef CONSOLE_ENABLE
383 static bool console_flush = false;
384 #define CONSOLE_FLUSH_SET(b) do { \
385 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {\
391 void EVENT_USB_Device_StartOfFrame(void)
393 static uint8_t count;
394 if (++count % 50) return;
397 if (!console_flush) return;
399 console_flush = false;
404 /** Event handler for the USB_ConfigurationChanged event.
405 * This is fired when the host sets the current configuration of the USB device after enumeration.
407 * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
408 * it is safe to use singl bank for all endpoints.
410 void EVENT_USB_Device_ConfigurationChanged(void)
412 bool ConfigSuccess = true;
414 /* Setup Keyboard HID Report Endpoints */
415 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
416 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
419 /* Setup Mouse HID Report Endpoint */
420 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
421 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
424 #ifdef EXTRAKEY_ENABLE
425 /* Setup Extra HID Report Endpoint */
426 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
427 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
431 /* Setup Raw HID Report Endpoints */
432 ConfigSuccess &= ENDPOINT_CONFIG(RAW_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
433 RAW_EPSIZE, ENDPOINT_BANK_SINGLE);
434 ConfigSuccess &= ENDPOINT_CONFIG(RAW_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
435 RAW_EPSIZE, ENDPOINT_BANK_SINGLE);
438 #ifdef CONSOLE_ENABLE
439 /* Setup Console HID Report Endpoints */
440 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
441 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
443 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
444 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
449 /* Setup NKRO HID Report Endpoints */
450 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
451 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
455 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
456 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
459 #ifdef VIRTSER_ENABLE
460 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE);
461 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
462 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
467 Appendix G: HID Request Support Requirements
469 The following table enumerates the requests that need to be supported by various types of HID class devices.
471 Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
472 ------------------------------------------------------------------------------------------
473 Boot Mouse Required Optional Optional Optional Required Required
474 Non-Boot Mouse Required Optional Optional Optional Optional Optional
475 Boot Keyboard Required Optional Required Required Required Required
476 Non-Boot Keybrd Required Optional Required Required Optional Optional
477 Other Device Required Optional Optional Optional Optional Optional
479 /** Event handler for the USB_ControlRequest event.
480 * This is fired before passing along unhandled control requests to the library for processing internally.
482 void EVENT_USB_Device_ControlRequest(void)
484 uint8_t* ReportData = NULL;
485 uint8_t ReportSize = 0;
487 /* Handle HID Class specific requests */
488 switch (USB_ControlRequest.bRequest)
490 case HID_REQ_GetReport:
491 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
493 Endpoint_ClearSETUP();
496 switch (USB_ControlRequest.wIndex) {
497 case KEYBOARD_INTERFACE:
499 ReportData = (uint8_t*)&keyboard_report_sent;
500 ReportSize = sizeof(keyboard_report_sent);
504 /* Write the report data to the control endpoint */
505 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
510 case HID_REQ_SetReport:
511 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
515 switch (USB_ControlRequest.wIndex) {
516 case KEYBOARD_INTERFACE:
520 Endpoint_ClearSETUP();
522 while (!(Endpoint_IsOUTReceived())) {
523 if (USB_DeviceState == DEVICE_STATE_Unattached)
526 keyboard_led_stats = Endpoint_Read_8();
529 Endpoint_ClearStatusStage();
537 case HID_REQ_GetProtocol:
538 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
540 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
541 Endpoint_ClearSETUP();
542 while (!(Endpoint_IsINReady()));
543 Endpoint_Write_8(keyboard_protocol);
545 Endpoint_ClearStatusStage();
550 case HID_REQ_SetProtocol:
551 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
553 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
554 Endpoint_ClearSETUP();
555 Endpoint_ClearStatusStage();
557 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
563 case HID_REQ_SetIdle:
564 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
566 Endpoint_ClearSETUP();
567 Endpoint_ClearStatusStage();
569 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
573 case HID_REQ_GetIdle:
574 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
576 Endpoint_ClearSETUP();
577 while (!(Endpoint_IsINReady()));
578 Endpoint_Write_8(keyboard_idle);
580 Endpoint_ClearStatusStage();
586 #ifdef VIRTSER_ENABLE
587 CDC_Device_ProcessControlRequest(&cdc_device);
591 /*******************************************************************************
593 ******************************************************************************/
594 static uint8_t keyboard_leds(void)
596 return keyboard_led_stats;
599 static void send_keyboard(report_keyboard_t *report)
601 uint8_t timeout = 255;
602 uint8_t where = where_to_send();
604 #ifdef BLUETOOTH_ENABLE
605 if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
606 bluefruit_serial_send(0xFD);
607 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
608 bluefruit_serial_send(report->raw[i]);
613 #ifdef ADAFRUIT_BLE_ENABLE
614 if (where == OUTPUT_ADAFRUIT_BLE) {
615 adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
619 if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
623 /* Select the Keyboard Report Endpoint */
625 if (keyboard_protocol && keymap_config.nkro) {
626 /* Report protocol - NKRO */
627 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
629 /* Check if write ready for a polling interval around 1ms */
630 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
631 if (!Endpoint_IsReadWriteAllowed()) return;
633 /* Write Keyboard Report Data */
634 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
640 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
642 /* Check if write ready for a polling interval around 10ms */
643 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
644 if (!Endpoint_IsReadWriteAllowed()) return;
646 /* Write Keyboard Report Data */
647 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
650 /* Finalize the stream transfer to send the last packet */
653 keyboard_report_sent = *report;
656 static void send_mouse(report_mouse_t *report)
659 uint8_t timeout = 255;
660 uint8_t where = where_to_send();
662 #ifdef BLUETOOTH_ENABLE
663 if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
664 bluefruit_serial_send(0xFD);
665 bluefruit_serial_send(0x00);
666 bluefruit_serial_send(0x03);
667 bluefruit_serial_send(report->buttons);
668 bluefruit_serial_send(report->x);
669 bluefruit_serial_send(report->y);
670 bluefruit_serial_send(report->v); // should try sending the wheel v here
671 bluefruit_serial_send(report->h); // should try sending the wheel h here
672 bluefruit_serial_send(0x00);
676 #ifdef ADAFRUIT_BLE_ENABLE
677 if (where == OUTPUT_ADAFRUIT_BLE) {
678 // FIXME: mouse buttons
679 adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h);
683 if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
687 /* Select the Mouse Report Endpoint */
688 Endpoint_SelectEndpoint(MOUSE_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 /* Write Mouse Report Data */
695 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
697 /* Finalize the stream transfer to send the last packet */
702 static void send_system(uint16_t data)
704 uint8_t timeout = 255;
706 if (USB_DeviceState != DEVICE_STATE_Configured)
710 .report_id = REPORT_ID_SYSTEM,
711 .usage = data - SYSTEM_POWER_DOWN + 1
713 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
715 /* Check if write ready for a polling interval around 10ms */
716 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
717 if (!Endpoint_IsReadWriteAllowed()) return;
719 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
723 static void send_consumer(uint16_t data)
725 uint8_t timeout = 255;
726 uint8_t where = where_to_send();
728 #ifdef BLUETOOTH_ENABLE
729 if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
730 static uint16_t last_data = 0;
731 if (data == last_data) return;
733 uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
734 bluefruit_serial_send(0xFD);
735 bluefruit_serial_send(0x00);
736 bluefruit_serial_send(0x02);
737 bluefruit_serial_send((bitmap>>8)&0xFF);
738 bluefruit_serial_send(bitmap&0xFF);
739 bluefruit_serial_send(0x00);
740 bluefruit_serial_send(0x00);
741 bluefruit_serial_send(0x00);
742 bluefruit_serial_send(0x00);
746 #ifdef ADAFRUIT_BLE_ENABLE
747 if (where == OUTPUT_ADAFRUIT_BLE) {
748 adafruit_ble_send_consumer_key(data, 0);
752 if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
757 .report_id = REPORT_ID_CONSUMER,
760 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
762 /* Check if write ready for a polling interval around 10ms */
763 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
764 if (!Endpoint_IsReadWriteAllowed()) return;
766 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
771 /*******************************************************************************
773 ******************************************************************************/
774 #ifdef CONSOLE_ENABLE
775 #define SEND_TIMEOUT 5
776 int8_t sendchar(uint8_t c)
778 // Not wait once timeouted.
779 // Because sendchar() is called so many times, waiting each call causes big lag.
780 static bool timeouted = false;
782 // prevents Console_Task() from running during sendchar() runs.
783 // or char will be lost. These two function is mutually exclusive.
784 CONSOLE_FLUSH_SET(false);
786 if (USB_DeviceState != DEVICE_STATE_Configured)
789 uint8_t ep = Endpoint_GetCurrentEndpoint();
790 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
791 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
795 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
801 uint8_t timeout = SEND_TIMEOUT;
802 while (!Endpoint_IsReadWriteAllowed()) {
803 if (USB_DeviceState != DEVICE_STATE_Configured) {
806 if (Endpoint_IsStalled()) {
818 // send when bank is full
819 if (!Endpoint_IsReadWriteAllowed()) {
820 while (!(Endpoint_IsINReady()));
823 CONSOLE_FLUSH_SET(true);
826 Endpoint_SelectEndpoint(ep);
829 Endpoint_SelectEndpoint(ep);
833 int8_t sendchar(uint8_t c)
839 /*******************************************************************************
841 ******************************************************************************/
844 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
845 MIDI_EventPacket_t event;
852 // Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
854 //if the length is undefined we assume it is a SYSEX message
855 if (midi_packet_length(byte0) == UNDEFINED) {
858 if (byte2 == SYSEX_END)
859 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
861 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
864 if (byte1 == SYSEX_END)
865 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
867 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
870 if (byte0 == SYSEX_END)
871 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
873 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
876 return; //invalid cnt
879 //deal with 'system common' messages
880 //TODO are there any more?
881 switch(byte0 & 0xF0){
882 case MIDI_SONGPOSITION:
883 event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
885 case MIDI_SONGSELECT:
886 case MIDI_TC_QUARTERFRAME:
887 event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
890 event.Event = MIDI_EVENT(cable, byte0);
895 // Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
896 // Endpoint_ClearIN();
898 MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
899 MIDI_Device_Flush(&USB_MIDI_Interface);
900 MIDI_Device_USBTask(&USB_MIDI_Interface);
904 static void usb_get_midi(MidiDevice * device) {
905 MIDI_EventPacket_t event;
906 while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
908 midi_packet_length_t length = midi_packet_length(event.Data1);
910 input[0] = event.Data1;
911 input[1] = event.Data2;
912 input[2] = event.Data3;
913 if (length == UNDEFINED) {
915 if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
917 } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
919 } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
926 //pass the data to the device input function
927 if (length != UNDEFINED)
928 midi_device_input(device, length, input);
930 MIDI_Device_USBTask(&USB_MIDI_Interface);
934 static void midi_usb_init(MidiDevice * device){
935 midi_device_init(device);
936 midi_device_set_send_func(device, usb_send_func);
937 midi_device_set_pre_input_process_func(device, usb_get_midi);
946 /* Device must be connected and configured for the task to run */
947 dprint("in MIDI_TASK\n");
948 if (USB_DeviceState != DEVICE_STATE_Configured)
950 dprint("continuing in MIDI_TASK\n");
952 Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
954 if (Endpoint_IsINReady())
957 dprint("Endpoint is ready\n");
959 uint8_t MIDICommand = 0;
962 /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
963 uint8_t Channel = MIDI_CHANNEL(1);
965 MIDICommand = MIDI_COMMAND_NOTE_ON;
968 /* Check if a MIDI command is to be sent */
971 dprint("Command exists\n");
972 MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
974 .Event = MIDI_EVENT(0, MIDICommand),
976 .Data1 = MIDICommand | Channel,
978 .Data3 = MIDI_STANDARD_VELOCITY,
981 /* Write the MIDI event packet to the endpoint */
982 Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
984 /* Send the data in the endpoint to the host */
990 /* Select the MIDI OUT stream */
991 Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
993 /* Check if a MIDI command has been received */
994 if (Endpoint_IsOUTReceived())
996 MIDI_EventPacket_t MIDIEvent;
998 /* Read the MIDI event packet from the endpoint */
999 Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
1001 /* If the endpoint is now empty, clear the bank */
1002 if (!(Endpoint_BytesInEndpoint()))
1004 /* Clear the endpoint ready for new packet */
1005 Endpoint_ClearOUT();
1012 /*******************************************************************************
1014 ******************************************************************************/
1016 #ifdef VIRTSER_ENABLE
1017 void virtser_init(void)
1019 cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ;
1020 CDC_Device_SendControlLineStateChange(&cdc_device);
1023 void virtser_recv(uint8_t c) __attribute__ ((weak));
1024 void virtser_recv(uint8_t c)
1026 // Ignore by default
1029 void virtser_task(void)
1031 uint16_t count = CDC_Device_BytesReceived(&cdc_device);
1035 ch = CDC_Device_ReceiveByte(&cdc_device);
1039 void virtser_send(const uint8_t byte)
1041 uint8_t timeout = 255;
1042 uint8_t ep = Endpoint_GetCurrentEndpoint();
1044 if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR)
1047 Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address);
1049 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
1050 Endpoint_SelectEndpoint(ep);
1054 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
1056 Endpoint_Write_8(byte);
1057 CDC_Device_Flush(&cdc_device);
1059 if (Endpoint_IsINReady()) {
1063 Endpoint_SelectEndpoint(ep);
1068 /*******************************************************************************
1070 ******************************************************************************/
1071 static void setup_mcu(void)
1073 /* Disable watchdog if enabled by bootloader/fuses */
1074 MCUSR &= ~(1 << WDRF);
1077 /* Disable clock division */
1078 // clock_prescale_set(clock_div_1);
1080 CLKPR = (1 << CLKPCE);
1081 CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
1084 static void setup_usb(void)
1086 // Leonardo needs. Without this USB device is not recognized.
1092 USB_Device_EnableSOFEvents();
1093 print_set_sendchar(sendchar);
1098 void fallthrough_callback(MidiDevice * device,
1099 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
1100 void cc_callback(MidiDevice * device,
1101 uint8_t chan, uint8_t num, uint8_t val);
1102 void sysex_callback(MidiDevice * device,
1103 uint16_t start, uint8_t length, uint8_t * data);
1106 int main(void) __attribute__ ((weak));
1111 midi_device_init(&midi_device);
1112 midi_device_set_send_func(&midi_device, usb_send_func);
1113 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
1122 midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
1123 midi_register_cc_callback(&midi_device, cc_callback);
1124 midi_register_sysex_callback(&midi_device, sysex_callback);
1127 // midi_send_cc(&midi_device, 0, 1, 2);
1128 // midi_send_cc(&midi_device, 15, 1, 0);
1129 // midi_send_noteon(&midi_device, 0, 64, 127);
1130 // midi_send_noteoff(&midi_device, 0, 64, 127);
1133 #ifdef BLUETOOTH_ENABLE
1137 /* wait for USB startup & debug output */
1140 while (USB_DeviceState != DEVICE_STATE_Configured) {
1141 #if defined(INTERRUPT_CONTROL_ENDPOINT)
1147 print("USB configured.\n");
1153 host_set_driver(&lufa_driver);
1154 #ifdef SLEEP_LED_ENABLE
1158 #ifdef VIRTSER_ENABLE
1162 print("Keyboard start.\n");
1164 #if !defined(BLUETOOTH_ENABLE) && !defined(ADAFRUIT_BLE_ENABLE)
1165 while (USB_DeviceState == DEVICE_STATE_Suspended) {
1167 suspend_power_down();
1168 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
1169 USB_Device_SendRemoteWakeup();
1177 midi_device_process(&midi_device);
1181 #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
1185 #ifdef ADAFRUIT_BLE_ENABLE
1186 adafruit_ble_task();
1189 #ifdef VIRTSER_ENABLE
1191 CDC_Device_USBTask(&cdc_device);
1198 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
1206 void fallthrough_callback(MidiDevice * device,
1207 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
1211 switch (byte0 & 0xF0) {
1213 play_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
1216 stop_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0));
1220 if (byte0 == MIDI_STOP) {
1227 void cc_callback(MidiDevice * device,
1228 uint8_t chan, uint8_t num, uint8_t val) {
1229 //sending it back on the next channel
1230 // midi_send_cc(device, (chan + 1) % 16, num, val);
1233 #ifdef API_SYSEX_ENABLE
1234 uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
1237 void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
1238 #ifdef API_SYSEX_ENABLE
1239 // SEND_STRING("\n");
1240 // send_word(start);
1241 // SEND_STRING(": ");
1242 // Don't store the header
1243 int16_t pos = start - 4;
1244 for (uint8_t place = 0; place < length; place++) {
1245 // send_byte(*data);
1247 if (*data == 0xF7) {
1248 // SEND_STRING("\nRD: ");
1249 // for (uint8_t i = 0; i < start + place + 1; i++){
1250 // send_byte(midi_buffer[i]);
1251 // SEND_STRING(" ");
1253 const unsigned decoded_length = sysex_decoded_length(pos);
1254 uint8_t decoded[API_SYSEX_MAX_SIZE];
1255 sysex_decode(decoded, midi_buffer, pos);
1256 process_api(decoded_length, decoded);
1259 else if (pos >= MIDI_SYSEX_BUFFER) {
1262 midi_buffer[pos] = *data;
1264 // SEND_STRING(" ");