forked from mirrors/linux
		
	HID: generic: create one input report per application type
It is not a good idea to try to fit all types of applications in the same input report. There are a lot of devices that are needing the quirk HID_MULTI_INPUT but this quirk doesn't match the actual HID description as it is based on the report ID. Given that most devices with MULTI_INPUT I can think of split nicely the devices inputs into application, it is a good thing to split the devices by default based on this assumption. Also make hid-multitouch following this rule, to not have to deal with too many input created. While we are at it, fix some checkpatch complaints about converting 'unsigned' to 'unsigned int'. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
This commit is contained in:
		
							parent
							
								
									e1b63c0148
								
							
						
					
					
						commit
						f07b3c1da9
					
				
					 6 changed files with 56 additions and 13 deletions
				
			
		| 
						 | 
					@ -57,7 +57,9 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle
 | 
				
			||||||
 * Register a new report for a device.
 | 
					 * Register a new report for a device.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
 | 
					struct hid_report *hid_register_report(struct hid_device *device,
 | 
				
			||||||
 | 
									       unsigned int type, unsigned int id,
 | 
				
			||||||
 | 
									       unsigned int application)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hid_report_enum *report_enum = device->report_enum + type;
 | 
						struct hid_report_enum *report_enum = device->report_enum + type;
 | 
				
			||||||
	struct hid_report *report;
 | 
						struct hid_report *report;
 | 
				
			||||||
| 
						 | 
					@ -78,6 +80,7 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type,
 | 
				
			||||||
	report->type = type;
 | 
						report->type = type;
 | 
				
			||||||
	report->size = 0;
 | 
						report->size = 0;
 | 
				
			||||||
	report->device = device;
 | 
						report->device = device;
 | 
				
			||||||
 | 
						report->application = application;
 | 
				
			||||||
	report_enum->report_id_hash[id] = report;
 | 
						report_enum->report_id_hash[id] = report;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_add_tail(&report->list, &report_enum->report_list);
 | 
						list_add_tail(&report->list, &report_enum->report_list);
 | 
				
			||||||
