brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 54bfaf6 Raw
168 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  HID driver for some a4tech "special" devices4 *5 *  Copyright (c) 1999 Andreas Gal6 *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>7 *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc8 *  Copyright (c) 2006-2007 Jiri Kosina9 *  Copyright (c) 2008 Jiri Slaby10 */11 12/*13 */14 15#include <linux/device.h>16#include <linux/input.h>17#include <linux/hid.h>18#include <linux/module.h>19#include <linux/slab.h>20 21#include "hid-ids.h"22 23#define A4_2WHEEL_MOUSE_HACK_7	0x0124#define A4_2WHEEL_MOUSE_HACK_B8	0x0225 26#define A4_WHEEL_ORIENTATION	(HID_UP_GENDESK | 0x000000b8)27 28struct a4tech_sc {29	unsigned long quirks;30	unsigned int hw_wheel;31	__s32 delayed_value;32};33 34static int a4_input_mapping(struct hid_device *hdev, struct hid_input *hi,35			    struct hid_field *field, struct hid_usage *usage,36			    unsigned long **bit, int *max)37{38	struct a4tech_sc *a4 = hid_get_drvdata(hdev);39 40	if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8 &&41	    usage->hid == A4_WHEEL_ORIENTATION) {42		/*43		 * We do not want to have this usage mapped to anything as it's44		 * nonstandard and doesn't really behave like an HID report.45		 * It's only selecting the orientation (vertical/horizontal) of46		 * the previous mouse wheel report. The input_events will be47		 * generated once both reports are recorded in a4_event().48		 */49		return -1;50	}51 52	return 0;53 54}55 56static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,57		struct hid_field *field, struct hid_usage *usage,58		unsigned long **bit, int *max)59{60	struct a4tech_sc *a4 = hid_get_drvdata(hdev);61 62	if (usage->type == EV_REL && usage->code == REL_WHEEL_HI_RES) {63		set_bit(REL_HWHEEL, *bit);64		set_bit(REL_HWHEEL_HI_RES, *bit);65	}66 67	if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007)68		return -1;69 70	return 0;71}72 73static int a4_event(struct hid_device *hdev, struct hid_field *field,74		struct hid_usage *usage, __s32 value)75{76	struct a4tech_sc *a4 = hid_get_drvdata(hdev);77	struct input_dev *input;78 79	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)80		return 0;81 82	input = field->hidinput->input;83 84	if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) {85		if (usage->type == EV_REL && usage->code == REL_WHEEL_HI_RES) {86			a4->delayed_value = value;87			return 1;88		}89 90		if (usage->hid == A4_WHEEL_ORIENTATION) {91			input_event(input, EV_REL, value ? REL_HWHEEL :92					REL_WHEEL, a4->delayed_value);93			input_event(input, EV_REL, value ? REL_HWHEEL_HI_RES :94					REL_WHEEL_HI_RES, a4->delayed_value * 120);95			return 1;96		}97	}98 99	if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) {100		a4->hw_wheel = !!value;101		return 1;102	}103 104	if (usage->code == REL_WHEEL_HI_RES && a4->hw_wheel) {105		input_event(input, usage->type, REL_HWHEEL, value);106		input_event(input, usage->type, REL_HWHEEL_HI_RES, value * 120);107		return 1;108	}109 110	return 0;111}112 113static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)114{115	struct a4tech_sc *a4;116	int ret;117 118	a4 = devm_kzalloc(&hdev->dev, sizeof(*a4), GFP_KERNEL);119	if (a4 == NULL) {120		hid_err(hdev, "can't alloc device descriptor\n");121		return -ENOMEM;122	}123 124	a4->quirks = id->driver_data;125 126	hid_set_drvdata(hdev, a4);127 128	ret = hid_parse(hdev);129	if (ret) {130		hid_err(hdev, "parse failed\n");131		return ret;132	}133 134	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);135	if (ret) {136		hid_err(hdev, "hw start failed\n");137		return ret;138	}139 140	return 0;141}142 143static const struct hid_device_id a4_devices[] = {144	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU),145		.driver_data = A4_2WHEEL_MOUSE_HACK_7 },146	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),147		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },148	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649),149		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },150	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_NB_95),151		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },152	{ }153};154MODULE_DEVICE_TABLE(hid, a4_devices);155 156static struct hid_driver a4_driver = {157	.name = "a4tech",158	.id_table = a4_devices,159	.input_mapping = a4_input_mapping,160	.input_mapped = a4_input_mapped,161	.event = a4_event,162	.probe = a4_probe,163};164module_hid_driver(a4_driver);165 166MODULE_DESCRIPTION("HID driver for some a4tech \"special\" devices");167MODULE_LICENSE("GPL");168