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>
58 #include "keycode_config.h"
60 extern keymap_config_t keymap_config;
68 #ifdef BLUETOOTH_ENABLE
69 #include "bluetooth.h"
71 #ifdef ADAFRUIT_BLE_ENABLE
72 #include "adafruit_ble.h"
79 #if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
84 #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,
183 /*******************************************************************************
185 ******************************************************************************/
186 #ifdef CONSOLE_ENABLE
187 static void Console_Task(void)
189 /* Device must be connected and configured for the task to run */
190 if (USB_DeviceState != DEVICE_STATE_Configured)
193 uint8_t ep = Endpoint_GetCurrentEndpoint();
196 // TODO: impl receivechar()/recvchar()
197 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
199 /* Check to see if a packet has been sent from the host */
200 if (Endpoint_IsOUTReceived())
202 /* Check to see if the packet contains data */
203 if (Endpoint_IsReadWriteAllowed())
205 /* Create a temporary buffer to hold the read in report from the host */
206 uint8_t ConsoleData[CONSOLE_EPSIZE];
208 /* Read Console Report Data */
209 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
211 /* Process Console Report Data */
212 //ProcessConsoleHIDReport(ConsoleData);
215 /* Finalize the stream transfer to send the last packet */
221 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
222 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
223 Endpoint_SelectEndpoint(ep);
228 while (Endpoint_IsReadWriteAllowed())
231 // flash senchar packet
232 if (Endpoint_IsINReady()) {
236 Endpoint_SelectEndpoint(ep);
241 /*******************************************************************************
243 ******************************************************************************/
245 * Event Order of Plug in:
246 * 0) EVENT_USB_Device_Connect
247 * 1) EVENT_USB_Device_Suspend
248 * 2) EVENT_USB_Device_Reset
249 * 3) EVENT_USB_Device_Wake
251 void EVENT_USB_Device_Connect(void)
254 /* For battery powered device */
255 if (!USB_IsInitialized) {
258 USB_Device_EnableSOFEvents();
262 void EVENT_USB_Device_Disconnect(void)
265 /* For battery powered device */
266 USB_IsInitialized = false;
267 /* TODO: This doesn't work. After several plug in/outs can not be enumerated.
268 if (USB_IsInitialized) {
269 USB_Disable(); // Disable all interrupts
270 USB_Controller_Enable();
271 USB_INT_Enable(USB_INT_VBUSTI);
276 void EVENT_USB_Device_Reset(void)
281 void EVENT_USB_Device_Suspend()
284 #ifdef SLEEP_LED_ENABLE
289 void EVENT_USB_Device_WakeUp()
292 suspend_wakeup_init();
294 #ifdef SLEEP_LED_ENABLE
296 // NOTE: converters may not accept this
297 led_set(host_keyboard_leds());
301 #ifdef CONSOLE_ENABLE
302 static bool console_flush = false;
303 #define CONSOLE_FLUSH_SET(b) do { \
304 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {\
310 void EVENT_USB_Device_StartOfFrame(void)
312 static uint8_t count;
313 if (++count % 50) return;
316 if (!console_flush) return;
318 console_flush = false;
322 /** Event handler for the USB_ConfigurationChanged event.
323 * This is fired when the host sets the current configuration of the USB device after enumeration.
325 * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
326 * it is safe to use singl bank for all endpoints.
328 void EVENT_USB_Device_ConfigurationChanged(void)
330 bool ConfigSuccess = true;
332 /* Setup Keyboard HID Report Endpoints */
333 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
334 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
337 /* Setup Mouse HID Report Endpoint */
338 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
339 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
342 #ifdef EXTRAKEY_ENABLE
343 /* Setup Extra HID Report Endpoint */
344 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
345 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
348 #ifdef CONSOLE_ENABLE
349 /* Setup Console HID Report Endpoints */
350 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
351 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
353 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
354 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
359 /* Setup NKRO HID Report Endpoints */
360 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
361 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
365 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
366 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
369 #ifdef VIRTSER_ENABLE
370 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE);
371 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
372 ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
377 Appendix G: HID Request Support Requirements
379 The following table enumerates the requests that need to be supported by various types of HID class devices.
381 Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
382 ------------------------------------------------------------------------------------------
383 Boot Mouse Required Optional Optional Optional Required Required
384 Non-Boot Mouse Required Optional Optional Optional Optional Optional
385 Boot Keyboard Required Optional Required Required Required Required
386 Non-Boot Keybrd Required Optional Required Required Optional Optional
387 Other Device Required Optional Optional Optional Optional Optional
389 /** Event handler for the USB_ControlRequest event.
390 * This is fired before passing along unhandled control requests to the library for processing internally.
392 void EVENT_USB_Device_ControlRequest(void)
394 uint8_t* ReportData = NULL;
395 uint8_t ReportSize = 0;
397 /* Handle HID Class specific requests */
398 switch (USB_ControlRequest.bRequest)
400 case HID_REQ_GetReport:
401 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
403 Endpoint_ClearSETUP();
406 switch (USB_ControlRequest.wIndex) {
407 case KEYBOARD_INTERFACE:
409 ReportData = (uint8_t*)&keyboard_report_sent;
410 ReportSize = sizeof(keyboard_report_sent);
414 /* Write the report data to the control endpoint */
415 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
420 case HID_REQ_SetReport:
421 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
425 switch (USB_ControlRequest.wIndex) {
426 case KEYBOARD_INTERFACE:
430 Endpoint_ClearSETUP();
432 while (!(Endpoint_IsOUTReceived())) {
433 if (USB_DeviceState == DEVICE_STATE_Unattached)
436 keyboard_led_stats = Endpoint_Read_8();
439 Endpoint_ClearStatusStage();
447 case HID_REQ_GetProtocol:
448 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
450 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
451 Endpoint_ClearSETUP();
452 while (!(Endpoint_IsINReady()));
453 Endpoint_Write_8(keyboard_protocol);
455 Endpoint_ClearStatusStage();
460 case HID_REQ_SetProtocol:
461 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
463 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
464 Endpoint_ClearSETUP();
465 Endpoint_ClearStatusStage();
467 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
473 case HID_REQ_SetIdle:
474 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
476 Endpoint_ClearSETUP();
477 Endpoint_ClearStatusStage();
479 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
483 case HID_REQ_GetIdle:
484 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
486 Endpoint_ClearSETUP();
487 while (!(Endpoint_IsINReady()));
488 Endpoint_Write_8(keyboard_idle);
490 Endpoint_ClearStatusStage();
496 #ifdef VIRTSER_ENABLE
497 CDC_Device_ProcessControlRequest(&cdc_device);
501 /*******************************************************************************
504 ******************************************************************************/
505 static uint8_t keyboard_leds(void)
507 return keyboard_led_stats;
514 static inline uint8_t where_to_send(void) {
515 #ifdef ADAFRUIT_BLE_ENABLE
517 if (adafruit_ble_is_connected()) {
518 // For testing, send to BLE as a priority
523 // This is the real policy
524 if (USB_DeviceState != DEVICE_STATE_Configured) {
525 if (adafruit_ble_is_connected()) {
530 return ((USB_DeviceState == DEVICE_STATE_Configured) ? SendToUSB : 0)
531 #ifdef BLUETOOTH_ENABLE
537 static void send_keyboard(report_keyboard_t *report)
539 #ifdef BLUETOOTH_ENABLE
540 bluefruit_serial_send(0xFD);
541 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
542 bluefruit_serial_send(report->raw[i]);
546 uint8_t timeout = 255;
547 uint8_t where = where_to_send();
549 #ifdef ADAFRUIT_BLE_ENABLE
550 if (where & SendToBLE) {
551 adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
555 if (!(where & SendToUSB)) {
559 /* Select the Keyboard Report Endpoint */
561 if (keyboard_protocol && keymap_config.nkro) {
562 /* Report protocol - NKRO */
563 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
565 /* Check if write ready for a polling interval around 1ms */
566 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
567 if (!Endpoint_IsReadWriteAllowed()) return;
569 /* Write Keyboard Report Data */
570 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
576 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
578 /* Check if write ready for a polling interval around 10ms */
579 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
580 if (!Endpoint_IsReadWriteAllowed()) return;
582 /* Write Keyboard Report Data */
583 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
586 /* Finalize the stream transfer to send the last packet */
589 keyboard_report_sent = *report;
592 static void send_mouse(report_mouse_t *report)
596 #ifdef BLUETOOTH_ENABLE
597 bluefruit_serial_send(0xFD);
598 bluefruit_serial_send(0x00);
599 bluefruit_serial_send(0x03);
600 bluefruit_serial_send(report->buttons);
601 bluefruit_serial_send(report->x);
602 bluefruit_serial_send(report->y);
603 bluefruit_serial_send(report->v); // should try sending the wheel v here
604 bluefruit_serial_send(report->h); // should try sending the wheel h here
605 bluefruit_serial_send(0x00);
608 uint8_t timeout = 255;
610 uint8_t where = where_to_send();
612 #ifdef ADAFRUIT_BLE_ENABLE
613 if (where & SendToBLE) {
614 // FIXME: mouse buttons
615 adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h);
618 if (!(where & SendToUSB)) {
622 /* Select the Mouse Report Endpoint */
623 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
625 /* Check if write ready for a polling interval around 10ms */
626 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
627 if (!Endpoint_IsReadWriteAllowed()) return;
629 /* Write Mouse Report Data */
630 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
632 /* Finalize the stream transfer to send the last packet */
637 static void send_system(uint16_t data)
639 uint8_t timeout = 255;
641 if (USB_DeviceState != DEVICE_STATE_Configured)
645 .report_id = REPORT_ID_SYSTEM,
648 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
650 /* Check if write ready for a polling interval around 10ms */
651 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
652 if (!Endpoint_IsReadWriteAllowed()) return;
654 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
658 static void send_consumer(uint16_t data)
661 #ifdef BLUETOOTH_ENABLE
662 static uint16_t last_data = 0;
663 if (data == last_data) return;
665 uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
666 bluefruit_serial_send(0xFD);
667 bluefruit_serial_send(0x00);
668 bluefruit_serial_send(0x02);
669 bluefruit_serial_send((bitmap>>8)&0xFF);
670 bluefruit_serial_send(bitmap&0xFF);
671 bluefruit_serial_send(0x00);
672 bluefruit_serial_send(0x00);
673 bluefruit_serial_send(0x00);
674 bluefruit_serial_send(0x00);
677 uint8_t timeout = 255;
678 uint8_t where = where_to_send();
680 #ifdef ADAFRUIT_BLE_ENABLE
681 if (where & SendToBLE) {
682 adafruit_ble_send_consumer_key(data, 0);
685 if (!(where & SendToUSB)) {
690 .report_id = REPORT_ID_CONSUMER,
693 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
695 /* Check if write ready for a polling interval around 10ms */
696 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
697 if (!Endpoint_IsReadWriteAllowed()) return;
699 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
704 /*******************************************************************************
706 ******************************************************************************/
707 #ifdef CONSOLE_ENABLE
708 #define SEND_TIMEOUT 5
709 int8_t sendchar(uint8_t c)
711 // Not wait once timeouted.
712 // Because sendchar() is called so many times, waiting each call causes big lag.
713 static bool timeouted = false;
715 // prevents Console_Task() from running during sendchar() runs.
716 // or char will be lost. These two function is mutually exclusive.
717 CONSOLE_FLUSH_SET(false);
719 if (USB_DeviceState != DEVICE_STATE_Configured)
722 uint8_t ep = Endpoint_GetCurrentEndpoint();
723 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
724 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
728 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
734 uint8_t timeout = SEND_TIMEOUT;
735 while (!Endpoint_IsReadWriteAllowed()) {
736 if (USB_DeviceState != DEVICE_STATE_Configured) {
739 if (Endpoint_IsStalled()) {
751 // send when bank is full
752 if (!Endpoint_IsReadWriteAllowed()) {
753 while (!(Endpoint_IsINReady()));
756 CONSOLE_FLUSH_SET(true);
759 Endpoint_SelectEndpoint(ep);
762 Endpoint_SelectEndpoint(ep);
766 int8_t sendchar(uint8_t c)
772 /*******************************************************************************
774 ******************************************************************************/
777 static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
778 MIDI_EventPacket_t event;
785 // Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
787 //if the length is undefined we assume it is a SYSEX message
788 if (midi_packet_length(byte0) == UNDEFINED) {
791 if (byte2 == SYSEX_END)
792 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
794 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
797 if (byte1 == SYSEX_END)
798 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
800 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
803 if (byte0 == SYSEX_END)
804 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
806 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
809 return; //invalid cnt
812 //deal with 'system common' messages
813 //TODO are there any more?
814 switch(byte0 & 0xF0){
815 case MIDI_SONGPOSITION:
816 event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
818 case MIDI_SONGSELECT:
819 case MIDI_TC_QUARTERFRAME:
820 event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
823 event.Event = MIDI_EVENT(cable, byte0);
828 // Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
829 // Endpoint_ClearIN();
831 MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
832 MIDI_Device_Flush(&USB_MIDI_Interface);
833 MIDI_Device_USBTask(&USB_MIDI_Interface);
837 static void usb_get_midi(MidiDevice * device) {
838 MIDI_EventPacket_t event;
839 while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
841 midi_packet_length_t length = midi_packet_length(event.Data1);
843 input[0] = event.Data1;
844 input[1] = event.Data2;
845 input[2] = event.Data3;
846 if (length == UNDEFINED) {
848 if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
850 } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
852 } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
859 //pass the data to the device input function
860 if (length != UNDEFINED)
861 midi_device_input(device, length, input);
863 MIDI_Device_USBTask(&USB_MIDI_Interface);
867 static void midi_usb_init(MidiDevice * device){
868 midi_device_init(device);
869 midi_device_set_send_func(device, usb_send_func);
870 midi_device_set_pre_input_process_func(device, usb_get_midi);
879 /* Device must be connected and configured for the task to run */
880 dprint("in MIDI_TASK\n");
881 if (USB_DeviceState != DEVICE_STATE_Configured)
883 dprint("continuing in MIDI_TASK\n");
885 Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
887 if (Endpoint_IsINReady())
890 dprint("Endpoint is ready\n");
892 uint8_t MIDICommand = 0;
895 /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
896 uint8_t Channel = MIDI_CHANNEL(1);
898 MIDICommand = MIDI_COMMAND_NOTE_ON;
901 /* Check if a MIDI command is to be sent */
904 dprint("Command exists\n");
905 MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
907 .Event = MIDI_EVENT(0, MIDICommand),
909 .Data1 = MIDICommand | Channel,
911 .Data3 = MIDI_STANDARD_VELOCITY,
914 /* Write the MIDI event packet to the endpoint */
915 Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
917 /* Send the data in the endpoint to the host */
923 /* Select the MIDI OUT stream */
924 Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
926 /* Check if a MIDI command has been received */
927 if (Endpoint_IsOUTReceived())
929 MIDI_EventPacket_t MIDIEvent;
931 /* Read the MIDI event packet from the endpoint */
932 Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
934 /* If the endpoint is now empty, clear the bank */
935 if (!(Endpoint_BytesInEndpoint()))
937 /* Clear the endpoint ready for new packet */
945 /*******************************************************************************
947 ******************************************************************************/
949 #ifdef VIRTSER_ENABLE
950 void virtser_init(void)
952 cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ;
953 CDC_Device_SendControlLineStateChange(&cdc_device);
956 void virtser_recv(uint8_t c) __attribute__ ((weak));
957 void virtser_recv(uint8_t c)
962 void virtser_task(void)
964 uint16_t count = CDC_Device_BytesReceived(&cdc_device);
968 ch = CDC_Device_ReceiveByte(&cdc_device);
972 void virtser_send(const uint8_t byte)
974 uint8_t timeout = 255;
975 uint8_t ep = Endpoint_GetCurrentEndpoint();
977 if (cdc_device.State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR)
980 Endpoint_SelectEndpoint(cdc_device.Config.DataINEndpoint.Address);
982 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
983 Endpoint_SelectEndpoint(ep);
987 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
989 Endpoint_Write_8(byte);
990 CDC_Device_Flush(&cdc_device);
992 if (Endpoint_IsINReady()) {
996 Endpoint_SelectEndpoint(ep);
1001 /*******************************************************************************
1003 ******************************************************************************/
1004 static void setup_mcu(void)
1006 /* Disable watchdog if enabled by bootloader/fuses */
1007 MCUSR &= ~(1 << WDRF);
1010 /* Disable clock division */
1011 // clock_prescale_set(clock_div_1);
1013 CLKPR = (1 << CLKPCE);
1014 CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
1017 static void setup_usb(void)
1019 // Leonardo needs. Without this USB device is not recognized.
1025 USB_Device_EnableSOFEvents();
1026 print_set_sendchar(sendchar);
1031 void fallthrough_callback(MidiDevice * device,
1032 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
1033 void cc_callback(MidiDevice * device,
1034 uint8_t chan, uint8_t num, uint8_t val);
1035 void sysex_callback(MidiDevice * device,
1036 uint16_t start, uint8_t length, uint8_t * data);
1039 int main(void) __attribute__ ((weak));
1044 midi_device_init(&midi_device);
1045 midi_device_set_send_func(&midi_device, usb_send_func);
1046 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
1055 midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
1056 midi_register_cc_callback(&midi_device, cc_callback);
1057 midi_register_sysex_callback(&midi_device, sysex_callback);
1060 // midi_send_cc(&midi_device, 0, 1, 2);
1061 // midi_send_cc(&midi_device, 15, 1, 0);
1062 // midi_send_noteon(&midi_device, 0, 64, 127);
1063 // midi_send_noteoff(&midi_device, 0, 64, 127);
1066 #ifdef BLUETOOTH_ENABLE
1070 /* wait for USB startup & debug output */
1073 while (USB_DeviceState != DEVICE_STATE_Configured) {
1074 #if defined(INTERRUPT_CONTROL_ENDPOINT)
1080 print("USB configured.\n");
1086 host_set_driver(&lufa_driver);
1087 #ifdef SLEEP_LED_ENABLE
1091 #ifdef VIRTSER_ENABLE
1095 print("Keyboard start.\n");
1097 #if !defined(BLUETOOTH_ENABLE) && !defined(ADAFRUIT_BLE_ENABLE)
1098 while (USB_DeviceState == DEVICE_STATE_Suspended) {
1100 suspend_power_down();
1101 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
1102 USB_Device_SendRemoteWakeup();
1110 midi_device_process(&midi_device);
1114 #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
1118 #ifdef ADAFRUIT_BLE_ENABLE
1119 adafruit_ble_task();
1122 #ifdef VIRTSER_ENABLE
1124 CDC_Device_USBTask(&cdc_device);
1127 #if !defined(INTERRUPT_CONTROL_ENDPOINT)
1134 void fallthrough_callback(MidiDevice * device,
1135 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
1139 switch (byte0 & 0xF0) {
1141 play_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
1144 stop_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0));
1148 if (byte0 == MIDI_STOP) {
1155 void cc_callback(MidiDevice * device,
1156 uint8_t chan, uint8_t num, uint8_t val) {
1157 //sending it back on the next channel
1158 // midi_send_cc(device, (chan + 1) % 16, num, val);
1161 uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
1163 void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
1164 #ifdef API_SYSEX_ENABLE
1165 // SEND_STRING("\n");
1166 // send_word(start);
1167 // SEND_STRING(": ");
1168 for (uint8_t place = 0; place < length; place++) {
1169 // send_byte(*data);
1170 midi_buffer[start + place] = *data;
1171 if (*data == 0xF7) {
1172 // SEND_STRING("\nRD: ");
1173 // for (uint8_t i = 0; i < start + place + 1; i++){
1174 // send_byte(midi_buffer[i]);
1175 // SEND_STRING(" ");
1177 uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4)));
1178 uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4);
1179 process_api(decode_length, decoded);
1181 // SEND_STRING(" ");