1
0

added initial support of mousekeys to ps2_vusb

This commit is contained in:
tmk 2011-02-03 13:26:44 +09:00
parent 4f5f1a53d4
commit 0632618d29
14 changed files with 676 additions and 270 deletions

View File

@ -65,7 +65,7 @@ FORMAT = ihex
# Object files directory # Object files directory
# To put object files in current directory, use a dot (.), do NOT make # To put object files in current directory, use a dot (.), do NOT make
# this an empty or blank macro! # this an empty or blank macro!
OBJDIR = . OBJDIR = obj
# Optimization level, can be [0, 1, 2, 3, s]. # Optimization level, can be [0, 1, 2, 3, s].
@ -347,7 +347,7 @@ AR = avr-ar rcs
NM = avr-nm NM = avr-nm
AVRDUDE = avrdude AVRDUDE = avrdude
REMOVE = rm -f REMOVE = rm -f
REMOVEDIR = rm -rf REMOVEDIR = rmdir
COPY = cp COPY = cp
WINSHELL = cmd WINSHELL = cmd
@ -601,7 +601,8 @@ clean_list :
$(REMOVE) $(LST) $(REMOVE) $(LST)
$(REMOVE) $(OBJ:.o=.s) $(REMOVE) $(OBJ:.o=.s)
$(REMOVE) $(OBJ:.o=.i) $(REMOVE) $(OBJ:.o=.i)
$(REMOVEDIR) .dep $(REMOVE) -r .dep
$(REMOVEDIR) $(OBJDIR)
# Create object files directory # Create object files directory

View File

@ -9,11 +9,13 @@ TARGET_DIR = .
# keyboard dependent files # keyboard dependent files
TARGET_SRC = main.c \ TARGET_SRC = main.c \
keyboard_vusb.c \ keyboard.c \
mousekey.c \
layer.c \ layer.c \
keymap.c \ keymap.c \
matrix.c \ matrix.c \
ps2.c \ ps2.c \
host_vusb.c \
print.c \ print.c \
util.c \ util.c \
timer.c \ timer.c \

35
ps2_vusb/host.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef HOST_H
#define HOST_H
#include <stdint.h>
#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

345
ps2_vusb/host_vusb.c Normal file
View File

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

7
ps2_vusb/host_vusb.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef HOST_VUSB_H
#define HOST_VUSB_H
void host_vusb_keyboard_send(void);
#endif

79
ps2_vusb/keyboard.c Normal file
View File

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

View File

@ -1,27 +1,21 @@
#ifndef KEYBOARD_H #ifndef KEYBOARD_H
#define KEYBOARD_H #define KEYBOARD_H
#include "stdbool.h" #include <stdint.h>
#include <stdbool.h>
#include "host.h"
#define REPORT_KEYS 6 void keyboard_send(void);
typedef struct{ bool keyboard_has_key(void);
uint8_t mods; void keyboard_add_mod(uint8_t mod);
uint8_t rserved; // not used void keyboard_add_key(uint8_t key);
uint8_t keys[REPORT_KEYS]; void keyboard_add_code(uint8_t code);
}report_t; void keyboard_swap_report(void);
void keyboard_clear_report(void);
report_keyboard_t *keyboard_report(void);
//extern report_t *report; report_keyboard_t *keyboard_report_prev(void);
//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 #endif

View File

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

View File

