added initial support of mousekeys to ps2_vusb
parent
4f5f1a53d4
commit
0632618d29
|
@ -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
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef HOST_VUSB_H
|
||||||
|
#define HOST_VUSB_H
|
||||||
|
|
||||||
|
void host_vusb_keyboard_send(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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 ------------------------ */
|
||||||
|
|
Loading…
Reference in New Issue