From 12ad6ebd615f57b7b1032953ab9ea9b29ca1bc87 Mon Sep 17 00:00:00 2001 From: Nicolas James Date: Sun, 13 Apr 2025 20:42:31 +1000 Subject: Add ability to write userspace tests, update cmake build process --- fastmouse.patch | 159 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 136 insertions(+), 23 deletions(-) (limited to 'fastmouse.patch') diff --git a/fastmouse.patch b/fastmouse.patch index 6670742..d525668 100644 --- a/fastmouse.patch +++ b/fastmouse.patch @@ -1,5 +1,43 @@ +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 4497b50799db..5a64a10b06da 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1680,6 +1680,8 @@ static void hid_process_report(struct hid_device *hid, + unsigned int a; + struct hid_field_entry *entry; + struct hid_field *field; ++ struct input_dev *fastmouse_dev = NULL; ++ + + /* first retrieve all incoming values in data */ + for (a = 0; a < report->maxfield; a++) +@@ -1692,6 +1694,10 @@ static void hid_process_report(struct hid_device *hid, + list) { + field = entry->field; + ++ if (hid->type == HID_TYPE_USBMOUSE && field->hidinput) { ++ fastmouse_dev = field->hidinput->input; ++ } ++ + if (field->flags & HID_MAIN_ITEM_VARIABLE) + hid_process_event(hid, + field, +@@ -1721,6 +1727,13 @@ static void hid_process_report(struct hid_device *hid, + hid_input_array_field(hid, field, interrupt); + } + } ++ ++ ++ if (fastmouse_dev) { ++ fastmouse_input_emit(fastmouse_dev); ++ } ++ ++ + } + + /* diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c -index 9d80635a91eb..8c8a7483261f 100644 +index 9d80635a91eb..56e1bb7b7023 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -14,6 +14,7 @@ @@ -10,21 +48,32 @@ index 9d80635a91eb..8c8a7483261f 100644 #include #include -@@ -1505,6 +1506,87 @@ static void hid_report_set_tool(struct hid_report *report, struct input_dev *inp +@@ -1505,6 +1506,150 @@ static void hid_report_set_tool(struct hid_report *report, struct input_dev *inp report->tool = new_tool; } +struct fastmouse_state { + int division; -+ long x, y; ++ long frame_x, frame_y; ++ long accum_x, accum_y; + int rise, run; ++ /* TODO ++ int polling_rate; ++ long accel; ++ */ +}; +static struct fastmouse_state fastmouse = { + .division = 1, -+ .x = 0, -+ .y = 0, ++ .frame_x = 0, ++ .frame_y = 0, ++ .accum_x = 0, ++ .accum_y = 0, + .rise = 0, + .run = INT_MAX, ++ /* TODO ++ .polling_rate = 4000, ++ .accel = 1, ++ */ +}; + +static int set_division(const char *val, const struct kernel_param *kp) { @@ -69,42 +118,94 @@ index 9d80635a91eb..8c8a7483261f 100644 +module_param_cb(run, &run_ops, &fastmouse.run, 0664); +MODULE_PARM_DESC(run, "Mouse movement run amount (default: INT_MAX)"); + -+static void fastmouse_handle_motion(const long in_x, const long in_y) { -+ const long rise = fastmouse.rise / fastmouse.division; -+ const long run = fastmouse.run / fastmouse.division; -+ fastmouse.x += in_x * run - in_y * rise; -+ fastmouse.y += in_x * rise + in_y * run; ++/* TODO ++static int set_polling_rate(const char *val, const struct kernel_param *kp) { ++ const int ret = kstrtoint(val, 0, &fastmouse.polling_rate); ++ if (ret != 0) { ++ return -EINVAL; ++ } ++ return ret; ++} ++static const struct kernel_param_ops poll_ops = { ++ .set = set_polling_rate, ++ .get = param_get_int, ++}; ++module_param_cb(polling_rate, &poll_ops, &fastmouse.polling_rate, 0664); ++MODULE_PARM_DESC(polling_rate, "Mouse polling rate (default: 4000)"); ++ ++static int set_accel(const char *val, const struct kernel_param *kp) { ++ const int ret = kstrtol(val, 0, &fastmouse.accel); ++ if (ret != 0) { ++ return -EINVAL; ++ } ++ return ret; +} ++static const struct kernel_param_ops accel_ops = { ++ .set = set_accel, ++ .get = param_get_int, ++}; ++module_param_cb(acceleration, &accel_ops, &fastmouse.accel, 0664); ++MODULE_PARM_DESC(acceleration, "Mouse acceleration (default: 1)"); ++*/ + -+static void input_event_fastmouse(struct input_dev *input, const unsigned int type, const unsigned int code, __s32 value) { -+ const long in_x = (code == REL_X) * value; -+ const long in_y = (code == REL_Y) * value; ++static void input_event_fastmouse_log( ++ struct input_dev *input, ++ const unsigned int type, ++ const unsigned int code, ++ __s32 value) { ++ fastmouse.frame_x += (code == REL_X) * value; ++ fastmouse.frame_y += (code == REL_Y) * value; ++} + -+ fastmouse_handle_motion(in_x, in_y); ++/* TODO (for accel) ++static unsigned __int128 i128_sqrt(const unsigned __int128 v) { ++ unsigned __int128 left = 0; ++ unsigned __int128 right = v; ++ while (left < right) { ++ const unsigned __int128 mid = left + ((right - left) / 2); ++ if (mid >= ~(u64)0 || mid * mid > v) { ++ right = mid; ++ } else if (mid * mid == v) { ++ return mid; ++ } else { ++ left = mid + 1; ++ } ++ } ++ return left != 0 ? left - 1 : 0; ++} ++*/ + -+ const long emit_x = fastmouse.x / INT_MAX; ++void fastmouse_input_emit(struct input_dev *input) { ++ const long rise = fastmouse.rise / fastmouse.division; ++ const long run = fastmouse.run / fastmouse.division; ++ ++ fastmouse.accum_x += fastmouse.frame_x * run - fastmouse.frame_y * rise; ++ fastmouse.accum_y += fastmouse.frame_x * rise + fastmouse.frame_y * run; ++ ++ const long emit_x = fastmouse.accum_x / INT_MAX; + if (emit_x != 0) { -+ input_event(input, type, REL_X, emit_x); ++ input_event(input, EV_REL, REL_X, emit_x); + } -+ const long emit_y = fastmouse.y / INT_MAX; ++ const long emit_y = fastmouse.accum_y / INT_MAX; + if (emit_y != 0) { -+ input_event(input, type, REL_Y, emit_y); ++ input_event(input, EV_REL, REL_Y, emit_y); + } -+ -+ fastmouse.x %= INT_MAX; -+ fastmouse.y %= INT_MAX; ++ fastmouse.accum_x %= INT_MAX; ++ fastmouse.accum_y %= INT_MAX; ++ ++ fastmouse.frame_x = fastmouse.frame_y = 0; +} + void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct input_dev *input; -@@ -1713,7 +1795,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct +@@ -1713,7 +1858,12 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct (!test_bit(usage->code, input->key)) == value) input_event(input, EV_MSC, MSC_SCAN, usage->hid); - input_event(input, usage->type, usage->code, value); + if (hid->type == HID_TYPE_USBMOUSE && usage->type == EV_REL) { -+ input_event_fastmouse(input, usage->type, usage->code, value); ++ input_event_fastmouse_log(input, usage->type, usage->code, value); + } else { + input_event(input, usage->type, usage->code, value); + } @@ -112,3 +213,15 @@ index 9d80635a91eb..8c8a7483261f 100644 if ((field->flags & HID_MAIN_ITEM_RELATIVE) && usage->type == EV_KEY && value) { +diff --git a/include/linux/hid.h b/include/linux/hid.h +index cdc0dc13c87f..8321d637b112 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -940,6 +940,7 @@ extern void hid_unregister_driver(struct hid_driver *); + module_driver(__hid_driver, hid_register_driver, \ + hid_unregister_driver) + ++extern void fastmouse_input_emit(struct input_dev *input); + extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); + extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); + extern int hidinput_connect(struct hid_device *hid, unsigned int force); -- cgit v1.2.3