-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathezscroll.c
More file actions
116 lines (97 loc) · 2.88 KB
/
Copy pathezscroll.c
File metadata and controls
116 lines (97 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/kbd_kern.h>
#include <linux/libps2.h>
#include <linux/kprobes.h>
#include <linux/serio.h>
#include <linux/input.h>
#include <linux/types.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MatusGuy");
// NOTE: I'm not sure if this works with the EZ-7000 but
// there exists a driver on Windows that supports both
// and I'm assuming it's using the same method...
MODULE_DESCRIPTION("Trust EZ-7000/8000 Keyboard Scroll Wheel driver");
static struct kprobe kp;
static struct input_dev* scrdev;
static bool extended = false;
/* Pre-handler: Executed before the probed instruction is run */
static int ezscroll_ps2_pre_handler(struct kprobe* p, struct pt_regs* regs)
{
//struct serio* serio = (struct serio*) regs->di; // First argument: struct serio *serio
u8 data = (u8) regs->si; // Second argument: u8 data
//unsigned int flags = (unsigned int) regs->dx; // Third argument: unsigned int flags
//pr_info("Kprobe hit: ps2_interrupt function called\n");
//pr_info("Serio struct address: %p\n", serio);
//pr_info("Data received: 0x%02x\n", data);
//pr_info("Flags: 0x%x\n", flags);
if (data == 0xe0)
{
/// Next byte should be an extended key
extended = true;
}
else if (extended)
{
u8 code = data & 0x7f;
bool pressed = !(data >> 7);
if (code == 0x0b)
{
input_report_rel(scrdev, REL_WHEEL, pressed ? 1 : -1);
input_sync(scrdev);
}
else if (code == 0x16)
{
input_report_key(scrdev, BTN_MIDDLE, pressed);
input_sync(scrdev);
}
extended = false;
}
return 0;
}
/* Module initialization */
static int __init ezscroll_init(void)
{
int ret;
scrdev = input_allocate_device();
if (!scrdev) {
printk(KERN_ERR "ezscroll_init: Error on input_allocate_device!\n");
return -ENOMEM;
}
scrdev->name = "Trust EZ-7000/8000 Keyboard Scroll Wheel";
scrdev->id.bustype = BUS_VIRTUAL;
scrdev->id.vendor = 0x0000;
scrdev->id.product = 0x0000;
scrdev->id.version = 0x0000;
/// Declare what kind of inputs will be sent
scrdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
scrdev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_MIDDLE);
scrdev->relbit[0] = BIT_MASK(REL_WHEEL);
ret = input_register_device(scrdev);
if (ret < 0) {
printk(KERN_ERR "ezscroll_init: Failed to register input device\n");
return ret;
}
/// Use kprobes to hook to the ps2 interrupt function.
kp.symbol_name = "ps2_interrupt";
kp.pre_handler = ezscroll_ps2_pre_handler;
ret = register_kprobe(&kp);
if (ret < 0) {
pr_err("Failed to register kprobe: %d\n", ret);
return ret;
}
return 0;
}
/* Module cleanup */
static void __exit ezscroll_exit(void)
{
input_unregister_device(scrdev);
unregister_kprobe(&kp);
}
module_init(ezscroll_init);
module_exit(ezscroll_exit);