mirror of
https://github.com/qmk/qmk_firmware
synced 2024-11-10 14:10:04 +00:00
Added PS/2 multimeda key support.
HID Consumer page and System control are also supported now. merged mediakey branch: d53a356cd2011b461843a5c7c1527a61692893c1
This commit is contained in:
parent
af85b6bba6
commit
6d45e05ede
10 changed files with 447 additions and 350 deletions
37
host.h
37
host.h
|
@ -7,7 +7,7 @@
|
|||
/* report id */
|
||||
#define REPORT_ID_MOUSE 1
|
||||
#define REPORT_ID_SYSTEM 2
|
||||
#define REPORT_ID_AUDIO 3
|
||||
#define REPORT_ID_CONSUMER 3
|
||||
|
||||
/* keyboard Modifiers in boot protocol report */
|
||||
#define BIT_LCTRL (1<<0)
|
||||
|
@ -30,15 +30,30 @@
|
|||
#define MOUSE_BTN4 (1<<3)
|
||||
#define MOUSE_BTN5 (1<<4)
|
||||
|
||||
// Consumer Page(0x0C) Consumer Control(0x01)
|
||||
#define AUDIO_VOL_UP (1<<0)
|
||||
#define AUDIO_VOL_DOWN (1<<1)
|
||||
#define AUDIO_MUTE (1<<2)
|
||||
// Consumer Page(0x0C)
|
||||
#define AUDIO_MUTE 0x00E2
|
||||
#define AUDIO_VOL_UP 0x00E9
|
||||
#define AUDIO_VOL_DOWN 0x00EA
|
||||
#define TRANSPORT_NEXT_TRACK 0x00B5
|
||||
#define TRANSPORT_PREV_TRACK 0x00B6
|
||||
#define TRANSPORT_STOP 0x00B7
|
||||
#define TRANSPORT_PLAY_PAUSE 0x00CD
|
||||
#define AL_CC_CONFIG 0x0183
|
||||
#define AL_EMAIL 0x018A
|
||||
#define AL_CALCULATOR 0x0192
|
||||
#define AL_LOCAL_BROWSER 0x0194
|
||||
#define AC_SEARCH 0x0221
|
||||
#define AC_HOME 0x0223
|
||||
#define AC_BACK 0x0224
|
||||
#define AC_FORWARD 0x0225
|
||||
#define AC_STOP 0x0226
|
||||
#define AC_REFRESH 0x0227
|
||||
#define AC_BOOKMARKS 0x022A
|
||||
|
||||
// Generic Desktop Page(0x01) System Control(0x80)
|
||||
#define SYSTEM_POWER_DOWN (1<<0)
|
||||
#define SYSTEM_SLEEP (1<<1)
|
||||
#define SYSTEM_WAKE_UP (1<<2)
|
||||
// Generic Desktop Page(0x01)
|
||||
#define SYSTEM_POWER_DOWN 0x0081
|
||||
#define SYSTEM_SLEEP 0x0082
|
||||
#define SYSTEM_WAKE_UP 0x0083
|
||||
|
||||
|
||||
#if defined(HOST_PJRC)
|
||||
|
@ -94,8 +109,8 @@ void host_send_keyboard_report(void);
|
|||
void host_mouse_send(report_mouse_t *report);
|
||||
#endif
|
||||
#ifdef USB_EXTRA_ENABLE
|
||||
void host_system_send(uint8_t data);
|
||||
void host_audio_send(uint8_t data);
|
||||
void host_system_send(uint16_t data);
|
||||
void host_consumer_send(uint16_t data);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
74
keyboard.c
74
keyboard.c
|
@ -31,6 +31,9 @@ void keyboard_init(void)
|
|||
void keyboard_proc(void)
|
||||
{
|
||||
uint8_t fn_bits = 0;
|
||||
#ifdef USB_EXTRA_ENABLE
|
||||
uint16_t consumer_code = 0;
|
||||
#endif
|
||||
|
||||
matrix_scan();
|
||||
|
||||
|
@ -64,20 +67,8 @@ void keyboard_proc(void)
|
|||
fn_bits |= FN_BIT(code);
|
||||
}
|
||||
#ifdef USB_EXTRA_ENABLE
|
||||
// audio control & system control
|
||||
else if (code == KB_MUTE) {
|
||||
host_audio_send(AUDIO_MUTE);
|
||||
_delay_ms(500);
|
||||
host_audio_send(0);
|
||||
} else if (code == KB_VOLU) {
|
||||
host_audio_send(AUDIO_VOL_UP);
|
||||
_delay_ms(200);
|
||||
host_audio_send(0);
|
||||
} else if (code == KB_VOLD) {
|
||||
host_audio_send(AUDIO_VOL_DOWN);
|
||||
_delay_ms(200);
|
||||
host_audio_send(0);
|
||||
} else if (code == KB_PWR) {
|
||||
// System Control
|
||||
else if (code == KB_SYSTEM_POWER) {
|
||||
#ifdef HOST_PJRC
|
||||
if (suspend && remote_wakeup) {
|
||||
usb_remote_wakeup();
|
||||
|
@ -87,7 +78,57 @@ void keyboard_proc(void)
|
|||
#else
|
||||
host_system_send(SYSTEM_POWER_DOWN);
|
||||
#endif
|
||||
_delay_ms(1000);
|
||||
host_system_send(0);
|
||||
_delay_ms(500);
|
||||
} else if (code == KB_SYSTEM_SLEEP) {
|
||||
host_system_send(SYSTEM_SLEEP);
|
||||
host_system_send(0);
|
||||
_delay_ms(500);
|
||||
} else if (code == KB_SYSTEM_WAKE) {
|
||||
host_system_send(SYSTEM_WAKE_UP);
|
||||
host_system_send(0);
|
||||
_delay_ms(500);
|
||||
}
|
||||
// Consumer Page
|
||||
else if (code == KB_AUDIO_MUTE) {
|
||||
consumer_code = AUDIO_MUTE;
|
||||
} else if (code == KB_AUDIO_VOL_UP) {
|
||||
consumer_code = AUDIO_VOL_UP;
|
||||
} else if (code == KB_AUDIO_VOL_DOWN) {
|
||||
consumer_code = AUDIO_VOL_DOWN;
|
||||
}
|
||||
else if (code == KB_MEDIA_NEXT_TRACK) {
|
||||
consumer_code = TRANSPORT_NEXT_TRACK;
|
||||
} else if (code == KB_MEDIA_PREV_TRACK) {
|
||||
consumer_code = TRANSPORT_PREV_TRACK;
|
||||
} else if (code == KB_MEDIA_STOP) {
|
||||
consumer_code = TRANSPORT_STOP;
|
||||
} else if (code == KB_MEDIA_PLAY_PAUSE) {
|
||||
consumer_code = TRANSPORT_PLAY_PAUSE;
|
||||
} else if (code == KB_MEDIA_SELECT) {
|
||||
consumer_code = AL_CC_CONFIG;
|
||||
}
|
||||
else if (code == KB_MAIL) {
|
||||
consumer_code = AL_EMAIL;
|
||||
} else if (code == KB_CALCULATOR) {
|
||||
consumer_code = AL_CALCULATOR;
|
||||
} else if (code == KB_MY_COMPUTER) {
|
||||
consumer_code = AL_LOCAL_BROWSER;
|
||||
}
|
||||
else if (code == KB_WWW_SEARCH) {
|
||||
consumer_code = AC_SEARCH;
|
||||
} else if (code == KB_WWW_HOME) {
|
||||
consumer_code = AC_HOME;
|
||||
} else if (code == KB_WWW_BACK) {
|
||||
consumer_code = AC_BACK;
|
||||
} else if (code == KB_WWW_FORWARD) {
|
||||
consumer_code = AC_FORWARD;
|
||||
} else if (code == KB_WWW_STOP) {
|
||||
consumer_code = AC_STOP;
|
||||
} else if (code == KB_WWW_REFRESH) {
|
||||
consumer_code = AC_REFRESH;
|
||||
} else if (code == KB_WWW_FAVORITES) {
|
||||
consumer_code = AC_BOOKMARKS;
|
||||
}
|
||||
#endif
|
||||
else if (IS_KEY(code)) {
|
||||
|
@ -113,6 +154,9 @@ void keyboard_proc(void)
|
|||
// TODO: should send only when changed from last report
|
||||
if (matrix_is_modified()) {
|
||||
host_send_keyboard_report();
|
||||
#ifdef USB_EXTRA_ENABLE
|
||||
host_consumer_send(consumer_code);
|
||||
#endif
|
||||
#ifdef DEBUG_LED
|
||||
// LED flash for debug
|
||||
DEBUG_LED_CONFIG;
|
||||
|
|
10
pjrc/host.c
10
pjrc/host.c
|
@ -117,14 +117,18 @@ void host_mouse_send(report_mouse_t *report)
|
|||
#endif
|
||||
|
||||
#ifdef USB_EXTRA_ENABLE
|
||||
void host_system_send(uint8_t data)
|
||||
void host_system_send(uint16_t data)
|
||||
{
|
||||
usb_extra_system_send(data);
|
||||
}
|
||||
|
||||
void host_audio_send(uint8_t data)
|
||||
void host_consumer_send(uint16_t data)
|
||||
{
|
||||
usb_extra_audio_send(data);
|
||||
static uint16_t last_data = 0;
|
||||
if (data == last_data) return;
|
||||
last_data = data;
|
||||
|
||||
usb_extra_consumer_send(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
169
pjrc/usb.c
Executable file → Normal file
169
pjrc/usb.c
Executable file → Normal file
|
@ -219,76 +219,53 @@ static uint8_t PROGMEM keyboard2_hid_report_desc[] = {
|
|||
// http://www.keil.com/forum/15671/
|
||||
// http://www.microsoft.com/whdc/device/input/wheel.mspx
|
||||
static uint8_t PROGMEM mouse_hid_report_desc[] = {
|
||||
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
|
||||
/* mouse */
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
//0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
|
||||
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)
|
||||
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)
|
||||
// ---------------------------- 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)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
// ---------------------------- 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)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0, // END_COLLECTION
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -309,38 +286,32 @@ static uint8_t PROGMEM debug_hid_report_desc[] = {
|
|||
// audio controls & system controls
|
||||
// http://www.microsoft.com/whdc/archive/w2kbd.mspx
|
||||
static uint8_t PROGMEM extra_hid_report_desc[] = {
|
||||
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
|
||||
0x09, 0x01, // USAGE (Consumer Control)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x01, // REPORT_ID (1)
|
||||
0x09, 0xe9, // USAGE (Volume Up)
|
||||
0x09, 0xea, // USAGE (Volume Down)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x95, 0x02, // REPORT_COUNT (2)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x09, 0xe2, // USAGE (Mute)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0x95, 0x05, // REPORT_COUNT (5)
|
||||
0x81, 0x07, // INPUT (Cnst,Var,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
|
||||
/* system control */
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x80, // USAGE (System Control)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x02, // REPORT_ID (2)
|
||||
0x19, 0x81, // USAGE_MINIMUM (System Power Down)
|
||||
0x29, 0x83, // USAGE_MAXIMUM (System Wake Up)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0x95, 0x05, // REPORT_COUNT (5)
|
||||
0x81, 0x07, // INPUT (Cnst,Var,Rel)
|
||||
0xc0 // END_COLLECTION
|
||||
0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
|
||||
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
|
||||
0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
|
||||
0x19, 0x01, // USAGE_MINIMUM (0x1)
|
||||
0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
|
||||
0x75, 0x10, // REPORT_SIZE (16)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x00, // INPUT (Data,Array,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
/* consumer */
|
||||
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
|
||||
0x09, 0x01, // USAGE (Consumer Control)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
|
||||
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
|
||||
0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
|
||||
0x19, 0x01, // USAGE_MINIMUM (0x1)
|
||||
0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
|
||||
0x75, 0x10, // REPORT_SIZE (16)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x00, // INPUT (Data,Array,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "host.h"
|
||||
#include "usb_extra.h"
|
||||
|
||||
|
||||
int8_t usb_extra_send(uint8_t report_id, uint8_t bits)
|
||||
int8_t usb_extra_send(uint8_t report_id, uint16_t data)
|
||||
{
|
||||
uint8_t intr_state, timeout;
|
||||
|
||||
|
@ -26,19 +28,20 @@ int8_t usb_extra_send(uint8_t report_id, uint8_t bits)
|
|||
}
|
||||
|
||||
UEDATX = report_id;
|
||||
UEDATX = bits;
|
||||
UEDATX = data&0xFF;
|
||||
UEDATX = (data>>8)&0xFF;
|
||||
|
||||
UEINTX = 0x3A;
|
||||
SREG = intr_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t usb_extra_audio_send(uint8_t bits)
|
||||
int8_t usb_extra_consumer_send(uint16_t bits)
|
||||
{
|
||||
return usb_extra_send(1, bits);
|
||||
return usb_extra_send(REPORT_ID_CONSUMER, bits);
|
||||
}
|
||||
|
||||
int8_t usb_extra_system_send(uint8_t bits)
|
||||
int8_t usb_extra_system_send(uint16_t bits)
|
||||
{
|
||||
return usb_extra_send(2, bits);
|
||||
return usb_extra_send(REPORT_ID_SYSTEM, bits);
|
||||
}
|
||||
|
|
|
@ -13,22 +13,11 @@
|
|||
|
||||
#define EXTRA_INTERFACE 3
|
||||
#define EXTRA_ENDPOINT 4
|
||||
#define EXTRA_SIZE 2
|
||||
#define EXTRA_SIZE 8
|
||||
#define EXTRA_BUFFER EP_DOUBLE_BUFFER
|
||||
|
||||
|
||||
// Consumer Page(0x0C) Consumer Control(0x01)
|
||||
#define AUDIO_VOL_UP (1<<0)
|
||||
#define AUDIO_VOL_DOWN (1<<1)
|
||||
#define AUDIO_MUTE (1<<2)
|
||||
|
||||
// Generic Desktop Page(0x01) System Control(0x80)
|
||||
#define SYSTEM_POWER_DOWN (1<<0)
|
||||
#define SYSTEM_SLEEP (1<<1)
|
||||
#define SYSTEM_WAKE_UP (1<<2)
|
||||
|
||||
|
||||
int8_t usb_extra_audio_send(uint8_t bits);
|
||||
int8_t usb_extra_system_send(uint8_t bits);
|
||||
int8_t usb_extra_consumer_send(uint16_t bits);
|
||||
int8_t usb_extra_system_send(uint16_t bits);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -133,4 +133,34 @@ needs a bit of your effort at this time.
|
|||
),
|
||||
|
||||
|
||||
Multimedia keys
|
||||
---------------
|
||||
Following lists PS/2 special keys supported by Windows.
|
||||
http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
|
||||
|
||||
Key PS/2(Set2) HID
|
||||
---------------------------------------------------
|
||||
System Power E0 37 01 0081
|
||||
System Sleep E0 3F 01 0082
|
||||
System Wake E0 5E 01 0083
|
||||
System Mute E0 23 0C 00E2
|
||||
Volume Up E0 32 0C 00E9
|
||||
Volume Down E0 21 0C 00EA
|
||||
Scan Next Track E0 4D 0C 00B5
|
||||
Scan Previous Track E0 15 0C 00B6
|
||||
Stop E0 3B 0C 00B7
|
||||
Play/Pause E0 34 0C 00CD
|
||||
Media Select E0 50 0C 0183
|
||||
Mail E0 48 0C 018A
|
||||
Calculator E0 2B 0C 0192
|
||||
My Computer E0 40 0C 0194
|
||||
WWW Search E0 10 0C 0221
|
||||
WWW Home E0 3A 0C 0223
|
||||
WWW Back E0 38 0C 0224
|
||||
WWW Forward E0 30 0C 0225
|
||||
WWW Stop E0 28 0C 0226
|
||||
WWW Refresh E0 20 0C 0227
|
||||
WWW Favorites E0 18 0C 022A
|
||||
|
||||
|
||||
EOF
|
||||
|
|
|
@ -13,15 +13,23 @@
|
|||
|
||||
#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)]))
|
||||
|
||||
// Convert physical keyboard layout to matrix array.
|
||||
// This is a macro to define keymap easily in keyboard layout form.
|
||||
#define KEYMAP( \
|
||||
K76, K05,K06,K04,K0C, K03,K0B,K83,K0A, K01,K09,K78,K07, KFC,K7E,KFE, KB7,KBF,KDE, \
|
||||
|
||||
// The keymap is a 32*8 matrix which convert a PS/2 scancode into a USB keycode.
|
||||
// See matrix.c for the detail of matrix.
|
||||
#define KEYMAP_ALL( \
|
||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
|
||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
|
||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \
|
||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \
|
||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
|
||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \
|
||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \
|
||||
\
|
||||
KB7, KBF, KDE, /* System Power, Sleep, Wake */ \
|
||||
KA3, KB2, KA1, /* Mute, Volume Up, Volume Down */ \
|
||||
KCD, K95, KBB, KB4, KD0, /* Next, Previous, Stop, Pause, Media Select */ \
|
||||
KC8, KAB, KC0, /* Mail, Calculator, My Computer */ \
|
||||
K90, KBA, KB8, KB0, /* WWW Search, Home, Back, Forward */ \
|
||||
KA8, KA0, K98 /* WWW Stop, Refresh, Favorites */ \
|
||||
) { \
|
||||
{ KB_NO, KB_##K01, KB_NO, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \
|
||||
{ KB_NO, KB_##K09, KB_##K0A, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_NO }, \
|
||||
|
@ -41,15 +49,15 @@
|
|||
{ KB_##K78, KB_##K79, KB_##K7A, KB_##K7B, KB_##K7C, KB_##K7D, KB_##K7E, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_##K83, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_##K91, KB_NO, KB_NO, KB_##K94, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K9F }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KA7 }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KAF }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KB7 }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##KBF }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_##KCA, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_##K90, KB_##K91, KB_NO, KB_NO, KB_##K94, KB_##K95, KB_NO, KB_NO }, \
|
||||
{ KB_##K98, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_##K9F }, \
|
||||
{ KB_##KA0, KB_##KA1, KB_NO, KB_##KA3, KB_NO, KB_NO, KB_NO, KB_##KA7 }, \
|
||||
{ KB_##KA8, KB_NO, KB_NO, KB_##KAB, KB_NO, KB_NO, KB_NO, KB_##KAF }, \
|
||||
{ KB_##KB0, KB_NO, KB_##KB2, KB_NO, KB_##KB4, KB_NO, KB_NO, KB_##KB7 }, \
|
||||
{ KB_##KB8, KB_NO, KB_##KBA, KB_##KBB, KB_NO, KB_NO, KB_NO, KB_##KBF }, \
|
||||
{ KB_##KC0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_##KC8, KB_NO, KB_##KCA, KB_NO, KB_NO, KB_##KCD, KB_NO, KB_NO }, \
|
||||
{ KB_##KD0, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_##KDA, KB_NO, KB_NO, KB_NO, KB_##KDE, KB_NO }, \
|
||||
{ KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO }, \
|
||||
{ KB_NO, KB_##KE9, KB_NO, KB_##KEB, KB_##KEC, KB_NO, KB_NO, KB_NO }, \
|
||||
|
@ -57,6 +65,30 @@
|
|||
{ KB_NO, KB_NO, KB_##KFA, KB_NO, KB_##KFC, KB_##KFD, KB_##KFE, KB_NO }, \
|
||||
}
|
||||
|
||||
#define KEYMAP( \
|
||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
|
||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
|
||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \
|
||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \
|
||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
|
||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA \
|
||||
) \
|
||||
KEYMAP_ALL( \
|
||||
K76,K05,K06,K04,K0C,K03,K0B,K83,K0A,K01,K09,K78,K07, KFC,K7E,KFE, \
|
||||
K0E,K16,K1E,K26,K25,K2E,K36,K3D,K3E,K46,K45,K4E,K55,K66, KF0,KEC,KFD, K77,KCA,K7C,K7B, \
|
||||
K0D,K15,K1D,K24,K2D,K2C,K35,K3C,K43,K44,K4D,K54,K5B,K5D, KF1,KE9,KFA, K6C,K75,K7D, \
|
||||
K58,K1C,K1B,K23,K2B,K34,K33,K3B,K42,K4B,K4C,K52, K5A, K6B,K73,K74,K79, \
|
||||
K12,K1A,K22,K21,K2A,K32,K31,K3A,K41,K49,K4A, K59, KF5, K69,K72,K7A, \
|
||||
K14,K9F,K11, K29, K91,KA7,KAF,K94, KEB,KF2,KF4, K70, K71,KDA, \
|
||||
\
|
||||
SYSTEM_POWER, SYSTEM_SLEEP, SYSTEM_WAKE, \
|
||||
AUDIO_MUTE, AUDIO_VOL_UP, AUDIO_VOL_DOWN, \
|
||||
MEDIA_NEXT_TRACK, MEDIA_PREV_TRACK, MEDIA_STOP, MEDIA_PLAY_PAUSE, MEDIA_SELECT, \
|
||||
MAIL, CALCULATOR, MY_COMPUTER, \
|
||||
WWW_SEARCH, WWW_HOME, WWW_BACK, WWW_FORWARD, \
|
||||
WWW_STOP, WWW_REFRESH, WWW_FAVORITES \
|
||||
)
|
||||
|
||||
|
||||
// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed.
|
||||
static const uint8_t PROGMEM fn_layer[] = {
|
||||
|
@ -102,61 +134,67 @@ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||
*/
|
||||
/* 0: default */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,FN2, S, D, F, G, H, J, K, L, FN0, QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, FN1, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
),
|
||||
|
||||
/* 1: plain Qwerty without layer switching */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
),
|
||||
|
||||
/* 2: Colemak http://colemak.com */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, W, F, P, G, J, L, U, Y, SCLN,LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
BSPC,A, R, S, T, D, H, N, E, I, O, QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, C, V, B, K, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
),
|
||||
|
||||
/* 3: Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
),
|
||||
|
||||
/* 4: Workman http://viralintrospection.wordpress.com/2010/09/06/a-different-philosophy-in-designing-keyboard-layouts/ */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, D, R, W, B, J, F, U, P, SCLN,LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
BSPC,A, S, H, T, G, Y, N, E, O, I, QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, M, C, V, K, L, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
),
|
||||
|
||||
/* 5: Mouse keys */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, WH_L,WH_D,MS_U,WH_U,WH_R,WH_L,WH_D,WH_U,WH_R,NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,FN2, MS_L,MS_D,MS_R,NO, MS_L,MS_D,MS_U,MS_R,FN0, NO, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,VOLD,VOLU,MUTE,BTN2,BTN3,BTN2,BTN1,VOLD,VOLU,MUTE, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, BTN1, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
),
|
||||
|
||||
/* 6: Cursor keys */
|
||||
KEYMAP(
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, PWR, F13, F14,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F8, F10, F11, F12, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, NO, NO, NO, BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,NO, NO, NO, NO, NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, P4, P5, P6, PPLS,
|
||||
|
|
211
usb_keycodes.h
211
usb_keycodes.h
|
@ -1,43 +1,13 @@
|
|||
/*
|
||||
* Key codes from HID Keyboard/Keypad Page
|
||||
* http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
|
||||
*
|
||||
* Based on Keyboard Upgrade v0.3.0 http://github.com/rhomann/kbupgrade
|
||||
*/
|
||||
/*
|
||||
* Keyboard Upgrade -- Firmware for homebrew computer keyboard controllers.
|
||||
* Copyright (C) 2009 Robert Homann
|
||||
*
|
||||
* Based on RUMP (http://mg8.org/rump/), Copyright (C) 2008 Chris Lee
|
||||
*
|
||||
* Based on c64key (http://symlink.dk/projects/c64key/),
|
||||
* Copyright (C) 2006-2007 Mikkel Holm Olsen
|
||||
*
|
||||
* Based on HID-Test by Christian Starkjohann, Objective Development
|
||||
*
|
||||
* This file is part of the Keyboard Upgrade package.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the Keyboard Upgrade package; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef USB_KEYCODES_H
|
||||
#define USB_KEYCODES_H
|
||||
|
||||
|
||||
#define IS_ERROR(code) (KB_ROLL_OVER <= (code) && (code) <= KB_UNDEFINED)
|
||||
#define IS_KEY(code) (KB_A <= (code) && (code) <= KB_KP_HEXADECIMAL)
|
||||
#define IS_KEY(code) (KB_A <= (code) && (code) <= KB_EXSEL)
|
||||
#define IS_MOD(code) (KB_LCTRL <= (code) && (code) <= KB_RGUI)
|
||||
#define IS_FN(code) (KB_FN0 <= (code) && (code) <= KB_FN7)
|
||||
#define IS_MOUSEKEY(code) (KB_MS_UP <= (code) && (code) <= KB_MS_WH_RIGHT)
|
||||
|
@ -49,9 +19,7 @@
|
|||
#define FN_BIT(code) (1<<((code) - KB_FN0))
|
||||
|
||||
|
||||
//
|
||||
// Short names
|
||||
//
|
||||
/* Short names */
|
||||
#define KB_LCTL KB_LCTRL
|
||||
#define KB_RCTL KB_RCTRL
|
||||
#define KB_LSFT KB_LSHIFT
|
||||
|
@ -79,20 +47,17 @@
|
|||
#define KB_SLSH KB_SLASH
|
||||
#define KB_SCLN KB_SCOLON
|
||||
#define KB_QUOT KB_QUOTE
|
||||
#define KB_PWR KB_POWER
|
||||
#define KB_VOLU KB_VOLUP
|
||||
#define KB_VOLD KB_VOLDOWN
|
||||
#define KB_APP KB_APPLICATION
|
||||
#define KB_NUHS KB_NONUS_HASH
|
||||
#define KB_NUBS KB_NONUS_BSLASH
|
||||
// for Japanese
|
||||
/* for Japanese */
|
||||
#define KB_RO KB_INT1
|
||||
#define KB_KANA KB_INT2
|
||||
#define KB_JYEN KB_INT3
|
||||
#define KB_HENK KB_INT4
|
||||
#define KB_MHEN KB_INT5
|
||||
#define KB_ZEHA KB_GRAVE
|
||||
// Keypad
|
||||
/* Keypad */
|
||||
#define KB_P1 KB_KP_1
|
||||
#define KB_P2 KB_KP_2
|
||||
#define KB_P3 KB_KP_3
|
||||
|
@ -110,7 +75,7 @@
|
|||
#define KB_PPLS KB_KP_PLUS
|
||||
#define KB_PEQL KB_KP_EQUAL
|
||||
#define KB_PENT KB_KP_ENTER
|
||||
// Mousekey
|
||||
/* Mousekey */
|
||||
#define KB_MS_U KB_MS_UP
|
||||
#define KB_MS_D KB_MS_DOWN
|
||||
#define KB_MS_L KB_MS_LEFT
|
||||
|
@ -124,8 +89,69 @@
|
|||
#define KB_WH_D KB_MS_WH_DOWN
|
||||
#define KB_WH_L KB_MS_WH_LEFT
|
||||
#define KB_WH_R KB_MS_WH_RIGHT
|
||||
/* Sytem Control & Consumer usage */
|
||||
#define KB_PWR KB_SYSTEM_POWER
|
||||
#define KB_MUTE KB_AUDIO_MUTE
|
||||
#define KB_VOLU KB_AUDIO_VOL_UP
|
||||
#define KB_VOLD KB_AUDIO_VOL_DOWN
|
||||
|
||||
|
||||
/* Special keycode */
|
||||
enum special_keycodes {
|
||||
/* System Control */
|
||||
KB_SYSTEM_POWER = 0xB0,
|
||||
KB_SYSTEM_SLEEP,
|
||||
KB_SYSTEM_WAKE,
|
||||
|
||||
/* Consumer Page */
|
||||
KB_AUDIO_MUTE,
|
||||
KB_AUDIO_VOL_UP,
|
||||
KB_AUDIO_VOL_DOWN,
|
||||
KB_MEDIA_NEXT_TRACK,
|
||||
KB_MEDIA_PREV_TRACK,
|
||||
KB_MEDIA_STOP,
|
||||
KB_MEDIA_PLAY_PAUSE,
|
||||
KB_MEDIA_SELECT,
|
||||
KB_MAIL,
|
||||
KB_CALCULATOR,
|
||||
KB_MY_COMPUTER,
|
||||
KB_WWW_SEARCH,
|
||||
KB_WWW_HOME,
|
||||
KB_WWW_BACK, /* 0xC0 */
|
||||
KB_WWW_FORWARD,
|
||||
KB_WWW_STOP,
|
||||
KB_WWW_REFRESH,
|
||||
KB_WWW_FAVORITES,
|
||||
|
||||
/* reserve 0xE0-E7 for Modifiers */
|
||||
|
||||
/* Layer Switching */
|
||||
KB_FN0 = 0xE8,
|
||||
KB_FN1,
|
||||
KB_FN2,
|
||||
KB_FN3,
|
||||
KB_FN4,
|
||||
KB_FN5,
|
||||
KB_FN6,
|
||||
KB_FN7,
|
||||
|
||||
/* Mousekey */
|
||||
KB_MS_UP = 0xF0,
|
||||
KB_MS_DOWN,
|
||||
KB_MS_LEFT,
|
||||
KB_MS_RIGHT,
|
||||
KB_MS_BTN1,
|
||||
KB_MS_BTN2,
|
||||
KB_MS_BTN3,
|
||||
KB_MS_BTN4,
|
||||
KB_MS_BTN5,
|
||||
/* Mousekey wheel */
|
||||
KB_MS_WH_UP,
|
||||
KB_MS_WH_DOWN,
|
||||
KB_MS_WH_LEFT,
|
||||
KB_MS_WH_RIGHT,
|
||||
};
|
||||
|
||||
enum keycodes {
|
||||
KB_NO = 0,
|
||||
KB_ROLL_OVER,
|
||||
|
@ -143,7 +169,7 @@ enum keycodes {
|
|||
KB_J,
|
||||
KB_K,
|
||||
KB_L,
|
||||
KB_M, /* 0x10 */
|
||||
KB_M, /* 0x10 */
|
||||
KB_N,
|
||||
KB_O,
|
||||
KB_P,
|
||||
|
@ -159,7 +185,7 @@ enum keycodes {
|
|||
KB_Z,
|
||||
KB_1,
|
||||
KB_2,
|
||||
KB_3, /* 0x20 */
|
||||
KB_3, /* 0x20 */
|
||||
KB_4,
|
||||
KB_5,
|
||||
KB_6,
|
||||
|
@ -174,16 +200,16 @@ enum keycodes {
|
|||
KB_SPACE,
|
||||
KB_MINUS,
|
||||
KB_EQUAL,
|
||||
KB_LBRACKET, /* [ */
|
||||
KB_RBRACKET, /* ] */
|
||||
KB_BSLASH, /* \ (and |) */
|
||||
KB_NONUS_HASH, /* Non-US # and ~ */
|
||||
KB_SCOLON, /* ; (and :) */
|
||||
KB_QUOTE, /* ' and " */
|
||||
KB_GRAVE, /* Grave accent and tilde */
|
||||
KB_COMMA, /* , and < */
|
||||
KB_DOT, /* . and > */
|
||||
KB_SLASH, /* / and ? */
|
||||
KB_LBRACKET,
|
||||
KB_RBRACKET, /* 0x30 */
|
||||
KB_BSLASH, /* \ (and |) */
|
||||
KB_NONUS_HASH, /* Non-US # and ~ */
|
||||
KB_SCOLON, /* ; (and :) */
|
||||
KB_QUOTE, /* ' and " */
|
||||
KB_GRAVE, /* Grave accent and tilde */
|
||||
KB_COMMA, /* , and < */
|
||||
KB_DOT, /* . and > */
|
||||
KB_SLASH, /* / and ? */
|
||||
KB_CAPSLOCK,
|
||||
KB_F1,
|
||||
KB_F2,
|
||||
|
@ -191,7 +217,7 @@ enum keycodes {
|
|||
KB_F4,
|
||||
KB_F5,
|
||||
KB_F6,
|
||||
KB_F7, /* 0x40 */
|
||||
KB_F7, /* 0x40 */
|
||||
KB_F8,
|
||||
KB_F9,
|
||||
KB_F10,
|
||||
|
@ -207,7 +233,7 @@ enum keycodes {
|
|||
KB_END,
|
||||
KB_PGDOWN,
|
||||
KB_RIGHT,
|
||||
KB_LEFT, /* 0x50 */
|
||||
KB_LEFT, /* 0x50 */
|
||||
KB_DOWN,
|
||||
KB_UP,
|
||||
KB_NUMLOCK,
|
||||
|
@ -223,11 +249,11 @@ enum keycodes {
|
|||
KB_KP_5,
|
||||
KB_KP_6,
|
||||
KB_KP_7,
|
||||
KB_KP_8, /* 0x60 */
|
||||
KB_KP_8, /* 0x60 */
|
||||
KB_KP_9,
|
||||
KB_KP_0,
|
||||
KB_KP_DOT,
|
||||
KB_NONUS_BSLASH, /* Non-US \ and | */
|
||||
KB_NONUS_BSLASH, /* Non-US \ and | */
|
||||
KB_APPLICATION,
|
||||
KB_POWER,
|
||||
KB_KP_EQUAL,
|
||||
|
@ -239,7 +265,7 @@ enum keycodes {
|
|||
KB_F18,
|
||||
KB_F19,
|
||||
KB_F20,
|
||||
KB_F21, /* 0x70 */
|
||||
KB_F21, /* 0x70 */
|
||||
KB_F22,
|
||||
KB_F23,
|
||||
KB_F24,
|
||||
|
@ -254,14 +280,14 @@ enum keycodes {
|
|||
KB_COPY,
|
||||
KB_PASTE,
|
||||
KB_FIND,
|
||||
KB_MUTE,
|
||||
KB_VOLUP, /* 0x80 */
|
||||
KB_VOLDOWN,
|
||||
KB_LOCKING_CAPS, /* locking Caps Lock */
|
||||
KB_LOCKING_NUM, /* locking Num Lock */
|
||||
KB_LOCKING_SCROLL, /* locking Scroll Lock */
|
||||
KB__MUTE,
|
||||
KB__VOLUP, /* 0x80 */
|
||||
KB__VOLDOWN,
|
||||
KB_LOCKING_CAPS, /* locking Caps Lock */
|
||||
KB_LOCKING_NUM, /* locking Num Lock */
|
||||
KB_LOCKING_SCROLL, /* locking Scroll Lock */
|
||||
KB_KP_COMMA,
|
||||
KB_KP_EQUAL_AS400, /* equal sign on AS/400 */
|
||||
KB_KP_EQUAL_AS400, /* equal sign on AS/400 */
|
||||
KB_INT1,
|
||||
KB_INT2,
|
||||
KB_INT3,
|
||||
|
@ -271,7 +297,7 @@ enum keycodes {
|
|||
KB_INT7,
|
||||
KB_INT8,
|
||||
KB_INT9,
|
||||
KB_LANG1, /* 0x90 */
|
||||
KB_LANG1, /* 0x90 */
|
||||
KB_LANG2,
|
||||
KB_LANG3,
|
||||
KB_LANG4,
|
||||
|
@ -287,12 +313,13 @@ enum keycodes {
|
|||
KB_PRIOR,
|
||||
KB_RETURN,
|
||||
KB_SEPARATOR,
|
||||
KB_OUT,
|
||||
KB_OUT, /* 0xA0 */
|
||||
KB_OPER,
|
||||
KB_CLEAR_AGAIN,
|
||||
KB_CRSEL,
|
||||
KB_EXSEL,
|
||||
|
||||
/* NOTE: uses 0xB0-DF for special keycodes */
|
||||
KB_KP_00 = 0xB0,
|
||||
KB_KP_000,
|
||||
KB_THOUSANDS_SEPARATOR,
|
||||
|
@ -301,15 +328,15 @@ enum keycodes {
|
|||
KB_CURRENCY_SUB_UNIT,
|
||||
KB_KP_LPAREN,
|
||||
KB_KP_RPAREN,
|
||||
KB_KP_LCBRACKET, /* { */
|
||||
KB_KP_RCBRACKET, /* } */
|
||||
KB_KP_LCBRACKET, /* { */
|
||||
KB_KP_RCBRACKET, /* } */
|
||||
KB_KP_TAB,
|
||||
KB_KP_BSPACE,
|
||||
KB_KP_A,
|
||||
KB_KP_B,
|
||||
KB_KP_C,
|
||||
KB_KP_D,
|
||||
KB_KP_E,
|
||||
KB_KP_E, /* 0xC0 */
|
||||
KB_KP_F,
|
||||
KB_KP_XOR,
|
||||
KB_KP_HAT,
|
||||
|
@ -325,7 +352,7 @@ enum keycodes {
|
|||
KB_KP_SPACE,
|
||||
KB_KP_ATMARK,
|
||||
KB_KP_EXCLAMATION,
|
||||
KB_KP_MEM_STORE,
|
||||
KB_KP_MEM_STORE, /* 0xD0 */
|
||||
KB_KP_MEM_RECALL,
|
||||
KB_KP_MEM_CLEAR,
|
||||
KB_KP_MEM_ADD,
|
||||
|
@ -340,41 +367,17 @@ enum keycodes {
|
|||
KB_KP_DECIMAL,
|
||||
KB_KP_HEXADECIMAL,
|
||||
|
||||
/* modifiers */
|
||||
KB_LCTRL = 0xE0, /* 0x01 */
|
||||
KB_LSHIFT, /* 0x02 */
|
||||
KB_LALT, /* 0x04 */
|
||||
KB_LGUI, /* 0x08 */
|
||||
KB_RCTRL, /* 0x10 */
|
||||
KB_RSHIFT, /* 0x20 */
|
||||
KB_RALT, /* 0x40 */
|
||||
KB_RGUI, /* 0x80 */
|
||||
/* Modifiers */
|
||||
KB_LCTRL = 0xE0,
|
||||
KB_LSHIFT,
|
||||
KB_LALT,
|
||||
KB_LGUI,
|
||||
KB_RCTRL,
|
||||
KB_RSHIFT,
|
||||
KB_RALT,
|
||||
KB_RGUI,
|
||||
|
||||
/* extensions for internal use */
|
||||
KB_FN0 = 0xE8,
|
||||
KB_FN1,
|
||||
KB_FN2,
|
||||
KB_FN3,
|
||||
KB_FN4,
|
||||
KB_FN5,
|
||||
KB_FN6,
|
||||
KB_FN7,
|
||||
// Mousekey move
|
||||
KB_MS_UP = 0xF0,
|
||||
KB_MS_DOWN,
|
||||
KB_MS_LEFT,
|
||||
KB_MS_RIGHT,
|
||||
// Mousekey buttons
|
||||
KB_MS_BTN1 = 0xF4,
|
||||
KB_MS_BTN2,
|
||||
KB_MS_BTN3,
|
||||
KB_MS_BTN4,
|
||||
KB_MS_BTN5,
|
||||
// Mousekey wheel
|
||||
KB_MS_WH_UP,
|
||||
KB_MS_WH_DOWN,
|
||||
KB_MS_WH_LEFT,
|
||||
KB_MS_WH_RIGHT,
|
||||
/* NOTE: uses 0xE8-FF for special keycodes */
|
||||
};
|
||||
|
||||
#endif /* USB_KEYCODES_H */
|
||||
|
|
154
vusb/host.c
154
vusb/host.c
|
@ -146,10 +146,12 @@ void host_mouse_send(report_mouse_t *report)
|
|||
#endif
|
||||
|
||||
#ifdef USB_EXTRA_ENABLE
|
||||
void host_system_send(uint8_t data)
|
||||
void host_system_send(uint16_t data)
|
||||
{
|
||||
static uint8_t report[] = { REPORT_ID_SYSTEM, 0 };
|
||||
report[1] = data;
|
||||
// Not need static?
|
||||
static uint8_t report[] = { REPORT_ID_SYSTEM, 0, 0 };
|
||||
report[1] = data&0xFF;
|
||||
report[2] = (data>>8)&0xFF;
|
||||
if (usbInterruptIsReady3()) {
|
||||
usbSetInterrupt3((void *)&report, sizeof(report));
|
||||
} else {
|
||||
|
@ -157,10 +159,16 @@ void host_system_send(uint8_t data)
|
|||
}
|
||||
}
|
||||
|
||||
void host_audio_send(uint8_t data)
|
||||
void host_consumer_send(uint16_t data)
|
||||
{
|
||||
static uint8_t report[] = { REPORT_ID_AUDIO, 0 };
|
||||
report[1] = data;
|
||||
static uint16_t last_data = 0;
|
||||
if (data == last_data) return;
|
||||
last_data = data;
|
||||
|
||||
// Not need static?
|
||||
static uint8_t report[] = { REPORT_ID_CONSUMER, 0, 0 };
|
||||
report[1] = data&0xFF;
|
||||
report[2] = (data>>8)&0xFF;
|
||||
if (usbInterruptIsReady3()) {
|
||||
usbSetInterrupt3((void *)&report, sizeof(report));
|
||||
} else {
|
||||
|
@ -293,85 +301,77 @@ PROGMEM uchar keyboard_hid_report[] = {
|
|||
*/
|
||||
PROGMEM uchar mouse_hid_report[] = {
|
||||
/* mouse */
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x01, // REPORT_ID (1)
|
||||
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)
|
||||
// ---------------------------- 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)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
// ---------------------------- 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)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0, // END_COLLECTION
|
||||
/* system */
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
|
||||
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)
|
||||
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)
|
||||
// ---------------------------- 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)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
// ---------------------------- 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)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0, // END_COLLECTION
|
||||
/* system control */
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x80, // USAGE (System Control)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x02, // REPORT_ID (2)
|
||||
0x19, 0x81, // USAGE_MINIMUM (System Power Down)
|
||||
0x29, 0x83, // USAGE_MAXIMUM (System Wake Up)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0x95, 0x05, // REPORT_COUNT (5)
|
||||
0x81, 0x07, // INPUT (Cnst,Var,Rel)
|
||||
0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
|
||||
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
|
||||
0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
|
||||
0x19, 0x01, // USAGE_MINIMUM (0x1)
|
||||
0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
|
||||
0x75, 0x10, // REPORT_SIZE (16)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x00, // INPUT (Data,Array,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
/* audio */
|
||||
/* consumer */
|
||||
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
|
||||
0x09, 0x01, // USAGE (Consumer Control)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x03, // REPORT_ID (3)
|
||||
0x09, 0xe9, // USAGE (Volume Up)
|
||||
0x09, 0xea, // USAGE (Volume Down)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x95, 0x02, // REPORT_COUNT (2)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x09, 0xe2, // USAGE (Mute)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
|
||||
0x15, 0x01, // LOGICAL_MINIMUM (0x1)
|
||||
0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
|
||||
0x19, 0x01, // USAGE_MINIMUM (0x1)
|
||||
0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
|
||||
0x75, 0x10, // REPORT_SIZE (16)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0x95, 0x05, // REPORT_COUNT (5)
|
||||
0x81, 0x07, // INPUT (Cnst,Var,Abs)
|
||||
0x81, 0x00, // INPUT (Data,Array,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue