diff --git a/common/host.c b/common/host.c
index 2c2279aa..56945165 100644
--- a/common/host.c
+++ b/common/host.c
@@ -37,8 +37,10 @@ static uint16_t last_consumer_report = 0;
static inline void add_key_byte(uint8_t code);
static inline void del_key_byte(uint8_t code);
+#ifdef NKRO_ENABLE
static inline void add_key_bit(uint8_t code);
static inline void del_key_bit(uint8_t code);
+#endif
void host_set_driver(host_driver_t *d)
@@ -63,11 +65,11 @@ void host_keyboard_send(report_keyboard_t *report)
(*driver->send_keyboard)(report);
if (debug_keyboard) {
- dprint("keys: ");
- for (int i = 0; i < REPORT_KEYS; i++) {
- dprintf("%02X ", keyboard_report->keys[i]);
+ dprint("keyboard_report: ");
+ for (uint8_t i = 0; i < REPORT_SIZE; i++) {
+ dprintf("%02X ", keyboard_report->raw[i]);
}
- dprintf(" mods: %02X\n", keyboard_report->mods);
+ dprint("\n");
}
}
@@ -122,8 +124,9 @@ void host_del_key(uint8_t key)
void host_clear_keys(void)
{
- for (int8_t i = 0; i < REPORT_KEYS; i++) {
- keyboard_report->keys[i] = 0;
+ // not clea mods
+ for (int8_t i = 1; i < REPORT_SIZE; i++) {
+ keyboard_report->raw[i] = 0;
}
}
@@ -155,8 +158,8 @@ void host_clear_mods(void)
uint8_t host_has_anykey(void)
{
uint8_t cnt = 0;
- for (int i = 0; i < REPORT_KEYS; i++) {
- if (keyboard_report->keys[i])
+ for (uint8_t i = 1; i < REPORT_SIZE; i++) {
+ if (keyboard_report->raw[i])
cnt++;
}
return cnt;
@@ -172,9 +175,9 @@ uint8_t host_get_first_key(void)
#ifdef NKRO_ENABLE
if (keyboard_nkro) {
uint8_t i = 0;
- for (; i < REPORT_KEYS && !keyboard_report->keys[i]; i++)
+ for (; i < REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
;
- return i<<3 | biton(keyboard_report->keys[i]);
+ return i<<3 | biton(keyboard_report->nkro.bits[i]);
}
#endif
return keyboard_report->keys[0];
@@ -222,18 +225,18 @@ static inline void add_key_byte(uint8_t code)
static inline void del_key_byte(uint8_t code)
{
- int i = 0;
- for (; i < REPORT_KEYS; i++) {
+ for (uint8_t i = 0; i < REPORT_KEYS; i++) {
if (keyboard_report->keys[i] == code) {
keyboard_report->keys[i] = 0;
}
}
}
+#ifdef NKRO_ENABLE
static inline void add_key_bit(uint8_t code)
{
- if ((code>>3) < REPORT_KEYS) {
- keyboard_report->keys[code>>3] |= 1<<(code&7);
+ if ((code>>3) < REPORT_BITS) {
+ keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
} else {
dprintf("add_key_bit: can't add: %02X\n", code);
}
@@ -241,9 +244,10 @@ static inline void add_key_bit(uint8_t code)
static inline void del_key_bit(uint8_t code)
{
- if ((code>>3) < REPORT_KEYS) {
- keyboard_report->keys[code>>3] &= ~(1<<(code&7));
+ if ((code>>3) < REPORT_BITS) {
+ keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
} else {
dprintf("del_key_bit: can't del: %02X\n", code);
}
}
+#endif
diff --git a/common/report.h b/common/report.h
index 02deb779..91982840 100644
--- a/common/report.h
+++ b/common/report.h
@@ -72,14 +72,20 @@ along with this program. If not, see .
/* key report size(NKRO or boot mode) */
-#if defined(PROTOCOL_PJRC)
+#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE)
# include "usb.h"
-# if defined(KBD2_REPORT_KEYS) && KBD2_REPORT_KEYS > KBD_REPORT_KEYS
-# define REPORT_KEYS KBD2_REPORT_KEYS
-# else
-# define REPORT_KEYS KBD_REPORT_KEYS
-# endif
+# define REPORT_SIZE KBD2_SIZE
+# define REPORT_KEYS (KBD2_SIZE - 2)
+# define REPORT_BITS (KBD2_SIZE - 1)
+
+#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE)
+# include "protocol/lufa/descriptor.h"
+# define REPORT_SIZE NKRO_EPSIZE
+# define REPORT_KEYS (NKRO_EPSIZE - 2)
+# define REPORT_BITS (NKRO_EPSIZE - 1)
+
#else
+# define REPORT_SIZE 8
# define REPORT_KEYS 6
#endif
@@ -88,11 +94,27 @@ along with this program. If not, see .
extern "C" {
#endif
+typedef union {
+ uint8_t raw[REPORT_SIZE];
+ struct {
+ uint8_t mods;
+ uint8_t reserved;
+ uint8_t keys[REPORT_KEYS];
+ };
+#ifdef NKRO_ENABLE
+ struct {
+ uint8_t mods;
+ uint8_t bits[REPORT_BITS];
+ } nkro;
+#endif
+} __attribute__ ((packed)) report_keyboard_t;
+/*
typedef struct {
uint8_t mods;
- uint8_t rserved;
+ uint8_t reserved;
uint8_t keys[REPORT_KEYS];
} __attribute__ ((packed)) report_keyboard_t;
+*/
typedef struct {
uint8_t buttons;
diff --git a/protocol/lufa/descriptor.c b/protocol/lufa/descriptor.c
index d34ab1c5..a46ba3ec 100644
--- a/protocol/lufa/descriptor.c
+++ b/protocol/lufa/descriptor.c
@@ -57,9 +57,11 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
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_REPORT_COUNT(8, 0x01),
HID_RI_REPORT_SIZE(8, 0x08),
- HID_RI_INPUT(8, HID_IOF_CONSTANT),
+ HID_RI_INPUT(8, HID_IOF_CONSTANT), /* reserved */
+
HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
@@ -69,6 +71,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
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), /* Keyboard */
HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
HID_RI_USAGE_MAXIMUM(8, 0xFF), /* Keyboard Application */
@@ -210,11 +213,13 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
- HID_RI_USAGE_MAXIMUM(8, NKRO_SIZE*8-1), /* Keyboard Right GUI */
+ 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_SIZE*8),
+ 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
@@ -439,6 +444,48 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
.PollingIntervalMS = 0x01
},
#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(01.11),
+ .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
};
@@ -535,6 +582,12 @@ uint16_t CALLBACK_USB_GetDescriptor(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;
@@ -561,6 +614,12 @@ uint16_t CALLBACK_USB_GetDescriptor(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;
diff --git a/protocol/lufa/descriptor.h b/protocol/lufa/descriptor.h
index 44f20d5a..9ee1c04d 100644
--- a/protocol/lufa/descriptor.h
+++ b/protocol/lufa/descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Jun Wako
+ * Copyright 2012,2013 Jun Wako
* This file is based on:
* LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
* LUFA-120219/Demos/Device/Lowlevel/GenericHID
@@ -78,6 +78,13 @@ typedef struct
USB_Descriptor_Endpoint_t Console_INEndpoint;
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
} USB_Descriptor_Configuration_t;
@@ -102,9 +109,15 @@ typedef struct
# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
#endif
+#ifdef NKRO_ENABLE
+# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
+#else
+# define NKRO_INTERFACE CONSOLE_INTERFACE
+#endif
+
/* nubmer of interfaces */
-#define TOTAL_INTERFACES (CONSOLE_INTERFACE + 1)
+#define TOTAL_INTERFACES (NKRO_INTERFACE + 1)
// Endopoint number and size
@@ -125,6 +138,12 @@ typedef struct
#ifdef CONSOLE_ENABLE
# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
+#else
+# define CONSOLE_OUT_EPNUM EXTRAKEY_IN_EPNUM
+#endif
+
+#ifdef NKRO_ENABLE
+# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
#endif
@@ -132,6 +151,7 @@ typedef struct
#define MOUSE_EPSIZE 8
#define EXTRAKEY_EPSIZE 8
#define CONSOLE_EPSIZE 32
+#define NKRO_EPSIZE 16
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c
index a863b8d2..c1617cd0 100644
--- a/protocol/lufa/lufa.c
+++ b/protocol/lufa/lufa.c
@@ -220,6 +220,12 @@ void EVENT_USB_Device_ConfigurationChanged(void)
ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
#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
}
/*
@@ -350,15 +356,31 @@ static void send_keyboard(report_keyboard_t *report)
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
- // TODO: handle NKRO report
/* Select the Keyboard Report Endpoint */
- Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro) {
+ Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
+ }
+ else
+#endif
+ {
+ Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
+ }
/* Check if Keyboard Endpoint Ready for Read/Write */
while (--timeout && !Endpoint_IsReadWriteAllowed()) ;
/* Write Keyboard Report Data */
- Endpoint_Write_Stream_LE(report, sizeof(report_keyboard_t), NULL);
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro) {
+ Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
+ }
+ else
+#endif
+ {
+ /* boot mode */
+ Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
+ }
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
diff --git a/protocol/pjrc/usb_keyboard.c b/protocol/pjrc/usb_keyboard.c
index 49b85c17..de798fcc 100644
--- a/protocol/pjrc/usb_keyboard.c
+++ b/protocol/pjrc/usb_keyboard.c
@@ -57,12 +57,12 @@ int8_t usb_keyboard_send_report(report_keyboard_t *report)
#ifdef NKRO_ENABLE
if (keyboard_nkro)
- result = send_report(report, KBD2_ENDPOINT, 0, KBD2_REPORT_KEYS);
+ result = send_report(report, KBD2_ENDPOINT, 0, KBD2_SIZE);
else
#endif
{
if (usb_keyboard_protocol)
- result = send_report(report, KBD_ENDPOINT, 0, KBD_REPORT_KEYS);
+ result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE);
else
result = send_report(report, KBD_ENDPOINT, 0, 6);
}
@@ -104,15 +104,8 @@ static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, ui
cli();
UENUM = endpoint;
}
- UEDATX = report->mods;
-#ifdef NKRO_ENABLE
- if (!keyboard_nkro)
- UEDATX = 0;
-#else
- UEDATX = 0;
-#endif
for (uint8_t i = keys_start; i < keys_end; i++) {
- UEDATX = report->keys[i];
+ UEDATX = report->raw[i];
}
UEINTX = 0x3A;
SREG = intr_state;