diff --git a/.gitignore b/.gitignore index 293c4523..c25d41d2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ *.lst *.map *.sym +tags diff --git a/Makefile b/Makefile index c9c668d4..1fe3ffa2 100644 --- a/Makefile +++ b/Makefile @@ -46,13 +46,14 @@ TARGET = mykey # List C source files here. (C dependencies are automatically generated.) SRC = $(TARGET).c \ + usb.c \ + usb_keyboard.c \ + usb_mouse.c \ + usb_debug.c \ keymap.c \ matrix.c \ - usb_device.c \ - usb_keyboard.c \ - usb_debug.c \ - print.c \ - jump_bootloader.c + jump_bootloader.c \ + print.c # MCU name, you MUST set this to match the board you are using diff --git a/keymap.h b/keymap.h index ac0cc5fe..6b95fb61 100644 --- a/keymap.h +++ b/keymap.h @@ -2,7 +2,7 @@ #define KEYMAP_H 1 #include -#include "usbkeycodes.h" +#include "usb_keycodes.h" int get_layer(void); uint8_t get_keycode(int layer, int row, int col); diff --git a/matrix.h b/matrix.h index d5290916..74b5f894 100644 --- a/matrix.h +++ b/matrix.h @@ -1,3 +1,6 @@ +#ifndef MATRIX_H +#define MATRIX_H 1 + #include 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 diff --git a/mykey.c b/mykey.c index 94cbbfb5..a295b8c5 100644 --- a/mykey.c +++ b/mykey.c @@ -30,7 +30,9 @@ #include #include -#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,69 +73,21 @@ int main(void) TCCR0B = 0x05; TIMSK0 = (1< 6) { - //Rollover - } - - 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(); @@ -150,27 +97,61 @@ int main(void) PORTD |= 1<> 8); phex(idle_count & 0xFF); print("\n"); - print("loop_count: "); phex((loop_count & 0xFF00) >> 8); phex(loop_count & 0xFF); print("\n"); - print_matrix(); + // 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< 6) { + //Rollover + } + usb_keyboard_send(); + } + } loop_count++; + _delay_ms(2); } } diff --git a/print.c b/print.c index 8e46deca..5395fa34 100644 --- a/print.c +++ b/print.c @@ -25,7 +25,6 @@ #include #include - #include "print.h" void print_P(const char *s) diff --git a/print.h b/print.h index 9a424627..d61e5de3 100644 --- a/print.h +++ b/print.h @@ -1,5 +1,5 @@ -#ifndef print_h__ -#define print_h__ +#ifndef PRINT_H__ +#define PRINT_H__ 1 #include #include "usb_debug.h" diff --git a/usb_device.c b/usb.c similarity index 83% rename from usb_device.c rename to usb.c index 1d790f04..c910a977 100644 --- a/usb_device.c +++ b/usb.c @@ -21,10 +21,12 @@ * THE SOFTWARE. */ +#include #include #include -#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; diff --git a/usb_device.h b/usb.h similarity index 95% rename from usb_device.h rename to usb.h index 233e439f..c1347f10 100644 --- a/usb_device.h +++ b/usb.h @@ -1,10 +1,8 @@ -#ifndef USB_DEVICE_H -#define USB_DEVICE_H 1 +#ifndef USB_H +#define USB_H 1 #include #include -#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 acc6716c..65ad05b0 100644 --- a/usb_debug.h +++ b/usb_debug.h @@ -2,11 +2,11 @@ #define USB_DEBUG_H 1 #include -#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 cd8ec4a9..90c2c5af 100644 --- a/usb_keyboard.h +++ b/usb_keyboard.h @@ -2,11 +2,11 @@ #define USB_KEYBOARD_H 1 #include -#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 similarity index 93% rename from usbkeycodes.h rename to usb_keycodes.h index b0e70583..95160398 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 00000000..539f2edd --- /dev/null +++ b/usb_mouse.c @@ -0,0 +1,62 @@ +#include +#include +#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< +#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