linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Wacom Intuos4 LED and OLED support
@ 2011-03-27 11:28 Eduard Hasenleithner
  2011-03-28  8:30 ` Henrik Rydberg
  2011-03-31 20:01 ` Eduard Hasenleithner
  0 siblings, 2 replies; 4+ messages in thread
From: Eduard Hasenleithner @ 2011-03-27 11:28 UTC (permalink / raw)
  To: linux-input

This commit enables control of the LEDs and OLED displays found
on the Wacom Intuos4 M, L, and XL. For this purpose, an IOCTL
interface is added to the wacom input driver. The IOCTLs can be
issued on the raw USB device of the tablet.

Summary of changes:
* A new ioctl-number (0xB2) for the Wacom IOCTL is allocated.
* A new header file for the IOCTLs is introduced
	(include/linux/usb/wacom-dev.h)
* Implementation of LED and OLED control in wacom_wac.c

Signed-off-by: Eduard Hasenleithner <eduard@hasenleithner.at>
---
 Documentation/ioctl/ioctl-number.txt |    1 +
 drivers/input/tablet/wacom.h         |    1 +
 drivers/input/tablet/wacom_sys.c     |    1 +
 drivers/input/tablet/wacom_wac.c     |   96 ++++++++++++++++++++++++++++++++++
 include/linux/usb/wacom-dev.h        |   48 +++++++++++++++++
 5 files changed, 147 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/usb/wacom-dev.h

diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index ac293e9..80aa4c3 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -302,6 +302,7 @@ Code  Seq#(hex)	Include File		Comments
 0xB0	all	RATIO devices		in development:
 					<mailto:vgo@ratio.de>
 0xB1	00-1F	PPPoX			<mailto:mostrows@styx.uwaterloo.ca>
