linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/4] Wacom Wireless Module Support
@ 2012-03-14  0:51 chris
  2012-03-14  0:51 ` [PATCH v4 1/4] Input: wacom - isolate input registration chris
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: chris @ 2012-03-14  0:51 UTC (permalink / raw)
  To: linux-input, dmitry.torokhov, killertofu; +Cc: Chris Bagwell

From: Chris Bagwell <chris@cnpbagwell.com>

The 3rd gen Bamboo Pen & Touch and Intuos5 tablets support an
optional wireless module.  This patch set adds support for it.

New in v4 -
 * Dropped patches related to 0xE5 support.  They will be sent
   on their own again.
 * Dropped a Kconfig patch that is already on for-linus branch.
 * Removed "Bamboo" references to wireless patch since
   wireless module works with at least 2 product families now.
 * Delayed enabling monitor interrupt to last possible moment in probe
   to fix crash reported by Jason Gerecke.

New in v3 - Changed a pointer reset from 0 to NULL.
Merged Ping's 0xE5 patches into this patch set to resolve
merge issues.

New in v2 - Updates only to 0xE5 patch set based on review comments.
No wireless patch changes.

Chris Bagwell (4):
  Input: wacom - isolate input registration
  Input: wacom - wireless monitor framework
  Input: wacom - create inputs when wireless connect
  Input: wacom - wireless battery status

 drivers/input/tablet/Kconfig     |    1 +
 drivers/input/tablet/wacom.h     |    9 ++
 drivers/input/tablet/wacom_sys.c |  230 ++++++++++++++++++++++++++++++++-----
 drivers/input/tablet/wacom_wac.c |   49 ++++++++-
 drivers/input/tablet/wacom_wac.h |    6 +
 5 files changed, 263 insertions(+), 32 deletions(-)

-- 
1.7.7.6


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v4 1/4] Input: wacom - isolate input registration
  2012-03-14  0:51 [PATCH v4 0/4] Wacom Wireless Module Support chris
@ 2012-03-14  0:51 ` chris
  2012-03-14  0:52 ` [PATCH v4 2/4] Input: wacom - wireless monitor framework chris
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: chris @ 2012-03-14  0:51 UTC (permalink / raw)
  To: linux-input, dmitry.torokhov, killertofu; +Cc: Chris Bagwell

From: Chris Bagwell <chris@cnpbagwell.com>

Although this better co-locates input registration logic,
the main goal is to make it easier to optionally create
input devices or delay creation to later time periods.

Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
---
 drivers/input/tablet/wacom_sys.c |   53 +++++++++++++++++++++++--------------
 1 files changed, 33 insertions(+), 20 deletions(-)

diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 39205ed..f6da2f8 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -822,6 +822,37 @@ static void wacom_destroy_leds(struct wacom *wacom)
 	}
 }
 
+static int wacom_register_input(struct wacom *wacom)
+{
+	struct input_dev *input_dev;
+	struct usb_interface *intf = wacom->intf;
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+	int error;
+
+	input_dev = input_allocate_device();
+	if (!input_dev)
+		return -ENOMEM;
+
+	input_dev->name = wacom_wac->name;
+	input_dev->dev.parent = &intf->dev;
+	input_dev->open = wacom_open;
+	input_dev->close = wacom_close;
+	usb_to_input_id(dev, &input_dev->id);
+	input_set_drvdata(input_dev, wacom);
+
+	wacom_wac->input = input_dev;
+	wacom_setup_input_capabilities(input_dev, wacom_wac);
+
+	error = input_register_device(input_dev);
+	if (error) {
+		input_free_device(input_dev);
+		wacom_wac->input = NULL;
+	}
+
+	return error;
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -829,18 +860,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	struct wacom *wacom;
 	struct wacom_wac *wacom_wac;
 	struct wacom_features *features;
-	struct input_dev *input_dev;
 	int error;
 
 	if (!id->driver_info)
 		return -EINVAL;
 
 	wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!wacom || !input_dev) {
-		error = -ENOMEM;
-		goto fail1;
-	}
 
 	wacom_wac = &wacom->wacom_wac;
 	wacom_wac->features = *((struct wacom_features *)id->driver_info);
@@ -869,8 +894,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
 	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
-	wacom_wac->input = input_dev;
-
 	endpoint = &intf->cur_altsetting->endpoint[0].desc;
 
 	/* Retrieve the physical and logical size for OEM devices */
@@ -894,15 +917,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 			goto fail3;
 	}
 
-	input_dev->name = wacom_wac->name;
-	input_dev->dev.parent = &intf->dev;
-	input_dev->open = wacom_open;
-	input_dev->close = wacom_close;
-	usb_to_input_id(dev, &input_dev->id);
-	input_set_drvdata(input_dev, wacom);
-
-	wacom_setup_input_capabilities(input_dev, wacom_wac);
-
 	usb_fill_int_urb(wacom->irq, dev,
 			 usb_rcvintpipe(dev, endpoint->bEndpointAddress),
 			 wacom_wac->data, features->pktlen,
@@ -914,7 +928,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	if (error)
 		goto fail4;
 
-	error = input_register_device(input_dev);
+	error = wacom_register_input(wacom);
 	if (error)
 		goto fail5;
 
@@ -928,8 +942,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
  fail4:	wacom_remove_shared_data(wacom_wac);
  fail3:	usb_free_urb(wacom->irq);
  fail2:	usb_free_coherent(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
- fail1:	input_free_device(input_dev);
-	kfree(wacom);
+ fail1:	kfree(wacom);
 	return error;
 }
 
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v4 2/4] Input: wacom - wireless monitor framework
  2012-03-14  0:51 [PATCH v4 0/4] Wacom Wireless Module Support chris
  2012-03-14  0:51 ` [PATCH v4 1/4] Input: wacom - isolate input registration chris
