Skip to content

Commit

Permalink
USB feature reports and further optimisations
Browse files Browse the repository at this point in the history
  • Loading branch information
ReFil committed Aug 18, 2023
1 parent 3998d4c commit 68f3a6b
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 43 deletions.
91 changes: 55 additions & 36 deletions app/include/zmk/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ static const uint8_t zmk_hid_report_desc[] = {
/* USAGE (Finger) */
HID_USAGE(HID_USAGE_DIGITIZERS_FINGER),
/* COLLECTION (Logical) */
HID_COLLECTION(0x02),
HID_COLLECTION(HID_COLLECTION_LOGICAL),
/* LOGICAL_MINIMUM (0) */
HID_LOGICAL_MIN8(0),
/* LOGICAL_MAXIMUM (1) */
Expand Down Expand Up @@ -202,6 +202,43 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_REPORT_SIZE(8),
/* INPUT(Data, Var, Abs) */
HID_INPUT(0x02),
// Button report herre for compat, isn't actuallyy used yet :)
HID_USAGE_PAGE(HID_USAGE_GEN_BUTTON),
/* USAGE (Button 1) */
HID_USAGE(0x01),
HID_USAGE(0x02),
HID_USAGE(0x03),
/* REPORT_SIZE (1) */
HID_REPORT_SIZE(1),
/* REPORT_COUNT (1) */
HID_REPORT_COUNT(3),
/* LOGICAL_MAXIMUM (1) */
HID_LOGICAL_MIN8(0),
HID_LOGICAL_MAX8(1),
/* INPUT (Data, Var, Abs) */
HID_INPUT(0x02),
/* REPORT_SIZE (1) */
HID_REPORT_SIZE(1),
/* REPORT_COUNT (byte padding) */
HID_REPORT_COUNT(1),
/* INPUT (Cnst,Var,Abs) */
HID_INPUT(0x03),
// Surface switch for mac
HID_USAGE_PAGE(HID_USAGE_DIGITIZERS),
/* USAGE (Surface switch) */
HID_USAGE(HID_USAGE_DIGITIZERS_SURFACE_SWITCH),
/* REPORT_COUNT (1) */
HID_REPORT_COUNT(1),
/* REPORT_SIZE (8) */
HID_REPORT_SIZE(1),
/* INPUT(Data, Var, Abs) */
HID_INPUT(0x02),
/* REPORT_SIZE (1) */
HID_REPORT_SIZE(1),
/* REPORT_COUNT (byte padding) */
HID_REPORT_COUNT(3),
/* INPUT (Cnst,Var,Abs) */
HID_INPUT(0x03),

/* Device Capabilities Feature Report */

Expand All @@ -218,6 +255,7 @@ static const uint8_t zmk_hid_report_desc[] = {
/* REPORT_COUNT (2) */
HID_REPORT_COUNT(2),
/* LOGICAL_MAXIMUM (15) */
HID_LOGICAL_MIN8(0),
HID_LOGICAL_MAX8(0x0F),
/* FEATURE (Data, Var, Abs) */
HID_FEATURE(0x02),
Expand All @@ -227,7 +265,7 @@ static const uint8_t zmk_hid_report_desc[] = {
/* USAGE_PAGE (Vendor Defined) */
0x06,
0x00,
0xFF,
0xff,
/* REPORT_ID (0x08) */
HID_REPORT_ID(ZMK_REPORT_ID_FEATURE_PTPHQA),
/* HID_USAGE (Vendor Usage 0xC5) */
Expand All @@ -247,34 +285,11 @@ static const uint8_t zmk_hid_report_desc[] = {
/* END_COLLECTION */
HID_END_COLLECTION,

// TLC
/* USAGE_PAGE (Digitizer) */
HID_USAGE_PAGE(HID_USAGE_DIGITIZERS),
/* USAGE (Configuration) */
HID_USAGE(0x0E),
/* HID_COLLECTION */
HID_COLLECTION(HID_COLLECTION_APPLICATION),
/* REPORT_ID (Feature 0x09) */
HID_REPORT_ID(ZMK_REPORT_ID_FEATURE_PTP_CONFIGURATION),
/* USAGE (Finger) */
HID_USAGE(HID_USAGE_DIGITIZERS_FINGER),
/* COLLECTION (Logical) */
HID_COLLECTION(0x02),
/* USAGE (Input Mode) */
HID_USAGE(0x52),
/* LOGICAL_MINIMUM (0) */
HID_LOGICAL_MIN8(0),
/* LOGICAL_MAXIMUM (10) */
HID_LOGICAL_MAX8(10),
/* REPORT_SIZE (8) */
HID_REPORT_SIZE(8),
/* REPORT_COUNT (1) */
HID_REPORT_COUNT(1),
/* FEATURE (Data, Var, Abs) */
HID_FEATURE(0x02),
/* END_COLLECTION */
HID_END_COLLECTION,

HID_USAGE(HID_USAGE_DIGITIZERS_DEVICE_CONFIGURATION),

HID_COLLECTION(HID_COLLECTION_APPLICATION),
/* USAGE (Finger) */
HID_USAGE(HID_USAGE_DIGITIZERS_FINGER),
/* COLLECTION (Physical) */
Expand All @@ -290,6 +305,7 @@ static const uint8_t zmk_hid_report_desc[] = {
/* REPORT_COUNT (2) */
HID_REPORT_COUNT(2),
/* LOGICAL_MAXIMUM (1) */
HID_LOGICAL_MIN8(0),
HID_LOGICAL_MAX8(1),
/* FEATURE (Data, Var, Abs) */
HID_FEATURE(0x02),
Expand All @@ -299,7 +315,6 @@ static const uint8_t zmk_hid_report_desc[] = {
HID_FEATURE(0x03),
/* END_COLLECTION */
HID_END_COLLECTION,
/* END_COLLECTION */
HID_END_COLLECTION,
#endif

Expand Down Expand Up @@ -359,8 +374,8 @@ struct zmk_hid_ptp_report_body {
struct zmk_ptp_finger finger;
// Contact count
uint8_t contact_count;
// Buttons
// uint8_t buttons;
// Buttons /surfaceswitch
uint8_t buttons;
} __packed;

// Report containing finger data
Expand All @@ -372,16 +387,16 @@ struct zmk_hid_ptp_report {
} __packed;

// Feature report for configuration
struct zmk_ptp_feature_configuration {
struct zmk_hid_ptp_feature_selective_report {
uint8_t report_id;
// 0 for Mouse collection, 3 for Windows Precision Touchpad Collection
uint8_t input_mode;
// Selective reporting: Surface switch (bit 0), Button switch (bit 1)
uint8_t selective_reporting;
} __packed;

// Feature report for certification
struct zmk_ptp_feature_certification {
struct zmk_hid_ptp_feature_certification_report {
uint8_t report_id;

uint8_t ptphqa_blob[256];
} __packed;

Expand All @@ -390,7 +405,7 @@ struct zmk_ptp_feature_certification {
#define PTP_PAD_TYPE_NON_CLICKABLE 0x02

// Feature report for device capabilities
struct zmk_ptp_feature_capabilities {
struct zmk_hid_ptp_feature_capabilities_report {
uint8_t report_id;
// Max touches (L 4bit) and pad type (H 4bit):
// Max touches: number 3-5
Expand Down Expand Up @@ -435,4 +450,8 @@ struct zmk_hid_keyboard_report *zmk_hid_get_keyboard_report();
struct zmk_hid_consumer_report *zmk_hid_get_consumer_report();
#if IS_ENABLED(CONFIG_ZMK_TRACKPAD)
struct zmk_hid_ptp_report *zmk_hid_get_ptp_report();
struct zmk_hid_ptp_feature_selective_report *zmk_hid_ptp_get_feature_selective_report();
void zmk_hid_ptp_set_feature_selective_report(uint8_t selective_report);
struct zmk_hid_ptp_feature_certification_report *zmk_hid_ptp_get_feature_certification_report();
struct zmk_hid_ptp_feature_capabilities_report *zmk_hid_ptp_get_feature_capabilities_report();
#endif
32 changes: 25 additions & 7 deletions app/src/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ static struct zmk_hid_consumer_report consumer_report = {.report_id = 2, .body =
// Report containing finger data
struct zmk_hid_ptp_report ptp_report = {
.report_id = ZMK_REPORT_ID_TRACKPAD,
.body = {.finger = {.confidence_tip = 0, .contact_id = 0, .x = 0, .y = 0}, .contact_count = 0}};
.body = {.finger = {.confidence_tip = 0, .contact_id = 0, .x = 0, .y = 0},
.contact_count = 0,
.buttons = (1 << 4)}};

// Feature report for configuration
struct zmk_ptp_feature_configuration ptp_feature_configuration = {
.report_id = ZMK_REPORT_ID_FEATURE_PTP_CONFIGURATION,
.input_mode = 0,
.selective_reporting = 0};
struct zmk_hid_ptp_feature_selective_report ptp_feature_selective_report = {
.report_id = ZMK_REPORT_ID_FEATURE_PTP_SELECTIVE, .selective_reporting = 3};

// Feature report for ptphqa
struct zmk_ptp_feature_certification ptp_feature_certification = {
struct zmk_hid_ptp_feature_certification_report ptp_feature_certification_report = {
.report_id = ZMK_REPORT_ID_FEATURE_PTPHQA,
.ptphqa_blob = {
0xfc, 0x28, 0xfe, 0x84, 0x40, 0xcb, 0x9a, 0x87, 0x0d, 0xbe, 0x57, 0x3c, 0xb6, 0x70, 0x09,
0x88, 0x07, 0x97, 0x2d, 0x2b, 0xe3, 0x38, 0x34, 0xb6, 0x6c, 0xed, 0xb0, 0xf7, 0xe5, 0x9c,
Expand All @@ -52,7 +53,8 @@ struct zmk_ptp_feature_certification ptp_feature_certification = {
0xc2}};

// Feature report for device capabilities
struct zmk_ptp_feature_capabilities ptp_feature_capabilities = {
struct zmk_hid_ptp_feature_capabilities_report ptp_feature_capabilities_report = {
.report_id = ZMK_REPORT_ID_FEATURE_PTP_CAPABILITIES,
.max_touches_pad_type = CONFIG_ZMK_TRACKPAD_MAX_FINGERS | (PTP_PAD_TYPE_NON_CLICKABLE << 4)};
#endif

Expand Down Expand Up @@ -322,4 +324,20 @@ struct zmk_hid_consumer_report *zmk_hid_get_consumer_report() {
struct zmk_hid_ptp_report *zmk_hid_get_ptp_report() {
return &ptp_report;
}

struct zmk_hid_ptp_feature_selective_report *zmk_hid_ptp_get_feature_selective_report() {
return &ptp_feature_selective_report;
}

void zmk_hid_ptp_set_feature_selective_report(uint8_t selective_report) {
ptp_feature_selective_report.selective_reporting = selective_report;
}

struct zmk_hid_ptp_feature_certification_report *zmk_hid_ptp_get_feature_certification_report() {
return &ptp_feature_certification_report;
}

struct zmk_hid_ptp_feature_capabilities_report *zmk_hid_ptp_get_feature_capabilities_report() {
return &ptp_feature_capabilities_report;
}
#endif
78 changes: 78 additions & 0 deletions app/src/usb_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <zephyr/usb/class/usb_hid.h>

#include <zmk/usb.h>
#include <zmk/usb_hid.h>
#include <zmk/hid.h>
#include <zmk/keymap.h>
#include <zmk/event_manager.h>
Expand All @@ -23,8 +24,85 @@ static K_SEM_DEFINE(hid_sem, 1, 1);

static void in_ready_cb(const struct device *dev) { k_sem_give(&hid_sem); }

#define HID_GET_REPORT_TYPE_MASK 0xff00
#define HID_GET_REPORT_ID_MASK 0x00ff

#define HID_REPORT_TYPE_INPUT 0x100
#define HID_REPORT_TYPE_OUTPUT 0x200
#define HID_REPORT_TYPE_FEATURE 0x300

#if IS_ENABLED(CONFIG_ZMK_TRACKPAD)
static int set_report_cb(const struct device *dev, struct usb_setup_packet *setup, int32_t *len,
uint8_t **data) {
if ((setup->wValue & HID_GET_REPORT_TYPE_MASK) != HID_REPORT_TYPE_FEATURE) {
LOG_ERR("Unsupported report type %d requested",
(setup->wValue & HID_GET_REPORT_TYPE_MASK) >> 8);
return -ENOTSUP;
}
switch (setup->wValue & HID_GET_REPORT_ID_MASK) {
case ZMK_REPORT_ID_FEATURE_PTP_SELECTIVE:
if (*len != sizeof(struct zmk_hid_ptp_feature_selective_report)) {
LOG_ERR("LED set report is malformed: length=%d", *len);
return -EINVAL;
} else {
struct zmk_hid_ptp_feature_selective_report *report =
(struct zmk_hid_ptp_feature_selective_report *)*data;
LOG_DBG("Selective report set %d", report->selective_reporting);
zmk_hid_ptp_set_feature_selective_report(report->selective_reporting);
}
break;
default:
LOG_ERR("Invalid report ID %d requested", setup->wValue & HID_GET_REPORT_ID_MASK);
return -EINVAL;
}

return 0;
}

static int get_report_cb(const struct device *dev, struct usb_setup_packet *setup, int32_t *len,
uint8_t **data) {
if ((setup->wValue & HID_GET_REPORT_TYPE_MASK) != HID_REPORT_TYPE_FEATURE) {
LOG_ERR("Unsupported report type %d requested",
(setup->wValue & HID_GET_REPORT_TYPE_MASK) >> 8);
return -ENOTSUP;
}

switch (setup->wValue & HID_GET_REPORT_ID_MASK) {
case ZMK_REPORT_ID_FEATURE_PTP_SELECTIVE:

*data = (uint8_t *)zmk_hid_ptp_get_feature_selective_report();
LOG_DBG("Selective report get %d", 0);
*len = sizeof(struct zmk_hid_ptp_feature_selective_report);
break;
case ZMK_REPORT_ID_FEATURE_PTPHQA:

*data = (uint8_t *)zmk_hid_ptp_get_feature_certification_report();
LOG_DBG("certification report get %d", 0);
*len = sizeof(struct zmk_hid_ptp_feature_certification_report);

break;
case ZMK_REPORT_ID_FEATURE_PTP_CAPABILITIES:

*data = (uint8_t *)zmk_hid_ptp_get_feature_capabilities_report();
LOG_DBG("capabilities report get %d", 0);
*len = sizeof(struct zmk_hid_ptp_feature_capabilities_report);

break;
default:
LOG_ERR("Invalid report ID %d requested", setup->wValue & HID_GET_REPORT_ID_MASK);
return -EINVAL;
}

return 0;
}
#endif

static const struct hid_ops ops = {
.int_in_ready = in_ready_cb,
#if IS_ENABLED(CONFIG_ZMK_TRACKPAD)
.set_report = set_report_cb,
.get_report = get_report_cb,
#endif
};

int zmk_usb_hid_send_report(const uint8_t *report, size_t len) {
Expand Down

0 comments on commit 68f3a6b

Please sign in to comment.