@ -98,23 +98,23 @@ void layer_switching(uint8_t fn_bits)
debug(" -> "); debug_hex(current_layer); debug("\n"); debug(" -> "); debug_hex(current_layer); debug("\n");
} }
} else { } 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); uint8_t _fn_to_send = BIT_SUBT(fn_bits, sent_fn);
if (_fn_to_send) { if (_fn_to_send) {
debug("Fn case: 4(send Fn before other key pressed)\n"); debug("Fn case: 4(send Fn before other key pressed)\n");
// send only Fn key first // send only Fn key first
report_swap(); keyboard_swap_report();
report_clear(); keyboard_clear_report();
report_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys keyboard_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys
report_add_mod(last_mods); keyboard_add_mod(last_mods);
report_send(); keyboard_send();
report_swap(); keyboard_swap_report();
sent_fn |= _fn_to_send; sent_fn |= _fn_to_send;
} }
} }
} }
// add Fn keys 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) } else { // Fn state is changed(edge)
uint8_t fn_changed = 0; uint8_t fn_changed = 0;
@ -128,7 +128,7 @@ void layer_switching(uint8_t fn_bits)
// pressed Fn // pressed Fn
if ((fn_changed = BIT_SUBT(fn_bits, last_fn))) { if ((fn_changed = BIT_SUBT(fn_bits, last_fn))) {
debug("fn_changed: "); debug_bin(fn_changed); debug("\n"); 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"); debug("Fn case: 5(pressed Fn with other key)\n");
sent_fn |= fn_changed; sent_fn |= fn_changed;
} else if (fn_changed & sent_fn) { // pressed same Fn in a row } 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 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"); debug("Fn case: 2(send Fn one shot: released Fn during LAYER_SEND_FN_TERM)\n");
// send only Fn key first // send only Fn key first
report_swap(); keyboard_swap_report();
report_clear(); keyboard_clear_report();
report_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys keyboard_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys
report_add_mod(last_mods); keyboard_add_mod(last_mods);
report_send(); keyboard_send();
report_swap(); keyboard_swap_report();
sent_fn |= fn_changed; sent_fn |= fn_changed;
} }
} }
@ -165,13 +165,13 @@ void layer_switching(uint8_t fn_bits)
} }
last_fn = fn_bits; last_fn = fn_bits;
last_mods = report_get()->mods; last_mods = keyboard_report()->mods;
last_timer = timer_read(); last_timer = timer_read();
} }
// send Fn keys // send Fn keys
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
if ((sent_fn & fn_bits) & (1<<i)) { if ((sent_fn & fn_bits) & (1<<i)) {
report_add_code(keymap_fn_keycode(1<<i)); keyboard_add_code(keymap_fn_keycode(1<<i));
} }
} }
} }

View File

@ -7,68 +7,50 @@
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $ * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $
*/ */
/*
This example should run on most AVRs with only little changes. No special
hardware resources except INT0 are used. You may have to change usbconfig.h for
different I/O pins for USB. Please note that USB D+ must be the INT0 pin, or
at least be connected to INT0 as well.
We use VID/PID 0x046D/0xC00E which is taken from a Logitech mouse. Don't
publish any hardware using these IDs! This is for demonstration only!
*/
#include <stdint.h> #include <stdint.h>
#include <avr/io.h> #include <avr/io.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include <avr/interrupt.h> /* for sei() */ #include <avr/interrupt.h> /* for sei() */
#include <util/delay.h> /* for _delay_ms() */
#include <avr/pgmspace.h> /* required by usbdrv.h */ #include <avr/pgmspace.h> /* required by usbdrv.h */
#include <util/delay.h> /* for _delay_ms() */
#include "usbdrv.h" #include "usbdrv.h"
#include "usart_print.h" /* This is also an example for using debug macros */ #include "usart_print.h" /* This is also an example for using debug macros */
#include "ps2.h"
#include "usb_keycodes.h" #include "usb_keycodes.h"
#include "matrix_skel.h" #include "matrix_skel.h"
#include "keymap_skel.h" #include "keymap_skel.h"
#include "mousekey.h"
#include "keyboard.h"
#include "layer.h" #include "layer.h"
#include "print.h" #include "print.h"
#include "debug.h" #include "debug.h"
#include "sendchar.h" #include "sendchar.h"
#include "keyboard.h" #include "host.h"
#include "host_vusb.h"
#include "timer.h" #include "timer.h"
/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */
int main(void) int main(void)
{ {
uchar i;
print_enable = true;
debug_enable = true;
timer_init();
matrix_init();
wdt_enable(WDTO_1S); wdt_enable(WDTO_1S);
/* Even if you don't use the watchdog, turn it off here. On newer devices, /* 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! * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
*/ */
/* RESET status: all port bits are inputs without pull-up. /* 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 * That's the way we need D+ and D-. Therefore we don't need any
* additional hardware initialization. * additional hardware initialization.
*/ */
odDebugInit(); odDebugInit();
DBG1(0x00, 0, 0); /* debug output: main starts */
usbInit(); 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 */ while(--i){ /* fake USB disconnect for > 250 ms */
wdt_reset(); wdt_reset();
_delay_ms(1); _delay_ms(1);
@ -78,23 +60,15 @@ matrix_init();
uint8_t fn_bits = 0; uint8_t fn_bits = 0;
while (1) { /* main event loop */ while (1) { /* main event loop */
DBG1(0x02, 0, 0); /* debug output: main loop iterates */
wdt_reset(); wdt_reset();
usbPoll(); usbPoll();
host_vusb_keyboard_send();
/*
static uint8_t code = 0;
code = ps2_host_recv();
if (code) {
odDebug(0x05, &code, 1);
}
*/
matrix_scan(); matrix_scan();
if (matrix_is_modified()) {
//matrix_print(); // too heavy on USART
fn_bits = 0; fn_bits = 0;
report_swap(); keyboard_swap_report();
report_clear(); keyboard_clear_report();
mousekey_clear_report();
for (int row = 0; row < matrix_rows(); row++) { for (int row = 0; row < matrix_rows(); row++) {
for (int col = 0; col < matrix_cols(); col++) { for (int col = 0; col < matrix_cols(); col++) {
if (!matrix_is_on(row, col)) continue; if (!matrix_is_on(row, col)) continue;
@ -104,23 +78,26 @@ if (code) {
// do nothing // do nothing
} }
else if (IS_MOD(code)) { else if (IS_MOD(code)) {
report_add_mod(MOD_BIT(code)); keyboard_add_mod(MOD_BIT(code));
} }
else if (IS_KEY(code)) { else if (IS_KEY(code)) {
report_add_key(code); keyboard_add_key(code);
} }
else if (IS_FN(code)) { else if (IS_FN(code)) {
fn_bits |= FN_BIT(code); fn_bits |= FN_BIT(code);
} }
else if (IS_MOUSEKEY(code)) {
mousekey_decode(code);
}
else { else {
debug("ignore keycode: "); debug_hex(code); debug("\n"); debug("ignore keycode: "); debug_hex(code); debug("\n");
} }
} }
} }
}
layer_switching(fn_bits); layer_switching(fn_bits);
if (matrix_is_modified()) { if (matrix_is_modified()) {
report_send(); keyboard_send();
} }
mousekey_send();
} }
} }