@ 2012-03-14  0:52 ` chris
  2012-03-14  0:52 ` [PATCH v4 3/4] Input: wacom - create inputs when wireless connect chris
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: chris @ 2012-03-14  0:52 UTC (permalink / raw)
  To: linux-input, dmitry.torokhov, killertofu; +Cc: Chris Bagwell

From: Chris Bagwell <chris@cnpbagwell.com>

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>
---
 drivers/input/tablet/wacom_sys.c |   36 +++++++++++++++++++++++++++++++-----
 drivers/input/tablet/wacom_wac.c |   28 +++++++++++++++++++++++++++-
 drivers/input/tablet/wacom_wac.h |    4 ++++
 3 files changed, 62 insertions(+), 6 deletions(-)

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 @@ 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);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 07a1f21..6264e6a 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -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) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 4f0ba21..2c04b62 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -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,
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v4 3/4] Input: wacom - create inputs when wireless connect
  2012-03-14  0:51 [PATCH v4 0/4] Wacom Wireless Module Support chris
  2012-03-14  0:51 ` [PATCH v4 1/4] Input: wacom - isolate input registration chris
  2012-03-14  0:52 ` [PATCH v4 2/4] Input: wacom - wireless monitor framework chris
@ 2012-03-14  0:52 ` chris
  2012-03-14  0:52 ` [PATCH v4 4/4] Input: wacom - wireless battery status chris
  2012-03-14 18:25 ` [PATCH v4 0/4] Wacom Wireless Module Support Jason Gerecke
  4 siblings, 0 replies; 7+ messages in thread
From: chris @ 2012-03-14  0:52 UTC (permalink / raw)
  To: linux-input, dmitry.torokhov, killertofu; +Cc: Chris Bagwell

From: Chris Bagwell <chris@cnpbagwell.com>

When a tablet connect or disconnect is detected, schedule
work queue to register or unregister related input devices.

When a wireless tablet connects, it reports same USB PID
used if tablet is connected with USB cable. Use this to
update features values, set input capabilities, and then
register device.  From there, the Pen and Touch interfaces
will reuse the existing tablet's IRQ routines.

Its possible that 1 receiver is shared with 2 tablets with
different PID (small and medium Bamboo for example) so the
input is unregister at disconnect to better support this case.

Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
---
 drivers/input/tablet/wacom.h     |    7 +++
 drivers/input/tablet/wacom_sys.c |   91 ++++++++++++++++++++++++++++++++++----
 drivers/input/tablet/wacom_wac.c |   20 ++++++++-
 drivers/input/tablet/wacom_wac.h |    1 +
 4 files changed, 109 insertions(+), 10 deletions(-)

diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 0783864..febbfd9 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -112,6 +112,7 @@ struct wacom {
 	struct urb *irq;
 	struct wacom_wac wacom_wac;
 	struct mutex lock;
+	struct work_struct work;
 	bool open;
 	char phys[32];
 	struct wacom_led {
@@ -122,6 +123,12 @@ struct wacom {
 	} led;
 };
 
+static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
+{
+	struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+	schedule_work(&wacom->work);
+}
+
 extern const struct usb_device_id wacom_ids[];
 
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index d8cc9ce..2fc7705 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -167,6 +167,19 @@ static void wacom_close(struct input_dev *dev)
 		usb_autopm_put_interface(wacom->intf);
 }
 
+/*
+ * Static values for max X/Y and resolution of Pen interface is stored in
+ * features. This mean physical size of active area can be computed.
+ * This is useful to do when Pen and Touch have same active area of tablet.
+ * This means for Touch device, we only need to find max X/Y value and we
+ * have enough information to compute resolution of touch.
+ */
+static void wacom_set_phy_from_res(struct wacom_features *features)
+{
+	features->x_phy = (features->x_max * 100) / features->x_resolution;
+	features->y_phy = (features->y_max * 100) / features->y_resolution;
+}
+
 static int wacom_parse_logical_collection(unsigned char *report,
 					  struct wacom_features *features)
 {
@@ -178,15 +191,7 @@ static int wacom_parse_logical_collection(unsigned char *report,
 		features->pktlen = WACOM_PKGLEN_BBTOUCH3;
 		features->device_type = BTN_TOOL_FINGER;
 
-		/*
-		 * Stylus and Touch have same active area
-		 * so compute physical size based on stylus
-		 * data before its overwritten.
-		 */
-		features->x_phy =
-			(features->x_max * features->x_resolution) / 100;
-		features->y_phy =
-			(features->y_max * features->y_resolution) / 100;
+		wacom_set_phy_from_res(features);
 
 		features->x_max = features->y_max =
 			get_unaligned_le16(&report[10]);
@@ -869,6 +874,72 @@ static int wacom_register_input(struct wacom *wacom)
 	return error;
 }
 
+static void wacom_wireless_work(struct work_struct *work)
+{
+	struct wacom *wacom = container_of(work, struct wacom, work);
+	struct usb_device *usbdev = wacom->usbdev;
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+	/*
+	 * Regardless if this is a disconnect or a new tablet,
+	 * remove any existing input devices.
+	 */
+
+	/* Stylus interface */
+	wacom = usb_get_intfdata(usbdev->config->interface[1]);
+	if (wacom->wacom_wac.input)
+		input_unregister_device(wacom->wacom_wac.input);
+	wacom->wacom_wac.input = 0;
+
+	/* Touch interface */
+	wacom = usb_get_intfdata(usbdev->config->interface[2]);
+	if (wacom->wacom_wac.input)
+		input_unregister_device(wacom->wacom_wac.input);
+	wacom->wacom_wac.input = 0;
+
+	if (wacom_wac->pid == 0) {
+		printk(KERN_INFO "wacom: wireless tablet disconnected\n");
+	} else {
+		const struct usb_device_id *id = wacom_ids;
+
+		printk(KERN_INFO
+		       "wacom: wireless tablet connected with PID %x\n",
+		       wacom_wac->pid);
+
+		while (id->match_flags) {
+			if (id->idVendor == USB_VENDOR_ID_WACOM &&
+			    id->idProduct == wacom_wac->pid)
+				break;
+			id++;
+		}
+
+		if (!id->match_flags) {
+			printk(KERN_INFO
+			       "wacom: ignorning unknown PID.\n");
+			return;
+		}
+
+		/* Stylus interface */
+		wacom = usb_get_intfdata(usbdev->config->interface[1]);
+		wacom_wac = &wacom->wacom_wac;
+		wacom_wac->features =
+			*((struct wacom_features *)id->driver_info);
+		wacom_wac->features.device_type = BTN_TOOL_PEN;
+		wacom_register_input(wacom);
+
+		/* Touch interface */
+		wacom = usb_get_intfdata(usbdev->config->interface[2]);
+		wacom_wac = &wacom->wacom_wac;
+		wacom_wac->features =
+			*((struct wacom_features *)id->driver_info);
+		wacom_wac->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
+		wacom_wac->features.device_type = BTN_TOOL_FINGER;
+		wacom_set_phy_from_res(&wacom_wac->features);
+		wacom_wac->features.x_max = wacom_wac->features.y_max = 4096;
+		wacom_register_input(wacom);
+	}
+}
+
 static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
@@ -907,6 +978,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	wacom->usbdev = dev;
 	wacom->intf = intf;
 	mutex_init(&wacom->lock);
+	INIT_WORK(&wacom->work, wacom_wireless_work);
 	usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
 	strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
 
@@ -977,6 +1049,7 @@ static void wacom_disconnect(struct usb_interface *intf)
 	usb_set_intfdata(intf, NULL);
 
 	usb_kill_urb(wacom->irq);
+	cancel_work_sync(&wacom->work);
 	if (wacom->wacom_wac.input)
 		input_unregister_device(wacom->wacom_wac.input);
 	wacom_destroy_leds(wacom);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 6264e6a..fce7a09 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1046,9 +1046,27 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
 
 static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
 {
-	if (len != WACOM_PKGLEN_WIRELESS)
+	unsigned char *data = wacom->data;
+	int connected;
+
+	if (len != WACOM_PKGLEN_WIRELESS || data[0] != 0x80)
 		return 0;
 
+	connected = data[1] & 0x01;
+	if (connected) {
+		int pid;
+
+		pid = get_unaligned_be16(&data[6]);
+		if (wacom->pid != pid) {
+			wacom->pid = pid;
+			wacom_schedule_work(wacom);
+		}
+	} else if (wacom->pid != 0) {
+		/* disconnected while previously connected */
+		wacom->pid = 0;
+		wacom_schedule_work(wacom);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 2c04b62..cffaf6b 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -111,6 +111,7 @@ struct wacom_wac {
 	struct wacom_features features;
 	struct wacom_shared *shared;
 	struct input_dev *input;
+	int pid;
 };
 
 #endif
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v4 4/4] Input: wacom - wireless battery status
  2012-03-14  0:51 [PATCH v4 0/4] Wacom Wireless Module Support chris
                   ` (2 preceding siblings ...)
  2012-03-14  0:52 ` [PATCH v4 3/4] Input: wacom - create inputs when wireless connect chris
@ 2012-03-14  0:52 ` chris
  2012-03-21  1:03   ` Ping Cheng
  2012-03-14 18:25 ` [PATCH v4 0/4] Wacom Wireless Module Support Jason Gerecke
  4 siblings, 1 reply; 7+ messages in thread
