add mouse function.
14 files changed, 275 insertions(+), 117 deletions(-) M .gitignore M Makefile M keymap.h M matrix.h M mykey.c M print.c M print.h R {usb_device => usb}.c R {usb_device => usb}.h M usb_debug.h M usb_keyboard.h R {usbkeycodes => usb_keycodes}.h A usb_mouse.c A usb_mouse.h
M .gitignore => .gitignore +1 -0
M Makefile => Makefile +6 -5
@@ 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
M keymap.h => keymap.h +1 -1
@@ 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);
M matrix.h => matrix.h +5 -0
@@ 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
M mykey.c => mykey.c +54 -73
@@ 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); } }
M print.c => print.c +0 -1
@@ 25,7 25,6 @@ #include <avr/io.h> #include <avr/pgmspace.h> #include "print.h" void print_P(const char *s)
M print.h => print.h +2 -2
@@ 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"
R usb_device.c => usb.c +107 -12
@@ 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;
R usb_device.h => usb.h +2 -4
@@ 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
M usb_debug.h => usb_debug.h +3 -3
@@ 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
M usb_keyboard.h => usb_keyboard.h +2 -2
@@ 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
R usbkeycodes.h => usb_keycodes.h +10 -14
@@ 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 */
A usb_mouse.c => usb_mouse.c +62 -0
@@ 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; }
A usb_mouse.h => usb_mouse.h +20 -0
@@ 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