#include "descriptor.h"
#include "lufa.h"
#include "quantum.h"
+#include <util/atomic.h>
#ifdef NKRO_ENABLE
#include "keycode_config.h"
#ifdef BLUETOOTH_ENABLE
#include "bluetooth.h"
#endif
+#ifdef ADAFRUIT_BLE_ENABLE
+ #include "adafruit_ble.h"
+#endif
#ifdef VIRTSER_ENABLE
#include "virtser.h"
#endif
#if (defined(RGB_MIDI) | defined(RGBLIGHT_ANIMATIONS)) & defined(RGBLIGHT_ENABLE)
- #include "rgblight.h"
+ #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,
return keyboard_led_stats;
}
+#define SendToUSB 1
+#define SendToBT 2
+#define SendToBLE 4
+
+static inline uint8_t where_to_send(void) {
+#ifdef ADAFRUIT_BLE_ENABLE
+#if 0
+ if (adafruit_ble_is_connected()) {
+ // For testing, send to BLE as a priority
+ return SendToBLE;
+ }
+#endif
+
+ // This is the real policy
+ if (USB_DeviceState != DEVICE_STATE_Configured) {
+ if (adafruit_ble_is_connected()) {
+ return SendToBLE;
+ }
+ }
+#endif
+ return ((USB_DeviceState == DEVICE_STATE_Configured) ? SendToUSB : 0)
+#ifdef BLUETOOTH_ENABLE
+ || SendToBT
+#endif
+ ;
+}
+
static void send_keyboard(report_keyboard_t *report)
{
-
#ifdef BLUETOOTH_ENABLE
bluefruit_serial_send(0xFD);
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
#endif
uint8_t timeout = 255;
+ uint8_t where = where_to_send();
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
+#ifdef ADAFRUIT_BLE_ENABLE
+ if (where & SendToBLE) {
+ adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
+ }
+#endif
+
+ if (!(where & SendToUSB)) {
+ return;
+ }
/* Select the Keyboard Report Endpoint */
#ifdef NKRO_ENABLE
uint8_t timeout = 255;
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
+ uint8_t where = where_to_send();
+
+#ifdef ADAFRUIT_BLE_ENABLE
+ if (where & SendToBLE) {
+ // FIXME: mouse buttons
+ adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h);
+ }
+#endif
+ if (!(where & SendToUSB)) {
+ 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);
#endif
uint8_t timeout = 255;
+ uint8_t where = where_to_send();
- if (USB_DeviceState != DEVICE_STATE_Configured)
- return;
+#ifdef ADAFRUIT_BLE_ENABLE
+ if (where & SendToBLE) {
+ adafruit_ble_send_consumer_key(data, 0);
+ }
+#endif
+ if (!(where & SendToUSB)) {
+ return;
+ }
report_extra_t r = {
.report_id = REPORT_ID_CONSUMER,
print("Keyboard start.\n");
while (1) {
- #ifndef BLUETOOTH_ENABLE
+ #if !defined(BLUETOOTH_ENABLE) && !defined(ADAFRUIT_BLE_ENABLE)
while (USB_DeviceState == DEVICE_STATE_Suspended) {
print("[s]");
suspend_power_down();
midi_device_process(&midi_device);
// MIDI_Task();
#endif
-
+
#if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE)
rgblight_task();
#endif
+#ifdef ADAFRUIT_BLE_ENABLE
+ 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
+
}
}