+0xB2	00-1F	WACOM tablets		<mailto:linuxwacom-devel@lists.sourceforge.net>
 0xC0	00-0F	linux/usb/iowarrior.h
 0xCB	00-1F	CBM serial IEC bus	in development:
 					<mailto:michael.klein@puffin.lb.shuttle.de>
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 23317bd..76446ec 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -118,6 +118,7 @@ struct wacom {
 
 extern const struct usb_device_id wacom_ids[];
 
+int wacom_ioctl(struct usb_interface *intf, unsigned int code, void *buf);
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
 void wacom_setup_device_quirks(struct wacom_features *features);
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b97665f..d11aa54 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -628,6 +628,7 @@ static struct usb_driver wacom_driver = {
 	.id_table =	wacom_ids,
 	.probe =	wacom_probe,
 	.disconnect =	wacom_disconnect,
+	.unlocked_ioctl = wacom_ioctl,
 	.suspend =	wacom_suspend,
 	.resume =	wacom_resume,
 	.reset_resume =	wacom_reset_resume,
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 5597637..8db4543 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -15,6 +15,7 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
+#include <linux/usb/wacom-dev.h>
 
 static int wacom_penpartner_irq(struct wacom_wac *wacom)
 {
@@ -1479,3 +1480,98 @@ const struct usb_device_id wacom_ids[] = {
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, wacom_ids);
+
+#define WAC_CMD_RETRIES 10
+
+#define WAC_CMD_LED_CTRL 0x20
+#define WAC_CMD_ICON_START 0x21
+#define WAC_CMD_ICON_XFER 0x23
+
+static int wacom_command_xfer(struct usb_interface *intf,
+	unsigned char id, void *buf, int size)
+{
+	int rval, retries = WAC_CMD_RETRIES;
+	do rval = usb_control_msg(interface_to_usbdev(intf),
+		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+		0x09, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		0x300 | id, intf->altsetting[0].desc.bInterfaceNumber,
+		buf, size, 1000);
+	while ((rval == -ETIMEDOUT || rval == -EPIPE) && --retries>0);
+
+	return rval;
+}
+
+static int wacom_ioctl_led_control(struct usb_interface *intf,
+	struct wacom_led_ctrl *arg)
+{
+	struct wacom *wacom = usb_get_intfdata(intf);
+	char buf[9] = {
+		WAC_CMD_LED_CTRL,
+		((arg->led_enable!=0)<<2) | (arg->led_select & 0x03),
+		arg->led_llv & 0x7f,
+		arg->led_hlv & 0x7f,
+		arg->img_lum & 0x0f,
+		0, 0, 0, 0
+	};
+
+	if (
+		wacom->wacom_wac.features.type < INTUOS4 ||
+		wacom->wacom_wac.features.type > INTUOS4L
+	) {
+		/* device not supported */
+		return -ENODEV;
+	}
+
+	return wacom_command_xfer(intf, WAC_CMD_LED_CTRL, buf, sizeof buf);
+}
+
+static int wacom_icon_start(struct usb_interface *intf, int start)
+{
+	char buf[2] = { WAC_CMD_ICON_START, start };
+	return wacom_command_xfer(intf, WAC_CMD_ICON_START, buf, sizeof buf);
+}
+
+static int wacom_ioctl_image_put(struct usb_interface *intf,
+	struct wacom_img_put *arg)
+{
+	unsigned char *buf;
+	int i, rval;
+	struct wacom *wacom = usb_get_intfdata(intf);
+	if (
+		wacom->wacom_wac.features.type < INTUOS4 ||
+		wacom->wacom_wac.features.type > INTUOS4L
+	) {
+		/* device not supported */
+		return -ENODEV;
+	}
+
+	buf = kzalloc(259, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	rval = wacom_icon_start(intf, 1);
+	if (rval >= 0) {
+		buf[0] = WAC_CMD_ICON_XFER;
+		buf[1] = arg->button_id & 0x07;
+		for (i=0; i<4; i++) {
+			buf[2] = i;
+			memcpy(buf+3, arg->buf + i*256, 256);
+			rval = wacom_command_xfer(intf, WAC_CMD_ICON_XFER, buf, 259);
+			if (rval<0) break;
+		}
+	}
+	kfree(buf);
+	wacom_icon_start(intf, 0);
+	return rval;
+}
+
+int wacom_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
+{
+	switch (code) {
+		case WACOM_LED_CONTROL:
+			return wacom_ioctl_led_control(intf, buf);
+		case WACOM_IMAGE_PUT:
+			return wacom_ioctl_image_put(intf, buf);
+		default:
+			return -EINVAL;
+	}
+}
diff --git a/include/linux/usb/wacom-dev.h b/include/linux/usb/wacom-dev.h
new file mode 100644
index 0000000..ac28e08
--- /dev/null
+++ b/include/linux/usb/wacom-dev.h
@@ -0,0 +1,48 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (c) 2011 Eduard Hasenleithner <eduard@hasenleithner.at>
+ */
+
+#ifndef _WACOM_DEV_H
+#define _WACOM_DEV_H
+
+/*
+ * IOCTL interface for wacom tablets.
+ *
+ * The IOCTLs can be sent to the wacom driver by means of its
+ * raw usb device (i.e. usbdevice_fs).
+ *
+ * Currently only used for control of LEDs and the OLED display
+ * on the Intuos4 M, L, and XL tablets.
+ */
+
+struct wacom_led_ctrl {
+	/* Status LED enable/disable */
+	char led_enable;
+	/* Status LED selector (0..3) when led_enable is true */
+	char led_select;
+	/* Luminance (0..127) of Status LED without stylus button pressed */
+	char led_llv;
+	/* Luminance (0..127) of Status LED with stylus button pressed */
+	char led_hlv;
+	/* Luminance (0..15) of button images */
+	char img_lum;
+};
+
+struct wacom_img_put {
+	/* Button id (0..7) to set image for */
+	unsigned char button_id;
+	/* 64x32 4-bit grayscale pixels with Intuos4 specific interleaving */
+	unsigned char buf[1024];
+};
+
+#define WACOM_IOCTL 0xB2
+
+#define WACOM_LED_CONTROL _IOW(WACOM_IOCTL, 0x00, struct wacom_led_ctrl)
+#define WACOM_IMAGE_PUT _IOW(WACOM_IOCTL, 0x01, struct wacom_img_put)
+
+#endif
-- 
1.7.0.4


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

* Re: [PATCH] Wacom Intuos4 LED and OLED support
  2011-03-27 11:28 [PATCH] Wacom Intuos4 LED and OLED support Eduard Hasenleithner
@ 2011-03-28  8:30 ` Henrik Rydberg
  2011-03-28  8:54   ` Eduard Hasenleithner
  2011-03-31 20:01 ` Eduard Hasenleithner
  1 sibling, 1 reply; 4+ messages in thread
From: Henrik Rydberg @ 2011-03-28  8:30 UTC (permalink / raw)
  To: Eduard Hasenleithner; +Cc: linux-input

On Sun, Mar 27, 2011 at 01:28:00PM +0200, Eduard Hasenleithner wrote:
> This commit enables control of the LEDs and OLED displays found
> on the Wacom Intuos4 M, L, and XL. For this purpose, an IOCTL
> interface is added to the wacom input driver. The IOCTLs can be
> issued on the raw USB device of the tablet.
> 
> Summary of changes:
> * A new ioctl-number (0xB2) for the Wacom IOCTL is allocated.
> * A new header file for the IOCTLs is introduced
> 	(include/linux/usb/wacom-dev.h)
> * Implementation of LED and OLED control in wacom_wac.c
> 
> Signed-off-by: Eduard Hasenleithner <eduard@hasenleithner.at>

Hi Eduard,

Did you consider using the LED input interface? Implement the
input_dev event hook and write EV_LED events to the device node.

Thanks,
Henrik

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

* Re: [PATCH] Wacom Intuos4 LED and OLED support
  2011-03-28  8:30 ` Henrik Rydberg
@ 2011-03-28  8:54   ` Eduard Hasenleithner
  0 siblings, 0 replies; 4+ messages in thread
From: Eduard Hasenleithner @ 2011-03-28  8:54 UTC (permalink / raw)
  To: Henrik Rydberg; +Cc: linux-input

On 2011-03-28 10:30, Henrik Rydberg wrote:
> Did you consider using the LED input interface? Implement the
> input_dev event hook and write EV_LED events to the device node.

Yes, but IMHO the OLED matrix displays for each button (8 buttons, 64x32 
pixels) are incompatible with the event interface LED IOCTLs. 
Furthermore, using the special wacom IOCTLs it is possible to set the 
luminance levels, which the event interface provides neither.

Please correct me if I'm wrong.

Br,
Eduard

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

* Re: [PATCH] Wacom Intuos4 LED and OLED support
  2011-03-27 11:28 [PATCH] Wacom Intuos4 LED and OLED support Eduard Hasenleithner
  2011-03-28  8:30 ` Henrik Rydberg
@ 2011-03-31 20:01 ` Eduard Hasenleithner
  1 sibling, 0 replies; 4+ messages in thread
From: Eduard Hasenleithner @ 2011-03-31 20:01 UTC (permalink / raw)
  To: Eduard Hasenleithner; +Cc: linux-input

Hi

Since there have already passed some days after posting this patch, I
want to ask about the general potential of inclusion into the linux
input subsystem.

Every now and than, input devices are built which have small LCD/LED
displays on it. AFAIK, there exists no (Intel approved USB-) standard
for these devices, they just use some Control URBs.

One example is the Intous4, for which I submitted the patch. Another
example is the Saitek X52 pro, for which I wrote a simple user-space
library for setting the LCD. With both devices it became obvious that
in the linux kernel, no direct support for this (unofficial) class of
devices is available yet. The X52 is an example, but not the direct
topic for this discussion, since the event device is not "grabbed" (at
least when I last checked), which means that URBs can be sent to the
device even when being registered with the input subsystem.

Currently I identified following possible methods for solving the task:
* URBs via USB raw device to physical usb device
* LED IOCTL via evdev to wacom.ko
* IOCTLs via USB raw device to wacom.ko (i.e. this patch)
* IOCTLs via evdev to wacom.ko
* Control URBs via evdev to wacom.ko

In the next sections I iterate over the individual methods. At the end
of each section I summarize good (+) and bad (-) properties.

==== URBs via USB raw device to physical USB device ====
There already exist some implementations using this method. The
general (and severe) problem with this method is, that the kernel
driver has to be unloaded before the images can be changed.
+ No changes in input subsystem required
+ No changes in input device driver needed
- Need for input device driver unload

==== LED IOCTL via evdev to wacom.ko ====
This method requires the input subsystem to be aware of input devices
with LEDs and OLED matrix displays. This could either be an extension
to the existing LED ioctl (unlikely) or a completely new
(matrix-)Display IOCTL.
+ Generic user-space tool can be implemented
- Requires changes in input subsystem
- Future proof IOCTL interface nearly impossible to specify

==== IOCTLs via USB raw device to wacom.ko ====
This is my currently preferred method. This method has been invented
by Nicolas Hirsch, and has been included to the linuxwacom tree. AFAIK
there were no efforts yet to get it into the main kernel tree.
I completely rewrote this patch, because a few adaptations were needed
for the 2.6.38 kernel, and I did not want to have the image
de-interleaving code in the kernel. (In a next version of the patch I
should put a "thanks to Nicolas" into a source comment).

For changing LED images, the commands travel in the following way to the tablet:
xsetwacom => wacom xorg-input-driver => wacom linux kernel driver
+ Requires no changes in input subsystem
+ It is possible to supply external kernel module for older kernel releases

==== IOCTLs via evdev to wacom.ko ====
This is is basically the previous method, but routed over the input
event device instead of using the raw USB device.
+ Removes the need to consult "/sys" for mapping the event device to
the raw USB device
- No possibility for compilation of externel wacom kernel driver for
older kernels

==== Control URBs via evdev to wacom.ko ====
This is probably a "bad idea". The idea is to let the input kernel
driver expose a restricted subset of Control URBs by means of the
input event device.
+ It is supposed that only very few lines of codes needed in input driver.
+ Most of the development happens in the user-space; kernel driver
patches frequency supposed to be almost zero after initial patch
- Might provide "hole" for several security related bugs
- No possibility for compilation of external wacom kernel driver for
older kernels

Comments and suggestions for further methods are welcome.

thanks,
Eduard

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

end of thread, other threads:[~2011-03-31 20:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-27 11:28 [PATCH] Wacom Intuos4 LED and OLED support Eduard Hasenleithner
2011-03-28  8:30 ` Henrik Rydberg
2011-03-28  8:54   ` Eduard Hasenleithner
2011-03-31 20:01 ` Eduard Hasenleithner

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).