diff options
| -rw-r--r-- | common_features.mk | 5 | ||||
| -rw-r--r-- | docs/_summary.md | 1 | ||||
| -rw-r--r-- | docs/feature_digitizer.md | 35 | ||||
| -rw-r--r-- | keyboards/handwired/onekey/keymaps/digitizer/keymap.c | 38 | ||||
| -rw-r--r-- | keyboards/handwired/onekey/keymaps/digitizer/rules.mk | 1 | ||||
| -rw-r--r-- | quantum/digitizer.c | 34 | ||||
| -rw-r--r-- | quantum/digitizer.h | 41 | ||||
| -rw-r--r-- | tmk_core/common.mk | 13 | ||||
| -rw-r--r-- | tmk_core/common/host.c | 19 | ||||
| -rw-r--r-- | tmk_core/common/host_driver.h | 2 | ||||
| -rw-r--r-- | tmk_core/common/keyboard.c | 7 | ||||
| -rw-r--r-- | tmk_core/common/report.h | 14 | ||||
| -rw-r--r-- | tmk_core/protocol/chibios/main.c | 1 | ||||
| -rw-r--r-- | tmk_core/protocol/chibios/usb_main.c | 28 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 26 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 101 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor.h | 27 | ||||
| -rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 48 |
18 files changed, 435 insertions, 6 deletions
diff --git a/common_features.mk b/common_features.mk index e442222ea..493aab635 100644 --- a/common_features.mk +++ b/common_features.mk | |||
| @@ -695,6 +695,11 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), digital) | |||
| 695 | OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE | 695 | OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE |
| 696 | endif | 696 | endif |
| 697 | 697 | ||
| 698 | DIGITIZER_ENABLE ?= no | ||
| 699 | ifneq ($(strip $(DIGITIZER_ENABLE)), no) | ||
| 700 | SRC += $(QUANTUM_DIR)/digitizer.c | ||
| 701 | endif | ||
| 702 | |||
| 698 | USBPD_ENABLE ?= no | 703 | USBPD_ENABLE ?= no |
| 699 | VALID_USBPD_DRIVER_TYPES = custom vendor | 704 | VALID_USBPD_DRIVER_TYPES = custom vendor |
| 700 | USBPD_DRIVER ?= vendor | 705 | USBPD_DRIVER ?= vendor |
diff --git a/docs/_summary.md b/docs/_summary.md index 48115cef4..2f6309e41 100644 --- a/docs/_summary.md +++ b/docs/_summary.md | |||
| @@ -108,6 +108,7 @@ | |||
| 108 | * [Bluetooth](feature_bluetooth.md) | 108 | * [Bluetooth](feature_bluetooth.md) |
| 109 | * [Bootmagic Lite](feature_bootmagic.md) | 109 | * [Bootmagic Lite](feature_bootmagic.md) |
| 110 | * [Custom Matrix](custom_matrix.md) | 110 | * [Custom Matrix](custom_matrix.md) |
| 111 | * [Digitizer](feature_digitizer.md) | ||
| 111 | * [DIP Switch](feature_dip_switch.md) | 112 | * [DIP Switch](feature_dip_switch.md) |
| 112 | * [Encoders](feature_encoders.md) | 113 | * [Encoders](feature_encoders.md) |
| 113 | * [Haptic Feedback](feature_haptic_feedback.md) | 114 | * [Haptic Feedback](feature_haptic_feedback.md) |
diff --git a/docs/feature_digitizer.md b/docs/feature_digitizer.md new file mode 100644 index 000000000..9b6aeddba --- /dev/null +++ b/docs/feature_digitizer.md | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | ## Digitizer | ||
| 2 | |||
| 3 | The digitizer HID interface allows setting the mouse cursor position at absolute coordinates, unlike the Pointing Device feature that applies relative displacements. | ||
| 4 | |||
| 5 | To enable the digitizer interface, add the following line to your rules.mk: | ||
| 6 | |||
| 7 | ```makefile | ||
| 8 | DIGITIZER_ENABLE = yes | ||
| 9 | ``` | ||
| 10 | |||
| 11 | In order to change the mouse cursor position from your keymap.c file, include the digitizer header : | ||
| 12 | |||
| 13 | ```c | ||
| 14 | #include "digitizer.h" | ||
| 15 | ``` | ||
| 16 | |||
| 17 | This gives you access to the `digitizer` structure which members allow you to change the cursor position. | ||
| 18 | |||
| 19 | The coordinates are normalized, meaning there value must be set between 0 and 1. For the `x` coordinate, the value `0` is the leftmost position, whereas the value `1` is the rightmost position. | ||
| 20 | For the `y` coordinate, `0` is at the top and `1` at the bottom. | ||
| 21 | |||
| 22 | Here is an example setting the cursor in the middle of the screen: | ||
| 23 | |||
| 24 | ```c | ||
| 25 | digitizer_t digitizer; | ||
| 26 | digitizer.x = 0.5; | ||
| 27 | digitizer.y = 0.5; | ||
| 28 | digitizer.tipswitch = 0; | ||
| 29 | digitizer.inrange = 1; | ||
| 30 | digitizer_set_report(digitizer); | ||
| 31 | ``` | ||
| 32 | |||
| 33 | The `tipswitch` member triggers what equates to a click when set to `1`. The `inrange` member is required for the change in coordinates to be taken. It can then be set to `0` in a new report to signal the end of the digitizer interaction, but it is not strictly required. | ||
| 34 | |||
| 35 | Once all members are set to the desired value, the `status` member needs its bitmask `DZ_UPDATED` to be set so the report is sent during the next main loop iteration. | ||
diff --git a/keyboards/handwired/onekey/keymaps/digitizer/keymap.c b/keyboards/handwired/onekey/keymaps/digitizer/keymap.c new file mode 100644 index 000000000..6b304e86f --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/digitizer/keymap.c | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | #include QMK_KEYBOARD_H | ||
| 17 | |||
| 18 | #include "digitizer.h" | ||
| 19 | |||
| 20 | #include "math.h" | ||
| 21 | |||
| 22 | const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(KC_A)}; | ||
| 23 | |||
| 24 | uint32_t timer = 0; | ||
| 25 | |||
| 26 | void matrix_scan_user() { | ||
| 27 | if (timer_elapsed32(timer) < 200) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | |||
| 31 | timer = timer_read32(); | ||
| 32 | digitizer_t digitizer; | ||
| 33 | digitizer.x = 0.5 - 0.2 * cos(timer_read() / 250. / 6.28); | ||
| 34 | digitizer.y = 0.5 - 0.2 * sin(timer_read() / 250. / 6.28); | ||
| 35 | digitizer.tipswitch = 0; | ||
| 36 | digitizer.inrange = 1; | ||
| 37 | digitizer_set_report(digitizer); | ||
| 38 | } | ||
diff --git a/keyboards/handwired/onekey/keymaps/digitizer/rules.mk b/keyboards/handwired/onekey/keymaps/digitizer/rules.mk new file mode 100644 index 000000000..ea9f9bd9a --- /dev/null +++ b/keyboards/handwired/onekey/keymaps/digitizer/rules.mk | |||
| @@ -0,0 +1 @@ | |||
| DIGITIZER_ENABLE = yes \ No newline at end of file | |||
diff --git a/quantum/digitizer.c b/quantum/digitizer.c new file mode 100644 index 000000000..e29986742 --- /dev/null +++ b/quantum/digitizer.c | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | /* Copyright 2021 | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | #include "digitizer.h" | ||
| 17 | |||
| 18 | digitizer_t digitizerReport = {.tipswitch = 0, .inrange = 0, .id = 0, .x = 0, .y = 0, .status = DZ_INITIALIZED}; | ||
| 19 | |||
| 20 | __attribute__((weak)) void digitizer_send(void) { | ||
| 21 | if (digitizerReport.status & DZ_UPDATED) { | ||
| 22 | host_digitizer_send(&digitizerReport); | ||
| 23 | digitizerReport.status &= ~DZ_UPDATED; | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | __attribute__((weak)) void digitizer_task(void) { digitizer_send(); } | ||
| 28 | |||
| 29 | digitizer_t digitizer_get_report(void) { return digitizerReport; } | ||
| 30 | |||
| 31 | void digitizer_set_report(digitizer_t newDigitizerReport) { | ||
| 32 | digitizerReport = newDigitizerReport; | ||
| 33 | digitizerReport.status |= DZ_UPDATED; | ||
| 34 | } \ No newline at end of file | ||
diff --git a/quantum/digitizer.h b/quantum/digitizer.h new file mode 100644 index 000000000..cef551567 --- /dev/null +++ b/quantum/digitizer.h | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | /* Copyright 2021 | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 2 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | #pragma once | ||
| 17 | |||
| 18 | #include "quantum.h" | ||
| 19 | |||
| 20 | #include <stdint.h> | ||
| 21 | |||
| 22 | enum digitizer_status { DZ_INITIALIZED = 1, DZ_UPDATED = 2 }; | ||
| 23 | |||
| 24 | typedef struct { | ||
| 25 | int8_t tipswitch; | ||
| 26 | int8_t inrange; | ||
| 27 | uint8_t id; | ||
| 28 | float x; | ||
| 29 | float y; | ||
| 30 | uint8_t status : 2; | ||
| 31 | } digitizer_t; | ||
| 32 | |||
| 33 | extern digitizer_t digitizer; | ||
| 34 | |||
| 35 | digitizer_t digitizer_get_report(void); | ||
| 36 | |||
| 37 | void digitizer_set_report(digitizer_t newDigitizerReport); | ||
| 38 | |||
| 39 | void digitizer_task(void); | ||
| 40 | |||
| 41 | void host_digitizer_send(digitizer_t *digitizer); | ||
diff --git a/tmk_core/common.mk b/tmk_core/common.mk index 6c8cf6935..fa907b47b 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk | |||
| @@ -106,6 +106,19 @@ ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes) | |||
| 106 | TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK | 106 | TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK |
| 107 | endif | 107 | endif |
| 108 | 108 | ||
| 109 | ifeq ($(strip $(DIGITIZER_SHARED_EP)), yes) | ||
| 110 | TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP | ||
| 111 | SHARED_EP_ENABLE = yes | ||
| 112 | endif | ||
| 113 | |||
| 114 | ifeq ($(strip $(DIGITIZER_ENABLE)), yes) | ||
| 115 | TMK_COMMON_DEFS += -DDIGITIZER_ENABLE | ||
| 116 | ifeq ($(strip $(SHARED_EP_ENABLE)), yes) | ||
| 117 | TMK_COMMON_DEFS += -DDIGITIZER_SHARED_EP | ||
| 118 | SHARED_EP_ENABLE = yes | ||
| 119 | endif | ||
| 120 | endif | ||
| 121 | |||
| 109 | ifeq ($(strip $(SHARED_EP_ENABLE)), yes) | 122 | ifeq ($(strip $(SHARED_EP_ENABLE)), yes) |
| 110 | TMK_COMMON_DEFS += -DSHARED_EP_ENABLE | 123 | TMK_COMMON_DEFS += -DSHARED_EP_ENABLE |
| 111 | endif | 124 | endif |
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c index a8b391e89..f0c396b18 100644 --- a/tmk_core/common/host.c +++ b/tmk_core/common/host.c | |||
| @@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 22 | #include "host.h" | 22 | #include "host.h" |
| 23 | #include "util.h" | 23 | #include "util.h" |
| 24 | #include "debug.h" | 24 | #include "debug.h" |
| 25 | #include "digitizer.h" | ||
| 25 | 26 | ||
| 26 | #ifdef NKRO_ENABLE | 27 | #ifdef NKRO_ENABLE |
| 27 | # include "keycode_config.h" | 28 | # include "keycode_config.h" |
| @@ -103,6 +104,24 @@ void host_consumer_send(uint16_t report) { | |||
| 103 | (*driver->send_consumer)(report); | 104 | (*driver->send_consumer)(report); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 107 | void host_digitizer_send(digitizer_t *digitizer) { | ||
| 108 | if (!driver) return; | ||
| 109 | |||
| 110 | report_digitizer_t report = { | ||
| 111 | #ifdef DIGITIZER_SHARED_EP | ||
| 112 | .report_id = REPORT_ID_DIGITIZER, | ||
| 113 | #endif | ||
| 114 | .tip = digitizer->tipswitch & 0x1, | ||
| 115 | .inrange = digitizer->inrange & 0x1, | ||
| 116 | .x = (uint16_t)(digitizer->x * 0x7FFF), | ||
| 117 | .y = (uint16_t)(digitizer->y * 0x7FFF), | ||
| 118 | }; | ||
| 119 | |||
| 120 | send_digitizer(&report); | ||
| 121 | } | ||
| 122 | |||
| 123 | __attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} | ||
| 124 | |||
| 106 | uint16_t host_last_system_report(void) { return last_system_report; } | 125 | uint16_t host_last_system_report(void) { return last_system_report; } |
| 107 | 126 | ||
| 108 | uint16_t host_last_consumer_report(void) { return last_consumer_report; } | 127 | uint16_t host_last_consumer_report(void) { return last_consumer_report; } |
diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h index f34a22053..2aebca043 100644 --- a/tmk_core/common/host_driver.h +++ b/tmk_core/common/host_driver.h | |||
| @@ -30,3 +30,5 @@ typedef struct { | |||
| 30 | void (*send_system)(uint16_t); | 30 | void (*send_system)(uint16_t); |
| 31 | void (*send_consumer)(uint16_t); | 31 | void (*send_consumer)(uint16_t); |
| 32 | } host_driver_t; | 32 | } host_driver_t; |
| 33 | |||
| 34 | void send_digitizer(report_digitizer_t *report); \ No newline at end of file | ||
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 28fa97bc8..fcc51973f 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c | |||
| @@ -106,6 +106,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 106 | #if defined(CRC_ENABLE) | 106 | #if defined(CRC_ENABLE) |
| 107 | # include "crc.h" | 107 | # include "crc.h" |
| 108 | #endif | 108 | #endif |
| 109 | #ifdef DIGITIZER_ENABLE | ||
| 110 | # include "digitizer.h" | ||
| 111 | #endif | ||
| 109 | 112 | ||
| 110 | static uint32_t last_input_modification_time = 0; | 113 | static uint32_t last_input_modification_time = 0; |
| 111 | uint32_t last_input_activity_time(void) { return last_input_modification_time; } | 114 | uint32_t last_input_activity_time(void) { return last_input_modification_time; } |
| @@ -537,6 +540,10 @@ MATRIX_LOOP_END: | |||
| 537 | joystick_task(); | 540 | joystick_task(); |
| 538 | #endif | 541 | #endif |
| 539 | 542 | ||
| 543 | #ifdef DIGITIZER_ENABLE | ||
| 544 | digitizer_task(); | ||
| 545 | #endif | ||
| 546 | |||
| 540 | // update LED | 547 | // update LED |
| 541 | if (led_status != host_keyboard_leds()) { | 548 | if (led_status != host_keyboard_leds()) { |
| 542 | led_status = host_keyboard_leds(); | 549 | led_status = host_keyboard_leds(); |
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index db6370657..f2223e806 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h | |||
| @@ -30,7 +30,8 @@ enum hid_report_ids { | |||
| 30 | REPORT_ID_SYSTEM, | 30 | REPORT_ID_SYSTEM, |
| 31 | REPORT_ID_CONSUMER, | 31 | REPORT_ID_CONSUMER, |
| 32 | REPORT_ID_NKRO, | 32 | REPORT_ID_NKRO, |
| 33 | REPORT_ID_JOYSTICK | 33 | REPORT_ID_JOYSTICK, |
| 34 | REPORT_ID_DIGITIZER | ||
| 34 | }; | 35 | }; |
| 35 | 36 | ||
| 36 | /* Mouse buttons */ | 37 | /* Mouse buttons */ |
| @@ -206,6 +207,17 @@ typedef struct { | |||
| 206 | } __attribute__((packed)) report_mouse_t; | 207 | } __attribute__((packed)) report_mouse_t; |
| 207 | 208 | ||
| 208 | typedef struct { | 209 | typedef struct { |
| 210 | #ifdef DIGITIZER_SHARED_EP | ||
| 211 | uint8_t report_id; | ||
| 212 | #endif | ||
| 213 | uint8_t tip : 1; | ||
| 214 | uint8_t inrange : 1; | ||
| 215 | uint8_t pad2 : 6; | ||
| 216 | uint16_t x; | ||
| 217 | uint16_t y; | ||
| 218 | } __attribute__((packed)) report_digitizer_t; | ||
| 219 | |||
| 220 | typedef struct { | ||
| 209 | #if JOYSTICK_AXES_COUNT > 0 | 221 | #if JOYSTICK_AXES_COUNT > 0 |
| 210 | # if JOYSTICK_AXES_RESOLUTION > 8 | 222 | # if JOYSTICK_AXES_RESOLUTION > 8 |
| 211 | int16_t axes[JOYSTICK_AXES_COUNT]; | 223 | int16_t axes[JOYSTICK_AXES_COUNT]; |
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 199741594..e41d6ff19 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c | |||
| @@ -65,6 +65,7 @@ void send_keyboard(report_keyboard_t *report); | |||
| 65 | void send_mouse(report_mouse_t *report); | 65 | void send_mouse(report_mouse_t *report); |
| 66 | void send_system(uint16_t data); | 66 | void send_system(uint16_t data); |
| 67 | void send_consumer(uint16_t data); | 67 | void send_consumer(uint16_t data); |
| 68 | void send_digitizer(report_digitizer_t *report); | ||
| 68 | 69 | ||
| 69 | /* host struct */ | 70 | /* host struct */ |
| 70 | host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; | 71 | host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; |
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index e5edd74dc..cc282e6a9 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c | |||
| @@ -316,6 +316,9 @@ typedef struct { | |||
| 316 | #ifdef JOYSTICK_ENABLE | 316 | #ifdef JOYSTICK_ENABLE |
| 317 | usb_driver_config_t joystick_driver; | 317 | usb_driver_config_t joystick_driver; |
| 318 | #endif | 318 | #endif |
| 319 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 320 | usb_driver_config_t digitizer_driver; | ||
| 321 | #endif | ||
| 319 | }; | 322 | }; |
| 320 | usb_driver_config_t array[0]; | 323 | usb_driver_config_t array[0]; |
| 321 | }; | 324 | }; |
| @@ -360,6 +363,14 @@ static usb_driver_configs_t drivers = { | |||
| 360 | # define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK | 363 | # define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK |
| 361 | .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false), | 364 | .joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false), |
| 362 | #endif | 365 | #endif |
| 366 | |||
| 367 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 368 | # define DIGITIZER_IN_CAPACITY 4 | ||
| 369 | # define DIGITIZER_OUT_CAPACITY 4 | ||
| 370 | # define DIGITIZER_IN_MODE USB_EP_MODE_TYPE_BULK | ||
| 371 | # define DIGITIZER_OUT_MODE USB_EP_MODE_TYPE_BULK | ||
| 372 | .digitizer_driver = QMK_USB_DRIVER_CONFIG(DIGITIZER, 0, false), | ||
| 373 | #endif | ||
| 363 | }; | 374 | }; |
| 364 | 375 | ||
| 365 | #define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t)) | 376 | #define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t)) |
| @@ -930,6 +941,23 @@ void send_consumer(uint16_t data) { | |||
| 930 | #endif | 941 | #endif |
| 931 | } | 942 | } |
| 932 | 943 | ||
| 944 | void send_digitizer(report_digitizer_t *report) { | ||
| 945 | #ifdef DIGITIZER_ENABLE | ||
| 946 | # ifdef DIGITIZER_SHARED_EP | ||
| 947 | osalSysLock(); | ||
| 948 | if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { | ||
| 949 | osalSysUnlock(); | ||
| 950 | return; | ||
| 951 | } | ||
| 952 | |||
| 953 | usbStartTransmitI(&USB_DRIVER, DIGITIZER_IN_EPNUM, (uint8_t *)report, sizeof(report_digitizer_t)); | ||
| 954 | osalSysUnlock(); | ||
| 955 | # else | ||
| 956 | chnWrite(&drivers.digitizer_driver.driver, (uint8_t *)report, sizeof(report_digitizer_t)); | ||
| 957 | # endif | ||
| 958 | #endif | ||
| 959 | } | ||
| 960 | |||
| 933 | /* --------------------------------------------------------- | 961 | /* --------------------------------------------------------- |
| 934 | * Console functions | 962 | * Console functions |
| 935 | * --------------------------------------------------------- | 963 | * --------------------------------------------------------- |
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 4ac079e16..8ddb8b1c4 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c | |||
| @@ -142,9 +142,7 @@ static void send_keyboard(report_keyboard_t *report); | |||
| 142 | static void send_mouse(report_mouse_t *report); | 142 | static void send_mouse(report_mouse_t *report); |
| 143 | static void send_system(uint16_t data); | 143 | static void send_system(uint16_t data); |
| 144 | static void send_consumer(uint16_t data); | 144 | static void send_consumer(uint16_t data); |
| 145 | host_driver_t lufa_driver = { | 145 | host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; |
| 146 | keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, | ||
| 147 | }; | ||
| 148 | 146 | ||
| 149 | #ifdef VIRTSER_ENABLE | 147 | #ifdef VIRTSER_ENABLE |
| 150 | // clang-format off | 148 | // clang-format off |
| @@ -525,6 +523,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) { | |||
| 525 | /* Setup joystick endpoint */ | 523 | /* Setup joystick endpoint */ |
| 526 | ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1); | 524 | ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1); |
| 527 | #endif | 525 | #endif |
| 526 | |||
| 527 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 528 | /* Setup digitizer endpoint */ | ||
| 529 | ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1); | ||
| 530 | #endif | ||
| 528 | } | 531 | } |
| 529 | 532 | ||
| 530 | /* FIXME: Expose this table in the docs somehow | 533 | /* FIXME: Expose this table in the docs somehow |
| @@ -983,6 +986,23 @@ void virtser_send(const uint8_t byte) { | |||
| 983 | } | 986 | } |
| 984 | #endif | 987 | #endif |
| 985 | 988 | ||
| 989 | void send_digitizer(report_digitizer_t *report) { | ||
| 990 | #ifdef DIGITIZER_ENABLE | ||
| 991 | uint8_t timeout = 255; | ||
| 992 | |||
| 993 | if (USB_DeviceState != DEVICE_STATE_Configured) return; | ||
| 994 | |||
| 995 | Endpoint_SelectEndpoint(DIGITIZER_IN_EPNUM); | ||
| 996 | |||
| 997 | /* Check if write ready for a polling interval around 10ms */ | ||
| 998 | while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40); | ||
| 999 | if (!Endpoint_IsReadWriteAllowed()) return; | ||
| 1000 | |||
| 1001 | Endpoint_Write_Stream_LE(report, sizeof(report_digitizer_t), NULL); | ||
| 1002 | Endpoint_ClearIN(); | ||
| 1003 | #endif | ||
| 1004 | } | ||
| 1005 | |||
| 986 | /******************************************************************************* | 1006 | /******************************************************************************* |
| 987 | * main | 1007 | * main |
| 988 | ******************************************************************************/ | 1008 | ******************************************************************************/ |
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 7a4a79031..099964ae5 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c | |||
| @@ -158,6 +158,53 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | |||
| 158 | # endif | 158 | # endif |
| 159 | #endif | 159 | #endif |
| 160 | 160 | ||
| 161 | #ifdef DIGITIZER_ENABLE | ||
| 162 | # ifndef DIGITIZER_SHARED_EP | ||
| 163 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM DigitizerReport[] = { | ||
| 164 | # elif !defined(SHARED_REPORT_STARTED) | ||
| 165 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | ||
| 166 | # define SHARED_REPORT_STARTED | ||
| 167 | # endif | ||
| 168 | HID_RI_USAGE_PAGE(8, 0x0D), // Digitizers | ||
| 169 | HID_RI_USAGE(8, 0x01), // Digitizer | ||
| 170 | HID_RI_COLLECTION(8, 0x01), // Application | ||
| 171 | # ifdef DIGITIZER_SHARED_EP | ||
| 172 | HID_RI_REPORT_ID(8, REPORT_ID_DIGITIZER), | ||
| 173 | # endif | ||
| 174 | HID_RI_USAGE(8, 0x20), // Stylus | ||
| 175 | HID_RI_COLLECTION(8, 0x00), // Physical | ||
| 176 | // Tip Switch (1 bit) | ||
| 177 | HID_RI_USAGE(8, 0x42), // Tip Switch | ||
| 178 | HID_RI_LOGICAL_MINIMUM(8, 0x00), | ||
| 179 | HID_RI_LOGICAL_MAXIMUM(8, 0x01), | ||
| 180 | HID_RI_REPORT_SIZE(8, 0x01), | ||
| 181 | HID_RI_REPORT_COUNT(8, 0x01), | ||
| 182 | HID_RI_INPUT(8, HID_IOF_VARIABLE), | ||
| 183 | // In Range (1 bit) | ||
| 184 | HID_RI_USAGE(8, 0x32), // In Range | ||
| 185 | HID_RI_INPUT(8, HID_IOF_VARIABLE), | ||
| 186 | // Padding (6 bits) | ||
| 187 | HID_RI_REPORT_COUNT(8, 0x06), | ||
| 188 | HID_RI_INPUT(8, HID_IOF_CONSTANT | HID_IOF_VARIABLE), | ||
| 189 | |||
| 190 | // X/Y Position (4 bytes) | ||
| 191 | HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop | ||
| 192 | HID_RI_LOGICAL_MAXIMUM(16, 0x7FFF), | ||
| 193 | HID_RI_REPORT_SIZE(8, 0x10), | ||
| 194 | HID_RI_REPORT_COUNT(8, 0x01), | ||
| 195 | HID_RI_UNIT(8, 0x33), // Inch, English Linear | ||
| 196 | HID_RI_UNIT_EXPONENT(8, 0x0E), // -2 | ||
| 197 | HID_RI_USAGE(8, 0x30), // X | ||
| 198 | HID_RI_INPUT(8, HID_IOF_VARIABLE), | ||
| 199 | HID_RI_USAGE(8, 0x31), // Y | ||
| 200 | HID_RI_INPUT(8, HID_IOF_VARIABLE), | ||
| 201 | HID_RI_END_COLLECTION(0), | ||
| 202 | HID_RI_END_COLLECTION(0), | ||
| 203 | # ifndef DIGITIZER_SHARED_EP | ||
| 204 | }; | ||
| 205 | # endif | ||
| 206 | #endif | ||
| 207 | |||
| 161 | #if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED) | 208 | #if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED) |
| 162 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | 209 | const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { |
| 163 | #endif | 210 | #endif |
| @@ -227,6 +274,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { | |||
| 227 | HID_RI_OUTPUT(8, HID_IOF_CONSTANT), | 274 | HID_RI_OUTPUT(8, HID_IOF_CONSTANT), |
| 228 | HID_RI_END_COLLECTION(0), | 275 | HID_RI_END_COLLECTION(0), |
| 229 | #endif | 276 | #endif |
| 277 | |||
| 230 | #ifdef SHARED_EP_ENABLE | 278 | #ifdef SHARED_EP_ENABLE |
| 231 | }; | 279 | }; |
| 232 | #endif | 280 | #endif |
| @@ -921,6 +969,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { | |||
| 921 | .PollingIntervalMS = USB_POLLING_INTERVAL_MS | 969 | .PollingIntervalMS = USB_POLLING_INTERVAL_MS |
| 922 | } | 970 | } |
| 923 | #endif | 971 | #endif |
| 972 | |||
| 973 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 974 | /* | ||
| 975 | * Digitizer | ||
| 976 | */ | ||
| 977 | .Digitizer_Interface = { | ||
| 978 | .Header = { | ||
| 979 | .Size = sizeof(USB_Descriptor_Interface_t), | ||
| 980 | .Type = DTYPE_Interface | ||
| 981 | }, | ||
| 982 | .InterfaceNumber = DIGITIZER_INTERFACE, | ||
| 983 | .AlternateSetting = 0x00, | ||
| 984 | .TotalEndpoints = 1, | ||
| 985 | .Class = HID_CSCP_HIDClass, | ||
| 986 | .SubClass = HID_CSCP_NonBootSubclass, | ||
| 987 | .Protocol = HID_CSCP_NonBootProtocol, | ||
| 988 | .InterfaceStrIndex = NO_DESCRIPTOR | ||
| 989 | }, | ||
| 990 | .Digitizer_HID = { | ||
| 991 | .Header = { | ||
| 992 | .Size = sizeof(USB_HID_Descriptor_HID_t), | ||
| 993 | .Type = HID_DTYPE_HID | ||
| 994 | }, | ||
| 995 | .HIDSpec = VERSION_BCD(1, 1, 1), | ||
| 996 | .CountryCode = 0x00, | ||
| 997 | .TotalReportDescriptors = 1, | ||
| 998 | .HIDReportType = HID_DTYPE_Report, | ||
| 999 | .HIDReportLength = sizeof(DigitizerReport) | ||
| 1000 | }, | ||
| 1001 | .Digitizer_INEndpoint = { | ||
| 1002 | .Header = { | ||
| 1003 | .Size = sizeof(USB_Descriptor_Endpoint_t), | ||
| 1004 | .Type = DTYPE_Endpoint | ||
| 1005 | }, | ||
| 1006 | .EndpointAddress = (ENDPOINT_DIR_IN | DIGITIZER_IN_EPNUM), | ||
| 1007 | .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), | ||
| 1008 | .EndpointSize = DIGITIZER_EPSIZE, | ||
| 1009 | .PollingIntervalMS = USB_POLLING_INTERVAL_MS | ||
| 1010 | }, | ||
| 1011 | #endif | ||
| 924 | }; | 1012 | }; |
| 925 | 1013 | ||
| 926 | /* | 1014 | /* |
| @@ -1059,6 +1147,13 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const | |||
| 1059 | Size = sizeof(USB_HID_Descriptor_HID_t); | 1147 | Size = sizeof(USB_HID_Descriptor_HID_t); |
| 1060 | break; | 1148 | break; |
| 1061 | #endif | 1149 | #endif |
| 1150 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 1151 | case DIGITIZER_INTERFACE: | ||
| 1152 | Address = &ConfigurationDescriptor.Digitizer_HID; | ||
| 1153 | Size = sizeof(USB_HID_Descriptor_HID_t); | ||
| 1154 | |||
| 1155 | break; | ||
| 1156 | #endif | ||
| 1062 | } | 1157 | } |
| 1063 | 1158 | ||
| 1064 | break; | 1159 | break; |
| @@ -1109,6 +1204,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const | |||
| 1109 | Size = sizeof(JoystickReport); | 1204 | Size = sizeof(JoystickReport); |
| 1110 | break; | 1205 | break; |
| 1111 | #endif | 1206 | #endif |
| 1207 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 1208 | case DIGITIZER_INTERFACE: | ||
| 1209 | Address = &DigitizerReport; | ||
| 1210 | Size = sizeof(DigitizerReport); | ||
| 1211 | break; | ||
| 1212 | #endif | ||
| 1112 | } | 1213 | } |
| 1113 | 1214 | ||
| 1114 | break; | 1215 | break; |
diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index 867e549b4..0f0c78f66 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h | |||
| @@ -135,6 +135,13 @@ typedef struct { | |||
| 135 | USB_HID_Descriptor_HID_t Joystick_HID; | 135 | USB_HID_Descriptor_HID_t Joystick_HID; |
| 136 | USB_Descriptor_Endpoint_t Joystick_INEndpoint; | 136 | USB_Descriptor_Endpoint_t Joystick_INEndpoint; |
| 137 | #endif | 137 | #endif |
| 138 | |||
| 139 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 140 | // Digitizer HID Interface | ||
| 141 | USB_Descriptor_Interface_t Digitizer_Interface; | ||
| 142 | USB_HID_Descriptor_HID_t Digitizer_HID; | ||
| 143 | USB_Descriptor_Endpoint_t Digitizer_INEndpoint; | ||
| 144 | #endif | ||
| 138 | } USB_Descriptor_Configuration_t; | 145 | } USB_Descriptor_Configuration_t; |
| 139 | 146 | ||
| 140 | /* | 147 | /* |
| @@ -180,6 +187,10 @@ enum usb_interfaces { | |||
| 180 | #if defined(JOYSTICK_ENABLE) | 187 | #if defined(JOYSTICK_ENABLE) |
| 181 | JOYSTICK_INTERFACE, | 188 | JOYSTICK_INTERFACE, |
| 182 | #endif | 189 | #endif |
| 190 | |||
| 191 | #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) | ||
| 192 | DIGITIZER_INTERFACE, | ||
| 193 | #endif | ||
| 183 | TOTAL_INTERFACES | 194 | TOTAL_INTERFACES |
| 184 | }; | 195 | }; |
| 185 | 196 | ||
| @@ -226,7 +237,7 @@ enum usb_endpoints { | |||
| 226 | # if STM32_USB_USE_OTG1 | 237 | # if STM32_USB_USE_OTG1 |
| 227 | # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM | 238 | # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM |
| 228 | # else | 239 | # else |
| 229 | CONSOLE_OUT_EPNUM = NEXT_EPNUM, | 240 | CONSOLE_OUT_EPNUM = NEXT_EPNUM, |
| 230 | # endif | 241 | # endif |
| 231 | # else | 242 | # else |
| 232 | # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM | 243 | # define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM |
| @@ -259,6 +270,19 @@ enum usb_endpoints { | |||
| 259 | JOYSTICK_OUT_EPNUM = NEXT_EPNUM, | 270 | JOYSTICK_OUT_EPNUM = NEXT_EPNUM, |
| 260 | # endif | 271 | # endif |
| 261 | #endif | 272 | #endif |
| 273 | |||
| 274 | #ifdef DIGITIZER_ENABLE | ||
| 275 | # if !defined(DIGITIZER_SHARED_EP) | ||
| 276 | DIGITIZER_IN_EPNUM = NEXT_EPNUM, | ||
| 277 | # if STM32_USB_USE_OTG1 | ||
| 278 | DIGITIZER_OUT_EPNUM = DIGITIZER_IN_EPNUM, | ||
| 279 | # else | ||
| 280 | DIGITIZER_OUT_EPNUM = NEXT_EPNUM, | ||
| 281 | # endif | ||
| 282 | # else | ||
| 283 | # define DIGITIZER_IN_EPNUM SHARED_IN_EPNUM | ||
| 284 | # endif | ||
| 285 | #endif | ||
| 262 | }; | 286 | }; |
| 263 | 287 | ||
| 264 | #ifdef PROTOCOL_LUFA | 288 | #ifdef PROTOCOL_LUFA |
| @@ -284,5 +308,6 @@ enum usb_endpoints { | |||
| 284 | #define CDC_NOTIFICATION_EPSIZE 8 | 308 | #define CDC_NOTIFICATION_EPSIZE 8 |
| 285 | #define CDC_EPSIZE 16 | 309 | #define CDC_EPSIZE 16 |
| 286 | #define JOYSTICK_EPSIZE 8 | 310 | #define JOYSTICK_EPSIZE 8 |
| 311 | #define DIGITIZER_EPSIZE 8 | ||
| 287 | 312 | ||
| 288 | uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress); | 313 | uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress); |
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 98cebf601..485b20c90 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c | |||
| @@ -292,6 +292,14 @@ static void send_consumer(uint16_t data) { | |||
| 292 | #endif | 292 | #endif |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | void send_digitizer(report_digitizer_t *report) { | ||
| 296 | #ifdef DIGITIZER_ENABLE | ||
| 297 | if (usbInterruptIsReadyShared()) { | ||
| 298 | usbSetInterruptShared((void *)report, sizeof(report_digitizer_t)); | ||
| 299 | } | ||
| 300 | #endif | ||
| 301 | } | ||
| 302 | |||
| 295 | /*------------------------------------------------------------------* | 303 | /*------------------------------------------------------------------* |
| 296 | * Request from host * | 304 | * Request from host * |
| 297 | *------------------------------------------------------------------*/ | 305 | *------------------------------------------------------------------*/ |
| @@ -510,8 +518,46 @@ const PROGMEM uchar shared_hid_report[] = { | |||
| 510 | 0x95, 0x01, // Report Count (1) | 518 | 0x95, 0x01, // Report Count (1) |
| 511 | 0x75, 0x10, // Report Size (16) | 519 | 0x75, 0x10, // Report Size (16) |
| 512 | 0x81, 0x00, // Input (Data, Array, Absolute) | 520 | 0x81, 0x00, // Input (Data, Array, Absolute) |
| 513 | 0xC0 // End Collection | 521 | 0xC0, // End Collection |
| 522 | #endif | ||
| 523 | |||
| 524 | #ifdef DIGITIZER_ENABLE | ||
| 525 | // Digitizer report descriptor | ||
| 526 | 0x05, 0x0D, // Usage Page (Digitizers) | ||
| 527 | 0x09, 0x01, // Usage (Digitizer) | ||
| 528 | 0xA1, 0x01, // Collection (Application) | ||
| 529 | 0x85, REPORT_ID_DIGITIZER, // Report ID | ||
| 530 | 0x09, 0x22, // Usage (Finger) | ||
| 531 | 0xA1, 0x00, // Collection (Physical) | ||
| 532 | // Tip Switch (1 bit) | ||
| 533 | 0x09, 0x42, // Usage (Tip Switch) | ||
| 534 | 0x15, 0x00, // Logical Minimum | ||
| 535 | 0x25, 0x01, // Logical Maximum | ||
| 536 | 0x95, 0x01, // Report Count (1) | ||
| 537 | 0x75, 0x01, // Report Size (16) | ||
| 538 | 0x81, 0x02, // Input (Data, Variable, Absolute) | ||
| 539 | // In Range (1 bit) | ||
| 540 | 0x09, 0x32, // Usage (In Range) | ||
| 541 | 0x81, 0x02, // Input (Data, Variable, Absolute) | ||
| 542 | // Padding (6 bits) | ||
| 543 | 0x95, 0x06, // Report Count (6) | ||
| 544 | 0x81, 0x03, // Input (Constant) | ||
| 545 | |||
| 546 | // X/Y Position (4 bytes) | ||
| 547 | 0x05, 0x01, // Usage Page (Generic Desktop) | ||
| 548 | 0x26, 0xFF, 0x7F, // Logical Maximum (32767) | ||
| 549 | 0x95, 0x01, // Report Count (1) | ||
| 550 | 0x75, 0x10, // Report Size (16) | ||
| 551 | 0x65, 0x33, // Unit (Inch, English Linear) | ||
| 552 | 0x55, 0x0E, // Unit Exponent (-2) | ||
| 553 | 0x09, 0x30, // Usage (X) | ||
| 554 | 0x81, 0x02, // Input (Data, Variable, Absolute) | ||
| 555 | 0x09, 0x31, // Usage (Y) | ||
| 556 | 0x81, 0x02, // Input (Data, Variable, Absolute) | ||
| 557 | 0xC0, // End Collection | ||
| 558 | 0xC0 // End Collection | ||
| 514 | #endif | 559 | #endif |
| 560 | |||
| 515 | #ifdef SHARED_EP_ENABLE | 561 | #ifdef SHARED_EP_ENABLE |
| 516 | }; | 562 | }; |
| 517 | #endif | 563 | #endif |
