Input: wacom - wireless monitor framework

The 3rd gen Bamboo Pen & Touch and Intuos5 tablets support an
optional wireless module. When its receiver is plugged into USB,
it presents 3 interfaces: 0) Monitor 1) Pen and 2) Touch.

The exact capabilities of the Pen and Touch interfaces can
not be determined until a tablet connection is established
and reported over the Monitor interface.

This patch detects this wireless receiver and enables interrupt
packets to be processed for the Monitor interface. Processing
the data in packets will be left to another patch.

Since it doesn't make sense to create an input device for the
Monitor interface, it is not created. Creation of Pen and Touch
input device is also delayed until monitor packets can be processed.

Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
Acked-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index f6da2f8..d8cc9ce 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -422,6 +422,7 @@
 						report_id, rep_data, 4, 1);
 		} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
 	} else if (features->type != TABLETPC &&
+		   features->type != WIRELESS &&
 		   features->device_type == BTN_TOOL_PEN) {
 		do {
 			rep_data[0] = 2;
@@ -454,6 +455,21 @@
 	features->pressure_fuzz = 0;
 	features->distance_fuzz = 0;
 
+	/*
+	 * The wireless device HID is basic and layout conflicts with
+	 * other tablets (monitor and touch interface can look like pen).
+	 * Skip the query for this type and modify defaults based on
+	 * interface number.
+	 */
+	if (features->type == WIRELESS) {
+		if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
+			features->device_type = 0;
+		} else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) {
+			features->device_type = BTN_TOOL_DOUBLETAP;
+			features->pktlen = WACOM_PKGLEN_BBTOUCH3;
+		}
+	}
+
 	/* only Tablet PCs and Bamboo P&T need to retrieve the info */
 	if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
 	    (features->type != BAMBOO_PT))
@@ -928,14 +944,22 @@
 	if (error)
 		goto fail4;
 
-	error = wacom_register_input(wacom);
-	if (error)
-		goto fail5;
+	if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
+		error = wacom_register_input(wacom);
+		if (error)
+			goto fail5;
+	}
 
 	/* Note that if query fails it is not a hard failure */
 	wacom_query_tablet_data(intf, features);
 
 	usb_set_intfdata(intf, wacom);
+
+	if (features->quirks & WACOM_QUIRK_MONITOR) {
+		if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+			goto fail5;
+	}
+
 	return 0;
 
  fail5: wacom_destroy_leds(wacom);
@@ -953,7 +977,8 @@
 	usb_set_intfdata(intf, NULL);
 
 	usb_kill_urb(wacom->irq);
-	input_unregister_device(wacom->wacom_wac.input);
+	if (wacom->wacom_wac.input)
+		input_unregister_device(wacom->wacom_wac.input);
 	wacom_destroy_leds(wacom);
 	usb_free_urb(wacom->irq);
 	usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
@@ -985,7 +1010,8 @@
 	wacom_query_tablet_data(intf, features);
 	wacom_led_control(wacom);
 
-	if (wacom->open && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
+	if ((wacom->open || features->quirks & WACOM_QUIRK_MONITOR)
+	     && usb_submit_urb(wacom->irq, GFP_NOIO) < 0)
 		rv = -EIO;
 
 	mutex_unlock(&wacom->lock);