added initial support of mousekeys to ps2_vusb
parent
4f5f1a53d4
commit
0632618d29
@ -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,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
|
||||
};
|
@ -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
|
Loading…
Reference in New Issue