aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/lufa/lufa.c
diff options
context:
space:
mode:
authorJack Humbert <jack.humb@gmail.com>2015-10-27 12:42:30 -0400
committerJack Humbert <jack.humb@gmail.com>2015-10-27 12:42:30 -0400
commit547da78335298df6666200c6063ac6f1aba312fd (patch)
tree47df0252ee24b1ecc27b9dd0458c51f20bf088c3 /tmk_core/protocol/lufa/lufa.c
parenta766918d5c48204375f4c207b30bbbf1389df14f (diff)
parentfa33719adab1393753312d298b8c365e04e844b9 (diff)
downloadqmk_firmware-547da78335298df6666200c6063ac6f1aba312fd.tar.gz
qmk_firmware-547da78335298df6666200c6063ac6f1aba312fd.zip
merging tmk
Diffstat (limited to 'tmk_core/protocol/lufa/lufa.c')
-rw-r--r--tmk_core/protocol/lufa/lufa.c975
1 files changed, 975 insertions, 0 deletions
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
new file mode 100644
index 000000000..f04790f4e
--- /dev/null
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -0,0 +1,975 @@
1/*
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
6 */
7
8/*
9 LUFA Library
10 Copyright (C) Dean Camera, 2012.
11
12 dean [at] fourwalledcubicle [dot] com
13 www.lufa-lib.org
14*/
15
16/*
17 Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
18 Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
19
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.
28
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
36 this software.
37*/
38
39#include "report.h"
40#include "host.h"
41#include "host_driver.h"
42#include "keyboard.h"
43#include "action.h"
44#include "led.h"
45#include "sendchar.h"
46#include "debug.h"
47#ifdef SLEEP_LED_ENABLE
48#include "sleep_led.h"
49#endif
50#include "suspend.h"
51
52#include "descriptor.h"
53#include "lufa.h"
54
55#ifdef MIDI_ENABLE
56 #include <beeps.h>
57#endif
58
59#ifdef BLUETOOTH_ENABLE
60 #include "bluetooth.h"
61#endif
62
63uint8_t keyboard_idle = 0;
64/* 0: Boot Protocol, 1: Report Protocol(default) */
65uint8_t keyboard_protocol = 1;
66static uint8_t keyboard_led_stats = 0;
67
68static report_keyboard_t keyboard_report_sent;
69
70#ifdef MIDI_ENABLE
71void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
72void usb_get_midi(MidiDevice * device);
73void midi_usb_init(MidiDevice * device);
74#endif
75
76/* Host driver */
77static uint8_t keyboard_leds(void);
78static void send_keyboard(report_keyboard_t *report);
79static void send_mouse(report_mouse_t *report);
80static void send_system(uint16_t data);
81static void send_consumer(uint16_t data);
82host_driver_t lufa_driver = {
83 keyboard_leds,
84 send_keyboard,
85 send_mouse,
86 send_system,
87 send_consumer,
88#ifdef MIDI_ENABLE
89 usb_send_func,
90 usb_get_midi,
91 midi_usb_init
92#endif
93};
94
95/*******************************************************************************
96 * MIDI
97 ******************************************************************************/
98
99#ifdef MIDI_ENABLE
100USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
101{
102 .Config =
103 {
104 .StreamingInterfaceNumber = AS_INTERFACE,
105 .DataINEndpoint =
106 {
107 .Address = MIDI_STREAM_IN_EPADDR,
108 .Size = MIDI_STREAM_EPSIZE,
109 .Banks = 1,
110 },
111 .DataOUTEndpoint =
112 {
113 .Address = MIDI_STREAM_OUT_EPADDR,
114 .Size = MIDI_STREAM_EPSIZE,
115 .Banks = 1,
116 },
117 },
118};
119
120#define SYSEX_START_OR_CONT 0x40
121#define SYSEX_ENDS_IN_1 0x50
122#define SYSEX_ENDS_IN_2 0x60
123#define SYSEX_ENDS_IN_3 0x70
124
125#define SYS_COMMON_1 0x50
126#define SYS_COMMON_2 0x20
127#define SYS_COMMON_3 0x30
128#endif
129
130
131/*******************************************************************************
132 * Console
133 ******************************************************************************/
134#ifdef CONSOLE_ENABLE
135static void Console_Task(void)
136{
137 /* Device must be connected and configured for the task to run */
138 if (USB_DeviceState != DEVICE_STATE_Configured)
139 return;
140
141 uint8_t ep = Endpoint_GetCurrentEndpoint();
142
143#if 0
144 // TODO: impl receivechar()/recvchar()
145 Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
146
147 /* Check to see if a packet has been sent from the host */
148 if (Endpoint_IsOUTReceived())
149 {
150 /* Check to see if the packet contains data */
151 if (Endpoint_IsReadWriteAllowed())
152 {
153 /* Create a temporary buffer to hold the read in report from the host */
154 uint8_t ConsoleData[CONSOLE_EPSIZE];
155
156 /* Read Console Report Data */
157 Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
158
159 /* Process Console Report Data */
160 //ProcessConsoleHIDReport(ConsoleData);
161 }
162
163 /* Finalize the stream transfer to send the last packet */
164 Endpoint_ClearOUT();
165 }
166#endif
167
168 /* IN packet */
169 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
170 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
171 Endpoint_SelectEndpoint(ep);
172 return;
173 }
174
175 // fill empty bank
176 while (Endpoint_IsReadWriteAllowed())
177 Endpoint_Write_8(0);
178
179 // flash senchar packet
180 if (Endpoint_IsINReady()) {
181 Endpoint_ClearIN();
182 }
183
184 Endpoint_SelectEndpoint(ep);
185}
186#else
187static void Console_Task(void)
188{
189}
190#endif
191
192
193/*******************************************************************************
194 * USB Events
195 ******************************************************************************/
196/*
197 * Event Order of Plug in:
198 * 0) EVENT_USB_Device_Connect
199 * 1) EVENT_USB_Device_Suspend
200 * 2) EVENT_USB_Device_Reset
201 * 3) EVENT_USB_Device_Wake
202*/
203void EVENT_USB_Device_Connect(void)
204{
205 print("[C]");
206 /* For battery powered device */
207 if (!USB_IsInitialized) {
208 USB_Disable();
209 USB_Init();
210 USB_Device_EnableSOFEvents();
211 }
212}
213
214void EVENT_USB_Device_Disconnect(void)
215{
216 print("[D]");
217 /* For battery powered device */
218 USB_IsInitialized = false;
219/* TODO: This doesn't work. After several plug in/outs can not be enumerated.
220 if (USB_IsInitialized) {
221 USB_Disable(); // Disable all interrupts
222 USB_Controller_Enable();
223 USB_INT_Enable(USB_INT_VBUSTI);
224 }
225*/
226}
227
228void EVENT_USB_Device_Reset(void)
229{
230 print("[R]");
231}
232
233void EVENT_USB_Device_Suspend()
234{
235 print("[S]");
236#ifdef SLEEP_LED_ENABLE
237 sleep_led_enable();
238#endif
239}
240
241void EVENT_USB_Device_WakeUp()
242{
243 print("[W]");
244 suspend_wakeup_init();
245
246#ifdef SLEEP_LED_ENABLE
247 sleep_led_disable();
248 // NOTE: converters may not accept this
249 led_set(host_keyboard_leds());
250#endif
251}
252
253#ifdef CONSOLE_ENABLE
254static bool console_flush = false;
255#define CONSOLE_FLUSH_SET(b) do { \
256 uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
257} while (0)
258
259// called every 1ms
260void EVENT_USB_Device_StartOfFrame(void)
261{
262 static uint8_t count;
263 if (++count % 50) return;
264 count = 0;
265
266 if (!console_flush) return;
267 Console_Task();
268 console_flush = false;
269}
270#endif
271
272/** Event handler for the USB_ConfigurationChanged event.
273 * This is fired when the host sets the current configuration of the USB device after enumeration.
274 *
275 * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
276 * it is safe to use singl bank for all endpoints.
277 */
278void EVENT_USB_Device_ConfigurationChanged(void)
279{
280 bool ConfigSuccess = true;
281
282 /* Setup Keyboard HID Report Endpoints */
283 ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
284 KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
285
286#ifdef MOUSE_ENABLE
287 /* Setup Mouse HID Report Endpoint */
288 ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
289 MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
290#endif
291
292#ifdef EXTRAKEY_ENABLE
293 /* Setup Extra HID Report Endpoint */
294 ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
295 EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
296#endif
297
298#ifdef CONSOLE_ENABLE
299 /* Setup Console HID Report Endpoints */
300 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
301 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
302#if 0
303 ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
304 CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
305#endif
306#endif
307
308#ifdef NKRO_ENABLE
309 /* Setup NKRO HID Report Endpoints */
310 ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
311 NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
312#endif
313
314#ifdef MIDI_ENABLE
315 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
316 ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
317#endif
318}
319
320/*
321Appendix G: HID Request Support Requirements
322
323The following table enumerates the requests that need to be supported by various types of HID class devices.
324
325Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
326------------------------------------------------------------------------------------------
327Boot Mouse Required Optional Optional Optional Required Required
328Non-Boot Mouse Required Optional Optional Optional Optional Optional
329Boot Keyboard Required Optional Required Required Required Required
330Non-Boot Keybrd Required Optional Required Required Optional Optional
331Other Device Required Optional Optional Optional Optional Optional
332*/
333/** Event handler for the USB_ControlRequest event.
334 * This is fired before passing along unhandled control requests to the library for processing internally.
335 */
336void EVENT_USB_Device_ControlRequest(void)
337{
338 uint8_t* ReportData = NULL;
339 uint8_t ReportSize = 0;
340
341 /* Handle HID Class specific requests */
342 switch (USB_ControlRequest.bRequest)
343 {
344 case HID_REQ_GetReport:
345 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
346 {
347 Endpoint_ClearSETUP();
348
349 // Interface
350 switch (USB_ControlRequest.wIndex) {
351 case KEYBOARD_INTERFACE:
352 // TODO: test/check
353 ReportData = (uint8_t*)&keyboard_report_sent;
354 ReportSize = sizeof(keyboard_report_sent);
355 break;
356 }
357
358 /* Write the report data to the control endpoint */
359 Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
360 Endpoint_ClearOUT();
361 }
362
363 break;
364 case HID_REQ_SetReport:
365 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
366 {
367
368 // Interface
369 switch (USB_ControlRequest.wIndex) {
370 case KEYBOARD_INTERFACE:
371#ifdef NKRO_ENABLE
372 case NKRO_INTERFACE:
373#endif
374 Endpoint_ClearSETUP();
375
376 while (!(Endpoint_IsOUTReceived())) {
377 if (USB_DeviceState == DEVICE_STATE_Unattached)
378 return;
379 }
380 keyboard_led_stats = Endpoint_Read_8();
381
382 Endpoint_ClearOUT();
383 Endpoint_ClearStatusStage();
384 break;
385 }
386
387 }
388
389 break;
390
391 case HID_REQ_GetProtocol:
392 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
393 {
394 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
395 Endpoint_ClearSETUP();
396 while (!(Endpoint_IsINReady()));
397 Endpoint_Write_8(keyboard_protocol);
398 Endpoint_ClearIN();
399 Endpoint_ClearStatusStage();
400 }
401 }
402
403 break;
404 case HID_REQ_SetProtocol:
405 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
406 {
407 if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
408 Endpoint_ClearSETUP();
409 Endpoint_ClearStatusStage();
410
411 keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
412 clear_keyboard();
413 }
414 }
415
416 break;
417 case HID_REQ_SetIdle:
418 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
419 {
420 Endpoint_ClearSETUP();
421 Endpoint_ClearStatusStage();
422
423 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
424 }
425
426 break;
427 case HID_REQ_GetIdle:
428 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
429 {
430 Endpoint_ClearSETUP();
431 while (!(Endpoint_IsINReady()));
432 Endpoint_Write_8(keyboard_idle);
433 Endpoint_ClearIN();
434 Endpoint_ClearStatusStage();
435 }
436
437 break;
438 }
439}
440
441/*******************************************************************************
442 * Host driver
443 ******************************************************************************/
444static uint8_t keyboard_leds(void)
445{
446 return keyboard_led_stats;
447}
448
449static void send_keyboard(report_keyboard_t *report)
450{
451
452#ifdef BLUETOOTH_ENABLE
453 bluefruit_serial_send(0xFD);
454 for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
455 bluefruit_serial_send(report->raw[i]);
456 }
457#endif
458
459 uint8_t timeout = 255;
460
461 if (USB_DeviceState != DEVICE_STATE_Configured)
462 return;
463
464 /* Select the Keyboard Report Endpoint */
465#ifdef NKRO_ENABLE
466 if (keyboard_protocol && keyboard_nkro) {
467 /* Report protocol - NKRO */
468 Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
469
470 /* Check if write ready for a polling interval around 1ms */
471 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
472 if (!Endpoint_IsReadWriteAllowed()) return;
473
474 /* Write Keyboard Report Data */
475 Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
476 }
477 else
478#endif
479 {
480 /* Boot protocol */
481 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
482
483 /* Check if write ready for a polling interval around 10ms */
484 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
485 if (!Endpoint_IsReadWriteAllowed()) return;
486
487 /* Write Keyboard Report Data */
488 Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
489 }
490
491 /* Finalize the stream transfer to send the last packet */
492 Endpoint_ClearIN();
493
494 keyboard_report_sent = *report;
495}
496
497static void send_mouse(report_mouse_t *report)
498{
499#ifdef MOUSE_ENABLE
500
501#ifdef BLUETOOTH_ENABLE
502 bluefruit_serial_send(0xFD);
503 bluefruit_serial_send(0x00);
504 bluefruit_serial_send(0x03);
505 bluefruit_serial_send(report->buttons);
506 bluefruit_serial_send(report->x);
507 bluefruit_serial_send(report->y);
508 bluefruit_serial_send(report->v); // should try sending the wheel v here
509 bluefruit_serial_send(report->h); // should try sending the wheel h here
510 bluefruit_serial_send(0x00);
511#endif
512
513 uint8_t timeout = 255;
514
515 if (USB_DeviceState != DEVICE_STATE_Configured)
516 return;
517
518 /* Select the Mouse Report Endpoint */
519 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
520
521 /* Check if write ready for a polling interval around 10ms */
522 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
523 if (!Endpoint_IsReadWriteAllowed()) return;
524
525 /* Write Mouse Report Data */
526 Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
527
528 /* Finalize the stream transfer to send the last packet */
529 Endpoint_ClearIN();
530#endif
531}
532
533static void send_system(uint16_t data)
534{
535 uint8_t timeout = 255;
536
537 if (USB_DeviceState != DEVICE_STATE_Configured)
538 return;
539
540 report_extra_t r = {
541 .report_id = REPORT_ID_SYSTEM,
542 .usage = data
543 };
544 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
545
546 /* Check if write ready for a polling interval around 10ms */
547 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
548 if (!Endpoint_IsReadWriteAllowed()) return;
549
550 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
551 Endpoint_ClearIN();
552}
553
554static void send_consumer(uint16_t data)
555{
556
557#ifdef BLUETOOTH_ENABLE
558 static uint16_t last_data = 0;
559 if (data == last_data) return;
560 last_data = data;
561 uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
562 bluefruit_serial_send(0xFD);
563 bluefruit_serial_send(0x00);
564 bluefruit_serial_send(0x02);
565 bluefruit_serial_send((bitmap>>8)&0xFF);
566 bluefruit_serial_send(bitmap&0xFF);
567 bluefruit_serial_send(0x00);
568 bluefruit_serial_send(0x00);
569 bluefruit_serial_send(0x00);
570 bluefruit_serial_send(0x00);
571#endif
572
573 uint8_t timeout = 255;
574
575 if (USB_DeviceState != DEVICE_STATE_Configured)
576 return;
577
578 report_extra_t r = {
579 .report_id = REPORT_ID_CONSUMER,
580 .usage = data
581 };
582 Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
583
584 /* Check if write ready for a polling interval around 10ms */
585 while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
586 if (!Endpoint_IsReadWriteAllowed()) return;
587
588 Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
589 Endpoint_ClearIN();
590}
591
592
593/*******************************************************************************
594 * sendchar
595 ******************************************************************************/
596#ifdef CONSOLE_ENABLE
597#define SEND_TIMEOUT 5
598int8_t sendchar(uint8_t c)
599{
600 // Not wait once timeouted.
601 // Because sendchar() is called so many times, waiting each call causes big lag.
602 static bool timeouted = false;
603
604 // prevents Console_Task() from running during sendchar() runs.
605 // or char will be lost. These two function is mutually exclusive.
606 CONSOLE_FLUSH_SET(false);
607
608 if (USB_DeviceState != DEVICE_STATE_Configured)
609 return -1;
610
611 uint8_t ep = Endpoint_GetCurrentEndpoint();
612 Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
613 if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
614 goto ERROR_EXIT;
615 }
616
617 if (timeouted && !Endpoint_IsReadWriteAllowed()) {
618 goto ERROR_EXIT;
619 }
620
621 timeouted = false;
622
623 uint8_t timeout = SEND_TIMEOUT;
624 while (!Endpoint_IsReadWriteAllowed()) {
625 if (USB_DeviceState != DEVICE_STATE_Configured) {
626 goto ERROR_EXIT;
627 }
628 if (Endpoint_IsStalled()) {
629 goto ERROR_EXIT;
630 }
631 if (!(timeout--)) {
632 timeouted = true;
633 goto ERROR_EXIT;
634 }
635 _delay_ms(1);
636 }
637
638 Endpoint_Write_8(c);
639
640 // send when bank is full
641 if (!Endpoint_IsReadWriteAllowed()) {
642 while (!(Endpoint_IsINReady()));
643 Endpoint_ClearIN();
644 } else {
645 CONSOLE_FLUSH_SET(true);
646 }
647
648 Endpoint_SelectEndpoint(ep);
649 return 0;
650ERROR_EXIT:
651 Endpoint_SelectEndpoint(ep);
652 return -1;
653}
654#else
655int8_t sendchar(uint8_t c)
656{
657 return 0;
658}
659#endif
660
661/*******************************************************************************
662 * MIDI
663 ******************************************************************************/
664
665#ifdef MIDI_ENABLE
666void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
667 MIDI_EventPacket_t event;
668 event.Data1 = byte0;
669 event.Data2 = byte1;
670 event.Data3 = byte2;
671
672 uint8_t cable = 0;
673
674// Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
675
676 //if the length is undefined we assume it is a SYSEX message
677 if (midi_packet_length(byte0) == UNDEFINED) {
678 switch(cnt) {
679 case 3:
680 if (byte2 == SYSEX_END)
681 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
682 else
683 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
684 break;
685 case 2:
686 if (byte1 == SYSEX_END)
687 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
688 else
689 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
690 break;
691 case 1:
692 if (byte0 == SYSEX_END)
693 event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
694 else
695 event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
696 break;
697 default:
698 return; //invalid cnt
699 }
700 } else {
701 //deal with 'system common' messages
702 //TODO are there any more?
703 switch(byte0 & 0xF0){
704 case MIDI_SONGPOSITION:
705 event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
706 break;
707 case MIDI_SONGSELECT:
708 case MIDI_TC_QUARTERFRAME:
709 event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
710 break;
711 default:
712 event.Event = MIDI_EVENT(cable, byte0);
713 break;
714 }
715 }
716
717// Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
718// Endpoint_ClearIN();
719
720 MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
721 MIDI_Device_Flush(&USB_MIDI_Interface);
722 MIDI_Device_USBTask(&USB_MIDI_Interface);
723 USB_USBTask();
724}
725
726void usb_get_midi(MidiDevice * device) {
727 MIDI_EventPacket_t event;
728 while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
729
730 midi_packet_length_t length = midi_packet_length(event.Data1);
731 uint8_t input[3];
732 input[0] = event.Data1;
733 input[1] = event.Data2;
734 input[2] = event.Data3;
735 if (length == UNDEFINED) {
736 //sysex
737 if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
738 length = 3;
739 } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
740 length = 2;
741 } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
742 length = 1;
743 } else {
744 //XXX what to do?
745 }
746 }
747
748 //pass the data to the device input function
749 if (length != UNDEFINED)
750 midi_device_input(device, length, input);
751 }
752 MIDI_Device_USBTask(&USB_MIDI_Interface);
753 USB_USBTask();
754}
755
756void midi_usb_init(MidiDevice * device){
757 midi_device_init(device);
758 midi_device_set_send_func(device, usb_send_func);
759 midi_device_set_pre_input_process_func(device, usb_get_midi);
760
761 SetupHardware();
762 sei();
763}
764
765void MIDI_Task(void)
766{
767
768 /* Device must be connected and configured for the task to run */
769 dprint("in MIDI_TASK\n");
770 if (USB_DeviceState != DEVICE_STATE_Configured)
771 return;
772 dprint("continuing in MIDI_TASK\n");
773
774 Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
775
776 if (Endpoint_IsINReady())
777 {
778
779 dprint("Endpoint is ready\n");
780
781 uint8_t MIDICommand = 0;
782 uint8_t MIDIPitch;
783
784 /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
785 uint8_t Channel = MIDI_CHANNEL(1);
786
787 MIDICommand = MIDI_COMMAND_NOTE_ON;
788 MIDIPitch = 0x3E;
789
790 /* Check if a MIDI command is to be sent */
791 if (MIDICommand)
792 {
793 dprint("Command exists\n");
794 MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
795 {
796 .Event = MIDI_EVENT(0, MIDICommand),
797
798 .Data1 = MIDICommand | Channel,
799 .Data2 = MIDIPitch,
800 .Data3 = MIDI_STANDARD_VELOCITY,
801 };
802
803 /* Write the MIDI event packet to the endpoint */
804 Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
805
806 /* Send the data in the endpoint to the host */
807 Endpoint_ClearIN();
808 }
809 }
810
811
812 /* Select the MIDI OUT stream */
813 Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
814
815 /* Check if a MIDI command has been received */
816 if (Endpoint_IsOUTReceived())
817 {
818 MIDI_EventPacket_t MIDIEvent;
819
820 /* Read the MIDI event packet from the endpoint */
821 Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
822
823 /* If the endpoint is now empty, clear the bank */
824 if (!(Endpoint_BytesInEndpoint()))
825 {
826 /* Clear the endpoint ready for new packet */
827 Endpoint_ClearOUT();
828 }
829 }
830}
831
832#endif
833
834
835/*******************************************************************************
836 * main
837 ******************************************************************************/
838static void setup_mcu(void)
839{
840 /* Disable watchdog if enabled by bootloader/fuses */
841 MCUSR &= ~(1 << WDRF);
842 wdt_disable();
843
844 /* Disable clock division */
845 clock_prescale_set(clock_div_1);
846}
847
848static void setup_usb(void)
849{
850 // Leonardo needs. Without this USB device is not recognized.
851 USB_Disable();
852
853 USB_Init();
854
855 // for Console_Task
856 USB_Device_EnableSOFEvents();
857 print_set_sendchar(sendchar);
858}
859
860
861#ifdef MIDI_ENABLE
862void fallthrough_callback(MidiDevice * device,
863 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
864void cc_callback(MidiDevice * device,
865 uint8_t chan, uint8_t num, uint8_t val);
866void sysex_callback(MidiDevice * device,
867 uint16_t start, uint8_t length, uint8_t * data);
868#endif
869
870int main(void) __attribute__ ((weak));
871int main(void)
872{
873
874#ifdef MIDI_ENABLE
875 midi_device_init(&midi_device);
876 midi_device_set_send_func(&midi_device, usb_send_func);
877 midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
878#endif
879
880 setup_mcu();
881 keyboard_setup();
882 setup_usb();
883 sei();
884
885#ifdef MIDI_ENABLE
886 midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
887 midi_register_cc_callback(&midi_device, cc_callback);
888 midi_register_sysex_callback(&midi_device, sysex_callback);
889
890 init_notes();
891 // midi_send_cc(&midi_device, 0, 1, 2);
892 // midi_send_cc(&midi_device, 15, 1, 0);
893 // midi_send_noteon(&midi_device, 0, 64, 127);
894 // midi_send_noteoff(&midi_device, 0, 64, 127);
895#endif
896
897#ifdef BLUETOOTH_ENABLE
898 serial_init();
899#endif
900
901 /* wait for USB startup & debug output */
902
903#ifdef WAIT_FOR_USB
904 while (USB_DeviceState != DEVICE_STATE_Configured) {
905 #if defined(INTERRUPT_CONTROL_ENDPOINT)
906 ;
907 #else
908 USB_USBTask();
909 #endif
910 }
911 print("USB configured.\n");
912#else
913 USB_USBTask();
914#endif
915 /* init modules */
916 keyboard_init();
917 host_set_driver(&lufa_driver);
918#ifdef SLEEP_LED_ENABLE
919 sleep_led_init();
920#endif
921
922 print("Keyboard start.\n");
923 while (1) {
924 #ifndef BLUETOOTH_ENABLE
925 while (USB_DeviceState == DEVICE_STATE_Suspended) {
926 print("[s]");
927 suspend_power_down();
928 if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
929 USB_Device_SendRemoteWakeup();
930 }
931 }
932 #endif
933
934#ifdef MIDI_ENABLE
935 midi_device_process(&midi_device);
936 // MIDI_Task();
937#endif
938 keyboard_task();
939
940#if !defined(INTERRUPT_CONTROL_ENDPOINT)
941 USB_USBTask();
942#endif
943 }
944}
945
946#ifdef MIDI_ENABLE
947void fallthrough_callback(MidiDevice * device,
948 uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
949 if (cnt == 3) {
950 switch (byte0 & 0xF0) {
951 case MIDI_NOTEON:
952 play_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
953 break;
954 case MIDI_NOTEOFF:
955 stop_note(((double)261.6)*pow(2.0, -1.0)*pow(2.0,(byte1 & 0x7F)/12.0));
956 break;
957 }
958 }
959 if (byte0 == MIDI_STOP) {
960 stop_all_notes();
961 }
962}
963
964void cc_callback(MidiDevice * device,
965 uint8_t chan, uint8_t num, uint8_t val) {
966 //sending it back on the next channel
967 midi_send_cc(device, (chan + 1) % 16, num, val);
968}
969
970void sysex_callback(MidiDevice * device,
971 uint16_t start, uint8_t length, uint8_t * data) {
972 for (int i = 0; i < length; i++)
973 midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i));
974}
975#endif