1
0

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
jonathan.liu
2018-12-06 23:35:20 -08:00
1684 changed files with 72110 additions and 11538 deletions

View File

@@ -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);

View File

@@ -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
}
}

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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();
}

View File

@@ -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),

View File

@@ -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)

View File

@@ -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);

View File

@@ -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
}

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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
View 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

View 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;
}