1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Vibration support for Mega World controllers 4 * 5 * Copyright 2022 Frank Zago 6 * 7 * Derived from hid-zpff.c: 8 * Copyright (c) 2005, 2006 Anssi Hannula <anssi.hannula@gmail.com> 9 */ 10 11 #include <linux/hid.h> 12 #include <linux/input.h> 13 #include <linux/module.h> 14 #include <linux/slab.h> 15 16 #include "hid-ids.h" 17 18 struct mwctrl_device { 19 struct hid_report *report; 20 s32 *weak; 21 s32 *strong; 22 }; 23 24 static int mwctrl_play(struct input_dev *dev, void *data, 25 struct ff_effect *effect) 26 { 27 struct hid_device *hid = input_get_drvdata(dev); 28 struct mwctrl_device *mwctrl = data; 29 30 *mwctrl->strong = effect->u.rumble.strong_magnitude >> 8; 31 *mwctrl->weak = effect->u.rumble.weak_magnitude >> 8; 32 33 hid_hw_request(hid, mwctrl->report, HID_REQ_SET_REPORT); 34 35 return 0; 36 } 37 38 static int mwctrl_input_configured(struct hid_device *hid, struct hid_input *hidinput) 39 { 40 struct mwctrl_device *mwctrl; 41 struct hid_report *report; 42 struct input_dev *dev = hidinput->input; 43 int error; 44 int i; 45 46 if (!list_is_first(&hidinput->list, &hid->inputs)) 47 return 0; 48 49 for (i = 0; i < 4; i++) { 50 report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); 51 if (!report) 52 return -ENODEV; 53 } 54 55 mwctrl = kzalloc_obj(struct mwctrl_device); 56 if (!mwctrl) 57 return -ENOMEM; 58 59 mwctrl->report = report; 60 /* Field 0 is always 2, and field 1 is always 0. The original 61 * windows driver has a 5 bytes command, where the 5th byte is 62 * a repeat of the 3rd byte, however the device has only 4 63 * fields. It could be a bug in the driver, or there is a 64 * different device that needs it. 65 */ 66 report->field[0]->value[0] = 0x02; 67 68 mwctrl->strong = &report->field[2]->value[0]; 69 mwctrl->weak = &report->field[3]->value[0]; 70 71 set_bit(FF_RUMBLE, dev->ffbit); 72 73 error = input_ff_create_memless(dev, mwctrl, mwctrl_play); 74 if (error) { 75 kfree(mwctrl); 76 return error; 77 } 78 79 return 0; 80 } 81 82 static const struct hid_device_id mwctrl_devices[] = { 83 { HID_USB_DEVICE(USB_VENDOR_MEGAWORLD, 84 USB_DEVICE_ID_MEGAWORLD_GAMEPAD) }, 85 { } 86 }; 87 MODULE_DEVICE_TABLE(hid, mwctrl_devices); 88 89 static struct hid_driver mwctrl_driver = { 90 .name = "megaworld", 91 .id_table = mwctrl_devices, 92 .input_configured = mwctrl_input_configured, 93 }; 94 module_hid_driver(mwctrl_driver); 95 96 MODULE_DESCRIPTION("Vibration support for Mega World controllers"); 97 MODULE_LICENSE("GPL"); 98