# 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]. | ||||
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 | ||||
$(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 |
# 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 \ |
#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 |
#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; | |||||
} |
#ifndef HOST_VUSB_H | |||||
#define HOST_VUSB_H | |||||
void host_vusb_keyboard_send(void); | |||||
#endif | |||||
#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; | |||||
} |
#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 | |||||
typedef struct{ | |||||
uint8_t mods; | |||||
uint8_t rserved; // not used | |||||
uint8_t keys[REPORT_KEYS]; | |||||
}report_t; | |||||
void keyboard_send(void); | |||||
bool keyboard_has_key(void); | |||||
void keyboard_add_mod(uint8_t mod); | |||||
void keyboard_add_key(uint8_t key); | |||||
void keyboard_add_code(uint8_t code); | |||||
void keyboard_swap_report(void); | |||||
void keyboard_clear_report(void); | |||||
report_keyboard_t *keyboard_report(void); | |||||
report_keyboard_t *keyboard_report_prev(void); | |||||
#endif | |||||
//extern report_t *report; | |||||
//extern report_t *report_prev; | |||||
report_t *report_get(void); | |||||
bool report_has_key(void); | |||||
void report_send(void); | |||||
void report_add_mod(uint8_t mod); | |||||
void report_add_key(uint8_t key); | |||||
void report_add_code(uint8_t code); | |||||
void report_swap(void); | |||||
void report_clear(void); | |||||
#endif |
#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 | |||||
}; |
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(); | |||||
report_clear(); | |||||
report_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys | |||||
report_add_mod(last_mods); | |||||
report_send(); | |||||
report_swap(); | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
keyboard_add_code(keymap_fn_keycode(_fn_to_send)); // TODO: do all Fn keys | |||||
keyboard_add_mod(last_mods); | |||||
keyboard_send(); | |||||
keyboard_swap_report(); | |||||
sent_fn |= _fn_to_send; | 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; | ||||
// 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 | ||||
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(); | |||||
report_clear(); | |||||
report_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys | |||||
report_add_mod(last_mods); | |||||
report_send(); | |||||
report_swap(); | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
keyboard_add_code(keymap_fn_keycode(fn_changed)); // TODO: do all Fn keys | |||||
keyboard_add_mod(last_mods); | |||||
keyboard_send(); | |||||
keyboard_swap_report(); | |||||
sent_fn |= fn_changed; | sent_fn |= fn_changed; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
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)); | |||||
} | } | ||||
} | } | ||||
} | } |
* 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); | ||||
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; | |||||
report_swap(); | |||||
report_clear(); | |||||
for (int row = 0; row < matrix_rows(); row++) { | |||||
for (int col = 0; col < matrix_cols(); col++) { | |||||
if (!matrix_is_on(row, col)) continue; | |||||
uint8_t code = layer_get_keycode(row, col); | |||||
if (code == KB_NO) { | |||||
// do nothing | |||||
} | |||||
else if (IS_MOD(code)) { | |||||
report_add_mod(MOD_BIT(code)); | |||||
} | |||||
else if (IS_KEY(code)) { | |||||
report_add_key(code); | |||||
} | |||||
else if (IS_FN(code)) { | |||||
fn_bits |= FN_BIT(code); | |||||
} | |||||
else { | |||||
debug("ignore keycode: "); debug_hex(code); debug("\n"); | |||||
} | |||||
fn_bits = 0; | |||||
keyboard_swap_report(); | |||||
keyboard_clear_report(); | |||||
mousekey_clear_report(); | |||||
for (int row = 0; row < matrix_rows(); row++) { | |||||
for (int col = 0; col < matrix_cols(); col++) { | |||||
if (!matrix_is_on(row, col)) continue; | |||||
uint8_t code = layer_get_keycode(row, col); | |||||
if (code == KB_NO) { | |||||
// do nothing | |||||
} | |||||
else if (IS_MOD(code)) { | |||||
keyboard_add_mod(MOD_BIT(code)); | |||||
} | |||||
else if (IS_KEY(code)) { | |||||
keyboard_add_key(code); | |||||
} | |||||
else if (IS_FN(code)) { | |||||
fn_bits |= FN_BIT(code); | |||||
} | |||||
else if (IS_MOUSEKEY(code)) { | |||||
mousekey_decode(code); | |||||
} | |||||
else { | |||||
debug("ignore keycode: "); debug_hex(code); debug("\n"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
layer_switching(fn_bits); | layer_switching(fn_bits); | ||||
if (matrix_is_modified()) { | if (matrix_is_modified()) { | ||||
report_send(); | |||||
keyboard_send(); | |||||
} | } | ||||
mousekey_send(); | |||||
} | } | ||||
} | } |
} | } | ||||
uint8_t code; | uint8_t code; | ||||
while ((code = ps2_host_recv())) { | |||||
//debug_hex(code); debug(" "); | |||||
code = ps2_host_recv(); | |||||
if (code == 0x00) return 0; | |||||
//while ((code = ps2_host_recv())) { | |||||
//phex(code); print(" "); | |||||
switch (state) { | switch (state) { | ||||
case INIT: | case INIT: | ||||
switch (code) { | switch (code) { | ||||
default: | default: | ||||
state = INIT; | state = INIT; | ||||
} | } | ||||
} | |||||
//} | |||||
//print("|"); | |||||
// handle LED indicators | // handle LED indicators | ||||
/* | /* | ||||
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"); | |||||
} | } | ||||
} | } | ||||
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"); | |||||
} | } | ||||
} | } | ||||
#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; | |||||
} |
#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 |
* 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. | ||||
* 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 | ||||
*/ | */ | ||||
#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 ------------------------ */ |