HID: add support for 3M multitouch 22" display

Now support the 22" display and its updated firmware, including touch
width and height.

The number of touches can now go up to 60, and our single touch emulation
will fail when there are more than 6-7 touches; further work is needed on
this.

Signed-off-by: Stephane Chatty <chatty@enac.fr>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c
index 2370aef..883fd1a 100644
--- a/drivers/hid/hid-3m-pct.c
+++ b/drivers/hid/hid-3m-pct.c
@@ -1,7 +1,7 @@
 /*
  *  HID driver for 3M PCT multitouch panels
  *
- *  Copyright (c) 2009 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr>
  *
  */
 
@@ -24,7 +24,7 @@
 #include "hid-ids.h"
 
 struct mmm_finger {
-	__s32 x, y;
+	__s32 x, y, w, h;
 	__u8 rank;
 	bool touch, valid;
 };
@@ -81,7 +81,18 @@
 			/* touchscreen emulation */
 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
 			return 1;
+		case HID_DG_WIDTH:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MAJOR);
+			return 1;
+		case HID_DG_HEIGHT:
+			hid_map_usage(hi, usage, bit, max,
+					EV_ABS, ABS_MT_TOUCH_MINOR);
+			input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
+					1, 1, 0, 0);
+			return 1;
 		case HID_DG_CONTACTID:
+			field->logical_maximum = 59;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TRACKING_ID);
 			return 1;
@@ -127,9 +138,15 @@
 			/* this finger is just placeholder data, ignore */
 		} else if (f->touch) {
 			/* this finger is on the screen */
+			int wide = (f->w > f->h);
 			input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i);
 			input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
 			input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
+			input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR,
+						wide ? f->w : f->h);
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
+						wide ? f->h : f->w);
 			input_mt_sync(input);
 			/*
 			 * touchscreen emulation: maintain the age rank
@@ -196,6 +213,14 @@
 		case HID_DG_CONFIDENCE:
 			md->valid = value;
 			break;
+		case HID_DG_WIDTH:
+			if (md->valid)
+				md->f[md->curid].w = value;
+			break;
+		case HID_DG_HEIGHT:
+			if (md->valid)
+				md->f[md->curid].h = value;
+			break;
 		case HID_DG_CONTACTID:
 			if (md->valid) {
 				md->curid = value;
@@ -254,6 +279,7 @@
 
 static const struct hid_device_id mmm_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mmm_devices);
@@ -286,5 +312,4 @@
 
 module_init(mmm_init);
 module_exit(mmm_exit);
-MODULE_LICENSE("GPL");
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 7396f47..9f92f62 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1251,6 +1251,7 @@
 /* a list of devices for which there is a specialized driver on HID bus */
 static const struct hid_device_id hid_blacklist[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 72c05f9..e1b4ce4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -20,6 +20,7 @@
 
 #define USB_VENDOR_ID_3M		0x0596
 #define USB_DEVICE_ID_3M1968		0x0500
+#define USB_DEVICE_ID_3M2256		0x0502
 
 #define USB_VENDOR_ID_A4TECH		0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006