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>
This commit is contained in:
Chris Bagwell 2012-03-25 23:26:11 -07:00 committed by Dmitry Torokhov
parent 3aac0ef10b
commit d3825d51c3
3 changed files with 62 additions and 6 deletions

View file

@ -422,6 +422,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
report_id, rep_data, 4, 1); report_id, rep_data, 4, 1);
} while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES); } while ((error < 0 || rep_data[1] != 4) && limit++ < WAC_MSG_RETRIES);
} else if (features->type != TABLETPC && } else if (features->type != TABLETPC &&
features->type != WIRELESS &&
features->device_type == BTN_TOOL_PEN) { features->device_type == BTN_TOOL_PEN) {
do { do {
rep_data[0] = 2; rep_data[0] = 2;
@ -454,6 +455,21 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
features->pressure_fuzz = 0; features->pressure_fuzz = 0;
features->distance_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 */ /* only Tablet PCs and Bamboo P&T need to retrieve the info */
if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) && if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
(features->type != BAMBOO_PT)) (features->type != BAMBOO_PT))
@ -928,14 +944,22 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
if (error) if (error)
goto fail4; goto fail4;
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
error = wacom_register_input(wacom); error = wacom_register_input(wacom);
if (error) if (error)
goto fail5; goto fail5;
}
/* Note that if query fails it is not a hard failure */ /* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(intf, features); wacom_query_tablet_data(intf, features);
usb_set_intfdata(intf, wacom); usb_set_intfdata(intf, wacom);
if (features->quirks & WACOM_QUIRK_MONITOR) {
if (usb_submit_urb(wacom->irq, GFP_KERNEL))
goto fail5;
}
return 0; return 0;
fail5: wacom_destroy_leds(wacom); fail5: wacom_destroy_leds(wacom);
@ -953,6 +977,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
usb_kill_urb(wacom->irq); usb_kill_urb(wacom->irq);
if (wacom->wacom_wac.input)
input_unregister_device(wacom->wacom_wac.input); input_unregister_device(wacom->wacom_wac.input);
wacom_destroy_leds(wacom); wacom_destroy_leds(wacom);
usb_free_urb(wacom->irq); usb_free_urb(wacom->irq);
@ -985,7 +1010,8 @@ static int wacom_resume(struct usb_interface *intf)
wacom_query_tablet_data(intf, features); wacom_query_tablet_data(intf, features);
wacom_led_control(wacom); 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; rv = -EIO;
mutex_unlock(&wacom->lock); mutex_unlock(&wacom->lock);

View file

@ -1044,6 +1044,14 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
return 0; 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) void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
{ {
bool sync; 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); sync = wacom_bpt_irq(wacom_wac, len);
break; break;
case WIRELESS:
sync = wacom_wireless_irq(wacom_wac, len);
break;
default: default:
sync = false; sync = false;
break; break;
@ -1155,7 +1167,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
/* these device have multiple inputs */ /* these device have multiple inputs */
if (features->type == TABLETPC || features->type == TABLETPC2FG || if (features->type == TABLETPC || features->type == TABLETPC2FG ||
features->type == BAMBOO_PT) features->type == BAMBOO_PT || features->type == WIRELESS)
features->quirks |= WACOM_QUIRK_MULTI_INPUT; features->quirks |= WACOM_QUIRK_MULTI_INPUT;
/* quirk for bamboo touch with 2 low res touches */ /* 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->y_fuzz <<= 5;
features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES; 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, 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 = static const struct wacom_features wacom_features_0x47 =
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023,
31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 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 = static const struct wacom_features wacom_features_0xD0 =
{ "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023,
31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 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_DEVICE_DETAILED(0xCE, USB_CLASS_HID,
USB_INTERFACE_SUBCLASS_BOOT, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_MOUSE) }, USB_INTERFACE_PROTOCOL_MOUSE) },
{ USB_DEVICE_WACOM(0x84) },
{ USB_DEVICE_WACOM(0xD0) }, { USB_DEVICE_WACOM(0xD0) },
{ USB_DEVICE_WACOM(0xD1) }, { USB_DEVICE_WACOM(0xD1) },
{ USB_DEVICE_WACOM(0xD2) }, { USB_DEVICE_WACOM(0xD2) },

View file

@ -24,6 +24,7 @@
#define WACOM_PKGLEN_BBTOUCH 20 #define WACOM_PKGLEN_BBTOUCH 20
#define WACOM_PKGLEN_BBTOUCH3 64 #define WACOM_PKGLEN_BBTOUCH3 64
#define WACOM_PKGLEN_BBPEN 10 #define WACOM_PKGLEN_BBPEN 10
#define WACOM_PKGLEN_WIRELESS 32
/* device IDs */ /* device IDs */
#define STYLUS_DEVICE_ID 0x02 #define STYLUS_DEVICE_ID 0x02
@ -45,6 +46,8 @@
/* device quirks */ /* device quirks */
#define WACOM_QUIRK_MULTI_INPUT 0x0001 #define WACOM_QUIRK_MULTI_INPUT 0x0001
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002 #define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
#define WACOM_QUIRK_NO_INPUT 0x0004
#define WACOM_QUIRK_MONITOR 0x0008
enum { enum {
PENPARTNER = 0, PENPARTNER = 0,
@ -54,6 +57,7 @@ enum {
PL, PL,
DTU, DTU,
BAMBOO_PT, BAMBOO_PT,
WIRELESS,
INTUOS, INTUOS,
INTUOS3S, INTUOS3S,
INTUOS3, INTUOS3,