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