forked from mirror/qmk_firmware
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -261,8 +261,9 @@ uint8_t I2C3733_Init_Control(void)
|
||||
{
|
||||
DBGC(DC_I2C3733_INIT_CONTROL_BEGIN);
|
||||
|
||||
srdata.bit.SDB_N = 1;
|
||||
SPI_WriteSRData();
|
||||
//Hardware state shutdown on boot
|
||||
//USB state machine will enable driver when communication is ready
|
||||
I2C3733_Control_Set(0);
|
||||
|
||||
CLK_delay_ms(1);
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ void disp_pixel_setup(void)
|
||||
while (cur < lede)
|
||||
{
|
||||
cur->px = (cur->x - disp.left) / disp.width * 100;
|
||||
cur->py = (cur->y - disp.top) / disp.height * 100;
|
||||
cur->py = (cur->y - disp.bottom) / disp.height * 100;
|
||||
*cur->rgb.r = 0;
|
||||
*cur->rgb.g = 0;
|
||||
*cur->rgb.b = 0;
|
||||
@@ -244,6 +244,7 @@ void led_matrix_prepare(void)
|
||||
uint8_t led_enabled;
|
||||
float led_animation_speed;
|
||||
uint8_t led_animation_direction;
|
||||
uint8_t led_animation_orientation;
|
||||
uint8_t led_animation_breathing;
|
||||
uint8_t led_animation_breathe_cur;
|
||||
uint8_t breathe_step;
|
||||
@@ -256,57 +257,57 @@ uint8_t led_lighting_mode;
|
||||
issi3733_led_t *led_cur;
|
||||
uint8_t led_per_run = 15;
|
||||
float breathe_mult;
|
||||
float pxmod;
|
||||
float pomod;
|
||||
|
||||
void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pxs) {
|
||||
float px;
|
||||
void led_run_pattern(led_setup_t *f, float* ro, float* go, float* bo, float pos) {
|
||||
float po;
|
||||
|
||||
while (f->end != 1)
|
||||
{
|
||||
px = pxs; //Reset px for new frame
|
||||
po = pos; //Reset po for new frame
|
||||
|
||||
//Add in any moving effects
|
||||
if ((!led_animation_direction && f->ef & EF_SCR_R) || (led_animation_direction && (f->ef & EF_SCR_L)))
|
||||
{
|
||||
px -= pxmod;
|
||||
po -= pomod;
|
||||
|
||||
if (px > 100) px -= 100;
|
||||
else if (px < 0) px += 100;
|
||||
if (po > 100) po -= 100;
|
||||
else if (po < 0) po += 100;
|
||||
}
|
||||
else if ((!led_animation_direction && f->ef & EF_SCR_L) || (led_animation_direction && (f->ef & EF_SCR_R)))
|
||||
{
|
||||
px += pxmod;
|
||||
po += pomod;
|
||||
|
||||
if (px > 100) px -= 100;
|
||||
else if (px < 0) px += 100;
|
||||
if (po > 100) po -= 100;
|
||||
else if (po < 0) po += 100;
|
||||
}
|
||||
|
||||
//Check if LED's px is in current frame
|
||||
if (px < f->hs) { f++; continue; }
|
||||
if (px > f->he) { f++; continue; }
|
||||
//Check if LED's po is in current frame
|
||||
if (po < f->hs) { f++; continue; }
|
||||
if (po > f->he) { f++; continue; }
|
||||
//note: < 0 or > 100 continue
|
||||
|
||||
//Calculate the px within the start-stop percentage for color blending
|
||||
px = (px - f->hs) / (f->he - f->hs);
|
||||
//Calculate the po within the start-stop percentage for color blending
|
||||
po = (po - f->hs) / (f->he - f->hs);
|
||||
|
||||
//Add in any color effects
|
||||
if (f->ef & EF_OVER)
|
||||
{
|
||||
*ro = (px * (f->re - f->rs)) + f->rs;// + 0.5;
|
||||
*go = (px * (f->ge - f->gs)) + f->gs;// + 0.5;
|
||||
*bo = (px * (f->be - f->bs)) + f->bs;// + 0.5;
|
||||
*ro = (po * (f->re - f->rs)) + f->rs;// + 0.5;
|
||||
*go = (po * (f->ge - f->gs)) + f->gs;// + 0.5;
|
||||
*bo = (po * (f->be - f->bs)) + f->bs;// + 0.5;
|
||||
}
|
||||
else if (f->ef & EF_SUBTRACT)
|
||||
{
|
||||
*ro -= (px * (f->re - f->rs)) + f->rs;// + 0.5;
|
||||
*go -= (px * (f->ge - f->gs)) + f->gs;// + 0.5;
|
||||
*bo -= (px * (f->be - f->bs)) + f->bs;// + 0.5;
|
||||
*ro -= (po * (f->re - f->rs)) + f->rs;// + 0.5;
|
||||
*go -= (po * (f->ge - f->gs)) + f->gs;// + 0.5;
|
||||
*bo -= (po * (f->be - f->bs)) + f->bs;// + 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ro += (px * (f->re - f->rs)) + f->rs;// + 0.5;
|
||||
*go += (px * (f->ge - f->gs)) + f->gs;// + 0.5;
|
||||
*bo += (px * (f->be - f->bs)) + f->bs;// + 0.5;
|
||||
*ro += (po * (f->re - f->rs)) + f->rs;// + 0.5;
|
||||
*go += (po * (f->ge - f->gs)) + f->gs;// + 0.5;
|
||||
*bo += (po * (f->be - f->bs)) + f->bs;// + 0.5;
|
||||
}
|
||||
|
||||
f++;
|
||||
@@ -319,12 +320,15 @@ led_instruction_t led_instructions[] = { { .end = 1 } };
|
||||
uint8_t highest_active_layer = 0;
|
||||
uint32_t temp_layer_state = 0;
|
||||
|
||||
void led_matrix_run(led_setup_t *f)
|
||||
__attribute__ ((weak))
|
||||
void led_matrix_run(void)
|
||||
{
|
||||
float ro;
|
||||
float go;
|
||||
float bo;
|
||||
float po;
|
||||
uint8_t led_this_run = 0;
|
||||
led_setup_t *f = (led_setup_t*)led_setups[led_animation_id];
|
||||
|
||||
if (led_cur == 0) //Denotes start of new processing cycle in the case of chunked processing
|
||||
{
|
||||
@@ -351,10 +355,10 @@ void led_matrix_run(led_setup_t *f)
|
||||
}
|
||||
|
||||
//Only needs to be calculated once per frame
|
||||
pxmod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
|
||||
pxmod *= 100.0f;
|
||||
pxmod = (uint32_t)pxmod % 10000;
|
||||
pxmod /= 100.0f;
|
||||
pomod = (float)(disp.frame % (uint32_t)(1000.0f / led_animation_speed)) / 10.0f * led_animation_speed;
|
||||
pomod *= 100.0f;
|
||||
pomod = (uint32_t)pomod % 10000;
|
||||
pomod /= 100.0f;
|
||||
|
||||
highest_active_layer = 0;
|
||||
temp_layer_state = layer_state;
|
||||
@@ -371,6 +375,15 @@ void led_matrix_run(led_setup_t *f)
|
||||
go = 0;
|
||||
bo = 0;
|
||||
|
||||
if (led_animation_orientation)
|
||||
{
|
||||
po = led_cur->py;
|
||||
}
|
||||
else
|
||||
{
|
||||
po = led_cur->px;
|
||||
}
|
||||
|
||||
if (led_lighting_mode == LED_MODE_KEYS_ONLY && led_cur->scan == 255)
|
||||
{
|
||||
//Do not act on this LED
|
||||
@@ -391,7 +404,7 @@ void led_matrix_run(led_setup_t *f)
|
||||
//Act on LED
|
||||
if (led_cur_instruction->end) {
|
||||
// If no instructions, use normal pattern
|
||||
led_run_pattern(f, &ro, &go, &bo, led_cur->px);
|
||||
led_run_pattern(f, &ro, &go, &bo, po);
|
||||
} else {
|
||||
uint8_t skip;
|
||||
uint8_t modid = (led_cur->id - 1) / 32; //PS: Calculate which id# contains the led bit
|
||||
@@ -424,9 +437,9 @@ void led_matrix_run(led_setup_t *f)
|
||||
go = led_cur_instruction->g;
|
||||
bo = led_cur_instruction->b;
|
||||
} else if (led_cur_instruction->flags & LED_FLAG_USE_PATTERN) {
|
||||
led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo, led_cur->px);
|
||||
led_run_pattern(led_setups[led_cur_instruction->pattern_id], &ro, &go, &bo, po);
|
||||
} else if (led_cur_instruction->flags & LED_FLAG_USE_ROTATE_PATTERN) {
|
||||
led_run_pattern(f, &ro, &go, &bo, led_cur->px);
|
||||
led_run_pattern(f, &ro, &go, &bo, po);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,6 +517,7 @@ uint8_t led_matrix_init(void)
|
||||
led_lighting_mode = LED_MODE_NORMAL;
|
||||
led_animation_speed = 4.0f;
|
||||
led_animation_direction = 0;
|
||||
led_animation_orientation = 0;
|
||||
led_animation_breathing = 0;
|
||||
led_animation_breathe_cur = BREATHE_MIN_STEP;
|
||||
breathe_step = 1;
|
||||
@@ -514,13 +528,19 @@ uint8_t led_matrix_init(void)
|
||||
|
||||
//Run led matrix code once for initial LED coloring
|
||||
led_cur = 0;
|
||||
led_matrix_run((led_setup_t*)led_setups[led_animation_id]);
|
||||
rgb_matrix_init_user();
|
||||
led_matrix_run();
|
||||
|
||||
DBGC(DC_LED_MATRIX_INIT_COMPLETE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void rgb_matrix_init_user(void) {
|
||||
|
||||
}
|
||||
|
||||
#define LED_UPDATE_RATE 10 //ms
|
||||
|
||||
//led data processing can take time, so process data in chunks to free up the processor
|
||||
@@ -557,7 +577,7 @@ void led_matrix_task(void)
|
||||
if (led_cur != lede)
|
||||
{
|
||||
//m15_off; //debug profiling
|
||||
led_matrix_run((led_setup_t*)led_setups[led_animation_id]);
|
||||
led_matrix_run();
|
||||
//m15_on; //debug profiling
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ typedef struct led_disp_s {
|
||||
} led_disp_t;
|
||||
|
||||
uint8_t led_matrix_init(void);
|
||||
void rgb_matrix_init_user(void);
|
||||
|
||||
#define LED_MODE_NORMAL 0 //Must be 0
|
||||
#define LED_MODE_KEYS_ONLY 1
|
||||
@@ -146,6 +147,7 @@ extern uint8_t led_enabled;
|
||||
extern float led_animation_speed;
|
||||
extern uint8_t led_lighting_mode;
|
||||
extern uint8_t led_animation_direction;
|
||||
extern uint8_t led_animation_orientation;
|
||||
extern uint8_t led_animation_breathing;
|
||||
extern uint8_t led_animation_breathe_cur;
|
||||
extern uint8_t breathe_dir;
|
||||
@@ -159,7 +161,7 @@ extern uint32_t layer_state;
|
||||
extern issi3733_led_t *led_cur;
|
||||
extern issi3733_led_t *lede;
|
||||
|
||||
void led_matrix_run(led_setup_t *f);
|
||||
void led_matrix_run(void);
|
||||
void led_matrix_task(void);
|
||||
|
||||
void gcr_compute(void);
|
||||
|
||||
@@ -31,6 +31,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//From keyboard's directory
|
||||
#include "config_led.h"
|
||||
|
||||
uint8_t g_usb_state = USB_FSMSTATUS_FSMSTATE_OFF_Val; //Saved USB state from hardware value to detect changes
|
||||
|
||||
void main_subtasks(void);
|
||||
uint8_t keyboard_leds(void);
|
||||
void send_keyboard(report_keyboard_t *report);
|
||||
@@ -155,39 +157,56 @@ void send_consumer(uint16_t data)
|
||||
#endif //EXTRAKEY_ENABLE
|
||||
}
|
||||
|
||||
uint8_t g_drvid;
|
||||
|
||||
void main_subtask_usb_state(void)
|
||||
{
|
||||
if (usb_state == USB_STATE_POWERDOWN)
|
||||
{
|
||||
uint32_t timer_led = timer_read32();
|
||||
static uint32_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware
|
||||
uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register
|
||||
|
||||
led_on;
|
||||
if (led_enabled)
|
||||
if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED
|
||||
{
|
||||
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If previously not SUSPENDED
|
||||
{
|
||||
for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
|
||||
suspend_power_down(); //Run suspend routine
|
||||
g_usb_state = fsmstate_now; //Save current USB state
|
||||
}
|
||||
}
|
||||
else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //Else if USB SLEEPING
|
||||
{
|
||||
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_SLEEP_Val) //If previously not SLEEPING
|
||||
{
|
||||
suspend_power_down(); //Run suspend routine
|
||||
g_usb_state = fsmstate_now; //Save current USB state
|
||||
}
|
||||
}
|
||||
else if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_ON_Val) //Else if USB ON
|
||||
{
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) //If previously not ON
|
||||
{
|
||||
if (fsmstate_on_delay == 0) //If ON delay timer is cleared
|
||||
{
|
||||
I2C3733_Control_Set(0);
|
||||
fsmstate_on_delay = CLK_get_ms() + 250; //Set ON delay timer
|
||||
}
|
||||
else if (CLK_get_ms() > fsmstate_on_delay) //Else if ON delay timer is active and timed out
|
||||
{
|
||||
suspend_wakeup_init(); //Run wakeup routine
|
||||
g_usb_state = fsmstate_now; //Save current USB state
|
||||
}
|
||||
}
|
||||
while (usb_state == USB_STATE_POWERDOWN)
|
||||
{
|
||||
if (timer_read32() - timer_led > 1000) led_off; //Good to indicate went to sleep, but only for a second
|
||||
}
|
||||
if (led_enabled)
|
||||
{
|
||||
for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
|
||||
{
|
||||
I2C3733_Control_Set(1);
|
||||
}
|
||||
}
|
||||
led_off;
|
||||
}
|
||||
else //Else if USB is in a state not being tracked
|
||||
{
|
||||
fsmstate_on_delay = 0; //Clear ON delay timer
|
||||
}
|
||||
}
|
||||
|
||||
void main_subtask_led(void)
|
||||
{
|
||||
if (g_usb_state != USB_FSMSTATUS_FSMSTATE_ON_Val) return; //Only run LED tasks if USB is operating
|
||||
|
||||
led_matrix_task();
|
||||
}
|
||||
|
||||
@@ -267,8 +286,8 @@ int main(void)
|
||||
|
||||
i2c_led_q_init();
|
||||
|
||||
for (g_drvid = 0; g_drvid < ISSI3733_DRIVER_COUNT; g_drvid++)
|
||||
I2C_LED_Q_ONOFF(g_drvid); //Queue data
|
||||
for (uint8_t drvid = 0; drvid < ISSI3733_DRIVER_COUNT; drvid++)
|
||||
I2C_LED_Q_ONOFF(drvid); //Queue data
|
||||
|
||||
keyboard_setup();
|
||||
|
||||
@@ -286,10 +305,21 @@ int main(void)
|
||||
|
||||
while (1)
|
||||
{
|
||||
keyboard_task();
|
||||
|
||||
main_subtasks(); //Note these tasks will also be run while waiting for USB keyboard polling intervals
|
||||
|
||||
if (g_usb_state == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val || g_usb_state == USB_FSMSTATUS_FSMSTATE_SLEEP_Val)
|
||||
{
|
||||
if (suspend_wakeup_condition())
|
||||
{
|
||||
udc_remotewakeup(); //Send remote wakeup signal
|
||||
wait_ms(50);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
keyboard_task();
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
if (CLK_get_ms() > next_print)
|
||||
{
|
||||
|
||||
@@ -210,7 +210,7 @@ static inline void udc_detach(void)
|
||||
/*! \brief The USB driver sends a resume signal called \e "Upstream Resume"
|
||||
* This is authorized only when the remote wakeup feature is enabled by host.
|
||||
*/
|
||||
static inline void udc_remotewakeup(void)
|
||||
inline void udc_remotewakeup(void)
|
||||
{
|
||||
udd_send_remotewakeup();
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "udi_hid.h"
|
||||
#include "udi_hid_kbd.h"
|
||||
#include <string.h>
|
||||
#include "report.h"
|
||||
|
||||
//***************************************************************************
|
||||
// KBD
|
||||
@@ -430,7 +431,7 @@ UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x80, // Usage (System Control),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x85, 0x02, // Report ID (2) (System),
|
||||
0x85, REPORT_ID_SYSTEM, // Report ID (2) (System),
|
||||
0x16, 0x01, 0x00, // Logical Minimum (1),
|
||||
0x26, 0x03, 0x00, // Logical Maximum (3),
|
||||
0x1A, 0x81, 0x00, // Usage Minimum (81) (System Power Down),
|
||||
@@ -445,7 +446,7 @@ UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {
|
||||
0x05, 0x0C, // Usage Page (Consumer),
|
||||
0x09, 0x01, // Usage (Consumer Control),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x85, 0x03, // Report ID (3) (Consumer),
|
||||
0x85, REPORT_ID_CONSUMER, // Report ID (3) (Consumer),
|
||||
0x16, 0x01, 0x00, // Logical Minimum (1),
|
||||
0x26, 0x9C, 0x02, // Logical Maximum (668),
|
||||
0x1A, 0x01, 0x00, // Usage Minimum (1),
|
||||
|
||||
@@ -52,8 +52,6 @@
|
||||
#include "samd51j18a.h"
|
||||
#include "ui.h"
|
||||
|
||||
volatile uint8_t usb_state;
|
||||
|
||||
//! Sequence process running each \c SEQUENCE_PERIOD ms
|
||||
#define SEQUENCE_PERIOD 150
|
||||
|
||||
@@ -72,12 +70,12 @@ static void ui_wakeup_handler(void)
|
||||
|
||||
void ui_init(void)
|
||||
{
|
||||
usb_state = USB_STATE_POWERUP;
|
||||
|
||||
}
|
||||
|
||||
void ui_powerdown(void)
|
||||
{
|
||||
usb_state = USB_STATE_POWERDOWN;
|
||||
|
||||
}
|
||||
|
||||
void ui_wakeup_enable(void)
|
||||
@@ -92,7 +90,7 @@ void ui_wakeup_disable(void)
|
||||
|
||||
void ui_wakeup(void)
|
||||
{
|
||||
usb_state = USB_STATE_POWERUP;
|
||||
|
||||
}
|
||||
|
||||
void ui_process(uint16_t framenumber)
|
||||
|
||||
@@ -47,12 +47,6 @@
|
||||
#ifndef _UI_H_
|
||||
#define _UI_H_
|
||||
|
||||
extern volatile uint8_t usb_state;
|
||||
|
||||
#define USB_STATE_UNKNOWN 0
|
||||
#define USB_STATE_POWERDOWN 1
|
||||
#define USB_STATE_POWERUP 2
|
||||
|
||||
//! \brief Initializes the user interface
|
||||
void ui_init(void);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#ifdef MIDI_ENABLE
|
||||
#include "qmk_midi.h"
|
||||
#endif
|
||||
#ifdef STM32F303xC
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
#include "eeprom_stm32.h"
|
||||
#endif
|
||||
#include "suspend.h"
|
||||
@@ -75,7 +75,7 @@ host_driver_t chibios_driver = {
|
||||
void virtser_task(void);
|
||||
#endif
|
||||
|
||||
#ifdef RAW_HID_ENABLE
|
||||
#ifdef RAW_ENABLE
|
||||
void raw_hid_task(void);
|
||||
#endif
|
||||
|
||||
@@ -112,7 +112,7 @@ int main(void) {
|
||||
halInit();
|
||||
chSysInit();
|
||||
|
||||
#ifdef STM32F303xC
|
||||
#ifdef STM32_EEPROM_ENABLE
|
||||
EEPROM_init();
|
||||
#endif
|
||||
|
||||
@@ -220,7 +220,7 @@ int main(void) {
|
||||
#ifdef VIRTSER_ENABLE
|
||||
virtser_task();
|
||||
#endif
|
||||
#ifdef RAW_HID_ENABLE
|
||||
#ifdef RAW_ENABLE
|
||||
raw_hid_task();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype
|
||||
return &desc;
|
||||
}
|
||||
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
/* keyboard endpoint state structure */
|
||||
static USBInEndpointState kbd_ep_state;
|
||||
/* keyboard endpoint initialization structure (IN) */
|
||||
@@ -110,8 +111,9 @@ static const USBEndpointConfig kbd_ep_config = {
|
||||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
/* mouse endpoint state structure */
|
||||
static USBInEndpointState mouse_ep_state;
|
||||
|
||||
@@ -128,45 +130,26 @@ static const USBEndpointConfig mouse_ep_config = {
|
||||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif /* MOUSE_ENABLE */
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
/* extrakey endpoint state structure */
|
||||
static USBInEndpointState extra_ep_state;
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
/* shared endpoint state structure */
|
||||
static USBInEndpointState shared_ep_state;
|
||||
|
||||
/* extrakey endpoint initialization structure (IN) */
|
||||
static const USBEndpointConfig extra_ep_config = {
|
||||
/* shared endpoint initialization structure (IN) */
|
||||
static const USBEndpointConfig shared_ep_config = {
|
||||
USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
|
||||
NULL, /* SETUP packet notification callback */
|
||||
extra_in_cb, /* IN notification callback */
|
||||
shared_in_cb, /* IN notification callback */
|
||||
NULL, /* OUT notification callback */
|
||||
EXTRAKEY_EPSIZE, /* IN maximum packet size */
|
||||
SHARED_EPSIZE, /* IN maximum packet size */
|
||||
0, /* OUT maximum packet size */
|
||||
&extra_ep_state, /* IN Endpoint state */
|
||||
&shared_ep_state, /* IN Endpoint state */
|
||||
NULL, /* OUT endpoint state */
|
||||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* nkro endpoint state structure */
|
||||
static USBInEndpointState nkro_ep_state;
|
||||
|
||||
/* nkro endpoint initialization structure (IN) */
|
||||
static const USBEndpointConfig nkro_ep_config = {
|
||||
USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
|
||||
NULL, /* SETUP packet notification callback */
|
||||
nkro_in_cb, /* IN notification callback */
|
||||
NULL, /* OUT notification callback */
|
||||
NKRO_EPSIZE, /* IN maximum packet size */
|
||||
0, /* OUT maximum packet size */
|
||||
&nkro_ep_state, /* IN Endpoint state */
|
||||
NULL, /* OUT endpoint state */
|
||||
2, /* IN multiplier */
|
||||
NULL /* SETUP buffer (not a SETUP endpoint) */
|
||||
};
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
size_t queue_capacity_in;
|
||||
@@ -309,16 +292,15 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
|
||||
case USB_EVENT_CONFIGURED:
|
||||
osalSysLockFromISR();
|
||||
/* Enable the endpoints specified into the configuration. */
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config);
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
usbInitEndpointI(usbp, MOUSE_IN_EPNUM, &mouse_ep_config);
|
||||
#endif /* MOUSE_ENABLE */
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
usbInitEndpointI(usbp, EXTRAKEY_IN_EPNUM, &extra_ep_config);
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
#ifdef NKRO_ENABLE
|
||||
usbInitEndpointI(usbp, NKRO_IN_EPNUM, &nkro_ep_config);
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
usbInitEndpointI(usbp, SHARED_IN_EPNUM, &shared_ep_config);
|
||||
#endif
|
||||
for (int i=0;i<NUM_USB_DRIVERS;i++) {
|
||||
usbInitEndpointI(usbp, drivers.array[i].config.bulk_in, &drivers.array[i].in_ep_config);
|
||||
usbInitEndpointI(usbp, drivers.array[i].config.bulk_out, &drivers.array[i].out_ep_config);
|
||||
@@ -389,9 +371,20 @@ static uint16_t get_hword(uint8_t *p) {
|
||||
* Other Device Required Optional Optional Optional Optional Optional
|
||||
*/
|
||||
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
static uint8_t set_report_buf[2] __attribute__((aligned(2)));
|
||||
static void set_led_transfer_cb(USBDriver *usbp) {
|
||||
if ((set_report_buf[0] == REPORT_ID_KEYBOARD) ||
|
||||
(set_report_buf[0] == REPORT_ID_NKRO)) {
|
||||
keyboard_led_stats = set_report_buf[1];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Callback for SETUP request on the endpoint 0 (control) */
|
||||
static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||
const USBDescriptor *dp;
|
||||
int has_report_id;
|
||||
|
||||
/* usbp->setup fields:
|
||||
* 0: bmRequestType (bitmask)
|
||||
@@ -409,42 +402,16 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||
case HID_GET_REPORT:
|
||||
switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#endif /* NKRO_ENABLE */
|
||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
case MOUSE_INTERFACE:
|
||||
usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
|
||||
switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
|
||||
case REPORT_ID_SYSTEM:
|
||||
extra_report_blank[0] = REPORT_ID_SYSTEM;
|
||||
usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
case REPORT_ID_CONSUMER:
|
||||
extra_report_blank[0] = REPORT_ID_CONSUMER;
|
||||
usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
#endif /* EXTRAKEY_ENABLE */
|
||||
#endif
|
||||
|
||||
default:
|
||||
usbSetupTransfer(usbp, NULL, 0, NULL);
|
||||
@@ -472,12 +439,25 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
|
||||
case HID_SET_REPORT:
|
||||
switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#endif /* NKRO_ENABLE */
|
||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
|
||||
case SHARED_INTERFACE:
|
||||
#endif
|
||||
/* keyboard_led_stats = <read byte from next OUT report>
|
||||
* keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
|
||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
|
||||
has_report_id = 0;
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
if (usbp->setup[4] == SHARED_INTERFACE) {
|
||||
has_report_id = 1;
|
||||
}
|
||||
#endif
|
||||
if (usbp->setup[4] == KEYBOARD_INTERFACE && !keyboard_protocol) {
|
||||
has_report_id = 0;
|
||||
}
|
||||
if (has_report_id) {
|
||||
usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
|
||||
} else {
|
||||
usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
|
||||
}
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -591,20 +571,13 @@ void init_usb_driver(USBDriver *usbp) {
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
/* keyboard IN callback hander (a kbd report has made it IN) */
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* nkro IN callback hander (a nkro report has made it IN) */
|
||||
void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
#endif /* NKRO_ENABLE */
|
||||
#endif
|
||||
|
||||
/* start-of-frame handler
|
||||
* TODO: i guess it would be better to re-implement using timers,
|
||||
@@ -628,9 +601,9 @@ static void keyboard_idle_timer_cb(void *arg) {
|
||||
}
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
if(!keymap_config.nkro && keyboard_idle) {
|
||||
if(!keymap_config.nkro && keyboard_idle && keyboard_protocol) {
|
||||
#else /* NKRO_ENABLE */
|
||||
if(keyboard_idle) {
|
||||
if(keyboard_idle && keyboard_protocol) {
|
||||
#endif /* NKRO_ENABLE */
|
||||
/* TODO: are we sure we want the KBD_ENDPOINT? */
|
||||
if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
|
||||
@@ -661,25 +634,25 @@ void send_keyboard(report_keyboard_t *report) {
|
||||
osalSysUnlock();
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
if(keymap_config.nkro) { /* NKRO protocol */
|
||||
if(keymap_config.nkro && keyboard_protocol) { /* NKRO protocol */
|
||||
/* need to wait until the previous packet has made it through */
|
||||
/* can rewrite this using the synchronous API, then would wait
|
||||
* until *after* the packet has been transmitted. I think
|
||||
* this is more efficient */
|
||||
/* busy wait, should be short and not very common */
|
||||
osalSysLock();
|
||||
if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) {
|
||||
if(usbGetTransmitStatusI(&USB_DRIVER, SHARED_IN_EPNUM)) {
|
||||
/* Need to either suspend, or loop and call unlock/lock during
|
||||
* every iteration - otherwise the system will remain locked,
|
||||
* no interrupts served, so USB not going through as well.
|
||||
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread);
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[SHARED_IN_EPNUM]->in_state->thread);
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t));
|
||||
usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)report, sizeof(struct nkro_report));
|
||||
osalSysUnlock();
|
||||
} else
|
||||
#endif /* NKRO_ENABLE */
|
||||
{ /* boot protocol */
|
||||
{ /* regular protocol */
|
||||
/* need to wait until the previous packet has made it through */
|
||||
/* busy wait, should be short and not very common */
|
||||
osalSysLock();
|
||||
@@ -690,7 +663,15 @@ void send_keyboard(report_keyboard_t *report) {
|
||||
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE);
|
||||
uint8_t *data, size;
|
||||
if (keyboard_protocol) {
|
||||
data = (uint8_t*)report;
|
||||
size = KEYBOARD_REPORT_SIZE;
|
||||
} else { /* boot protocol */
|
||||
data = &report->mods;
|
||||
size = 8;
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, data, size);
|
||||
osalSysUnlock();
|
||||
}
|
||||
keyboard_report_sent = *report;
|
||||
@@ -703,11 +684,13 @@ void send_keyboard(report_keyboard_t *report) {
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
|
||||
#ifndef MOUSE_SHARED_EP
|
||||
/* mouse IN callback hander (a mouse report has made it IN) */
|
||||
void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
#endif
|
||||
|
||||
void send_mouse(report_mouse_t *report) {
|
||||
osalSysLock();
|
||||
@@ -715,15 +698,16 @@ void send_mouse(report_mouse_t *report) {
|
||||
osalSysUnlock();
|
||||
return;
|
||||
}
|
||||
osalSysUnlock();
|
||||
|
||||
osalSysLock();
|
||||
if(usbGetTransmitStatusI(&USB_DRIVER, MOUSE_IN_EPNUM)) {
|
||||
/* Need to either suspend, or loop and call unlock/lock during
|
||||
* every iteration - otherwise the system will remain locked,
|
||||
* no interrupts served, so USB not going through as well.
|
||||
* Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
|
||||
osalThreadSuspendS(&(&USB_DRIVER)->epc[MOUSE_IN_EPNUM]->in_state->thread);
|
||||
if (osalThreadSuspendTimeoutS(&(&USB_DRIVER)->epc[MOUSE_IN_EPNUM]->in_state->thread, MS2ST(10))==MSG_TIMEOUT) {
|
||||
osalSysUnlock();
|
||||
return;
|
||||
}
|
||||
}
|
||||
usbStartTransmitI(&USB_DRIVER, MOUSE_IN_EPNUM, (uint8_t *)report, sizeof(report_mouse_t));
|
||||
osalSysUnlock();
|
||||
@@ -735,20 +719,25 @@ void send_mouse(report_mouse_t *report) {
|
||||
}
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Shared EP functions
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
/* shared IN callback hander */
|
||||
void shared_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Extrakey functions
|
||||
* ---------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
|
||||
/* extrakey IN callback hander */
|
||||
void extra_in_cb(USBDriver *usbp, usbep_t ep) {
|
||||
/* STUB */
|
||||
(void)usbp;
|
||||
(void)ep;
|
||||
}
|
||||
|
||||
static void send_extra_report(uint8_t report_id, uint16_t data) {
|
||||
osalSysLock();
|
||||
if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
|
||||
@@ -761,7 +750,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) {
|
||||
.usage = data
|
||||
};
|
||||
|
||||
usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
|
||||
usbStartTransmitI(&USB_DRIVER, SHARED_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,14 @@ void nkro_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
void mouse_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
#endif /* MOUSE_ENABLE */
|
||||
|
||||
/* ---------------
|
||||
* Shared EP header
|
||||
* ---------------
|
||||
*/
|
||||
|
||||
/* shared IN request callback handler */
|
||||
void shared_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
/* ---------------
|
||||
* Extrakey header
|
||||
* ---------------
|
||||
@@ -72,9 +80,6 @@ void mouse_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
|
||||
/* extrakey IN request callback handler */
|
||||
void extra_in_cb(USBDriver *usbp, usbep_t ep);
|
||||
|
||||
/* extra report structure */
|
||||
typedef struct {
|
||||
uint8_t report_id;
|
||||
|
||||
@@ -409,19 +409,21 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
bool ConfigSuccess = true;
|
||||
|
||||
/* Setup Keyboard HID Report Endpoints */
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
/* Setup Mouse HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
/* Setup Extra HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
/* Setup Shared HID Report Endpoint */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(SHARED_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
SHARED_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
@@ -442,12 +444,6 @@ void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
/* Setup NKRO HID Report Endpoints */
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
|
||||
NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
@@ -512,8 +508,8 @@ void EVENT_USB_Device_ControlRequest(void)
|
||||
// Interface
|
||||
switch (USB_ControlRequest.wIndex) {
|
||||
case KEYBOARD_INTERFACE:
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
|
||||
case SHARED_INTERFACE:
|
||||
#endif
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
@@ -521,7 +517,17 @@ void EVENT_USB_Device_ControlRequest(void)
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return;
|
||||
}
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
uint8_t report_id = REPORT_ID_KEYBOARD;
|
||||
if (keyboard_protocol) {
|
||||
report_id = Endpoint_Read_8();
|
||||
}
|
||||
if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
}
|
||||
#else
|
||||
keyboard_led_stats = Endpoint_Read_8();
|
||||
#endif
|
||||
|
||||
Endpoint_ClearOUT();
|
||||
Endpoint_ClearStatusStage();
|
||||
@@ -612,16 +618,20 @@ static void send_keyboard(report_keyboard_t *report)
|
||||
#ifdef MODULE_ADAFRUIT_BLE
|
||||
adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
|
||||
#elif MODULE_RN42
|
||||
bluefruit_serial_send(0xFD);
|
||||
bluefruit_serial_send(0x09);
|
||||
bluefruit_serial_send(0x01);
|
||||
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
|
||||
bluefruit_serial_send(report->raw[i]);
|
||||
}
|
||||
bluefruit_serial_send(0xFD);
|
||||
bluefruit_serial_send(0x09);
|
||||
bluefruit_serial_send(0x01);
|
||||
bluefruit_serial_send(report->mods);
|
||||
bluefruit_serial_send(report->reserved);
|
||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
|
||||
bluefruit_serial_send(report->keys[i]);
|
||||
}
|
||||
#else
|
||||
bluefruit_serial_send(0xFD);
|
||||
for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
|
||||
bluefruit_serial_send(report->raw[i]);
|
||||
bluefruit_serial_send(report->mods);
|
||||
bluefruit_serial_send(report->reserved);
|
||||
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
|
||||
bluefruit_serial_send(report->keys[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -632,30 +642,24 @@ static void send_keyboard(report_keyboard_t *report)
|
||||
}
|
||||
|
||||
/* Select the Keyboard Report Endpoint */
|
||||
uint8_t ep = KEYBOARD_IN_EPNUM;
|
||||
uint8_t size = KEYBOARD_REPORT_SIZE;
|
||||
#ifdef NKRO_ENABLE
|
||||
if (keyboard_protocol && keymap_config.nkro) {
|
||||
/* Report protocol - NKRO */
|
||||
Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 1ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Write Keyboard Report Data */
|
||||
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
|
||||
ep = SHARED_IN_EPNUM;
|
||||
size = sizeof(struct nkro_report);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Boot protocol */
|
||||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(ep);
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Write Keyboard Report Data */
|
||||
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
|
||||
/* If we're in Boot Protocol, don't send any report ID or other funky fields */
|
||||
if (!keyboard_protocol) {
|
||||
Endpoint_Write_Stream_LE(&report->mods, 8, NULL);
|
||||
} else {
|
||||
Endpoint_Write_Stream_LE(report, size, NULL);
|
||||
}
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
@@ -718,6 +722,7 @@ static void send_mouse(report_mouse_t *report)
|
||||
*/
|
||||
static void send_system(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
uint8_t timeout = 255;
|
||||
|
||||
if (USB_DeviceState != DEVICE_STATE_Configured)
|
||||
@@ -727,7 +732,7 @@ static void send_system(uint16_t data)
|
||||
.report_id = REPORT_ID_SYSTEM,
|
||||
.usage = data - SYSTEM_POWER_DOWN + 1
|
||||
};
|
||||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
@@ -735,6 +740,7 @@ static void send_system(uint16_t data)
|
||||
|
||||
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
|
||||
Endpoint_ClearIN();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Send Consumer
|
||||
@@ -743,6 +749,7 @@ static void send_system(uint16_t data)
|
||||
*/
|
||||
static void send_consumer(uint16_t data)
|
||||
{
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
uint8_t timeout = 255;
|
||||
uint8_t where = where_to_send();
|
||||
|
||||
@@ -786,7 +793,7 @@ static void send_consumer(uint16_t data)
|
||||
.report_id = REPORT_ID_CONSUMER,
|
||||
.usage = data
|
||||
};
|
||||
Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
|
||||
Endpoint_SelectEndpoint(SHARED_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
@@ -794,6 +801,7 @@ static void send_consumer(uint16_t data)
|
||||
|
||||
Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
|
||||
Endpoint_ClearIN();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,11 +47,18 @@
|
||||
/*******************************************************************************
|
||||
* HID Report Descriptors
|
||||
******************************************************************************/
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
{
|
||||
#ifdef KEYBOARD_SHARED_EP
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||
#define SHARED_REPORT_STARTED
|
||||
#else
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] = {
|
||||
#endif
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
# ifdef KEYBOARD_SHARED_EP
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_KEYBOARD),
|
||||
# endif
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
@@ -84,14 +91,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
HID_RI_REPORT_SIZE(8, 0x08),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
||||
{
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MOUSE_ENABLE)
|
||||
|
||||
# if !defined(MOUSE_SHARED_EP)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] = {
|
||||
# elif !defined(SHARED_REPORT_STARTED)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||
#define SHARED_REPORT_STARTED
|
||||
# endif
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x02), /* Mouse */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
# ifdef MOUSE_SHARED_EP
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_MOUSE),
|
||||
# endif
|
||||
HID_RI_USAGE(8, 0x01), /* Pointer */
|
||||
HID_RI_COLLECTION(8, 0x00), /* Physical */
|
||||
|
||||
@@ -133,12 +151,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
||||
|
||||
HID_RI_END_COLLECTION(0),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
# ifndef MOUSE_SHARED_EP
|
||||
};
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
|
||||
{
|
||||
#if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
|
||||
#endif
|
||||
# ifdef EXTRAKEY_ENABLE
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x80), /* System Control */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
@@ -164,6 +185,43 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
|
||||
HID_RI_REPORT_COUNT(8, 1),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
# endif
|
||||
|
||||
# ifdef NKRO_ENABLE
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
HID_RI_REPORT_ID(8, REPORT_ID_NKRO),
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, 0x08),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
||||
HID_RI_REPORT_COUNT(8, 0x05),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_REPORT_COUNT(8, 0x01),
|
||||
HID_RI_REPORT_SIZE(8, 0x03),
|
||||
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
||||
HID_RI_USAGE_MAXIMUM(8, KEYBOARD_REPORT_BITS*8-1),
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, KEYBOARD_REPORT_BITS*8),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
# endif
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -211,42 +269,6 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
|
||||
{
|
||||
HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
|
||||
HID_RI_USAGE(8, 0x06), /* Keyboard */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Application */
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, 0x08),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
|
||||
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
|
||||
HID_RI_REPORT_COUNT(8, 0x05),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_REPORT_COUNT(8, 0x01),
|
||||
HID_RI_REPORT_SIZE(8, 0x03),
|
||||
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
|
||||
|
||||
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
|
||||
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
|
||||
HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Device Descriptors
|
||||
@@ -303,6 +325,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
/*
|
||||
* Keyboard
|
||||
*/
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
.Keyboard_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
@@ -339,11 +362,12 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
.EndpointSize = KEYBOARD_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Mouse
|
||||
*/
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
.Mouse_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
@@ -383,26 +407,31 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Extra
|
||||
* Shared
|
||||
*/
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
.Extrakey_Interface =
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
.Shared_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = EXTRAKEY_INTERFACE,
|
||||
.InterfaceNumber = SHARED_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
# ifdef KEYBOARD_SHARED_EP
|
||||
.SubClass = HID_CSCP_BootSubclass,
|
||||
.Protocol = HID_CSCP_KeyboardBootProtocol,
|
||||
# else
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
#endif
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.Extrakey_HID =
|
||||
.Shared_HID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
@@ -410,16 +439,16 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(ExtrakeyReport)
|
||||
.HIDReportLength = sizeof(SharedReport)
|
||||
},
|
||||
|
||||
.Extrakey_INEndpoint =
|
||||
.Shared_INEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM),
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | SHARED_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = EXTRAKEY_EPSIZE,
|
||||
.EndpointSize = SHARED_EPSIZE,
|
||||
.PollingIntervalMS = 0x0A
|
||||
},
|
||||
#endif
|
||||
@@ -528,48 +557,6 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NKRO
|
||||
*/
|
||||
#ifdef NKRO_ENABLE
|
||||
.NKRO_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = NKRO_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.NKRO_HID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
.HIDSpec = VERSION_BCD(1,1,1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(NKROReport)
|
||||
},
|
||||
|
||||
.NKRO_INEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = NKRO_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
.Audio_Interface_Association =
|
||||
{
|
||||
@@ -936,19 +923,21 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
|
||||
break;
|
||||
case HID_DTYPE_HID:
|
||||
switch (wIndex) {
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
case KEYBOARD_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Keyboard_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
case MOUSE_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Mouse_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Extrakey_HID;
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
case SHARED_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Shared_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
@@ -963,31 +952,27 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
|
||||
Address = &ConfigurationDescriptor.Console_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.NKRO_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case HID_DTYPE_Report:
|
||||
switch (wIndex) {
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
case KEYBOARD_INTERFACE:
|
||||
Address = &KeyboardReport;
|
||||
Size = sizeof(KeyboardReport);
|
||||
break;
|
||||
#ifdef MOUSE_ENABLE
|
||||
#endif
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
case MOUSE_INTERFACE:
|
||||
Address = &MouseReport;
|
||||
Size = sizeof(MouseReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
case EXTRAKEY_INTERFACE:
|
||||
Address = &ExtrakeyReport;
|
||||
Size = sizeof(ExtrakeyReport);
|
||||
#ifdef SHARED_EP_ENABLE
|
||||
case SHARED_INTERFACE:
|
||||
Address = &SharedReport;
|
||||
Size = sizeof(SharedReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef RAW_ENABLE
|
||||
@@ -1001,12 +986,6 @@ uint16_t get_usb_descriptor(const uint16_t wValue,
|
||||
Address = &ConsoleReport;
|
||||
Size = sizeof(ConsoleReport);
|
||||
break;
|
||||
#endif
|
||||
#ifdef NKRO_ENABLE
|
||||
case NKRO_INTERFACE:
|
||||
Address = &NKROReport;
|
||||
Size = sizeof(NKROReport);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -53,26 +53,27 @@ typedef struct
|
||||
{
|
||||
USB_Descriptor_Configuration_Header_t Config;
|
||||
|
||||
#ifndef KEYBOARD_SHARED_EP
|
||||
// Keyboard HID Interface
|
||||
USB_Descriptor_Interface_t Keyboard_Interface;
|
||||
USB_HID_Descriptor_HID_t Keyboard_HID;
|
||||
USB_Descriptor_Endpoint_t Keyboard_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
// Mouse HID Interface
|
||||
USB_Descriptor_Interface_t Mouse_Interface;
|
||||
USB_HID_Descriptor_HID_t Mouse_HID;
|
||||
USB_Descriptor_Endpoint_t Mouse_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
// Extrakey HID Interface
|
||||
USB_Descriptor_Interface_t Extrakey_Interface;
|
||||
USB_HID_Descriptor_HID_t Extrakey_HID;
|
||||
USB_Descriptor_Endpoint_t Extrakey_INEndpoint;
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
USB_Descriptor_Interface_t Shared_Interface;
|
||||
USB_HID_Descriptor_HID_t Shared_HID;
|
||||
USB_Descriptor_Endpoint_t Shared_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
#if defined(RAW_ENABLE)
|
||||
// Raw HID Interface
|
||||
USB_Descriptor_Interface_t Raw_Interface;
|
||||
USB_HID_Descriptor_HID_t Raw_HID;
|
||||
@@ -88,13 +89,6 @@ typedef struct
|
||||
USB_Descriptor_Endpoint_t Console_OUTEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
// NKRO HID Interface
|
||||
USB_Descriptor_Interface_t NKRO_Interface;
|
||||
USB_HID_Descriptor_HID_t NKRO_HID;
|
||||
USB_Descriptor_Endpoint_t NKRO_INEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
USB_Descriptor_Interface_Association_t Audio_Interface_Association;
|
||||
// MIDI Audio Control Interface
|
||||
@@ -133,133 +127,105 @@ typedef struct
|
||||
|
||||
|
||||
/* index of interface */
|
||||
#define KEYBOARD_INTERFACE 0
|
||||
|
||||
enum usb_interfaces {
|
||||
#if !defined(KEYBOARD_SHARED_EP)
|
||||
KEYBOARD_INTERFACE,
|
||||
#else
|
||||
# define KEYBOARD_INTERFACE SHARED_INTERFACE
|
||||
#endif
|
||||
// It is important that the Raw HID interface is at a constant
|
||||
// interface number, to support Linux/OSX platforms and chrome.hid
|
||||
// If Raw HID is enabled, let it be always 1.
|
||||
#ifdef RAW_ENABLE
|
||||
# define RAW_INTERFACE (KEYBOARD_INTERFACE + 1)
|
||||
#else
|
||||
# define RAW_INTERFACE KEYBOARD_INTERFACE
|
||||
#if defined(RAW_ENABLE)
|
||||
RAW_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
# define MOUSE_INTERFACE (RAW_INTERFACE + 1)
|
||||
#else
|
||||
# define MOUSE_INTERFACE RAW_INTERFACE
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
MOUSE_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
# define EXTRAKEY_INTERFACE (MOUSE_INTERFACE + 1)
|
||||
#else
|
||||
# define EXTRAKEY_INTERFACE MOUSE_INTERFACE
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
SHARED_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_INTERFACE (EXTRAKEY_INTERFACE + 1)
|
||||
#else
|
||||
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
|
||||
#if defined(CONSOLE_ENABLE)
|
||||
CONSOLE_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
|
||||
#else
|
||||
# define NKRO_INTERFACE CONSOLE_INTERFACE
|
||||
#if defined(MIDI_ENABLE)
|
||||
AC_INTERFACE,
|
||||
AS_INTERFACE,
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
# define AC_INTERFACE (NKRO_INTERFACE + 1)
|
||||
# define AS_INTERFACE (NKRO_INTERFACE + 2)
|
||||
#else
|
||||
# define AS_INTERFACE NKRO_INTERFACE
|
||||
#if defined(VIRTSER_ENABLE)
|
||||
CCI_INTERFACE,
|
||||
CDI_INTERFACE,
|
||||
#endif
|
||||
TOTAL_INTERFACES
|
||||
};
|
||||
|
||||
#ifdef VIRTSER_ENABLE
|
||||
# define CCI_INTERFACE (AS_INTERFACE + 1)
|
||||
# define CDI_INTERFACE (AS_INTERFACE + 2)
|
||||
#define NEXT_EPNUM __COUNTER__
|
||||
|
||||
enum usb_endpoints {
|
||||
__unused_epnum__ = NEXT_EPNUM, /* EP numbering starts at 1 */
|
||||
#if !defined(KEYBOARD_SHARED_EP)
|
||||
KEYBOARD_IN_EPNUM = NEXT_EPNUM,
|
||||
#else
|
||||
# define CDI_INTERFACE AS_INTERFACE
|
||||
# define KEYBOARD_IN_EPNUM SHARED_IN_EPNUM
|
||||
#endif
|
||||
|
||||
/* nubmer of interfaces */
|
||||
#define TOTAL_INTERFACES (CDI_INTERFACE + 1)
|
||||
|
||||
|
||||
// Endopoint number and size
|
||||
#define KEYBOARD_IN_EPNUM 1
|
||||
|
||||
#ifdef MOUSE_ENABLE
|
||||
# define MOUSE_IN_EPNUM (KEYBOARD_IN_EPNUM + 1)
|
||||
#if defined(MOUSE_ENABLE) && !defined(MOUSE_SHARED_EP)
|
||||
MOUSE_IN_EPNUM = NEXT_EPNUM,
|
||||
#else
|
||||
# define MOUSE_IN_EPNUM KEYBOARD_IN_EPNUM
|
||||
# define MOUSE_IN_EPNUM SHARED_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef EXTRAKEY_ENABLE
|
||||
# define EXTRAKEY_IN_EPNUM (MOUSE_IN_EPNUM + 1)
|
||||
#else
|
||||
# define EXTRAKEY_IN_EPNUM MOUSE_IN_EPNUM
|
||||
#if defined(RAW_ENABLE)
|
||||
RAW_IN_EPNUM = NEXT_EPNUM,
|
||||
RAW_OUT_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
|
||||
#ifdef RAW_ENABLE
|
||||
# define RAW_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
|
||||
# define RAW_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
|
||||
#else
|
||||
# define RAW_OUT_EPNUM EXTRAKEY_IN_EPNUM
|
||||
#if defined(SHARED_EP_ENABLE)
|
||||
SHARED_IN_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
|
||||
#ifdef CONSOLE_ENABLE
|
||||
# define CONSOLE_IN_EPNUM (RAW_OUT_EPNUM + 1)
|
||||
#if defined(CONSOLE_ENABLE)
|
||||
CONSOLE_IN_EPNUM = NEXT_EPNUM,
|
||||
#ifdef PROTOCOL_CHIBIOS
|
||||
// ChibiOS has enough memory and descriptor to actually enable the endpoint
|
||||
// It could use the same endpoint numbers, as that's supported by ChibiOS
|
||||
// But the QMK code currently assumes that the endpoint numbers are different
|
||||
# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 2)
|
||||
CONSOLE_OUT_EPNUM = NEXT_EPNUM,
|
||||
#else
|
||||
# define CONSOLE_OUT_EPNUM (RAW_OUT_EPNUM + 1)
|
||||
#define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM
|
||||
#endif
|
||||
#else
|
||||
# define CONSOLE_OUT_EPNUM RAW_OUT_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef NKRO_ENABLE
|
||||
# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
|
||||
#else
|
||||
# define NKRO_IN_EPNUM CONSOLE_OUT_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef MIDI_ENABLE
|
||||
# define MIDI_STREAM_IN_EPNUM (NKRO_IN_EPNUM + 1)
|
||||
// # define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 1)
|
||||
# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
|
||||
MIDI_STREAM_IN_EPNUM = NEXT_EPNUM,
|
||||
MIDI_STREAM_OUT_EPNUM = NEXT_EPNUM,
|
||||
# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
|
||||
# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
|
||||
#else
|
||||
# define MIDI_STREAM_OUT_EPNUM NKRO_IN_EPNUM
|
||||
#endif
|
||||
|
||||
#ifdef VIRTSER_ENABLE
|
||||
# define CDC_NOTIFICATION_EPNUM (MIDI_STREAM_OUT_EPNUM + 1)
|
||||
# define CDC_IN_EPNUM (MIDI_STREAM_OUT_EPNUM + 2)
|
||||
# define CDC_OUT_EPNUM (MIDI_STREAM_OUT_EPNUM + 3)
|
||||
CDC_NOTIFICATION_EPNUM = NEXT_EPNUM,
|
||||
CDC_IN_EPNUM = NEXT_EPNUM,
|
||||
CDC_OUT_EPNUM = NEXT_EPNUM,
|
||||
# define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM)
|
||||
# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
|
||||
# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
|
||||
#else
|
||||
# define CDC_OUT_EPNUM MIDI_STREAM_OUT_EPNUM
|
||||
#endif
|
||||
};
|
||||
|
||||
#if (defined(PROTOCOL_LUFA) && CDC_OUT_EPNUM > (ENDPOINT_TOTAL_ENDPOINTS - 1)) || \
|
||||
(defined(PROTOCOL_CHIBIOS) && CDC_OUT_EPNUM > USB_MAX_ENDPOINTS)
|
||||
# error "There are not enough available endpoints to support all functions. Remove some in the rules.mk file.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL, STENO)"
|
||||
#if defined(PROTOCOL_LUFA)
|
||||
/* LUFA tells us total endpoints including control */
|
||||
#define MAX_ENDPOINTS (ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
#elif defined(PROTOCOL_CHIBIOS)
|
||||
/* ChibiOS gives us number of available user endpoints, not control */
|
||||
#define MAX_ENDPOINTS USB_MAX_ENDPOINTS
|
||||
#endif
|
||||
/* TODO - ARM_ATSAM */
|
||||
|
||||
|
||||
#if (NEXT_EPNUM - 1) > MAX_ENDPOINTS
|
||||
# error There are not enough available endpoints to support all functions. Remove some in the rules.mk file. (MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI, SERIAL, STENO)
|
||||
#endif
|
||||
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
#define SHARED_EPSIZE 32
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define EXTRAKEY_EPSIZE 8
|
||||
#define RAW_EPSIZE 32
|
||||
#define CONSOLE_EPSIZE 32
|
||||
#define NKRO_EPSIZE 32
|
||||
#define MIDI_STREAM_EPSIZE 64
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
#define CDC_EPSIZE 16
|
||||
|
||||
@@ -118,7 +118,7 @@ RTMODEL "__rt_version", "3"
|
||||
# define polyH r21
|
||||
# define scratch r23
|
||||
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
/* Register assignments for usbCrc16 on gcc */
|
||||
/* Calling conventions on gcc:
|
||||
* First parameter passed in r24/r25, second in r22/23 and so on.
|
||||
@@ -151,7 +151,7 @@ RTMODEL "__rt_version", "3"
|
||||
; unsigned table(unsigned char x)
|
||||
; {
|
||||
; unsigned value;
|
||||
;
|
||||
;
|
||||
; value = (unsigned)x << 6;
|
||||
; value ^= (unsigned)x << 7;
|
||||
; if(parity(x))
|
||||
@@ -161,7 +161,7 @@ RTMODEL "__rt_version", "3"
|
||||
; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
|
||||
; {
|
||||
; unsigned crc = 0xffff;
|
||||
;
|
||||
;
|
||||
; while(argLen--)
|
||||
; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
|
||||
; return ~crc;
|
||||
@@ -299,7 +299,7 @@ usbCrc16Append:
|
||||
# define cnt16H r31
|
||||
# define cntH r18
|
||||
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
#else /* __IAR_SYSTEMS_ASM__ */
|
||||
/* Register assignments for usbMeasureFrameLength on gcc */
|
||||
/* Calling conventions on gcc:
|
||||
* First parameter passed in r24/r25, second in r22/23 and so on.
|
||||
|
||||
71
tmk_core/protocol/xt.h
Normal file
71
tmk_core/protocol/xt.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright 2018 Jun WAKO <wakojun@gmail.com>
|
||||
Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
|
||||
|
||||
This software is licensed with a Modified BSD License.
|
||||
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
||||
GPL-compatible, and OK to use in both free and proprietary applications.
|
||||
Additions and corrections to this file are welcome.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef XT_H
|
||||
#define XT_H
|
||||
|
||||
#define XT_DATA_IN() do { \
|
||||
XT_DATA_DDR &= ~(1<<XT_DATA_BIT); \
|
||||
XT_DATA_PORT |= (1<<XT_DATA_BIT); \
|
||||
} while (0)
|
||||
|
||||
#define XT_DATA_READ() (XT_DATA_PIN&(1<<XT_DATA_BIT))
|
||||
|
||||
#define XT_DATA_LO() do { \
|
||||
XT_DATA_PORT &= ~(1<<XT_DATA_BIT); \
|
||||
XT_DATA_DDR |= (1<<XT_DATA_BIT); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define XT_CLOCK_IN() do { \
|
||||
XT_CLOCK_DDR &= ~(1<<XT_CLOCK_BIT); \
|
||||
XT_CLOCK_PORT |= (1<<XT_CLOCK_BIT); \
|
||||
} while (0)
|
||||
|
||||
#define XT_CLOCK_READ() (XT_CLOCK_PIN&(1<<XT_CLOCK_BIT))
|
||||
|
||||
#define XT_CLOCK_LO() do { \
|
||||
XT_CLOCK_PORT &= ~(1<<XT_CLOCK_BIT); \
|
||||
XT_CLOCK_DDR |= (1<<XT_CLOCK_BIT); \
|
||||
} while (0)
|
||||
|
||||
|
||||
void xt_host_init(void);
|
||||
uint8_t xt_host_recv(void);
|
||||
|
||||
#endif
|
||||
173
tmk_core/protocol/xt_interrupt.c
Normal file
173
tmk_core/protocol/xt_interrupt.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
Copyright 2018 Jun WAKO <wakojun@gmail.com>
|
||||
Copyright 2016 Ethan Apodaca <papodaca@gmail.com>
|
||||
|
||||
This software is licensed with a Modified BSD License.
|
||||
All of this is supposed to be Free Software, Open Source, DFSG-free,
|
||||
GPL-compatible, and OK to use in both free and proprietary applications.
|
||||
Additions and corrections to this file are welcome.
|
||||
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "xt.h"
|
||||
#include "wait.h"
|
||||
#include "print.h"
|
||||
|
||||
static inline uint8_t pbuf_dequeue(void);
|
||||
static inline void pbuf_enqueue(uint8_t data);
|
||||
static inline bool pbuf_has_data(void);
|
||||
static inline void pbuf_clear(void);
|
||||
|
||||
void xt_host_init(void)
|
||||
{
|
||||
XT_INT_INIT();
|
||||
XT_INT_OFF();
|
||||
|
||||
/* hard reset */
|
||||
#ifdef XT_RESET
|
||||
XT_RESET();
|
||||
#endif
|
||||
|
||||
/* soft reset: pull clock line down for 20ms */
|
||||
XT_DATA_LO();
|
||||
XT_CLOCK_LO();
|
||||
_delay_ms(20);
|
||||
|
||||
/* input mode with pullup */
|
||||
XT_CLOCK_IN();
|
||||
XT_DATA_IN();
|
||||
|
||||
XT_INT_ON();
|
||||
}
|
||||
|
||||
/* get data received by interrupt */
|
||||
uint8_t xt_host_recv(void)
|
||||
{
|
||||
if (pbuf_has_data()) {
|
||||
return pbuf_dequeue();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ISR(XT_INT_VECT)
|
||||
{
|
||||
/*
|
||||
* XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data,
|
||||
* which should be read on falling edge of clock.
|
||||
*
|
||||
* start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7
|
||||
*
|
||||
* Original IBM XT keyboard sends start(0) bit while some of clones don't.
|
||||
* Start(0) bit is read as low on data line while start(1) as high.
|
||||
*
|
||||
* https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol
|
||||
*/
|
||||
static enum {
|
||||
START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7
|
||||
} state = START;
|
||||
static uint8_t data = 0;
|
||||
|
||||
uint8_t dbit = XT_DATA_READ();
|
||||
|
||||
// This is needed if using PCINT which can be called on both falling and rising edge
|
||||
//if (XT_CLOCK_READ()) return;
|
||||
|
||||
switch (state) {
|
||||
case START:
|
||||
// ignore start(0) bit
|
||||
if (!dbit) return;
|
||||
break;
|
||||
case BIT0 ... BIT7:
|
||||
data >>= 1;
|
||||
if (dbit)
|
||||
data |= 0x80;
|
||||
break;
|
||||
}
|
||||
if (state++ == BIT7) {
|
||||
pbuf_enqueue(data);
|
||||
state = START;
|
||||
data = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Ring buffer to store scan codes from keyboard
|
||||
*------------------------------------------------------------------*/
|
||||
#define PBUF_SIZE 32
|
||||
static uint8_t pbuf[PBUF_SIZE];
|
||||
static uint8_t pbuf_head = 0;
|
||||
static uint8_t pbuf_tail = 0;
|
||||
static inline void pbuf_enqueue(uint8_t data)
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
|
||||
if (next != pbuf_tail) {
|
||||
pbuf[pbuf_head] = data;
|
||||
pbuf_head = next;
|
||||
} else {
|
||||
print("pbuf: full\n");
|
||||
}
|
||||
SREG = sreg;
|
||||
}
|
||||
static inline uint8_t pbuf_dequeue(void)
|
||||
{
|
||||
uint8_t val = 0;
|
||||
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
if (pbuf_head != pbuf_tail) {
|
||||
val = pbuf[pbuf_tail];
|
||||
pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
|
||||
}
|
||||
SREG = sreg;
|
||||
|
||||
return val;
|
||||
}
|
||||
static inline bool pbuf_has_data(void)
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
bool has_data = (pbuf_head != pbuf_tail);
|
||||
SREG = sreg;
|
||||
return has_data;
|
||||
}
|
||||
static inline void pbuf_clear(void)
|
||||
{
|
||||
uint8_t sreg = SREG;
|
||||
cli();
|
||||
pbuf_head = pbuf_tail = 0;
|
||||
SREG = sreg;
|
||||
}
|
||||
Reference in New Issue
Block a user