diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | keymap.h | 2 | ||||
-rw-r--r-- | matrix.h | 5 | ||||
-rw-r--r-- | mykey.c | 127 | ||||
-rw-r--r-- | print.c | 1 | ||||
-rw-r--r-- | print.h | 4 | ||||
-rw-r--r-- | usb.c (renamed from usb_device.c) | 119 | ||||
-rw-r--r-- | usb.h (renamed from usb_device.h) | 6 | ||||
-rw-r--r-- | usb_debug.h | 6 | ||||
-rw-r--r-- | usb_keyboard.h | 4 | ||||
-rw-r--r-- | usb_keycodes.h (renamed from usbkeycodes.h) | 24 | ||||
-rw-r--r-- | usb_mouse.c | 62 | ||||
-rw-r--r-- | usb_mouse.h | 20 |
14 files changed, 275 insertions, 117 deletions
diff --git a/.gitignore b/.gitignore index 293c452390..c25d41d238 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.lst *.map *.sym +tags @@ -46,13 +46,14 @@ TARGET = mykey # List C source files here. (C dependencies are automatically generated.) SRC = $(TARGET).c \ - keymap.c \ - matrix.c \ - usb_device.c \ + usb.c \ usb_keyboard.c \ + usb_mouse.c \ usb_debug.c \ - print.c \ - jump_bootloader.c + keymap.c \ + matrix.c \ + jump_bootloader.c \ + print.c # MCU name, you MUST set this to match the board you are using @@ -2,7 +2,7 @@ #define KEYMAP_H 1 #include <stdint.h> -#include "usbkeycodes.h" +#include "usb_keycodes.h" int get_layer(void); uint8_t get_keycode(int layer, int row, int col); @@ -1,3 +1,6 @@ +#ifndef MATRIX_H +#define MATRIX_H 1 + #include <stdbool.h> extern uint8_t *matrix; @@ -8,3 +11,5 @@ uint8_t matrix_scan(void); bool matrix_is_modified(void); bool matrix_has_ghost(void); bool matrix_has_ghost_in_row(uint8_t row); + +#endif @@ -30,7 +30,9 @@ #include <avr/interrupt.h> #include <util/delay.h> -#include "usb_device.h" +#include "usb.h" +#include "usb_keyboard.h" +#include "usb_mouse.h" #include "print.h" #include "matrix.h" #include "keymap.h" @@ -50,16 +52,9 @@ uint16_t idle_count=0; int main(void) { - bool modified = false; - bool has_ghost = false; - uint8_t key_index = 0; - // set for 16 MHz clock CPU_PRESCALE(0); - matrix_init(); - - // Initialize the USB, and then wait for the host to set configuration. // If the Teensy is powered without a PC connected to the USB port, // this will wait forever. @@ -78,99 +73,85 @@ int main(void) TCCR0B = 0x05; TIMSK0 = (1<<TOIE0); + + matrix_init(); print("firmware 0.2 for t.m.k.\n"); + bool modified = false; + bool has_ghost = false; + int key_index = 0; int loop_count = 0; + int layer = 0; while (1) { - int layer = 0; - matrix_scan(); layer = get_layer(); - modified = matrix_is_modified(); has_ghost = matrix_has_ghost(); - // doesnt send keys during ghost occurs - if (modified && !has_ghost) { - key_index = 0; - keyboard_modifier_keys = 0; - for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO; + // print matrix state for debug + if (modified) { + print_matrix(); - for (int row = 0; row < MATRIX_ROWS; row++) { - for (int col = 0; col < MATRIX_COLS; col++) { - if (matrix[row] & 1<<col) continue; - - uint8_t code = get_keycode(layer, row, col); - if (code == KB_NO) { - continue; - } else if (KB_LCTRL <= code && code <= KB_RGUI) { - // modifier keycode: 0xE0-0xE7 - keyboard_modifier_keys |= 1<<(code & 0x07); - } else { - if (key_index < 6) - keyboard_keys[key_index] = code; - key_index++; - } + // LED flush + DDRD |= 1<<PD6; + PORTD |= 1<<PD6; + } + + // set matrix state to keyboard_keys, keyboard_modifier_keys + key_index = 0; + keyboard_modifier_keys = 0; + for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO; + for (int row = 0; row < MATRIX_ROWS; row++) { + for (int col = 0; col < MATRIX_COLS; col++) { + if (matrix[row] & 1<<col) continue; + + uint8_t code = get_keycode(layer, row, col); + if (code == KB_NO) { + continue; + } else if (KB_LCTRL <= code && code <= KB_RGUI) { + // modifier keycode: 0xE0-0xE7 + keyboard_modifier_keys |= 1<<(code & 0x07); + } else { + if (key_index < 6) + keyboard_keys[key_index] = code; + key_index++; } } + } - // run bootloader when 4 left modifier keys down + if (!has_ghost) { + // when 4 left modifier keys down if (keyboard_modifier_keys == (MOD_LCTRL | MOD_LSHIFT | MOD_LALT | MOD_LGUI)) { // cancel all keys keyboard_modifier_keys = 0; for (int i = 0; i < 6; i++) keyboard_keys[i] = KB_NO; usb_keyboard_send(); + /* print("jump to bootloader...\n"); _delay_ms(1000); jump_bootloader(); - } + */ - if (key_index > 6) { - //Rollover - } + // mouse + print("usb_mouse_move\n"); + usb_mouse_move(10, 0, 0); - usb_keyboard_send(); - - - // variables shared with interrupt routines must be - // accessed carefully so the interrupt routine doesn't - // try to use the variable in the middle of our access - cli(); - //idle_count = 0; - sei(); - } - - // print matrix state for debug - if (modified) { - print_matrix(); - - // LED flush - DDRD |= 1<<PD6; - PORTD |= 1<<PD6; - } + _delay_ms(100); + continue; + } -/* - // print counts for debug - if ((loop_count % 0x1000) == 0) { - //print("."); - print("idle_count: "); phex((idle_count & 0xFF00) >> 8); phex(idle_count & 0xFF); print("\n"); - print("loop_count: "); phex((loop_count & 0xFF00) >> 8); phex(loop_count & 0xFF); print("\n"); - print_matrix(); - } - // teensy LED flush for debug - if ((loop_count & 0x100) == 0) { - DDRD |= 1<<PD6; - PORTD |= 1<<PD6; + // send keys to host + if (modified) { + if (key_index > 6) { + //Rollover + } + usb_keyboard_send(); + } } -*/ - - // now the current pins will be the previous, and - // wait a short delay so we're not highly sensitive - // to mechanical "bounce". - _delay_ms(2); loop_count++; + _delay_ms(2); } } @@ -25,7 +25,6 @@ #include <avr/io.h> #include <avr/pgmspace.h> - #include "print.h" void print_P(const char *s) @@ -1,5 +1,5 @@ -#ifndef print_h__ -#define print_h__ +#ifndef PRINT_H__ +#define PRINT_H__ 1 #include <avr/pgmspace.h> #include "usb_debug.h" @@ -21,10 +21,12 @@ * THE SOFTWARE. */ +#include <avr/io.h> #include <avr/pgmspace.h> #include <avr/interrupt.h> -#include "usb_device.h" +#include "usb.h" #include "usb_keyboard.h" +#include "usb_mouse.h" #include "usb_debug.h" @@ -64,11 +66,15 @@ #define ENDPOINT0_SIZE 32 +// 0:control endpoint is enabled automatically by controller. static const uint8_t PROGMEM endpoint_config_table[] = { - 0, - 0, - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, - 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER + // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation) + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, // 1 + 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 + 0, // 4 + 0, // 5 + 0, // 6 }; @@ -138,6 +144,36 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = { 0xc0 // End Collection }; +// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension +static uint8_t PROGMEM mouse_hid_report_desc[] = { + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x02, // Usage (Mouse) + 0xA1, 0x01, // Collection (Application) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (Button #1) + 0x29, 0x03, // Usage Maximum (Button #3) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x03, // Report Count (3) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input (Data, Variable, Absolute) + 0x95, 0x01, // Report Count (1) + 0x75, 0x05, // Report Size (5) + 0x81, 0x03, // Input (Constant) + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x15, 0x81, // Logical Minimum (-127) + 0x25, 0x7F, // Logical Maximum (127) + 0x75, 0x08, // Report Size (8), + 0x95, 0x02, // Report Count (2), + 0x81, 0x06, // Input (Data, Variable, Relative) + 0x09, 0x38, // Usage (Wheel) + 0x95, 0x01, // Report Count (1), + 0x81, 0x06, // Input (Data, Variable, Relative) + 0xC0 // End Collection +}; + static uint8_t PROGMEM debug_hid_report_desc[] = { 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) 0x09, 0x74, // Usage 0x74 @@ -151,20 +187,22 @@ static uint8_t PROGMEM debug_hid_report_desc[] = { 0xC0 // end collection }; -#define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7) +#define CONFIG1_DESC_SIZE (9+(9+9+7)+(9+9+7)+(9+9+7)) #define KEYBOARD_HID_DESC_OFFSET (9+9) -#define DEBUG_HID_DESC_OFFSET (9+9+9+7+9) +#define MOUSE_HID_DESC_OFFSET (9+(9+9+7)+9) +#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)+(9+9+7)+9) static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 9, // bLength; 2, // bDescriptorType; LSB(CONFIG1_DESC_SIZE), // wTotalLength MSB(CONFIG1_DESC_SIZE), - 2, // bNumInterfaces + 3, // bNumInterfaces 1, // bConfigurationValue 0, // iConfiguration 0xC0, // bmAttributes 50, // bMaxPower + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType @@ -175,7 +213,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { 0x01, // bInterfaceSubClass (0x01 = Boot) 0x01, // bInterfaceProtocol (0x01 = Keyboard) 0, // iInterface - // HID interface descriptor, HID 1.11 spec, section 6.2.1 + // HID descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID @@ -191,6 +229,34 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { 0x03, // bmAttributes (0x03=intr) KEYBOARD_SIZE, 0, // wMaxPacketSize 1, // bInterval + + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + MOUSE_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x01, // bInterfaceSubClass (0x01 = Boot) + 0x02, // bInterfaceProtocol (0x02 = Mouse) + 0, // 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(mouse_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + MOUSE_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + 4, 0, // wMaxPacketSize + 1, // bInterval + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 9, // bLength 4, // bDescriptorType @@ -201,7 +267,7 @@ static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { 0x00, // bInterfaceSubClass 0x00, // bInterfaceProtocol 0, // iInterface - // HID interface descriptor, HID 1.11 spec, section 6.2.1 + // HID descriptor, HID 1.11 spec, section 6.2.1 9, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID @@ -259,6 +325,9 @@ static struct descriptor_list_struct { {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, // HID REPORT + {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)}, + {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9}, + // HID REPORT {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, // STRING descriptor @@ -470,7 +539,7 @@ ISR(USB_COM_vect) usb_configuration = wValue; usb_send_in(); cfg = endpoint_config_table; - for (i=1; i<5; i++) { + for (i=1; i<=6; i++) { UENUM = i; en = pgm_read_byte(cfg++); UECONX = en; @@ -479,7 +548,7 @@ ISR(USB_COM_vect) UECFG1X = pgm_read_byte(cfg++); } } - UERST = 0x1E; + UERST = 0x7E; UERST = 0; return; } @@ -571,6 +640,32 @@ ISR(USB_COM_vect) } } } + if (wIndex == MOUSE_INTERFACE) { + if (bmRequestType == 0xA1) { + if (bRequest == HID_GET_REPORT) { + usb_wait_in_ready(); + UEDATX = mouse_buttons; + UEDATX = 0; + UEDATX = 0; + UEDATX = 0; + usb_send_in(); + return; + } + if (bRequest == HID_GET_PROTOCOL) { + usb_wait_in_ready(); + UEDATX = mouse_protocol; + usb_send_in(); + return; + } + } + if (bmRequestType == 0x21) { + if (bRequest == HID_SET_PROTOCOL) { + mouse_protocol = wValue; + usb_send_in(); + return; + } + } + } if (wIndex == DEBUG_INTERFACE) { if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) { len = wLength; @@ -1,10 +1,8 @@ -#ifndef USB_DEVICE_H -#define USB_DEVICE_H 1 +#ifndef USB_H +#define USB_H 1 #include <stdint.h> #include <avr/io.h> -#include "usb_keyboard.h" -#include "usb_debug.h" void usb_init(void); // initialize everything diff --git a/usb_debug.h b/usb_debug.h index acc6716cde..65ad05b04a 100644 --- a/usb_debug.h +++ b/usb_debug.h @@ -2,11 +2,11 @@ #define USB_DEBUG_H 1 #include <stdint.h> -#include "usb_device.h" +#include "usb.h" -#define DEBUG_INTERFACE 1 -#define DEBUG_TX_ENDPOINT 4 +#define DEBUG_INTERFACE 2 +#define DEBUG_TX_ENDPOINT 3 #define DEBUG_TX_SIZE 32 #define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER diff --git a/usb_keyboard.h b/usb_keyboard.h index cd8ec4a9d1..90c2c5af62 100644 --- a/usb_keyboard.h +++ b/usb_keyboard.h @@ -2,11 +2,11 @@ #define USB_KEYBOARD_H 1 #include <stdint.h> -#include "usb_device.h" +#include "usb.h" #define KEYBOARD_INTERFACE 0 -#define KEYBOARD_ENDPOINT 3 +#define KEYBOARD_ENDPOINT 1 #define KEYBOARD_SIZE 8 #define KEYBOARD_BUFFER EP_DOUBLE_BUFFER diff --git a/usbkeycodes.h b/usb_keycodes.h index b0e7058363..95160398d8 100644 --- a/usbkeycodes.h +++ b/usb_keycodes.h @@ -1,5 +1,8 @@ -/* Some modified from Keyboard Upgrade 0.3.0 - * 2010/08/22 +/* + * Key codes from HID Keyboard/Keypad Page + * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf + * + * Based on Keyboard Upgrade v0.3.0 http://github.com/rhomann/kbupgrade */ /* * Keyboard Upgrade -- Firmware for homebrew computer keyboard controllers. @@ -30,17 +33,10 @@ * MA 02110-1301 USA */ -#ifndef USBKEYCODES_H -#define USBKEYCODES_H +#ifndef USB_KEYCODES_H +#define USB_KEYCODES_H + -/* - * The USB keycodes are enumerated here - the first part is simply - * an enumeration of the allowed scan-codes used for USB HID devices. - */ -/* - * see 10 Keyboard/Keypad Page(0x07) - * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf - */ enum keycodes { KB_NO = 0, KB_ROLL_OVER, @@ -265,11 +261,11 @@ enum keycodes { KB_RALT, /* 0x40 */ KB_RGUI, /* 0x80 */ - /* function keys */ + /* extensions for internal use */ FN_0 = 0xF0, FN_1, FN_2, FN_3, }; -#endif /* USBKEYCODES_H */ +#endif /* USB_KEYCODES_H */ diff --git a/usb_mouse.c b/usb_mouse.c new file mode 100644 index 0000000000..539f2edd37 --- /dev/null +++ b/usb_mouse.c @@ -0,0 +1,62 @@ +#include <avr/interrupt.h> +#include <util/delay.h> +#include "usb_mouse.h" + + +// which buttons are currently pressed +uint8_t mouse_buttons=0; + +// 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 mouse_protocol=1; + + +// Set the mouse buttons. To create a "click", 2 calls are needed, +// one to push the button down and the second to release it +int8_t usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right) +{ + uint8_t mask=0; + + if (left) mask |= 1; + if (middle) mask |= 4; + if (right) mask |= 2; + mouse_buttons = mask; + return usb_mouse_move(0, 0, 0); +} + +// Move the mouse. x, y and wheel are -127 to 127. Use 0 for no movement. +int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel) +{ + uint8_t intr_state, timeout; + + if (!usb_configured()) return -1; + if (x == -128) x = -127; + if (y == -128) y = -127; + if (wheel == -128) wheel = -127; + intr_state = SREG; + cli(); + UENUM = MOUSE_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_configured()) return -1; + // have we waited too long? + if (UDFNUML == timeout) return -1; + // get ready to try checking again + intr_state = SREG; + cli(); + UENUM = MOUSE_ENDPOINT; + } + UEDATX = mouse_buttons; + UEDATX = x; + UEDATX = y; + UEDATX = wheel; + UEINTX = 0x3A; + SREG = intr_state; + return 0; +} + diff --git a/usb_mouse.h b/usb_mouse.h new file mode 100644 index 0000000000..f1f39776f7 --- /dev/null +++ b/usb_mouse.h @@ -0,0 +1,20 @@ +#ifndef USB_MOUSE_H +#define USB_MOUSE_H 1 + +#include <stdint.h> +#include "usb.h" + + +#define MOUSE_INTERFACE 1 +#define MOUSE_ENDPOINT 2 +#define MOUSE_SIZE 8 +#define MOUSE_BUFFER EP_DOUBLE_BUFFER + +extern uint8_t mouse_buttons; +extern uint8_t mouse_protocol; + + +int8_t usb_mouse_buttons(uint8_t left, uint8_t middle, uint8_t right); +int8_t usb_mouse_move(int8_t x, int8_t y, int8_t wheel); + +#endif |