2483 lines · 70.1 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* *  Copyright (c) 2000-2001 Vojtech Pavlik *  Copyright (c) 2006-2010 Jiri Kosina * *  HID to Linux Input mapping */ /* * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ #include <linux/module.h>#include <linux/slab.h>#include <linux/kernel.h> #include <linux/hid.h>#include <linux/hid-debug.h> #include "hid-ids.h" #define unk	KEY_UNKNOWN static const unsigned char hid_keyboard[256] = {	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,	115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,	122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,	unk,unk,unk,unk,unk,unk,179,180,unk,unk,unk,unk,unk,unk,unk,unk,	unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,	unk,unk,unk,unk,unk,unk,unk,unk,111,unk,unk,unk,unk,unk,unk,unk,	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,	150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk}; static const struct {	__s32 x;	__s32 y;}  hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; struct usage_priority {	__u32 usage;			/* the HID usage associated */	bool global;			/* we assume all usages to be slotted,					 * unless global					 */	unsigned int slot_overwrite;	/* for globals: allows to set the usage					 * before or after the slots					 */}; /* * hid-input will convert this list into priorities: * the first element will have the highest priority * (the length of the following array) and the last * element the lowest (1). * * hid-input will then shift the priority by 8 bits to leave some space * in case drivers want to interleave other fields. * * To accommodate slotted devices, the slot priority is * defined in the next 8 bits (defined by 0xff - slot). * * If drivers want to add fields before those, hid-input will * leave out the first 8 bits of the priority value. * * This still leaves us 65535 individual priority values. */static const struct usage_priority hidinput_usages_priorities[] = {	{ /* Eraser (eraser touching) must always come before tipswitch */	  .usage = HID_DG_ERASER,	},	{ /* Invert must always come before In Range */	  .usage = HID_DG_INVERT,	},	{ /* Is the tip of the tool touching? */	  .usage = HID_DG_TIPSWITCH,	},	{ /* Tip Pressure might emulate tip switch */	  .usage = HID_DG_TIPPRESSURE,	},	{ /* In Range needs to come after the other tool states */	  .usage = HID_DG_INRANGE,	},}; #define map_abs(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_ABS, (c))#define map_rel(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c))#define map_key(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c))#define map_led(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c))#define map_msc(c)	hid_map_usage(hidinput, usage, &bit, &max, EV_MSC, (c)) #define map_abs_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \		&max, EV_ABS, (c))#define map_key_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \		&max, EV_KEY, (c)) static bool match_scancode(struct hid_usage *usage,			   unsigned int cur_idx, unsigned int scancode){	return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;} static bool match_keycode(struct hid_usage *usage,			  unsigned int cur_idx, unsigned int keycode){	/*	 * We should exclude unmapped usages when doing lookup by keycode.	 */	return (usage->type == EV_KEY && usage->code == keycode);} static bool match_index(struct hid_usage *usage,			unsigned int cur_idx, unsigned int idx){	return cur_idx == idx;} typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,				unsigned int cur_idx, unsigned int val); static struct hid_usage *hidinput_find_key(struct hid_device *hid,					   hid_usage_cmp_t match,					   unsigned int value,					   unsigned int *usage_idx){	unsigned int i, j, k, cur_idx = 0;	struct hid_report *report;	struct hid_usage *usage; 	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {			for (i = 0; i < report->maxfield; i++) {				for (j = 0; j < report->field[i]->maxusage; j++) {					usage = report->field[i]->usage + j;					if (usage->type == EV_KEY || usage->type == 0) {						if (match(usage, cur_idx, value)) {							if (usage_idx)								*usage_idx = cur_idx;							return usage;						}						cur_idx++;					}				}			}		}	}	return NULL;} static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,					const struct input_keymap_entry *ke,					unsigned int *index){	struct hid_usage *usage;	unsigned int scancode; 	if (ke->flags & INPUT_KEYMAP_BY_INDEX)		usage = hidinput_find_key(hid, match_index, ke->index, index);	else if (input_scancode_to_scalar(ke, &scancode) == 0)		usage = hidinput_find_key(hid, match_scancode, scancode, index);	else		usage = NULL; 	return usage;} static int hidinput_getkeycode(struct input_dev *dev,			       struct input_keymap_entry *ke){	struct hid_device *hid = input_get_drvdata(dev);	struct hid_usage *usage;	unsigned int scancode, index; 	usage = hidinput_locate_usage(hid, ke, &index);	if (usage) {		ke->keycode = usage->type == EV_KEY ?				usage->code : KEY_RESERVED;		ke->index = index;		scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);		ke->len = sizeof(scancode);		memcpy(ke->scancode, &scancode, sizeof(scancode));		return 0;	} 	return -EINVAL;} static int hidinput_setkeycode(struct input_dev *dev,			       const struct input_keymap_entry *ke,			       unsigned int *old_keycode){	struct hid_device *hid = input_get_drvdata(dev);	struct hid_usage *usage; 	usage = hidinput_locate_usage(hid, ke, NULL);	if (usage) {		*old_keycode = usage->type == EV_KEY ?				usage->code : KEY_RESERVED;		usage->type = EV_KEY;		usage->code = ke->keycode; 		clear_bit(*old_keycode, dev->keybit);		set_bit(usage->code, dev->keybit);		dbg_hid("Assigned keycode %d to HID usage code %x\n",			usage->code, usage->hid); 		/*		 * Set the keybit for the old keycode if the old keycode is used		 * by another key		 */		if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))			set_bit(*old_keycode, dev->keybit); 		return 0;	} 	return -EINVAL;}  /** * hidinput_calc_abs_res - calculate an absolute axis resolution * @field: the HID report field to calculate resolution for * @code: axis code * * The formula is: *                         (logical_maximum - logical_minimum) * resolution = ---------------------------------------------------------- *              (physical_maximum - physical_minimum) * 10 ^ unit_exponent * * as seen in the HID specification v1.11 6.2.2.7 Global Items. * * Only exponent 1 length units are processed. Centimeters and inches are * converted to millimeters. Degrees are converted to radians. */__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code){	__s32 unit_exponent = field->unit_exponent;	__s32 logical_extents = field->logical_maximum -					field->logical_minimum;	__s32 physical_extents = field->physical_maximum -					field->physical_minimum;	__s32 prev; 	/* Check if the extents are sane */	if (logical_extents <= 0 || physical_extents <= 0)		return 0; 	/*	 * Verify and convert units.	 * See HID specification v1.11 6.2.2.7 Global Items for unit decoding	 */	switch (code) {	case ABS_X:	case ABS_Y:	case ABS_Z:	case ABS_MT_POSITION_X:	case ABS_MT_POSITION_Y:	case ABS_MT_TOOL_X:	case ABS_MT_TOOL_Y:	case ABS_MT_TOUCH_MAJOR:	case ABS_MT_TOUCH_MINOR:		if (field->unit == 0x11) {		/* If centimeters */			/* Convert to millimeters */			unit_exponent += 1;		} else if (field->unit == 0x13) {	/* If inches */			/* Convert to millimeters */			prev = physical_extents;			physical_extents *= 254;			if (physical_extents < prev)				return 0;			unit_exponent -= 1;		} else {			return 0;		}		break; 	case ABS_RX:	case ABS_RY:	case ABS_RZ:	case ABS_WHEEL:	case ABS_TILT_X:	case ABS_TILT_Y:		if (field->unit == 0x14) {		/* If degrees */			/* Convert to radians */			prev = logical_extents;			logical_extents *= 573;			if (logical_extents < prev)				return 0;			unit_exponent += 1;		} else if (field->unit != 0x12) {	/* If not radians */			return 0;		}		break; 	case ABS_PRESSURE:	case ABS_MT_PRESSURE:		if (field->unit == HID_UNIT_NEWTON) {			/* Convert to grams, 1 newton is 101.97 grams */			prev = physical_extents;			physical_extents *= 10197;			if (physical_extents < prev)				return 0;			unit_exponent -= 2;		} else if (field->unit != HID_UNIT_GRAM) {			return 0;		}		break;	default:		return 0;	} 	/* Apply negative unit exponent */	for (; unit_exponent < 0; unit_exponent++) {		prev = logical_extents;		logical_extents *= 10;		if (logical_extents < prev)			return 0;	}	/* Apply positive unit exponent */	for (; unit_exponent > 0; unit_exponent--) {		prev = physical_extents;		physical_extents *= 10;		if (physical_extents < prev)			return 0;	} 	/* Calculate resolution */	return DIV_ROUND_CLOSEST(logical_extents, physical_extents);}EXPORT_SYMBOL_GPL(hidinput_calc_abs_res); #ifdef CONFIG_HID_BATTERY_STRENGTHstatic enum power_supply_property hidinput_battery_props[] = {	POWER_SUPPLY_PROP_PRESENT,	POWER_SUPPLY_PROP_ONLINE,	POWER_SUPPLY_PROP_CAPACITY,	POWER_SUPPLY_PROP_MODEL_NAME,	POWER_SUPPLY_PROP_STATUS,	POWER_SUPPLY_PROP_SCOPE,}; #define HID_BATTERY_QUIRK_PERCENT	(1 << 0) /* always reports percent */#define HID_BATTERY_QUIRK_FEATURE	(1 << 1) /* ask for feature report */#define HID_BATTERY_QUIRK_IGNORE	(1 << 2) /* completely ignore the battery */#define HID_BATTERY_QUIRK_AVOID_QUERY	(1 << 3) /* do not query the battery */#define HID_BATTERY_QUIRK_DYNAMIC	(1 << 4) /* report present only after life signs */ static const struct hid_device_id hid_battery_quirks[] = {	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,			       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,		USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,		USB_DEVICE_ID_APPLE_MAGICTRACKPAD),	  HID_BATTERY_QUIRK_IGNORE },	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,		USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC),	  HID_BATTERY_QUIRK_AVOID_QUERY },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,		USB_DEVICE_ID_ELECOM_BM084),	  HID_BATTERY_QUIRK_IGNORE },	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL,		USB_DEVICE_ID_SYMBOL_SCANNER_3),	  HID_BATTERY_QUIRK_IGNORE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),	  HID_BATTERY_QUIRK_IGNORE },	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,		USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),	  HID_BATTERY_QUIRK_IGNORE },	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L),	  HID_BATTERY_QUIRK_AVOID_QUERY },	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW),	  HID_BATTERY_QUIRK_AVOID_QUERY },	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW),	  HID_BATTERY_QUIRK_AVOID_QUERY },	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM),	  HID_BATTERY_QUIRK_AVOID_QUERY },	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_PRO_12IN),	  HID_BATTERY_QUIRK_IGNORE },	/*	 * Elan HID touchscreens seem to all report a non present battery,	 * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices.	 */	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC },	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC },	{}}; static unsigned find_battery_quirk(struct hid_device *hdev){	unsigned quirks = 0;	const struct hid_device_id *match; 	match = hid_match_id(hdev, hid_battery_quirks);	if (match != NULL)		quirks = match->driver_data; 	return quirks;} static int hidinput_scale_battery_capacity(struct hid_battery *bat,					   int value){	if (bat->min < bat->max &&	    value >= bat->min && value <= bat->max)		value = ((value - bat->min) * 100) /			(bat->max - bat->min); 	return value;} static int hidinput_query_battery_capacity(struct hid_battery *bat){	int ret;	/*	 * The capacity field may not be the first field in the report: some	 * devices (e.g. the Apple Magic Trackpad 2 over Bluetooth) precede it	 * with status flags. Read it from its actual byte offset in the report	 * (report_offset is in bits; the leading byte is the report id).	 */	int offset = 1 + bat->report_offset / 8;	int len = offset + 1; 	u8 *buf __free(kfree) = kmalloc(max(len, 4), GFP_KERNEL);	if (!buf)		return -ENOMEM; 	ret = hid_hw_raw_request(bat->dev, bat->report_id, buf, max(len, 4),				 bat->report_type, HID_REQ_GET_REPORT);	if (ret < len)		return -ENODATA; 	return hidinput_scale_battery_capacity(bat, buf[offset]);} static int hidinput_get_battery_property(struct power_supply *psy,					 enum power_supply_property prop,					 union power_supply_propval *val){	struct hid_battery *bat = power_supply_get_drvdata(psy);	struct hid_device *dev = bat->dev;	int value;	int ret = 0; 	switch (prop) {	case POWER_SUPPLY_PROP_ONLINE:		val->intval = 1;		break; 	case POWER_SUPPLY_PROP_PRESENT:		val->intval = bat->present;		break; 	case POWER_SUPPLY_PROP_CAPACITY:		if (bat->status != HID_BATTERY_REPORTED &&		    !bat->avoid_query) {			value = hidinput_query_battery_capacity(bat);			if (value < 0)				return value;		} else  {			value = bat->capacity;		} 		val->intval = value;		break; 	case POWER_SUPPLY_PROP_MODEL_NAME:		val->strval = dev->name;		break; 	case POWER_SUPPLY_PROP_STATUS:		if (bat->status != HID_BATTERY_REPORTED &&		    !bat->avoid_query) {			value = hidinput_query_battery_capacity(bat);			if (value < 0)				return value; 

Lines 1–500 of 2483.