diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index c88ce36011c8..7ad1cf4bde96 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -855,6 +855,14 @@ ifeq ($(strip $(JOYSTICK_ENABLE)), yes) endif endif +FRAMEWORK_TOUCHPAD_ENABLE ?= no +ifeq ($(strip $(FRAMEWORK_TOUCHPAD_ENABLE)), yes) + OPT_DEFS += -DFRAMEWORK_TOUCHPAD_ENABLE + SRC += $(QUANTUM_DIR)/framework_touchpad.c + + I2C_DRIVER_REQUIRED = yes +endif + USBPD_ENABLE ?= no VALID_USBPD_DRIVER_TYPES = custom vendor USBPD_DRIVER ?= vendor diff --git a/quantum/framework_touchpad.c b/quantum/framework_touchpad.c new file mode 100644 index 000000000000..2f093e533868 --- /dev/null +++ b/quantum/framework_touchpad.c @@ -0,0 +1,48 @@ +/* Copyright 2025 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "framework_touchpad.h" +#include "i2c_master.h" +#include "print.h" + +#define FRAMEWORK_TOUCHPAD_I2C_ADDRESS (0x2c << 1) + +void framework_touchpad_init(void) { + i2c_init(); +} + +void framework_touchpad_task(void) { + int length = 0; + int status = I2C_STATUS_SUCCESS; + uint8_t buffer[37] = {0}; + uint8_t report[34] = {0}; + + status = i2c_receive(FRAMEWORK_TOUCHPAD_I2C_ADDRESS, buffer, 1, 100); + length = buffer[0]; + if (status != I2C_STATUS_SUCCESS || buffer[0] <= 0) { + return; + } + + status = i2c_receive(FRAMEWORK_TOUCHPAD_I2C_ADDRESS, buffer, length, 100); + if (status != I2C_STATUS_SUCCESS || buffer[2] != 0x01) { + return; + } + + memcpy(report, buffer + 3, 34); + + void host_framework_touchpad_send(uint8_t(*report)[34]); + host_framework_touchpad_send(&report); +} \ No newline at end of file diff --git a/quantum/framework_touchpad.h b/quantum/framework_touchpad.h new file mode 100644 index 000000000000..0656ec329626 --- /dev/null +++ b/quantum/framework_touchpad.h @@ -0,0 +1,27 @@ +/* Copyright 2025 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +/** + * \brief Handle the initialization of the subsystem. + */ +void framework_touchpad_init(void); + +/** + * \brief Handle various subsystem background tasks. + */ +void framework_touchpad_task(void); \ No newline at end of file diff --git a/quantum/keyboard.c b/quantum/keyboard.c index d7836cf36e00..5c097777421c 100644 --- a/quantum/keyboard.c +++ b/quantum/keyboard.c @@ -92,6 +92,9 @@ along with this program. If not, see . #ifdef JOYSTICK_ENABLE # include "joystick.h" #endif +#ifdef FRAMEWORK_TOUCHPAD_ENABLE +# include "framework_touchpad.h" +#endif #ifdef HD44780_ENABLE # include "hd44780.h" #endif @@ -469,6 +472,9 @@ void keyboard_init(void) { #ifdef JOYSTICK_ENABLE joystick_init(); #endif +#ifdef FRAMEWORK_TOUCHPAD_ENABLE + framework_touchpad_init(); +#endif #ifdef SLEEP_LED_ENABLE sleep_led_init(); #endif @@ -742,6 +748,10 @@ void keyboard_task(void) { joystick_task(); #endif +#ifdef FRAMEWORK_TOUCHPAD_ENABLE + framework_touchpad_task(); +#endif + #ifdef BLUETOOTH_ENABLE bluetooth_task(); #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index 9db88a54d4ba..70cec38e692b 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -194,6 +194,10 @@ extern layer_state_t layer_state; # include "digitizer.h" #endif +#ifdef FRAMEWORK_TOUCHPAD_ENABLE +# include "framework_touchpad.h" +#endif + #ifdef VIA_ENABLE # include "via.h" #endif diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk index 8f019765484a..ff9eafbbb42f 100644 --- a/tmk_core/protocol.mk +++ b/tmk_core/protocol.mk @@ -92,6 +92,14 @@ ifeq ($(strip $(DIGITIZER_ENABLE)), yes) endif endif +ifeq ($(strip $(FRAMEWORK_TOUCHPAD_ENABLE)), yes) + OPT_DEFS += -DFRAMEWORK_TOUCHPAD_ENABLE + ifeq ($(strip $(SHARED_EP_ENABLE)), yes) + OPT_DEFS += -DFRAMEWORK_TOUCHPAD_SHARED_EP + SHARED_EP_ENABLE = yes + endif +endif + ifeq ($(strip $(SHARED_EP_ENABLE)), yes) OPT_DEFS += -DSHARED_EP_ENABLE endif diff --git a/tmk_core/protocol/chibios/usb_endpoints.c b/tmk_core/protocol/chibios/usb_endpoints.c index 856df6242603..5f0bd2382e30 100644 --- a/tmk_core/protocol/chibios/usb_endpoints.c +++ b/tmk_core/protocol/chibios/usb_endpoints.c @@ -64,6 +64,10 @@ usb_endpoint_in_t usb_endpoints_in[USB_ENDPOINT_IN_COUNT] = { [USB_ENDPOINT_IN_DIGITIZER] = QMK_USB_ENDPOINT_IN(USB_EP_MODE_TYPE_INTR, DIGITIZER_EPSIZE, DIGITIZER_IN_EPNUM, DIGITIZER_IN_CAPACITY, NULL, QMK_USB_REPORT_STORAGE_DEFAULT(sizeof(report_digitizer_t))), #endif +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + [USB_ENDPOINT_IN_FRAMEWORK_TOUCHPAD] = QMK_USB_ENDPOINT_IN(USB_EP_MODE_TYPE_INTR, DIGITIZER_EPSIZE, DIGITIZER_IN_EPNUM, DIGITIZER_IN_CAPACITY, NULL, QMK_USB_REPORT_STORAGE_DEFAULT(sizeof(report_digitizer_t))), +#endif + #if defined(CONSOLE_ENABLE) # if defined(USB_ENDPOINTS_ARE_REORDERABLE) [USB_ENDPOINT_IN_CONSOLE] = QMK_USB_ENDPOINT_IN_SHARED(USB_EP_MODE_TYPE_INTR, CONSOLE_EPSIZE, CONSOLE_IN_EPNUM, CONSOLE_IN_CAPACITY, NULL, QMK_USB_REPORT_STORAGE_DEFAULT(CONSOLE_EPSIZE)), @@ -135,6 +139,10 @@ usb_endpoint_in_lut_t usb_endpoint_interface_lut[TOTAL_INTERFACES] = { #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) [DIGITIZER_INTERFACE] = USB_ENDPOINT_IN_DIGITIZER, #endif + +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + [FRAMEWORK_TOUCHPAD_INTERFACE] = USB_ENDPOINT_IN_FRAMEWORK_TOUCHPAD, +#endif }; usb_endpoint_out_t usb_endpoints_out[USB_ENDPOINT_OUT_COUNT] = { diff --git a/tmk_core/protocol/chibios/usb_endpoints.h b/tmk_core/protocol/chibios/usb_endpoints.h index a4e5ed88fce3..9d234e6ec909 100644 --- a/tmk_core/protocol/chibios/usb_endpoints.h +++ b/tmk_core/protocol/chibios/usb_endpoints.h @@ -82,6 +82,10 @@ typedef enum { USB_ENDPOINT_IN_DIGITIZER, #endif +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + USB_ENDPOINT_IN_FRAMEWORK_TOUCHPAD, +#endif + #if defined(CONSOLE_ENABLE) USB_ENDPOINT_IN_CONSOLE, #endif @@ -116,6 +120,9 @@ typedef enum { # if defined(DIGITIZER_SHARED_EP) USB_ENDPOINT_IN_DIGITIZER = USB_ENDPOINT_IN_SHARED, # endif +# if defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + USB_ENDPOINT_IN_FRAMEWORK_TOUCHPAD = USB_ENDPOINT_IN_SHARED, +# endif #endif } usb_endpoint_in_lut_t; diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 5a5354416f48..4fb807959fd2 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -497,6 +497,12 @@ void send_digitizer(report_digitizer_t *report) { #endif } +void send_framework_touchpad(report_framework_touchpad_t *report) { +#ifdef FRAMEWORK_TOUCHPAD_ENABLE + send_report(USB_ENDPOINT_IN_FRAMEWORK_TOUCHPAD, report, sizeof(report_framework_touchpad_t)); +#endif +} + /* --------------------------------------------------------- * Console functions * --------------------------------------------------------- diff --git a/tmk_core/protocol/host.c b/tmk_core/protocol/host.c index df805c827c2a..64232ec52738 100644 --- a/tmk_core/protocol/host.c +++ b/tmk_core/protocol/host.c @@ -26,6 +26,10 @@ along with this program. If not, see . # include "digitizer.h" #endif +#ifdef FRAMEWORK_TOUCHPAD_ENABLE +# include "framework_touchpad.h" +#endif + #ifdef JOYSTICK_ENABLE # include "joystick.h" #endif @@ -240,6 +244,23 @@ void host_digitizer_send(digitizer_t *digitizer) { __attribute__((weak)) void send_digitizer(report_digitizer_t *report) {} +#ifdef FRAMEWORK_TOUCHPAD_ENABLE +void host_framework_touchpad_send(uint8_t (*data)[34]) { + report_framework_touchpad_t report = { +# ifdef FRAMEWORK_TOUCHPAD_SHARED_EP + .report_id = REPORT_ID_FRAMEWORK_TOUCHPAD, +# endif + .report = {0}, + }; + + memcpy(report.report, data, 34); + + send_framework_touchpad(&report); +} +#endif + +__attribute__((weak)) void send_framework_touchpad(report_framework_touchpad_t *report) {} + #ifdef PROGRAMMABLE_BUTTON_ENABLE void host_programmable_button_send(uint32_t data) { report_programmable_button_t report = { diff --git a/tmk_core/protocol/host_driver.h b/tmk_core/protocol/host_driver.h index 8aa38b6dee2c..a364012624b0 100644 --- a/tmk_core/protocol/host_driver.h +++ b/tmk_core/protocol/host_driver.h @@ -33,4 +33,5 @@ typedef struct { void send_joystick(report_joystick_t *report); void send_digitizer(report_digitizer_t *report); +void send_framework_touchpad(report_framework_touchpad_t *report); void send_programmable_button(report_programmable_button_t *report); diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 81da035f0c03..fe0ca543b4ee 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -385,6 +385,11 @@ void EVENT_USB_Device_ConfigurationChanged(void) { ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1); #endif +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + /* Setup digitizer endpoint */ + ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1); +#endif + usb_device_state_set_configuration(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber); } diff --git a/tmk_core/protocol/report.h b/tmk_core/protocol/report.h index d854f51d5c45..13c8c9a6a50d 100644 --- a/tmk_core/protocol/report.h +++ b/tmk_core/protocol/report.h @@ -39,6 +39,7 @@ enum hid_report_ids { REPORT_ID_NKRO, REPORT_ID_JOYSTICK, REPORT_ID_DIGITIZER, + REPORT_ID_FRAMEWORK_TOUCHPAD, REPORT_ID_COUNT = REPORT_ID_DIGITIZER }; @@ -232,6 +233,13 @@ typedef struct { uint16_t y; } PACKED report_digitizer_t; +typedef struct { +#ifdef FRAMEWORK_TOUCHPAD_SHARED_EP + uint8_t report_id; +#endif + uint8_t report[34]; +} PACKED report_framework_touchpad_t; + #if JOYSTICK_AXIS_RESOLUTION > 8 typedef int16_t joystick_axis_t; #else diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index c7fb660b65d6..c3c4ebc2c066 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -332,6 +332,191 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { # endif #endif +#ifdef FRAMEWORK_TOUCHPAD_ENABLE +# ifndef FRAMEWORK_TOUCHPAD_SHARED_EP +const USB_Descriptor_HIDReport_Datatype_t PROGMEM TouchPadReport[] = { +# elif !defined(SHARED_REPORT_STARTED) +const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { +# define SHARED_REPORT_STARTED +# endif + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x05), // Usage (Touch Pad) + HID_RI_COLLECTION(8, 0x01), // Collection (Application) +# ifdef FRAMEWORK_TOUCHPAD_SHARED_EP + HID_RI_REPORT_ID(8, REPORT_ID_FRAMEWORK_TOUCHPAD), +# endif + +#define FINGER(FINGER_NUMBER) \ + HID_RI_USAGE_PAGE(8, 0x0D), /* Usage Page (Digitizer) */ \ + HID_RI_USAGE(8, 0x22), /* Usage (Finger) */ \ + HID_RI_COLLECTION(8, 0x02), /* Collection (Logical) */ \ + HID_RI_USAGE(8, 0x47), /* Usage (0x47) */ \ + HID_RI_USAGE(8, 0x42), /* Usage (Tip Switch) */ \ + HID_RI_LOGICAL_MINIMUM(8, 0x00), /* Logical Minimum (0) */ \ + HID_RI_LOGICAL_MAXIMUM(8, 0x01), /* Logical Maximum (1) */ \ + HID_RI_REPORT_SIZE(8, 0x01), /* Report Size (1) */ \ + HID_RI_REPORT_COUNT(8, 0x02), /* Report Count (2) */ \ + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */ \ + HID_RI_REPORT_COUNT(8, 0x06), /* Report Count (6) */ \ + HID_RI_INPUT(8, HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), /* Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */ \ + HID_RI_USAGE(8, 0x51), /* Usage (0x51) */ \ + HID_RI_LOGICAL_MAXIMUM(8, 0x0F), /* Logical Maximum (15) */ \ + HID_RI_REPORT_SIZE(8, 0x08), /* Report Size (8) */ \ + HID_RI_REPORT_COUNT(8, 0x01), /* Report Count (1) */ \ + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */ \ + HID_RI_USAGE_PAGE(8, 0x01), /* Usage Page (Generic Desktop Ctrls) */ \ + HID_RI_USAGE(8, 0x30), /* Usage (X) */ \ + HID_RI_REPORT_SIZE(8, 0x10), /* Report Size (16) */ \ + HID_RI_UNIT_EXPONENT(8, 0x0E), /* Unit Exponent (-2) */ \ + HID_RI_UNIT(8, 0x11), /* Unit (System: SI Linear, Length: Centimeter) */ \ + HID_RI_PHYSICAL_MINIMUM(8, 0x00), /* Physical Minimum (0) */ \ + HID_RI_PHYSICAL_MAXIMUM(16, 0x045A), /* Physical Maximum (1114) */ \ + HID_RI_LOGICAL_MAXIMUM(32, 0x00000539), /* Logical Maximum (1336) */ \ + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */ \ + HID_RI_USAGE(8, 0x31), /* Usage (Y) */ \ + HID_RI_PHYSICAL_MAXIMUM(16, 0x02DA), /* Physical Maximum (730) */ \ + HID_RI_LOGICAL_MAXIMUM(32, 0x0000036C), /* Logical Maximum (875) */ \ + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), /* Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) */ \ + HID_RI_END_COLLECTION(0), /* End Collection */ + + FINGER(1) + FINGER(2) + FINGER(3) + FINGER(4) + FINGER(5) + +#undef FINGER + + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x54), // Usage (0x54) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x05), // Logical Maximum (5) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + HID_RI_USAGE_PAGE(8, 0x09), // Usage Page (Button) + HID_RI_USAGE(8, 0x01), // Usage (0x01) + HID_RI_USAGE(8, 0x02), // Usage (0x02) + HID_RI_USAGE(8, 0x03), // Usage (0x03) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x01), // Logical Maximum (1) + HID_RI_REPORT_SIZE(8, 0x01), // Report Size (1) + HID_RI_REPORT_COUNT(8, 0x03), // Report Count (3) + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + HID_RI_REPORT_COUNT(8, 0x05), // Report Count (5) + HID_RI_INPUT(8, HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x56), // Usage (0x56) + HID_RI_UNIT_EXPONENT(8, 0x0C), // Unit Exponent (-4) + HID_RI_UNIT(16, 0x1001), // Unit (System: SI Linear, Time: Seconds) + HID_RI_PHYSICAL_MINIMUM(8, 0x00), // Physical Minimum (0) + HID_RI_PHYSICAL_MAXIMUM(32, 0x0000FFFF), // Physical Maximum (65534) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(32, 0x0000FFFF), // Logical Maximum (65534) + HID_RI_REPORT_SIZE(8, 0x10), // Report Size (16) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION), // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x55), // Usage (0x55) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x05), // Logical Maximum (5) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_REPORT_ID(8, 0x03), // Report ID (3) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x59), // Usage (0x59) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x0F), // Logical Maximum (15) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_REPORT_ID(8, 0x04), // Report ID (4) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_USAGE_PAGE(16, 0xFF00), // Usage Page (Vendor Defined 0xFF00) + HID_RI_REPORT_ID(8, 0x05), // Report ID (5) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_USAGE(8, 0xC6), // Usage (0xC6) + HID_RI_LOGICAL_MAXIMUM(8, 0x08), // Logical Maximum (8) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_USAGE(8, 0xC7), // Usage (0xC7) + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), // Logical Maximum (255) + HID_RI_REPORT_COUNT(8, 0x20), // Report Count (32) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_END_COLLECTION(0), // End Collection + + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x0E), // Usage (0x0E) + HID_RI_COLLECTION(8, 0x01), // Collection (Application) + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x22), // Usage (Finger) + HID_RI_COLLECTION(8, 0x02), // Collection (Logical) + HID_RI_USAGE(8, 0x52), // Usage (0x52) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x0A), // Logical Maximum (10) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_REPORT_ID(8, 0x06), // Report ID (6) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_END_COLLECTION(0), // End Collection + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x22), // Usage (Finger) + HID_RI_COLLECTION(8, 0x00), // Collection (Physical) + HID_RI_USAGE(8, 0x57), // Usage (0x57) + HID_RI_USAGE(8, 0x58), // Usage (0x58) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x01), // Logical Maximum (1) + HID_RI_REPORT_SIZE(8, 0x01), // Report Size (1) + HID_RI_REPORT_COUNT(8, 0x02), // Report Count (2) + HID_RI_REPORT_ID(8, 0x07), // Report ID (7) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_REPORT_COUNT(8, 0x06), // Report Count (6) + HID_RI_FEATURE(8, HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_END_COLLECTION(0), // End Collection + HID_RI_USAGE_PAGE(8, 0x0D), // Usage Page (Digitizer) + HID_RI_USAGE(8, 0x60), // Usage (0x60) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(8, 0x01), // Logical Maximum (1) + HID_RI_REPORT_SIZE(8, 0x01), // Report Size (1) + HID_RI_REPORT_COUNT(8, 0x01), // Report Count (1) + HID_RI_REPORT_ID(8, 0x08), // Report ID (8) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_REPORT_COUNT(8, 0x07), // Report Count (7) + HID_RI_FEATURE(8, HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_END_COLLECTION(0), // End Collection + HID_RI_USAGE_PAGE(16, 0xFF00), // Usage Page (Vendor Defined 0xFF00) + HID_RI_USAGE(8, 0x01), // Usage (0x01) + HID_RI_COLLECTION(8, 0x01), // Collection (Application) + HID_RI_REPORT_ID(8, 0x42), // Report ID (66) + HID_RI_USAGE(8, 0x06), // Usage (0x06) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), // Logical Maximum (255) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(8, 0x03), // Report Count (3) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_USAGE_PAGE(16, 0xFF00), // Usage Page (Vendor Defined 0xFF00) + HID_RI_USAGE(8, 0x05), // Usage (0x05) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), // Logical Maximum (255) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(16, 0x0100), // Report Count (256) + HID_RI_REPORT_ID(8, 0x41), // Report ID (65) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_REPORT_ID(8, 0x43), // Report ID (67) + HID_RI_USAGE(8, 0x06), // Usage (0x06) + HID_RI_LOGICAL_MINIMUM(8, 0x00), // Logical Minimum (0) + HID_RI_LOGICAL_MAXIMUM(16, 0x00FF), // Logical Maximum (255) + HID_RI_REPORT_SIZE(8, 0x08), // Report Size (8) + HID_RI_REPORT_COUNT(8, 0x03), // Report Count (3) + HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NO_WRAP | HID_IOF_LINEAR | HID_IOF_PREFERRED_STATE | HID_IOF_NO_NULL_POSITION | HID_IOF_NON_VOLATILE), // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + HID_RI_END_COLLECTION(0), // End Collection + +# ifndef FRAMEWORK_TOUCHPAD_SHARED_EP +}; +# endif +#endif + #if defined(SHARED_EP_ENABLE) && !defined(SHARED_REPORT_STARTED) const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { #endif @@ -1073,6 +1258,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = { .PollingIntervalMS = USB_POLLING_INTERVAL_MS }, #endif + +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + /* + * Digitizer + */ + .Framework_Touchpad_Interface = { + .Header = { + .Size = sizeof(USB_Descriptor_Interface_t), + .Type = DTYPE_Interface + }, + .InterfaceNumber = FRAMEWORK_TOUCHPAD_INTERFACE, + .AlternateSetting = 0x00, + .TotalEndpoints = 1, + .Class = HID_CSCP_HIDClass, + .SubClass = HID_CSCP_NonBootSubclass, + .Protocol = HID_CSCP_NonBootProtocol, + .InterfaceStrIndex = NO_DESCRIPTOR + }, + .Framework_Touchpad_HID = { + .Header = { + .Size = sizeof(USB_HID_Descriptor_HID_t), + .Type = HID_DTYPE_HID + }, + .HIDSpec = VERSION_BCD(1, 1, 1), + .CountryCode = 0x00, + .TotalReportDescriptors = 1, + .HIDReportType = HID_DTYPE_Report, + .HIDReportLength = sizeof(TouchPadReport) + }, + .Framework_Touchpad_INEndpoint = { + .Header = { + .Size = sizeof(USB_Descriptor_Endpoint_t), + .Type = DTYPE_Endpoint + }, + .EndpointAddress = (ENDPOINT_DIR_IN | DIGITIZER_IN_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = DIGITIZER_EPSIZE, + .PollingIntervalMS = USB_POLLING_INTERVAL_MS + }, +#endif }; /* diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index 1de8c5ec88a3..775a6e49446d 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -144,6 +144,13 @@ typedef struct { USB_HID_Descriptor_HID_t Digitizer_HID; USB_Descriptor_Endpoint_t Digitizer_INEndpoint; #endif + +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + // Touchpad HID Interface + USB_Descriptor_Interface_t Framework_Touchpad_Interface; + USB_HID_Descriptor_HID_t Framework_Touchpad_HID; + USB_Descriptor_Endpoint_t Framework_Touchpad_INEndpoint; +#endif } USB_Descriptor_Configuration_t; /* @@ -193,6 +200,10 @@ enum usb_interfaces { #if defined(DIGITIZER_ENABLE) && !defined(DIGITIZER_SHARED_EP) DIGITIZER_INTERFACE, #endif + +#if defined(FRAMEWORK_TOUCHPAD_ENABLE) && !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + FRAMEWORK_TOUCHPAD_INTERFACE, +#endif TOTAL_INTERFACES }; @@ -269,6 +280,14 @@ enum usb_endpoints { # define DIGITIZER_IN_EPNUM SHARED_IN_EPNUM # endif #endif + +#ifdef FRAMEWORK_TOUCHPAD_ENABLE +# if !defined(FRAMEWORK_TOUCHPAD_SHARED_EP) + DIGITIZER_IN_EPNUM = NEXT_EPNUM, +# else +# define DIGITIZER_IN_EPNUM SHARED_IN_EPNUM +# endif +#endif }; #ifdef PROTOCOL_LUFA