From: chris @ 2012-03-14  0:52 UTC (permalink / raw)
  To: linux-input, dmitry.torokhov, killertofu; +Cc: Chris Bagwell

From: Chris Bagwell <chris@cnpbagwell.com>

Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>
---
 drivers/input/tablet/Kconfig     |    1 +
 drivers/input/tablet/wacom.h     |    2 +
 drivers/input/tablet/wacom_sys.c |   58 +++++++++++++++++++++++++++++++++++++-
 drivers/input/tablet/wacom_wac.c |    5 ++-
 drivers/input/tablet/wacom_wac.h |    1 +
 5 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
index 58a8775..0edeb94 100644
--- a/drivers/input/tablet/Kconfig
+++ b/drivers/input/tablet/Kconfig
@@ -76,6 +76,7 @@ config TABLET_USB_KBTAB
 config TABLET_USB_WACOM
 	tristate "Wacom Intuos/Graphire tablet support (USB)"
 	depends on USB_ARCH_HAS_HCD
+	select POWER_SUPPLY
 	select USB
 	help
 	  Say Y here if you want to use the USB version of the Wacom Intuos
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index febbfd9..b4842d0 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -88,6 +88,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/init.h>
 #include <linux/usb/input.h>
+#include <linux/power_supply.h>
 #include <asm/unaligned.h>
 
 /*
@@ -121,6 +122,7 @@ struct wacom {
 		u8 hlv;       /* status led brightness button pressed (1..127) */
 		u8 img_lum;   /* OLED matrix display brightness */
 	} led;
