0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/input.h>
0019 #include <linux/slab.h>
0020 #include <linux/hid.h>
0021 #include <linux/module.h>
0022
0023 #include "hid-ids.h"
0024
0025 #ifdef CONFIG_DRAGONRISE_FF
0026
0027 struct drff_device {
0028 struct hid_report *report;
0029 };
0030
0031 static int drff_play(struct input_dev *dev, void *data,
0032 struct ff_effect *effect)
0033 {
0034 struct hid_device *hid = input_get_drvdata(dev);
0035 struct drff_device *drff = data;
0036 int strong, weak;
0037
0038 strong = effect->u.rumble.strong_magnitude;
0039 weak = effect->u.rumble.weak_magnitude;
0040
0041 dbg_hid("called with 0x%04x 0x%04x", strong, weak);
0042
0043 if (strong || weak) {
0044 strong = strong * 0xff / 0xffff;
0045 weak = weak * 0xff / 0xffff;
0046
0047
0048
0049
0050 if (weak == 0x0a)
0051 weak = 0x0b;
0052
0053 drff->report->field[0]->value[0] = 0x51;
0054 drff->report->field[0]->value[1] = 0x00;
0055 drff->report->field[0]->value[2] = weak;
0056 drff->report->field[0]->value[4] = strong;
0057 hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
0058
0059 drff->report->field[0]->value[0] = 0xfa;
0060 drff->report->field[0]->value[1] = 0xfe;
0061 } else {
0062 drff->report->field[0]->value[0] = 0xf3;
0063 drff->report->field[0]->value[1] = 0x00;
0064 }
0065
0066 drff->report->field[0]->value[2] = 0x00;
0067 drff->report->field[0]->value[4] = 0x00;
0068 dbg_hid("running with 0x%02x 0x%02x", strong, weak);
0069 hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
0070
0071 return 0;
0072 }
0073
0074 static int drff_init(struct hid_device *hid)
0075 {
0076 struct drff_device *drff;
0077 struct hid_report *report;
0078 struct hid_input *hidinput;
0079 struct list_head *report_list =
0080 &hid->report_enum[HID_OUTPUT_REPORT].report_list;
0081 struct input_dev *dev;
0082 int error;
0083
0084 if (list_empty(&hid->inputs)) {
0085 hid_err(hid, "no inputs found\n");
0086 return -ENODEV;
0087 }
0088 hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
0089 dev = hidinput->input;
0090
0091 if (list_empty(report_list)) {
0092 hid_err(hid, "no output reports found\n");
0093 return -ENODEV;
0094 }
0095
0096 report = list_first_entry(report_list, struct hid_report, list);
0097 if (report->maxfield < 1) {
0098 hid_err(hid, "no fields in the report\n");
0099 return -ENODEV;
0100 }
0101
0102 if (report->field[0]->report_count < 7) {
0103 hid_err(hid, "not enough values in the field\n");
0104 return -ENODEV;
0105 }
0106
0107 drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL);
0108 if (!drff)
0109 return -ENOMEM;
0110
0111 set_bit(FF_RUMBLE, dev->ffbit);
0112
0113 error = input_ff_create_memless(dev, drff, drff_play);
0114 if (error) {
0115 kfree(drff);
0116 return error;
0117 }
0118
0119 drff->report = report;
0120 drff->report->field[0]->value[0] = 0xf3;
0121 drff->report->field[0]->value[1] = 0x00;
0122 drff->report->field[0]->value[2] = 0x00;
0123 drff->report->field[0]->value[3] = 0x00;
0124 drff->report->field[0]->value[4] = 0x00;
0125 drff->report->field[0]->value[5] = 0x00;
0126 drff->report->field[0]->value[6] = 0x00;
0127 hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);
0128
0129 hid_info(hid, "Force Feedback for DragonRise Inc. "
0130 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
0131
0132 return 0;
0133 }
0134 #else
0135 static inline int drff_init(struct hid_device *hid)
0136 {
0137 return 0;
0138 }
0139 #endif
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 #define PID0011_RDESC_ORIG_SIZE 101
0200
0201
0202 static __u8 pid0011_rdesc_fixed[] = {
0203 0x05, 0x01,
0204 0x09, 0x04,
0205 0xA1, 0x01,
0206 0xA1, 0x02,
0207 0x14,
0208 0x75, 0x08,
0209 0x95, 0x03,
0210 0x81, 0x01,
0211 0x26, 0xFF, 0x00,
0212 0x95, 0x02,
0213 0x09, 0x30,
0214 0x09, 0x31,
0215 0x81, 0x02,
0216 0x75, 0x01,
0217 0x95, 0x04,
0218 0x81, 0x01,
0219 0x25, 0x01,
0220 0x95, 0x0A,
0221 0x05, 0x09,
0222 0x19, 0x01,
0223 0x29, 0x0A,
0224 0x81, 0x02,
0225 0x95, 0x0A,
0226 0x81, 0x01,
0227 0xC0,
0228 0xC0
0229 };
0230
0231 static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
0232 unsigned int *rsize)
0233 {
0234 switch (hdev->product) {
0235 case 0x0011:
0236 if (*rsize == PID0011_RDESC_ORIG_SIZE) {
0237 rdesc = pid0011_rdesc_fixed;
0238 *rsize = sizeof(pid0011_rdesc_fixed);
0239 }
0240 break;
0241 }
0242 return rdesc;
0243 }
0244
0245 #define map_abs(c) hid_map_usage(hi, usage, bit, max, EV_ABS, (c))
0246 #define map_rel(c) hid_map_usage(hi, usage, bit, max, EV_REL, (c))
0247
0248 static int dr_input_mapping(struct hid_device *hdev, struct hid_input *hi,
0249 struct hid_field *field, struct hid_usage *usage,
0250 unsigned long **bit, int *max)
0251 {
0252 switch (usage->hid) {
0253
0254
0255
0256
0257 case HID_GD_X: case HID_GD_Y: case HID_GD_Z:
0258 case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
0259 if (field->flags & HID_MAIN_ITEM_RELATIVE)
0260 map_rel(usage->hid & 0xf);
0261 else
0262 map_abs(usage->hid & 0xf);
0263 return 1;
0264 }
0265
0266 return 0;
0267 }
0268
0269 static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
0270 {
0271 int ret;
0272
0273 dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe...");
0274
0275 ret = hid_parse(hdev);
0276 if (ret) {
0277 hid_err(hdev, "parse failed\n");
0278 goto err;
0279 }
0280
0281 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
0282 if (ret) {
0283 hid_err(hdev, "hw start failed\n");
0284 goto err;
0285 }
0286
0287 switch (hdev->product) {
0288 case 0x0006:
0289 ret = drff_init(hdev);
0290 if (ret) {
0291 dev_err(&hdev->dev, "force feedback init failed\n");
0292 hid_hw_stop(hdev);
0293 goto err;
0294 }
0295 break;
0296 }
0297
0298 return 0;
0299 err:
0300 return ret;
0301 }
0302
0303 static const struct hid_device_id dr_devices[] = {
0304 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), },
0305 { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011), },
0306 { }
0307 };
0308 MODULE_DEVICE_TABLE(hid, dr_devices);
0309
0310 static struct hid_driver dr_driver = {
0311 .name = "dragonrise",
0312 .id_table = dr_devices,
0313 .report_fixup = dr_report_fixup,
0314 .probe = dr_probe,
0315 .input_mapping = dr_input_mapping,
0316 };
0317 module_hid_driver(dr_driver);
0318
0319 MODULE_LICENSE("GPL");