#include "linux/input-event-codes.h" #include "linux/input.h" #include "linux/kern_levels.h" #include "linux/printk.h" #include #include #include #include #include #include #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");