+	struct power_supply battery;
 };
 
 static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2fc7705..fe8a7f6 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -843,6 +843,56 @@ static void wacom_destroy_leds(struct wacom *wacom)
 	}
 }
 
+static enum power_supply_property wacom_battery_props[] = {
+	POWER_SUPPLY_PROP_CAPACITY
+};
+
+static int wacom_battery_get_property(struct power_supply *psy,
+				      enum power_supply_property psp,
+				      union power_supply_propval *val)
+{
+	struct wacom *wacom = container_of(psy, struct wacom, battery);
+	int ret = 0;
+
+	switch (psp) {
+		case POWER_SUPPLY_PROP_CAPACITY:
+			val->intval =
+				wacom->wacom_wac.battery_capacity * 100 / 31;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+	}
+
+	return ret;
+}
+
+static int wacom_initialize_battery(struct wacom *wacom)
+{
+	int error = 0;
+
+	if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
+		wacom->battery.properties = wacom_battery_props;
+		wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
+		wacom->battery.get_property = wacom_battery_get_property;
+		wacom->battery.name = "wacom_battery";
+		wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+		wacom->battery.use_for_apm = 0;
+
+		error = power_supply_register(&wacom->usbdev->dev,
+					      &wacom->battery);
+	}
+
+	return error;
+}
+
+static void wacom_destroy_battery(struct wacom *wacom)
+{
+	if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
+		power_supply_unregister(&wacom->battery);
+	}
+}
+
 static int wacom_register_input(struct wacom *wacom)
 {
 	struct input_dev *input_dev;
@@ -1016,10 +1066,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 	if (error)
 		goto fail4;
 
+	error = wacom_initialize_battery(wacom);
+	if (error)
+		goto fail5;
+
 	if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
 		error = wacom_register_input(wacom);
 		if (error)
-			goto fail5;
+			goto fail6;
 	}
 
 	/* Note that if query fails it is not a hard failure */
