aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol
diff options
context:
space:
mode:
authora-chol <a-chol@users.noreply.github.com>2021-08-17 20:52:44 +0200
committerGitHub <noreply@github.com>2021-08-18 04:52:44 +1000
commit75b49aff56436c57a424e622c91f6d80e1d0ecc2 (patch)
tree1968a4e939efef6aec0451d4bc991f4494292e22 /tmk_core/protocol
parent7794e97f32fb9dcb07e7fa928cde08691b257fbe (diff)
downloadqmk_firmware-75b49aff56436c57a424e622c91f6d80e1d0ecc2.tar.gz
qmk_firmware-75b49aff56436c57a424e622c91f6d80e1d0ecc2.zip
Digitizer HID interface : absolute coordinates for mouse cursor (#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>
Diffstat (limited to 'tmk_core/protocol')
-rw-r--r--tmk_core/protocol/chibios/main.c1
-rw-r--r--tmk_core/protocol/chibios/usb_main.c28
-rw-r--r--tmk_core/protocol/lufa/lufa.c26
-rw-r--r--tmk_core/protocol/usb_descriptor.c101
-rw-r--r--tmk_core/protocol/usb_descriptor.h27
-rw-r--r--tmk_core/protocol/vusb/vusb.c48
6 files changed, 226 insertions, 5 deletions
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);
65void send_mouse(report_mouse_t *report); 65void send_mouse(report_mouse_t *report);
66void send_system(uint16_t data); 66void send_system(uint16_t data);
67void send_consumer(uint16_t data); 67void send_consumer(uint16_t data);
68void send_digitizer(report_digitizer_t *report);
68 69
69/* host struct */ 70/* host struct */
70host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; 71host_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
944void 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);
142static void send_mouse(report_mouse_t *report); 142static void send_mouse(report_mouse_t *report);
143static void send_system(uint16_t data); 143static void send_system(uint16_t data);
144static void send_consumer(uint16_t data); 144static void send_consumer(uint16_t data);
145host_driver_t lufa_driver = { 145host_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
989void 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
163const USB_Descriptor_HIDReport_Datatype_t PROGMEM DigitizerReport[] = {
164# elif !defined(SHARED_REPORT_STARTED)
165const 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)
162const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { 209const 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
288uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress); 313uint16_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
295void 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