diff options
| -rw-r--r-- | Documentation/hid/uhid.txt | 11 | ||||
| -rw-r--r-- | drivers/hid/hid-ids.h | 3 | ||||
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 281 | ||||
| -rw-r--r-- | drivers/hid/hid-sony.c | 12 | ||||
| -rw-r--r-- | drivers/hid/uhid.c | 78 | ||||
| -rw-r--r-- | include/linux/hid.h | 3 | ||||
| -rw-r--r-- | include/uapi/linux/uhid.h | 23 | 
7 files changed, 233 insertions, 178 deletions
| diff --git a/Documentation/hid/uhid.txt b/Documentation/hid/uhid.txt index dc35a2b75eee..ee6593608c8e 100644 --- a/Documentation/hid/uhid.txt +++ b/Documentation/hid/uhid.txt @@ -93,6 +93,11 @@ the request was handled successfully.    event to the kernel. The payload is of type struct uhid_create_req and    contains information about your device. You can start I/O now. +  UHID_CREATE2: +  Same as UHID_CREATE, but the HID report descriptor data (rd_data) is an array +  inside struct uhid_create2_req, instead of a pointer to a separate array. +  Enables use from languages that don't support pointers, e.g. Python. +    UHID_DESTROY:    This destroys the internal HID device. No further I/O will be accepted. There    may still be pending messages that you can receive with read() but no further @@ -105,6 +110,12 @@ the request was handled successfully.    contains a data-payload. This is the raw data that you read from your device.    The kernel will parse the HID reports and react on it. +  UHID_INPUT2: +  Same as UHID_INPUT, but the data array is the last field of uhid_input2_req. +  Enables userspace to write only the required bytes to kernel (ev.type + +  ev.u.input2.size + the part of the data array that matters), instead of +  the entire struct uhid_input2_req. +    UHID_FEATURE_ANSWER:    If you receive a UHID_FEATURE request you must answer with this request. You    must copy the "id" field from the request into the answer. Set the "err" field diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index af15a631bb24..548c1a519593 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -67,6 +67,9 @@  #define USB_VENDOR_ID_ALPS		0x0433  #define USB_DEVICE_ID_IBM_GAMEPAD	0x1101 +#define USB_VENDOR_ID_ANTON		0x1130 +#define USB_DEVICE_ID_ANTON_TOUCH_PAD	0x3101 +  #define USB_VENDOR_ID_APPLE		0x05ac  #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304  #define USB_DEVICE_ID_APPLE_MAGICMOUSE	0x030d diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 221d503f1c24..35278e43c7a4 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -68,6 +68,9 @@ MODULE_LICENSE("GPL");  #define MT_QUIRK_HOVERING		(1 << 11)  #define MT_QUIRK_CONTACT_CNT_ACCURATE	(1 << 12) +#define MT_INPUTMODE_TOUCHSCREEN	0x02 +#define MT_INPUTMODE_TOUCHPAD		0x03 +  struct mt_slot {  	__s32 x, y, cx, cy, p, w, h;  	__s32 contactid;	/* the device ContactID assigned to this slot */ @@ -84,6 +87,7 @@ struct mt_class {  	__s32 sn_pressure;	/* Signal/noise ratio for pressure events */  	__u8 maxcontacts;  	bool is_indirect;	/* true for touchpads */ +	bool export_all_inputs;	/* do not ignore mouse, keyboards, etc... */  };  struct mt_fields { @@ -100,11 +104,11 @@ struct mt_device {  	int cc_value_index;	/* contact count value index in the field */  	unsigned last_slot_field;	/* the last field of a slot */  	unsigned mt_report_id;	/* the report ID of the multitouch device */ -	unsigned pen_report_id;	/* the report ID of the pen device */  	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */  	__s16 inputmode_index;	/* InputMode HID feature index in the report */  	__s16 maxcontact_report_id;	/* Maximum Contact Number HID feature,  				   -1 if non-existent */ +	__u8 inputmode_value;  /* InputMode HID feature value */  	__u8 num_received;	/* how many contacts we received */  	__u8 num_expected;	/* expected last contact index */  	__u8 maxcontacts; @@ -128,16 +132,17 @@ static void mt_post_parse(struct mt_device *td);  #define MT_CLS_CONFIDENCE_MINUS_ONE		0x0005  #define MT_CLS_DUAL_INRANGE_CONTACTID		0x0006  #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	0x0007 -#define MT_CLS_DUAL_NSMU_CONTACTID		0x0008 +/* reserved					0x0008 */  #define MT_CLS_INRANGE_CONTACTNUMBER		0x0009  #define MT_CLS_NSMU				0x000a -#define MT_CLS_DUAL_CONTACT_NUMBER		0x0010 -#define MT_CLS_DUAL_CONTACT_ID			0x0011 +/* reserved					0x0010 */ +/* reserved					0x0011 */  #define MT_CLS_WIN_8				0x0012 +#define MT_CLS_EXPORT_ALL_INPUTS		0x0013  /* vendor specific classes */  #define MT_CLS_3M				0x0101 -#define MT_CLS_CYPRESS				0x0102 +/* reserved					0x0102 */  #define MT_CLS_EGALAX				0x0103  #define MT_CLS_EGALAX_SERIAL			0x0104  #define MT_CLS_TOPSEED				0x0105 @@ -189,28 +194,18 @@ static struct mt_class mt_classes[] = {  		.quirks = MT_QUIRK_VALID_IS_INRANGE |  			MT_QUIRK_SLOT_IS_CONTACTNUMBER,  		.maxcontacts = 2 }, -	{ .name = MT_CLS_DUAL_NSMU_CONTACTID, -		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | -			MT_QUIRK_SLOT_IS_CONTACTID, -		.maxcontacts = 2 },  	{ .name = MT_CLS_INRANGE_CONTACTNUMBER,  		.quirks = MT_QUIRK_VALID_IS_INRANGE |  			MT_QUIRK_SLOT_IS_CONTACTNUMBER }, -	{ .name = MT_CLS_DUAL_CONTACT_NUMBER, -		.quirks = MT_QUIRK_ALWAYS_VALID | -			MT_QUIRK_CONTACT_CNT_ACCURATE | -			MT_QUIRK_SLOT_IS_CONTACTNUMBER, -		.maxcontacts = 2 }, -	{ .name = MT_CLS_DUAL_CONTACT_ID, -		.quirks = MT_QUIRK_ALWAYS_VALID | -			MT_QUIRK_CONTACT_CNT_ACCURATE | -			MT_QUIRK_SLOT_IS_CONTACTID, -		.maxcontacts = 2 },  	{ .name = MT_CLS_WIN_8,  		.quirks = MT_QUIRK_ALWAYS_VALID |  			MT_QUIRK_IGNORE_DUPLICATES |  			MT_QUIRK_HOVERING |  			MT_QUIRK_CONTACT_CNT_ACCURATE }, +	{ .name = MT_CLS_EXPORT_ALL_INPUTS, +		.quirks = MT_QUIRK_ALWAYS_VALID | +			MT_QUIRK_CONTACT_CNT_ACCURATE, +		.export_all_inputs = true },  	/*  	 * vendor specific classes @@ -223,10 +218,6 @@ static struct mt_class mt_classes[] = {  		.sn_height = 128,  		.maxcontacts = 60,  	}, -	{ .name = MT_CLS_CYPRESS, -		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | -			MT_QUIRK_CYPRESS, -		.maxcontacts = 10 },  	{ .name = MT_CLS_EGALAX,  		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |  			MT_QUIRK_VALID_IS_INRANGE, @@ -360,45 +351,6 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,  	f->usages[f->length++] = usage->hid;  } -static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi, -		struct hid_field *field, struct hid_usage *usage, -		unsigned long **bit, int *max) -{ -	struct mt_device *td = hid_get_drvdata(hdev); - -	td->pen_report_id = field->report->id; - -	return 0; -} - -static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi, -		struct hid_field *field, struct hid_usage *usage, -		unsigned long **bit, int *max) -{ -	return 0; -} - -static int mt_pen_event(struct hid_device *hid, struct hid_field *field, -				struct hid_usage *usage, __s32 value) -{ -	/* let hid-input handle it */ -	return 0; -} - -static void mt_pen_report(struct hid_device *hid, struct hid_report *report) -{ -	struct hid_field *field = report->field[0]; - -	input_sync(field->hidinput->input); -} - -static void mt_pen_input_configured(struct hid_device *hdev, -					struct hid_input *hi) -{ -	/* force BTN_STYLUS to allow tablet matching in udev */ -	__set_bit(BTN_STYLUS, hi->input->keybit); -} -  static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,  		struct hid_field *field, struct hid_usage *usage,  		unsigned long **bit, int *max) @@ -415,8 +367,10 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,  	 * Model touchscreens providing buttons as touchpads.  	 */  	if (field->application == HID_DG_TOUCHPAD || -	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) +	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {  		td->mt_flags |= INPUT_MT_POINTER; +		td->inputmode_value = MT_INPUTMODE_TOUCHPAD; +	}  	if (usage->usage_index)  		prev_usage = &field->usage[usage->usage_index - 1]; @@ -776,28 +730,52 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,  		struct hid_field *field, struct hid_usage *usage,  		unsigned long **bit, int *max)  { -	/* Only map fields from TouchScreen or TouchPad collections. -	* We need to ignore fields that belong to other collections -	* such as Mouse that might have the same GenericDesktop usages. */ -	if (field->application != HID_DG_TOUCHSCREEN && +	struct mt_device *td = hid_get_drvdata(hdev); + +	/* +	 * If mtclass.export_all_inputs is not set, only map fields from +	 * TouchScreen or TouchPad collections. We need to ignore fields +	 * that belong to other collections such as Mouse that might have +	 * the same GenericDesktop usages. +	 */ +	if (!td->mtclass.export_all_inputs && +	    field->application != HID_DG_TOUCHSCREEN &&  	    field->application != HID_DG_PEN &&  	    field->application != HID_DG_TOUCHPAD)  		return -1; +	/* +	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" +	 * for the stylus. +	 */  	if (field->physical == HID_DG_STYLUS) -		return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); +		return 0; -	return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); +	if (field->application == HID_DG_TOUCHSCREEN || +	    field->application == HID_DG_TOUCHPAD) +		return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); + +	/* let hid-core decide for the others */ +	return 0;  }  static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,  		struct hid_field *field, struct hid_usage *usage,  		unsigned long **bit, int *max)  { +	/* +	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" +	 * for the stylus. +	 */  	if (field->physical == HID_DG_STYLUS) -		return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); +		return 0; -	return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); +	if (field->application == HID_DG_TOUCHSCREEN || +	    field->application == HID_DG_TOUCHPAD) +		return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); + +	/* let hid-core decide for the others */ +	return 0;  }  static int mt_event(struct hid_device *hid, struct hid_field *field, @@ -808,25 +786,22 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,  	if (field->report->id == td->mt_report_id)  		return mt_touch_event(hid, field, usage, value); -	if (field->report->id == td->pen_report_id) -		return mt_pen_event(hid, field, usage, value); - -	/* ignore other reports */ -	return 1; +	return 0;  }  static void mt_report(struct hid_device *hid, struct hid_report *report)  {  	struct mt_device *td = hid_get_drvdata(hid); +	struct hid_field *field = report->field[0];  	if (!(hid->claimed & HID_CLAIMED_INPUT))  		return;  	if (report->id == td->mt_report_id) -		mt_touch_report(hid, report); +		return mt_touch_report(hid, report); -	if (report->id == td->pen_report_id) -		mt_pen_report(hid, report); +	if (field && field->hidinput && field->hidinput->input) +		input_sync(field->hidinput->input);  }  static void mt_set_input_mode(struct hid_device *hdev) @@ -841,7 +816,7 @@ static void mt_set_input_mode(struct hid_device *hdev)  	re = &(hdev->report_enum[HID_FEATURE_REPORT]);  	r = re->report_id_hash[td->inputmode];  	if (r) { -		r->field[0]->value[td->inputmode_index] = 0x02; +		r->field[0]->value[td->inputmode_index] = td->inputmode_value;  		hid_hw_request(hdev, r, HID_REQ_SET_REPORT);  	}  } @@ -907,13 +882,49 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)  	struct mt_device *td = hid_get_drvdata(hdev);  	char *name;  	const char *suffix = NULL; +	struct hid_field *field = hi->report->field[0];  	if (hi->report->id == td->mt_report_id)  		mt_touch_input_configured(hdev, hi); +	/* +	 * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" +	 * for the stylus. Check this first, and then rely on the application +	 * field. +	 */  	if (hi->report->field[0]->physical == HID_DG_STYLUS) {  		suffix = "Pen"; -		mt_pen_input_configured(hdev, hi); +		/* force BTN_STYLUS to allow tablet matching in udev */ +		__set_bit(BTN_STYLUS, hi->input->keybit); +	} else { +		switch (field->application) { +		case HID_GD_KEYBOARD: +			suffix = "Keyboard"; +			break; +		case HID_GD_KEYPAD: +			suffix = "Keypad"; +			break; +		case HID_GD_MOUSE: +			suffix = "Mouse"; +			break; +		case HID_DG_STYLUS: +			suffix = "Pen"; +			/* force BTN_STYLUS to allow tablet matching in udev */ +			__set_bit(BTN_STYLUS, hi->input->keybit); +			break; +		case HID_DG_TOUCHSCREEN: +			/* we do not set suffix = "Touchscreen" */ +			break; +		case HID_GD_SYSTEM_CONTROL: +			suffix = "System Control"; +			break; +		case HID_CP_CONSUMER_CONTROL: +			suffix = "Consumer Control"; +			break; +		default: +			suffix = "UNKNOWN"; +			break; +		}  	}  	if (suffix) { @@ -973,9 +984,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)  	td->mtclass = *mtclass;  	td->inputmode = -1;  	td->maxcontact_report_id = -1; +	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;  	td->cc_index = -1;  	td->mt_report_id = -1; -	td->pen_report_id = -1;  	hid_set_drvdata(hdev, td);  	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields), @@ -1034,6 +1045,12 @@ static void mt_remove(struct hid_device *hdev)  	hid_hw_stop(hdev);  } +/* + * This list contains only: + * - VID/PID of products not working with the default multitouch handling + * - 2 generic rules. + * So there is no point in adding here any device with MT_CLS_DEFAULT. + */  static const struct hid_device_id mt_devices[] = {  	/* 3M panels */ @@ -1047,33 +1064,25 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_3M,  			USB_DEVICE_ID_3M3266) }, -	/* ActionStar panels */ -	{ .driver_data = MT_CLS_NSMU, -		MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR, -			USB_DEVICE_ID_ACTIONSTAR_1011) }, +	/* Anton devices */ +	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS, +		MT_USB_DEVICE(USB_VENDOR_ID_ANTON, +			USB_DEVICE_ID_ANTON_TOUCH_PAD) },  	/* Atmel panels */  	{ .driver_data = MT_CLS_SERIAL,  		MT_USB_DEVICE(USB_VENDOR_ID_ATMEL, -			USB_DEVICE_ID_ATMEL_MULTITOUCH) }, -	{ .driver_data = MT_CLS_SERIAL, -		MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,  			USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },  	/* Baanto multitouch devices */  	{ .driver_data = MT_CLS_NSMU,  		MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,  			USB_DEVICE_ID_BAANTO_MT_190W2) }, +  	/* Cando panels */  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,  		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,  			USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, -	{ .driver_data = MT_CLS_DUAL_CONTACT_NUMBER, -		MT_USB_DEVICE(USB_VENDOR_ID_CANDO, -			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, -	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, -		MT_USB_DEVICE(USB_VENDOR_ID_CANDO, -			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,  		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,  			USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, @@ -1088,16 +1097,6 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,  			USB_DEVICE_ID_CVTOUCH_SCREEN) }, -	/* Cypress panel */ -	{ .driver_data = MT_CLS_CYPRESS, -		HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, -			USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, - -	/* Data Modul easyMaxTouch */ -	{ .driver_data = MT_CLS_DEFAULT, -		MT_USB_DEVICE(USB_VENDOR_ID_DATA_MODUL, -			USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH) }, -  	/* eGalax devices (resistive) */  	{ .driver_data = MT_CLS_EGALAX,  		MT_USB_DEVICE(USB_VENDOR_ID_DWAV, @@ -1156,11 +1155,6 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,  			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, -	/* Elo TouchSystems IntelliTouch Plus panel */ -	{ .driver_data = MT_CLS_DUAL_CONTACT_ID, -		MT_USB_DEVICE(USB_VENDOR_ID_ELO, -			USB_DEVICE_ID_ELO_TS2515) }, -  	/* Flatfrog Panels */  	{ .driver_data = MT_CLS_FLATFROG,  		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG, @@ -1209,37 +1203,11 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,  			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, -	/* Ideacom panel */ -	{ .driver_data = MT_CLS_SERIAL, -		MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM, -			USB_DEVICE_ID_IDEACOM_IDC6650) }, -	{ .driver_data = MT_CLS_SERIAL, -		MT_USB_DEVICE(USB_VENDOR_ID_IDEACOM, -			USB_DEVICE_ID_IDEACOM_IDC6651) }, -  	/* Ilitek dual touch panel */  	{  .driver_data = MT_CLS_NSMU,  		MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,  			USB_DEVICE_ID_ILITEK_MULTITOUCH) }, -	/* IRTOUCH panels */ -	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, -		MT_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, -			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, - -	/* LG Display panels */ -	{ .driver_data = MT_CLS_DEFAULT, -		MT_USB_DEVICE(USB_VENDOR_ID_LG, -			USB_DEVICE_ID_LG_MULTITOUCH) }, - -	/* Lumio panels */ -	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, -		MT_USB_DEVICE(USB_VENDOR_ID_LUMIO, -			USB_DEVICE_ID_CRYSTALTOUCH) }, -	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, -		MT_USB_DEVICE(USB_VENDOR_ID_LUMIO, -			USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, -  	/* MosArt panels */  	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,  		MT_USB_DEVICE(USB_VENDOR_ID_ASUS, @@ -1251,11 +1219,6 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,  			USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, -	/* Nexio panels */ -	{ .driver_data = MT_CLS_DEFAULT, -		MT_USB_DEVICE(USB_VENDOR_ID_NEXIO, -			USB_DEVICE_ID_NEXIO_MULTITOUCH_420)}, -  	/* Panasonic panels */  	{ .driver_data = MT_CLS_PANASONIC,  		MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, @@ -1269,11 +1232,6 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,  			USB_DEVICE_ID_NOVATEK_PCT) }, -	/* PenMount panels */ -	{ .driver_data = MT_CLS_CONFIDENCE, -		MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, -			USB_DEVICE_ID_PENMOUNT_PCI) }, -  	/* PixArt optical touch screen */  	{ .driver_data = MT_CLS_INRANGE_CONTACTNUMBER,  		MT_USB_DEVICE(USB_VENDOR_ID_PIXART, @@ -1287,44 +1245,18 @@ static const struct hid_device_id mt_devices[] = {  	/* PixCir-based panels */  	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID, -		MT_USB_DEVICE(USB_VENDOR_ID_HANVON, -			USB_DEVICE_ID_HANVON_MULTITOUCH) }, -	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,  		MT_USB_DEVICE(USB_VENDOR_ID_CANDO,  			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },  	/* Quanta-based panels */  	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID,  		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, -			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, -	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, -		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA,  			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001) }, -	{ .driver_data = MT_CLS_CONFIDENCE_CONTACT_ID, -		MT_USB_DEVICE(USB_VENDOR_ID_QUANTA, -			USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008) }, - -	/* SiS panels */ -	{ .driver_data = MT_CLS_DEFAULT, -		HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, -		USB_DEVICE_ID_SIS9200_TOUCH) }, -	{ .driver_data = MT_CLS_DEFAULT, -		HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, -		USB_DEVICE_ID_SIS817_TOUCH) }, -	{ .driver_data = MT_CLS_DEFAULT, -		HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, -		USB_DEVICE_ID_SIS1030_TOUCH) },  	/* Stantum panels */  	{ .driver_data = MT_CLS_CONFIDENCE, -		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM, -			USB_DEVICE_ID_MTP)}, -	{ .driver_data = MT_CLS_CONFIDENCE,  		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,  			USB_DEVICE_ID_MTP_STM)}, -	{ .driver_data = MT_CLS_DEFAULT, -		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, -			USB_DEVICE_ID_MTP_SITRONIX)},  	/* TopSeed panels */  	{ .driver_data = MT_CLS_TOPSEED, @@ -1383,11 +1315,6 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,  			USB_DEVICE_ID_XIROKU_CSR2) }, -	/* Zytronic panels */ -	{ .driver_data = MT_CLS_SERIAL, -		MT_USB_DEVICE(USB_VENDOR_ID_ZYTRONIC, -			USB_DEVICE_ID_ZYTRONIC_ZXY100) }, -  	/* Generic MT device */  	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index b3e82585309e..4d348c069981 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -863,7 +863,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size)  		battery_capacity = sixaxis_battery_capacity[index];  		battery_charging = 0;  	} -	cable_state = !((rd[31] >> 4) & 0x01); +	cable_state = !(rd[31] & 0x04);  	spin_lock_irqsave(&sc->lock, flags);  	sc->cable_state = cable_state; @@ -1632,11 +1632,21 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)  		sc->worker_initialized = 1;  		INIT_WORK(&sc->state_worker, sixaxis_state_worker);  	} else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { +		/* +		 * The Sixaxis wants output reports sent on the ctrl endpoint +		 * when connected via Bluetooth. +		 */ +		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;  		ret = sixaxis_set_operational_bt(hdev);  		sc->worker_initialized = 1;  		INIT_WORK(&sc->state_worker, sixaxis_state_worker);  	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {  		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) { +			/* +			 * The DualShock 4 wants output reports sent on the ctrl +			 * endpoint when connected via Bluetooth. +			 */ +			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;  			ret = dualshock4_set_operational_bt(hdev);  			if (ret < 0) {  				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n"); diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 7ed79be2686a..0d078c32db4f 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -428,6 +428,67 @@ err_free:  	return ret;  } +static int uhid_dev_create2(struct uhid_device *uhid, +			    const struct uhid_event *ev) +{ +	struct hid_device *hid; +	int ret; + +	if (uhid->running) +		return -EALREADY; + +	uhid->rd_size = ev->u.create2.rd_size; +	if (uhid->rd_size <= 0 || uhid->rd_size > HID_MAX_DESCRIPTOR_SIZE) +		return -EINVAL; + +	uhid->rd_data = kmalloc(uhid->rd_size, GFP_KERNEL); +	if (!uhid->rd_data) +		return -ENOMEM; + +	memcpy(uhid->rd_data, ev->u.create2.rd_data, uhid->rd_size); + +	hid = hid_allocate_device(); +	if (IS_ERR(hid)) { +		ret = PTR_ERR(hid); +		goto err_free; +	} + +	strncpy(hid->name, ev->u.create2.name, 127); +	hid->name[127] = 0; +	strncpy(hid->phys, ev->u.create2.phys, 63); +	hid->phys[63] = 0; +	strncpy(hid->uniq, ev->u.create2.uniq, 63); +	hid->uniq[63] = 0; + +	hid->ll_driver = &uhid_hid_driver; +	hid->bus = ev->u.create2.bus; +	hid->vendor = ev->u.create2.vendor; +	hid->product = ev->u.create2.product; +	hid->version = ev->u.create2.version; +	hid->country = ev->u.create2.country; +	hid->driver_data = uhid; +	hid->dev.parent = uhid_misc.this_device; + +	uhid->hid = hid; +	uhid->running = true; + +	ret = hid_add_device(hid); +	if (ret) { +		hid_err(hid, "Cannot register HID device\n"); +		goto err_hid; +	} + +	return 0; + +err_hid: +	hid_destroy_device(hid); +	uhid->hid = NULL; +	uhid->running = false; +err_free: +	kfree(uhid->rd_data); +	return ret; +} +  static int uhid_dev_destroy(struct uhid_device *uhid)  {  	if (!uhid->running) @@ -456,6 +517,17 @@ static int uhid_dev_input(struct uhid_device *uhid, struct uhid_event *ev)  	return 0;  } +static int uhid_dev_input2(struct uhid_device *uhid, struct uhid_event *ev) +{ +	if (!uhid->running) +		return -EINVAL; + +	hid_input_report(uhid->hid, HID_INPUT_REPORT, ev->u.input2.data, +			 min_t(size_t, ev->u.input2.size, UHID_DATA_MAX), 0); + +	return 0; +} +  static int uhid_dev_feature_answer(struct uhid_device *uhid,  				   struct uhid_event *ev)  { @@ -592,12 +664,18 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,  	case UHID_CREATE:  		ret = uhid_dev_create(uhid, &uhid->input_buf);  		break; +	case UHID_CREATE2: +		ret = uhid_dev_create2(uhid, &uhid->input_buf); +		break;  	case UHID_DESTROY:  		ret = uhid_dev_destroy(uhid);  		break;  	case UHID_INPUT:  		ret = uhid_dev_input(uhid, &uhid->input_buf);  		break; +	case UHID_INPUT2: +		ret = uhid_dev_input2(uhid, &uhid->input_buf); +		break;  	case UHID_FEATURE_ANSWER:  		ret = uhid_dev_feature_answer(uhid, &uhid->input_buf);  		break; diff --git a/include/linux/hid.h b/include/linux/hid.h index 01a90b8d53bb..720e3a10608c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -201,6 +201,7 @@ struct hid_item {  #define HID_GD_VBRZ		0x00010045  #define HID_GD_VNO		0x00010046  #define HID_GD_FEATURE		0x00010047 +#define HID_GD_SYSTEM_CONTROL	0x00010080  #define HID_GD_UP		0x00010090  #define HID_GD_DOWN		0x00010091  #define HID_GD_RIGHT		0x00010092 @@ -208,6 +209,8 @@ struct hid_item {  #define HID_DC_BATTERYSTRENGTH	0x00060020 +#define HID_CP_CONSUMER_CONTROL	0x000c0001 +  #define HID_DG_DIGITIZER	0x000d0001  #define HID_DG_PEN		0x000d0002  #define HID_DG_LIGHTPEN		0x000d0003 diff --git a/include/uapi/linux/uhid.h b/include/uapi/linux/uhid.h index 414b74be4da1..1e3b09c191cd 100644 --- a/include/uapi/linux/uhid.h +++ b/include/uapi/linux/uhid.h @@ -21,6 +21,7 @@  #include <linux/input.h>  #include <linux/types.h> +#include <linux/hid.h>  enum uhid_event_type {  	UHID_CREATE, @@ -34,6 +35,8 @@ enum uhid_event_type {  	UHID_INPUT,  	UHID_FEATURE,  	UHID_FEATURE_ANSWER, +	UHID_CREATE2, +	UHID_INPUT2,  };  struct uhid_create_req { @@ -50,6 +53,19 @@ struct uhid_create_req {  	__u32 country;  } __attribute__((__packed__)); +struct uhid_create2_req { +	__u8 name[128]; +	__u8 phys[64]; +	__u8 uniq[64]; +	__u16 rd_size; +	__u16 bus; +	__u32 vendor; +	__u32 product; +	__u32 version; +	__u32 country; +	__u8 rd_data[HID_MAX_DESCRIPTOR_SIZE]; +} __attribute__((__packed__)); +  #define UHID_DATA_MAX 4096  enum uhid_report_type { @@ -63,6 +79,11 @@ struct uhid_input_req {  	__u16 size;  } __attribute__((__packed__)); +struct uhid_input2_req { +	__u16 size; +	__u8 data[UHID_DATA_MAX]; +} __attribute__((__packed__)); +  struct uhid_output_req {  	__u8 data[UHID_DATA_MAX];  	__u16 size; @@ -100,6 +121,8 @@ struct uhid_event {  		struct uhid_output_ev_req output_ev;  		struct uhid_feature_req feature;  		struct uhid_feature_answer_req feature_answer; +		struct uhid_create2_req create2; +		struct uhid_input2_req input2;  	} u;  } __attribute__((__packed__)); | 
