#endif
#include "suspend.h"
-#include "descriptor.h"
+#include "usb_descriptor.h"
#include "lufa.h"
#include "quantum.h"
#include <util/atomic.h>
#include "outputselect.h"
+#include "rgblight_reconfig.h"
#ifdef NKRO_ENABLE
#include "keycode_config.h"
#endif
#ifdef MIDI_ENABLE
- #include "sysex_tools.h"
+ #include "qmk_midi.h"
#endif
#ifdef RAW_ENABLE
static report_keyboard_t keyboard_report_sent;
-#ifdef MIDI_ENABLE
-static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
-static void usb_get_midi(MidiDevice * device);
-static void midi_usb_init(MidiDevice * device);
-#endif
-
/* Host driver */
static uint8_t keyboard_leds(void);
static void send_keyboard(report_keyboard_t *report);
send_mouse,
send_system,
send_consumer,
-#ifdef MIDI_ENABLE
- usb_send_func,
- usb_get_midi,
- midi_usb_init
-#endif
-};
-
-/*******************************************************************************
- * MIDI
- ******************************************************************************/
-
-#ifdef MIDI_ENABLE
-USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
-{
- .Config =
- {
- .StreamingInterfaceNumber = AS_INTERFACE,
- .DataINEndpoint =
- {
- .Address = MIDI_STREAM_IN_EPADDR,
- .Size = MIDI_STREAM_EPSIZE,
- .Banks = 1,
- },
- .DataOUTEndpoint =
- {
- .Address = MIDI_STREAM_OUT_EPADDR,
- .Size = MIDI_STREAM_EPSIZE,
- .Banks = 1,
- },
- },
};
-#define SYSEX_START_OR_CONT 0x40
-#define SYSEX_ENDS_IN_1 0x50
-#define SYSEX_ENDS_IN_2 0x60
-#define SYSEX_ENDS_IN_3 0x70
-
-#define SYS_COMMON_1 0x50
-#define SYS_COMMON_2 0x20
-#define SYS_COMMON_3 0x30
-#endif
-
#ifdef VIRTSER_ENABLE
USB_ClassInfo_CDC_Device_t cdc_device =
{
#ifdef RAW_ENABLE
+/** \brief Raw HID Send
+ *
+ * FIXME: Needs doc
+ */
void raw_hid_send( uint8_t *data, uint8_t length )
{
// TODO: implement variable size packet
Endpoint_SelectEndpoint(ep);
}
+/** \brief Raw HID Receive
+ *
+ * FIXME: Needs doc
+ */
__attribute__ ((weak))
void raw_hid_receive( uint8_t *data, uint8_t length )
{
// so users can opt to not handle data coming in.
}
+/** \brief Raw HID Task
+ *
+ * FIXME: Needs doc
+ */
static void raw_hid_task(void)
{
// Create a temporary buffer to hold the read in data from the host
* Console
******************************************************************************/
#ifdef CONSOLE_ENABLE
+/** \brief Console Task
+ *
+ * FIXME: Needs doc
+ */
static void Console_Task(void)
{
/* Device must be connected and configured for the task to run */
* 2) EVENT_USB_Device_Reset
* 3) EVENT_USB_Device_Wake
*/
+/** \brief Event USB Device Connect
+ *
+ * FIXME: Needs doc
+ */
void EVENT_USB_Device_Connect(void)
{
print("[C]");
}
}
+/** \brief Event USB Device Connect
+ *
+ * FIXME: Needs doc
+ */
void EVENT_USB_Device_Disconnect(void)
{
print("[D]");
*/
}
+/** \brief Event USB Device Connect
+ *
+ * FIXME: Needs doc
+ */
void EVENT_USB_Device_Reset(void)
{
print("[R]");
}
+/** \brief Event USB Device Connect
+ *
+ * FIXME: Needs doc
+ */
void EVENT_USB_Device_Suspend()
{
print("[S]");
#endif
}
+/** \brief Event USB Device Connect
+ *
+ * FIXME: Needs doc
+ */
void EVENT_USB_Device_WakeUp()
{
print("[W]");
} \
} while (0)
-// called every 1ms
+/** \brief Event USB Device Start Of Frame
+ *
+ * FIXME: Needs doc
+ * called every 1ms
+ */
void EVENT_USB_Device_StartOfFrame(void)
{
static uint8_t count;
#endif
-/** Event handler for the USB_ConfigurationChanged event.
+/** \brief Event handler for the USB_ConfigurationChanged event.
+ *
* This is fired when the host sets the current configuration of the USB device after enumeration.
*
* ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
- * it is safe to use singl bank for all endpoints.
+ * it is safe to use single bank for all endpoints.
*/
void EVENT_USB_Device_ConfigurationChanged(void)
{
#endif
}
-/*
+/* FIXME: Expose this table in the docs somehow
Appendix G: HID Request Support Requirements
The following table enumerates the requests that need to be supported by various types of HID class devices.
Non-Boot Keybrd Required Optional Required Required Optional Optional
Other Device Required Optional Optional Optional Optional Optional
*/
-/** Event handler for the USB_ControlRequest event.
+/** \brief Event handler for the USB_ControlRequest event.
+ *
* This is fired before passing along unhandled control requests to the library for processing internally.
*/
void EVENT_USB_Device_ControlRequest(void)
/*******************************************************************************
* Host driver
******************************************************************************/
+/** \brief Keyboard LEDs
+ *
+ * FIXME: Needs doc
+ */
static uint8_t keyboard_leds(void)
{
return keyboard_led_stats;
}
+/** \brief Send Keyboard
+ *
+ * FIXME: Needs doc
+ */
static void send_keyboard(report_keyboard_t *report)
{
uint8_t timeout = 255;
keyboard_report_sent = *report;
}
-
+
+/** \brief Send Mouse
+ *
+ * FIXME: Needs doc
+ */
static void send_mouse(report_mouse_t *report)
{
#ifdef MOUSE_ENABLE
if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
#ifdef MODULE_ADAFRUIT_BLE
// FIXME: mouse buttons
- adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h);
+ adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons);
#else
bluefruit_serial_send(0xFD);
bluefruit_serial_send(0x00);
#endif
}
+/** \brief Send System
+ *
+ * FIXME: Needs doc
+ */
static void send_system(uint16_t data)
{
uint8_t timeout = 255;
Endpoint_ClearIN();
}
+/** \brief Send Consumer
+ *
+ * FIXME: Needs doc
+ */
static void send_consumer(uint16_t data)
{
uint8_t timeout = 255;
******************************************************************************/
#ifdef CONSOLE_ENABLE
#define SEND_TIMEOUT 5
+/** \brief Send Char
+ *
+ * FIXME: Needs doc
+ */
int8_t sendchar(uint8_t c)
{
// Not wait once timeouted.
******************************************************************************/
#ifdef MIDI_ENABLE
-static void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
- MIDI_EventPacket_t event;
- event.Data1 = byte0;
- event.Data2 = byte1;
- event.Data3 = byte2;
-
- uint8_t cable = 0;
-
-// Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
-
- //if the length is undefined we assume it is a SYSEX message
- if (midi_packet_length(byte0) == UNDEFINED) {
- switch(cnt) {
- case 3:
- if (byte2 == SYSEX_END)
- event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
- else
- event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
- break;
- case 2:
- if (byte1 == SYSEX_END)
- event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
- else
- event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
- break;
- case 1:
- if (byte0 == SYSEX_END)
- event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
- else
- event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
- break;
- default:
- return; //invalid cnt
- }
- } else {
- //deal with 'system common' messages
- //TODO are there any more?
- switch(byte0 & 0xF0){
- case MIDI_SONGPOSITION:
- event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
- break;
- case MIDI_SONGSELECT:
- case MIDI_TC_QUARTERFRAME:
- event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
- break;
- default:
- event.Event = MIDI_EVENT(cable, byte0);
- break;
- }
- }
-
-// Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
-// Endpoint_ClearIN();
-
- MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
- MIDI_Device_Flush(&USB_MIDI_Interface);
- MIDI_Device_USBTask(&USB_MIDI_Interface);
- USB_USBTask();
-}
-
-static void usb_get_midi(MidiDevice * device) {
- MIDI_EventPacket_t event;
- while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
-
- midi_packet_length_t length = midi_packet_length(event.Data1);
- uint8_t input[3];
- input[0] = event.Data1;
- input[1] = event.Data2;
- input[2] = event.Data3;
- if (length == UNDEFINED) {
- //sysex
- if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
- length = 3;
- } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
- length = 2;
- } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
- length = 1;
- } else {
- //XXX what to do?
- }
- }
-
- //pass the data to the device input function
- if (length != UNDEFINED)
- midi_device_input(device, length, input);
- }
- MIDI_Device_USBTask(&USB_MIDI_Interface);
- USB_USBTask();
-}
-
-static void midi_usb_init(MidiDevice * device){
- midi_device_init(device);
- midi_device_set_send_func(device, usb_send_func);
- midi_device_set_pre_input_process_func(device, usb_get_midi);
-
- // SetupHardware();
- sei();
-}
-
-void MIDI_Task(void)
+USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
{
-
- /* Device must be connected and configured for the task to run */
- dprint("in MIDI_TASK\n");
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
- dprint("continuing in MIDI_TASK\n");
-
- Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
-
- if (Endpoint_IsINReady())
+ .Config =
+ {
+ .StreamingInterfaceNumber = AS_INTERFACE,
+ .DataINEndpoint =
{
-
- dprint("Endpoint is ready\n");
-
- uint8_t MIDICommand = 0;
- uint8_t MIDIPitch;
-
- /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
- uint8_t Channel = MIDI_CHANNEL(1);
-
- MIDICommand = MIDI_COMMAND_NOTE_ON;
- MIDIPitch = 0x3E;
-
- /* Check if a MIDI command is to be sent */
- if (MIDICommand)
- {
- dprint("Command exists\n");
- MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
- {
- .Event = MIDI_EVENT(0, MIDICommand),
-
- .Data1 = MIDICommand | Channel,
- .Data2 = MIDIPitch,
- .Data3 = MIDI_STANDARD_VELOCITY,
- };
-
- /* Write the MIDI event packet to the endpoint */
- Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
-
- /* Send the data in the endpoint to the host */
- Endpoint_ClearIN();
- }
- }
-
-
- /* Select the MIDI OUT stream */
- Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
-
- /* Check if a MIDI command has been received */
- if (Endpoint_IsOUTReceived())
+ .Address = MIDI_STREAM_IN_EPADDR,
+ .Size = MIDI_STREAM_EPSIZE,
+ .Banks = 1,
+ },
+ .DataOUTEndpoint =
{
- MIDI_EventPacket_t MIDIEvent;
+ .Address = MIDI_STREAM_OUT_EPADDR,
+ .Size = MIDI_STREAM_EPSIZE,
+ .Banks = 1,
+ },
+ },
+};
- /* Read the MIDI event packet from the endpoint */
- Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
+void send_midi_packet(MIDI_EventPacket_t* event) {
+ MIDI_Device_SendEventPacket(&USB_MIDI_Interface, event);
+}
- /* If the endpoint is now empty, clear the bank */
- if (!(Endpoint_BytesInEndpoint()))
- {
- /* Clear the endpoint ready for new packet */
- Endpoint_ClearOUT();
- }
- }
+bool recv_midi_packet(MIDI_EventPacket_t* const event) {
+ return MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, event);
}
#endif
******************************************************************************/
#ifdef VIRTSER_ENABLE
+/** \brief Virtual Serial Init
+ *
+ * FIXME: Needs doc
+ */
void virtser_init(void)
{
cdc_device.State.ControlLineStates.DeviceToHost = CDC_CONTROL_LINE_IN_DSR ;
CDC_Device_SendControlLineStateChange(&cdc_device);
}
+/** \brief Virtual Serial Receive
+ *
+ * FIXME: Needs doc
+ */
void virtser_recv(uint8_t c) __attribute__ ((weak));
void virtser_recv(uint8_t c)
{
// Ignore by default
}
+/** \brief Virtual Serial Task
+ *
+ * FIXME: Needs doc
+ */
void virtser_task(void)
{
uint16_t count = CDC_Device_BytesReceived(&cdc_device);
virtser_recv(ch);
}
}
+/** \brief Virtual Serial Send
+ *
+ * FIXME: Needs doc
+ */
void virtser_send(const uint8_t byte)
{
uint8_t timeout = 255;
/*******************************************************************************
* main
******************************************************************************/
+/** \brief Setup MCU
+ *
+ * FIXME: Needs doc
+ */
static void setup_mcu(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
}
+/** \brief Setup USB
+ *
+ * FIXME: Needs doc
+ */
static void setup_usb(void)
{
// Leonardo needs. Without this USB device is not recognized.
print_set_sendchar(sendchar);
}
-
-#ifdef MIDI_ENABLE
-void fallthrough_callback(MidiDevice * device,
- uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
-void cc_callback(MidiDevice * device,
- uint8_t chan, uint8_t num, uint8_t val);
-void sysex_callback(MidiDevice * device,
- uint16_t start, uint8_t length, uint8_t * data);
-
-void setup_midi(void)
-{
-#ifdef MIDI_ADVANCED
- midi_init();
-#endif
- midi_device_init(&midi_device);
- midi_device_set_send_func(&midi_device, usb_send_func);
- midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
-}
-#endif
-
+/** \brief Main
+ *
+ * FIXME: Needs doc
+ */
int main(void) __attribute__ ((weak));
int main(void)
{
setup_usb();
sei();
-#ifdef MIDI_ENABLE
- midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
- midi_register_cc_callback(&midi_device, cc_callback);
- midi_register_sysex_callback(&midi_device, sysex_callback);
-
- // init_notes();
- // midi_send_cc(&midi_device, 0, 1, 2);
- // midi_send_cc(&midi_device, 15, 1, 0);
- // midi_send_noteon(&midi_device, 0, 64, 127);
- // midi_send_noteoff(&midi_device, 0, 64, 127);
-#endif
-
#if defined(MODULE_ADAFRUIT_EZKEY) || defined(MODULE_RN42)
serial_init();
#endif
print("Keyboard start.\n");
while (1) {
- #if !defined(BLUETOOTH_ENABLE)
+ #if !defined(NO_USB_STARTUP_CHECK)
while (USB_DeviceState == DEVICE_STATE_Suspended) {
print("[s]");
suspend_power_down();
keyboard_task();
#ifdef MIDI_ENABLE
- midi_device_process(&midi_device);
-#ifdef MIDI_ADVANCED
- midi_task();
-#endif
+ MIDI_Device_USBTask(&USB_MIDI_Interface);
#endif
#if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
}
}
-#ifdef MIDI_ENABLE
-void fallthrough_callback(MidiDevice * device,
- uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
-
-#ifdef AUDIO_ENABLE
- if (cnt == 3) {
- switch (byte0 & 0xF0) {
- case MIDI_NOTEON:
- play_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
- break;
- case MIDI_NOTEOFF:
- stop_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0));
- break;
- }
- }
- if (byte0 == MIDI_STOP) {
- stop_all_notes();
- }
-#endif
-}
-
-
-void cc_callback(MidiDevice * device,
- uint8_t chan, uint8_t num, uint8_t val) {
- //sending it back on the next channel
- // midi_send_cc(device, (chan + 1) % 16, num, val);
-}
-
-#ifdef API_SYSEX_ENABLE
-uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
-#endif
-
-void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
- #ifdef API_SYSEX_ENABLE
- // SEND_STRING("\n");
- // send_word(start);
- // SEND_STRING(": ");
- // Don't store the header
- int16_t pos = start - 4;
- for (uint8_t place = 0; place < length; place++) {
- // send_byte(*data);
- if (pos >= 0) {
- if (*data == 0xF7) {
- // SEND_STRING("\nRD: ");
- // for (uint8_t i = 0; i < start + place + 1; i++){
- // send_byte(midi_buffer[i]);
- // SEND_STRING(" ");
- // }
- const unsigned decoded_length = sysex_decoded_length(pos);
- uint8_t decoded[API_SYSEX_MAX_SIZE];
- sysex_decode(decoded, midi_buffer, pos);
- process_api(decoded_length, decoded);
- return;
- }
- else if (pos >= MIDI_SYSEX_BUFFER) {
- return;
- }
- midi_buffer[pos] = *data;
- }
- // SEND_STRING(" ");
- data++;
- pos++;
- }
- #endif
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint16_t wIndex,
+ const void** const DescriptorAddress)
+{
+ return get_usb_descriptor(wValue, wIndex, DescriptorAddress);
}
-
-#endif