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 f6da2f8a9c18a08f5de28aa04d97805a08251fd3..d8cc9ce165ff2b3829a498aca8a4b44c3ec2db53 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 07a1f218b5c1b6943512e0e7ea1148f61ed1fac2..6264e6a8d513744209b4d9caf16bcf01b1c60d35 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 4f0ba21b01962c4b2556535468c96f7355e17d1c..2c04b6248a568e1847d81c801ac7070dbaf66774 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,