From 0632618d29dfb30c76b4e7c310dc7bee36919f63 Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 3 Feb 2011 13:26:44 +0900 Subject: [PATCH] added initial support of mousekeys to ps2_vusb --- Makefile.vusb | 7 +- ps2_vusb/Makefile | 4 +- ps2_vusb/host.h | 35 ++++ ps2_vusb/host_vusb.c | 345 +++++++++++++++++++++++++++++++++++++++ ps2_vusb/host_vusb.h | 7 + ps2_vusb/keyboard.c | 79 +++++++++ ps2_vusb/keyboard.h | 32 ++-- ps2_vusb/keyboard_vusb.c | 156 ------------------ ps2_vusb/layer.c | 34 ++-- ps2_vusb/main.c | 111 +++++-------- ps2_vusb/matrix.c | 11 +- ps2_vusb/mousekey.c | 102 ++++++++++++ ps2_vusb/mousekey.h | 12 ++ ps2_vusb/usbconfig.h | 11 +- 14 files changed, 676 insertions(+), 270 deletions(-) create mode 100644 ps2_vusb/host.h create mode 100644 ps2_vusb/host_vusb.c create mode 100644 ps2_vusb/host_vusb.h create mode 100644 ps2_vusb/keyboard.c delete mode 100644 ps2_vusb/keyboard_vusb.c create mode 100644 ps2_vusb/mousekey.c create mode 100644 ps2_vusb/mousekey.h diff --git a/Makefile.vusb b/Makefile.vusb index b372ce25..8ee2209c 100644 --- a/Makefile.vusb +++ b/Makefile.vusb @@ -65,7 +65,7 @@ FORMAT = ihex # Object files directory # To put object files in current directory, use a dot (.), do NOT make # this an empty or blank macro! -OBJDIR = . +OBJDIR = obj # Optimization level, can be [0, 1, 2, 3, s]. @@ -347,7 +347,7 @@ AR = avr-ar rcs NM = avr-nm AVRDUDE = avrdude REMOVE = rm -f -REMOVEDIR = rm -rf +REMOVEDIR = rmdir COPY = cp WINSHELL = cmd @@ -601,7 +601,8 @@ clean_list : $(REMOVE) $(LST) $(REMOVE) $(OBJ:.o=.s) $(REMOVE) $(OBJ:.o=.i) - $(REMOVEDIR) .dep + $(REMOVE) -r .dep + $(REMOVEDIR) $(OBJDIR) # Create object files directory diff --git a/ps2_vusb/Makefile b/ps2_vusb/Makefile index 48748a74..5b25e514 100644 --- a/ps2_vusb/Makefile +++ b/ps2_vusb/Makefile @@ -9,11 +9,13 @@ TARGET_DIR = . # keyboard dependent files TARGET_SRC = main.c \ - keyboard_vusb.c \ + keyboard.c \ + mousekey.c \ layer.c \ keymap.c \ matrix.c \ ps2.c \ + host_vusb.c \ print.c \ util.c \ timer.c \ diff --git a/ps2_vusb/host.h b/ps2_vusb/host.h new file mode 100644 index 00000000..b4b9eefb --- /dev/null +++ b/ps2_vusb/host.h @@ -0,0 +1,35 @@ +#ifndef HOST_H +#define HOST_H + +#include + + +#define REPORT_KEYS 6 +#define MOUSE_BTN1 (1<<0) +#define MOUSE_BTN2 (1<<1) +#define MOUSE_BTN3 (1<<2) +#define MOUSE_BTN4 (1<<3) +#define MOUSE_BTN5 (1<<4) + + +typedef struct { + uint8_t mods; + uint8_t rserved; // not used + uint8_t keys[REPORT_KEYS]; +} report_keyboard_t; + +typedef struct { + uint8_t buttons; + int8_t x; + int8_t y; +/* + int8_t v; + int8_t h; + */ +} report_mouse_t; + + +void host_keyboard_send(report_keyboard_t *report); +void host_mouse_send(report_mouse_t *report); + +#endif diff --git a/ps2_vusb/host_vusb.c b/ps2_vusb/host_vusb.c new file mode 100644 index 00000000..cda90487 --- /dev/null +++ b/ps2_vusb/host_vusb.c @@ -0,0 +1,345 @@ +#include "usbdrv.h" +#include "usbconfig.h" +#include "keyboard.h" +#include "print.h" +#include "host.h" +#include "host_vusb.h" + + +#define KBUF_SIZE 8 +static report_keyboard_t kbuf[KBUF_SIZE]; +static uint8_t kbuf_head = 0; +static uint8_t kbuf_tail = 0; + + +void host_vusb_keyboard_send() +{ + if (kbuf_head != kbuf_tail) { + if (usbInterruptIsReady()) { + usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t)); + kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE; + } + } +} + +void host_keyboard_send(report_keyboard_t *report) +{ + uint8_t next = (kbuf_head + 1) % KBUF_SIZE; + if (next != kbuf_tail) { + kbuf[kbuf_head] = *report; + kbuf_head = next; + } +} + +void host_mouse_send(report_mouse_t *report) +{ + // dirty hack to send twice a loop :( + //while (!usbInterruptIsReady3()) usbPoll(); + + if (usbInterruptIsReady3()) { + usbSetInterrupt3((void *)report, sizeof(*report)); + } else { + print("Int3 not ready\n"); + } +} + + + + + +static uchar idleRate; /* repeat rate for keyboards, never used for mice */ +usbMsgLen_t usbFunctionSetup(uchar data[8]) +{ +usbRequest_t *rq = (void *)data; + + print("Setup: "); + if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ + print("CLASS: "); + phex(rq->bRequest); + if(rq->bRequest == USBRQ_HID_GET_REPORT){ + print("GET_REPORT"); + /* we only have one report type, so don't look at wValue */ + usbMsgPtr = (void *)keyboard_report; + return sizeof(*keyboard_report); + }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ + print("GET_IDLE: "); + phex(idleRate); + usbMsgPtr = &idleRate; + return 1; + }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ + idleRate = rq->wValue.bytes[1]; + print("SET_IDLE: "); + phex(idleRate); + } + print("\n"); + }else{ + print("VENDOR\n"); + /* no vendor specific requests implemented */ + } + return 0; /* default for not implemented requests: return no data back to host */ +} + + +PROGMEM uchar keyboard_hid_report[] = { + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application), + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte + 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), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x03, // Output (Constant), ;LED report padding + 0x95, 0x06, // Report Count (6), + 0x75, 0x08, // Report Size (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0xFF, // Logical Maximum(255), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0xFF, // Usage Maximum (255), + 0x81, 0x00, // Input (Data, Array), + 0xc0 // End Collection +}; + +// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension +// http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521 +// http://www.keil.com/forum/15671/ +// http://www.microsoft.com/whdc/device/input/wheel.mspx +PROGMEM uchar mouse_hid_report[] = { + /* from HID 1.11 spec example */ + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x02, // Usage (Mouse), + 0xA1, 0x01, // Collection (Application), + 0x09, 0x01, // Usage (Pointer), + 0xA1, 0x00, // Collection (Physical), + 0x05, 0x09, // Usage Page (Buttons), + 0x19, 0x01, // Usage Minimum (01), + 0x29, 0x03, // Usage Maximun (03), + 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), ;3 button bits + 0x95, 0x01, // Report Count (1), + 0x75, 0x05, // Report Size (5), + 0x81, 0x01, // Input (Constant), ;5 bit padding + 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), ;2 position bytes (X & Y) + 0xC0, // End Collection, + 0xC0, // End Collection +/* + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x01, // COLLECTION (Application) + 0x09, 0x02, // USAGE (Mouse) + 0xa1, 0x02, // COLLECTION (Logical) + 0x09, 0x01, // USAGE (Pointer) + 0xa1, 0x00, // COLLECTION (Physical) + // ------------------------------ Buttons + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x05, // USAGE_MAXIMUM (Button 5) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x05, // REPORT_COUNT (5) + 0x81, 0x02, // INPUT (Data,Var,Abs) + // ------------------------------ Padding + 0x75, 0x03, // REPORT_SIZE (3) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x03, // INPUT (Cnst,Var,Abs) + // ------------------------------ X,Y position + 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,Var,Rel) + 0xa1, 0x02, // COLLECTION (Logical) + // ------------------------------ Vertical wheel res multiplier + 0x09, 0x48, // USAGE (Resolution Multiplier) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x35, 0x01, // PHYSICAL_MINIMUM (1) + 0x45, 0x04, // PHYSICAL_MAXIMUM (4) + 0x75, 0x02, // REPORT_SIZE (2) + 0x95, 0x01, // REPORT_COUNT (1) + 0xa4, // PUSH + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + // ------------------------------ Vertical wheel + 0x09, 0x38, // USAGE (Wheel) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical + 0x45, 0x00, // PHYSICAL_MAXIMUM (0) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x06, // INPUT (Data,Var,Rel) + 0xc0, // END_COLLECTION + 0xa1, 0x02, // COLLECTION (Logical) + // ------------------------------ Horizontal wheel res multiplier + 0x09, 0x48, // USAGE (Resolution Multiplier) + 0xb4, // POP + 0xb1, 0x02, // FEATURE (Data,Var,Abs) + // ------------------------------ Padding for Feature report + 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical + 0x45, 0x00, // PHYSICAL_MAXIMUM (0) + 0x75, 0x04, // REPORT_SIZE (4) + 0xb1, 0x03, // FEATURE (Cnst,Var,Abs) + // ------------------------------ Horizontal wheel + 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) + 0x0a, 0x38, 0x02, // USAGE (AC Pan) + 0x15, 0x81, // LOGICAL_MINIMUM (-127) + 0x25, 0x7f, // LOGICAL_MAXIMUM (127) + 0x75, 0x08, // REPORT_SIZE (8) + 0x81, 0x06, // INPUT (Data,Var,Rel) + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION + 0xc0, // END_COLLECTION + 0xc0 // END_COLLECTION +*/ +}; + + +/* Descriptor for compite device: Keyboard + Mouse */ +#if USB_CFG_DESCR_PROPS_CONFIGURATION +PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */ + 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */ + USBDESCR_CONFIG, /* descriptor type */ + 9 + (9 + 9 + 7) + (9 + 9 + 7), 0, + //18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0, + /* total length of data returned (including inlined descriptors) */ + 2, /* number of interfaces in this configuration */ + 1, /* index of this configuration */ + 0, /* configuration name string index */ +#if USB_CFG_IS_SELF_POWERED + (1 << 7) | USBATTR_SELFPOWER, /* attributes */ +#else + (1 << 7), /* attributes */ +#endif + USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */ + + /* + * Keyboard interface + */ + /* Interface descriptor */ + 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */ + USBDESCR_INTERFACE, /* descriptor type */ + 0, /* index of this interface */ + 0, /* alternate setting for this interface */ + USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */ + USB_CFG_INTERFACE_CLASS, + USB_CFG_INTERFACE_SUBCLASS, + USB_CFG_INTERFACE_PROTOCOL, + 0, /* string index for interface */ + /* HID descriptor */ + 9, /* sizeof(usbDescrHID): length of descriptor in bytes */ + USBDESCR_HID, /* descriptor type: HID */ + 0x01, 0x01, /* BCD representation of HID version */ + 0x00, /* target country code */ + 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ + 0x22, /* descriptor type: report */ + sizeof(keyboard_hid_report), 0, /* total length of report descriptor */ + /* Endpoint descriptor */ +#if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */ + 7, /* sizeof(usbDescrEndpoint) */ + USBDESCR_ENDPOINT, /* descriptor type = endpoint */ + (char)0x81, /* IN endpoint number 1 */ + 0x03, /* attrib: Interrupt endpoint */ + 8, 0, /* maximum packet size */ + USB_CFG_INTR_POLL_INTERVAL, /* in ms */ +#endif + + /* + * Mouse interface + */ + /* Interface descriptor */ + 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */ + USBDESCR_INTERFACE, /* descriptor type */ + 1, /* index of this interface */ + 0, /* alternate setting for this interface */ + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */ + 0x03, /* CLASS: HID */ + 0, /* SUBCLASS: none */ + 0, /* PROTOCOL: none */ + 0, /* string index for interface */ + /* HID descriptor */ + 9, /* sizeof(usbDescrHID): length of descriptor in bytes */ + USBDESCR_HID, /* descriptor type: HID */ + 0x01, 0x01, /* BCD representation of HID version */ + 0x00, /* target country code */ + 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */ + 0x22, /* descriptor type: report */ + sizeof(mouse_hid_report), 0, /* total length of report descriptor */ +#if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */ + /* Endpoint descriptor */ + 7, /* sizeof(usbDescrEndpoint) */ + USBDESCR_ENDPOINT, /* descriptor type = endpoint */ + (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */ + 0x03, /* attrib: Interrupt endpoint */ + 8, 0, /* maximum packet size */ + USB_CFG_INTR_POLL_INTERVAL, /* in ms */ +#endif +}; +#endif + +USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) +{ + usbMsgLen_t len = 0; + + print("usbFunctionDescriptor: "); + phex(rq->bmRequestType); print(" "); + phex(rq->bRequest); print(" "); + phex16(rq->wValue.word); print(" "); + phex16(rq->wIndex.word); print(" "); + phex16(rq->wLength.word); print("\n"); + + switch (rq->wValue.bytes[1]) { +#if USB_CFG_DESCR_PROPS_CONFIGURATION + case USBDESCR_CONFIG: + usbMsgPtr = (unsigned char *)usbDescriptorConfiguration; + len = sizeof(usbDescriptorConfiguration); + break; +#endif + case USBDESCR_HID: + usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 18); + len = 9; + break; + case USBDESCR_HID_REPORT: + /* interface index */ + switch (rq->wIndex.word) { + case 0: + usbMsgPtr = keyboard_hid_report; + len = sizeof(keyboard_hid_report); + break; + case 1: + usbMsgPtr = mouse_hid_report; + len = sizeof(mouse_hid_report); + break; + } + break; + } + print("desc len: "); phex(len); print("\n"); + return len; +} diff --git a/ps2_vusb/host_vusb.h b/ps2_vusb/host_vusb.h new file mode 100644 index 00000000..c9b1d776 --- /dev/null +++ b/ps2_vusb/host_vusb.h @@ -0,0 +1,7 @@ +#ifndef HOST_VUSB_H +#define HOST_VUSB_H + +void host_vusb_keyboard_send(void); + +#endif + diff --git a/ps2_vusb/keyboard.c b/ps2_vusb/keyboard.c new file mode 100644 index 00000000..95f65887 --- /dev/null +++ b/ps2_vusb/keyboard.c @@ -0,0 +1,79 @@ +#include "usb_keycodes.h" +#include "host.h" +#include "keyboard.h" + +static report_keyboard_t report0; +static report_keyboard_t report1; +static report_keyboard_t *report = &report0; +static report_keyboard_t *report_prev = &report1; + +void keyboard_send(void) +{ + host_keyboard_send(report); +} + +bool keyboard_has_key(void) +{ + for (int i = 0; i < REPORT_KEYS; i++) { + if (report->keys[i]) + return true; + } + return false; +} + +void keyboard_add_mod(uint8_t mod) +{ + report->mods |= mod; +} + +void keyboard_add_key(uint8_t code) +{ + int8_t i = 0; + int8_t empty = -1; + for (; i < REPORT_KEYS; i++) { + if (report_prev->keys[i] == code) { + report->keys[i] = code; + break; + } + if (empty == -1 && report_prev->keys[i] == KB_NO && report->keys[i] == KB_NO) { + empty = i; + } + } + if (i == REPORT_KEYS && empty != -1) { + report->keys[empty] = code; + } +} + +void keyboard_add_code(uint8_t code) +{ + if (IS_MOD(code)) { + keyboard_add_mod(code); + } else { + keyboard_add_key(code); + } +} + +void keyboard_swap_report(void) +{ + report_keyboard_t *tmp = report_prev; + report_prev = report; + report = tmp; +} + +void keyboard_clear_report(void) +{ + report->mods = 0; + for (int8_t i = 0; i < REPORT_KEYS; i++) { + report->keys[i] = 0; + } +} + +report_keyboard_t *keyboard_report(void) +{ + return report; +} + +report_keyboard_t *keyboard_report_prev(void) +{ + return report_prev; +} diff --git a/ps2_vusb/keyboard.h b/ps2_vusb/keyboard.h index 87c61139..bc6b2149 100644 --- a/ps2_vusb/keyboard.h +++ b/ps2_vusb/keyboard.h @@ -1,27 +1,21 @@ #ifndef KEYBOARD_H #define KEYBOARD_H -#include "stdbool.h" +#include +#include +#include "host.h" -#define REPORT_KEYS 6 -typedef struct{ - uint8_t mods; - uint8_t rserved; // not used - uint8_t keys[REPORT_KEYS]; -}report_t; +void keyboard_send(void); +bool keyboard_has_key(void); +void keyboard_add_mod(uint8_t mod); +void keyboard_add_key(uint8_t key); +void keyboard_add_code(uint8_t code); +void keyboard_swap_report(void); +void keyboard_clear_report(void); +report_keyboard_t *keyboard_report(void); +report_keyboard_t *keyboard_report_prev(void); +#endif -//extern report_t *report; -//extern report_t *report_prev; - -report_t *report_get(void); -bool report_has_key(void); -void report_send(void); -void report_add_mod(uint8_t mod); -void report_add_key(uint8_t key); -void report_add_code(uint8_t code); -void report_swap(void); -void report_clear(void); -#endif diff --git a/ps2_vusb/keyboard_vusb.c b/ps2_vusb/keyboard_vusb.c deleted file mode 100644 index 6ea19575..00000000 --- a/ps2_vusb/keyboard_vusb.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "usbdrv.h" -#include "usb_keycodes.h" -#include "keyboard.h" -#include "print.h" - -static report_t report0; -static report_t report1; -static report_t *report = &report0; -static report_t *report_prev = &report1; - -void report_send(void) -{ - if (usbInterruptIsReady()){ - usbSetInterrupt((void *)report, sizeof(*report)); - } -} - -report_t *report_get(void) -{ - return report; -} - -uint8_t report_mods(void) -{ - return report->mods; -} - -uint8_t *report_keys(void) -{ - return report->keys; -} - -bool report_has_key(void) -{ - for (int i = 0; i < REPORT_KEYS; i++) { - if (report->keys[i]) - return true; - } - return false; -} - -void report_add_mod(uint8_t mod) -{ - report->mods |= mod; -} - -void report_add_key(uint8_t code) -{ - int8_t i = 0; - int8_t empty = -1; - for (; i < REPORT_KEYS; i++) { - if (report_prev->keys[i] == code) { - report->keys[i] = code; - break; - } - if (empty == -1 && report_prev->keys[i] == KB_NO && report->keys[i] == KB_NO) { - empty = i; - } - } - if (i == REPORT_KEYS && empty != -1) { - report->keys[empty] = code; - } -} - -void report_add_code(uint8_t code) -{ - if (IS_MOD(code)) { - report_add_mod(code); - } else { - report_add_key(code); - } -} - -void report_swap(void) -{ - report_t *tmp = report_prev; - report_prev = report; - report = tmp; -} - -void report_clear(void) -{ - report->mods = 0; - for (int8_t i = 0; i < REPORT_KEYS; i++) { - report->keys[i] = 0; - } -} - - -static uchar idleRate; /* repeat rate for keyboards, never used for mice */ -usbMsgLen_t usbFunctionSetup(uchar data[8]) -{ -usbRequest_t *rq = (void *)data; - - print("Setup: "); - if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */ - print("CLASS: "); - phex(rq->bRequest); - if(rq->bRequest == USBRQ_HID_GET_REPORT){ - print("GET_REPORT"); - /* we only have one report type, so don't look at wValue */ - usbMsgPtr = (void *)report; - return sizeof(*report); - }else if(rq->bRequest == USBRQ_HID_GET_IDLE){ - print("GET_IDLE: "); - phex(idleRate); - usbMsgPtr = &idleRate; - return 1; - }else if(rq->bRequest == USBRQ_HID_SET_IDLE){ - idleRate = rq->wValue.bytes[1]; - print("SET_IDLE: "); - phex(idleRate); - } - print("\n"); - }else{ - print("VENDOR\n"); - /* no vendor specific requests implemented */ - } - return 0; /* default for not implemented requests: return no data back to host */ -} - - -PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { - 0x05, 0x01, // Usage Page (Generic Desktop), - 0x09, 0x06, // Usage (Keyboard), - 0xA1, 0x01, // Collection (Application), - 0x75, 0x01, // Report Size (1), - 0x95, 0x08, // Report Count (8), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0xE0, // Usage Minimum (224), - 0x29, 0xE7, // Usage Maximum (231), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte - 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), - 0x19, 0x01, // Usage Minimum (1), - 0x29, 0x05, // Usage Maximum (5), - 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report - 0x95, 0x01, // Report Count (1), - 0x75, 0x03, // Report Size (3), - 0x91, 0x03, // Output (Constant), ;LED report padding - 0x95, 0x06, // Report Count (6), - 0x75, 0x08, // Report Size (8), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0xFF, // Logical Maximum(255), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0x00, // Usage Minimum (0), - 0x29, 0xFF, // Usage Maximum (255), - 0x81, 0x00, // Input (Data, Array), - 0xc0 // End Collection -}; diff --git a/ps2_vusb/layer.c b/ps2_vusb/layer.c index e4132bad..b9ce8ca4 100644 --- a/ps2_vusb/layer.c +++ b/ps2_vusb/layer.c @@ -98,23 +98,23 @@ void layer_switching(uint8_t fn_bits) debug(" -> "); debug_hex(current_layer); debug("\n"); } } else { - if (report_has_key()) { // other keys is pressed + if (keyboard_has_key()) { // other keys is pressed uint8_t _fn_to_send = BIT_SUBT(fn_bits, sent_fn); if (_fn_to_send) { debug("Fn case: 4(send Fn before other key pressed)\n"); // send only Fn key first - report_swap(); - report_clear(); - report_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys - report_add_mod(last_mods); - report_send(); - report_swap(); + keyboard_swap_report(); + keyboard_clear_report(); + keyboard_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys + keyboard_add_mod(last_mods); + keyboard_send(); + keyboard_swap_report(); sent_fn |= _fn_to_send; } } } // add Fn keys to send - //report_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys + //keyboard_add_code(keymap_fn_keycode(fn_bits&sent_fn)); // TODO: do all Fn keys } } else { // Fn state is changed(edge) uint8_t fn_changed = 0; @@ -128,7 +128,7 @@ void layer_switching(uint8_t fn_bits) // pressed Fn if ((fn_changed = BIT_SUBT(fn_bits, last_fn))) { debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); - if (report_has_key()) { + if (keyboard_has_key()) { debug("Fn case: 5(pressed Fn with other key)\n"); sent_fn |= fn_changed; } else if (fn_changed & sent_fn) { // pressed same Fn in a row @@ -149,12 +149,12 @@ void layer_switching(uint8_t fn_bits) if (BIT_SUBT(fn_changed, sent_fn)) { // layer not used && Fn not sent debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n"); // send only Fn key first - report_swap(); - report_clear(); - report_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys - report_add_mod(last_mods); - report_send(); - report_swap(); + keyboard_swap_report(); + keyboard_clear_report(); + keyboard_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys + keyboard_add_mod(last_mods); + keyboard_send(); + keyboard_swap_report(); sent_fn |= fn_changed; } } @@ -165,13 +165,13 @@ void layer_switching(uint8_t fn_bits) } last_fn = fn_bits; - last_mods = report_get()->mods; + last_mods = keyboard_report()->mods; last_timer = timer_read(); } // send Fn keys for (uint8_t i = 0; i < 8; i++) { if ((sent_fn & fn_bits) & (1< #include #include #include /* for sei() */ -#include /* for _delay_ms() */ - #include /* required by usbdrv.h */ +#include /* for _delay_ms() */ #include "usbdrv.h" #include "usart_print.h" /* This is also an example for using debug macros */ -#include "ps2.h" #include "usb_keycodes.h" #include "matrix_skel.h" #include "keymap_skel.h" +#include "mousekey.h" +#include "keyboard.h" #include "layer.h" #include "print.h" #include "debug.h" #include "sendchar.h" -#include "keyboard.h" +#include "host.h" +#include "host_vusb.h" #include "timer.h" -/* ------------------------------------------------------------------------- */ -/* ----------------------------- USB interface ----------------------------- */ -/* ------------------------------------------------------------------------- */ - - - - - int main(void) { -uchar i; - -print_enable = true; -debug_enable = true; -timer_init(); -matrix_init(); - wdt_enable(WDTO_1S); /* Even if you don't use the watchdog, turn it off here. On newer devices, * the status of the watchdog (on/off, period) is PRESERVED OVER RESET! */ + /* RESET status: all port bits are inputs without pull-up. * That's the way we need D+ and D-. Therefore we don't need any * additional hardware initialization. */ odDebugInit(); - DBG1(0x00, 0, 0); /* debug output: main starts */ usbInit(); - usbDeviceDisconnect(); /* enforce re-enumeration, do this while interrupts are disabled! */ - i = 0; + + print_enable = true; + //debug_enable = true; + timer_init(); + matrix_init(); + + /* enforce re-enumeration, do this while interrupts are disabled! */ + usbDeviceDisconnect(); + uint8_t i = 0; while(--i){ /* fake USB disconnect for > 250 ms */ wdt_reset(); _delay_ms(1); @@ -78,49 +60,44 @@ matrix_init(); uint8_t fn_bits = 0; while (1) { /* main event loop */ - DBG1(0x02, 0, 0); /* debug output: main loop iterates */ wdt_reset(); usbPoll(); + host_vusb_keyboard_send(); -/* -static uint8_t code = 0; -code = ps2_host_recv(); -if (code) { - odDebug(0x05, &code, 1); -} -*/ matrix_scan(); - if (matrix_is_modified()) { - //matrix_print(); // too heavy on USART - fn_bits = 0; - report_swap(); - report_clear(); - for (int row = 0; row < matrix_rows(); row++) { - for (int col = 0; col < matrix_cols(); col++) { - if (!matrix_is_on(row, col)) continue; - - uint8_t code = layer_get_keycode(row, col); - if (code == KB_NO) { - // do nothing - } - else if (IS_MOD(code)) { - report_add_mod(MOD_BIT(code)); - } - else if (IS_KEY(code)) { - report_add_key(code); - } - else if (IS_FN(code)) { - fn_bits |= FN_BIT(code); - } - else { - debug("ignore keycode: "); debug_hex(code); debug("\n"); - } + fn_bits = 0; + keyboard_swap_report(); + keyboard_clear_report(); + mousekey_clear_report(); + for (int row = 0; row < matrix_rows(); row++) { + for (int col = 0; col < matrix_cols(); col++) { + if (!matrix_is_on(row, col)) continue; + + uint8_t code = layer_get_keycode(row, col); + if (code == KB_NO) { + // do nothing + } + else if (IS_MOD(code)) { + keyboard_add_mod(MOD_BIT(code)); + } + else if (IS_KEY(code)) { + keyboard_add_key(code); + } + else if (IS_FN(code)) { + fn_bits |= FN_BIT(code); + } + else if (IS_MOUSEKEY(code)) { + mousekey_decode(code); + } + else { + debug("ignore keycode: "); debug_hex(code); debug("\n"); } } } layer_switching(fn_bits); if (matrix_is_modified()) { - report_send(); + keyboard_send(); } + mousekey_send(); } } diff --git a/ps2_vusb/matrix.c b/ps2_vusb/matrix.c index c4647339..bd9b9244 100644 --- a/ps2_vusb/matrix.c +++ b/ps2_vusb/matrix.c @@ -190,8 +190,10 @@ uint8_t matrix_scan(void) } uint8_t code; - while ((code = ps2_host_recv())) { -//debug_hex(code); debug(" "); + code = ps2_host_recv(); + if (code == 0x00) return 0; + //while ((code = ps2_host_recv())) { +//phex(code); print(" "); switch (state) { case INIT: switch (code) { @@ -348,7 +350,8 @@ uint8_t matrix_scan(void) default: state = INIT; } - } + //} +//print("|"); // handle LED indicators /* @@ -463,6 +466,7 @@ static void matrix_make(uint8_t code) if (!matrix_is_on(ROW(code), COL(code))) { matrix[ROW(code)] |= 1< +#include +#include "usb_keycodes.h" +#include "host.h" +#include "timer.h" +#include "print.h" +#include "mousekey.h" + + +static report_mouse_t report; +static report_mouse_t report_prev; + +static uint8_t mousekey_repeat = 0; + + +/* + * TODO: fix acceleration algorithm + * see wikipedia http://en.wikipedia.org/wiki/Mouse_keys + */ +#ifndef MOUSEKEY_DELAY_TIME +# define MOUSEKEY_DELAY_TIME 255 +#endif + + +static inline uint8_t move_unit(void) +{ + uint8_t unit = (10 + (mousekey_repeat)); + return unit > 127 ? 127 : unit; +} + +void mousekey_decode(uint8_t code) +{ + if (code == KB_MS_UP) report.y -= move_unit(); + else if (code == KB_MS_DOWN) report.y += move_unit(); + else if (code == KB_MS_LEFT) report.x -= move_unit(); + else if (code == KB_MS_RIGHT) report.x += move_unit(); + else if (code == KB_MS_BTN1) report.buttons |= MOUSE_BTN1; + else if (code == KB_MS_BTN2) report.buttons |= MOUSE_BTN2; + else if (code == KB_MS_BTN3) report.buttons |= MOUSE_BTN3; +/* + else if (code == KB_MS_BTN4) report.buttons |= MOUSE_BTN4; + else if (code == KB_MS_BTN5) report.buttons |= MOUSE_BTN5; + else if (code == KB_MS_WH_UP) report.v += 1; + else if (code == KB_MS_WH_DOWN) report.v -= 1; + else if (code == KB_MS_WH_LEFT) report.h -= 1; + else if (code == KB_MS_WH_RIGHT)report.h += 1; +*/ +} + +bool mousekey_changed(void) +{ + return (report.buttons != report_prev.buttons || + report.x != report_prev.x || + report.y != report_prev.y || + report.x || report.y); + //return (report.buttons != report_prev.buttons || report.x || report.y); +} + +void mousekey_send(void) +{ + static uint16_t last_timer = 0; + + if (!mousekey_changed()) { + mousekey_repeat = 0; + return; + } + + // send immediately when buttun state is changed + if (report.buttons == report_prev.buttons) { + // TODO: delay parameter setting + if ((timer_elapsed(last_timer) < (mousekey_repeat == 1 ? 20 : 5))) { + return; + } + } + + if (report.x && report.y) { + report.x *= 0.7; + report.y *= 0.7; + } + + /* + print("mousekey_repeat: "); phex(mousekey_repeat); print("\n"); + print("timer: "); phex16(timer_read()); print("\n"); + print("last_timer: "); phex16(last_timer); print("\n"); + print("mousekey: "); phex(report.buttons); print(" "); phex(report.x); print(" "); phex(report.y); print("\n"); + */ + + host_mouse_send(&report); + report_prev.buttons = report.buttons; + report_prev.x = report.x; + report_prev.y = report.y; + if (mousekey_repeat != 0xFF) mousekey_repeat++; + last_timer = timer_read(); + mousekey_clear_report(); +} + +void mousekey_clear_report(void) +{ + report.buttons = 0; + report.x = 0; + report.y = 0; +} diff --git a/ps2_vusb/mousekey.h b/ps2_vusb/mousekey.h new file mode 100644 index 00000000..ea9b4f27 --- /dev/null +++ b/ps2_vusb/mousekey.h @@ -0,0 +1,12 @@ +#ifndef MOUSEKEY_H +#define MOUSEKEY_H + +#include +#include "host.h" + +void mousekey_decode(uint8_t code); +bool mousekey_changed(void); +void mousekey_send(void); +void mousekey_clear_report(void); + +#endif diff --git a/ps2_vusb/usbconfig.h b/ps2_vusb/usbconfig.h index 12bf1d53..84fc6fd3 100644 --- a/ps2_vusb/usbconfig.h +++ b/ps2_vusb/usbconfig.h @@ -77,7 +77,7 @@ section at the end of this file). * default control endpoint 0 and an interrupt-in endpoint (any other endpoint * number). */ -#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0 +#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1 /* Define this to 1 if you want to compile a version with three endpoints: The * default control endpoint 0, an interrupt-in endpoint 3 (or the number * configured below) and a catch-all default interrupt-in endpoint as above. @@ -277,7 +277,7 @@ section at the end of this file). * HID class is 3, no subclass and protocol required (but may be useful!) * CDC class is 2, use subclass 2 and protocol 1 for ACM */ -#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 63 +#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0 /* Define this to the length of the HID report descriptor, if you implement * an HID device. Otherwise don't define it or define it to 0. * If you use this define, you must add a PROGMEM character array named @@ -343,14 +343,17 @@ section at the end of this file). */ #define USB_CFG_DESCR_PROPS_DEVICE 0 -#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 +#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC +//#define USB_CFG_DESCR_PROPS_CONFIGURATION 0 #define USB_CFG_DESCR_PROPS_STRINGS 0 #define USB_CFG_DESCR_PROPS_STRING_0 0 #define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 #define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0 +//#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC #define USB_CFG_DESCR_PROPS_HID 0 -#define USB_CFG_DESCR_PROPS_HID_REPORT 0 +#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC +//#define USB_CFG_DESCR_PROPS_HID_REPORT 0 #define USB_CFG_DESCR_PROPS_UNKNOWN 0 /* ----------------------- Optional MCU Description ------------------------ */ -- 2.46.2