@@ -1034,6 +1088,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
 
 	return 0;
 
+ fail6: wacom_destroy_battery(wacom);
  fail5: wacom_destroy_leds(wacom);
  fail4:	wacom_remove_shared_data(wacom_wac);
  fail3:	usb_free_urb(wacom->irq);
@@ -1052,6 +1107,7 @@ static void wacom_disconnect(struct usb_interface *intf)
 	cancel_work_sync(&wacom->work);
 	if (wacom->wacom_wac.input)
 		input_unregister_device(wacom->wacom_wac.input);
+	wacom_destroy_battery(wacom);
 	wacom_destroy_leds(wacom);
 	usb_free_urb(wacom->irq);
 	usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index fce7a09..99fb6fe 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1054,17 +1054,20 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
 
 	connected = data[1] & 0x01;
 	if (connected) {
-		int pid;
+		int pid, battery;
 
 		pid = get_unaligned_be16(&data[6]);
+		battery = data[5] & 0x3f;
 		if (wacom->pid != pid) {
 			wacom->pid = pid;
 			wacom_schedule_work(wacom);
 		}
+		wacom->battery_capacity = battery;
 	} else if (wacom->pid != 0) {
 		/* disconnected while previously connected */
 		wacom->pid = 0;
 		wacom_schedule_work(wacom);
+		wacom->battery_capacity = 0;
 	}
 
 	return 0;
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index cffaf6b..ba5a334 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -112,6 +112,7 @@ struct wacom_wac {
 	struct wacom_shared *shared;
 	struct input_dev *input;
 	int pid;
+	int battery_capacity;
 };
 
 #endif
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 0/4] Wacom Wireless Module Support
  2012-03-14  0:51 [PATCH v4 0/4] Wacom Wireless Module Support chris
                   ` (3 preceding siblings ...)
  2012-03-14  0:52 ` [PATCH v4 4/4] Input: wacom - wireless battery status chris
