diff options
Diffstat (limited to 'drivers/hid/hid-core.c')
| -rw-r--r-- | drivers/hid/hid-core.c | 56 | 
1 files changed, 43 insertions, 13 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9c1d31f63f85..1ee623c26c49 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -41,11 +41,6 @@  #define DRIVER_DESC "HID core driver" -int hid_debug = 0; -module_param_named(debug, hid_debug, int, 0600); -MODULE_PARM_DESC(debug, "toggle HID debugging messages"); -EXPORT_SYMBOL_GPL(hid_debug); -  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"); @@ -804,7 +799,8 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)  	int i;  	if (((parser->global.usage_page << 16) == HID_UP_SENSOR) && -	    type == HID_COLLECTION_PHYSICAL) +	    (type == HID_COLLECTION_PHYSICAL || +	     type == HID_COLLECTION_APPLICATION))  		hid->group = HID_GROUP_SENSOR_HUB;  	if (hid->vendor == USB_VENDOR_ID_MICROSOFT && @@ -993,8 +989,8 @@ struct hid_report *hid_validate_values(struct hid_device *hid,  		 * Validating on id 0 means we should examine the first  		 * report in the list.  		 */ -		report = list_entry( -				hid->report_enum[type].report_list.next, +		report = list_first_entry_or_null( +				&hid->report_enum[type].report_list,  				struct hid_report, list);  	} else {  		report = hid->report_enum[type].report_id_hash[id]; @@ -1202,6 +1198,7 @@ int hid_open_report(struct hid_device *device)  	__u8 *end;  	__u8 *next;  	int ret; +	int i;  	static int (*dispatch_type[])(struct hid_parser *parser,  				      struct hid_item *item) = {  		hid_parser_main, @@ -1218,7 +1215,8 @@ int hid_open_report(struct hid_device *device)  		return -ENODEV;  	size = device->dev_rsize; -	buf = kmemdup(start, size, GFP_KERNEL); +	/* call_hid_bpf_rdesc_fixup() ensures we work on a copy of rdesc */ +	buf = call_hid_bpf_rdesc_fixup(device, start, &size);  	if (buf == NULL)  		return -ENOMEM; @@ -1252,6 +1250,8 @@ int hid_open_report(struct hid_device *device)  		goto err;  	}  	device->collection_size = HID_DEFAULT_NUM_COLLECTIONS; +	for (i = 0; i < HID_DEFAULT_NUM_COLLECTIONS; i++) +		device->collection[i].parent_idx = -1;  	ret = -EINVAL;  	while ((next = fetch_item(start, end, &item)) != NULL) { @@ -1315,6 +1315,9 @@ static s32 snto32(__u32 value, unsigned n)  	if (!value || !n)  		return 0; +	if (n > 32) +		n = 32; +  	switch (n) {  	case 8:  return ((__s8)value);  	case 16: return ((__s16)value); @@ -2040,6 +2043,12 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data  	report_enum = hid->report_enum + type;  	hdrv = hid->driver; +	data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt); +	if (IS_ERR(data)) { +		ret = PTR_ERR(data); +		goto unlock; +	} +  	if (!size) {  		dbg_hid("empty report\n");  		ret = -1; @@ -2154,6 +2163,10 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)  	int len;  	int ret; +	ret = hid_bpf_connect_device(hdev); +	if (ret) +		return ret; +  	if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE)  		connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV);  	if (hdev->quirks & HID_QUIRK_HIDINPUT_FORCE) @@ -2255,6 +2268,8 @@ void hid_disconnect(struct hid_device *hdev)  	if (hdev->claimed & HID_CLAIMED_HIDRAW)  		hidraw_disconnect(hdev);  	hdev->claimed = 0; + +	hid_bpf_disconnect_device(hdev);  }  EXPORT_SYMBOL_GPL(hid_disconnect); @@ -2790,6 +2805,8 @@ struct hid_device *hid_allocate_device(void)  	sema_init(&hdev->driver_input_lock, 1);  	mutex_init(&hdev->ll_open_lock); +	hid_bpf_device_init(hdev); +  	return hdev;  }  EXPORT_SYMBOL_GPL(hid_allocate_device); @@ -2816,6 +2833,7 @@ static void hid_remove_device(struct hid_device *hdev)   */  void hid_destroy_device(struct hid_device *hdev)  { +	hid_bpf_destroy_device(hdev);  	hid_remove_device(hdev);  	put_device(&hdev->dev);  } @@ -2902,20 +2920,29 @@ int hid_check_keys_pressed(struct hid_device *hid)  }  EXPORT_SYMBOL_GPL(hid_check_keys_pressed); +#ifdef CONFIG_HID_BPF +static struct hid_bpf_ops hid_ops = { +	.hid_get_report = hid_get_report, +	.hid_hw_raw_request = hid_hw_raw_request, +	.owner = THIS_MODULE, +	.bus_type = &hid_bus_type, +}; +#endif +  static int __init hid_init(void)  {  	int ret; -	if (hid_debug) -		pr_warn("hid_debug is now used solely for parser and driver debugging.\n" -			"debugfs is now used for inspecting the device (report descriptor, reports)\n"); -  	ret = bus_register(&hid_bus_type);  	if (ret) {  		pr_err("can't register hid bus\n");  		goto err;  	} +#ifdef CONFIG_HID_BPF +	hid_bpf_ops = &hid_ops; +#endif +  	ret = hidraw_init();  	if (ret)  		goto err_bus; @@ -2931,6 +2958,9 @@ err:  static void __exit hid_exit(void)  { +#ifdef CONFIG_HID_BPF +	hid_bpf_ops = NULL; +#endif  	hid_debug_exit();  	hidraw_exit();  	bus_unregister(&hid_bus_type);  |