Blame view
drivers/hid/hid-gaff.c
4.75 KB
42859e0bd HID: force feedba... |
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 |
/* * Force feedback support for GreenAsia (Product ID 0x12) based devices * * The devices are distributed under various names and the same USB device ID * can be used in many game controllers. * * * 0e8f:0012 "GreenAsia Inc. USB Joystick " * - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635. * * Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info> */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/input.h> |
5a0e3ad6a include cleanup: ... |
31 |
#include <linux/slab.h> |
42859e0bd HID: force feedba... |
32 33 |
#include <linux/usb.h> #include <linux/hid.h> |
8f86a2c3c hid: Add module.h... |
34 |
#include <linux/module.h> |
42859e0bd HID: force feedba... |
35 |
#include "hid-ids.h" |
0f6f4319a HID: fix hid-ff d... |
36 37 |
#ifdef CONFIG_GREENASIA_FF |
42859e0bd HID: force feedba... |
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 |
#include "usbhid/usbhid.h" struct gaff_device { struct hid_report *report; }; static int hid_gaff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { struct hid_device *hid = input_get_drvdata(dev); struct gaff_device *gaff = data; int left, right; left = effect->u.rumble.strong_magnitude; right = effect->u.rumble.weak_magnitude; dbg_hid("called with 0x%04x 0x%04x", left, right); left = left * 0xfe / 0xffff; right = right * 0xfe / 0xffff; gaff->report->field[0]->value[0] = 0x51; gaff->report->field[0]->value[1] = 0x0; gaff->report->field[0]->value[2] = right; gaff->report->field[0]->value[3] = 0; gaff->report->field[0]->value[4] = left; gaff->report->field[0]->value[5] = 0; dbg_hid("running with 0x%02x 0x%02x", left, right); usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); gaff->report->field[0]->value[0] = 0xfa; gaff->report->field[0]->value[1] = 0xfe; gaff->report->field[0]->value[2] = 0x0; gaff->report->field[0]->value[4] = 0x0; usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); return 0; } static int gaff_init(struct hid_device *hid) { struct gaff_device *gaff; struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct list_head *report_ptr = report_list; struct input_dev *dev = hidinput->input; int error; if (list_empty(report_list)) { |
4291ee305 HID: Add and use ... |
91 92 |
hid_err(hid, "no output reports found "); |
42859e0bd HID: force feedba... |
93 94 95 96 97 98 99 |
return -ENODEV; } report_ptr = report_ptr->next; report = list_entry(report_ptr, struct hid_report, list); if (report->maxfield < 1) { |
4291ee305 HID: Add and use ... |
100 101 |
hid_err(hid, "no fields in the report "); |
42859e0bd HID: force feedba... |
102 103 104 105 |
return -ENODEV; } if (report->field[0]->report_count < 6) { |
4291ee305 HID: Add and use ... |
106 107 |
hid_err(hid, "not enough values in the field "); |
42859e0bd HID: force feedba... |
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
return -ENODEV; } gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL); if (!gaff) return -ENOMEM; set_bit(FF_RUMBLE, dev->ffbit); error = input_ff_create_memless(dev, gaff, hid_gaff_play); if (error) { kfree(gaff); return error; } gaff->report = report; gaff->report->field[0]->value[0] = 0x51; gaff->report->field[0]->value[1] = 0x00; gaff->report->field[0]->value[2] = 0x00; gaff->report->field[0]->value[3] = 0x00; usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); gaff->report->field[0]->value[0] = 0xfa; gaff->report->field[0]->value[1] = 0xfe; usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); |
4291ee305 HID: Add and use ... |
134 135 |
hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski <lukasz@lubojanski.info> "); |
42859e0bd HID: force feedba... |
136 137 138 |
return 0; } |
0f6f4319a HID: fix hid-ff d... |
139 140 141 142 143 144 |
#else static inline int gaff_init(struct hid_device *hdev) { return 0; } #endif |
42859e0bd HID: force feedba... |
145 146 147 148 149 150 151 152 153 |
static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret; dev_dbg(&hdev->dev, "Greenasia HID hardware probe..."); ret = hid_parse(hdev); if (ret) { |
4291ee305 HID: Add and use ... |
154 155 |
hid_err(hdev, "parse failed "); |
42859e0bd HID: force feedba... |
156 157 158 159 160 |
goto err; } ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); if (ret) { |
4291ee305 HID: Add and use ... |
161 162 |
hid_err(hdev, "hw start failed "); |
42859e0bd HID: force feedba... |
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
goto err; } gaff_init(hdev); return 0; err: return ret; } static const struct hid_device_id ga_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), }, { } }; MODULE_DEVICE_TABLE(hid, ga_devices); static struct hid_driver ga_driver = { .name = "greenasia", .id_table = ga_devices, .probe = ga_probe, }; static int __init ga_init(void) { return hid_register_driver(&ga_driver); } static void __exit ga_exit(void) { hid_unregister_driver(&ga_driver); } module_init(ga_init); module_exit(ga_exit); MODULE_LICENSE("GPL"); |