Input: wacom - wireless monitor framework
authorChris Bagwell <chris@cnpbagwell.com>
Mon, 26 Mar 2012 06:26:11 +0000 (23:26 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 26 Mar 2012 06:31:32 +0000 (23:31 -0700)
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>
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h

index f6da2f8..d8cc9ce 100644 (file)
@@ -422,6 +422,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                                                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 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
        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 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        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 @@ static void wacom_disconnect(struct usb_interface *intf)
        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 @@ static int wacom_resume(struct usb_interface *intf)
        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);
index 07a1f21..6264e6a 100644 (file)
@@ -1044,6 +1044,14 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
        return 0;
 }
 
+static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
+{
+       if (len != WACOM_PKGLEN_WIRELESS)
+               return 0;
+
+       return 0;
+}
+
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 {
        bool sync;
@@ -1094,6 +1102,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_bpt_irq(wacom_wac, len);
                break;
 
+       case WIRELESS:
+               sync = wacom_wireless_irq(wacom_wac, len);
+               break;
+
        default:
                sync = false;
                break;
@@ -1155,7 +1167,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* these device have multiple inputs */
        if (features->type == TABLETPC || features->type == TABLETPC2FG ||
-           features->type == BAMBOO_PT)
+           features->type == BAMBOO_PT || features->type == WIRELESS)
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
        /* quirk for bamboo touch with 2 low res touches */
@@ -1167,6 +1179,16 @@ void wacom_setup_device_quirks(struct wacom_features *features)
                features->y_fuzz <<= 5;
                features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
        }
+
+       if (features->type == WIRELESS) {
+
+               /* monitor never has input and pen/touch have delayed create */
+               features->quirks |= WACOM_QUIRK_NO_INPUT;
+
+               /* must be monitor interface if no device_type set */
+               if (!features->device_type)
+                       features->quirks |= WACOM_QUIRK_MONITOR;
+       }
 }
 
 static unsigned int wacom_calculate_touch_res(unsigned int logical_max,
@@ -1640,6 +1662,9 @@ static const struct wacom_features wacom_features_0xEC =
 static const struct wacom_features wacom_features_0x47 =
        { "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
          31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x84 =
+       { "Wacom Wireless Receiver", WACOM_PKGLEN_WIRELESS, 0, 0, 0,
+         0, WIRELESS, 0, 0 };
 static const struct wacom_features wacom_features_0xD0 =
        { "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
          31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -1766,6 +1791,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
                              USB_INTERFACE_SUBCLASS_BOOT,
                              USB_INTERFACE_PROTOCOL_MOUSE) },
+       { USB_DEVICE_WACOM(0x84) },
        { USB_DEVICE_WACOM(0xD0) },
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
index 4f0ba21..2c04b62 100644 (file)
@@ -24,6 +24,7 @@
 #define WACOM_PKGLEN_BBTOUCH   20
 #define WACOM_PKGLEN_BBTOUCH3  64
 #define WACOM_PKGLEN_BBPEN     10
+#define WACOM_PKGLEN_WIRELESS  32
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
@@ -45,6 +46,8 @@
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT                0x0001
 #define WACOM_QUIRK_BBTOUCH_LOWRES     0x0002
+#define WACOM_QUIRK_NO_INPUT           0x0004
+#define WACOM_QUIRK_MONITOR            0x0008
 
 enum {
        PENPARTNER = 0,
@@ -54,6 +57,7 @@ enum {
        PL,
        DTU,
        BAMBOO_PT,
+       WIRELESS,
        INTUOS,
        INTUOS3S,
        INTUOS3,