Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: betop: add drivers/hid/hid-betopff.c

Commit fc38a8a66e ("HID: add BETOP game controller force feedback support")
is missing the actual addition of drivers/hid/hid-betopff.c due to my
mistake (I forgot to add the file after fixing conflicts).

Fixes: fc38a8a66e1b ("HID: add BETOP game controller force feedback support")
Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

+160
+160
drivers/hid/hid-betopff.c
··· 1 + /* 2 + * Force feedback support for Betop based devices 3 + * 4 + * The devices are distributed under various names and the same USB device ID 5 + * can be used in both adapters and actual game controllers. 6 + * 7 + * 0x11c2:0x2208 "BTP2185 BFM mode Joystick" 8 + * - tested with BTP2185 BFM Mode. 9 + * 10 + * 0x11C0:0x5506 "BTP2185 PC mode Joystick" 11 + * - tested with BTP2185 PC Mode. 12 + * 13 + * 0x8380:0x1850 "BTP2185 V2 PC mode USB Gamepad" 14 + * - tested with BTP2185 PC Mode with another version. 15 + * 16 + * 0x20bc:0x5500 "BTP2185 V2 BFM mode Joystick" 17 + * - tested with BTP2171s. 18 + * Copyright (c) 2014 Huang Bo <huangbobupt@163.com> 19 + */ 20 + 21 + /* 22 + * This program is free software; you can redistribute it and/or modify it 23 + * under the terms of the GNU General Public License as published by the Free 24 + * Software Foundation; either version 2 of the License, or (at your option) 25 + * any later version. 26 + */ 27 + 28 + 29 + #include <linux/input.h> 30 + #include <linux/slab.h> 31 + #include <linux/module.h> 32 + #include <linux/hid.h> 33 + 34 + #include "hid-ids.h" 35 + 36 + struct betopff_device { 37 + struct hid_report *report; 38 + }; 39 + 40 + static int hid_betopff_play(struct input_dev *dev, void *data, 41 + struct ff_effect *effect) 42 + { 43 + struct hid_device *hid = input_get_drvdata(dev); 44 + struct betopff_device *betopff = data; 45 + __u16 left, right; 46 + 47 + left = effect->u.rumble.strong_magnitude; 48 + right = effect->u.rumble.weak_magnitude; 49 + 50 + betopff->report->field[2]->value[0] = left / 256; 51 + betopff->report->field[3]->value[0] = right / 256; 52 + 53 + hid_hw_request(hid, betopff->report, HID_REQ_SET_REPORT); 54 + 55 + return 0; 56 + } 57 + 58 + static int betopff_init(struct hid_device *hid) 59 + { 60 + struct betopff_device *betopff; 61 + struct hid_report *report; 62 + struct hid_input *hidinput = 63 + list_first_entry(&hid->inputs, struct hid_input, list); 64 + struct list_head *report_list = 65 + &hid->report_enum[HID_OUTPUT_REPORT].report_list; 66 + struct input_dev *dev = hidinput->input; 67 + int field_count = 0; 68 + int error; 69 + int i, j; 70 + 71 + if (list_empty(report_list)) { 72 + hid_err(hid, "no output reports found\n"); 73 + return -ENODEV; 74 + } 75 + 76 + report = list_first_entry(report_list, struct hid_report, list); 77 + /* 78 + * Actually there are 4 fields for 4 Bytes as below: 79 + * ----------------------------------------- 80 + * Byte0 Byte1 Byte2 Byte3 81 + * 0x00 0x00 left_motor right_motor 82 + * ----------------------------------------- 83 + * Do init them with default value. 84 + */ 85 + for (i = 0; i < report->maxfield; i++) { 86 + for (j = 0; j < report->field[i]->report_count; j++) { 87 + report->field[i]->value[j] = 0x00; 88 + field_count++; 89 + } 90 + } 91 + 92 + if (field_count < 4) { 93 + hid_err(hid, "not enough fields in the report: %d\n", 94 + field_count); 95 + return -ENODEV; 96 + } 97 + 98 + betopff = kzalloc(sizeof(*betopff), GFP_KERNEL); 99 + if (!betopff) 100 + return -ENOMEM; 101 + 102 + set_bit(FF_RUMBLE, dev->ffbit); 103 + 104 + error = input_ff_create_memless(dev, betopff, hid_betopff_play); 105 + if (error) { 106 + kfree(betopff); 107 + return error; 108 + } 109 + 110 + betopff->report = report; 111 + hid_hw_request(hid, betopff->report, HID_REQ_SET_REPORT); 112 + 113 + hid_info(hid, "Force feedback for betop devices by huangbo <huangbobupt@163.com>\n"); 114 + 115 + return 0; 116 + } 117 + 118 + static int betop_probe(struct hid_device *hdev, const struct hid_device_id *id) 119 + { 120 + int ret; 121 + 122 + if (id->driver_data) 123 + hdev->quirks |= HID_QUIRK_MULTI_INPUT; 124 + 125 + ret = hid_parse(hdev); 126 + if (ret) { 127 + hid_err(hdev, "parse failed\n"); 128 + goto err; 129 + } 130 + 131 + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); 132 + if (ret) { 133 + hid_err(hdev, "hw start failed\n"); 134 + goto err; 135 + } 136 + 137 + betopff_init(hdev); 138 + 139 + return 0; 140 + err: 141 + return ret; 142 + } 143 + 144 + static const struct hid_device_id betop_devices[] = { 145 + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) }, 146 + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185PC, 0x5506) }, 147 + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2PC, 0x1850) }, 148 + { HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185V2BFM, 0x5500) }, 149 + { } 150 + }; 151 + MODULE_DEVICE_TABLE(hid, betop_devices); 152 + 153 + static struct hid_driver betop_driver = { 154 + .name = "betop", 155 + .id_table = betop_devices, 156 + .probe = betop_probe, 157 + }; 158 + module_hid_driver(betop_driver); 159 + 160 + MODULE_LICENSE("GPL");