#include "descriptor.h"
#include "lufa.h"
#include "quantum.h"
+#include <util/atomic.h>
+#include "outputselect.h"
#ifdef NKRO_ENABLE
#include "keycode_config.h"
#endif
#ifdef BLUETOOTH_ENABLE
+ #ifdef MODULE_ADAFRUIT_BLE
+ #include "adafruit_ble.h"
+ #else
#include "bluetooth.h"
+ #endif
#endif
#ifdef VIRTSER_ENABLE
#include "virtser.h"
#endif
-#ifdef RGB_MIDI
- #include "rgblight.h"
+#if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
+ #include "rgblight.h"
#endif
#ifdef MIDI_ENABLE
#include "sysex_tools.h"
#endif
+#ifdef RAW_ENABLE
+ #include "raw_hid.h"
+#endif
+
uint8_t keyboard_idle = 0;
/* 0: Boot Protocol, 1: Report Protocol(default) */
uint8_t keyboard_protocol = 1;
};
#endif
+#ifdef RAW_ENABLE
+
+void raw_hid_send( uint8_t *data, uint8_t length )
+{
+ // TODO: implement variable size packet
+ if ( length != RAW_EPSIZE )
+ {
+ return;
+ }
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ {
+ return;
+ }
+
+ // TODO: decide if we allow calls to raw_hid_send() in the middle
+ // of other endpoint usage.
+ uint8_t ep = Endpoint_GetCurrentEndpoint();
+
+ Endpoint_SelectEndpoint(RAW_IN_EPNUM);
+
+ // Check to see if the host is ready to accept another packet
+ if (Endpoint_IsINReady())
+ {
+ // Write data
+ Endpoint_Write_Stream_LE(data, RAW_EPSIZE, NULL);
+ // Finalize the stream transfer to send the last packet
+ Endpoint_ClearIN();
+ }
+
+ Endpoint_SelectEndpoint(ep);
+}
+
+__attribute__ ((weak))
+void raw_hid_receive( uint8_t *data, uint8_t length )
+{
+ // Users should #include "raw_hid.h" in their own code
+ // and implement this function there. Leave this as weak linkage
+ // so users can opt to not handle data coming in.
+}
+
+static void raw_hid_task(void)
+{
+ // Create a temporary buffer to hold the read in data from the host
+ uint8_t data[RAW_EPSIZE];
+ bool data_read = false;
+
+ // Device must be connected and configured for the task to run
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ Endpoint_SelectEndpoint(RAW_OUT_EPNUM);
+
+ // Check to see if a packet has been sent from the host
+ if (Endpoint_IsOUTReceived())
+ {
+ // Check to see if the packet contains data
+ if (Endpoint_IsReadWriteAllowed())
+ {
+ /* Read data */
+ Endpoint_Read_Stream_LE(data, sizeof(data), NULL);
+ data_read = true;
+ }
+
+ // Finalize the stream transfer to receive the last packet
+ Endpoint_ClearOUT();
+
+ if ( data_read )
+ {
+ raw_hid_receive( data, sizeof(data) );
+ }
+ }
+}
+#endif
/*******************************************************************************
* Console
#endif
}
+
+
#ifdef CONSOLE_ENABLE
static bool console_flush = false;
#define CONSOLE_FLUSH_SET(b) do { \
- uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {\
+ console_flush = b; \
+ } \
} while (0)
// called every 1ms
Console_Task();
console_flush = false;
}
+
#endif
/** Event handler for the USB_ConfigurationChanged event.
EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
#endif
+#ifdef RAW_ENABLE
+ /* Setup Raw HID Report Endpoints */
+ ConfigSuccess &= ENDPOINT_CONFIG(RAW_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ RAW_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= ENDPOINT_CONFIG(RAW_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
+ RAW_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+
#ifdef CONSOLE_ENABLE
/* Setup Console HID Report Endpoints */
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
/*******************************************************************************
* Host driver
-p
******************************************************************************/
static uint8_t keyboard_leds(void)
{
static void send_keyboard(report_keyboard_t *report)
{
+ uint8_t timeout = 255;
+ uint8_t where = where_to_send();
#ifdef BLUETOOTH_ENABLE
- bluefruit_serial_send(0xFD);
- for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
+ if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
+ #ifdef MODULE_ADAFRUIT_BLE
+ adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
+ #else
+ bluefruit_serial_send(0xFD);
+ for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
bluefruit_serial_send(report->raw[i]);
- }
+ }
+ #endif
+ }
#endif
- uint8_t timeout = 255;
-
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
+ if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
+ return;
+ }
/* Select the Keyboard Report Endpoint */
#ifdef NKRO_ENABLE
static void send_mouse(report_mouse_t *report)
{
#ifdef MOUSE_ENABLE
+ uint8_t timeout = 255;
+ uint8_t where = where_to_send();
#ifdef BLUETOOTH_ENABLE
- bluefruit_serial_send(0xFD);
- bluefruit_serial_send(0x00);
- bluefruit_serial_send(0x03);
- bluefruit_serial_send(report->buttons);
- bluefruit_serial_send(report->x);
- bluefruit_serial_send(report->y);
- bluefruit_serial_send(report->v); // should try sending the wheel v here
- bluefruit_serial_send(report->h); // should try sending the wheel h here
- bluefruit_serial_send(0x00);
+ 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);
+ #else
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x03);
+ bluefruit_serial_send(report->buttons);
+ bluefruit_serial_send(report->x);
+ bluefruit_serial_send(report->y);
+ bluefruit_serial_send(report->v); // should try sending the wheel v here
+ bluefruit_serial_send(report->h); // should try sending the wheel h here
+ bluefruit_serial_send(0x00);
+ #endif
+ }
#endif
- uint8_t timeout = 255;
-
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
+ if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
+ return;
+ }
/* Select the Mouse Report Endpoint */
Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
report_extra_t r = {
.report_id = REPORT_ID_SYSTEM,
- .usage = data
+ .usage = data - SYSTEM_POWER_DOWN + 1
};
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
static void send_consumer(uint16_t data)
{
+ uint8_t timeout = 255;
+ uint8_t where = where_to_send();
#ifdef BLUETOOTH_ENABLE
- static uint16_t last_data = 0;
- if (data == last_data) return;
- last_data = data;
- uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
- bluefruit_serial_send(0xFD);
- bluefruit_serial_send(0x00);
- bluefruit_serial_send(0x02);
- bluefruit_serial_send((bitmap>>8)&0xFF);
- bluefruit_serial_send(bitmap&0xFF);
- bluefruit_serial_send(0x00);
- bluefruit_serial_send(0x00);
- bluefruit_serial_send(0x00);
- bluefruit_serial_send(0x00);
+ if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
+ #ifdef MODULE_ADAFRUIT_BLE
+ adafruit_ble_send_consumer_key(data, 0);
+ #else
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+ uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x02);
+ bluefruit_serial_send((bitmap>>8)&0xFF);
+ bluefruit_serial_send(bitmap&0xFF);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ #endif
+ }
#endif
- uint8_t timeout = 255;
-
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
+ if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
+ return;
+ }
report_extra_t r = {
.report_id = REPORT_ID_CONSUMER,
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
int main(void) __attribute__ ((weak));
int main(void)
{
-
#ifdef MIDI_ENABLE
- 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);
+ setup_midi();
#endif
setup_mcu();
// midi_send_noteoff(&midi_device, 0, 64, 127);
#endif
-#ifdef BLUETOOTH_ENABLE
+#ifdef MODULE_ADAFRUIT_EZKEY
serial_init();
#endif
print("Keyboard start.\n");
while (1) {
- #ifndef BLUETOOTH_ENABLE
+ #if !defined(BLUETOOTH_ENABLE)
while (USB_DeviceState == DEVICE_STATE_Suspended) {
print("[s]");
suspend_power_down();
#ifdef MIDI_ENABLE
midi_device_process(&midi_device);
- // MIDI_Task();
+#ifdef MIDI_ADVANCED
+ midi_task();
+#endif
#endif
-
-#ifdef RGBLIGHT_ANIMATIONS
+
+#if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
rgblight_task();
#endif
+#ifdef MODULE_ADAFRUIT_BLE
+ adafruit_ble_task();
+#endif
+
#ifdef VIRTSER_ENABLE
virtser_task();
CDC_Device_USBTask(&cdc_device);
#endif
+#ifdef RAW_ENABLE
+ raw_hid_task();
+#endif
+
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif
+
}
}
#endif
}
-#ifdef RGB_MIDI
- rgblight_config_t rgblight_config;
-#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 RGB_MIDI
- rgblight_config.raw = eeconfig_read_rgblight();
- switch (num) {
- case 14:
- rgblight_config.hue = val * 360 / 127;
- break;
- case 15:
- rgblight_config.sat = val << 1;
- break;
- case 16:
- rgblight_config.val = val << 1;
- break;
- }
- rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
- #endif
}
+#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) {
- // for (int i = 0; i < length; i++)
- // midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i));
- // if (start == 0x27) {
+ #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);
- midi_buffer[start + place] = *data;
- if (*data == 0xF7) {
- // SEND_STRING("\nRD: ");
- // for (uint8_t i = 0; i < start + place + 1; i++){
- // send_byte(midi_buffer[i]);
- // SEND_STRING(" ");
- // }
- uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4)));
- uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4);
- sysex_buffer_callback(device, decode_length, decoded);
+ 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++;
}
- // }
-
-}
-
-uint32_t decode_uint32_chunk(uint8_t * data) {
- uint32_t part1 = *data++;
- uint32_t part2 = *data++;
- uint32_t part3 = *data++;
- uint32_t part4 = *data++;
- uint32_t part5 = *data++;
- return ((part1 & 0x1FUL) << 28) | (part2 << 21) | (part3 << 14) | (part4 << 7) | part5;
-}
-
-uint32_t decode_uint8_chunk(uint8_t * data) {
- uint32_t part4 = *data++;
- uint32_t part5 = *data++;
- return (part4 << 7) | part5;
-}
-
-void encode_uint32_chunk(uint32_t data, uint8_t * pointer) {
- *pointer++ = (data >> 28) & 0x7F;
- *pointer++ = (data >> 21) & 0x7F;
- *pointer++ = (data >> 14) & 0x7F;
- *pointer++ = (data >> 7) & 0x7F;
- *pointer++ = (data) & 0x7F;
-}
-
-void encode_uint8_chunk(uint8_t data, uint8_t * pointer) {
- *pointer++ = (data >> 7) & 0x7F;
- *pointer++ = (data) & 0x7F;
-}
-
-void dword_to_bytes(uint8_t * bytes, uint32_t dword) {
- bytes[0] = (dword >> 24) & 0xFF;
- bytes[1] = (dword >> 16) & 0xFF;
- bytes[2] = (dword >> 8) & 0xFF;
- bytes[3] = (dword >> 0) & 0xFF;
-}
-
-void sysex_buffer_callback(MidiDevice * device, uint8_t length, uint8_t * data) {
- // SEND_STRING("\nRX: ");
- // for (uint8_t i = 0; i < length; i++) {
- // send_byte(data[i]);
- // SEND_STRING(" ");
- // }
-
- switch (*data++) {
- case 0x07: ; // Quantum action
- break;
- case 0x08: ; // Keyboard action
- break;
- case 0x09: ; // User action
- break;
- case 0x12: ; // Set info on keyboard
- switch (*data++) {
- case 0x02: ; // set default layer
- eeconfig_update_default_layer(data[0] << 8 | data[1]);
- default_layer_set((uint32_t)(data[0] << 8 | data[1]));
- break;
- case 0x08: ; // set keymap options
- eeconfig_update_keymap(data[0]);
- break;
- }
- break;
- case 0x13: ; // Get info from keyboard
- switch (*data++) {
- case 0x00: ; // Handshake
- send_bytes_sysex(0x00, NULL, 0);
- break;
- case 0x01: ; // Get debug state
- uint8_t debug_bytes[1] = { eeprom_read_byte(EECONFIG_DEBUG) };
- send_bytes_sysex(0x01, debug_bytes, 1);
- break;
- case 0x02: ; // Get default layer
- uint8_t default_bytes[1] = { eeprom_read_byte(EECONFIG_DEFAULT_LAYER) };
- send_bytes_sysex(0x02, default_bytes, 1);
- break;
- #ifdef AUDIO_ENABLE
- case 0x03: ; // Get backlight state
- uint8_t audio_bytes[1] = { eeprom_read_byte(EECONFIG_AUDIO) };
- send_bytes_sysex(0x03, audio_bytes, 1);
- #endif
- case 0x04: ; // Get layer state
- uint8_t layer_state_bytes[4];
- dword_to_bytes(layer_state_bytes, layer_state);
- send_bytes_sysex(0x04, layer_state_bytes, 4);
- break;
- #ifdef BACKLIGHT_ENABLE
- case 0x06: ; // Get backlight state
- uint8_t backlight_bytes[1] = { eeprom_read_byte(EECONFIG_BACKLIGHT) };
- send_bytes_sysex(0x06, backlight_bytes, 1);
- #endif
- #ifdef RGBLIGHT_ENABLE
- case 0x07: ; // Get rgblight state
- uint8_t rgblight_bytes[4];
- dword_to_bytes(rgblight_bytes, eeprom_read_dword(EECONFIG_RGBLIGHT));
- send_bytes_sysex(0x07, rgblight_bytes, 4);
- #endif
- case 0x08: ; // Keymap options
- uint8_t keymap_bytes[1] = { eeconfig_read_keymap() };
- send_bytes_sysex(0x08, keymap_bytes, 1);
- break;
- }
- break;
- #ifdef RGBLIGHT_ENABLE
- case 0x27: ; // RGB LED functions
- switch (*data++) {
- case 0x00: ; // Update HSV
- rgblight_sethsv((data[0] << 8 | data[1]) % 360, data[2], data[3]);
- break;
- case 0x01: ; // Update RGB
- break;
- case 0x02: ; // Update mode
- rgblight_mode(data[0]);
- break;
- }
- break;
- #endif
- }
-
-}
-
-void send_unicode_midi(uint32_t unicode) {
- uint8_t chunk[5];
- encode_uint32_chunk(unicode, chunk);
- send_bytes_sysex(0x05, chunk, 5);
+ #endif
}
-void send_bytes_sysex(uint8_t type, uint8_t * bytes, uint8_t length) {
- // SEND_STRING("\nTX: ");
- // for (uint8_t i = 0; i < length; i++) {
- // send_byte(bytes[i]);
- // SEND_STRING(" ");
- // }
- uint8_t * precode = malloc(sizeof(uint8_t) * (length + 1));
- precode[0] = type;
- memcpy(precode + 1, bytes, length);
- uint8_t * encoded = malloc(sizeof(uint8_t) * (sysex_encoded_length(length + 1)));
- uint16_t encoded_length = sysex_encode(encoded, precode, length + 1);
- uint8_t * array = malloc(sizeof(uint8_t) * (encoded_length + 5));
- array[0] = 0xF0;
- array[1] = 0x00;
- array[2] = 0x00;
- array[3] = 0x00;
- array[encoded_length + 4] = 0xF7;
- memcpy(array + 4, encoded, encoded_length);
- midi_send_array(&midi_device, encoded_length + 5, array);
-
- // SEND_STRING("\nTD: ");
- // for (uint8_t i = 0; i < encoded_length + 5; i++) {
- // send_byte(array[i]);
- // SEND_STRING(" ");
- // }
-}
#endif