- NKRO is used only when keyboard_protocol = 1(report)tags/v1.9
void add_key(uint8_t key) | void add_key(uint8_t key) | ||||
{ | { | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_nkro && keyboard_protocol) { | |||||
add_key_bit(key); | add_key_bit(key); | ||||
return; | return; | ||||
} | } | ||||
void del_key(uint8_t key) | void del_key(uint8_t key) | ||||
{ | { | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_nkro && keyboard_protocol) { | |||||
del_key_bit(key); | del_key_bit(key); | ||||
return; | return; | ||||
} | } | ||||
uint8_t get_first_key(void) | uint8_t get_first_key(void) | ||||
{ | { | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_nkro && keyboard_protocol) { | |||||
uint8_t i = 0; | uint8_t i = 0; | ||||
for (; i < REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | for (; i < REPORT_BITS && !keyboard_report->nkro.bits[i]; i++) | ||||
; | ; |
case KC_S: | case KC_S: | ||||
print("\n\n----- Status -----\n"); | print("\n\n----- Status -----\n"); | ||||
print_val_hex8(host_keyboard_leds()); | print_val_hex8(host_keyboard_leds()); | ||||
print_val_hex8(keyboard_protocol); | |||||
print_val_hex8(keyboard_idle); | |||||
#ifdef PROTOCOL_PJRC | #ifdef PROTOCOL_PJRC | ||||
print_val_hex8(UDCON); | print_val_hex8(UDCON); | ||||
print_val_hex8(UDIEN); | print_val_hex8(UDIEN); | ||||
print_val_hex8(UDINT); | print_val_hex8(UDINT); | ||||
print_val_hex8(usb_keyboard_leds); | print_val_hex8(usb_keyboard_leds); | ||||
print_val_hex8(usb_keyboard_protocol); | |||||
print_val_hex8(usb_keyboard_idle_config); | |||||
print_val_hex8(usb_keyboard_idle_count); | print_val_hex8(usb_keyboard_idle_count); | ||||
#endif | #endif | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
bool keyboard_nkro = false; | |||||
bool keyboard_nkro = true; | |||||
#endif | #endif | ||||
static host_driver_t *driver; | static host_driver_t *driver; |
extern bool keyboard_nkro; | extern bool keyboard_nkro; | ||||
#endif | #endif | ||||
uint8_t keyboard_idle; | |||||
uint8_t keyboard_protocol; | |||||
/* host driver */ | /* host driver */ | ||||
void host_set_driver(host_driver_t *driver); | void host_set_driver(host_driver_t *driver); |
#include "descriptor.h" | #include "descriptor.h" | ||||
#include "lufa.h" | #include "lufa.h" | ||||
static uint8_t idle_duration = 0; | |||||
static uint8_t protocol_report = 1; | |||||
uint8_t keyboard_idle = 0; | |||||
uint8_t keyboard_protocol = 1; | |||||
static uint8_t keyboard_led_stats = 0; | static uint8_t keyboard_led_stats = 0; | ||||
static report_keyboard_t keyboard_report_sent; | static report_keyboard_t keyboard_report_sent; | ||||
case HID_REQ_GetProtocol: | case HID_REQ_GetProtocol: | ||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
{ | { | ||||
Endpoint_ClearSETUP(); | |||||
while (!(Endpoint_IsINReady())); | |||||
Endpoint_Write_8(protocol_report); | |||||
Endpoint_ClearIN(); | |||||
Endpoint_ClearStatusStage(); | |||||
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { | |||||
Endpoint_ClearSETUP(); | |||||
while (!(Endpoint_IsINReady())); | |||||
Endpoint_Write_8(keyboard_protocol); | |||||
Endpoint_ClearIN(); | |||||
Endpoint_ClearStatusStage(); | |||||
} | |||||
} | } | ||||
break; | break; | ||||
case HID_REQ_SetProtocol: | case HID_REQ_SetProtocol: | ||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) | ||||
{ | { | ||||
Endpoint_ClearSETUP(); | |||||
Endpoint_ClearStatusStage(); | |||||
if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) { | |||||
Endpoint_ClearSETUP(); | |||||
Endpoint_ClearStatusStage(); | |||||
protocol_report = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | |||||
keyboard_protocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00); | |||||
clear_keyboard(); | |||||
} | |||||
} | } | ||||
break; | break; | ||||
Endpoint_ClearSETUP(); | Endpoint_ClearSETUP(); | ||||
Endpoint_ClearStatusStage(); | Endpoint_ClearStatusStage(); | ||||
idle_duration = ((USB_ControlRequest.wValue & 0xFF00) >> 8); | |||||
keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8); | |||||
} | } | ||||
break; | break; | ||||
{ | { | ||||
Endpoint_ClearSETUP(); | Endpoint_ClearSETUP(); | ||||
while (!(Endpoint_IsINReady())); | while (!(Endpoint_IsINReady())); | ||||
Endpoint_Write_8(idle_duration); | |||||
Endpoint_Write_8(keyboard_idle); | |||||
Endpoint_ClearIN(); | Endpoint_ClearIN(); | ||||
Endpoint_ClearStatusStage(); | Endpoint_ClearStatusStage(); | ||||
} | } | ||||
/* Select the Keyboard Report Endpoint */ | /* Select the Keyboard Report Endpoint */ | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) { | |||||
if (keyboard_nkro && keyboard_protocol) { | |||||
/* Report protocol - NKRO */ | |||||
Endpoint_SelectEndpoint(NKRO_IN_EPNUM); | Endpoint_SelectEndpoint(NKRO_IN_EPNUM); | ||||
/* Check if write ready for a polling interval around 1ms */ | /* Check if write ready for a polling interval around 1ms */ | ||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4); | while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4); | ||||
if (!Endpoint_IsReadWriteAllowed()) return; | if (!Endpoint_IsReadWriteAllowed()) return; | ||||
/* Write Keyboard Report Data */ | |||||
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL); | |||||
} | } | ||||
else | else | ||||
#endif | #endif | ||||
{ | { | ||||
/* Boot protocol */ | |||||
Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); | Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM); | ||||
/* Check if write ready for a polling interval around 10ms */ | /* Check if write ready for a polling interval around 10ms */ | ||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | ||||
if (!Endpoint_IsReadWriteAllowed()) return; | if (!Endpoint_IsReadWriteAllowed()) return; | ||||
} | |||||
/* Write Keyboard Report Data */ | |||||
#ifdef NKRO_ENABLE | |||||
if (keyboard_nkro) { | |||||
Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL); | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
/* boot mode */ | |||||
/* Write Keyboard Report Data */ | |||||
Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); | Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL); | ||||
} | } | ||||
#include "sleep_led.h" | #include "sleep_led.h" | ||||
#endif | #endif | ||||
#include "suspend.h" | #include "suspend.h" | ||||
#include "action.h" | |||||
#include "action_util.h" | #include "action_util.h" | ||||
} | } | ||||
/* TODO: should keep IDLE rate on each keyboard interface */ | /* TODO: should keep IDLE rate on each keyboard interface */ | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (!keyboard_nkro && usb_keyboard_idle_config && (++div4 & 3) == 0) { | |||||
if (!keyboard_nkro && keyboard_idle && (++div4 & 3) == 0) { | |||||
#else | #else | ||||
if (usb_keyboard_idle_config && (++div4 & 3) == 0) { | |||||
if (keyboard_idle && (++div4 & 3) == 0) { | |||||
#endif | #endif | ||||
UENUM = KBD_ENDPOINT; | UENUM = KBD_ENDPOINT; | ||||
if (UEINTX & (1<<RWAL)) { | if (UEINTX & (1<<RWAL)) { | ||||
usb_keyboard_idle_count++; | usb_keyboard_idle_count++; | ||||
if (usb_keyboard_idle_count == usb_keyboard_idle_config) { | |||||
if (usb_keyboard_idle_count == keyboard_idle) { | |||||
usb_keyboard_idle_count = 0; | usb_keyboard_idle_count = 0; | ||||
/* TODO: fix keyboard_report inconsistency */ | /* TODO: fix keyboard_report inconsistency */ | ||||
/* To avoid Mac SET_IDLE behaviour. | /* To avoid Mac SET_IDLE behaviour. | ||||
UEDATX = keyboard_report_prev->mods; | UEDATX = keyboard_report_prev->mods; | ||||
UEDATX = 0; | UEDATX = 0; | ||||
uint8_t keys = usb_keyboard_protocol ? KBD_REPORT_KEYS : 6; | |||||
uint8_t keys = keyboard_protocol ? KBD_REPORT_KEYS : 6; | |||||
for (uint8_t i=0; i<keys; i++) { | for (uint8_t i=0; i<keys; i++) { | ||||
UEDATX = keyboard_report_prev->keys[i]; | UEDATX = keyboard_report_prev->keys[i]; | ||||
} | } | ||||
} | } | ||||
if (bRequest == HID_GET_IDLE) { | if (bRequest == HID_GET_IDLE) { | ||||
usb_wait_in_ready(); | usb_wait_in_ready(); | ||||
UEDATX = usb_keyboard_idle_config; | |||||
UEDATX = keyboard_idle; | |||||
usb_send_in(); | usb_send_in(); | ||||
return; | return; | ||||
} | } | ||||
if (bRequest == HID_GET_PROTOCOL) { | if (bRequest == HID_GET_PROTOCOL) { | ||||
usb_wait_in_ready(); | usb_wait_in_ready(); | ||||
UEDATX = usb_keyboard_protocol; | |||||
UEDATX = keyboard_protocol; | |||||
usb_send_in(); | usb_send_in(); | ||||
return; | return; | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
if (bRequest == HID_SET_IDLE) { | if (bRequest == HID_SET_IDLE) { | ||||
usb_keyboard_idle_config = (wValue >> 8); | |||||
keyboard_idle = (wValue >> 8); | |||||
usb_keyboard_idle_count = 0; | usb_keyboard_idle_count = 0; | ||||
//usb_wait_in_ready(); | //usb_wait_in_ready(); | ||||
usb_send_in(); | usb_send_in(); | ||||
return; | return; | ||||
} | } | ||||
if (bRequest == HID_SET_PROTOCOL) { | if (bRequest == HID_SET_PROTOCOL) { | ||||
usb_keyboard_protocol = wValue; | |||||
keyboard_protocol = wValue; | |||||
clear_keyboard(); | |||||
//usb_wait_in_ready(); | //usb_wait_in_ready(); | ||||
usb_send_in(); | usb_send_in(); | ||||
return; | return; |
// protocol setting from the host. We use exactly the same report | // protocol setting from the host. We use exactly the same report | ||||
// either way, so this variable only stores the setting since we | // either way, so this variable only stores the setting since we | ||||
// are required to be able to report which setting is in use. | // are required to be able to report which setting is in use. | ||||
uint8_t usb_keyboard_protocol=1; | |||||
uint8_t keyboard_protocol=1; | |||||
// the idle configuration, how often we send the report to the | // the idle configuration, how often we send the report to the | ||||
// host (ms * 4) even when it hasn't changed | // host (ms * 4) even when it hasn't changed | ||||
// Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request. | // Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request. | ||||
uint8_t usb_keyboard_idle_config=125; | |||||
uint8_t keyobard_idle=125; | |||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t usb_keyboard_idle_count=0; | uint8_t usb_keyboard_idle_count=0; | ||||
int8_t result = 0; | int8_t result = 0; | ||||
#ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||
if (keyboard_nkro) | |||||
if (keyboard_nkro && keyboard_protocol) | |||||
result = send_report(report, KBD2_ENDPOINT, 0, KBD2_SIZE); | result = send_report(report, KBD2_ENDPOINT, 0, KBD2_SIZE); | ||||
else | else | ||||
#endif | #endif | ||||
{ | { | ||||
if (usb_keyboard_protocol) | |||||
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE); | |||||
else | |||||
result = send_report(report, KBD_ENDPOINT, 0, 6); | |||||
result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE); | |||||
} | } | ||||
if (result) return result; | if (result) return result; |
#include "host.h" | #include "host.h" | ||||
extern uint8_t usb_keyboard_protocol; | |||||
extern uint8_t usb_keyboard_idle_config; | |||||
extern uint8_t usb_keyboard_idle_count; | extern uint8_t usb_keyboard_idle_count; | ||||
extern volatile uint8_t usb_keyboard_leds; | extern volatile uint8_t usb_keyboard_leds; | ||||