From eedba5387afb4bfc265913bcf444665d8840f0dd Mon Sep 17 00:00:00 2001 From: "Lukas F. Hartmann" Date: Thu, 25 Aug 2022 16:45:56 +0200 Subject: [PATCH] WIP: keyboard/trackball firmware initial --- .../pocket-hid/CMakeLists.txt | 34 + pocket-reform-keyboard-fw/pocket-hid/build.sh | 10 + pocket-reform-keyboard-fw/pocket-hid/flash.sh | 4 + .../pocket-hid/src/main.c | 678 ++++++++++++++++++ .../pocket-hid/src/matrix.h | 142 ++++ .../pocket-hid/src/tusb_config.h | 106 +++ .../pocket-hid/src/usb_descriptors.c | 295 ++++++++ .../pocket-hid/src/usb_descriptors.h | 37 + .../pocket-hid/src/usb_hid_keys.h | 287 ++++++++ 9 files changed, 1593 insertions(+) create mode 100644 pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt create mode 100755 pocket-reform-keyboard-fw/pocket-hid/build.sh create mode 100755 pocket-reform-keyboard-fw/pocket-hid/flash.sh create mode 100644 pocket-reform-keyboard-fw/pocket-hid/src/main.c create mode 100644 pocket-reform-keyboard-fw/pocket-hid/src/matrix.h create mode 100644 pocket-reform-keyboard-fw/pocket-hid/src/tusb_config.h create mode 100644 pocket-reform-keyboard-fw/pocket-hid/src/usb_descriptors.c create mode 100644 pocket-reform-keyboard-fw/pocket-hid/src/usb_descriptors.h create mode 100644 pocket-reform-keyboard-fw/pocket-hid/src/usb_hid_keys.h diff --git a/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt b/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt new file mode 100644 index 0000000..2e9db5c --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../tinyusb/hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_device_example(${PROJECT}) + +target_link_libraries(${PROJECT} PRIVATE pico_stdlib pico_multicore tinyusb_device tinyusb_board hardware_pwm hardware_i2c) + +target_compile_definitions(${PROJECT} PUBLIC + PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 + ) diff --git a/pocket-reform-keyboard-fw/pocket-hid/build.sh b/pocket-reform-keyboard-fw/pocket-hid/build.sh new file mode 100755 index 0000000..d5f508b --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/build.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +export PICO_SDK_PATH=$(pwd)/../../../pico-sdk + +mkdir -p build +cd build +cmake -DFAMILY=rp2040 .. + +make + diff --git a/pocket-reform-keyboard-fw/pocket-hid/flash.sh b/pocket-reform-keyboard-fw/pocket-hid/flash.sh new file mode 100755 index 0000000..9efed3e --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/flash.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +picotool load build/pocket-hid.uf2 + diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/main.c b/pocket-reform-keyboard-fw/pocket-hid/src/main.c new file mode 100644 index 0000000..baf1a40 --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/main.c @@ -0,0 +1,678 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +#include "pico/stdlib.h" +#include "pico/binary_info.h" +#include "pico/multicore.h" +#include "hardware/gpio.h" +#include "hardware/i2c.h" +#include "hardware/irq.h" + +#include "usb_descriptors.h" + +#define KBD_VARIANT_QWERTY_US +#define KBD_COLS 12 +#define KBD_ROWS 6 +#define KBD_MATRIX_SZ KBD_COLS * KBD_ROWS + 4 + +#include "matrix.h" + +#define PIN_SDA 0 +#define PIN_SCL 1 + +#define PIN_UART_TX 4 +#define PIN_UART_RX 5 + +#define PIN_ROW1 19 +#define PIN_ROW2 20 +#define PIN_ROW3 23 +#define PIN_ROW4 22 +#define PIN_ROW5 21 +#define PIN_ROW6 18 + +#define PIN_COL1 6 +#define PIN_COL2 7 +#define PIN_COL3 8 +#define PIN_COL4 9 +#define PIN_COL5 10 +#define PIN_COL6 11 +#define PIN_COL7 12 +#define PIN_COL8 13 +#define PIN_COL9 14 +#define PIN_COL10 15 +#define PIN_COL11 16 +#define PIN_COL12 17 + +#define PIN_LEDS 24 + +#define ADDR_SENSOR (0x79) + +#define MAX_SCANCODES 6 +static uint8_t pressed_scancodes[MAX_SCANCODES] = {0,0,0,0,0,0}; +static int pressed_keys = 0; + +void hid_task(void); +void led_task(uint32_t rgb); +void led_core(void); + +#define UART_ID uart1 +#define BAUD_RATE 115200 +#define DATA_BITS 8 +#define STOP_BITS 1 +#define PARITY UART_PARITY_NONE + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + tusb_init(); + + uart_init(UART_ID, BAUD_RATE); + uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY); + uart_set_hw_flow(UART_ID, false, false); + uart_set_fifo_enabled(UART_ID, true); + gpio_set_function(PIN_UART_TX, GPIO_FUNC_UART); + gpio_set_function(PIN_UART_RX, GPIO_FUNC_UART); + int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ; + //irq_set_exclusive_handler(UART_IRQ, on_uart_rx); + //irq_set_enabled(UART_IRQ, true); + //uart_set_irq_enables(UART_ID, true, false); // bool rx_has_data, bool tx_needs_data + + gpio_pull_up(PIN_COL1); + gpio_init(PIN_LEDS); + gpio_set_dir(PIN_LEDS, true); // output + + gpio_init(PIN_COL1); + gpio_set_dir(PIN_COL1, false); + gpio_pull_up(PIN_COL1); + gpio_init(PIN_COL2); + gpio_set_dir(PIN_COL2, false); + gpio_pull_up(PIN_COL2); + gpio_init(PIN_COL3); + gpio_set_dir(PIN_COL3, false); + gpio_pull_up(PIN_COL3); + gpio_init(PIN_COL4); + gpio_set_dir(PIN_COL4, false); + gpio_pull_up(PIN_COL4); + gpio_init(PIN_COL5); + gpio_set_dir(PIN_COL5, false); + gpio_pull_up(PIN_COL5); + gpio_init(PIN_COL6); + gpio_set_dir(PIN_COL6, false); + gpio_pull_up(PIN_COL6); + gpio_init(PIN_COL7); + gpio_set_dir(PIN_COL7, false); + gpio_pull_up(PIN_COL7); + gpio_init(PIN_COL8); + gpio_set_dir(PIN_COL8, false); + gpio_pull_up(PIN_COL8); + gpio_init(PIN_COL9); + gpio_set_dir(PIN_COL9, false); + gpio_pull_up(PIN_COL9); + gpio_init(PIN_COL10); + gpio_set_dir(PIN_COL10, false); + gpio_pull_up(PIN_COL10); + gpio_init(PIN_COL11); + gpio_set_dir(PIN_COL11, false); + gpio_pull_up(PIN_COL11); + gpio_init(PIN_COL12); + gpio_set_dir(PIN_COL12, false); + gpio_pull_up(PIN_COL12); + + gpio_init(PIN_ROW1); + gpio_set_dir(PIN_ROW1, true); + gpio_init(PIN_ROW2); + gpio_set_dir(PIN_ROW2, true); + gpio_init(PIN_ROW3); + gpio_set_dir(PIN_ROW3, true); + gpio_init(PIN_ROW4); + gpio_set_dir(PIN_ROW4, true); + gpio_init(PIN_ROW5); + gpio_set_dir(PIN_ROW5, true); + gpio_init(PIN_ROW6); + gpio_set_dir(PIN_ROW6, true); + + i2c_init(i2c0, 100 * 1000); + gpio_set_function(PIN_SDA, GPIO_FUNC_I2C); + gpio_set_function(PIN_SCL, GPIO_FUNC_I2C); + + bi_decl(bi_2pins_with_func(PIN_SDA, PIN_SCL, GPIO_FUNC_I2C)); + + char buf[] = {0x7f, 0x00, 0x00, 0x00}; + i2c_write_blocking(i2c0, ADDR_SENSOR, buf, 2, false); + + buf[0] = 0x05; + buf[1] = 0x01; + i2c_write_blocking(i2c0, ADDR_SENSOR, buf, 2, false); + + //multicore_launch_core1(led_core); + /*for (int i=0; i<10; i++) { + led_task(0x000000); + }*/ + + led_task(0xffff00); + + while (1) { + pressed_keys = process_keyboard(pressed_scancodes); + tud_task(); // tinyusb device task + hid_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ +} + +// RGB LEDS + +int __attribute__((optimize("Os"))) delay300ns() { + // ~300ns + asm volatile( + "mov r0, #6\n" // 1 cycle (was 10) + "loop1: sub r0, r0, #1\n" // 1 cycle + "bne loop1\n" // 2 cycles if loop taken, 1 if not + ); + return 0; +} + +//--------------------------------------------------------------------+ +// USB HID +//--------------------------------------------------------------------+ + +typedef struct TU_ATTR_PACKED +{ + uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */ + int8_t x; /**< Current delta x movement of the mouse. */ + int8_t y; /**< Current delta y movement on the mouse. */ + int8_t wheel; /**< Current delta wheel movement on the mouse. */ + int8_t pan; // using AC Pan +} hid_trackball_report_t; + +bool tud_hid_trackball_report(uint8_t report_id, + uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) +{ + hid_trackball_report_t report = + { + .buttons = buttons, + .x = x, + .y = y, + .wheel = vertical, + .pan = horizontal + }; + + return tud_hid_report(report_id, &report, sizeof(report)); +} + +uint8_t matrix_debounce[KBD_COLS*KBD_ROWS]; +uint8_t matrix_state[KBD_COLS*KBD_ROWS]; +int active_meta_mode = 0; +uint8_t last_meta_key = 0; +uint8_t* active_matrix = matrix; +bool media_toggle = 0; +bool fn_key = 0; // Am I holding FN? +bool circle = 0; // Am I holding circle? + +int command_sent = 0; + +int process_keyboard(uint8_t* resulting_scancodes) { + // how many keys are pressed this round + uint8_t total_pressed = 0; + uint8_t used_key_codes = 0; + + for (int i=0; i 0) { + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, pressed_scancodes); + //} else { + // send empty key report if previously has key pressed + //if (prev_num_keys) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + //} + prev_num_keys = pressed_keys; + } + break; + + case REPORT_ID_MOUSE: + { + int8_t const delta = 5; + int8_t buf[] = {0x7f, 0x00, 0x00, 0x00}; + + // no button, right + down, no scroll, no pan + //tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); + + buf[0] = 0x02; + i2c_write_blocking(i2c0, ADDR_SENSOR, buf, 1, true); + i2c_read_blocking(i2c0, ADDR_SENSOR, buf, 1, false); + + int btn3 = matrix_state[KBD_COLS*5+3]>0; + int btn1 = matrix_state[KBD_COLS*5+4]>0; + int btn2 = matrix_state[KBD_COLS*5+7]>0; + int btn4 = matrix_state[KBD_COLS*5+8]>0; + + uint8_t buttons = btn1 | (btn2<<1) | (btn4<<2); + + if (buf[0] & 0xf0) { + buf[0] = 0x03; + i2c_write_blocking(i2c0, ADDR_SENSOR, buf, 1, true); + i2c_read_blocking(i2c0, ADDR_SENSOR, buf, 2, false); + + int8_t nx = buf[0]; + int8_t ny = buf[1]; + + // no button, right + down, no scroll pan + if (btn3 || scroll_toggle) { + tud_hid_mouse_report(REPORT_ID_MOUSE, buttons, 0, 0, 2*ny, -2*nx); + } else { + tud_hid_mouse_report(REPORT_ID_MOUSE, buttons, -2*nx, -2*ny, 0, 0); + } + } else { + //if (buttons != prev_buttons) { + tud_hid_mouse_report(REPORT_ID_MOUSE, buttons, 0, 0, 0, 0); + //} + } + + prev_buttons = buttons; + } + break; + + case REPORT_ID_CONSUMER_CONTROL: + { + // use to avoid send multiple consecutive zero report + /*static bool has_consumer_key = false; + + if ( btn ) + { + // volume down + uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; + tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); + has_consumer_key = true; + }else + { + // send empty key report (release key) if previously has key pressed + uint16_t empty_key = 0; + if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + has_consumer_key = false; + }*/ + } + break; + + case REPORT_ID_GAMEPAD: + { + // use to avoid send multiple consecutive zero report for keyboard + /*static bool has_gamepad_key = false; + + hid_gamepad_report_t report = + { + .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, + .hat = 0, .buttons = 0 + }; + + if ( btn ) + { + report.hat = GAMEPAD_HAT_UP; + report.buttons = GAMEPAD_BUTTON_A; + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + + has_gamepad_key = true; + }else + { + report.hat = GAMEPAD_HAT_CENTERED; + report.buttons = 0; + if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + has_gamepad_key = false; + }*/ + } + break; + + default: break; + } +} + +int led_counter = 0; +int rgb_channel = 0; +int rgb_val = 0; + +void led_task(uint32_t rgb) { + int offset = 0; + uint32_t color = rgb; + + for (int y=0; y<6; y++) { + int w = 12; + if (y==5) w = 4; + for (int x=0; x0 || y>0) bits = 0; + + for (int i=23; i>=0; i--) { + if (bits & (1<<23)) { + // one + gpio_put(PIN_LEDS, 1); + delay300ns(); + delay300ns(); + delay300ns(); + gpio_put(PIN_LEDS, 0); + // ~600ms delay + delay300ns(); + delay300ns(); + } else { + // zero + gpio_put(PIN_LEDS, 1); + delay300ns(); + gpio_put(PIN_LEDS, 0); + // ~1.2ms delay + delay300ns(); + delay300ns(); + delay300ns(); + delay300ns(); + //delay300ns(); + } + bits <<= 1; + } + } + } +} + +// Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) +// tud_hid_report_complete_cb() is used to send the next report after previous one is complete +void hid_task(void) +{ + // Poll every 10ms + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; + + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + uint32_t const btn = 0; //board_button_read(); + + // Remote wakeup + if ( tud_suspended() && btn ) + { + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); + } else { + // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() + send_hid_report(REPORT_ID_KEYBOARD); + } +} + +void led_core() { + for (int i=0; i<10; i++) { + sleep_ms(200); + led_task(0x00ff00); //rgb_val< 0xff) { + rgb_val = 0; + rgb_channel += 8; + if (rgb_channel > 16) { + rgb_channel = 0; + } + }*/ + } +} + +// Invoked when sent REPORT successfully to host +// Application can use this to send the next report +// Note: For composite reports, report[0] is report ID +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len) +{ + (void) instance; + (void) len; + + uint8_t next_report_id = report[0] + 1; + + if (next_report_id < REPORT_ID_COUNT) + { + send_hid_report(next_report_id); + } +} + +// Invoked when received GET_REPORT control request +// Application must fill buffer report's content and return its length. +// Return zero will cause the stack to STALL request +uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +{ + // TODO not Implemented + (void) instance; + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; + + return 0; +} + +// Invoked when received SET_REPORT control request or +// received data on OUT endpoint ( Report ID = 0, Type = 0 ) +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +{ + (void) instance; + + if (report_type == HID_REPORT_TYPE_OUTPUT) + { + // Set keyboard LED e.g Capslock, Numlock etc... + if (report_id == REPORT_ID_KEYBOARD) + { + // bufsize should be (at least) 1 + if ( bufsize < 1 ) return; + + //uint8_t const kbd_leds = buffer[0]; + } + } +} diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/matrix.h b/pocket-reform-keyboard-fw/pocket-hid/src/matrix.h new file mode 100644 index 0000000..f14ff9b --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/matrix.h @@ -0,0 +1,142 @@ +/* + MNT Reform 2.0 Keyboard Firmware + See keyboard.c for Copyright + SPDX-License-Identifier: MIT +*/ + +#include "usb_hid_keys.h" + +// Top row, left to right +#define MATRIX_DEFAULT_ROW_1 \ + KEY_ESC,\ + KEY_1,\ + KEY_2,\ + KEY_3,\ + KEY_4,\ + KEY_5,\ + KEY_6,\ + KEY_7,\ + KEY_8,\ + KEY_9,\ + KEY_0,\ + KEY_BACKSPACE + +// Third row +#define MATRIX_DEFAULT_ROW_2 \ + KEY_TAB,\ + KEY_Q,\ + KEY_W,\ + KEY_E,\ + KEY_R,\ + KEY_T,\ + KEY_Y,\ + KEY_U,\ + KEY_I,\ + KEY_O,\ + KEY_P,\ + KEY_BACKSLASH + +// Fourth row +#define MATRIX_DEFAULT_ROW_3 \ + KEY_LEFTCTRL,\ + KEY_A,\ + KEY_S,\ + KEY_D,\ + KEY_F,\ + KEY_G,\ + KEY_H,\ + KEY_J,\ + KEY_K,\ + KEY_L,\ + KEY_SEMICOLON,\ + KEY_ENTER + +// Fifth row +#define MATRIX_DEFAULT_ROW_4 \ + KEY_LEFTSHIFT,\ + KEY_Z,\ + KEY_X,\ + KEY_C,\ + KEY_V,\ + KEY_B,\ + KEY_N,\ + KEY_M,\ + KEY_SLASH,\ + KEY_APOSTROPHE,\ + KEY_UP,\ + KEY_RIGHTSHIFT + +// Sixth row +#define MATRIX_DEFAULT_ROW_5 \ + KEY_COMPOSE,\ + KEY_LEFTMETA,\ + KEY_LEFTALT,\ + KEY_MINUS,\ + KEY_EQUAL,\ + KEY_SPACE,\ + KEY_SPACE,\ + KEY_COMMA,\ + KEY_DOT,\ + KEY_LEFT,\ + KEY_DOWN,\ + KEY_RIGHT + +// Every line of `matrix` is a row of the keyboard, starting from the top. +// Check keyboard.h for the definitions of the default rows. +uint8_t matrix[KBD_MATRIX_SZ] = { + MATRIX_DEFAULT_ROW_1, + MATRIX_DEFAULT_ROW_2, + MATRIX_DEFAULT_ROW_3, + MATRIX_DEFAULT_ROW_4, + MATRIX_DEFAULT_ROW_5 +}; + +// When holding down HYPER +/*uint8_t matrix_fn[KBD_MATRIX_SZ] = { + // Media keys on Hyper + F7-F12 + KEY_ESC, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + HID_KEYBOARD_SC_MEDIA_BACKWARD, + HID_KEYBOARD_SC_MEDIA_PLAY, + HID_KEYBOARD_SC_MEDIA_FORWARD, + HID_KEYBOARD_SC_MEDIA_MUTE, + HID_KEYBOARD_SC_MEDIA_VOLUME_DOWN, + HID_KEYBOARD_SC_MEDIA_VOLUME_UP, + KEY_CIRCLE, + + MATRIX_DEFAULT_ROW_2, + MATRIX_DEFAULT_ROW_3, + MATRIX_DEFAULT_ROW_4, + MATRIX_DEFAULT_ROW_5, + MATRIX_DEFAULT_ROW_6 + };*/ + +// Second layer (toggled by HYPER+CIRCLE) +/*uint8_t matrix_fn_toggled[KBD_MATRIX_SZ] = { + // Custom top row + KEY_ESCAPE, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + KEY_F6, + HID_KEYBOARD_SC_MEDIA_BACKWARD, + HID_KEYBOARD_SC_MEDIA_PLAY, + HID_KEYBOARD_SC_MEDIA_FORWARD, + HID_KEYBOARD_SC_MEDIA_MUTE, + HID_KEYBOARD_SC_MEDIA_VOLUME_DOWN, + HID_KEYBOARD_SC_MEDIA_VOLUME_UP, + KEY_CIRCLE, + + MATRIX_DEFAULT_ROW_2, + MATRIX_DEFAULT_ROW_3, + MATRIX_DEFAULT_ROW_4, + MATRIX_DEFAULT_ROW_5, + MATRIX_DEFAULT_ROW_6 + };*/ diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/tusb_config.h b/pocket-reform-keyboard-fw/pocket-hid/src/tusb_config.h new file mode 100644 index 0000000..d0f2b51 --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/tusb_config.h @@ -0,0 +1,106 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by board.mk +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +// RHPort number used for device can be defined by board.mk, default to port 0 +#ifndef BOARD_DEVICE_RHPORT_NUM + #define BOARD_DEVICE_RHPORT_NUM 0 +#endif + +// RHPort max operational speed can defined by board.mk +// Default to max (auto) speed for MCU with internal HighSpeed PHY +#ifndef BOARD_DEVICE_RHPORT_SPEED + #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +// Device mode with rhport and speed defined by board.mk +#if BOARD_DEVICE_RHPORT_NUM == 0 + #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#elif BOARD_DEVICE_RHPORT_NUM == 1 + #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) +#else + #error "Incorrect RHPort configuration" +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_HID 1 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +// HID buffer size Should be sufficient to hold ID (if any) + Data +#define CFG_TUD_HID_EP_BUFSIZE 16 + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/usb_descriptors.c b/pocket-reform-keyboard-fw/pocket-hid/src/usb_descriptors.c new file mode 100644 index 0000000..0ab76b3 --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/usb_descriptors.c @@ -0,0 +1,295 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "tusb.h" +#include "usb_descriptors.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ + _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) + +#define USB_VID 0xCafe +#define USB_BCD 0x0200 + +//--------------------------------------------------------------------+ +// Device Descriptors +//--------------------------------------------------------------------+ +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +// Invoked when received GET DEVICE DESCRIPTOR +// Application return pointer to descriptor +uint8_t const * tud_descriptor_device_cb(void) +{ + return (uint8_t const *) &desc_device; +} + +//--------------------------------------------------------------------+ +// HID Report Descriptor +//--------------------------------------------------------------------+ + +/* FIXME REPORT_ID 5 hardcoded */ +#define TUD_HID_REPORT_DESC_MNTMOUSE() \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ + HID_REPORT_ID ( REPORT_ID_MOUSE ) \ + HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ + HID_USAGE_MIN ( 1 ) ,\ + HID_USAGE_MAX ( 5 ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + /* Left, Right, Middle, Backward, Forward buttons */ \ + HID_REPORT_COUNT( 5 ) ,\ + HID_REPORT_SIZE ( 1 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* 3 bit padding */ \ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 3 ) ,\ + HID_INPUT ( HID_CONSTANT ) ,\ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + /* X, Y position [-127, 127] */ \ + HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_REPORT_COUNT( 2 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ + HID_COLLECTION ( HID_COLLECTION_LOGICAL ) ,\ + HID_REPORT_ID ( 5 ) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER ) ,\ + HID_LOGICAL_MIN ( 0 ) ,\ + HID_LOGICAL_MAX ( 1 ) ,\ + HID_PHYSICAL_MIN ( 1 ), \ + HID_PHYSICAL_MAX ( 12 ), \ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ + /* Vertical wheel scroll [-127, 127] */ \ + HID_REPORT_ID ( REPORT_ID_MOUSE ) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ + HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ + HID_LOGICAL_MIN ( 0x81 ) ,\ + HID_LOGICAL_MAX ( 0x7f ) ,\ + HID_PHYSICAL_MIN ( 0 ), \ + HID_PHYSICAL_MAX ( 0 ), \ + HID_REPORT_COUNT( 1 ) ,\ + HID_REPORT_SIZE ( 8 ) ,\ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ + HID_REPORT_ID ( REPORT_ID_MOUSE ) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ + /* Horizontal wheel scroll [-127, 127] */ \ + HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ + HID_LOGICAL_MIN ( 0x81 ), \ + HID_LOGICAL_MAX ( 0x7f ), \ + HID_PHYSICAL_MIN ( 0x81 ), \ + HID_PHYSICAL_MAX ( 0x7f ), \ + HID_REPORT_COUNT( 1 ), \ + HID_REPORT_SIZE ( 8 ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ + HID_COLLECTION_END , \ + HID_COLLECTION_END , \ + HID_COLLECTION_END \ + + +uint8_t const desc_hid_report[] = +{ + TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD )), + TUD_HID_REPORT_DESC_MNTMOUSE( ), + TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )), + TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD )) +}; + +// Invoked when received GET HID REPORT DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) +{ + (void) instance; + return desc_hid_report; +} + +//--------------------------------------------------------------------+ +// Configuration Descriptor +//--------------------------------------------------------------------+ + +enum +{ + ITF_NUM_HID, + ITF_NUM_TOTAL +}; + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN) + +#define EPNUM_HID 0x81 + +uint8_t const desc_configuration[] = +{ + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + + // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5) +}; + +#if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +// other speed configuration +uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = +{ + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = USB_BCD, + + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const* tud_descriptor_device_qualifier_cb(void) +{ + return (uint8_t const*) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + + // other speed config is basically configuration with type = OHER_SPEED_CONFIG + memcpy(desc_other_speed_config, desc_configuration, CONFIG_TOTAL_LEN); + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; + + // this example use the same configuration for both high and full speed mode + return desc_other_speed_config; +} + +#endif // highspeed + +// Invoked when received GET CONFIGURATION DESCRIPTOR +// Application return pointer to descriptor +// Descriptor contents must exist long enough for transfer to complete +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; // for multiple configurations + + // This example use the same configuration for both high and full speed mode + return desc_configuration; +} + +//--------------------------------------------------------------------+ +// String Descriptors +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +char const* string_desc_arr [] = +{ + (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) + "MNT", // 1: Manufacturer + "Pocket Reform Input", // 2: Product + "RP2040", // 3: Serials, should use chip ID +}; + +static uint16_t _desc_str[32]; + +// Invoked when received GET STRING DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void) langid; + + uint8_t chr_count; + + if ( index == 0) + { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + }else + { + // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + + if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + + const char* str = string_desc_arr[index]; + + // Cap at max char + chr_count = strlen(str); + if ( chr_count > 31 ) chr_count = 31; + + // Convert ASCII string into UTF-16 + for(uint8_t i=0; i +#define KEY_SLASH 0x38 // Keyboard / and ? +#define KEY_CAPSLOCK 0x39 // Keyboard Caps Lock + +#define KEY_F1 0x3a // Keyboard F1 +#define KEY_F2 0x3b // Keyboard F2 +#define KEY_F3 0x3c // Keyboard F3 +#define KEY_F4 0x3d // Keyboard F4 +#define KEY_F5 0x3e // Keyboard F5 +#define KEY_F6 0x3f // Keyboard F6 +#define KEY_F7 0x40 // Keyboard F7 +#define KEY_F8 0x41 // Keyboard F8 +#define KEY_F9 0x42 // Keyboard F9 +#define KEY_F10 0x43 // Keyboard F10 +#define KEY_F11 0x44 // Keyboard F11 +#define KEY_F12 0x45 // Keyboard F12 + +#define KEY_SYSRQ 0x46 // Keyboard Print Screen +#define KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock +#define KEY_PAUSE 0x48 // Keyboard Pause +#define KEY_INSERT 0x49 // Keyboard Insert +#define KEY_HOME 0x4a // Keyboard Home +#define KEY_PAGEUP 0x4b // Keyboard Page Up +#define KEY_DELETE 0x4c // Keyboard Delete Forward +#define KEY_END 0x4d // Keyboard End +#define KEY_PAGEDOWN 0x4e // Keyboard Page Down +#define KEY_RIGHT 0x4f // Keyboard Right Arrow +#define KEY_LEFT 0x50 // Keyboard Left Arrow +#define KEY_DOWN 0x51 // Keyboard Down Arrow +#define KEY_UP 0x52 // Keyboard Up Arrow + +#define KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear +#define KEY_KPSLASH 0x54 // Keypad / +#define KEY_KPASTERISK 0x55 // Keypad * +#define KEY_KPMINUS 0x56 // Keypad - +#define KEY_KPPLUS 0x57 // Keypad + +#define KEY_KPENTER 0x58 // Keypad ENTER +#define KEY_KP1 0x59 // Keypad 1 and End +#define KEY_KP2 0x5a // Keypad 2 and Down Arrow +#define KEY_KP3 0x5b // Keypad 3 and PageDn +#define KEY_KP4 0x5c // Keypad 4 and Left Arrow +#define KEY_KP5 0x5d // Keypad 5 +#define KEY_KP6 0x5e // Keypad 6 and Right Arrow +#define KEY_KP7 0x5f // Keypad 7 and Home +#define KEY_KP8 0x60 // Keypad 8 and Up Arrow +#define KEY_KP9 0x61 // Keypad 9 and Page Up +#define KEY_KP0 0x62 // Keypad 0 and Insert +#define KEY_KPDOT 0x63 // Keypad . and Delete + +#define KEY_102ND 0x64 // Keyboard Non-US \ and | +#define KEY_COMPOSE 0x65 // Keyboard Application +#define KEY_POWER 0x66 // Keyboard Power +#define KEY_KPEQUAL 0x67 // Keypad = + +#define KEY_F13 0x68 // Keyboard F13 +#define KEY_F14 0x69 // Keyboard F14 +#define KEY_F15 0x6a // Keyboard F15 +#define KEY_F16 0x6b // Keyboard F16 +#define KEY_F17 0x6c // Keyboard F17 +#define KEY_F18 0x6d // Keyboard F18 +#define KEY_F19 0x6e // Keyboard F19 +#define KEY_F20 0x6f // Keyboard F20 +#define KEY_F21 0x70 // Keyboard F21 +#define KEY_F22 0x71 // Keyboard F22 +#define KEY_F23 0x72 // Keyboard F23 +#define KEY_F24 0x73 // Keyboard F24 + +#define KEY_OPEN 0x74 // Keyboard Execute +#define KEY_HELP 0x75 // Keyboard Help +#define KEY_PROPS 0x76 // Keyboard Menu +#define KEY_FRONT 0x77 // Keyboard Select +#define KEY_STOP 0x78 // Keyboard Stop +#define KEY_AGAIN 0x79 // Keyboard Again +#define KEY_UNDO 0x7a // Keyboard Undo +#define KEY_CUT 0x7b // Keyboard Cut +#define KEY_COPY 0x7c // Keyboard Copy +#define KEY_PASTE 0x7d // Keyboard Paste +#define KEY_FIND 0x7e // Keyboard Find +#define KEY_MUTE 0x7f // Keyboard Mute +#define KEY_VOLUMEUP 0x80 // Keyboard Volume Up +#define KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down +// 0x82 Keyboard Locking Caps Lock +// 0x83 Keyboard Locking Num Lock +// 0x84 Keyboard Locking Scroll Lock +#define KEY_KPCOMMA 0x85 // Keypad Comma +// 0x86 Keypad Equal Sign +#define KEY_RO 0x87 // Keyboard International1 +#define KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2 +#define KEY_YEN 0x89 // Keyboard International3 +#define KEY_HENKAN 0x8a // Keyboard International4 +#define KEY_MUHENKAN 0x8b // Keyboard International5 +#define KEY_KPJPCOMMA 0x8c // Keyboard International6 +// 0x8d Keyboard International7 +// 0x8e Keyboard International8 +// 0x8f Keyboard International9 +#define KEY_HANGEUL 0x90 // Keyboard LANG1 +#define KEY_HANJA 0x91 // Keyboard LANG2 +#define KEY_KATAKANA 0x92 // Keyboard LANG3 +#define KEY_HIRAGANA 0x93 // Keyboard LANG4 +#define KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5 +// 0x95 Keyboard LANG6 +// 0x96 Keyboard LANG7 +// 0x97 Keyboard LANG8 +// 0x98 Keyboard LANG9 +// 0x99 Keyboard Alternate Erase +// 0x9a Keyboard SysReq/Attention +// 0x9b Keyboard Cancel +// 0x9c Keyboard Clear +// 0x9d Keyboard Prior +// 0x9e Keyboard Return +// 0x9f Keyboard Separator +// 0xa0 Keyboard Out +// 0xa1 Keyboard Oper +// 0xa2 Keyboard Clear/Again +// 0xa3 Keyboard CrSel/Props +// 0xa4 Keyboard ExSel + +// 0xb0 Keypad 00 +// 0xb1 Keypad 000 +// 0xb2 Thousands Separator +// 0xb3 Decimal Separator +// 0xb4 Currency Unit +// 0xb5 Currency Sub-unit +#define KEY_KPLEFTPAREN 0xb6 // Keypad ( +#define KEY_KPRIGHTPAREN 0xb7 // Keypad ) +// 0xb8 Keypad { +// 0xb9 Keypad } +// 0xba Keypad Tab +// 0xbb Keypad Backspace +// 0xbc Keypad A +// 0xbd Keypad B +// 0xbe Keypad C +// 0xbf Keypad D +// 0xc0 Keypad E +// 0xc1 Keypad F +// 0xc2 Keypad XOR +// 0xc3 Keypad ^ +// 0xc4 Keypad % +// 0xc5 Keypad < +// 0xc6 Keypad > +// 0xc7 Keypad & +// 0xc8 Keypad && +// 0xc9 Keypad | +// 0xca Keypad || +// 0xcb Keypad : +// 0xcc Keypad # +// 0xcd Keypad Space +// 0xce Keypad @ +// 0xcf Keypad ! +// 0xd0 Keypad Memory Store +// 0xd1 Keypad Memory Recall +// 0xd2 Keypad Memory Clear +// 0xd3 Keypad Memory Add +// 0xd4 Keypad Memory Subtract +// 0xd5 Keypad Memory Multiply +// 0xd6 Keypad Memory Divide +// 0xd7 Keypad +/- +// 0xd8 Keypad Clear +// 0xd9 Keypad Clear Entry +// 0xda Keypad Binary +// 0xdb Keypad Octal +// 0xdc Keypad Decimal +// 0xdd Keypad Hexadecimal + +#define KEY_LEFTCTRL 0xe0 // Keyboard Left Control +#define KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift +#define KEY_LEFTALT 0xe2 // Keyboard Left Alt +#define KEY_LEFTMETA 0xe3 // Keyboard Left GUI +#define KEY_RIGHTCTRL 0xe4 // Keyboard Right Control +#define KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift +#define KEY_RIGHTALT 0xe6 // Keyboard Right Alt +#define KEY_RIGHTMETA 0xe7 // Keyboard Right GUI + +#define KEY_MEDIA_PLAYPAUSE 0xe8 +#define KEY_MEDIA_STOPCD 0xe9 +#define KEY_MEDIA_PREVIOUSSONG 0xea +#define KEY_MEDIA_NEXTSONG 0xeb +#define KEY_MEDIA_EJECTCD 0xec +#define KEY_MEDIA_VOLUMEUP 0xed +#define KEY_MEDIA_VOLUMEDOWN 0xee +#define KEY_MEDIA_MUTE 0xef +#define KEY_MEDIA_WWW 0xf0 +#define KEY_MEDIA_BACK 0xf1 +#define KEY_MEDIA_FORWARD 0xf2 +#define KEY_MEDIA_STOP 0xf3 +#define KEY_MEDIA_FIND 0xf4 +#define KEY_MEDIA_SCROLLUP 0xf5 +#define KEY_MEDIA_SCROLLDOWN 0xf6 +#define KEY_MEDIA_EDIT 0xf7 +#define KEY_MEDIA_SLEEP 0xf8 +#define KEY_MEDIA_COFFEE 0xf9 +#define KEY_MEDIA_REFRESH 0xfa +#define KEY_MEDIA_CALC 0xfb + +#endif // USB_HID_KEYS