Skip to content

Commit 75b49af

Browse files
a-chola-cholfauxpark
authoredAug 17, 2021
Digitizer HID interface : absolute coordinates for mouse cursor (qmk#12851)
* Add digitizer HID interface for setting the mouse cursor position at absolute screen coordinates. Tested on Pro Micro, Proton C and Blackpill. * Update docs/feature_digitizer.md Co-authored-by: Ryan <fauxpark@gmail.com> * Update tmk_core/protocol/usb_descriptor.c Co-authored-by: Ryan <fauxpark@gmail.com> * Add missing copyrights Add V-USB support * Add support for digitizer dedicated endpoint for lufa and chibios. Fix formatting issues Move digitizer_task definition to the feature's base implementation file * Run cformat on modified files * Change digitizer report usage to Digitizer instead of Pen to avoid pointer disappearing on Windows. * Update tmk_core/protocol/vusb/vusb.c Co-authored-by: Ryan <fauxpark@gmail.com> * Run cformat from docker image * Remove send_digitizer from host_driver_t and instead rely on the declaration being the interface to the implementation in each HW-specific usb implementation. * Fix build : send_digitizer shouldn't be static in vusb and add weak-linkage implementation for tests without usb implementation * Change digitizer user interface to match pointing device's * Update documentation with new API Co-authored-by: a-chol <nothing@none.com> Co-authored-by: Ryan <fauxpark@gmail.com>
1 parent 7794e97 commit 75b49af

File tree

18 files changed

+435
-6
lines changed

18 files changed

+435
-6
lines changed
 

‎common_features.mk

+5
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,11 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), digital)
695695
OPT_DEFS += -DDIGITAL_JOYSTICK_ENABLE
696696
endif
697697

698+
DIGITIZER_ENABLE ?= no
699+
ifneq ($(strip $(DIGITIZER_ENABLE)), no)
700+
SRC += $(QUANTUM_DIR)/digitizer.c
701+
endif
702+
698703
USBPD_ENABLE ?= no
699704
VALID_USBPD_DRIVER_TYPES = custom vendor
700705
USBPD_DRIVER ?= vendor

‎docs/_summary.md

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
* [Bluetooth](feature_bluetooth.md)
109109
* [Bootmagic Lite](feature_bootmagic.md)
110110
* [Custom Matrix](custom_matrix.md)
111+
* [Digitizer](feature_digitizer.md)
111112
* [DIP Switch](feature_dip_switch.md)
112113
* [Encoders](feature_encoders.md)
113114
* [Haptic Feedback](feature_haptic_feedback.md)

‎docs/feature_digitizer.md

+35
Original file line numberDiff line numberDiff line change
@@ -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.
Original file line numberDiff line numberDiff line change
@@ -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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DIGITIZER_ENABLE = yes

‎quantum/digitizer.c

+34
Original file line numberDiff line numberDiff line change
@@ -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+
}

‎quantum/digitizer.h

+41
Original file line numberDiff line numberDiff line change
@@ -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);

‎tmk_core/common.mk

+13
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ ifeq ($(strip $(NO_USB_STARTUP_CHECK)), yes)
106106
TMK_COMMON_DEFS += -DNO_USB_STARTUP_CHECK
107107
endif
108108

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+
109122
ifeq ($(strip $(SHARED_EP_ENABLE)), yes)
110123
TMK_COMMON_DEFS += -DSHARED_EP_ENABLE
111124
endif

‎tmk_core/common/host.c

+19
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2222
#include "host.h"
2323
#include "util.h"
2424
#include "debug.h"
25+
#include "digitizer.h"
2526

2627
#ifdef NKRO_ENABLE
2728
# include "keycode_config.h"
@@ -103,6 +104,24 @@ void host_consumer_send(uint16_t report) {
103104
(*driver->send_consumer)(report);
104105
}
105106

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+
106125
uint16_t host_last_system_report(void) { return last_system_report; }
107126

108127
uint16_t host_last_consumer_report(void) { return last_consumer_report; }

‎tmk_core/common/host_driver.h

+2
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,5 @@ typedef struct {
3030
void (*send_system)(uint16_t);
3131
void (*send_consumer)(uint16_t);
3232
} host_driver_t;
33+
34+
void send_digitizer(report_digitizer_t *report);

‎tmk_core/common/keyboard.c

+7
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
106106
#if defined(CRC_ENABLE)
107107
# include "crc.h"
108108
#endif
109+
#ifdef DIGITIZER_ENABLE
110+
# include "digitizer.h"
111+
#endif
109112

