Skip to content

Commit

Permalink
fix(mouse): Better batching of MT events.
Browse files Browse the repository at this point in the history
* Handle input events for multiple slots before a sync
  event triggers a HID report.
  • Loading branch information
petejohanson committed Mar 27, 2024
1 parent 6861dc7 commit e8f0612
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 38 deletions.
7 changes: 5 additions & 2 deletions app/include/zmk/mouse/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,9 @@ struct zmk_hid_mouse_report {
// Report for single finger
struct zmk_ptp_finger {
// Touch Valid (bit 0) and tip switch (bit 1)
uint8_t valid_tip;
uint8_t touch_valid : 1;
uint8_t tip_switch : 1;
uint8_t padding : 6;
// Contact ID
uint8_t contact_id;
// X
Expand Down Expand Up @@ -363,7 +365,8 @@ struct zmk_hid_mouse_report *zmk_mouse_hid_get_mouse_report();

int zmk_mouse_hid_set_ptp_finger(struct zmk_ptp_finger finger);
void zmk_mouse_hid_ptp_update_scan_time(void);
void zmk_mouse_hid_ptp_clear(void);
void zmk_mouse_hid_ptp_clear_lifted_fingers(void);
// void zmk_mouse_hid_ptp_clear(void);

struct zmk_hid_ptp_report *zmk_mouse_hid_get_ptp_report();

Expand Down
56 changes: 38 additions & 18 deletions app/src/mouse/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,14 @@ static struct zmk_hid_ptp_report ptp_report = {
};

int zmk_mouse_hid_set_ptp_finger(struct zmk_ptp_finger finger) {
bool finger_removed = false;
// First try to update existing
for (int i = 0; i < ptp_report.body.contact_count; i++) {
if (ptp_report.body.fingers[i].contact_id == finger.contact_id) {
ptp_report.body.fingers[i] = finger;

if (!finger.valid_tip) {
finger_removed = true;
} else {
return 0;
}
} else if (finger_removed) {
ptp_report.body.fingers[i - 1] = ptp_report.body.fingers[i];
return 0;
}
}

if (finger_removed) {
memset(&ptp_report.body.fingers[--ptp_report.body.contact_count], 0,
sizeof(struct zmk_ptp_finger));
return 0;
}

if (ptp_report.body.contact_count == CONFIG_ZMK_TRACKPAD_FINGERS) {
return -ENOMEM;
}
Expand All @@ -152,6 +139,27 @@ int zmk_mouse_hid_set_ptp_finger(struct zmk_ptp_finger finger) {
return 0;
}

void zmk_mouse_hid_ptp_clear_lifted_fingers(void) {
int valid_count = 0;
for (int i = 0; i < ptp_report.body.contact_count; i++) {
if (!ptp_report.body.fingers[i].tip_switch) {
continue;
}

ptp_report.body.fingers[valid_count++] = ptp_report.body.fingers[i];
}

for (int i = valid_count; i < ptp_report.body.contact_count; i++) {
memset(&ptp_report.body.fingers[i], 0, sizeof(struct zmk_ptp_finger));
}

ptp_report.body.contact_count = valid_count;

if (ptp_report.body.contact_count == 0) {
ptp_report.body.scan_time = 0;
}
}

void zmk_mouse_hid_ptp_update_scan_time(void) {
if (ptp_report.body.contact_count > 0) {
// scan time is in 100 microsecond units
Expand All @@ -169,12 +177,24 @@ struct zmk_hid_ptp_report *zmk_mouse_hid_get_ptp_report() {
return &ptp_report;
}

struct zmk_hid_ptp_feature_selective_report *zmk_mouse_hid_ptp_get_feature_selective_report();
struct zmk_hid_ptp_feature_selective_report selective_report = {
.report_id = ZMK_MOUSE_HID_REPORT_ID_FEATURE_PTP_SELECTIVE,
.body =
{
.surface_switch = 1,
.button_switch = 1,
},
};

struct zmk_hid_ptp_feature_selective_report *zmk_mouse_hid_ptp_get_feature_selective_report() {
return &selective_report;
}

void zmk_mouse_hid_ptp_set_feature_selective_report(bool surface_switch, bool button_switch);

struct zmk_hid_ptp_feature_mode_report mode_report = {
.report_id = ZMK_MOUSE_HID_REPORT_ID_FEATURE_PTP_MODE,
.mode = 0,
.mode = 3,
};

struct zmk_hid_ptp_feature_mode_report *zmk_mouse_hid_ptp_get_feature_mode_report() {
Expand Down Expand Up @@ -217,7 +237,7 @@ static struct zmk_hid_ptp_feature_capabilities_report cap_report = {
.body =
{
.max_touches = CONFIG_ZMK_TRACKPAD_FINGERS,
.pad_type = PTP_PAD_TYPE_NON_CLICKABLE,
.pad_type = PTP_PAD_TYPE_DEPRESSIBLE,
},
};

Expand Down
48 changes: 30 additions & 18 deletions app/src/mouse/input_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct input_listener_data {
} mouse;

struct {
bool pending_data;
struct input_listener_xy_data data;
uint8_t finger_idx;
bool touched;
Expand Down Expand Up @@ -92,18 +93,41 @@ static void handle_rel_code(struct input_listener_data *data, struct input_event
}
}

static int send_ptp_finger_to_hid(struct input_listener_data *data) {
struct zmk_ptp_finger finger = {.contact_id = data->ptp.finger_idx};
finger.x = data->ptp.data.x;
finger.y = data->ptp.data.y;
finger.touch_valid = 1;
finger.tip_switch = data->ptp.touched ? 1 : 0;

int err = zmk_mouse_hid_set_ptp_finger(finger);

data->ptp.pending_data = false;
data->ptp.data.y = data->ptp.data.x = 0;
data->ptp.touched = false;

return err;
}

static void handle_abs_code(const struct input_listener_config *config,
struct input_listener_data *data, struct input_event *evt) {
if (config->mode == INPUT_LISTENER_MODE_PTP) {
switch (evt->code) {
case INPUT_ABS_MT_SLOT:
if (data->ptp.pending_data) {
send_ptp_finger_to_hid(data);
}

data->ptp.pending_data = true;
data->ptp.finger_idx = evt->value;
break;
case INPUT_ABS_X:
data->ptp.pending_data = true;
data->ptp.data.mode = INPUT_LISTENER_XY_DATA_MODE_ABS;
data->ptp.data.x = evt->value;
break;
case INPUT_ABS_Y:
data->ptp.pending_data = true;
data->ptp.data.mode = INPUT_LISTENER_XY_DATA_MODE_ABS;
data->ptp.data.y = evt->value;
break;
Expand Down Expand Up @@ -230,28 +254,16 @@ static void input_handler(const struct input_listener_config *config,
break;
case INPUT_LISTENER_MODE_PTP:
#if IS_ENABLED(CONFIG_ZMK_TRACKPAD)
struct zmk_ptp_finger finger = {.contact_id = data->ptp.finger_idx};
finger.x = data->ptp.data.x;
finger.y = data->ptp.data.y;
WRITE_BIT(finger.valid_tip, 0, 1);
WRITE_BIT(finger.valid_tip, 1, data->ptp.touched ? 1 : 0);

zmk_mouse_hid_set_ptp_finger(finger);
zmk_mouse_hid_ptp_update_scan_time();
if (data->ptp.pending_data) {
send_ptp_finger_to_hid(data);
}

// TODO: Button Data
zmk_endpoints_send_ptp_report();

if (!data->ptp.touched) {
finger.x = finger.y = 0;
WRITE_BIT(finger.valid_tip, 0, 0);

zmk_mouse_hid_set_ptp_finger(finger);
zmk_mouse_hid_ptp_update_scan_time();
zmk_mouse_hid_ptp_update_scan_time();
zmk_endpoints_send_ptp_report();

// TODO: Button Data
zmk_endpoints_send_ptp_report();
}
zmk_mouse_hid_ptp_clear_lifted_fingers();
#else
LOG_WRN("PTP Mode not supported without CONFIG_ZMK_TRACKPAD=y");
#endif // IS_ENABLED(CONFIG_ZMK_TRACKPAD)
Expand Down

0 comments on commit e8f0612

Please sign in to comment.