@ 2012-03-14 18:25 ` Jason Gerecke
  4 siblings, 0 replies; 7+ messages in thread
From: Jason Gerecke @ 2012-03-14 18:25 UTC (permalink / raw)
  To: chris; +Cc: linux-input, dmitry.torokhov

On Tue, Mar 13, 2012 at 5:51 PM,  <chris@cnpbagwell.com> wrote:
> From: Chris Bagwell <chris@cnpbagwell.com>
>
> The 3rd gen Bamboo Pen & Touch and Intuos5 tablets support an
> optional wireless module.  This patch set adds support for it.
>
> New in v4 -
>  * Dropped patches related to 0xE5 support.  They will be sent
>   on their own again.
>  * Dropped a Kconfig patch that is already on for-linus branch.
>  * Removed "Bamboo" references to wireless patch since
>   wireless module works with at least 2 product families now.
>  * Delayed enabling monitor interrupt to last possible moment in probe
>   to fix crash reported by Jason Gerecke.
>
> New in v3 - Changed a pointer reset from 0 to NULL.
> Merged Ping's 0xE5 patches into this patch set to resolve
> merge issues.
>
> New in v2 - Updates only to 0xE5 patch set based on review comments.
> No wireless patch changes.
>
> Chris Bagwell (4):
>  Input: wacom - isolate input registration
>  Input: wacom - wireless monitor framework
>  Input: wacom - create inputs when wireless connect
>  Input: wacom - wireless battery status
>
>  drivers/input/tablet/Kconfig     |    1 +
>  drivers/input/tablet/wacom.h     |    9 ++
>  drivers/input/tablet/wacom_sys.c |  230 ++++++++++++++++++++++++++++++++-----
>  drivers/input/tablet/wacom_wac.c |   49 ++++++++-
>  drivers/input/tablet/wacom_wac.h |    6 +
>  5 files changed, 263 insertions(+), 32 deletions(-)
>
> --
> 1.7.7.6
>

There's a fair bit in this patch set that's beyond my knowledge to
properly review, but I can at least provide (for both the 3rd-gen
Bamboo and Intuos5):

Tested-By: Jason Gerecke <killertofu@gmail.com>

Jason

---
Day xee-nee-svsh duu-'ushtlh-ts'it;
nuu-wee-ya' duu-xan' 'vm-nvshtlh-ts'it.
Huu-chan xuu naa~-gha.
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 4/4] Input: wacom - wireless battery status
  2012-03-14  0:52 ` [PATCH v4 4/4] Input: wacom - wireless battery status chris
