Skip to content

Commit

Permalink
fix(mouse): Get PTP working on Windows over BLE
Browse files Browse the repository at this point in the history
* Proper characteristic read/write settings for feature reports.
* Make our PTP input reports a tiny bit more compact to bring down
  size.
* Minor: Report correct HID version in our service.
  • Loading branch information
petejohanson committed Mar 29, 2024
1 parent 4208bc4 commit 0edb585
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 35 deletions.
31 changes: 13 additions & 18 deletions app/include/zmk/mouse/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,17 @@
HID_ITEM(HID_ITEM_TAG_UNIT, HID_ITEM_TYPE_GLOBAL, 2), (a & 0xFF), (a >> 8 & 0xFF)

#define TRACKPAD_FINGER_DESC(n, c) \
HID_USAGE(HID_USAGE_DIGITIZERS_FINGER), HID_COLLECTION(HID_COLLECTION_LOGICAL), \
HID_LOGICAL_MIN8(0), HID_LOGICAL_MAX8(1), HID_USAGE(HID_USAGE_DIGITIZERS_TOUCH_VALID), \
HID_USAGE(HID_USAGE_DIGITIZERS_TIP_SWITCH), HID_REPORT_COUNT(2), HID_REPORT_SIZE(1), \
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | \
ZMK_HID_MAIN_VAL_ABS), /* Filler Bits */ \
HID_REPORT_SIZE(1), HID_REPORT_COUNT(6), \
HID_INPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_ARRAY | ZMK_HID_MAIN_VAL_ABS), \
HID_USAGE_PAGE(HID_USAGE_DIGITIZERS), HID_USAGE(HID_USAGE_DIGITIZERS_FINGER), \
HID_COLLECTION(HID_COLLECTION_LOGICAL), HID_LOGICAL_MIN8(0), HID_LOGICAL_MAX8(1), \
HID_USAGE(HID_USAGE_DIGITIZERS_TOUCH_VALID), HID_USAGE(HID_USAGE_DIGITIZERS_TIP_SWITCH), \
HID_REPORT_COUNT(2), HID_REPORT_SIZE(1), \
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS), \
\
HID_REPORT_COUNT(1), HID_REPORT_SIZE(3), HID_LOGICAL_MAX8(CONFIG_ZMK_TRACKPAD_FINGERS), \
HID_REPORT_COUNT(1), HID_REPORT_SIZE(4), HID_LOGICAL_MAX8(CONFIG_ZMK_TRACKPAD_FINGERS), \
HID_USAGE(HID_USAGE_DIGITIZERS_CONTACT_IDENTIFIER), \
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | \
ZMK_HID_MAIN_VAL_ABS), /* Filler Bits */ \
HID_REPORT_SIZE(1), HID_REPORT_COUNT(5), \
HID_REPORT_SIZE(1), HID_REPORT_COUNT(2), \
HID_INPUT(ZMK_HID_MAIN_VAL_CONST | ZMK_HID_MAIN_VAL_ARRAY | ZMK_HID_MAIN_VAL_ABS), \
\
HID_USAGE_PAGE(HID_USAGE_GD), HID_LOGICAL_MIN8(0), \
Expand Down Expand Up @@ -139,11 +137,8 @@ static const uint8_t zmk_mouse_hid_report_desc[] = {
// Windows Precision Touchpad Input Reports
HID_REPORT_ID(ZMK_MOUSE_HID_REPORT_ID_DIGITIZER),

LISTIFY(CONFIG_ZMK_TRACKPAD_FINGERS, TRACKPAD_FINGER_DESC,
(HID_USAGE_PAGE(HID_USAGE_DIGITIZERS), ))
LISTIFY(CONFIG_ZMK_TRACKPAD_FINGERS, TRACKPAD_FINGER_DESC, ())

HID_USAGE_PAGE(HID_USAGE_DIGITIZERS),
HID_USAGE(HID_USAGE_DIGITIZERS_SCAN_TIME),
/* Exponent (-4) */
ZMK_HID_EXPONENT8(0x0C),
/* Unit (Linear Seconds) */
Expand All @@ -152,6 +147,8 @@ static const uint8_t zmk_mouse_hid_report_desc[] = {
ZMK_HID_LOGICAL_MAX32(0xFFFF),
HID_REPORT_SIZE(16),
HID_REPORT_COUNT(1),
HID_USAGE_PAGE(HID_USAGE_DIGITIZERS),
HID_USAGE(HID_USAGE_DIGITIZERS_SCAN_TIME),
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),

// Contact Count
Expand Down Expand Up @@ -193,8 +190,7 @@ static const uint8_t zmk_mouse_hid_report_desc[] = {
// PTPHQA Blob: Necessary for < Windows 10

// USAGE_PAGE (Vendor Defined)
ZMK_HID_USAGE_PAGE16(0x00FF),
HID_COLLECTION(HID_COLLECTION_LOGICAL),
ZMK_HID_USAGE_PAGE16(0xFF00),
HID_REPORT_ID(ZMK_MOUSE_HID_REPORT_ID_FEATURE_PTPHQA),
// Vendor Usage (0xC5)
HID_USAGE(0xC5),
Expand All @@ -208,7 +204,6 @@ static const uint8_t zmk_mouse_hid_report_desc[] = {

HID_FEATURE(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_ABS),
HID_END_COLLECTION,
HID_END_COLLECTION,

// // Configuration collection
HID_USAGE_PAGE(HID_USAGE_DIGITIZERS),
Expand Down Expand Up @@ -272,9 +267,9 @@ struct zmk_ptp_finger {
// Touch Valid (bit 0) and tip switch (bit 1)
uint8_t touch_valid : 1;
uint8_t tip_switch : 1;
uint8_t padding : 6;
// Contact ID
uint8_t contact_id;
uint8_t contact_id : 4;
uint8_t padding : 2;
// X
uint16_t x;
// Y
Expand Down
32 changes: 15 additions & 17 deletions app/src/mouse/hog.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct hids_report {
} __packed;

static struct hids_info info = {
.version = 0x0101,
.version = 0x1101,
.code = 0x00,
.flags = HIDS_NORMALLY_CONNECTABLE | HIDS_REMOTE_WAKE,
};
Expand Down Expand Up @@ -223,8 +223,7 @@ BT_GATT_SERVICE_DEFINE(
mouse_hog_svc, BT_GATT_PRIMARY_SERVICE(BT_UUID_HIDS),
// BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_PROTOCOL_MODE, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
// BT_GATT_PERM_WRITE, NULL, write_proto_mode, &proto_mode),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_hids_info,
NULL, &info),

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT_MAP, BT_GATT_CHRC_READ, BT_GATT_PERM_READ_ENCRYPT,
read_hids_report_map, NULL, NULL),

Expand All @@ -241,43 +240,42 @@ BT_GATT_SERVICE_DEFINE(
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &ptp_input),

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT, read_hids_ptp_caps_report, NULL, NULL),
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
read_hids_ptp_caps_report, NULL, NULL),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &ptp_caps),

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT, read_hids_ptp_hqa_report, NULL, NULL),
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
read_hids_ptp_hqa_report, NULL, NULL),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &ptp_hqa),

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
read_hids_ptp_mode, write_hids_ptp_mode, NULL),
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &ptp_mode),

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_REPORT, BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT,
read_hids_ptp_sel_reporting, write_hids_ptp_sel_reporting, NULL),
BT_GATT_CCC(input_ccc_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_DESCRIPTOR(BT_UUID_HIDS_REPORT_REF, BT_GATT_PERM_READ_ENCRYPT, read_hids_report_ref,
NULL, &ptp_selective_reporting),

#endif // IS_ENABLED(CONFIG_ZMK_TRACKPAD)

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_INFO, BT_GATT_CHRC_READ, BT_GATT_PERM_READ, read_hids_info,
NULL, &info),

BT_GATT_CHARACTERISTIC(BT_UUID_HIDS_CTRL_POINT, BT_GATT_CHRC_WRITE_WITHOUT_RESP,
BT_GATT_PERM_WRITE, NULL, write_ctrl_point, &ctrl_point));

static struct bt_conn *destination_connection(void) {
struct bt_conn *conn;
bt_addr_le_t *addr = zmk_ble_active_profile_addr();
LOG_DBG("Address pointer %p", addr);

if (!bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
LOG_WRN("Not sending, no active address for current profile");
return NULL;
Expand Down Expand Up @@ -358,7 +356,7 @@ void send_ptp_report_callback(struct k_work *work) {
}

struct bt_gatt_notify_params notify_params = {
.attr = &mouse_hog_svc.attrs[9],
.attr = &mouse_hog_svc.attrs[7],
.data = &report,
.len = sizeof(report),
};
Expand Down

0 comments on commit 0edb585

Please sign in to comment.