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
117
118
119
120
121
122
123
124
125
126
127
|
#include "linux/input-event-codes.h"
#include "linux/input.h"
#include "linux/kern_levels.h"
#include "linux/printk.h"
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/hid.h>
#include "startbit.h"
struct wiimouse_dev {
struct hid_device* hdev;
struct input_dev* in_dev;
};
static const struct hid_device_id wiimouse_ids[] = {
{HID_BLUETOOTH_DEVICE(NINTENDO_WIIMOTE_VENDOR_ID, NINTENDO_WIIMOTE_PRODUCT_ID)},
{}
};
/*
* wiimote_init
* Initialize certain aspects of the wiimote such as the LEDs and sensors by
* sending appropriate HID reports to the device. Returns 0 on success, non-zero
* on error
* Details about the report details can be found in https://wiibrew.org/wiki/Wiimote
*/
static int wiimote_init(struct hid_device* hdev) {
int ret = 0;
__u8 rumble[2] = { HID_REPORT_ID_WIIMOTE_RUMBLE_ENABLE, HID_REPORT_DATA_WIIMOTE_RUMBLE_ENABLE };
if ((ret = hid_hw_output_report(hdev, (__u8*)rumble, 2)) < 0) return ret;
__u8 led_p1[2] = { HID_REPORT_ID_WIIMOTE_LED_ENABLE, HID_REPORT_DATA_WIIMOTE_LED_ENABLE_P1 };
if ((ret = hid_hw_output_report(hdev, (__u8*)led_p1, 2)) < 0) return ret;
__u8 enable_ir1[2] = { HID_REPORT_ID_WIIMOTE_IR1_ENABLE, HID_REPORT_DATA_WIIMOTE_IR1_ENABLE };
if ((ret = hid_hw_output_report(hdev, (__u8*)enable_ir1, 2)) < 0) return ret;
__u8 enable_ir2[2] = { HID_REPORT_ID_WIIMOTE_IR2_ENABLE, HID_REPORT_DATA_WIIMOTE_IR2_ENABLE };
if ((ret = hid_hw_output_report(hdev, (__u8*)enable_ir2, 2)) < 0) return ret;
return ret;
}
static int wiimote_event(struct hid_device* hdev, struct hid_report* report, u8 *data, int size) {
printk(KERN_DEBUG "Report ID: %02x | Buttons: %02x %02x %02x\n", report->id, data[0], data[1], data[2]);
struct wiimouse_dev* wdev = hid_get_drvdata(hdev);
if (data[2] & 0x08) {
printk(KERN_DEBUG "A button was pressed\n");
struct input_dev* in_dev = wdev->in_dev;
input_report_key(in_dev, BTN_LEFT, 1);
input_sync(in_dev);
input_report_key(in_dev, BTN_LEFT, 0);
input_sync(in_dev);
}
return 0;
}
MODULE_DEVICE_TABLE(hid, wiimouse_ids);
static int wiimouse_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret = 0;
struct wiimouse_dev* wdev;
wdev = devm_kzalloc(&hdev->dev, sizeof(struct wiimouse_dev), GFP_KERNEL);
wdev->hdev = hdev;
struct input_dev* in_dev = input_allocate_device();
if(in_dev == NULL) {
return -1;
}
wdev->in_dev = in_dev;
in_dev->name = "Wiimouse";
in_dev->id.vendor = NINTENDO_WIIMOTE_VENDOR_ID;
in_dev->id.product = NINTENDO_WIIMOTE_PRODUCT_ID;
in_dev->id.version = 0x0000;
set_bit(EV_KEY, in_dev->evbit);
set_bit(BTN_LEFT, in_dev->keybit);
ret = input_register_device(in_dev);
if (ret) {
input_free_device(in_dev);
return ret;
}
printk(KERN_DEBUG "wiimouse-mouse: Starting parse");
/* Init hid device, setup input subsystem etc. */
ret = hid_parse(hdev);
if (ret) return ret;
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) return ret;
wiimote_init(hdev);
hid_set_drvdata(hdev, wdev);
/* Init done, device ready to use */
printk(KERN_DEBUG "Hello I'm a wiimouse!");
return 0;
}
static void wiimote_remove(struct hid_device* hdev) {
struct wiimouse_dev* wdev = hid_get_drvdata(hdev);
input_unregister_device(wdev->in_dev);
}
static void wiimote_report(struct hid_device *hdev, struct hid_report *report) {
printk(KERN_DEBUG "Report ID: %02x\n", report->id);
}
static struct hid_driver wiimouse_driver = {
.name = "wiimouse-mouse",
.id_table = wiimouse_ids,
.probe = wiimouse_probe,
.raw_event = wiimote_event,
.report = wiimote_report,
.remove = wiimote_remove,
};
module_hid_driver(wiimouse_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Aaditya Dhruv");
MODULE_DESCRIPTION("Use your wiimote as a simple mouse");
|