View File

@ -190,8 +190,10 @@ uint8_t matrix_scan(void)
} }
uint8_t code; uint8_t code;
while ((code = ps2_host_recv())) { code = ps2_host_recv();
//debug_hex(code); debug(" "); if (code == 0x00) return 0;
//while ((code = ps2_host_recv())) {
//phex(code); print(" ");
switch (state) { switch (state) {
case INIT: case INIT:
switch (code) { switch (code) {
@ -348,7 +350,8 @@ uint8_t matrix_scan(void)
default: default:
state = INIT; state = INIT;
} }
} //}
//print("|");
// handle LED indicators // handle LED indicators
/* /*
@ -463,6 +466,7 @@ static void matrix_make(uint8_t code)
if (!matrix_is_on(ROW(code), COL(code))) { if (!matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] |= 1<<COL(code); matrix[ROW(code)] |= 1<<COL(code);
is_modified = true; is_modified = true;
//print("matrix_make: "); phex(code); print("\n");
} }
} }
@ -472,6 +476,7 @@ static void matrix_break(uint8_t code)
if (matrix_is_on(ROW(code), COL(code))) { if (matrix_is_on(ROW(code), COL(code))) {
matrix[ROW(code)] &= ~(1<<COL(code)); matrix[ROW(code)] &= ~(1<<COL(code));
is_modified = true; is_modified = true;
//print("matrix_break: "); phex(code); print("\n");
} }
} }

102
ps2_vusb/mousekey.c Normal file
View File

@ -0,0 +1,102 @@
#include <stdint.h>
#include <util/delay.h>
#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;
}

12
ps2_vusb/mousekey.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef MOUSEKEY_H
#define MOUSEKEY_H
#include <stdbool.h>
#include "host.h"
void mousekey_decode(uint8_t code);
bool mousekey_changed(void);
void mousekey_send(void);
void mousekey_clear_report(void);
#endif

View File

@ -77,7 +77,7 @@ section at the end of this file).
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint * default control endpoint 0 and an interrupt-in endpoint (any other endpoint
* number). * 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 /* 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 * default control endpoint 0, an interrupt-in endpoint 3 (or the number
* configured below) and a catch-all default interrupt-in endpoint as above. * 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!) * 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 * 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 /* 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. * 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 * 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_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_STRINGS 0
#define USB_CFG_DESCR_PROPS_STRING_0 0 #define USB_CFG_DESCR_PROPS_STRING_0 0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0 #define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0 #define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 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 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 #define USB_CFG_DESCR_PROPS_UNKNOWN 0
/* ----------------------- Optional MCU Description ------------------------ */ /* ----------------------- Optional MCU Description ------------------------ */