@@ -6,7 +6,7 @@ | |||
#ifdef M | |||
#undef M | |||
#endif | |||
#define M(n) ((n) & 0x3FFF) | |||
#define M(n) ((n) & KEYCODE_MASK) | |||
const KEYCODE_TYPE PROGMEM keycodes_ascii[] = { | |||
M(ASCII_20), M(ASCII_21), M(ASCII_22), M(ASCII_23), |
@@ -35,14 +35,12 @@ | |||
static const uint8_t PROGMEM endpoint_config_table[] = { | |||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, | |||
1, EP_TYPE_INTERRUPT_OUT, EP_SIZE(DEBUG_RX_SIZE) | DEBUG_RX_BUFFER, | |||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, | |||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, | |||
#ifdef JOYSTICK_INTERFACE | |||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(JOYSTICK_SIZE) | JOYSTICK_BUFFER, | |||
0 | |||
#endif | |||
EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, | |||
EP_TYPE_INTERRUPT_OUT, EP_SIZE(DEBUG_RX_SIZE) | DEBUG_RX_BUFFER, | |||
EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, | |||
EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, | |||
EP_TYPE_INTERRUPT_IN, EP_SIZE(JOYSTICK_SIZE) | JOYSTICK_BUFFER, | |||
EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYMEDIA_SIZE) | KEYMEDIA_BUFFER, | |||
}; | |||
@@ -88,20 +86,9 @@ static const uint8_t PROGMEM keyboard_hid_report_desc[] = { | |||
0x15, 0x00, // Logical Minimum (0), | |||
0x25, 0x01, // Logical Maximum (1), | |||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte | |||
0x95, 0x08, // Report Count (8), | |||
0x75, 0x01, // Report Size (1), | |||
0x15, 0x00, // Logical Minimum (0), | |||
0x25, 0x01, // Logical Maximum (1), | |||
0x05, 0x0C, // Usage Page (Consumer), | |||
0x09, 0xE9, // Usage (Volume Increment), | |||
0x09, 0xEA, // Usage (Volume Decrement), | |||
0x09, 0xE2, // Usage (Mute), | |||
0x09, 0xCD, // Usage (Play/Pause), | |||
0x09, 0xB5, // Usage (Scan Next Track), | |||
0x09, 0xB6, // Usage (Scan Previous Track), | |||
0x09, 0xB7, // Usage (Stop), | |||
0x09, 0xB8, // Usage (Eject), | |||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Media keys | |||
0x95, 0x01, // Report Count (1), | |||
0x75, 0x08, // Report Size (8), | |||
0x81, 0x03, // Input (Constant), ;Reserved byte | |||
0x95, 0x05, // Report Count (5), | |||
0x75, 0x01, // Report Size (1), | |||
0x05, 0x08, // Usage Page (LEDs), | |||
@@ -122,6 +109,28 @@ static const uint8_t PROGMEM keyboard_hid_report_desc[] = { | |||
0xc0 // End Collection | |||
}; | |||
static const uint8_t PROGMEM keymedia_hid_report_desc[] = { | |||
0x05, 0x0C, // Usage Page (Consumer) | |||
0x09, 0x01, // Usage (Consumer Controls) | |||
0xA1, 0x01, // Collection (Application) | |||
0x75, 0x0A, // Report Size (10) | |||
0x95, 0x04, // Report Count (4) | |||
0x19, 0x00, // Usage Minimum (0) | |||
0x2A, 0x9C, 0x02, // Usage Maximum (0x29C) | |||
0x15, 0x00, // Logical Minimum (0) | |||
0x26, 0x9C, 0x02, // Logical Maximum (0x29C) | |||
0x81, 0x00, // Input (Data, Array) | |||
0x05, 0x01, // Usage Page (Generic Desktop) | |||
0x75, 0x08, // Report Size (8) | |||
0x95, 0x03, // Report Count (3) | |||
0x19, 0x00, // Usage Minimum (0) | |||
0x29, 0xB7, // Usage Maximum (0xB7) | |||
0x15, 0x00, // Logical Minimum (0) | |||
0x26, 0xB7, 0x00, // Logical Maximum (0xB7) | |||
0x81, 0x00, // Input (Data, Array) | |||
0xC0 // End Collection | |||
}; | |||
// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension | |||
static const uint8_t PROGMEM mouse_hid_report_desc[] = { | |||
0x05, 0x01, // Usage Page (Generic Desktop) | |||
@@ -229,12 +238,9 @@ static const uint8_t PROGMEM debug_hid_report_desc[] = { | |||
#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 ) | |||
#ifdef JOYSTICK_INTERFACE | |||
#define JOYSTICK_HID_DESC_OFFSET ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9 ) | |||
#define CONFIG1_DESC_SIZE ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7) | |||
#else | |||
#define CONFIG1_DESC_SIZE ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 ) | |||
#endif | |||
#define KEYMEDIA_HID_DESC_OFFSET ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7 + 9 ) | |||
#define CONFIG1_DESC_SIZE ( 9 + 9+9+7 + 9+9+7 + 9+9+7+7 + 9+9+7 + 9+9+7 ) | |||
static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | |||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 | |||
@@ -336,7 +342,6 @@ static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | |||
DEBUG_RX_SIZE, 0, // wMaxPacketSize | |||
DEBUG_RX_INTERVAL, // bInterval | |||
#ifdef JOYSTICK_INTERFACE | |||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||
9, // bLength | |||
4, // bDescriptorType | |||
@@ -363,7 +368,33 @@ static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { | |||
0x03, // bmAttributes (0x03=intr) | |||
12, 0, // wMaxPacketSize | |||
JOYSTICK_INTERVAL, // bInterval | |||
#endif | |||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 | |||
9, // bLength | |||
4, // bDescriptorType | |||
KEYMEDIA_INTERFACE, // bInterfaceNumber | |||
0, // bAlternateSetting | |||
1, // bNumEndpoints | |||
0x03, // bInterfaceClass (0x03 = HID) | |||
0x00, // bInterfaceSubClass | |||
0x00, // bInterfaceProtocol | |||
0, // iInterface | |||
// HID interface descriptor, HID 1.11 spec, section 6.2.1 | |||
9, // bLength | |||
0x21, // bDescriptorType | |||
0x11, 0x01, // bcdHID | |||
0, // bCountryCode | |||
1, // bNumDescriptors | |||
0x22, // bDescriptorType | |||
LSB(sizeof(keymedia_hid_report_desc)), // wDescriptorLength | |||
MSB(sizeof(keymedia_hid_report_desc)), | |||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 | |||
7, // bLength | |||
5, // bDescriptorType | |||
KEYMEDIA_ENDPOINT | 0x80, // bEndpointAddress | |||
0x03, // bmAttributes (0x03=intr) | |||
KEYMEDIA_SIZE, 0, // wMaxPacketSize | |||
KEYMEDIA_INTERVAL, // bInterval | |||
}; | |||
// If you're desperate for a little extra code memory, these strings | |||
@@ -401,10 +432,10 @@ static const struct descriptor_list_struct { | |||
{0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, | |||
{0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, | |||
{0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, | |||
#ifdef JOYSTICK_INTERFACE | |||
{0x2200, JOYSTICK_INTERFACE, joystick_hid_report_desc, sizeof(joystick_hid_report_desc)}, | |||
{0x2100, JOYSTICK_INTERFACE, config1_descriptor+JOYSTICK_HID_DESC_OFFSET, 9}, | |||
#endif | |||
{0x2200, KEYMEDIA_INTERFACE, keymedia_hid_report_desc, sizeof(keymedia_hid_report_desc)}, | |||
{0x2100, KEYMEDIA_INTERFACE, config1_descriptor+KEYMEDIA_HID_DESC_OFFSET, 9}, | |||
{0x0300, 0x0000, (const uint8_t *)&string0, 4}, | |||
{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_PRODUCT)}, | |||
}; | |||
@@ -456,9 +487,13 @@ uint8_t mouse_buttons USBSTATE; | |||
static uint8_t mouse_protocol USBSTATE; | |||
// joystick data | |||
#ifdef JOYSTICK_INTERFACE | |||
uint8_t joystick_report_data[12] USBSTATE; | |||
#endif | |||
// keyboard media keys data | |||
uint8_t keymedia_report_data[8] USBSTATE; | |||
uint16_t keymedia_consumer_keys[4] USBSTATE; | |||
uint8_t keymedia_system_keys[3] USBSTATE; | |||
/************************************************************************** | |||
@@ -499,7 +534,6 @@ void usb_init(void) | |||
keyboard_leds = 0; | |||
mouse_buttons = 0; | |||
mouse_protocol = 1; | |||
#ifdef JOYSTICK_INTERFACE | |||
joystick_report_data[0] = 0; | |||
joystick_report_data[1] = 0; | |||
joystick_report_data[2] = 0; | |||
@@ -512,7 +546,21 @@ void usb_init(void) | |||
joystick_report_data[9] = 0x08; | |||
joystick_report_data[10] = 0x20; | |||
joystick_report_data[11] = 0x80; | |||
#endif | |||
keymedia_report_data[0] = 0; | |||
keymedia_report_data[1] = 0; | |||
keymedia_report_data[2] = 0; | |||
keymedia_report_data[3] = 0; | |||
keymedia_report_data[4] = 0; | |||
keymedia_report_data[5] = 0; | |||
keymedia_report_data[6] = 0; | |||
keymedia_report_data[7] = 0; | |||
keymedia_consumer_keys[0] = 0; | |||
keymedia_consumer_keys[1] = 0; | |||
keymedia_consumer_keys[2] = 0; | |||
keymedia_consumer_keys[3] = 0; | |||
keymedia_system_keys[0] = 0; | |||
keymedia_system_keys[1] = 0; | |||
keymedia_system_keys[2] = 0; | |||
UDINT = 0; | |||
UDIEN = (1<<EORSTE)|(1<<SOFE); | |||
//sei(); // init() in wiring.c does this | |||
@@ -644,7 +692,7 @@ ISR(USB_COM_vect) | |||
uint8_t intbits; | |||
const uint8_t *list; | |||
const uint8_t *cfg; | |||
uint8_t i, n, len, en; | |||
uint8_t i, n, len; | |||
uint8_t bmRequestType; | |||
uint8_t bRequest; | |||
uint16_t wValue; | |||
@@ -714,14 +762,11 @@ ISR(USB_COM_vect) | |||
debug_flush_timer = 0; | |||
usb_send_in(); | |||
cfg = endpoint_config_table; | |||
for (i=1; i<NUM_ENDPOINTS; i++) { | |||
for (i=1; i<7; i++) { | |||
UENUM = i; | |||
pgm_read_byte_postinc(en, cfg); | |||
UECONX = en; | |||
if (en) { | |||
pgm_read_byte_postinc(UECFG0X, cfg); | |||
pgm_read_byte_postinc(UECFG1X, cfg); | |||
} | |||
UECONX = 1; | |||
pgm_read_byte_postinc(UECFG0X, cfg); | |||
pgm_read_byte_postinc(UECFG1X, cfg); | |||
} | |||
UERST = 0x1E; | |||
UERST = 0; | |||
@@ -835,7 +880,6 @@ ISR(USB_COM_vect) | |||
} | |||
} | |||
} | |||
#ifdef JOYSTICK_INTERFACE | |||
if (wIndex == JOYSTICK_INTERFACE) { | |||
if (bmRequestType == 0xA1) { | |||
if (bRequest == HID_GET_REPORT) { | |||
@@ -848,7 +892,18 @@ ISR(USB_COM_vect) | |||
} | |||
} | |||
} | |||
#endif | |||
if (wIndex == KEYMEDIA_INTERFACE) { | |||
if (bmRequestType == 0xA1) { | |||
if (bRequest == HID_GET_REPORT) { | |||
usb_wait_in_ready(); | |||
for (i=0; i<8; i++) { | |||
UEDATX = keymedia_report_data[i]; | |||
} | |||
usb_send_in(); | |||
return; | |||
} | |||
} | |||
} | |||
if (wIndex == DEBUG_INTERFACE) { | |||
if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) { | |||
len = wLength; |
@@ -33,11 +33,7 @@ | |||
// Step #1, decode UTF8 to Unicode code points | |||
// | |||
#if ARDUINO >= 100 | |||
size_t usb_keyboard_class::write(uint8_t c) | |||
#else | |||
void usb_keyboard_class::write(uint8_t c) | |||
#endif | |||
{ | |||
if (c < 0x80) { | |||
// single byte encoded, 0x00 to 0x7F | |||
@@ -67,9 +63,7 @@ void usb_keyboard_class::write(uint8_t c) | |||
// or illegal, 0xF5 to 0xFF | |||
utf8_state = 255; | |||
} | |||
#if ARDUINO >= 100 | |||
return 1; | |||
#endif | |||
} | |||
@@ -80,7 +74,8 @@ KEYCODE_TYPE usb_keyboard_class::unicode_to_keycode(uint16_t cpoint) | |||
// Unicode code points beyond U+FFFF are not supported | |||
// technically this input should probably be called UCS-2 | |||
if (cpoint < 32) { | |||
if (cpoint == 10) return KEY_ENTER & 0x3FFF; | |||
if (cpoint == 10) return KEY_ENTER & KEYCODE_MASK; | |||
if (cpoint == 11) return KEY_TAB & KEYCODE_MASK; | |||
return 0; | |||
} | |||
if (cpoint < 128) { | |||
@@ -253,10 +248,6 @@ void usb_keyboard_class::set_key6(uint8_t c) | |||
{ | |||
keyboard_report_data[7] = c; | |||
} | |||
void usb_keyboard_class::set_media(uint8_t c) | |||
{ | |||
keyboard_report_data[1] = c; | |||
} | |||
void usb_keyboard_class::send_now(void) | |||
@@ -300,20 +291,28 @@ void usb_keyboard_class::press(uint16_t n) | |||
uint8_t key, mod, msb, modrestore=0; | |||
msb = n >> 8; | |||
if (msb >= 0xC2 && msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else | |||
if (msb == 0x80) { | |||
presskey(0, n); | |||
return; | |||
} else | |||
if (msb == 0x40) { | |||
presskey(n, 0); | |||
return; | |||
if (msb >= 0xC2) { | |||
if (msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else if (msb == 0xF0) { | |||
presskey(n, 0); | |||
return; | |||
} else if (msb == 0xE0) { | |||
presskey(0, n); | |||
return; | |||
} else if (msb == 0xE2) { | |||
press_system_key(n); | |||
return; | |||
} else if (msb >= 0xE4 && msb <= 0xE7) { | |||
press_consumer_key(n & 0x3FF); | |||
return; | |||
} else { | |||
return; | |||
} | |||
} | |||
KEYCODE_TYPE keycode = unicode_to_keycode(n); | |||
if (!keycode) return; | |||
#ifdef DEADKEYS_MASK | |||
#ifdef DEADKEYS_MASK | |||
KEYCODE_TYPE deadkeycode = deadkey_to_keycode(keycode); | |||
if (deadkeycode) { | |||
modrestore = keyboard_report_data[0]; | |||
@@ -328,7 +327,7 @@ void usb_keyboard_class::press(uint16_t n) | |||
presskey(key, mod); | |||
releasekey(key, mod); | |||
} | |||
#endif | |||
#endif | |||
mod = keycode_to_modifier(keycode); | |||
key = keycode_to_key(keycode); | |||
presskey(key, mod | modrestore); | |||
@@ -339,16 +338,24 @@ void usb_keyboard_class::release(uint16_t n) | |||
uint8_t key, mod, msb; | |||
msb = n >> 8; | |||
if (msb >= 0xC2 && msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else | |||
if (msb == 0x80) { | |||
releasekey(0, n); | |||
return; | |||
} else | |||
if (msb == 0x40) { | |||
releasekey(n, 0); | |||
return; | |||
if (msb >= 0xC2) { | |||
if (msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else if (msb == 0xF0) { | |||
releasekey(n, 0); | |||
return; | |||
} else if (msb == 0xE0) { | |||
releasekey(0, n); | |||
return; | |||
} else if (msb == 0xE2) { | |||
release_system_key(n); | |||
return; | |||
} else if (msb >= 0xE4 && msb <= 0xE7) { | |||
release_consumer_key(n & 0x3FF); | |||
return; | |||
} else { | |||
return; | |||
} | |||
} | |||
KEYCODE_TYPE keycode = unicode_to_keycode(n); | |||
if (!keycode) return; | |||
@@ -420,6 +427,122 @@ void usb_keyboard_class::releaseAll(void) | |||
send_now(); | |||
} | |||
void usb_keyboard_class::press_consumer_key(uint16_t key) | |||
{ | |||
if (key == 0) return; | |||
for (uint8_t i=0; i < 4; i++) { | |||
if (keymedia_consumer_keys[i] == key) return; | |||
} | |||
for (uint8_t i=0; i < 4; i++) { | |||
if (keymedia_consumer_keys[i] == 0) { | |||
keymedia_consumer_keys[i] = key; | |||
keymedia_send(); | |||
return; | |||
} | |||
} | |||
} | |||
void usb_keyboard_class::release_consumer_key(uint16_t key) | |||
{ | |||
if (key == 0) return; | |||
for (uint8_t i=0; i < 4; i++) { | |||
if (keymedia_consumer_keys[i] == key) { | |||
keymedia_consumer_keys[i] = 0; | |||
keymedia_send(); | |||
return; | |||
} | |||
} | |||
} | |||
void usb_keyboard_class::press_system_key(uint8_t key) | |||
{ | |||
if (key == 0) return; | |||
for (uint8_t i=0; i < 3; i++) { | |||
if (keymedia_system_keys[i] == key) return; | |||
} | |||
for (uint8_t i=0; i < 3; i++) { | |||
if (keymedia_system_keys[i] == 0) { | |||
keymedia_system_keys[i] = key; | |||
keymedia_send(); | |||
return; | |||
} | |||
} | |||
} | |||
void usb_keyboard_class::release_system_key(uint8_t key) | |||
{ | |||
if (key == 0) return; | |||
for (uint8_t i=0; i < 3; i++) { | |||
if (keymedia_system_keys[i] == key) { | |||
keymedia_system_keys[i] = 0; | |||
keymedia_send(); | |||
return; | |||
} | |||
} | |||
} | |||
void usb_keyboard_class::keymedia_release_all(void) | |||
{ | |||
uint8_t anybits = 0; | |||
for (uint8_t i=0; i < 4; i++) { | |||
if (keymedia_consumer_keys[i] != 0) anybits = 1; | |||
keymedia_consumer_keys[i] = 0; | |||
} | |||
for (uint8_t i=0; i < 3; i++) { | |||
if (keymedia_system_keys[i] != 0) anybits = 1; | |||
keymedia_system_keys[i] = 0; | |||
} | |||
if (anybits) keymedia_send(); | |||
} | |||
// send the contents of keyboard_keys and keyboard_modifier_keys | |||
void usb_keyboard_class::keymedia_send(void) | |||
{ | |||
uint8_t intr_state, timeout; | |||
if (!usb_configuration) return; | |||
intr_state = SREG; | |||
cli(); | |||
UENUM = KEYMEDIA_ENDPOINT; | |||
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_configuration) return; | |||
// have we waited too long? | |||
if (UDFNUML == timeout) return; | |||
// get ready to try checking again | |||
intr_state = SREG; | |||
cli(); | |||
UENUM = KEYMEDIA_ENDPOINT; | |||
} | |||
// 44444444 44333333 33332222 22222211 11111111 | |||
// 98765432 10987654 32109876 54321098 76543210 | |||
UEDATX = keymedia_consumer_keys[0]; | |||
UEDATX = (keymedia_consumer_keys[1] << 2) | ((keymedia_consumer_keys[0] >> 8) & 0x03); | |||
UEDATX = (keymedia_consumer_keys[2] << 4) | ((keymedia_consumer_keys[1] >> 6) & 0x0F); | |||
UEDATX = (keymedia_consumer_keys[3] << 6) | ((keymedia_consumer_keys[2] >> 4) & 0x3F); | |||
UEDATX = keymedia_consumer_keys[3] >> 2; | |||
UEDATX = keymedia_system_keys[0]; | |||
UEDATX = keymedia_system_keys[1]; | |||
UEDATX = keymedia_system_keys[2]; | |||
UEINTX = 0x3A; | |||
SREG = intr_state; | |||
} | |||
void usb_mouse_class::move(int8_t x, int8_t y, int8_t wheel) | |||
@@ -499,9 +622,6 @@ bool usb_mouse_class::isPressed(uint8_t b) | |||
} | |||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
void usb_joystick_class::send_now(void) | |||
{ | |||
uint8_t intr_state, timeout; | |||
@@ -540,7 +660,6 @@ void usb_joystick_class::send_now(void) | |||
SREG = intr_state; | |||
} | |||
#endif | |||
@@ -679,11 +798,7 @@ void usb_serial_class::flush() | |||
} | |||
// transmit a character. | |||
#if ARDUINO >= 100 | |||
size_t usb_serial_class::write(uint8_t c) | |||
#else | |||
void usb_serial_class::write(uint8_t c) | |||
#endif | |||
{ | |||
//static uint8_t previous_timeout=0; | |||
uint8_t timeout, intr_state; | |||
@@ -736,16 +851,10 @@ void usb_serial_class::write(uint8_t c) | |||
debug_flush_timer = TRANSMIT_FLUSH_TIMEOUT; | |||
} | |||
SREG = intr_state; | |||
#if ARDUINO >= 100 | |||
return 1; | |||
#endif | |||
error: | |||
#if ARDUINO >= 100 | |||
setWriteError(); | |||
return 0; | |||
#else | |||
return; | |||
#endif | |||
} | |||
@@ -814,7 +923,5 @@ usb_serial_class::operator bool() | |||
usb_serial_class Serial = usb_serial_class(); | |||
usb_keyboard_class Keyboard = usb_keyboard_class(); | |||
usb_mouse_class Mouse = usb_mouse_class(); | |||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
usb_joystick_class Joystick = usb_joystick_class(); | |||
#endif | |||
@@ -12,11 +12,7 @@ class usb_keyboard_class : public Print | |||
public: | |||
void begin(void) { } | |||
void end(void) { } | |||
#if ARDUINO >= 100 | |||
virtual size_t write(uint8_t); | |||
#else | |||
virtual void write(uint8_t); | |||
#endif | |||
using Print::write; | |||
void write_unicode(uint16_t unicode) { write_keycode(unicode_to_keycode(unicode)); } | |||
void set_modifier(uint8_t); | |||
@@ -26,7 +22,13 @@ class usb_keyboard_class : public Print | |||
void set_key4(uint8_t); | |||
void set_key5(uint8_t); | |||
void set_key6(uint8_t); | |||
void set_media(uint8_t); | |||
void set_media(uint16_t c) { | |||
if (c == 0) { | |||
keymedia_release_all(); | |||
} else if (c >= 0xE400 && c <= 0xE7FF) { | |||
press(c); | |||
} | |||
} | |||
void send_now(void); | |||
void press(uint16_t n); | |||
void release(uint16_t n); | |||
@@ -40,6 +42,12 @@ class usb_keyboard_class : public Print | |||
void releasekey(uint8_t key, uint8_t modifier); | |||
void write_keycode(KEYCODE_TYPE key); | |||
void write_key(KEYCODE_TYPE code); | |||
void press_consumer_key(uint16_t key); | |||
void release_consumer_key(uint16_t key); | |||
void press_system_key(uint8_t key); | |||
void release_system_key(uint8_t key); | |||
void keymedia_release_all(void); | |||
void keymedia_send(void); | |||
uint8_t utf8_state; | |||
uint16_t unicode_wchar; | |||
}; | |||
@@ -70,8 +78,6 @@ extern usb_mouse_class Mouse; | |||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
extern uint8_t joystick_report_data[12]; | |||
class usb_joystick_class | |||
@@ -171,7 +177,6 @@ class usb_joystick_class | |||
extern usb_joystick_class Joystick; | |||
#endif | |||
@@ -185,11 +190,7 @@ class usb_serial_class : public Stream | |||
virtual int read(); | |||
virtual int peek(); | |||
virtual void flush(); | |||
#if ARDUINO >= 100 | |||
virtual size_t write(uint8_t); | |||
#else | |||
virtual void write(uint8_t); | |||
#endif | |||
using Print::write; | |||
operator bool(); | |||
// Teensy extensions |
@@ -25,21 +25,13 @@ extern "C"{ | |||
* | |||
**************************************************************************/ | |||
// These buffer sizes are best for most applications, but perhaps if you | |||
// want more buffering on some endpoint at the expense of others, this | |||
// is where you can make such changes. The AT90USB162 has only 176 bytes | |||
// of DPRAM (USB buffers) and only endpoints 3 & 4 can double buffer. | |||
// 0: control 32 64 | |||
// 1: debug IN 64 64x2 | |||
// 2: debug OUT 32 32x2 | |||
// 3: keyboard IN 8x2 8x2 | |||
// 4: mouse + joystick IN (IDs) 16x2 16x2 | |||
// 5: joystick 16x2 | |||
// 6: | |||
#if defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) | |||
// 0: control 64 | |||
// 1: debug IN 64x2 | |||
// 2: debug OUT 32x2 | |||
// 3: keyboard IN 8x2 | |||
// 4: mouse IN 16x2 | |||
// 5: joystick IN 16x2 | |||
// 6: keyboard media IN 8x2 | |||
// Some operating systems, especially Windows, may cache USB device | |||
// info. Changes to the device name may not update on the same | |||
@@ -77,41 +69,14 @@ extern "C"{ | |||
#define JOYSTICK_BUFFER EP_DOUBLE_BUFFER | |||
#define JOYSTICK_INTERVAL 2 | |||
#define NUM_ENDPOINTS 7 | |||
#define NUM_INTERFACE 4 | |||
#elif defined(__AVR_AT90USB162__) | |||
#define STR_PRODUCT L"Teensy Keyboard/Mouse" | |||
#define ENDPOINT0_SIZE 32 | |||
#define DEBUG_INTERFACE 2 | |||
#define DEBUG_TX_ENDPOINT 1 | |||
#define DEBUG_TX_SIZE 64 | |||
#define DEBUG_TX_BUFFER EP_SINGLE_BUFFER | |||
#define DEBUG_TX_INTERVAL 2 | |||
#define DEBUG_RX_ENDPOINT 2 | |||
#define DEBUG_RX_SIZE 32 | |||
#define DEBUG_RX_BUFFER EP_SINGLE_BUFFER | |||
#define DEBUG_RX_INTERVAL 8 | |||
#define KEYBOARD_INTERFACE 0 | |||
#define KEYBOARD_ENDPOINT 3 | |||
#define KEYBOARD_SIZE 8 | |||
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER | |||
#define KEYBOARD_INTERVAL 1 | |||
#define MOUSE_INTERFACE 1 | |||
#define MOUSE_ENDPOINT 4 | |||
#define MOUSE_SIZE 8 | |||
#define MOUSE_BUFFER EP_DOUBLE_BUFFER | |||
#define MOUSE_INTERVAL 8 | |||
#define NUM_ENDPOINTS 5 | |||
#define NUM_INTERFACE 3 | |||
#endif | |||
#define KEYMEDIA_INTERFACE 4 | |||
#define KEYMEDIA_ENDPOINT 6 | |||
#define KEYMEDIA_SIZE 8 | |||
#define KEYMEDIA_BUFFER EP_DOUBLE_BUFFER | |||
#define KEYMEDIA_INTERVAL 4 | |||
#define NUM_ENDPOINTS 7 | |||
#define NUM_INTERFACE 5 | |||
// setup | |||
@@ -126,9 +91,10 @@ extern uint8_t keyboard_report_data[]; | |||
extern uint8_t keyboard_idle_count; | |||
extern volatile uint8_t keyboard_leds; | |||
extern uint8_t mouse_buttons; | |||
#ifdef JOYSTICK_INTERFACE | |||
extern uint8_t joystick_report_data[12]; | |||
#endif | |||
extern uint8_t keymedia_report_data[8]; | |||
extern uint16_t keymedia_consumer_keys[4]; | |||
extern uint8_t keymedia_system_keys[3]; | |||
@@ -199,17 +199,10 @@ void usb_serial_class::write(uint8_t c) | |||
// transmit a block of data | |||
#if ARDUINO >= 100 | |||
size_t usb_serial_class::write(const uint8_t *buffer, uint16_t size) | |||
#else | |||
#define setWriteError() | |||
void usb_serial_class::write(const uint8_t *buffer, uint16_t size) | |||
#endif | |||
{ | |||
uint8_t timeout, intr_state, write_size; | |||
#if ARDUINO >= 100 | |||
size_t count=0; | |||
#endif | |||
// if we're not online (enumerated and configured), error | |||
if (!usb_configuration) { | |||
@@ -261,9 +254,7 @@ void usb_serial_class::write(const uint8_t *buffer, uint16_t size) | |||
write_size = CDC_TX_SIZE - UEBCLX; | |||
if (write_size > size) write_size = size; | |||
size -= write_size; | |||
#if ARDUINO >= 100 | |||
count += write_size; | |||
#endif | |||
#define ASM_COPY1(src, dest, tmp) "ld " tmp ", " src "\n\t" "st " dest ", " tmp "\n\t" | |||
#define ASM_COPY2(src, dest, tmp) ASM_COPY1(src, dest, tmp) ASM_COPY1(src, dest, tmp) | |||
@@ -315,11 +306,7 @@ void usb_serial_class::write(const uint8_t *buffer, uint16_t size) | |||
} | |||
SREG = intr_state; | |||
end: | |||
#if ARDUINO >= 100 | |||
return count; | |||
#else | |||
return; | |||
#endif | |||
} | |||
// transmit a string | |||
@@ -398,11 +385,7 @@ usb_serial_class::operator bool() | |||
// Step #1, decode UTF8 to Unicode code points | |||
// | |||
#if ARDUINO >= 100 | |||
size_t usb_keyboard_class::write(uint8_t c) | |||
#else | |||
void usb_keyboard_class::write(uint8_t c) | |||
#endif | |||
{ | |||
if (c < 0x80) { | |||
// single byte encoded, 0x00 to 0x7F | |||
@@ -432,9 +415,7 @@ void usb_keyboard_class::write(uint8_t c) | |||
// or illegal, 0xF5 to 0xFF | |||
utf8_state = 255; | |||
} | |||
#if ARDUINO >= 100 | |||
return 1; | |||
#endif | |||
} | |||
@@ -445,7 +426,8 @@ KEYCODE_TYPE usb_keyboard_class::unicode_to_keycode(uint16_t cpoint) | |||
// Unicode code points beyond U+FFFF are not supported | |||
// technically this input should probably be called UCS-2 | |||
if (cpoint < 32) { | |||
if (cpoint == 10) return KEY_ENTER & 0x3FFF; | |||
if (cpoint == 10) return KEY_ENTER & KEYCODE_MASK; | |||
if (cpoint == 11) return KEY_TAB & KEYCODE_MASK; | |||
return 0; | |||
} | |||
if (cpoint < 128) { | |||
@@ -618,10 +600,6 @@ void usb_keyboard_class::set_key6(uint8_t c) | |||
{ | |||
keyboard_report_data[7] = c; | |||
} | |||
void usb_keyboard_class::set_media(uint8_t c) | |||
{ | |||
keyboard_report_data[1] = c; | |||
} | |||
void usb_keyboard_class::send_now(void) | |||
@@ -665,17 +643,25 @@ void usb_keyboard_class::press(uint16_t n) | |||
uint8_t key, mod, msb, modrestore=0; | |||
msb = n >> 8; | |||
if (msb >= 0xC2 && msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else | |||
if (msb == 0x80) { | |||
presskey(0, n); | |||
return; | |||
} else | |||
if (msb == 0x40) { | |||
presskey(n, 0); | |||
return; | |||
} | |||
if (msb >= 0xC2) { | |||
if (msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else if (msb == 0xF0) { | |||
presskey(n, 0); | |||
return; | |||
} else if (msb == 0xE0) { | |||
presskey(0, n); | |||
return; | |||
} else if (msb == 0xE2) { | |||
//press_system_key(n); | |||
return; | |||
} else if (msb >= 0xE4 && msb <= 0xE7) { | |||
//press_consumer_key(n & 0x3FF); | |||
return; | |||
} else { | |||
return; | |||
} | |||
} | |||
KEYCODE_TYPE keycode = unicode_to_keycode(n); | |||
if (!keycode) return; | |||
#ifdef DEADKEYS_MASK | |||
@@ -704,17 +690,25 @@ void usb_keyboard_class::release(uint16_t n) | |||
uint8_t key, mod, msb; | |||
msb = n >> 8; | |||
if (msb >= 0xC2 && msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else | |||
if (msb == 0x80) { | |||
releasekey(0, n); | |||
return; | |||
} else | |||
if (msb == 0x40) { | |||
releasekey(n, 0); | |||
return; | |||
} | |||
if (msb >= 0xC2) { | |||
if (msb <= 0xDF) { | |||
n = (n & 0x3F) | ((uint16_t)(msb & 0x1F) << 6); | |||
} else if (msb == 0xF0) { | |||
releasekey(n, 0); | |||
return; | |||
} else if (msb == 0xE0) { | |||
releasekey(0, n); | |||
return; | |||
} else if (msb == 0xE2) { | |||
//release_system_key(n); | |||
return; | |||
} else if (msb >= 0xE4 && msb <= 0xE7) { | |||
//release_consumer_key(n & 0x3FF); | |||
return; | |||
} else { | |||
return; | |||
} | |||
} | |||
KEYCODE_TYPE keycode = unicode_to_keycode(n); | |||
if (!keycode) return; | |||
mod = keycode_to_modifier(keycode); |
@@ -61,7 +61,8 @@ class usb_keyboard_class : public Print | |||
void set_key4(uint8_t); | |||
void set_key5(uint8_t); | |||
void set_key6(uint8_t); | |||
void set_media(uint8_t); | |||
void set_media(uint8_t) { | |||
} | |||
void send_now(void); | |||
void press(uint16_t n); | |||
void release(uint16_t n); |