1991 lines · 56.6 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}}; #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_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->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; 	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 */ 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_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 },	{}}; 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_device *dev,					   int value){	if (dev->battery_min < dev->battery_max &&	    value >= dev->battery_min && value <= dev->battery_max)		value = ((value - dev->battery_min) * 100) /			(dev->battery_max - dev->battery_min); 	return value;} static int hidinput_query_battery_capacity(struct hid_device *dev){	u8 *buf;	int ret; 	buf = kmalloc(4, GFP_KERNEL);	if (!buf)		return -ENOMEM; 	ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 4,				 dev->battery_report_type, HID_REQ_GET_REPORT);	if (ret < 2) {		kfree(buf);		return -ENODATA;	} 	ret = hidinput_scale_battery_capacity(dev, buf[1]);	kfree(buf);	return ret;} static int hidinput_get_battery_property(struct power_supply *psy,					 enum power_supply_property prop,					 union power_supply_propval *val){	struct hid_device *dev = power_supply_get_drvdata(psy);	int value;	int ret = 0; 	switch (prop) {	case POWER_SUPPLY_PROP_PRESENT:	case POWER_SUPPLY_PROP_ONLINE:		val->intval = 1;		break; 	case POWER_SUPPLY_PROP_CAPACITY:		if (dev->battery_status != HID_BATTERY_REPORTED &&		    !dev->battery_avoid_query) {			value = hidinput_query_battery_capacity(dev);			if (value < 0)				return value;		} else  {			value = dev->battery_capacity;		} 		val->intval = value;		break; 	case POWER_SUPPLY_PROP_MODEL_NAME:		val->strval = dev->name;		break; 	case POWER_SUPPLY_PROP_STATUS:		if (dev->battery_status != HID_BATTERY_REPORTED &&		    !dev->battery_avoid_query) {			value = hidinput_query_battery_capacity(dev);			if (value < 0)				return value; 			dev->battery_capacity = value;			dev->battery_status = HID_BATTERY_QUERIED;		} 		if (dev->battery_status == HID_BATTERY_UNKNOWN)			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;		else if (dev->battery_capacity == 100)			val->intval = POWER_SUPPLY_STATUS_FULL;		else			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;		break; 	case POWER_SUPPLY_PROP_SCOPE:		val->intval = POWER_SUPPLY_SCOPE_DEVICE;		break; 	default:		ret = -EINVAL;		break;	} 	return ret;} static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, struct hid_field *field){	struct power_supply_desc *psy_desc;	struct power_supply_config psy_cfg = { .drv_data = dev, };	unsigned quirks;	s32 min, max;	int error; 	if (dev->battery)		return 0;	/* already initialized? */ 	quirks = find_battery_quirk(dev); 	hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",		dev->bus, dev->vendor, dev->product, dev->version, quirks); 	if (quirks & HID_BATTERY_QUIRK_IGNORE)		return 0; 	psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL);	if (!psy_desc)		return -ENOMEM; 	psy_desc->name = kasprintf(GFP_KERNEL, "hid-%s-battery",				   strlen(dev->uniq) ?					dev->uniq : dev_name(&dev->dev));	if (!psy_desc->name) {		error = -ENOMEM;		goto err_free_mem;	} 	psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;	psy_desc->properties = hidinput_battery_props;	psy_desc->num_properties = ARRAY_SIZE(hidinput_battery_props);	psy_desc->use_for_apm = 0;	psy_desc->get_property = hidinput_get_battery_property; 	min = field->logical_minimum;	max = field->logical_maximum; 	if (quirks & HID_BATTERY_QUIRK_PERCENT) {		min = 0;		max = 100;	} 	if (quirks & HID_BATTERY_QUIRK_FEATURE)		report_type = HID_FEATURE_REPORT; 	dev->battery_min = min;	dev->battery_max = max;	dev->battery_report_type = report_type;	dev->battery_report_id = field->report->id; 	/*	 * Stylus is normally not connected to the device and thus we	 * can't query the device and get meaningful battery strength.	 * We have to wait for the device to report it on its own.	 */	dev->battery_avoid_query = report_type == HID_INPUT_REPORT &&				   field->physical == HID_DG_STYLUS; 	dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);	if (IS_ERR(dev->battery)) {		error = PTR_ERR(dev->battery);		hid_warn(dev, "can't register power supply: %d\n", error);		goto err_free_name;	} 	power_supply_powers(dev->battery, &dev->dev);	return 0;

Lines 1–500 of 1991.