X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=tmk_core%2Fprotocol%2Flufa%2Flufa.c;h=60cba8d2a9897cf6978080c3c149c589c0586c3e;hb=62faa20ef6ddab7dacc74123b2253cf25b5c20f7;hp=c4531c8d730ada8ed3b8cf64975c5c79aa11120c;hpb=3d7aaa31e41a9c96e785b0c089d74dfda525dfbe;p=qmk_firmware.git diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index c4531c8d7..60cba8d2a 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -52,6 +52,8 @@ #include "descriptor.h" #include "lufa.h" #include "quantum.h" +#include +#include "outputselect.h" #ifdef NKRO_ENABLE #include "keycode_config.h" @@ -65,21 +67,29 @@ #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; @@ -175,6 +185,80 @@ USB_ClassInfo_CDC_Device_t cdc_device = }; #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 @@ -294,10 +378,14 @@ void EVENT_USB_Device_WakeUp() #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 @@ -311,6 +399,7 @@ void EVENT_USB_Device_StartOfFrame(void) Console_Task(); console_flush = false; } + #endif /** Event handler for the USB_ConfigurationChanged event. @@ -339,6 +428,14 @@ void EVENT_USB_Device_ConfigurationChanged(void) 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, @@ -494,7 +591,6 @@ void EVENT_USB_Device_ControlRequest(void) /******************************************************************************* * Host driver -p ******************************************************************************/ static uint8_t keyboard_leds(void) { @@ -503,18 +599,25 @@ 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 @@ -552,23 +655,31 @@ static void send_keyboard(report_keyboard_t *report) 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); @@ -594,7 +705,7 @@ static void send_system(uint16_t data) report_extra_t r = { .report_id = REPORT_ID_SYSTEM, - .usage = data + .usage = data - SYSTEM_POWER_DOWN + 1 }; Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM); @@ -608,27 +719,34 @@ static void send_system(uint16_t data) 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, @@ -978,16 +1096,23 @@ 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 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(); @@ -1007,7 +1132,7 @@ int main(void) // midi_send_noteoff(&midi_device, 0, 64, 127); #endif -#ifdef BLUETOOTH_ENABLE +#ifdef MODULE_ADAFRUIT_EZKEY serial_init(); #endif @@ -1038,7 +1163,7 @@ int main(void) print("Keyboard start.\n"); while (1) { - #ifndef BLUETOOTH_ENABLE + #if !defined(BLUETOOTH_ENABLE) while (USB_DeviceState == DEVICE_STATE_Suspended) { print("[s]"); suspend_power_down(); @@ -1052,21 +1177,32 @@ int main(void) #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 + } } @@ -1091,209 +1227,50 @@ void fallthrough_callback(MidiDevice * device, #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