Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Force feedback support for EMS Trio Linker Plus II
0004  *
0005  *  Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.de>
0006  */
0007 
0008 /*
0009  */
0010 
0011 
0012 #include <linux/hid.h>
0013 #include <linux/input.h>
0014 #include <linux/module.h>
0015 
0016 #include "hid-ids.h"
0017 
0018 struct emsff_device {
0019     struct hid_report *report;
0020 };
0021 
0022 static int emsff_play(struct input_dev *dev, void *data,
0023              struct ff_effect *effect)
0024 {
0025     struct hid_device *hid = input_get_drvdata(dev);
0026     struct emsff_device *emsff = data;
0027     int weak, strong;
0028 
0029     weak = effect->u.rumble.weak_magnitude;
0030     strong = effect->u.rumble.strong_magnitude;
0031 
0032     dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);
0033 
0034     weak = weak * 0xff / 0xffff;
0035     strong = strong * 0xff / 0xffff;
0036 
0037     emsff->report->field[0]->value[1] = weak;
0038     emsff->report->field[0]->value[2] = strong;
0039 
0040     dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
0041     hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
0042 
0043     return 0;
0044 }
0045 
0046 static int emsff_init(struct hid_device *hid)
0047 {
0048     struct emsff_device *emsff;
0049     struct hid_report *report;
0050     struct hid_input *hidinput;
0051     struct list_head *report_list =
0052             &hid->report_enum[HID_OUTPUT_REPORT].report_list;
0053     struct input_dev *dev;
0054     int error;
0055 
0056     if (list_empty(&hid->inputs)) {
0057         hid_err(hid, "no inputs found\n");
0058         return -ENODEV;
0059     }
0060     hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
0061     dev = hidinput->input;
0062 
0063     if (list_empty(report_list)) {
0064         hid_err(hid, "no output reports found\n");
0065         return -ENODEV;
0066     }
0067 
0068     report = list_first_entry(report_list, struct hid_report, list);
0069     if (report->maxfield < 1) {
0070         hid_err(hid, "no fields in the report\n");
0071         return -ENODEV;
0072     }
0073 
0074     if (report->field[0]->report_count < 7) {
0075         hid_err(hid, "not enough values in the field\n");
0076         return -ENODEV;
0077     }
0078 
0079     emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL);
0080     if (!emsff)
0081         return -ENOMEM;
0082 
0083     set_bit(FF_RUMBLE, dev->ffbit);
0084 
0085     error = input_ff_create_memless(dev, emsff, emsff_play);
0086     if (error) {
0087         kfree(emsff);
0088         return error;
0089     }
0090 
0091     emsff->report = report;
0092     emsff->report->field[0]->value[0] = 0x01;
0093     emsff->report->field[0]->value[1] = 0x00;
0094     emsff->report->field[0]->value[2] = 0x00;
0095     emsff->report->field[0]->value[3] = 0x00;
0096     emsff->report->field[0]->value[4] = 0x00;
0097     emsff->report->field[0]->value[5] = 0x00;
0098     emsff->report->field[0]->value[6] = 0x00;
0099     hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
0100 
0101     hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
0102 
0103     return 0;
0104 }
0105 
0106 static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id)
0107 {
0108     int ret;
0109 
0110     ret = hid_parse(hdev);
0111     if (ret) {
0112         hid_err(hdev, "parse failed\n");
0113         goto err;
0114     }
0115 
0116     ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
0117     if (ret) {
0118         hid_err(hdev, "hw start failed\n");
0119         goto err;
0120     }
0121 
0122     ret = emsff_init(hdev);
0123     if (ret) {
0124         dev_err(&hdev->dev, "force feedback init failed\n");
0125         hid_hw_stop(hdev);
0126         goto err;
0127     }
0128 
0129     return 0;
0130 err:
0131     return ret;
0132 }
0133 
0134 static const struct hid_device_id ems_devices[] = {
0135     { HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
0136     { }
0137 };
0138 MODULE_DEVICE_TABLE(hid, ems_devices);
0139 
0140 static struct hid_driver ems_driver = {
0141     .name = "hkems",
0142     .id_table = ems_devices,
0143     .probe = ems_probe,
0144 };
0145 module_hid_driver(ems_driver);
0146 
0147 MODULE_LICENSE("GPL");
0148