#ifndef FASTMOUSE_H_ #define FASTMOUSE_H_ // Mock functionality and structs for user space unit tests. #ifndef __KERNEL__ #include typedef int __s32; struct input_dev {}; enum event_type { EV_REL, }; enum movement_type { REL_X, REL_Y, }; struct mouse_movement { int x = 0; int y = 0; }; static struct mouse_movement movement = { .x = 0, .y = 0, }; static void input_event(input_dev*, event_type, movement_type code, int value) { movement.x += (code == REL_X) * value; movement.y += (code == REL_Y) * value; } #endif extern void input_event_fastmouse_log( struct input_dev*, const unsigned int, const unsigned int code, __s32 value); extern void fastmouse_input_emit(struct input_dev *input); struct fastmouse_state { int division; long frame_x, frame_y; long accum_x, accum_y; int rise, run; /* TODO int polling_rate; long accel; */ }; /* 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; } */ #ifdef FASTMOUSE_IMPL static struct fastmouse_state fastmouse = { .division = 1, .frame_x = 0, .frame_y = 0, .accum_x = 0, .accum_y = 0, .rise = 0, .run = INT_MAX, /* TODO .polling_rate = 4000, .accel = 1, */ }; void input_event_fastmouse_log( struct input_dev*, const unsigned int, const unsigned int code, __s32 value) { fastmouse.frame_x += (code == REL_X) * value; fastmouse.frame_y += (code == REL_Y) * value; } 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, EV_REL, REL_X, (__s32)emit_x); } const long emit_y = fastmouse.accum_y / INT_MAX; if (emit_y != 0) { input_event(input, EV_REL, REL_Y, (__s32)emit_y); } fastmouse.accum_x %= INT_MAX; fastmouse.accum_y %= INT_MAX; fastmouse.frame_x = fastmouse.frame_y = 0; } #ifdef __KERNEL__ #include static int set_division(const char *val, const struct kernel_param *kp) { const int ret = kstrtoint(val, 0, &fastmouse.division); if (ret != 0 || fastmouse.division <= 0) { return -EINVAL; } return ret; } static const struct kernel_param_ops division_ops = { .set = set_division, .get = param_get_int, }; module_param_cb(division, &division_ops, &fastmouse.division, 0664); MODULE_PARM_DESC(division, "Mouse movement division amount (default: 1)"); static int set_rise(const char *val, const struct kernel_param *kp) { const int ret = kstrtoint(val, 0, &fastmouse.rise); if (ret != 0) { return -EINVAL; } return ret; } static const struct kernel_param_ops rise_ops = { .set = set_rise, .get = param_get_int, }; module_param_cb(rise, &rise_ops, &fastmouse.rise, 0664); MODULE_PARM_DESC(rise, "Mouse movement rise amount (default: 0)"); static int set_run(const char *val, const struct kernel_param *kp) { const int ret = kstrtoint(val, 0, &fastmouse.run); if (ret != 0) { return -EINVAL; } return ret; } static const struct kernel_param_ops run_ops = { .set = set_run, .get = param_get_int, }; module_param_cb(run, &run_ops, &fastmouse.run, 0664); MODULE_PARM_DESC(run, "Mouse movement run amount (default: INT_MAX)"); /* 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)"); */ #endif #endif #endif