@ 2012-03-21  1:03   ` Ping Cheng
  0 siblings, 0 replies; 7+ messages in thread
From: Ping Cheng @ 2012-03-21  1:03 UTC (permalink / raw)
  To: chris; +Cc: linux-input, dmitry.torokhov, killertofu

On Tue, Mar 13, 2012 at 5:52 PM, <chris@cnpbagwell.com> wrote:
>
> From: Chris Bagwell <chris@cnpbagwell.com>
>
> Signed-off-by: Chris Bagwell <chris@cnpbagwell.com>

Acked-by: Ping Cheng <pingc@wacom.com> for the whole patchset.

As far as I know, Jason tested this patchset on Intuos5. So, Dmitry, you can add

Tested-by: Jason Gerecke <killertofu@gmail.com>.

Ping

> ---
>  drivers/input/tablet/Kconfig     |    1 +
>  drivers/input/tablet/wacom.h     |    2 +
>  drivers/input/tablet/wacom_sys.c |   58
> +++++++++++++++++++++++++++++++++++++-
>  drivers/input/tablet/wacom_wac.c |    5 ++-
>  drivers/input/tablet/wacom_wac.h |    1 +
>  5 files changed, 65 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
> index 58a8775..0edeb94 100644
> --- a/drivers/input/tablet/Kconfig
> +++ b/drivers/input/tablet/Kconfig
> @@ -76,6 +76,7 @@ config TABLET_USB_KBTAB
>  config TABLET_USB_WACOM
>        tristate "Wacom Intuos/Graphire tablet support (USB)"
>        depends on USB_ARCH_HAS_HCD
> +       select POWER_SUPPLY
>        select USB
>        help
>          Say Y here if you want to use the USB version of the Wacom Intuos
> diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
> index febbfd9..b4842d0 100644
> --- a/drivers/input/tablet/wacom.h
> +++ b/drivers/input/tablet/wacom.h
> @@ -88,6 +88,7 @@
>  #include <linux/mod_devicetable.h>
>  #include <linux/init.h>
>  #include <linux/usb/input.h>
> +#include <linux/power_supply.h>
>  #include <asm/unaligned.h>
>
>  /*
> @@ -121,6 +122,7 @@ struct wacom {
>                u8 hlv;       /* status led brightness button pressed
> (1..127) */
>                u8 img_lum;   /* OLED matrix display brightness */
>        } led;
> +       struct power_supply battery;
>  };
>
>  static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
> diff --git a/drivers/input/tablet/wacom_sys.c
> b/drivers/input/tablet/wacom_sys.c
> index 2fc7705..fe8a7f6 100644
> --- a/drivers/input/tablet/wacom_sys.c
> +++ b/drivers/input/tablet/wacom_sys.c
> @@ -843,6 +843,56 @@ static void wacom_destroy_leds(struct wacom *wacom)
>        }
>  }
>
> +static enum power_supply_property wacom_battery_props[] = {
> +       POWER_SUPPLY_PROP_CAPACITY
> +};
> +
> +static int wacom_battery_get_property(struct power_supply *psy,
> +                                     enum power_supply_property psp,
> +                                     union power_supply_propval *val)
> +{
> +       struct wacom *wacom = container_of(psy, struct wacom, battery);
> +       int ret = 0;
> +
> +       switch (psp) {
> +               case POWER_SUPPLY_PROP_CAPACITY:
> +                       val->intval =
> +                               wacom->wacom_wac.battery_capacity * 100 /
> 31;
> +                       break;
> +               default:
> +                       ret = -EINVAL;
> +                       break;
> +       }
> +
> +       return ret;
> +}
> +
> +static int wacom_initialize_battery(struct wacom *wacom)
> +{
> +       int error = 0;
> +
> +       if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
> +               wacom->battery.properties = wacom_battery_props;
> +               wacom->battery.num_properties =
> ARRAY_SIZE(wacom_battery_props);
> +               wacom->battery.get_property = wacom_battery_get_property;
> +               wacom->battery.name = "wacom_battery";
> +               wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
> +               wacom->battery.use_for_apm = 0;
> +
> +               error = power_supply_register(&wacom->usbdev->dev,
> +                                             &wacom->battery);
> +       }
> +
> +       return error;
> +}
> +
> +static void wacom_destroy_battery(struct wacom *wacom)
> +{
> +       if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
> +               power_supply_unregister(&wacom->battery);
> +       }
> +}
> +
>  static int wacom_register_input(struct wacom *wacom)
>  {
>        struct input_dev *input_dev;
> @@ -1016,10 +1066,14 @@ static int wacom_probe(struct usb_interface *intf,
> const struct usb_device_id *i
>        if (error)
>                goto fail4;
>
> +       error = wacom_initialize_battery(wacom);
> +       if (error)
> +               goto fail5;
> +
>        if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
>                error = wacom_register_input(wacom);
>                if (error)
> -                       goto fail5;
> +                       goto fail6;
>        }
>
>        /* Note that if query fails it is not a hard failure */
> @@ -1034,6 +1088,7 @@ static int wacom_probe(struct usb_interface *intf,
> const struct usb_device_id *i
>
>        return 0;
>
> + fail6: wacom_destroy_battery(wacom);
>  fail5: wacom_destroy_leds(wacom);
>  fail4:        wacom_remove_shared_data(wacom_wac);
>  fail3:        usb_free_urb(wacom->irq);
> @@ -1052,6 +1107,7 @@ static void wacom_disconnect(struct usb_interface
> *intf)
>        cancel_work_sync(&wacom->work);
>        if (wacom->wacom_wac.input)
>                input_unregister_device(wacom->wacom_wac.input);
> +       wacom_destroy_battery(wacom);
>        wacom_destroy_leds(wacom);
>        usb_free_urb(wacom->irq);
>        usb_free_coherent(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
> diff --git a/drivers/input/tablet/wacom_wac.c
> b/drivers/input/tablet/wacom_wac.c
> index fce7a09..99fb6fe 100644
> --- a/drivers/input/tablet/wacom_wac.c
> +++ b/drivers/input/tablet/wacom_wac.c
> @@ -1054,17 +1054,20 @@ static int wacom_wireless_irq(struct wacom_wac
> *wacom, size_t len)
>
>        connected = data[1] & 0x01;
>        if (connected) {
> -               int pid;
> +               int pid, battery;
>
>                pid = get_unaligned_be16(&data[6]);
> +               battery = data[5] & 0x3f;
>                if (wacom->pid != pid) {
>                        wacom->pid = pid;
>                        wacom_schedule_work(wacom);
>                }
> +               wacom->battery_capacity = battery;
>        } else if (wacom->pid != 0) {
>                /* disconnected while previously connected */
>                wacom->pid = 0;
>                wacom_schedule_work(wacom);
> +               wacom->battery_capacity = 0;
>        }
>
>        return 0;
> diff --git a/drivers/input/tablet/wacom_wac.h
> b/drivers/input/tablet/wacom_wac.h
> index cffaf6b..ba5a334 100644
> --- a/drivers/input/tablet/wacom_wac.h
> +++ b/drivers/input/tablet/wacom_wac.h
> @@ -112,6 +112,7 @@ struct wacom_wac {
>        struct wacom_shared *shared;
>        struct input_dev *input;
>        int pid;
> +       int battery_capacity;
>  };
>
>  #endif
> --
> 1.7.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-03-21  1:03 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-14  0:51 [PATCH v4 0/4] Wacom Wireless Module Support chris
2012-03-14  0:51 ` [PATCH v4 1/4] Input: wacom - isolate input registration chris
2012-03-14  0:52 ` [PATCH v4 2/4] Input: wacom - wireless monitor framework chris
2012-03-14  0:52 ` [PATCH v4 3/4] Input: wacom - create inputs when wireless connect chris
2012-03-14  0:52 ` [PATCH v4 4/4] Input: wacom - wireless battery status chris
2012-03-21  1:03   ` Ping Cheng
2012-03-14 18:25 ` [PATCH v4 0/4] Wacom Wireless Module Support Jason Gerecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).