cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-emsff.c (3314B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Force feedback support for EMS Trio Linker Plus II
      4 *
      5 *  Copyright (c) 2010 Ignaz Forster <ignaz.forster@gmx.de>
      6 */
      7
      8/*
      9 */
     10
     11
     12#include <linux/hid.h>
     13#include <linux/input.h>
     14#include <linux/module.h>
     15
     16#include "hid-ids.h"
     17
     18struct emsff_device {
     19	struct hid_report *report;
     20};
     21
     22static int emsff_play(struct input_dev *dev, void *data,
     23			 struct ff_effect *effect)
     24{
     25	struct hid_device *hid = input_get_drvdata(dev);
     26	struct emsff_device *emsff = data;
     27	int weak, strong;
     28
     29	weak = effect->u.rumble.weak_magnitude;
     30	strong = effect->u.rumble.strong_magnitude;
     31
     32	dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);
     33
     34	weak = weak * 0xff / 0xffff;
     35	strong = strong * 0xff / 0xffff;
     36
     37	emsff->report->field[0]->value[1] = weak;
     38	emsff->report->field[0]->value[2] = strong;
     39
     40	dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
     41	hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
     42
     43	return 0;
     44}
     45
     46static int emsff_init(struct hid_device *hid)
     47{
     48	struct emsff_device *emsff;
     49	struct hid_report *report;
     50	struct hid_input *hidinput;
     51	struct list_head *report_list =
     52			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
     53	struct input_dev *dev;
     54	int error;
     55
     56	if (list_empty(&hid->inputs)) {
     57		hid_err(hid, "no inputs found\n");
     58		return -ENODEV;
     59	}
     60	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
     61	dev = hidinput->input;
     62
     63	if (list_empty(report_list)) {
     64		hid_err(hid, "no output reports found\n");
     65		return -ENODEV;
     66	}
     67
     68	report = list_first_entry(report_list, struct hid_report, list);
     69	if (report->maxfield < 1) {
     70		hid_err(hid, "no fields in the report\n");
     71		return -ENODEV;
     72	}
     73
     74	if (report->field[0]->report_count < 7) {
     75		hid_err(hid, "not enough values in the field\n");
     76		return -ENODEV;
     77	}
     78
     79	emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL);
     80	if (!emsff)
     81		return -ENOMEM;
     82
     83	set_bit(FF_RUMBLE, dev->ffbit);
     84
     85	error = input_ff_create_memless(dev, emsff, emsff_play);
     86	if (error) {
     87		kfree(emsff);
     88		return error;
     89	}
     90
     91	emsff->report = report;
     92	emsff->report->field[0]->value[0] = 0x01;
     93	emsff->report->field[0]->value[1] = 0x00;
     94	emsff->report->field[0]->value[2] = 0x00;
     95	emsff->report->field[0]->value[3] = 0x00;
     96	emsff->report->field[0]->value[4] = 0x00;
     97	emsff->report->field[0]->value[5] = 0x00;
     98	emsff->report->field[0]->value[6] = 0x00;
     99	hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);
    100
    101	hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <ignaz.forster@gmx.de>\n");
    102
    103	return 0;
    104}
    105
    106static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id)
    107{
    108	int ret;
    109
    110	ret = hid_parse(hdev);
    111	if (ret) {
    112		hid_err(hdev, "parse failed\n");
    113		goto err;
    114	}
    115
    116	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
    117	if (ret) {
    118		hid_err(hdev, "hw start failed\n");
    119		goto err;
    120	}
    121
    122	ret = emsff_init(hdev);
    123	if (ret) {
    124		dev_err(&hdev->dev, "force feedback init failed\n");
    125		hid_hw_stop(hdev);
    126		goto err;
    127	}
    128
    129	return 0;
    130err:
    131	return ret;
    132}
    133
    134static const struct hid_device_id ems_devices[] = {
    135	{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
    136	{ }
    137};
    138MODULE_DEVICE_TABLE(hid, ems_devices);
    139
    140static struct hid_driver ems_driver = {
    141	.name = "hkems",
    142	.id_table = ems_devices,
    143	.probe = ems_probe,
    144};
    145module_hid_driver(ems_driver);
    146
    147MODULE_LICENSE("GPL");
    148