| 
						 | 
					@ -221,11 +224,15 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct hid_report *report;
 | 
						struct hid_report *report;
 | 
				
			||||||
	struct hid_field *field;
 | 
						struct hid_field *field;
 | 
				
			||||||
	unsigned usages;
 | 
						unsigned int usages;
 | 
				
			||||||
	unsigned offset;
 | 
						unsigned int offset;
 | 
				
			||||||
	unsigned i;
 | 
						unsigned int i;
 | 
				
			||||||
 | 
						unsigned int application;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	report = hid_register_report(parser->device, report_type, parser->global.report_id);
 | 
						application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						report = hid_register_report(parser->device, report_type,
 | 
				
			||||||
 | 
									     parser->global.report_id, application);
 | 
				
			||||||
	if (!report) {
 | 
						if (!report) {
 | 
				
			||||||
		hid_err(parser->device, "hid_register_report failed\n");
 | 
							hid_err(parser->device, "hid_register_report failed\n");
 | 
				
			||||||
		return -1;
 | 
							return -1;
 | 
				
			||||||
| 
						 | 
					@ -259,7 +266,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
 | 
						field->physical = hid_lookup_collection(parser, HID_COLLECTION_PHYSICAL);
 | 
				
			||||||
	field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
 | 
						field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
 | 
				
			||||||
	field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 | 
						field->application = application;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < usages; i++) {
 | 
						for (i = 0; i < usages; i++) {
 | 
				
			||||||
		unsigned j = i;
 | 
							unsigned j = i;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,20 @@ static bool hid_generic_match(struct hid_device *hdev,
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int hid_generic_probe(struct hid_device *hdev,
 | 
				
			||||||
 | 
								     const struct hid_device_id *id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hdev->quirks |= HID_QUIRK_INPUT_PER_APP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = hid_parse(hdev);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct hid_device_id hid_table[] = {
 | 
					static const struct hid_device_id hid_table[] = {
 | 
				
			||||||
	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
 | 
						{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, HID_ANY_ID, HID_ANY_ID) },
 | 
				
			||||||
	{ }
 | 
						{ }
 | 
				
			||||||
| 
						 | 
					@ -66,6 +80,7 @@ static struct hid_driver hid_generic = {
 | 
				
			||||||
	.name = "hid-generic",
 | 
						.name = "hid-generic",
 | 
				
			||||||
	.id_table = hid_table,
 | 
						.id_table = hid_table,
 | 
				
			||||||
	.match = hid_generic_match,
 | 
						.match = hid_generic_match,
 | 
				
			||||||
 | 
						.probe = hid_generic_probe,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
module_hid_driver(hid_generic);
 | 
					module_hid_driver(hid_generic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,7 +116,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 | 
				
			||||||
		 * those reports reach gfrm_raw_event() from hid_input_report().
 | 
							 * those reports reach gfrm_raw_event() from hid_input_report().
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (!hid_register_report(hdev, HID_INPUT_REPORT,
 | 
							if (!hid_register_report(hdev, HID_INPUT_REPORT,
 | 
				
			||||||
					 GFRM100_SEARCH_KEY_REPORT_ID)) {
 | 
										 GFRM100_SEARCH_KEY_REPORT_ID, 0)) {
 | 
				
			||||||
			ret = -ENOMEM;
 | 
								ret = -ENOMEM;
 | 
				
			||||||
			goto done;
 | 
								goto done;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1610,6 +1610,20 @@ static struct hid_input *hidinput_match(struct hid_report *report)
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct hid_input *hidinput_match_application(struct hid_report *report)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct hid_device *hid = report->device;
 | 
				
			||||||
 | 
						struct hid_input *hidinput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(hidinput, &hid->inputs, list) {
 | 
				
			||||||
 | 
							if (hidinput->report &&
 | 
				
			||||||
 | 
							    hidinput->report->application == report->application)
 | 
				
			||||||
 | 
								return hidinput;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void hidinput_configure_usages(struct hid_input *hidinput,
 | 
					static inline void hidinput_configure_usages(struct hid_input *hidinput,
 | 
				
			||||||
					     struct hid_report *report)
 | 
										     struct hid_report *report)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1670,6 +1684,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if (hid->quirks & HID_QUIRK_MULTI_INPUT)
 | 
								if (hid->quirks & HID_QUIRK_MULTI_INPUT)
 | 
				
			||||||
				hidinput = hidinput_match(report);
 | 
									hidinput = hidinput_match(report);
 | 
				
			||||||
 | 
								else if (hid->maxapplication > 1 &&
 | 
				
			||||||
 | 
									 (hid->quirks & HID_QUIRK_INPUT_PER_APP))
 | 
				
			||||||
 | 
									hidinput = hidinput_match_application(report);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!hidinput) {
 | 
								if (!hidinput) {
 | 
				
			||||||
				hidinput = hidinput_allocate(hid);
 | 
									hidinput = hidinput_allocate(hid);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -531,12 +531,12 @@ static int magicmouse_probe(struct hid_device *hdev,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
 | 
						if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
 | 
				
			||||||
		report = hid_register_report(hdev, HID_INPUT_REPORT,
 | 
							report = hid_register_report(hdev, HID_INPUT_REPORT,
 | 
				
			||||||
			MOUSE_REPORT_ID);
 | 
								MOUSE_REPORT_ID, 0);
 | 
				
			||||||
	else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 | 
						else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 | 
				
			||||||
		report = hid_register_report(hdev, HID_INPUT_REPORT,
 | 
							report = hid_register_report(hdev, HID_INPUT_REPORT,
 | 
				
			||||||
			TRACKPAD_REPORT_ID);
 | 
								TRACKPAD_REPORT_ID, 0);
 | 
				
			||||||
		report = hid_register_report(hdev, HID_INPUT_REPORT,
 | 
							report = hid_register_report(hdev, HID_INPUT_REPORT,
 | 
				
			||||||
			DOUBLE_REPORT_ID);
 | 
								DOUBLE_REPORT_ID, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!report) {
 | 
						if (!report) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -341,6 +341,7 @@ struct hid_item {
 | 
				
			||||||
/* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT */
 | 
					/* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT */
 | 
				
			||||||
/* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */
 | 
					/* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS */
 | 
				
			||||||
#define HID_QUIRK_ALWAYS_POLL			BIT(10)
 | 
					#define HID_QUIRK_ALWAYS_POLL			BIT(10)
 | 
				
			||||||
 | 
					#define HID_QUIRK_INPUT_PER_APP			BIT(11)
 | 
				
			||||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS		BIT(16)
 | 
					#define HID_QUIRK_SKIP_OUTPUT_REPORTS		BIT(16)
 | 
				
			||||||
#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID		BIT(17)
 | 
					#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID		BIT(17)
 | 
				
			||||||
#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP	BIT(18)
 | 
					#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP	BIT(18)
 | 
				
			||||||
| 
						 | 
					@ -465,8 +466,9 @@ struct hid_field {
 | 
				
			||||||
struct hid_report {
 | 
					struct hid_report {
 | 
				
			||||||
	struct list_head list;
 | 
						struct list_head list;
 | 
				
			||||||
	struct list_head hidinput_list;
 | 
						struct list_head hidinput_list;
 | 
				
			||||||
	unsigned id;					/* id of this report */
 | 
						unsigned int id;				/* id of this report */
 | 
				
			||||||
	unsigned type;					/* report type */
 | 
						unsigned int type;				/* report type */
 | 
				
			||||||
 | 
						unsigned int application;			/* application usage for this report */
 | 
				
			||||||
	struct hid_field *field[HID_MAX_FIELDS];	/* fields of the report */
 | 
						struct hid_field *field[HID_MAX_FIELDS];	/* fields of the report */
 | 
				
			||||||
	unsigned maxfield;				/* maximum valid field index */
 | 
						unsigned maxfield;				/* maximum valid field index */
 | 
				
			||||||
	unsigned size;					/* size of the report (bits) */
 | 
						unsigned size;					/* size of the report (bits) */
 | 
				
			||||||
| 
						 | 
					@ -861,7 +863,9 @@ void hid_output_report(struct hid_report *report, __u8 *data);
 | 
				
			||||||
void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype);
 | 
					void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype);
 | 
				
			||||||
u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 | 
					u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
 | 
				
			||||||
struct hid_device *hid_allocate_device(void);
 | 
					struct hid_device *hid_allocate_device(void);
 | 
				
			||||||
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
 | 
					struct hid_report *hid_register_report(struct hid_device *device,
 | 
				
			||||||
 | 
									       unsigned int type, unsigned int id,
 | 
				
			||||||
 | 
									       unsigned int application);
 | 
				
			||||||
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
 | 
					int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
 | 
				
			||||||
struct hid_report *hid_validate_values(struct hid_device *hid,
 | 
					struct hid_report *hid_validate_values(struct hid_device *hid,
 | 
				
			||||||
				       unsigned int type, unsigned int id,
 | 
									       unsigned int type, unsigned int id,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue