static int mouse_repeat = 0; | static int mouse_repeat = 0; | ||||
bool modified = false; | bool modified = false; | ||||
int key_index = 0; | |||||
uint8_t mouse_btn = 0; | uint8_t mouse_btn = 0; | ||||
int8_t mouse_x = 0; | int8_t mouse_x = 0; | ||||
int8_t mouse_y = 0; | int8_t mouse_y = 0; | ||||
return; | return; | ||||
} | } | ||||
usb_keyboard_swap_report(); | |||||
usb_keyboard_clear_report(); | usb_keyboard_clear_report(); | ||||
for (int row = 0; row < matrix_rows(); row++) { | for (int row = 0; row < matrix_rows(); row++) { | ||||
for (int col = 0; col < matrix_cols(); col++) { | for (int col = 0; col < matrix_cols(); col++) { | ||||
// normal keys | // normal keys | ||||
else { | else { | ||||
if (key_index < 6) | |||||
usb_keyboard_keys[key_index] = code; | |||||
key_index++; | |||||
// TODO: fix ugly code | |||||
int8_t i = 0; | |||||
int8_t empty = -1; | |||||
for (; i < KEYBOARD_REPORT_MAX; i++) { | |||||
if (usb_keyboard_keys_prev[i] == code) { | |||||
usb_keyboard_keys[i] = code; | |||||
break; | |||||
} else if (empty == -1 && usb_keyboard_keys_prev[i] == 0 && usb_keyboard_keys[i] == 0) { | |||||
empty = i; | |||||
} | |||||
} | |||||
if (i == KEYBOARD_REPORT_MAX) { | |||||
if (empty != -1) { | |||||
usb_keyboard_keys[empty] = code; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// send key packet to host | // send key packet to host | ||||
if (modified) { | if (modified) { | ||||
if (key_index > 6) { | |||||
//Rollover | |||||
} | |||||
usb_keyboard_send(); | usb_keyboard_send(); | ||||
} | } | ||||
} | } |
# define STR_PRODUCT LSTR(PRODUCT) | # define STR_PRODUCT LSTR(PRODUCT) | ||||
#endif | #endif | ||||
#define STR_KEYBOARD_INTERFACE L"t.m.k. keyboard I/F" | |||||
#define STR_MOUSE_INTERFACE L"t.m.k. mouse I/F" | |||||
#define STR_DEBUG_INTERFACE L"t.m.k. debug I/F" | |||||
#define STR_EXTRA_INTERFACE L"t.m.k. extrakey I/F" | |||||
#define STR_KEYBOARD2_INTERFACE L"t.m.k. keyboard2 I/F" | |||||
// Mac OS-X and Linux automatically load the correct drivers. On | // Mac OS-X and Linux automatically load the correct drivers. On | ||||
// Windows, even though the driver is supplied by Microsoft, an | // Windows, even though the driver is supplied by Microsoft, an | ||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2 | ||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3 | ||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4 | 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4 | ||||
0, // 5 | |||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 5 | |||||
0, // 6 | 0, // 6 | ||||
}; | }; | ||||
0xc0 // END_COLLECTION | 0xc0 // END_COLLECTION | ||||
}; | }; | ||||
#define CONFIG1_DESC_SIZE (9+(9+9+7)*4) | |||||
#define KEYBOARD_HID_DESC_OFFSET (9+(9+9+7)*0+9) | |||||
#define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*1+9) | |||||
#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*2+9) | |||||
#define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*3+9) | |||||
#define NUM_INTERFACES 5 | |||||
#define KEYBOARD_HID_DESC_OFFSET (9+9) | |||||
#define MOUSE_HID_DESC_OFFSET (9+(9+9+7)+9) | |||||
#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)+(9+9+7)+9) | |||||
#define EXTRA_HID_DESC_OFFSET (9+(9+9+7)+(9+9+7)+(9+9+7)+9) | |||||
#define KEYBOARD2_HID_DESC_OFFSET (9+(9+9+7)+(9+9+7)+(9+9+7)+(9+9+7)+9) | |||||
#define CONFIG1_DESC_SIZE (9+(9+9+7)+(9+9+7)+(9+9+7)+(9+9+7)+(9+9+7)) | |||||
static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | ||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | ||||
9, // bLength; | 9, // bLength; | ||||
2, // bDescriptorType; | 2, // bDescriptorType; | ||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength | LSB(CONFIG1_DESC_SIZE), // wTotalLength | ||||
MSB(CONFIG1_DESC_SIZE), | MSB(CONFIG1_DESC_SIZE), | ||||
4, // bNumInterfaces | |||||
NUM_INTERFACES, // bNumInterfaces | |||||
1, // bConfigurationValue | 1, // bConfigurationValue | ||||
0, // iConfiguration | 0, // iConfiguration | ||||
0xA0, // bmAttributes | 0xA0, // bmAttributes | ||||
0x03, // bInterfaceClass (0x03 = HID) | 0x03, // bInterfaceClass (0x03 = HID) | ||||
0x01, // bInterfaceSubClass (0x01 = Boot) | 0x01, // bInterfaceSubClass (0x01 = Boot) | ||||
0x01, // bInterfaceProtocol (0x01 = Keyboard) | 0x01, // bInterfaceProtocol (0x01 = Keyboard) | ||||
0, // iInterface | |||||
3, // iInterface | |||||
// HID descriptor, HID 1.11 spec, section 6.2.1 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | 9, // bLength | ||||
0x21, // bDescriptorType | 0x21, // bDescriptorType | ||||
0x03, // bInterfaceClass (0x03 = HID) | 0x03, // bInterfaceClass (0x03 = HID) | ||||
0x01, // bInterfaceSubClass (0x01 = Boot) | 0x01, // bInterfaceSubClass (0x01 = Boot) | ||||
0x02, // bInterfaceProtocol (0x02 = Mouse) | 0x02, // bInterfaceProtocol (0x02 = Mouse) | ||||
0, // iInterface | |||||
4, // iInterface | |||||
// HID descriptor, HID 1.11 spec, section 6.2.1 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | 9, // bLength | ||||
0x21, // bDescriptorType | 0x21, // bDescriptorType | ||||
0x03, // bInterfaceClass (0x03 = HID) | 0x03, // bInterfaceClass (0x03 = HID) | ||||
0x00, // bInterfaceSubClass | 0x00, // bInterfaceSubClass | ||||
0x00, // bInterfaceProtocol | 0x00, // bInterfaceProtocol | ||||
0, // iInterface | |||||
5, // iInterface | |||||
// HID descriptor, HID 1.11 spec, section 6.2.1 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | 9, // bLength | ||||
0x21, // bDescriptorType | 0x21, // bDescriptorType | ||||
0x03, // bInterfaceClass (0x03 = HID) | 0x03, // bInterfaceClass (0x03 = HID) | ||||
0x00, // bInterfaceSubClass | 0x00, // bInterfaceSubClass | ||||
0x00, // bInterfaceProtocol | 0x00, // bInterfaceProtocol | ||||
0, // iInterface | |||||
6, // iInterface | |||||
// HID descriptor, HID 1.11 spec, section 6.2.1 | // HID descriptor, HID 1.11 spec, section 6.2.1 | ||||
9, // bLength | 9, // bLength | ||||
0x21, // bDescriptorType | 0x21, // bDescriptorType | ||||
0x03, // bmAttributes (0x03=intr) | 0x03, // bmAttributes (0x03=intr) | ||||
EXTRA_SIZE, 0, // wMaxPacketSize | EXTRA_SIZE, 0, // wMaxPacketSize | ||||
10, // bInterval | 10, // bInterval | ||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||||
9, // bLength | |||||
4, // bDescriptorType | |||||
KEYBOARD_INTERFACE2, // bInterfaceNumber | |||||
0, // bAlternateSetting | |||||
1, // bNumEndpoints | |||||
0x03, // bInterfaceClass (0x03 = HID) | |||||
0x00, // bInterfaceSubClass (0x01 = Boot) | |||||
0x00, // bInterfaceProtocol (0x01 = Keyboard) | |||||
7, // iInterface | |||||
// HID descriptor, HID 1.11 spec, section 6.2.1 | |||||
9, // bLength | |||||
0x21, // bDescriptorType | |||||
0x11, 0x01, // bcdHID | |||||
0, // bCountryCode | |||||
1, // bNumDescriptors | |||||
0x22, // bDescriptorType | |||||
sizeof(keyboard_hid_report_desc), // wDescriptorLength | |||||
0, | |||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||||
7, // bLength | |||||
5, // bDescriptorType | |||||
KEYBOARD_ENDPOINT2 | 0x80, // bEndpointAddress | |||||
0x03, // bmAttributes (0x03=intr) | |||||
KEYBOARD_SIZE, 0, // wMaxPacketSize | |||||
1, // bInterval | |||||
}; | }; | ||||
// If you're desperate for a little extra code memory, these strings | // If you're desperate for a little extra code memory, these strings | ||||
3, | 3, | ||||
STR_PRODUCT | STR_PRODUCT | ||||
}; | }; | ||||
static struct usb_string_descriptor_struct PROGMEM string3 = { | |||||
sizeof(STR_KEYBOARD_INTERFACE), | |||||
3, | |||||
STR_KEYBOARD_INTERFACE | |||||
}; | |||||
static struct usb_string_descriptor_struct PROGMEM string4 = { | |||||
sizeof(STR_MOUSE_INTERFACE), | |||||
3, | |||||
STR_MOUSE_INTERFACE | |||||
}; | |||||
static struct usb_string_descriptor_struct PROGMEM string5 = { | |||||
sizeof(STR_DEBUG_INTERFACE), | |||||
3, | |||||
STR_DEBUG_INTERFACE | |||||
}; | |||||
static struct usb_string_descriptor_struct PROGMEM string6 = { | |||||
sizeof(STR_EXTRA_INTERFACE), | |||||
3, | |||||
STR_EXTRA_INTERFACE | |||||
}; | |||||
static struct usb_string_descriptor_struct PROGMEM string7 = { | |||||
sizeof(STR_KEYBOARD2_INTERFACE), | |||||
3, | |||||
STR_KEYBOARD2_INTERFACE | |||||
}; | |||||
// This table defines which descriptor data is sent for each specific | // This table defines which descriptor data is sent for each specific | ||||
// request from the host (in wValue and wIndex). | // request from the host (in wValue and wIndex). | ||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, | ||||
// CONFIGURATION descriptor | // CONFIGURATION descriptor | ||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, | {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, | ||||
// HID REPORT | |||||
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, | |||||
// HID/REPORT descriptors | |||||
{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, | {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, | ||||
// HID REPORT | |||||
{0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, | |||||
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, | |||||
{0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, | {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, | ||||
// HID REPORT | |||||
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, | |||||
{0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, | |||||
{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, | {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, | ||||
// HID REPORT | |||||
{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)}, | |||||
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, | |||||
{0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9}, | {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9}, | ||||
// STRING descriptor | |||||
{0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)}, | |||||
{0x2100, KEYBOARD_INTERFACE2, config1_descriptor+KEYBOARD2_HID_DESC_OFFSET, 9}, | |||||
{0x2200, KEYBOARD_INTERFACE2, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, | |||||
// STRING descriptors | |||||
{0x0300, 0x0000, (const uint8_t *)&string0, 4}, | {0x0300, 0x0000, (const uint8_t *)&string0, 4}, | ||||
{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, | {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, | ||||
{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)} | |||||
{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}, | |||||
{0x0303, 0x0409, (const uint8_t *)&string3, sizeof(STR_KEYBOARD_INTERFACE)}, | |||||
{0x0304, 0x0409, (const uint8_t *)&string4, sizeof(STR_MOUSE_INTERFACE)}, | |||||
{0x0305, 0x0409, (const uint8_t *)&string5, sizeof(STR_DEBUG_INTERFACE)}, | |||||
{0x0306, 0x0409, (const uint8_t *)&string6, sizeof(STR_EXTRA_INTERFACE)}, | |||||
{0x0307, 0x0409, (const uint8_t *)&string7, sizeof(STR_KEYBOARD2_INTERFACE)}, | |||||
}; | }; | ||||
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) | #define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) | ||||
// keyboard report. | // keyboard report. | ||||
static usb_keyboard_report_t _report0 = { {0,0,0,0,0,0}, 0 }; | |||||
static usb_keyboard_report_t _report1 = { {0,0,0,0,0,0}, 0 }; | |||||
static usb_keyboard_report_t _report0 = { {0}, 0 }; | |||||
static usb_keyboard_report_t _report1 = { {0}, 0 }; | |||||
usb_keyboard_report_t *usb_keyboard_report = &_report0; | usb_keyboard_report_t *usb_keyboard_report = &_report0; | ||||
usb_keyboard_report_t *usb_keyboard_report_back = &_report1; | |||||
usb_keyboard_report_t *usb_keyboard_report_prev = &_report1; | |||||
// 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 | ||||
} | } | ||||
UEDATX = report->mods; | UEDATX = report->mods; | ||||
UEDATX = 0; | UEDATX = 0; | ||||
for (i=0; i<6; i++) { | |||||
for (i = 0; i < 6; i++) { | |||||
UEDATX = report->keys[i]; | UEDATX = report->keys[i]; | ||||
} | } | ||||
UEINTX = 0x3A; | UEINTX = 0x3A; | ||||
usb_keyboard_idle_count = 0; | |||||
SREG = intr_state; | SREG = intr_state; | ||||
report->is_sent =true; | |||||
if (!usb_configured()) return -1; | |||||
intr_state = SREG; | |||||
cli(); | |||||
UENUM = KEYBOARD_ENDPOINT2; | |||||
timeout = UDFNUML + 50; | |||||
while (1) { | |||||
// are we ready to transmit? | |||||
if (UEINTX & (1<<RWAL)) break; | |||||
SREG = intr_state; | |||||
// has the USB gone offline? | |||||
if (!usb_configured()) return -1; | |||||
// have we waited too long? | |||||
if (UDFNUML == timeout) return -1; | |||||
// get ready to try checking again | |||||
intr_state = SREG; | |||||
cli(); | |||||
UENUM = KEYBOARD_ENDPOINT2; | |||||
} | |||||
UEDATX = 0; | |||||
UEDATX = 0; | |||||
for (i = 6; i < 12; i++) { | |||||
UEDATX = report->keys[i]; | |||||
} | |||||
UEINTX = 0x3A; | |||||
SREG = intr_state; | |||||
usb_keyboard_idle_count = 0; | |||||
report->is_sent =true; | |||||
usb_keyboard_print_report(report); | usb_keyboard_print_report(report); | ||||
return 0; | return 0; | ||||
} | } | ||||
void usb_keyboard_swap_report(void) { | void usb_keyboard_swap_report(void) { | ||||
usb_keyboard_report_t *tmp = usb_keyboard_report_back; | |||||
usb_keyboard_report_back = usb_keyboard_report; | |||||
usb_keyboard_report_t *tmp = usb_keyboard_report_prev; | |||||
usb_keyboard_report_prev = usb_keyboard_report; | |||||
usb_keyboard_report = tmp; | usb_keyboard_report = tmp; | ||||
} | } | ||||
} | } | ||||
void usb_keyboard_clear_keys(void) { | void usb_keyboard_clear_keys(void) { | ||||
for (int i = 0; i < 6; i++) usb_keyboard_report->keys[i] = 0; | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) usb_keyboard_report->keys[i] = 0; | |||||
} | } | ||||
void usb_keyboard_clear_mods(void) | void usb_keyboard_clear_mods(void) | ||||
void usb_keyboard_add_key(uint8_t code) | void usb_keyboard_add_key(uint8_t code) | ||||
{ | { | ||||
for (int i = 0; i < 6; i++) { | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { | |||||
if (!usb_keyboard_report->keys[i]) { | if (!usb_keyboard_report->keys[i]) { | ||||
usb_keyboard_report->keys[i] = code; | usb_keyboard_report->keys[i] = code; | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
void usb_keyboard_set_keys(uint8_t keys[6]) | |||||
void usb_keyboard_set_keys(uint8_t *keys) | |||||
{ | { | ||||
for (int i = 0; i < 6; i++) | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) | |||||
usb_keyboard_report->keys[i] = keys[i]; | usb_keyboard_report->keys[i] = keys[i]; | ||||
} | } | ||||
void usb_keyboard_del_key(uint8_t code) | void usb_keyboard_del_key(uint8_t code) | ||||
{ | { | ||||
for (int i = 0; i < 6; i++) { | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { | |||||
if (usb_keyboard_report->keys[i] == code) { | if (usb_keyboard_report->keys[i] == code) { | ||||
usb_keyboard_report->keys[i] = KB_NO; | usb_keyboard_report->keys[i] = KB_NO; | ||||
return; | return; | ||||
bool usb_keyboard_has_key(void) | bool usb_keyboard_has_key(void) | ||||
{ | { | ||||
uint8_t keys = 0; | uint8_t keys = 0; | ||||
for (int i = 0; i < 6; i++) keys |= usb_keyboard_report->keys[i]; | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) keys |= usb_keyboard_report->keys[i]; | |||||
return keys ? true : false; | return keys ? true : false; | ||||
} | } | ||||
{ | { | ||||
if (!debug_keyboard) return; | if (!debug_keyboard) return; | ||||
print("keys: "); | print("keys: "); | ||||
for (int i = 0; i < 6; i++) { phex(report->keys[i]); print(" "); } | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { phex(report->keys[i]); print(" "); } | |||||
print(" mods: "); phex(report->mods); print("\n"); | print(" mods: "); phex(report->mods); print("\n"); | ||||
} | } |
#include <avr/interrupt.h> | |||||
#include <avr/pgmspace.h> | |||||
#include "usb_keycodes.h" | |||||
#include "usb_keyboard.h" | |||||
#include "print.h" | |||||
#include "debug.h" | |||||
// keyboard report. | |||||
static usb_keyboard_report_t _report0 = { {0}, 0 }; | |||||
static usb_keyboard_report_t _report1 = { {0}, 0 }; | |||||
usb_keyboard_report_t *usb_keyboard_report = &_report0; | |||||
usb_keyboard_report_t *usb_keyboard_report_back = &_report1; | |||||
// protocol setting from the host. We use exactly the same report | |||||
// either way, so this variable only stores the setting since we | |||||
// are required to be able to report which setting is in use. | |||||
uint8_t usb_keyboard_protocol=1; | |||||
// the idle configuration, how often we send the report to the | |||||
// host (ms * 4) even when it hasn't changed | |||||
uint8_t usb_keyboard_idle_config=125; | |||||
// count until idle timeout | |||||
uint8_t usb_keyboard_idle_count=0; | |||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana | |||||
volatile uint8_t usb_keyboard_leds=0; | |||||
int8_t usb_keyboard_send(void) | |||||
{ | |||||
return usb_keyboard_send_report(usb_keyboard_report); | |||||
} | |||||
int8_t usb_keyboard_send_report(usb_keyboard_report_t *report) | |||||
{ | |||||
uint8_t i, intr_state, timeout; | |||||
if (!usb_configured()) return -1; | |||||
timeout = UDFNUML + 50; | |||||
do { | |||||
intr_state = SREG; | |||||
cli(); | |||||
UENUM = KEYBOARD_ENDPOINT; | |||||
// are we ready to transmit? | |||||
if (UEINTX & (1<<RWAL)) break; | |||||
SREG = intr_state; | |||||
// has the USB gone offline? | |||||
if (!usb_configured()) return -1; | |||||
// have we waited too long? | |||||
if (UDFNUML == timeout) return -1; | |||||
} while (1); | |||||
UEDATX = report->mods; | |||||
UEDATX = 0; | |||||
for (i = 0; i < 6; i++) { | |||||
UEDATX = report->keys[i]; | |||||
} | |||||
UEINTX = 0x3A; | |||||
/* | |||||
timeout = UDFNUML + 50; | |||||
do { | |||||
intr_state = SREG; | |||||
cli(); | |||||
UENUM = KEYBOARD_ENDPOINT2; | |||||
// are we ready to transmit? | |||||
if (UEINTX & (1<<RWAL)) break; | |||||
SREG = intr_state; | |||||
// has the USB gone offline? | |||||
if (!usb_configured()) return -1; | |||||
// have we waited too long? | |||||
if (UDFNUML == timeout) return -1; | |||||
} while (1); | |||||
UEDATX = 0; | |||||
UEDATX = 0; | |||||
for (i = 6; i < 12; i++) { | |||||
UEDATX = report->keys[i]; | |||||
} | |||||
UEINTX = 0x3A; | |||||
*/ | |||||
usb_keyboard_idle_count = 0; | |||||
report->is_sent =true; | |||||
usb_keyboard_print_report(report); | |||||
return 0; | |||||
} | |||||
void usb_keyboard_swap_report(void) { | |||||
usb_keyboard_report_t *tmp = usb_keyboard_report_back; | |||||
usb_keyboard_report_back = usb_keyboard_report; | |||||
usb_keyboard_report = tmp; | |||||
} | |||||
void usb_keyboard_clear_report(void) { | |||||
usb_keyboard_clear_keys(); | |||||
usb_keyboard_clear_mods(); | |||||
usb_keyboard_report->is_sent = false; | |||||
} | |||||
void usb_keyboard_clear_keys(void) { | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) usb_keyboard_report->keys[i] = 0; | |||||
} | |||||
void usb_keyboard_clear_mods(void) | |||||
{ | |||||
usb_keyboard_report->mods = 0; | |||||
} | |||||
void usb_keyboard_add_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
usb_keyboard_add_mod(code); | |||||
} else { | |||||
usb_keyboard_add_key(code); | |||||
} | |||||
} | |||||
void usb_keyboard_add_key(uint8_t code) | |||||
{ | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { | |||||
if (!usb_keyboard_report->keys[i]) { | |||||
usb_keyboard_report->keys[i] = code; | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
void usb_keyboard_set_keys(uint8_t *keys) | |||||
{ | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) | |||||
usb_keyboard_report->keys[i] = keys[i]; | |||||
} | |||||
void usb_keyboard_set_mods(uint8_t mods) | |||||
{ | |||||
usb_keyboard_report->mods = mods; | |||||
} | |||||
void usb_keyboard_add_mod(uint8_t code) | |||||
{ | |||||
usb_keyboard_report->mods |= MOD_BIT(code); | |||||
} | |||||
void usb_keyboard_del_code(uint8_t code) | |||||
{ | |||||
if (IS_MOD(code)) { | |||||
usb_keyboard_del_mod(code); | |||||
} else { | |||||
usb_keyboard_del_key(code); | |||||
} | |||||
} | |||||
void usb_keyboard_del_key(uint8_t code) | |||||
{ | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { | |||||
if (usb_keyboard_report->keys[i] == code) { | |||||
usb_keyboard_report->keys[i] = KB_NO; | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
void usb_keyboard_del_mod(uint8_t code) | |||||
{ | |||||
usb_keyboard_report->mods &= ~MOD_BIT(code); | |||||
} | |||||
bool usb_keyboard_is_sent(void) | |||||
{ | |||||
return usb_keyboard_report->is_sent; | |||||
} | |||||
bool usb_keyboard_has_key(void) | |||||
{ | |||||
uint8_t keys = 0; | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) keys |= usb_keyboard_report->keys[i]; | |||||
return keys ? true : false; | |||||
} | |||||
bool usb_keyboard_has_mod(void) | |||||
{ | |||||
return usb_keyboard_report->mods ? true : false; | |||||
} | |||||
void usb_keyboard_print_report(usb_keyboard_report_t *report) | |||||
{ | |||||
if (!debug_keyboard) return; | |||||
print("keys: "); | |||||
for (int i = 0; i < KEYBOARD_REPORT_MAX; i++) { phex(report->keys[i]); print(" "); } | |||||
print(" mods: "); phex(report->mods); print("\n"); | |||||
} |
#define KEYBOARD_INTERFACE 0 | #define KEYBOARD_INTERFACE 0 | ||||
#define KEYBOARD_ENDPOINT 1 | #define KEYBOARD_ENDPOINT 1 | ||||
#define KEYBOARD_INTERFACE2 4 | |||||
#define KEYBOARD_ENDPOINT2 5 | |||||
#define KEYBOARD_SIZE 8 | #define KEYBOARD_SIZE 8 | ||||
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER | #define KEYBOARD_BUFFER EP_DOUBLE_BUFFER | ||||
#define BIT_LSFT BIT_LSHIFT | #define BIT_LSFT BIT_LSHIFT | ||||
#define BIT_RSFT BIT_RSHIFT | #define BIT_RSFT BIT_RSHIFT | ||||
#define KEYBOARD_REPORT_MAX 12 | |||||
typedef struct report { | typedef struct report { | ||||
uint8_t keys[6]; | |||||
uint8_t keys[KEYBOARD_REPORT_MAX]; | |||||
uint8_t mods; | uint8_t mods; | ||||
bool is_sent; | bool is_sent; | ||||
} usb_keyboard_report_t; | } usb_keyboard_report_t; | ||||
#define usb_keyboard_keys usb_keyboard_report->keys | #define usb_keyboard_keys usb_keyboard_report->keys | ||||
#define usb_keyboard_mods usb_keyboard_report->mods | #define usb_keyboard_mods usb_keyboard_report->mods | ||||
#define usb_keyboard_keys_prev usb_keyboard_report_prev->keys | |||||
#define usb_keyboard_mods_prev usb_keyboard_report_prev->mods | |||||
extern usb_keyboard_report_t *usb_keyboard_report; | extern usb_keyboard_report_t *usb_keyboard_report; |