110113
static uint32_t last_input_modification_time = 0;
111114
uint32_t last_input_activity_time(void) { return last_input_modification_time; }
@@ -537,6 +540,10 @@ void keyboard_task(void) {
537540
joystick_task();
538541
#endif
539542

543+
#ifdef DIGITIZER_ENABLE
544+
digitizer_task();
545+
#endif
546+
540547
// update LED
541548
if (led_status != host_keyboard_leds()) {
542549
led_status = host_keyboard_leds();

‎tmk_core/common/report.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ enum hid_report_ids {
3030
REPORT_ID_SYSTEM,
3131
REPORT_ID_CONSUMER,
3232
REPORT_ID_NKRO,
33-
REPORT_ID_JOYSTICK
33+
REPORT_ID_JOYSTICK,
34+
REPORT_ID_DIGITIZER
3435
};
3536

3637
/* Mouse buttons */
@@ -205,6 +206,17 @@ typedef struct {
205206
int8_t h;
206207
} __attribute__((packed)) report_mouse_t;
207208

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+
208220
typedef struct {
209221
#if JOYSTICK_AXES_COUNT > 0
210222
# if JOYSTICK_AXES_RESOLUTION > 8

‎tmk_core/protocol/chibios/main.c

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ void send_keyboard(report_keyboard_t *report);
6565
void send_mouse(report_mouse_t *report);
6666
void send_system(uint16_t data);
6767
void send_consumer(uint16_t data);
68+
void send_digitizer(report_digitizer_t *report);
6869

6970
/* host struct */
7071
host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};

‎tmk_core/protocol/chibios/usb_main.c

+28
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ typedef struct {
315315
#endif
316316
#ifdef JOYSTICK_ENABLE
317317
usb_driver_config_t joystick_driver;
318+
#endif
319+
#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP)
320+
usb_driver_config_t digitizer_driver;
318321
#endif
319322
};
320323
usb_driver_config_t array[0];
@@ -360,6 +363,14 @@ static usb_driver_configs_t drivers = {
360363
# define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
361364
.joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
362365
#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
363374
};
364375

365376
#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
@@ -930,6 +941,23 @@ void send_consumer(uint16_t data) {
930941
#endif
931942
}
932943

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+
933961
/* ---------------------------------------------------------
934962
* Console functions
935963
* ---------------------------------------------------------

‎tmk_core/protocol/lufa/lufa.c

+23-3
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,7 @@ static void send_keyboard(report_keyboard_t *report);
142142
static void send_mouse(report_mouse_t *report);
143143
static void send_system(uint16_t data);
144144
static void send_consumer(uint16_t data);
145-
host_driver_t lufa_driver = {
146-
keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer,
147-
};
145+
host_driver_t lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer};
148146

149147
#ifdef VIRTSER_ENABLE
150148
// clang-format off
@@ -525,6 +523,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
525523
/* Setup joystick endpoint */
526524
ConfigSuccess &= Endpoint_ConfigureEndpoint((JOYSTICK_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, JOYSTICK_EPSIZE, 1);
527525
#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
528531
}
529532

530533
/* FIXME: Expose this table in the docs somehow
@@ -983,6 +986,23 @@ void virtser_send(const uint8_t byte) {
983986
}
984987
#endif
985988

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+
9861006
/*******************************************************************************
9871007
* main
9881008
******************************************************************************/

‎tmk_core/protocol/usb_descriptor.c

+101
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,53 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
158158
# endif
159159
#endif
160160

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+
161208
#if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED)
162209
const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
163210
#endif
@@ -227,6 +274,7 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {
227274
HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
228275
HID_RI_END_COLLECTION(0),
229276
#endif
277+
230278
#ifdef SHARED_EP_ENABLE
231279
};
232280
#endif
@@ -921,6 +969,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
921969
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
922970
}
923971
#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
9241012
};
9251013

9261014
/*
@@ -1059,6 +1147,13 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
10591147
Size = sizeof(USB_HID_Descriptor_HID_t);
10601148
break;
10611149
#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
10621157
}
10631158

10641159
break;
@@ -1108,6 +1203,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
11081203
Address = &JoystickReport;
11091204
Size = sizeof(JoystickReport);
11101205
break;
1206+
#endif
1207+
#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP)
1208+
case DIGITIZER_INTERFACE:
1209+
Address = &DigitizerReport;
1210+
Size = sizeof(DigitizerReport);
1211+
break;
11111212
#endif
11121213
}
11131214

‎tmk_core/protocol/usb_descriptor.h

+26-1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ typedef struct {
135135
USB_HID_Descriptor_HID_t Joystick_HID;
136136
USB_Descriptor_Endpoint_t Joystick_INEndpoint;
137137
#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
138145
} USB_Descriptor_Configuration_t;
139146

140147
/*
@@ -180,6 +187,10 @@ enum usb_interfaces {
180187
#if defined(JOYSTICK_ENABLE)
181188
JOYSTICK_INTERFACE,
182189
#endif
190+
191+
#if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP)
192+
DIGITIZER_INTERFACE,
193+
#endif
183194
TOTAL_INTERFACES
184195
};
185196

@@ -226,7 +237,7 @@ enum usb_endpoints {
226237
# if STM32_USB_USE_OTG1
227238
# define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM
228239
# else
229-
CONSOLE_OUT_EPNUM = NEXT_EPNUM,
240+
CONSOLE_OUT_EPNUM = NEXT_EPNUM,
230241
# endif
231242
# else
232243
# define CONSOLE_OUT_EPNUM CONSOLE_IN_EPNUM
@@ -259,6 +270,19 @@ enum usb_endpoints {
259270
JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
260271
# endif
261272
#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
262286
};
263287

264288
#ifdef PROTOCOL_LUFA
@@ -284,5 +308,6 @@ enum usb_endpoints {
284308
#define CDC_NOTIFICATION_EPSIZE 8
285309
#define CDC_EPSIZE 16
286310
#define JOYSTICK_EPSIZE 8
311+
#define DIGITIZER_EPSIZE 8
287312

288313
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);

‎tmk_core/protocol/vusb/vusb.c

+47-1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ static void send_consumer(uint16_t data) {
292292
#endif
293293
}
294294

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+
295303
/*------------------------------------------------------------------*
296304
* Request from host *
297305
*------------------------------------------------------------------*/
@@ -510,8 +518,46 @@ const PROGMEM uchar shared_hid_report[] = {
510518
0x95, 0x01, // Report Count (1)
511519
0x75, 0x10, // Report Size (16)
512520
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
514559
#endif
560+
515561
#ifdef SHARED_EP_ENABLE
516562
};
517563
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.