3290 lines · 81.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* *  HID support for Linux * *  Copyright (c) 1999 Andreas Gal *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz> *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc *  Copyright (c) 2006-2012 Jiri Kosina */ /* */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/mm.h>#include <linux/spinlock.h>#include <linux/unaligned.h>#include <asm/byteorder.h>#include <linux/input.h>#include <linux/wait.h>#include <linux/vmalloc.h>#include <linux/sched.h>#include <linux/semaphore.h> #include <linux/hid.h>#include <linux/hiddev.h>#include <linux/hid-debug.h>#include <linux/hidraw.h> #include "hid-ids.h" /* * Version Information */ #define DRIVER_DESC "HID core driver" static int hid_ignore_special_drivers = 0;module_param_named(ignore_special_drivers, hid_ignore_special_drivers, int, 0600);MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle all devices by generic driver"); /* * Convert a signed n-bit integer to signed 32-bit integer. */ static s32 snto32(__u32 value, unsigned int n){	if (!value || !n)		return 0; 	if (n > 32)		n = 32; 	return sign_extend32(value, n - 1);} /* * Convert a signed 32-bit integer to a signed n-bit integer. */ static u32 s32ton(__s32 value, unsigned int n){	s32 a; 	if (!value || !n)		return 0; 	if (n > 32)		n = 32; 	a = value >> (n - 1);	if (a && a != -1)		return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;	return value & ((1 << n) - 1);} /* * Register a new report for a device. */ struct hid_report *hid_register_report(struct hid_device *device,				       enum hid_report_type type, unsigned int id,				       unsigned int application){	struct hid_report_enum *report_enum = device->report_enum + type;	struct hid_report *report; 	if (id >= HID_MAX_IDS)		return NULL;	if (report_enum->report_id_hash[id])		return report_enum->report_id_hash[id]; 	report = kzalloc_obj(struct hid_report);	if (!report)		return NULL; 	if (id != 0)		report_enum->numbered = 1; 	report->id = id;	report->type = type;	report->size = 0;	report->device = device;	report->application = application;	report_enum->report_id_hash[id] = report; 	list_add_tail(&report->list, &report_enum->report_list);	INIT_LIST_HEAD(&report->field_entry_list); 	return report;}EXPORT_SYMBOL_GPL(hid_register_report); /* * Register a new field for this report. */ static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages){	struct hid_field *field; 	if (report->maxfield == HID_MAX_FIELDS) {		hid_err(report->device, "too many fields in report\n");		return NULL;	} 	field = kvzalloc((sizeof(struct hid_field) +			  usages * sizeof(struct hid_usage) +			  3 * usages * sizeof(unsigned int)), GFP_KERNEL);	if (!field)		return NULL; 	field->index = report->maxfield++;	report->field[field->index] = field;	field->usage = (struct hid_usage *)(field + 1);	field->value = (s32 *)(field->usage + usages);	field->new_value = (s32 *)(field->value + usages);	field->usages_priorities = (s32 *)(field->new_value + usages);	field->report = report; 	return field;} /* * Open a collection. The type/usage is pushed on the stack. */ static int open_collection(struct hid_parser *parser, unsigned type){	struct hid_collection *collection;	unsigned usage;	int collection_index; 	usage = parser->local.usage[0]; 	if (parser->collection_stack_ptr == parser->collection_stack_size) {		unsigned int *collection_stack;		unsigned int new_size = parser->collection_stack_size +					HID_COLLECTION_STACK_SIZE; 		collection_stack = krealloc(parser->collection_stack,					    new_size * sizeof(unsigned int),					    GFP_KERNEL);		if (!collection_stack)			return -ENOMEM; 		parser->collection_stack = collection_stack;		parser->collection_stack_size = new_size;	} 	if (parser->device->maxcollection == parser->device->collection_size) {		collection = kmalloc(				array3_size(sizeof(struct hid_collection),					    parser->device->collection_size,					    2),				GFP_KERNEL);		if (collection == NULL) {			hid_err(parser->device, "failed to reallocate collection array\n");			return -ENOMEM;		}		memcpy(collection, parser->device->collection,			sizeof(struct hid_collection) *			parser->device->collection_size);		memset(collection + parser->device->collection_size, 0,			sizeof(struct hid_collection) *			parser->device->collection_size);		kfree(parser->device->collection);		parser->device->collection = collection;		parser->device->collection_size *= 2;	} 	parser->collection_stack[parser->collection_stack_ptr++] =		parser->device->maxcollection; 	collection_index = parser->device->maxcollection++;	collection = parser->device->collection + collection_index;	collection->type = type;	collection->usage = usage;	collection->level = parser->collection_stack_ptr - 1;	collection->parent_idx = (collection->level == 0) ? -1 :		parser->collection_stack[collection->level - 1]; 	if (type == HID_COLLECTION_APPLICATION)		parser->device->maxapplication++; 	return 0;} /* * Close a collection. */ static int close_collection(struct hid_parser *parser){	if (!parser->collection_stack_ptr) {		hid_err(parser->device, "collection stack underflow\n");		return -EINVAL;	}	parser->collection_stack_ptr--;	return 0;} /* * Climb up the stack, search for the specified collection type * and return the usage. */ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type){	struct hid_collection *collection = parser->device->collection;	int n; 	for (n = parser->collection_stack_ptr - 1; n >= 0; n--) {		unsigned index = parser->collection_stack[n];		if (collection[index].type == type)			return collection[index].usage;	}	return 0; /* we know nothing about this usage type */} /* * Concatenate usage which defines 16 bits or less with the * currently defined usage page to form a 32 bit usage */ static void complete_usage(struct hid_parser *parser, unsigned int index){	parser->local.usage[index] &= 0xFFFF;	parser->local.usage[index] |=		(parser->global.usage_page & 0xFFFF) << 16;} /* * Add a usage to the temporary parser table. */ static int hid_add_usage(struct hid_parser *parser, unsigned usage, u8 size){	if (parser->local.usage_index >= HID_MAX_USAGES) {		hid_err(parser->device, "usage index exceeded\n");		return -1;	}	parser->local.usage[parser->local.usage_index] = usage; 	/*	 * If Usage item only includes usage id, concatenate it with	 * currently defined usage page	 */	if (size <= 2)		complete_usage(parser, parser->local.usage_index); 	parser->local.usage_size[parser->local.usage_index] = size;	parser->local.collection_index[parser->local.usage_index] =		parser->collection_stack_ptr ?		parser->collection_stack[parser->collection_stack_ptr - 1] : 0;	parser->local.usage_index++;	return 0;} /* * Register a new field for this report. */ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsigned flags){	struct hid_report *report;	struct hid_field *field;	unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;	unsigned int usages;	unsigned int offset;	unsigned int i;	unsigned int application; 	application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION); 	report = hid_register_report(parser->device, report_type,				     parser->global.report_id, application);	if (!report) {		hid_err(parser->device, "hid_register_report failed\n");		return -1;	} 	/* Handle both signed and unsigned cases properly */	if ((parser->global.logical_minimum < 0 &&		parser->global.logical_maximum <		parser->global.logical_minimum) ||		(parser->global.logical_minimum >= 0 &&		(__u32)parser->global.logical_maximum <		(__u32)parser->global.logical_minimum)) {		dbg_hid("logical range invalid 0x%x 0x%x\n",			parser->global.logical_minimum,			parser->global.logical_maximum);		return -1;	} 	offset = report->size;	report->size += parser->global.report_size * parser->global.report_count; 	if (parser->device->ll_driver->max_buffer_size)		max_buffer_size = parser->device->ll_driver->max_buffer_size; 	/* Total size check: Allow for possible report index byte */	if (report->size > (max_buffer_size - 1) << 3) {		hid_err(parser->device, "report is too long\n");		return -1;	} 	if (!parser->local.usage_index) /* Ignore padding fields */		return 0; 	usages = max_t(unsigned, parser->local.usage_index,				 parser->global.report_count); 	field = hid_register_field(report, usages);	if (!field)		return 0; 	field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);	field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);	field->application = application; 	for (i = 0; i < usages; i++) {		unsigned j = i;		/* Duplicate the last usage we parsed if we have excess values */		if (i >= parser->local.usage_index)			j = parser->local.usage_index - 1;		field->usage[i].hid = parser->local.usage[j];		field->usage[i].collection_index =			parser->local.collection_index[j];		field->usage[i].usage_index = i;		field->usage[i].resolution_multiplier = 1;	} 	field->maxusage = usages;	field->flags = flags;	field->report_offset = offset;	field->report_type = report_type;	field->report_size = parser->global.report_size;	field->report_count = parser->global.report_count;	field->logical_minimum = parser->global.logical_minimum;	field->logical_maximum = parser->global.logical_maximum;	field->physical_minimum = parser->global.physical_minimum;	field->physical_maximum = parser->global.physical_maximum;	field->unit_exponent = parser->global.unit_exponent;	field->unit = parser->global.unit; 	return 0;} /* * Read data value from item. */ static u32 item_udata(struct hid_item *item){	if (item->format != HID_ITEM_FORMAT_SHORT)		return 0; 	switch (item->size) {	case 1: return item->data.u8;	case 2: return item->data.u16;	case 4: return item->data.u32;	}	return 0;} static s32 item_sdata(struct hid_item *item){	if (item->format != HID_ITEM_FORMAT_SHORT)		return 0; 	switch (item->size) {	case 1: return item->data.s8;	case 2: return item->data.s16;	case 4: return item->data.s32;	}	return 0;} /* * Process a global item. */ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item){	__s32 raw_value;	switch (item->tag) {	case HID_GLOBAL_ITEM_TAG_PUSH: 		if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {			hid_err(parser->device, "global environment stack overflow\n");			return -1;		} 		memcpy(parser->global_stack + parser->global_stack_ptr++,			&parser->global, sizeof(struct hid_global));		return 0; 	case HID_GLOBAL_ITEM_TAG_POP: 		if (!parser->global_stack_ptr) {			hid_err(parser->device, "global environment stack underflow\n");			return -1;		} 		memcpy(&parser->global, parser->global_stack +			--parser->global_stack_ptr, sizeof(struct hid_global));		return 0; 	case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:		parser->global.usage_page = item_udata(item);		return 0; 	case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:		parser->global.logical_minimum = item_sdata(item);		return 0; 	case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:		if (parser->global.logical_minimum < 0)			parser->global.logical_maximum = item_sdata(item);		else			parser->global.logical_maximum = item_udata(item);		return 0; 	case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:		parser->global.physical_minimum = item_sdata(item);		return 0; 	case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:		if (parser->global.physical_minimum < 0)			parser->global.physical_maximum = item_sdata(item);		else			parser->global.physical_maximum = item_udata(item);		return 0; 	case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:		/* Many devices provide unit exponent as a two's complement		 * nibble due to the common misunderstanding of HID		 * specification 1.11, 6.2.2.7 Global Items. Attempt to handle		 * both this and the standard encoding. */		raw_value = item_sdata(item);		if (!(raw_value & 0xfffffff0))			parser->global.unit_exponent = snto32(raw_value, 4);		else			parser->global.unit_exponent = raw_value;		return 0; 	case HID_GLOBAL_ITEM_TAG_UNIT:		parser->global.unit = item_udata(item);		return 0; 	case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:		parser->global.report_size = item_udata(item);		if (parser->global.report_size > 256) {			hid_err(parser->device, "invalid report_size %d\n",					parser->global.report_size);			return -1;		}		return 0; 	case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:		parser->global.report_count = item_udata(item);		if (parser->global.report_count > HID_MAX_USAGES) {			hid_err(parser->device, "invalid report_count %d\n",					parser->global.report_count);			return -1;		}		return 0; 	case HID_GLOBAL_ITEM_TAG_REPORT_ID:		parser->global.report_id = item_udata(item);		if (parser->global.report_id == 0 ||		    parser->global.report_id >= HID_MAX_IDS) {			hid_err(parser->device, "report_id %u is invalid\n",

Lines 1–500 of 3290.