* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-15 0:34 UTC (permalink / raw)
To: Richard Weinberger
Cc: Lars-Peter Clausen, Greg Kroah-Hartman,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
linux-iio-u79uwXL29TY76Z2rM5mHXA, Benjamin Herrenschmidt,
teg-B22kvLQNl6c, Thierry Reding, Lennox Wu, Marek Vasut,
Liqin Chen, msalter-H+wXaHxf7aLQT0dZR+AlfA,
linux-pwm-u79uwXL29TY76Z2rM5mHXA,
devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
knaack.h-Mmb7MZpHnFY, Martin Schwidefsky,
Mischa.Jonker-HKixBCOQz3hWk0Htik3J/w,
jic23-DgEjT+Ai2ygdnm+yROfE0A, arnd-r2nGTMty4D4,
Geert Uytterhoeven
In-Reply-To: <5A40E1FC-CA61-4AFF-B205-4BAC175AA7AC-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On 07/14/2014 05:22 PM, Chen Gang wrote:
>
> 在 2014年7月14日,下午4:57,Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org> 写道:
>
>> Am 14.07.2014 10:48, schrieb Lars-Peter Clausen:
>>> On 07/14/2014 10:31 AM, Richard Weinberger wrote:
>>>> Am 13.07.2014 22:17, schrieb Greg Kroah-Hartman:
>>>>> On Sun, Jul 13, 2014 at 09:33:38PM +0200, Richard Weinberger wrote:
>>>>>> Maybe we could add COMPILE_TEST to the version string too?
>>>>>> Just to detect such kernels fast in user bug reports...
>>>>>
>>>>> What kind of bug report are you going to get?
>>>>
>>>> User manages to enable CONFIG_FOO by selecting COMPILE_TEST and
>>>> complains that it does not work. :)
>>>
>>> These drivers are typically drivers for some SoC peripheral and the device will simply physically not exist on a platform that does not provide HAS_IOMEM. This is not really any
>>> different from making the driver selectable via COMPILE_TEST for any other platform. To hit the issue you'd have to instantiate a device driver instance for a device that
>>> physically does not exist. This will always result in a failure.
>>
>> Okay, you have convinced me. :)
>>
After search the history patches, I found one related patch which made
by myself (when I am in Asianux):
"https://lkml.org/lkml/2013/7/1/641"
For me, it is a long discussion, and forced many members have to join
in. Please help check again.
Thanks.
>
> OK, thank all of you, and I shall send the related patch for it.
>
> I will try to finish it within this week.
>
--
Chen Gang
Open, share, and attitude like air, water, and life which God blessed
^ permalink raw reply
* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-15 0:35 UTC (permalink / raw)
To: Richard Weinberger
Cc: Lars-Peter Clausen, Greg Kroah-Hartman,
dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
linux-iio-u79uwXL29TY76Z2rM5mHXA, Benjamin Herrenschmidt,
teg-B22kvLQNl6c, Thierry Reding, Lennox Wu, Marek Vasut,
Liqin Chen, msalter-H+wXaHxf7aLQT0dZR+AlfA,
linux-pwm-u79uwXL29TY76Z2rM5mHXA,
devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b,
linux-watchdog-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
knaack.h-Mmb7MZpHnFY, Martin Schwidefsky,
Mischa.Jonker-HKixBCOQz3hWk0Htik3J/w,
jic23-DgEjT+Ai2ygdnm+yROfE0A, arnd-r2nGTMty4D4,
Geert Uytterhoeven
In-Reply-To: <5A40E1FC-CA61-4AFF-B205-4BAC175AA7AC-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On 07/14/2014 05:22 PM, Chen Gang wrote:
>
> 在 2014年7月14日,下午4:57,Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org> 写道:
>
>> Am 14.07.2014 10:48, schrieb Lars-Peter Clausen:
>>> On 07/14/2014 10:31 AM, Richard Weinberger wrote:
>>>> Am 13.07.2014 22:17, schrieb Greg Kroah-Hartman:
>>>>> On Sun, Jul 13, 2014 at 09:33:38PM +0200, Richard Weinberger wrote:
>>>>>> Maybe we could add COMPILE_TEST to the version string too?
>>>>>> Just to detect such kernels fast in user bug reports...
>>>>>
>>>>> What kind of bug report are you going to get?
>>>>
>>>> User manages to enable CONFIG_FOO by selecting COMPILE_TEST and
>>>> complains that it does not work. :)
>>>
>>> These drivers are typically drivers for some SoC peripheral and the device will simply physically not exist on a platform that does not provide HAS_IOMEM. This is not really any
>>> different from making the driver selectable via COMPILE_TEST for any other platform. To hit the issue you'd have to instantiate a device driver instance for a device that
>>> physically does not exist. This will always result in a failure.
>>
>> Okay, you have convinced me. :)
>>
After search the history patches, I found one related patch which made
by myself (when I am in Asianux):
"https://lkml.org/lkml/2013/7/1/641"
For me, it is a long discussion, and forced many members have to join
in. Please help check again.
Thanks.
>
> OK, thank all of you, and I shall send the related patch for it.
>
> I will try to finish it within this week.
>
--
Chen Gang
Open, share, and attitude like air, water, and life which God blessed
^ permalink raw reply
* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Guenter Roeck @ 2014-07-15 0:53 UTC (permalink / raw)
To: Chen Gang, Richard Weinberger
Cc: Lars-Peter Clausen, Greg Kroah-Hartman, dmitry.torokhov,
linux-iio, Benjamin Herrenschmidt, teg, Thierry Reding, Lennox Wu,
Marek Vasut, Liqin Chen, msalter, linux-pwm, devel,
linux-watchdog, linux-input, linux-kernel@vger.kernel.org,
knaack.h, Martin Schwidefsky, Mischa.Jonker, jic23, arnd,
Geert Uytterhoeven
In-Reply-To: <53C47725.8000005@gmail.com>
On 07/14/2014 05:34 PM, Chen Gang wrote:
> On 07/14/2014 05:22 PM, Chen Gang wrote:
>>
>> 在 2014年7月14日,下午4:57,Richard Weinberger <richard@nod.at> 写道:
>>
>>> Am 14.07.2014 10:48, schrieb Lars-Peter Clausen:
>>>> On 07/14/2014 10:31 AM, Richard Weinberger wrote:
>>>>> Am 13.07.2014 22:17, schrieb Greg Kroah-Hartman:
>>>>>> On Sun, Jul 13, 2014 at 09:33:38PM +0200, Richard Weinberger wrote:
>>>>>>> Maybe we could add COMPILE_TEST to the version string too?
>>>>>>> Just to detect such kernels fast in user bug reports...
>>>>>>
>>>>>> What kind of bug report are you going to get?
>>>>>
>>>>> User manages to enable CONFIG_FOO by selecting COMPILE_TEST and
>>>>> complains that it does not work. :)
>>>>
>>>> These drivers are typically drivers for some SoC peripheral and the device will simply physically not exist on a platform that does not provide HAS_IOMEM. This is not really any
>>>> different from making the driver selectable via COMPILE_TEST for any other platform. To hit the issue you'd have to instantiate a device driver instance for a device that
>>>> physically does not exist. This will always result in a failure.
>>>
>>> Okay, you have convinced me. :)
>>>
>
> After search the history patches, I found one related patch which made
> by myself (when I am in Asianux):
>
> "https://lkml.org/lkml/2013/7/1/641"
>
> For me, it is a long discussion, and forced many members have to join
> in. Please help check again.
>
One thing you could try would be to return NULL (or where appropriate
an error) in the #else case of CONFIG_HAS_IOMEM and CONFIG_HAS_IOPORT,
ie dont take COMPILE_TEST into account at all. Obviously that means
you won't be able to dump a warning message in the COMPILE_TEST
case, but at least the code would compile. The rejection of above patch
would make a good case for this approach.
Guenter
^ permalink raw reply
* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-15 1:11 UTC (permalink / raw)
To: Guenter Roeck, Richard Weinberger
Cc: Lars-Peter Clausen, Greg Kroah-Hartman, dmitry.torokhov,
linux-iio, Benjamin Herrenschmidt, teg, Thierry Reding, Lennox Wu,
Marek Vasut, Liqin Chen, msalter, linux-pwm, devel,
linux-watchdog, linux-input, linux-kernel@vger.kernel.org,
knaack.h, Martin Schwidefsky, Mischa.Jonker, jic23, arnd,
Geert Uytterhoeven
In-Reply-To: <53C47B76.4080306@roeck-us.net>
On 07/15/2014 08:53 AM, Guenter Roeck wrote:
> On 07/14/2014 05:34 PM, Chen Gang wrote:
>> On 07/14/2014 05:22 PM, Chen Gang wrote:
>>>
>>> 在 2014年7月14日,下午4:57,Richard Weinberger <richard@nod.at> 写道:
>>>
>>>> Am 14.07.2014 10:48, schrieb Lars-Peter Clausen:
>>>>> On 07/14/2014 10:31 AM, Richard Weinberger wrote:
>>>>>> Am 13.07.2014 22:17, schrieb Greg Kroah-Hartman:
>>>>>>> On Sun, Jul 13, 2014 at 09:33:38PM +0200, Richard Weinberger wrote:
>>>>>>>> Maybe we could add COMPILE_TEST to the version string too?
>>>>>>>> Just to detect such kernels fast in user bug reports...
>>>>>>>
>>>>>>> What kind of bug report are you going to get?
>>>>>>
>>>>>> User manages to enable CONFIG_FOO by selecting COMPILE_TEST and
>>>>>> complains that it does not work. :)
>>>>>
>>>>> These drivers are typically drivers for some SoC peripheral and the
>>>>> device will simply physically not exist on a platform that does not
>>>>> provide HAS_IOMEM. This is not really any
>>>>> different from making the driver selectable via COMPILE_TEST for
>>>>> any other platform. To hit the issue you'd have to instantiate a
>>>>> device driver instance for a device that
>>>>> physically does not exist. This will always result in a failure.
>>>>
>>>> Okay, you have convinced me. :)
>>>>
>>
>> After search the history patches, I found one related patch which made
>> by myself (when I am in Asianux):
>>
>> "https://lkml.org/lkml/2013/7/1/641"
>>
>> For me, it is a long discussion, and forced many members have to join
>> in. Please help check again.
>>
>
> One thing you could try would be to return NULL (or where appropriate
> an error) in the #else case of CONFIG_HAS_IOMEM and CONFIG_HAS_IOPORT,
> ie dont take COMPILE_TEST into account at all. Obviously that means
> you won't be able to dump a warning message in the COMPILE_TEST
> case, but at least the code would compile. The rejection of above patch
> would make a good case for this approach.
>
OK, thanks: at least, it can be improved. But still welcome any other
opinions of another related members.
Thanks.
--
Chen Gang
Open, share, and attitude like air, water, and life which God blessed
^ permalink raw reply
* Re: [PATCH v2] Input: Add driver for Microchip's CAP1106
From: Mark Rutland @ 2014-07-15 8:51 UTC (permalink / raw)
To: Daniel Mack
Cc: dtor@mail.ru, linux-input@vger.kernel.org, broonie@kernel.org,
dh.herrmann@gmail.com, devicetree@vger.kernel.org
In-Reply-To: <53C3AEE1.4030805@zonque.org>
On Mon, Jul 14, 2014 at 11:20:17AM +0100, Daniel Mack wrote:
> Hi Mark,
>
> thanks a lot for your feedback! Much appreciated.
>
> On 07/14/2014 11:52 AM, Mark Rutland wrote:
> > On Fri, Jul 11, 2014 at 11:06:33AM +0100, Daniel Mack wrote:
>
> >> +++ b/Documentation/devicetree/bindings/input/cap1106.txt
> >> @@ -0,0 +1,63 @@
> >> +Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
> >> +
> >> +The node for this driver must be a child of a I2C controller node, as the
> >> +device communication via I2C only.
> >> +
> >> +Required properties:
> >> +
> >> + compatible: Must be "microchip,cap1106"
> >> + reg: The I2C slave address of the device.
> >> + Only 0x28 is valid.
> >> + interrupt: Node describing the interrupt line the device's
> >> + ALERT#/CM_IRQ# pin is connected to.
> >
> > s/interrupt/interrupts/
> >
> > This is a _property_, not a node.
>
> Yes, I reworded that description a couple of times. Together with
> interrupt-parent, it's actually a property referencing a node ;) Will fix.
>
> > I take it the device only has a single interrupt line?
>
> Yes.
Ok, that sounds fine then.
> >> +
> >> +Optional properties:
> >> +
> >> + autorepeat: Enables the Linux input system's autorepeat
> >> + feature on the input device.
> >> + microchip,sensor-gain: Defines the gain of the sensor circuitry. This
> >> + effectively controls the sensitivity, as a
> >> + smaller delta capacitance is required to
> >> + generate the same delta count values.
> >> + Valid values are 1, 2, 4, and 8.
> >> + By default, a gain of 1 is set.
> >
> > Does the official documentation describe this in absolute terms?
>
> The documentation describes the gain feature as "1, 2, 4, or 8", so I
> kept it like this in the bindings. Internally, the register stores that
> value in 2 bits. The driver takes care for the translation.
That sounds fine.
> >> +To define details of each individual button channel, six subnodes can be
> >> +specified. Inside each of those, the following property is valid:
> >> +
> >> + linux,keycode: Specify the numeric identifier of the keycode to be
> >> + generated when this channel is activated. If this
> >> + property is omitted, KEY_A, KEY_B, etc are used as
> >> + defaults.
> >
> > What are those subnodes, and how are they told apart? Name, compatible?
> >
> > I strongly recommend against relying on the order of the DT. It's very
> > easy for that to get messed up and makes things hard to read.
> >
> > Is is not possible to use linux,keymap and treat the buttons as a
> > matrix keypad? Then you don't need subnodes at all, and you can have a
> > sparse keymap if you want.
>
> Hmm, I thought about that, but there are - in theory - more details that
> could be specified per channel. I left those functions out for the first
> version, as I have no good way to test them.
Ok. Could you elaborate on what those details might be? It might make
sense to have these as nodes if there are arbitrary properties to
describe for each button, but I'm not familiar enough with the hardware
to make a call either way.
> Hence, my idea was to have everything related to one channel nicely
> grouped in a subnode. I've also seen bindings that rely on the order of
> subnodes before, for example in regulator drivers.
Sure. There's plenty of bad practice in DT bindings and code. There's
just too much of it going on to get everything sane, and it's not always
possible to fix the insane stuff if people are already using it.
> But I agree with you that it makes board definitions error-prone.
>
> linux,keycode feels a bit overkill here though, so I'd rather go for a
> fixed-size linux,keycodes property. The number of entries is fixed,
> anyway. Would you be fine with that?
Assuming no-one's likely to want a sparse keymap (i.e. one where some
keys do nothing) then that's probably ok.
> >> +struct cap1106_priv {
> >> + struct regmap *regmap;
> >> + struct input_dev *idev;
> >> + struct work_struct work;
> >> + spinlock_t lock;
> >> + bool closed:1;
> >
> > I don't think you're saving anything here by trying to have a bool
> > bitfield.
>
> That variable has been dropped in v3 already :)
>
> >> + i = 0;
> >> + for_each_child_of_node(node, child) {
> >> + if (i == CAP1106_NUM_CHN) {
> >> + dev_err(dev, "Too many button nodes.\n");
> >> + return -EINVAL;
> >> + }
> >> +
> >> + if (!of_property_read_u32(child, "linux,keycode", &tmp32))
> >> + priv->keycodes[i] = tmp32;
> >> +
> >> + i++;
> >> + }
> >
> > I don't think that it is a good idea to rely on the order of sub-nodes
> > in the DTB.
>
> Jup, I agree. As mentioned above, I'd like to solve that with
> linux,keycode for now.
>
> > [...]
> >
> >> + if (of_get_property(node, "autorepeat", NULL))
> >> + __set_bit(EV_REP, priv->idev->evbit);
> >
> > Use of_property_read_bool.
>
> Will do, thanks.
>
> > /me mutters usual grumblings about the autorepeat property.
>
> I took that from the gpio-keys driver. Is there a better way to denote
> such a feature?
Unfortunately not, given current practice. My gripe is that it's a Linux
detail that were describing rather than a property of the device. We can
forget about that for now.
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH v4] Input: Add driver for Microchip's CAP1106
From: Mark Rutland @ 2014-07-15 8:53 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Daniel Mack, linux-input@vger.kernel.org, broonie@kernel.org,
dh.herrmann@gmail.com, devicetree@vger.kernel.org
In-Reply-To: <20140714184642.GA38980@core.coreip.homeip.net>
On Mon, Jul 14, 2014 at 07:46:43PM +0100, Dmitry Torokhov wrote:
> On Mon, Jul 14, 2014 at 04:28:02PM +0200, Daniel Mack wrote:
> > +
> > +static int cap1106_i2c_remove(struct i2c_client *i2c_client)
> > +{
> > + struct cap1106_priv *priv = i2c_get_clientdata(i2c_client);
> > +
> > + input_unregister_device(priv->idev);
> > +
>
> No need to call unregister on managed input devices.
>
> Otherwise if DT guys are happy with bindings I am happy with the patch.
First I'd like to clarify the situation with properties for buttons
which I've just asked about on the last posting, but otherwise this
looks fine to me.
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH v2] Input: Add driver for Microchip's CAP1106
From: Daniel Mack @ 2014-07-15 9:12 UTC (permalink / raw)
To: Mark Rutland
Cc: dtor@mail.ru, linux-input@vger.kernel.org, broonie@kernel.org,
dh.herrmann@gmail.com, devicetree@vger.kernel.org
In-Reply-To: <20140715085138.GR26465@leverpostej>
On 07/15/2014 10:51 AM, Mark Rutland wrote:
> On Mon, Jul 14, 2014 at 11:20:17AM +0100, Daniel Mack wrote:
>> Hmm, I thought about that, but there are - in theory - more details that
>> could be specified per channel. I left those functions out for the first
>> version, as I have no good way to test them.
>
> Ok. Could you elaborate on what those details might be? It might make
> sense to have these as nodes if there are arbitrary properties to
> describe for each button, but I'm not familiar enough with the hardware
> to make a call either way.
No, there are just settings that can be made for each indvidual
channel/button, such as sensitivity settings for instance. But they can
of course be specified in a similar manner as the keycodes, in a
fixed-size array. That's completely ok I think.
>> linux,keycode feels a bit overkill here though, so I'd rather go for a
>> fixed-size linux,keycodes property. The number of entries is fixed,
>> anyway. Would you be fine with that?
>
> Assuming no-one's likely to want a sparse keymap (i.e. one where some
> keys do nothing) then that's probably ok.
If such a setup occurs, support for disabling channels could easily be
added, and in such cases, the keycode is simple ignored. I don't think a
sparse matrix keymap makes much sense here, especially as the buttons
are not organized in rows and columns.
>>> /me mutters usual grumblings about the autorepeat property.
>>
>> I took that from the gpio-keys driver. Is there a better way to denote
>> such a feature?
>
> Unfortunately not, given current practice. My gripe is that it's a Linux
> detail that were describing rather than a property of the device. We can
> forget about that for now.
I see, so I'll leave it as it is.
I'll drop the input device unregister call as Dmitry said, and repost v5.
Thanks again!
Daniel
^ permalink raw reply
* [PATCH v5] Input: Add driver for Microchip's CAP1106
From: Daniel Mack @ 2014-07-15 11:30 UTC (permalink / raw)
To: dtor
Cc: linux-input, broonie, dh.herrmann, devicetree, mark.rutland,
Daniel Mack
This patch adds a driver for Microchips CAP1106, an I2C driven, 6-channel
capacitive touch sensor.
For now, only the capacitive buttons are supported, and no specific
settings that can be tweaked for individual channels, except for the
device-wide sensitivity gain. The defaults seem to work just fine out of
the box, so I'll leave configurable parameters for someone who's in need
of them and who can actually measure the impact. All registers are
prepared, however. Many of them are just not used for now.
The implementation does not make any attempt to be compatible to platform
data driven boards, but fully depends on CONFIG_OF.
Power management functions are also left for volounteers with the ability
to actually test them.
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
v2:
* Fix potential deadlocks pointed out by David.
v3:
* Use devm_request_threaded_irq() and get rid of the work struct.
* Drop ->open() and ->close() as it isn't actually needed for an
interrupt-driven device. This way, we can also get rid of the
locking entirely.
v4:
* Follow Mark Rutland's advices regarding the DTS bindings:
* Fix 'interrupt' node in the bindings documentation
* Drop the subnode structure, and store keycodes in an array named
'linux,keycodes'. This way, we no longer rely on subnodes
ordering.
* Use of_property_read_bool() to read boolean properties.
* Re-introduce ->open() and ->close() for the input device, for
power-saving purposes. Also, put the device to deep sleep at probe
time, so it draws less power until ->open() is called.
* Re-introduce ->open() and ->close() for the input device, for
power-saving purposes. Also, put the device to deep sleep at probe
time, so it draws less power until ->open() is called.
v5:
* Remove input_unregister_device(). As that was the only call in the
drivers ->remove() function, the entire thing can be dropped.
* Fix compilation error when building as module
.../devicetree/bindings/input/cap1106.txt | 53 ++++
drivers/input/keyboard/Kconfig | 10 +
drivers/input/keyboard/Makefile | 1 +
drivers/input/keyboard/cap1106.c | 337 +++++++++++++++++++++
4 files changed, 401 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/cap1106.txt
create mode 100644 drivers/input/keyboard/cap1106.c
diff --git a/Documentation/devicetree/bindings/input/cap1106.txt b/Documentation/devicetree/bindings/input/cap1106.txt
new file mode 100644
index 0000000..4b46390
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/cap1106.txt
@@ -0,0 +1,53 @@
+Device tree bindings for Microchip CAP1106, 6 channel capacitive touch sensor
+
+The node for this driver must be a child of a I2C controller node, as the
+device communication via I2C only.
+
+Required properties:
+
+ compatible: Must be "microchip,cap1106"
+
+ reg: The I2C slave address of the device.
+ Only 0x28 is valid.
+
+ interrupts: Property describing the interrupt line the
+ device's ALERT#/CM_IRQ# pin is connected to.
+ The device only has one interrupt source.
+
+Optional properties:
+
+ autorepeat: Enables the Linux input system's autorepeat
+ feature on the input device.
+
+ microchip,sensor-gain: Defines the gain of the sensor circuitry. This
+ effectively controls the sensitivity, as a
+ smaller delta capacitance is required to
+ generate the same delta count values.
+ Valid values are 1, 2, 4, and 8.
+ By default, a gain of 1 is set.
+
+ linux,keycodes: Specifies an array of numeric keycode values to
+ be used for the channels. If this property is
+ omitted, KEY_A, KEY_B, etc are used as
+ defaults. The array must have exactly six
+ entries.
+
+Example:
+
+i2c_controller {
+ cap1106@28 {
+ compatible = "microchip,cap1106";
+ interrupt-parent = <&gpio1>;
+ interrupts = <0 0>;
+ reg = <0x28>;
+ autorepeat;
+ microchip,sensor-gain = <2>;
+
+ linux,keycodes = <103 /* KEY_UP */
+ 106 /* KEY_RIGHT */
+ 108 /* KEY_DOWN */
+ 105 /* KEY_LEFT */
+ 109 /* KEY_PAGEDOWN */
+ 104>; /* KEY_PAGEUP */
+ };
+}
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index f7e79b4..a3958c6 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -665,4 +665,14 @@ config KEYBOARD_CROS_EC
To compile this driver as a module, choose M here: the
module will be called cros_ec_keyb.
+config KEYBOARD_CAP1106
+ tristate "Microchip CAP1106 touch sensor"
+ depends on OF && I2C
+ select REGMAP_I2C
+ help
+ Say Y here to enable the CAP1106 touch sensor driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cap1106.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 7504ae1..0a33456 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
+obj-$(CONFIG_KEYBOARD_CAP1106) += cap1106.o
obj-$(CONFIG_KEYBOARD_CLPS711X) += clps711x-keypad.o
obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
diff --git a/drivers/input/keyboard/cap1106.c b/drivers/input/keyboard/cap1106.c
new file mode 100644
index 0000000..fe754c8
--- /dev/null
+++ b/drivers/input/keyboard/cap1106.c
@@ -0,0 +1,337 @@
+/*
+ * Input driver for Microchip CAP1106, 6 channel capacitive touch sensor
+ *
+ * http://www.microchip.com/wwwproducts/Devices.aspx?product=CAP1106
+ *
+ * (c) 2014 Daniel Mack <linux@zonque.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+
+#define CAP1106_REG_MAIN_CONTROL 0x00
+#define CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT (6)
+#define CAP1106_REG_MAIN_CONTROL_GAIN_MASK (0xc0)
+#define CAP1106_REG_MAIN_CONTROL_DLSEEP BIT(4)
+#define CAP1106_REG_GENERAL_STATUS 0x02
+#define CAP1106_REG_SENSOR_INPUT 0x03
+#define CAP1106_REG_NOISE_FLAG_STATUS 0x0a
+#define CAP1106_REG_SENOR_DELTA(X) (0x10 + (X))
+#define CAP1106_REG_SENSITIVITY_CONTROL 0x1f
+#define CAP1106_REG_CONFIG 0x20
+#define CAP1106_REG_SENSOR_ENABLE 0x21
+#define CAP1106_REG_SENSOR_CONFIG 0x22
+#define CAP1106_REG_SENSOR_CONFIG2 0x23
+#define CAP1106_REG_SAMPLING_CONFIG 0x24
+#define CAP1106_REG_CALIBRATION 0x25
+#define CAP1106_REG_INT_ENABLE 0x26
+#define CAP1106_REG_REPEAT_RATE 0x28
+#define CAP1106_REG_MT_CONFIG 0x2a
+#define CAP1106_REG_MT_PATTERN_CONFIG 0x2b
+#define CAP1106_REG_MT_PATTERN 0x2d
+#define CAP1106_REG_RECALIB_CONFIG 0x2f
+#define CAP1106_REG_SENSOR_THRESH(X) (0x30 + (X))
+#define CAP1106_REG_SENSOR_NOISE_THRESH 0x38
+#define CAP1106_REG_STANDBY_CHANNEL 0x40
+#define CAP1106_REG_STANDBY_CONFIG 0x41
+#define CAP1106_REG_STANDBY_SENSITIVITY 0x42
+#define CAP1106_REG_STANDBY_THRESH 0x43
+#define CAP1106_REG_CONFIG2 0x44
+#define CAP1106_REG_SENSOR_BASE_CNT(X) (0x50 + (X))
+#define CAP1106_REG_SENSOR_CALIB (0xb1 + (X))
+#define CAP1106_REG_SENSOR_CALIB_LSB1 0xb9
+#define CAP1106_REG_SENSOR_CALIB_LSB2 0xba
+#define CAP1106_REG_PRODUCT_ID 0xfd
+#define CAP1106_REG_MANUFACTURER_ID 0xfe
+#define CAP1106_REG_REVISION 0xff
+
+#define CAP1106_NUM_CHN 6
+#define CAP1106_PRODUCT_ID 0x55
+#define CAP1106_MANUFACTURER_ID 0x5d
+
+struct cap1106_priv {
+ struct regmap *regmap;
+ struct input_dev *idev;
+
+ /* config */
+ unsigned int keycodes[CAP1106_NUM_CHN];
+};
+
+static const struct reg_default cap1106_reg_defaults[] = {
+ { CAP1106_REG_MAIN_CONTROL, 0x00 },
+ { CAP1106_REG_GENERAL_STATUS, 0x00 },
+ { CAP1106_REG_SENSOR_INPUT, 0x00 },
+ { CAP1106_REG_NOISE_FLAG_STATUS, 0x00 },
+ { CAP1106_REG_SENSITIVITY_CONTROL, 0x2f },
+ { CAP1106_REG_CONFIG, 0x20 },
+ { CAP1106_REG_SENSOR_ENABLE, 0x3f },
+ { CAP1106_REG_SENSOR_CONFIG, 0xa4 },
+ { CAP1106_REG_SENSOR_CONFIG2, 0x07 },
+ { CAP1106_REG_SAMPLING_CONFIG, 0x39 },
+ { CAP1106_REG_CALIBRATION, 0x00 },
+ { CAP1106_REG_INT_ENABLE, 0x3f },
+ { CAP1106_REG_REPEAT_RATE, 0x3f },
+ { CAP1106_REG_MT_CONFIG, 0x80 },
+ { CAP1106_REG_MT_PATTERN_CONFIG, 0x00 },
+ { CAP1106_REG_MT_PATTERN, 0x3f },
+ { CAP1106_REG_RECALIB_CONFIG, 0x8a },
+ { CAP1106_REG_SENSOR_THRESH(0), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(1), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(2), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(3), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(4), 0x40 },
+ { CAP1106_REG_SENSOR_THRESH(5), 0x40 },
+ { CAP1106_REG_SENSOR_NOISE_THRESH, 0x01 },
+ { CAP1106_REG_STANDBY_CHANNEL, 0x00 },
+ { CAP1106_REG_STANDBY_CONFIG, 0x39 },
+ { CAP1106_REG_STANDBY_SENSITIVITY, 0x02 },
+ { CAP1106_REG_STANDBY_THRESH, 0x40 },
+ { CAP1106_REG_CONFIG2, 0x40 },
+ { CAP1106_REG_SENSOR_CALIB_LSB1, 0x00 },
+ { CAP1106_REG_SENSOR_CALIB_LSB2, 0x00 },
+};
+
+static bool cap1106_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CAP1106_REG_MAIN_CONTROL:
+ case CAP1106_REG_SENSOR_INPUT:
+ case CAP1106_REG_SENOR_DELTA(0):
+ case CAP1106_REG_SENOR_DELTA(1):
+ case CAP1106_REG_SENOR_DELTA(2):
+ case CAP1106_REG_SENOR_DELTA(3):
+ case CAP1106_REG_SENOR_DELTA(4):
+ case CAP1106_REG_SENOR_DELTA(5):
+ case CAP1106_REG_PRODUCT_ID:
+ case CAP1106_REG_MANUFACTURER_ID:
+ case CAP1106_REG_REVISION:
+ return true;
+ }
+
+ return false;
+}
+
+static const struct regmap_config cap1106_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CAP1106_REG_REVISION,
+ .reg_defaults = cap1106_reg_defaults,
+
+ .num_reg_defaults = ARRAY_SIZE(cap1106_reg_defaults),
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = cap1106_volatile_reg,
+};
+
+static irqreturn_t cap1106_thread_func(int irq_num, void *data)
+{
+ struct cap1106_priv *priv = data;
+ unsigned int status;
+ int ret, i;
+
+ /*
+ * Deassert interrupt. This needs to be done before reading the status
+ * registers, which will not carry valid values otherwise.
+ */
+ ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL, 1, 0);
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_read(priv->regmap, CAP1106_REG_SENSOR_INPUT, &status);
+ if (ret < 0)
+ goto out;
+
+ for (i = 0; i < CAP1106_NUM_CHN; i++)
+ input_report_key(priv->idev, priv->keycodes[i],
+ status & (1 << i));
+
+ input_sync(priv->idev);
+
+out:
+ return IRQ_HANDLED;
+}
+
+static int cap1106_set_sleep(struct cap1106_priv *priv, bool sleep)
+{
+ return regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+ CAP1106_REG_MAIN_CONTROL_DLSEEP,
+ sleep ? CAP1106_REG_MAIN_CONTROL_DLSEEP : 0);
+}
+
+static int cap1106_input_open(struct input_dev *idev)
+{
+ struct cap1106_priv *priv = input_get_drvdata(idev);
+
+ return cap1106_set_sleep(priv, false);
+}
+
+static void cap1106_input_close(struct input_dev *idev)
+{
+ struct cap1106_priv *priv = input_get_drvdata(idev);
+
+ cap1106_set_sleep(priv, true);
+}
+
+static int cap1106_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &i2c_client->dev;
+ struct cap1106_priv *priv;
+ struct device_node *node;
+ int i, ret, irq, gain = 0;
+ unsigned int val, rev;
+ u32 gain32, keycodes[CAP1106_NUM_CHN];
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = devm_regmap_init_i2c(i2c_client, &cap1106_regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ ret = regmap_read(priv->regmap, CAP1106_REG_PRODUCT_ID, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != CAP1106_PRODUCT_ID) {
+ dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
+ val, CAP1106_PRODUCT_ID);
+ return -ENODEV;
+ }
+
+ ret = regmap_read(priv->regmap, CAP1106_REG_MANUFACTURER_ID, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != CAP1106_MANUFACTURER_ID) {
+ dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
+ val, CAP1106_MANUFACTURER_ID);
+ return -ENODEV;
+ }
+
+ ret = regmap_read(priv->regmap, CAP1106_REG_REVISION, &rev);
+ if (ret < 0)
+ return ret;
+
+ dev_info(dev, "CAP1106 detected, revision 0x%02x\n", rev);
+ i2c_set_clientdata(i2c_client, priv);
+ node = dev->of_node;
+
+ if (!of_property_read_u32(node, "microchip,sensor-gain", &gain32)) {
+ if (is_power_of_2(gain32) && gain32 <= 8)
+ gain = ilog2(gain32);
+ else
+ dev_err(dev, "Invalid sensor-gain value %d\n", gain32);
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(keycodes) != ARRAY_SIZE(priv->keycodes));
+
+ /* Provide some useful defaults */
+ for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+ keycodes[i] = KEY_A + i;
+
+ of_property_read_u32_array(node, "linux,keycodes",
+ keycodes, ARRAY_SIZE(keycodes));
+
+ for (i = 0; i < ARRAY_SIZE(keycodes); i++)
+ priv->keycodes[i] = keycodes[i];
+
+ ret = regmap_update_bits(priv->regmap, CAP1106_REG_MAIN_CONTROL,
+ CAP1106_REG_MAIN_CONTROL_GAIN_MASK,
+ gain << CAP1106_REG_MAIN_CONTROL_GAIN_SHIFT);
+ if (ret < 0)
+ return ret;
+
+ /* Disable autorepeat. The Linux input system has its own handling. */
+ ret = regmap_write(priv->regmap, CAP1106_REG_REPEAT_RATE, 0);
+ if (ret < 0)
+ return ret;
+
+ priv->idev = devm_input_allocate_device(dev);
+ if (!priv->idev)
+ return -ENOMEM;
+
+ priv->idev->name = "CAP1106 capacitive touch sensor";
+ priv->idev->id.bustype = BUS_I2C;
+ priv->idev->evbit[0] = BIT_MASK(EV_KEY);
+
+ if (of_property_read_bool(node, "autorepeat"))
+ __set_bit(EV_REP, priv->idev->evbit);
+
+ for (i = 0; i < CAP1106_NUM_CHN; i++) {
+ unsigned int code = priv->keycodes[i];
+ priv->idev->keybit[BIT_WORD(code)] |= BIT_MASK(code);
+ }
+
+ priv->idev->id.vendor = CAP1106_MANUFACTURER_ID;
+ priv->idev->id.product = CAP1106_PRODUCT_ID;
+ priv->idev->id.version = rev;
+
+ priv->idev->open = cap1106_input_open;
+ priv->idev->close = cap1106_input_close;
+
+ input_set_drvdata(priv->idev, priv);
+
+ /*
+ * Put the device in deep sleep mode for now.
+ * ->open() will bring it back once the it is actually needed.
+ */
+ cap1106_set_sleep(priv, true);
+
+ ret = input_register_device(priv->idev);
+ if (ret < 0)
+ return ret;
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq) {
+ dev_err(dev, "Unable to parse or map IRQ\n");
+ return -ENXIO;
+ }
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, cap1106_thread_func,
+ IRQF_ONESHOT, dev_name(dev), priv);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id cap1106_dt_ids[] = {
+ { .compatible = "microchip,cap1106", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, cap1106_dt_ids);
+
+static const struct i2c_device_id cap1106_i2c_ids[] = {
+ { "cap1106", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cap1106_i2c_ids);
+
+static struct i2c_driver cap1106_i2c_driver = {
+ .driver = {
+ .name = "cap1106",
+ .owner = THIS_MODULE,
+ .of_match_table = cap1106_dt_ids,
+ },
+ .id_table = cap1106_i2c_ids,
+ .probe = cap1106_i2c_probe,
+};
+
+module_i2c_driver(cap1106_i2c_driver);
+
+MODULE_ALIAS("platform:cap1106");
+MODULE_DESCRIPTION("Microchip CAP1106 driver");
+MODULE_AUTHOR("Daniel Mack <linux@zonque.org>");
+MODULE_LICENSE("GPL v2");
--
1.9.3
^ permalink raw reply related
* Re: [PATCH] PM / sleep / irq: Do not suspend wakeup interrupts
From: Alexander Stein @ 2014-07-15 12:22 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Thomas Gleixner, Li, Aubrey, Dmitry Torokhov,
linux-input@vger.kernel.org, LKML, One Thousand Gnomes,
Linux PM list
In-Reply-To: <4679574.kGUnqAuNl9@vostro.rjw.lan>
On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> If an IRQ has been configured for wakeup via enable_irq_wake(), the
> driver who has done that must be prepared for receiving interrupts
> after suspend_device_irqs() has returned, so there is no need to
> "suspend" such IRQs. Moreover, if drivers using enable_irq_wake()
> actually want to receive interrupts after suspend_device_irqs() has
> returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> requesting the IRQs, which shouldn't be necessary (it also goes a bit
> too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> suspend_device_irqs() all the time regardless of whether or not it
> has been configured for signaling wakeup).
>
> For the above reasons, make __disable_irq() ignore IRQ descriptors
> with IRQD_WAKEUP_STATE set when its suspend argument is true which
> effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> set.
>
> This also allows IRQs configured for wakeup via enable_irq_wake()
> to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> sleep mode automatically just like for any other sleep states.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
> kernel/irq/manage.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> Index: linux-pm/kernel/irq/manage.c
> ===================================================================
> --- linux-pm.orig/kernel/irq/manage.c
> +++ linux-pm/kernel/irq/manage.c
> @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> {
> if (suspend) {
> - if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> + if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> + || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> return;
> desc->istate |= IRQS_SUSPENDED;
> }
Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?
Best regards,
Alexander
^ permalink raw reply
* Re: [PATCH] PM / sleep / irq: Do not suspend wakeup interrupts
From: Alexander Stein @ 2014-07-15 12:36 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Thomas Gleixner, Li, Aubrey, Dmitry Torokhov,
linux-input@vger.kernel.org, LKML, One Thousand Gnomes,
Linux PM list
In-Reply-To: <1776825.8kf9TZPye4@vostro.rjw.lan>
On Tuesday 15 July 2014 14:50:28, Rafael J. Wysocki wrote:
> On Tuesday, July 15, 2014 02:22:25 PM Alexander Stein wrote:
> > On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > If an IRQ has been configured for wakeup via enable_irq_wake(), the
> > > driver who has done that must be prepared for receiving interrupts
> > > after suspend_device_irqs() has returned, so there is no need to
> > > "suspend" such IRQs. Moreover, if drivers using enable_irq_wake()
> > > actually want to receive interrupts after suspend_device_irqs() has
> > > returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> > > requesting the IRQs, which shouldn't be necessary (it also goes a bit
> > > too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> > > suspend_device_irqs() all the time regardless of whether or not it
> > > has been configured for signaling wakeup).
> > >
> > > For the above reasons, make __disable_irq() ignore IRQ descriptors
> > > with IRQD_WAKEUP_STATE set when its suspend argument is true which
> > > effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> > > set.
> > >
> > > This also allows IRQs configured for wakeup via enable_irq_wake()
> > > to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> > > sleep mode automatically just like for any other sleep states.
> > >
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > > kernel/irq/manage.c | 3 ++-
> > > 1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > Index: linux-pm/kernel/irq/manage.c
> > > ===================================================================
> > > --- linux-pm.orig/kernel/irq/manage.c
> > > +++ linux-pm/kernel/irq/manage.c
> > > @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> > > void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> > > {
> > > if (suspend) {
> > > - if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> > > + if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> > > + || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> > > return;
> > > desc->istate |= IRQS_SUSPENDED;
> > > }
> >
> > Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?
>
> Not without looking at the code in question.
>
> One guess would be a missing call to enable_irq_wake().
No, ads7846.c does call 'enable_irq_wake(ts->spi->irq)'. So is this a platform or driver specific problem?
Regards,
Alexander
^ permalink raw reply
* Re: [PATCH] PM / sleep / irq: Do not suspend wakeup interrupts
From: Rafael J. Wysocki @ 2014-07-15 12:50 UTC (permalink / raw)
To: Alexander Stein
Cc: Thomas Gleixner, Li, Aubrey, Dmitry Torokhov,
linux-input@vger.kernel.org, LKML, One Thousand Gnomes,
Linux PM list
In-Reply-To: <2067046.JFGH9LUctP@ws-stein>
On Tuesday, July 15, 2014 02:22:25 PM Alexander Stein wrote:
> On Thursday 10 July 2014 23:37:54, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > If an IRQ has been configured for wakeup via enable_irq_wake(), the
> > driver who has done that must be prepared for receiving interrupts
> > after suspend_device_irqs() has returned, so there is no need to
> > "suspend" such IRQs. Moreover, if drivers using enable_irq_wake()
> > actually want to receive interrupts after suspend_device_irqs() has
> > returned, they need to add IRQF_NO_SUSPEND to the IRQ flags while
> > requesting the IRQs, which shouldn't be necessary (it also goes a bit
> > too far, as IRQF_NO_SUSPEND causes the IRQ to be ignored by
> > suspend_device_irqs() all the time regardless of whether or not it
> > has been configured for signaling wakeup).
> >
> > For the above reasons, make __disable_irq() ignore IRQ descriptors
> > with IRQD_WAKEUP_STATE set when its suspend argument is true which
> > effectively causes them to behave like IRQs with IRQF_NO_SUSPEND
> > set.
> >
> > This also allows IRQs configured for wakeup via enable_irq_wake()
> > to work as wakeup interrupts for the "freeze" (suspend-to-idle)
> > sleep mode automatically just like for any other sleep states.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> > kernel/irq/manage.c | 3 ++-
> > 1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > Index: linux-pm/kernel/irq/manage.c
> > ===================================================================
> > --- linux-pm.orig/kernel/irq/manage.c
> > +++ linux-pm/kernel/irq/manage.c
> > @@ -385,7 +385,8 @@ setup_affinity(unsigned int irq, struct
> > void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
> > {
> > if (suspend) {
> > - if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
> > + if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND)
> > + || irqd_has_set(&desc->irq_data, IRQD_WAKEUP_STATE))
> > return;
> > desc->istate |= IRQS_SUSPENDED;
> > }
>
> Nice, this fixes my wakeup problem from freeze using gpio-keys. Unfortunately my SPI-attached touchscreen controller cannot be used for wakeup from freeze. Using it to wakeup from mem does work instead. Any ideas what might be wrong in this case?
Not without looking at the code in question.
One guess would be a missing call to enable_irq_wake().
Rafael
^ permalink raw reply
* Re: [PATCH] drivers: Let several drivers depends on HAS_IOMEM for 'devm_ioremap_resource'
From: Chen Gang @ 2014-07-15 14:38 UTC (permalink / raw)
To: Guenter Roeck, Richard Weinberger
Cc: linux-iio, Benjamin Herrenschmidt, teg, Thierry Reding, Lennox Wu,
Marek Vasut, Liqin Chen, Lars-Peter Clausen, Geert Uytterhoeven,
msalter, linux-pwm, devel, linux-watchdog, arnd, linux-input,
Greg Kroah-Hartman, dmitry.torokhov, linux-kernel@vger.kernel.org,
knaack.h, Martin Schwidefsky, Mischa.Jonker, jic23
In-Reply-To: <53C47FB7.6080304@gmail.com>
On 07/15/2014 09:11 AM, Chen Gang wrote:
>
>
> On 07/15/2014 08:53 AM, Guenter Roeck wrote:
>> On 07/14/2014 05:34 PM, Chen Gang wrote:
>>> On 07/14/2014 05:22 PM, Chen Gang wrote:
>>>>
>>>> 在 2014年7月14日,下午4:57,Richard Weinberger <richard@nod.at> 写道:
>>>>
>>>>> Am 14.07.2014 10:48, schrieb Lars-Peter Clausen:
>>>>>> On 07/14/2014 10:31 AM, Richard Weinberger wrote:
>>>>>>> Am 13.07.2014 22:17, schrieb Greg Kroah-Hartman:
>>>>>>>> On Sun, Jul 13, 2014 at 09:33:38PM +0200, Richard Weinberger wrote:
>>>>>>>>> Maybe we could add COMPILE_TEST to the version string too?
>>>>>>>>> Just to detect such kernels fast in user bug reports...
>>>>>>>>
>>>>>>>> What kind of bug report are you going to get?
>>>>>>>
>>>>>>> User manages to enable CONFIG_FOO by selecting COMPILE_TEST and
>>>>>>> complains that it does not work. :)
>>>>>>
>>>>>> These drivers are typically drivers for some SoC peripheral and the
>>>>>> device will simply physically not exist on a platform that does not
>>>>>> provide HAS_IOMEM. This is not really any
>>>>>> different from making the driver selectable via COMPILE_TEST for
>>>>>> any other platform. To hit the issue you'd have to instantiate a
>>>>>> device driver instance for a device that
>>>>>> physically does not exist. This will always result in a failure.
>>>>>
>>>>> Okay, you have convinced me. :)
>>>>>
>>>
>>> After search the history patches, I found one related patch which made
>>> by myself (when I am in Asianux):
>>>
>>> "https://lkml.org/lkml/2013/7/1/641"
>>>
>>> For me, it is a long discussion, and forced many members have to join
>>> in. Please help check again.
>>>
>>
>> One thing you could try would be to return NULL (or where appropriate
>> an error) in the #else case of CONFIG_HAS_IOMEM and CONFIG_HAS_IOPORT,
>> ie dont take COMPILE_TEST into account at all. Obviously that means
>> you won't be able to dump a warning message in the COMPILE_TEST
>> case, but at least the code would compile. The rejection of above patch
>> would make a good case for this approach.
>>
>
> OK, thanks: at least, it can be improved. But still welcome any other
> opinions of another related members.
>
If no reply within 3 days (2014-07-18), I shall try to send related
patch for it within this week end (2014-07-20).
Thanks.
--
Chen Gang
Open share and attitude like air water and life which God blessed
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
^ permalink raw reply
* Re: [PATCH v2] Input: Add driver for Microchip's CAP1106
From: Mark Rutland @ 2014-07-15 14:42 UTC (permalink / raw)
To: Daniel Mack
Cc: dtor@mail.ru, linux-input@vger.kernel.org, broonie@kernel.org,
dh.herrmann@gmail.com, devicetree@vger.kernel.org
In-Reply-To: <53C4F076.1070500@zonque.org>
On Tue, Jul 15, 2014 at 10:12:22AM +0100, Daniel Mack wrote:
> On 07/15/2014 10:51 AM, Mark Rutland wrote:
> > On Mon, Jul 14, 2014 at 11:20:17AM +0100, Daniel Mack wrote:
>
> >> Hmm, I thought about that, but there are - in theory - more details that
> >> could be specified per channel. I left those functions out for the first
> >> version, as I have no good way to test them.
> >
> > Ok. Could you elaborate on what those details might be? It might make
> > sense to have these as nodes if there are arbitrary properties to
> > describe for each button, but I'm not familiar enough with the hardware
> > to make a call either way.
>
> No, there are just settings that can be made for each indvidual
> channel/button, such as sensitivity settings for instance. But they can
> of course be specified in a similar manner as the keycodes, in a
> fixed-size array. That's completely ok I think.
>
> >> linux,keycode feels a bit overkill here though, so I'd rather go for a
> >> fixed-size linux,keycodes property. The number of entries is fixed,
> >> anyway. Would you be fine with that?
> >
> > Assuming no-one's likely to want a sparse keymap (i.e. one where some
> > keys do nothing) then that's probably ok.
>
> If such a setup occurs, support for disabling channels could easily be
> added, and in such cases, the keycode is simple ignored. I don't think a
> sparse matrix keymap makes much sense here, especially as the buttons
> are not organized in rows and columns.
>
> >>> /me mutters usual grumblings about the autorepeat property.
> >>
> >> I took that from the gpio-keys driver. Is there a better way to denote
> >> such a feature?
> >
> > Unfortunately not, given current practice. My gripe is that it's a Linux
> > detail that were describing rather than a property of the device. We can
> > forget about that for now.
>
> I see, so I'll leave it as it is.
>
> I'll drop the input device unregister call as Dmitry said, and repost v5.
Sure, that all sounds fine.
Cheers,
Mark.
^ permalink raw reply
* Re: [PATCH v2] Input: Add driver for Microchip's CAP1106
From: Dmitry Torokhov @ 2014-07-15 16:41 UTC (permalink / raw)
To: Mark Rutland
Cc: Daniel Mack, linux-input@vger.kernel.org, broonie@kernel.org,
dh.herrmann@gmail.com, devicetree@vger.kernel.org
In-Reply-To: <20140715085138.GR26465@leverpostej>
Hi Mark,
On Tue, Jul 15, 2014 at 09:51:38AM +0100, Mark Rutland wrote:
> On Mon, Jul 14, 2014 at 11:20:17AM +0100, Daniel Mack wrote:
> >
> > linux,keycode feels a bit overkill here though, so I'd rather go for a
> > fixed-size linux,keycodes property. The number of entries is fixed,
> > anyway. Would you be fine with that?
>
> Assuming no-one's likely to want a sparse keymap (i.e. one where some
> keys do nothing) then that's probably ok.
For such a small keymap, if one does not want to use some of the
buttons, setting corresponding entries to KEY_RESERVED should work well.
> >
> > I took that from the gpio-keys driver. Is there a better way to denote
> > such a feature?
>
> Unfortunately not, given current practice. My gripe is that it's a Linux
> detail that were describing rather than a property of the device. We can
> forget about that for now.
I prefer looking at it as user expressing the desired behavior of the
driver; it is up to OS to deliver such behavior ;)
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2] Input: Add driver for Microchip's CAP1106
From: Mark Rutland @ 2014-07-15 17:17 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Daniel Mack, linux-input@vger.kernel.org, broonie@kernel.org,
dh.herrmann@gmail.com, devicetree@vger.kernel.org
In-Reply-To: <20140715164149.GA40351@core.coreip.homeip.net>
On Tue, Jul 15, 2014 at 05:41:49PM +0100, Dmitry Torokhov wrote:
> Hi Mark,
>
> On Tue, Jul 15, 2014 at 09:51:38AM +0100, Mark Rutland wrote:
> > On Mon, Jul 14, 2014 at 11:20:17AM +0100, Daniel Mack wrote:
> > >
> > > linux,keycode feels a bit overkill here though, so I'd rather go for a
> > > fixed-size linux,keycodes property. The number of entries is fixed,
> > > anyway. Would you be fine with that?
> >
> > Assuming no-one's likely to want a sparse keymap (i.e. one where some
> > keys do nothing) then that's probably ok.
>
>
> For such a small keymap, if one does not want to use some of the
> buttons, setting corresponding entries to KEY_RESERVED should work well.
Ah, I was not aware of KEY_RESERVED. That sounds perfect then.
> > >
> > > I took that from the gpio-keys driver. Is there a better way to denote
> > > such a feature?
> >
> > Unfortunately not, given current practice. My gripe is that it's a Linux
> > detail that were describing rather than a property of the device. We can
> > forget about that for now.
>
> I prefer looking at it as user expressing the desired behavior of the
> driver; it is up to OS to deliver such behavior ;)
Sure, but the user and DTB author are not the same, and may have
different preferences. Additionally autorepeat as a property only tells
half the story; I might prefer a 1ms delay while my neighbour Joe might
like a 3 billion year delay (he's a bit like that, Joe is). He also only
wants the esc key to repeat and can't figure out how to express that in
this DTB thing he's never heard of.
We can just leave this with me grumbling if you prefer ;)
Thanks,
Mark.
^ permalink raw reply
* [RFC] edt-ft5x06 - cannot see IRQ Qfrom device after DT probe
From: Markus Niebel @ 2014-07-15 17:43 UTC (permalink / raw)
To: linux-input
Hallo,
working with said tochcontroller we found that the IRQ is not seen in the following scenario:
- bootloader uses pin as an output for some reason
- pin is configured as GPIO and as INT source via device tree
- driver loads correctly and communicates over I2C
- IRQs not seen by CPU becaus pin is still configured as output
- when adding an int-gpios node to devicetree and parsing this gpio the gpio will be configured as input
- IRQ can be seen by CPU
Question:
- shall we add an int-gpio property to enable gpio pin config as input or
Regards
Markus Niebel
^ permalink raw reply
* [PATCH v2 00/23] Wacom queued patches
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
Hi Dmitry,
this is a resend/v2 of part of the Wacom tablet kernel work I have been
conducted during this merge window.
There are 2 fixes (01/23 and 02/23), a compatibility feature for wayland
(splitting the pad input device out of the pen/finger ones, which allows to
have a simple mapping kernel event / user event), and the conversion from a pure
usb driver to a HID one.
This conversion will allow us to make regression tests and hopefully help
including new devices in a much faster way when the report descriptors will be
fixed in the kernel or in the hardware.
I added a brand new patch (23/23) which moves wacom.ko into drivers/hid.
Jiri asked me to move the module into his subtree once the change is done, so
here it is.
I discussed with Jiri last Friday, and he was fine that you take this work
through your tree, even if it changes some files in his.
In order not to make the mess between your two trees, I removed one patch
(HID: uhid: add and set HID_TYPE_UHID for uhid devices) which is not mandatory
for the user.
Cheers,
Benjamin
Benjamin Tissoires (23):
Revert "Input: wacom - testing result shows get_report is
unnecessary."
Input - wacom: assign phys field from struct wacom into input_dev
Input - wacom: create a separate input device for pads
Input - wacom: split out the pad device for Intuos/Cintiq
Input - wacom: split out the pad device for Bamboos
Input - wacom: split out the pad device for DTUS
Input - wacom: split out the pad device for Graphire G4 and MO
Input - wacom: split out the pad device for the wireless receiver
Input - wacom: include and use linux/hid.h
Input - wacom: switch from an USB driver to a HID driver
Input - wacom: use hid communication instead of plain usb
Input - wacom: use HID core to actually fetch the report descriptor
Input - wacom: compute the HID report size to get the actual packet
size
Input - wacom: install LED/OLED sysfs files in the HID device instead
of USB
Input - wacom: register the input devices on top of the HID one
Input - wacom: remove usb dependency for siblings devices
Input - wacom: register power device at the HID level
Input - wacom: use hid_info instead of plain dev_info
Input - wacom: use in-kernel HID parser
Input - wacom: use hidinput_calc_abs_res instead of duplicating its
code
Input - wacom: remove field pktlen declaration in the list of devices
Input - wacom: keep wacom_ids ordered
Input - wacom: Move the USB (now hid) Wacom driver in drivers/hid
drivers/hid/Kconfig | 13 +
drivers/hid/Makefile | 3 +
drivers/hid/hid-core.c | 10 +-
drivers/hid/hid-wacom.c | 2 +-
drivers/hid/wacom.h | 138 +++
drivers/hid/wacom_sys.c | 1257 +++++++++++++++++++
drivers/hid/wacom_wac.c | 2534 ++++++++++++++++++++++++++++++++++++++
drivers/hid/wacom_wac.h | 169 +++
drivers/input/tablet/Kconfig | 16 -
drivers/input/tablet/Makefile | 3 -
drivers/input/tablet/wacom.h | 139 ---
drivers/input/tablet/wacom_sys.c | 1497 ----------------------
drivers/input/tablet/wacom_wac.c | 2485 -------------------------------------
drivers/input/tablet/wacom_wac.h | 165 ---
include/linux/hid.h | 5 +
15 files changed, 4129 insertions(+), 4307 deletions(-)
create mode 100644 drivers/hid/wacom.h
create mode 100644 drivers/hid/wacom_sys.c
create mode 100644 drivers/hid/wacom_wac.c
create mode 100644 drivers/hid/wacom_wac.h
delete mode 100644 drivers/input/tablet/wacom.h
delete mode 100644 drivers/input/tablet/wacom_sys.c
delete mode 100644 drivers/input/tablet/wacom_wac.c
delete mode 100644 drivers/input/tablet/wacom_wac.h
--
2.0.0
^ permalink raw reply
* [PATCH v2 02/23] Input - wacom: assign phys field from struct wacom into input_dev
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
This field was not used for 9 years, it is time to assign it.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 72b1724..7cd0886 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1127,6 +1127,7 @@ static int wacom_register_input(struct wacom *wacom)
}
input_dev->name = wacom_wac->name;
+ input_dev->phys = wacom->phys;
input_dev->dev.parent = &intf->dev;
input_dev->open = wacom_open;
input_dev->close = wacom_close;
--
2.0.0
^ permalink raw reply related
* [PATCH v2 04/23] Input - wacom: split out the pad device for Intuos/Cintiq
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
MSC_SERIAL can be safely dropped for pad input devices.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Ping Cheng <pingc@wacom.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_wac.c | 208 +++++++++++++++++++++++----------------
1 file changed, 122 insertions(+), 86 deletions(-)
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 11c7c4e..0be2c73 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -584,6 +584,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
/* pad packets. Works as a second tool and is always in prox */
if (data[0] == WACOM_REPORT_INTUOSPAD || data[0] == WACOM_REPORT_INTUOS5PAD) {
+ input = wacom->pad_input;
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
input_report_key(input, BTN_0, (data[2] & 0x01));
input_report_key(input, BTN_1, (data[3] & 0x01));
@@ -773,7 +774,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_MISC, 0);
}
}
- input_event(input, EV_MSC, MSC_SERIAL, 0xffffffff);
return 1;
}
@@ -1656,61 +1656,20 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case WACOM_24HD:
- __set_bit(BTN_A, input_dev->keybit);
- __set_bit(BTN_B, input_dev->keybit);
- __set_bit(BTN_C, input_dev->keybit);
- __set_bit(BTN_X, input_dev->keybit);
- __set_bit(BTN_Y, input_dev->keybit);
- __set_bit(BTN_Z, input_dev->keybit);
-
- for (i = 6; i < 10; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
- __set_bit(KEY_PROG1, input_dev->keybit);
- __set_bit(KEY_PROG2, input_dev->keybit);
- __set_bit(KEY_PROG3, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
/* fall through */
case DTK:
- for (i = 0; i < 6; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
wacom_setup_cintiq(wacom_wac);
break;
case WACOM_22HD:
- __set_bit(KEY_PROG1, input_dev->keybit);
- __set_bit(KEY_PROG2, input_dev->keybit);
- __set_bit(KEY_PROG3, input_dev->keybit);
- /* fall through */
-
case WACOM_21UX2:
- __set_bit(BTN_A, input_dev->keybit);
- __set_bit(BTN_B, input_dev->keybit);
- __set_bit(BTN_C, input_dev->keybit);
- __set_bit(BTN_X, input_dev->keybit);
- __set_bit(BTN_Y, input_dev->keybit);
- __set_bit(BTN_Z, input_dev->keybit);
- __set_bit(BTN_BASE, input_dev->keybit);
- __set_bit(BTN_BASE2, input_dev->keybit);
- /* fall through */
-
case WACOM_BEE:
- __set_bit(BTN_8, input_dev->keybit);
- __set_bit(BTN_9, input_dev->keybit);
- /* fall through */
-
case CINTIQ:
- for (i = 0; i < 8; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
- input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
- input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -1719,9 +1678,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case WACOM_13HD:
- for (i = 0; i < 9; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
wacom_setup_cintiq(wacom_wac);
@@ -1729,21 +1685,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS3:
case INTUOS3L:
- __set_bit(BTN_4, input_dev->keybit);
- __set_bit(BTN_5, input_dev->keybit);
- __set_bit(BTN_6, input_dev->keybit);
- __set_bit(BTN_7, input_dev->keybit);
-
- input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
- /* fall through */
-
case INTUOS3S:
- __set_bit(BTN_0, input_dev->keybit);
- __set_bit(BTN_1, input_dev->keybit);
- __set_bit(BTN_2, input_dev->keybit);
- __set_bit(BTN_3, input_dev->keybit);
-
- input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
/* fall through */
@@ -1757,20 +1699,11 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS5L:
case INTUOSPM:
case INTUOSPL:
- if (features->device_type == BTN_TOOL_PEN) {
- __set_bit(BTN_7, input_dev->keybit);
- __set_bit(BTN_8, input_dev->keybit);
- }
- /* fall through */
-
case INTUOS5S:
case INTUOSPS:
__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
if (features->device_type == BTN_TOOL_PEN) {
- for (i = 0; i < 7; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_DISTANCE, 0,
features->distance_max,
0, 0);
@@ -1791,14 +1724,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
case INTUOS4:
case INTUOS4L:
- __set_bit(BTN_7, input_dev->keybit);
- __set_bit(BTN_8, input_dev->keybit);
- /* fall through */
-
case INTUOS4S:
- for (i = 0; i < 7; i++)
- __set_bit(BTN_0 + i, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
wacom_setup_intuos(wacom_wac);
@@ -1908,17 +1834,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
break;
case CINTIQ_HYBRID:
- __set_bit(BTN_1, input_dev->keybit);
- __set_bit(BTN_2, input_dev->keybit);
- __set_bit(BTN_3, input_dev->keybit);
- __set_bit(BTN_4, input_dev->keybit);
-
- __set_bit(BTN_5, input_dev->keybit);
- __set_bit(BTN_6, input_dev->keybit);
- __set_bit(BTN_7, input_dev->keybit);
- __set_bit(BTN_8, input_dev->keybit);
- __set_bit(BTN_0, input_dev->keybit);
-
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -1932,6 +1847,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac)
{
struct wacom_features *features = &wacom_wac->features;
+ int i;
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
@@ -1943,6 +1859,126 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
switch (features->type) {
+ case WACOM_24HD:
+ __set_bit(BTN_A, input_dev->keybit);
+ __set_bit(BTN_B, input_dev->keybit);
+ __set_bit(BTN_C, input_dev->keybit);
+ __set_bit(BTN_X, input_dev->keybit);
+ __set_bit(BTN_Y, input_dev->keybit);
+ __set_bit(BTN_Z, input_dev->keybit);
+
+ for (i = 0; i < 10; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ __set_bit(KEY_PROG1, input_dev->keybit);
+ __set_bit(KEY_PROG2, input_dev->keybit);
+ __set_bit(KEY_PROG3, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+ break;
+
+ case DTK:
+ for (i = 0; i < 6; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ break;
+
+ case WACOM_22HD:
+ __set_bit(KEY_PROG1, input_dev->keybit);
+ __set_bit(KEY_PROG2, input_dev->keybit);
+ __set_bit(KEY_PROG3, input_dev->keybit);
+ /* fall through */
+
+ case WACOM_21UX2:
+ __set_bit(BTN_A, input_dev->keybit);
+ __set_bit(BTN_B, input_dev->keybit);
+ __set_bit(BTN_C, input_dev->keybit);
+ __set_bit(BTN_X, input_dev->keybit);
+ __set_bit(BTN_Y, input_dev->keybit);
+ __set_bit(BTN_Z, input_dev->keybit);
+ __set_bit(BTN_BASE, input_dev->keybit);
+ __set_bit(BTN_BASE2, input_dev->keybit);
+ /* fall through */
+
+ case WACOM_BEE:
+ __set_bit(BTN_8, input_dev->keybit);
+ __set_bit(BTN_9, input_dev->keybit);
+ /* fall through */
+
+ case CINTIQ:
+ for (i = 0; i < 8; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+ input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+ break;
+
+ case WACOM_13HD:
+ for (i = 0; i < 9; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ break;
+
+ case INTUOS3:
+ case INTUOS3L:
+ __set_bit(BTN_4, input_dev->keybit);
+ __set_bit(BTN_5, input_dev->keybit);
+ __set_bit(BTN_6, input_dev->keybit);
+ __set_bit(BTN_7, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+ /* fall through */
+
+ case INTUOS3S:
+ __set_bit(BTN_0, input_dev->keybit);
+ __set_bit(BTN_1, input_dev->keybit);
+ __set_bit(BTN_2, input_dev->keybit);
+ __set_bit(BTN_3, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+ break;
+
+ case INTUOS5:
+ case INTUOS5L:
+ case INTUOSPM:
+ case INTUOSPL:
+ __set_bit(BTN_7, input_dev->keybit);
+ __set_bit(BTN_8, input_dev->keybit);
+ /* fall through */
+
+ case INTUOS5S:
+ case INTUOSPS:
+ /* touch interface does not have the pad device */
+ if (features->device_type != BTN_TOOL_PEN)
+ return 1;
+
+ for (i = 0; i < 7; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ break;
+
+ case INTUOS4:
+ case INTUOS4L:
+ __set_bit(BTN_7, input_dev->keybit);
+ __set_bit(BTN_8, input_dev->keybit);
+ /* fall through */
+
+ case INTUOS4S:
+ for (i = 0; i < 7; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
+ break;
+
+ case CINTIQ_HYBRID:
+ for (i = 0; i < 9; i++)
+ __set_bit(BTN_0 + i, input_dev->keybit);
+
+ break;
+
default:
/* no pad supported */
return 1;
--
2.0.0
^ permalink raw reply related
* [PATCH v2 08/23] Input - wacom: split out the pad device for the wireless receiver
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
The Wireless Receiver should also behave in the same way than regular
USB devices.
To simplify the unregistering of the different devices,
wacom_unregister_inputs() is introduced.
For consistency, the function wacom_register_input() is renamed into
wacom_register_inputs().
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Ping Cheng <pingc@wacom.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 46 ++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b258485..dd0dbc2 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -1142,7 +1142,17 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom)
return input_dev;
}
-static int wacom_register_input(struct wacom *wacom)
+static void wacom_unregister_inputs(struct wacom *wacom)
+{
+ if (wacom->wacom_wac.input)
+ input_unregister_device(wacom->wacom_wac.input);
+ if (wacom->wacom_wac.pad_input)
+ input_unregister_device(wacom->wacom_wac.pad_input);
+ wacom->wacom_wac.input = NULL;
+ wacom->wacom_wac.pad_input = NULL;
+}
+
+static int wacom_register_inputs(struct wacom *wacom)
{
struct input_dev *input_dev, *pad_input_dev;
struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
@@ -1214,16 +1224,12 @@ static void wacom_wireless_work(struct work_struct *work)
/* Stylus interface */
wacom1 = usb_get_intfdata(usbdev->config->interface[1]);
wacom_wac1 = &(wacom1->wacom_wac);
- if (wacom_wac1->input)
- input_unregister_device(wacom_wac1->input);
- wacom_wac1->input = NULL;
+ wacom_unregister_inputs(wacom1);
/* Touch interface */
wacom2 = usb_get_intfdata(usbdev->config->interface[2]);
wacom_wac2 = &(wacom2->wacom_wac);
- if (wacom_wac2->input)
- input_unregister_device(wacom_wac2->input);
- wacom_wac2->input = NULL;
+ wacom_unregister_inputs(wacom2);
if (wacom_wac->pid == 0) {
dev_info(&wacom->intf->dev, "wireless tablet disconnected\n");
@@ -1253,9 +1259,11 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_wac1->features.device_type = BTN_TOOL_PEN;
snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen",
wacom_wac1->features.name);
+ snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
+ wacom_wac1->features.name);
wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
wacom_wac1->shared->type = wacom_wac1->features.type;
- error = wacom_register_input(wacom1);
+ error = wacom_register_inputs(wacom1);
if (error)
goto fail;
@@ -1273,7 +1281,9 @@ static void wacom_wireless_work(struct work_struct *work)
else
snprintf(wacom_wac2->name, WACOM_NAME_MAX,
"%s (WL) Pad",wacom_wac2->features.name);
- error = wacom_register_input(wacom2);
+ snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
+ "%s (WL) Pad", wacom_wac2->features.name);
+ error = wacom_register_inputs(wacom2);
if (error)
goto fail;
@@ -1290,15 +1300,8 @@ static void wacom_wireless_work(struct work_struct *work)
return;
fail:
- if (wacom_wac2->input) {
- input_unregister_device(wacom_wac2->input);
- wacom_wac2->input = NULL;
- }
-
- if (wacom_wac1->input) {
- input_unregister_device(wacom_wac1->input);
- wacom_wac1->input = NULL;
- }
+ wacom_unregister_inputs(wacom1);
+ wacom_unregister_inputs(wacom2);
return;
}
@@ -1444,7 +1447,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
goto fail4;
if (!(features->quirks & WACOM_QUIRK_NO_INPUT)) {
- error = wacom_register_input(wacom);
+ error = wacom_register_inputs(wacom);
if (error)
goto fail5;
}
@@ -1484,10 +1487,7 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_kill_urb(wacom->irq);
cancel_work_sync(&wacom->work);
- if (wacom->wacom_wac.input)
- input_unregister_device(wacom->wacom_wac.input);
- if (wacom->wacom_wac.pad_input)
- input_unregister_device(wacom->wacom_wac.pad_input);
+ wacom_unregister_inputs(wacom);
wacom_destroy_battery(wacom);
wacom_destroy_leds(wacom);
usb_free_urb(wacom->irq);
--
2.0.0
^ permalink raw reply related
* [PATCH v2 09/23] Input - wacom: include and use linux/hid.h
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
The current wacom code redefines constants that are already in linux/hid.h
This patch includes the official implementation and use it accross the code.
There is a conflict with HID_USAGE and others at the same level:
- in the wacom.ko implementation, those are the #define regarding the
value of the field in the report descriptor
- in the hid.h, those are bitmask
So add HDESC_ in their current definition.
Also, the struct hid_descriptor slightly differs from the linux/hid.h
point of view, so mark it as custom for this driver.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 53 +++++++++++++++++-----------------------
1 file changed, 22 insertions(+), 31 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index dd0dbc2..c34791e 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -13,28 +13,19 @@
#include "wacom_wac.h"
#include "wacom.h"
+#include <linux/hid.h>
/* defines to get HID report descriptor */
#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
-#define HID_USAGE_UNDEFINED 0x00
-#define HID_USAGE_PAGE 0x05
-#define HID_USAGE_PAGE_DIGITIZER 0x0d
-#define HID_USAGE_PAGE_DESKTOP 0x01
-#define HID_USAGE 0x09
-#define HID_USAGE_X ((HID_USAGE_PAGE_DESKTOP << 16) | 0x30)
-#define HID_USAGE_Y ((HID_USAGE_PAGE_DESKTOP << 16) | 0x31)
-#define HID_USAGE_PRESSURE ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x30)
-#define HID_USAGE_X_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3d)
-#define HID_USAGE_Y_TILT ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x3e)
-#define HID_USAGE_FINGER ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x22)
-#define HID_USAGE_STYLUS ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x20)
-#define HID_USAGE_CONTACTMAX ((HID_USAGE_PAGE_DIGITIZER << 16) | 0x55)
-#define HID_COLLECTION 0xa1
-#define HID_COLLECTION_LOGICAL 0x02
-#define HID_COLLECTION_END 0xc0
-
-struct hid_descriptor {
+#define HID_HDESC_USAGE_UNDEFINED 0x00
+#define HID_HDESC_USAGE_PAGE 0x05
+#define HID_HDESC_USAGE 0x09
+#define HID_HDESC_COLLECTION 0xa1
+#define HID_HDESC_COLLECTION_LOGICAL 0x02
+#define HID_HDESC_COLLECTION_END 0xc0
+
+struct wac_hid_descriptor {
struct usb_descriptor_header header;
__le16 bcdHID;
u8 bCountryCode;
@@ -301,7 +292,7 @@ static void wacom_retrieve_report_data(struct usb_interface *intf,
* this after returning from this function.
*/
static int wacom_parse_hid(struct usb_interface *intf,
- struct hid_descriptor *hid_desc,
+ struct wac_hid_descriptor *hid_desc,
struct wacom_features *features)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -334,14 +325,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
for (i = 0; i < hid_desc->wDescriptorLength; i++) {
switch (report[i]) {
- case HID_USAGE_PAGE:
+ case HID_HDESC_USAGE_PAGE:
page = report[i + 1];
i++;
break;
- case HID_USAGE:
+ case HID_HDESC_USAGE:
switch (page << 16 | report[i + 1]) {
- case HID_USAGE_X:
+ case HID_GD_X:
if (finger) {
features->device_type = BTN_TOOL_FINGER;
/* touch device at least supports one touch point */
@@ -420,7 +411,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
}
break;
- case HID_USAGE_Y:
+ case HID_GD_Y:
if (finger) {
switch (features->type) {
case TABLETPC2FG:
@@ -472,7 +463,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
}
break;
- case HID_USAGE_FINGER:
+ case HID_DG_FINGER:
finger = 1;
i++;
break;
@@ -482,19 +473,19 @@ static int wacom_parse_hid(struct usb_interface *intf,
* X/Y values and some cases of invalid Digitizer X/Y
* values commonly reported.
*/
- case HID_USAGE_STYLUS:
+ case HID_DG_STYLUS:
pen = 1;
i++;
break;
- case HID_USAGE_CONTACTMAX:
+ case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */
if (!features->touch_max)
wacom_retrieve_report_data(intf, features);
i++;
break;
- case HID_USAGE_PRESSURE:
+ case HID_DG_TIPPRESSURE:
if (pen) {
features->pressure_max =
get_unaligned_le16(&report[i + 3]);
@@ -504,15 +495,15 @@ static int wacom_parse_hid(struct usb_interface *intf,
}
break;
- case HID_COLLECTION_END:
+ case HID_HDESC_COLLECTION_END:
/* reset UsagePage and Finger */
finger = page = 0;
break;
- case HID_COLLECTION:
+ case HID_HDESC_COLLECTION:
i++;
switch (report[i]) {
- case HID_COLLECTION_LOGICAL:
+ case HID_HDESC_COLLECTION_LOGICAL:
i += wacom_parse_logical_collection(&report[i],
features);
break;
@@ -585,7 +576,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
{
int error = 0;
struct usb_host_interface *interface = intf->cur_altsetting;
- struct hid_descriptor *hid_desc;
+ struct wac_hid_descriptor *hid_desc;
/* default features */
features->device_type = BTN_TOOL_PEN;
--
2.0.0
^ permalink raw reply related
* [PATCH v2 11/23] Input - wacom: use hid communication instead of plain usb
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
Wacom.ko was a plain USB driver for a HID device. The communications
from/to the devices can actually be replaced with the HID API.
At the USB level, the reports are exactly the same.
This will allow to use uhid virtual devices instead of true USB devices.
This step is necessary to implement regression tests.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 81 ++++++++++++++++++----------------------
1 file changed, 36 insertions(+), 45 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 5ceeab6..120ab1b 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -34,11 +34,6 @@ struct wac_hid_descriptor {
__le16 wDescriptorLength;
} __attribute__ ((packed));
-/* defines to get/set USB message */
-#define USB_REQ_GET_REPORT 0x01
-#define USB_REQ_SET_REPORT 0x09
-
-#define WAC_HID_FEATURE_REPORT 0x03
#define WAC_MSG_RETRIES 5
#define WAC_CMD_LED_CONTROL 0x20
@@ -46,38 +41,27 @@ struct wac_hid_descriptor {
#define WAC_CMD_ICON_XFER 0x23
#define WAC_CMD_RETRIES 10
-static int wacom_get_report(struct usb_interface *intf, u8 type, u8 id,
+static int wacom_get_report(struct hid_device *hdev, u8 type, u8 id,
void *buf, size_t size, unsigned int retries)
{
- struct usb_device *dev = interface_to_usbdev(intf);
int retval;
do {
- retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_REPORT,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- (type << 8) + id,
- intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 100);
+ retval = hid_hw_raw_request(hdev, id, buf, size, type,
+ HID_REQ_GET_REPORT);
} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
return retval;
}
-static int wacom_set_report(struct usb_interface *intf, u8 type, u8 id,
+static int wacom_set_report(struct hid_device *hdev, u8 type, u8 id,
void *buf, size_t size, unsigned int retries)
{
- struct usb_device *dev = interface_to_usbdev(intf);
int retval;
do {
- retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
- USB_REQ_SET_REPORT,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- (type << 8) + id,
- intf->altsetting[0].desc.bInterfaceNumber,
- buf, size, 1000);
+ retval = hid_hw_raw_request(hdev, id, buf, size, type,
+ HID_REQ_SET_REPORT);
} while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries);
return retval;
@@ -188,7 +172,7 @@ static int wacom_parse_logical_collection(unsigned char *report,
return length;
}
-static void wacom_retrieve_report_data(struct usb_interface *intf,
+static void wacom_retrieve_report_data(struct hid_device *hdev,
struct wacom_features *features)
{
int result = 0;
@@ -198,7 +182,7 @@ static void wacom_retrieve_report_data(struct usb_interface *intf,
if (rep_data) {
rep_data[0] = 12;
- result = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
+ result = wacom_get_report(hdev, HID_FEATURE_REPORT,
rep_data[0], rep_data, 2,
WAC_MSG_RETRIES);
@@ -245,10 +229,12 @@ static void wacom_retrieve_report_data(struct usb_interface *intf,
* Intuos5 touch interface does not contain useful data. We deal with
* this after returning from this function.
*/
-static int wacom_parse_hid(struct usb_interface *intf,
+static int wacom_parse_hid(struct hid_device *hdev,
struct wac_hid_descriptor *hid_desc,
struct wacom_features *features)
{
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct usb_interface *intf = wacom->intf;
struct usb_device *dev = interface_to_usbdev(intf);
char limit = 0;
/* result has to be defined as int for some devices */
@@ -435,7 +421,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */
if (!features->touch_max)
- wacom_retrieve_report_data(intf, features);
+ wacom_retrieve_report_data(hdev, features);
i++;
break;
@@ -474,7 +460,8 @@ static int wacom_parse_hid(struct usb_interface *intf,
return result;
}
-static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode)
+static int wacom_set_device_mode(struct hid_device *hdev, int report_id,
+ int length, int mode)
{
unsigned char *rep_data;
int error = -ENOMEM, limit = 0;
@@ -487,10 +474,10 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
rep_data[0] = report_id;
rep_data[1] = mode;
- error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT,
+ error = wacom_set_report(hdev, HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
if (error >= 0)
- error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT,
+ error = wacom_get_report(hdev, HID_FEATURE_REPORT,
report_id, rep_data, length, 1);
} while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES);
@@ -506,29 +493,32 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int
* from the tablet, it is necessary to switch the tablet out of this
* mode and into one which sends the full range of tablet data.
*/
-static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features)
+static int wacom_query_tablet_data(struct hid_device *hdev,
+ struct wacom_features *features)
{
if (features->device_type == BTN_TOOL_FINGER) {
if (features->type > TABLETPC) {
/* MT Tablet PC touch */
- return wacom_set_device_mode(intf, 3, 4, 4);
+ return wacom_set_device_mode(hdev, 3, 4, 4);
}
else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
- return wacom_set_device_mode(intf, 18, 3, 2);
+ return wacom_set_device_mode(hdev, 18, 3, 2);
}
} else if (features->device_type == BTN_TOOL_PEN) {
if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
- return wacom_set_device_mode(intf, 2, 2, 2);
+ return wacom_set_device_mode(hdev, 2, 2, 2);
}
}
return 0;
}
-static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
+static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
struct wacom_features *features)
{
int error = 0;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct usb_interface *intf = wacom->intf;
struct usb_host_interface *interface = intf->cur_altsetting;
struct wac_hid_descriptor *hid_desc;
@@ -564,12 +554,12 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
error = usb_get_extra_descriptor(&interface->endpoint[0],
HID_DEVICET_REPORT, &hid_desc);
if (error) {
- dev_err(&intf->dev,
+ hid_err(hdev,
"can not retrieve extra class descriptor\n");
goto out;
}
}
- error = wacom_parse_hid(intf, hid_desc, features);
+ error = wacom_parse_hid(hdev, hid_desc, features);
out:
return error;
@@ -711,8 +701,8 @@ static int wacom_led_control(struct wacom *wacom)
buf[4] = wacom->led.img_lum;
}
- retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_LED_CONTROL,
- buf, 9, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
+ WAC_CMD_LED_CONTROL, buf, 9, WAC_CMD_RETRIES);
kfree(buf);
return retval;
@@ -730,8 +720,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im
/* Send 'start' command */
buf[0] = WAC_CMD_ICON_START;
buf[1] = 1;
- retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
- buf, 2, WAC_CMD_RETRIES);
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
+ WAC_CMD_ICON_START, buf, 2, WAC_CMD_RETRIES);
if (retval < 0)
goto out;
@@ -741,7 +731,8 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im
buf[2] = i;
memcpy(buf + 3, img + i * 256, 256);
- retval = wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_XFER,
+ retval = wacom_set_report(wacom->hdev, HID_FEATURE_REPORT,
+ WAC_CMD_ICON_XFER,
buf, 259, WAC_CMD_RETRIES);
if (retval < 0)
break;
@@ -750,7 +741,7 @@ static int wacom_led_putimage(struct wacom *wacom, int button_id, const void *im
/* Send 'stop' */
buf[0] = WAC_CMD_ICON_START;
buf[1] = 0;
- wacom_set_report(wacom->intf, 0x03, WAC_CMD_ICON_START,
+ wacom_set_report(wacom->hdev, HID_FEATURE_REPORT, WAC_CMD_ICON_START,
buf, 2, WAC_CMD_RETRIES);
out:
@@ -1331,7 +1322,7 @@ static int wacom_probe(struct hid_device *hdev,
wacom_set_default_phy(features);
/* Retrieve the physical and logical size for touch devices */
- error = wacom_retrieve_hid_descriptor(intf, features);
+ error = wacom_retrieve_hid_descriptor(hdev, features);
if (error)
goto fail1;
@@ -1395,7 +1386,7 @@ static int wacom_probe(struct hid_device *hdev,
}
/* Note that if query fails it is not a hard failure */
- wacom_query_tablet_data(intf, features);
+ wacom_query_tablet_data(hdev, features);
/* Regular HID work starts now */
error = hid_parse(hdev);
@@ -1452,7 +1443,7 @@ static int wacom_resume(struct hid_device *hdev)
mutex_lock(&wacom->lock);
/* switch to wacom mode first */
- wacom_query_tablet_data(wacom->intf, features);
+ wacom_query_tablet_data(hdev, features);
wacom_led_control(wacom);
mutex_unlock(&wacom->lock);
--
2.0.0
^ permalink raw reply related
* [PATCH v2 12/23] Input - wacom: use HID core to actually fetch the report descriptor
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
HID core already retrieves the report descritor. There is no need
to ask ourself for one.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 70 ++++++----------------------------------
1 file changed, 10 insertions(+), 60 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 120ab1b..2c0983b 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -15,9 +15,6 @@
#include "wacom.h"
#include <linux/hid.h>
-/* defines to get HID report descriptor */
-#define HID_DEVICET_HID (USB_TYPE_CLASS | 0x01)
-#define HID_DEVICET_REPORT (USB_TYPE_CLASS | 0x02)
#define HID_HDESC_USAGE_UNDEFINED 0x00
#define HID_HDESC_USAGE_PAGE 0x05
#define HID_HDESC_USAGE 0x09
@@ -25,15 +22,6 @@
#define HID_HDESC_COLLECTION_LOGICAL 0x02
#define HID_HDESC_COLLECTION_END 0xc0
-struct wac_hid_descriptor {
- struct usb_descriptor_header header;
- __le16 bcdHID;
- u8 bCountryCode;
- u8 bNumDescriptors;
- u8 bDescriptorType;
- __le16 wDescriptorLength;
-} __attribute__ ((packed));
-
#define WAC_MSG_RETRIES 5
#define WAC_CMD_LED_CONTROL 0x20
@@ -230,39 +218,14 @@ static void wacom_retrieve_report_data(struct hid_device *hdev,
* this after returning from this function.
*/
static int wacom_parse_hid(struct hid_device *hdev,
- struct wac_hid_descriptor *hid_desc,
struct wacom_features *features)
{
- struct wacom *wacom = hid_get_drvdata(hdev);
- struct usb_interface *intf = wacom->intf;
- struct usb_device *dev = interface_to_usbdev(intf);
- char limit = 0;
/* result has to be defined as int for some devices */
int result = 0, touch_max = 0;
int i = 0, page = 0, finger = 0, pen = 0;
- unsigned char *report;
+ unsigned char *report = hdev->rdesc;
- report = kzalloc(hid_desc->wDescriptorLength, GFP_KERNEL);
- if (!report)
- return -ENOMEM;
-
- /* retrive report descriptors */
- do {
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_DESCRIPTOR,
- USB_RECIP_INTERFACE | USB_DIR_IN,
- HID_DEVICET_REPORT << 8,
- intf->altsetting[0].desc.bInterfaceNumber, /* interface */
- report,
- hid_desc->wDescriptorLength,
- 5000); /* 5 secs */
- } while (result < 0 && limit++ < WAC_MSG_RETRIES);
-
- /* No need to parse the Descriptor. It isn't an error though */
- if (result < 0)
- goto out;
-
- for (i = 0; i < hid_desc->wDescriptorLength; i++) {
+ for (i = 0; i < hdev->rsize; i++) {
switch (report[i]) {
case HID_HDESC_USAGE_PAGE:
@@ -452,11 +415,9 @@ static int wacom_parse_hid(struct hid_device *hdev,
}
}
- out:
if (!features->touch_max && touch_max)
features->touch_max = touch_max;
result = 0;
- kfree(report);
return result;
}
@@ -519,8 +480,6 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
int error = 0;
struct wacom *wacom = hid_get_drvdata(hdev);
struct usb_interface *intf = wacom->intf;
- struct usb_host_interface *interface = intf->cur_altsetting;
- struct wac_hid_descriptor *hid_desc;
/* default features */
features->device_type = BTN_TOOL_PEN;
@@ -549,17 +508,7 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
goto out;
}
- error = usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc);
- if (error) {
- error = usb_get_extra_descriptor(&interface->endpoint[0],
- HID_DEVICET_REPORT, &hid_desc);
- if (error) {
- hid_err(hdev,
- "can not retrieve extra class descriptor\n");
- goto out;
- }
- }
- error = wacom_parse_hid(hdev, hid_desc, features);
+ error = wacom_parse_hid(hdev, features);
out:
return error;
@@ -1296,6 +1245,13 @@ static int wacom_probe(struct hid_device *hdev,
hid_set_drvdata(hdev, wacom);
wacom->hdev = hdev;
+ /* ask for the report descriptor to be loaded by HID */
+ error = hid_parse(hdev);
+ if (error) {
+ hid_err(hdev, "parse failed\n");
+ goto fail1;
+ }
+
wacom_wac = &wacom->wacom_wac;
wacom_wac->features = *((struct wacom_features *)id->driver_data);
features = &wacom_wac->features;
@@ -1389,12 +1345,6 @@ static int wacom_probe(struct hid_device *hdev,
wacom_query_tablet_data(hdev, features);
/* Regular HID work starts now */
- error = hid_parse(hdev);
- if (error) {
- hid_err(hdev, "parse failed\n");
- goto fail4;
- }
-
error = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
if (error) {
hid_err(hdev, "hw start failed\n");
--
2.0.0
^ permalink raw reply related
* [PATCH v2 16/23] Input - wacom: remove usb dependency for siblings devices
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
Wacom tablets can share different physical sensors on one physical device.
These are called siblings in the code. The current way of implementation
relies on the USB topology to be able to share data amongs those sensors.
We can replace the code to match a HID subsystem, without involving the USB
topology:
- the first probed sensor does not find any siblings in the list
wacom_udev_list, so it creates its own wacom_hdev_data with its own
struct hid_device
- the other sensor checks the current list of siblings in wacom_hdev_data,
and if there is a match, it associates itself to the matched device.
To be sure that we are not associating different sensors from different
physical devices, we also check for the phys path of the hid device which
contains the USB topology.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
---
changes in v2:
- use Jason's suggestion to find the sibblings devices
drivers/input/tablet/wacom_sys.c | 76 +++++++++++++++++++---------------------
1 file changed, 37 insertions(+), 39 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 2650443..8065bac 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -488,46 +488,48 @@ static int wacom_retrieve_hid_descriptor(struct hid_device *hdev,
return error;
}
-struct wacom_usbdev_data {
+struct wacom_hdev_data {
struct list_head list;
struct kref kref;
- struct usb_device *dev;
+ struct hid_device *dev;
struct wacom_shared shared;
};
static LIST_HEAD(wacom_udev_list);
static DEFINE_MUTEX(wacom_udev_list_lock);
-static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+static bool wacom_are_sibling(struct hid_device *hdev,
+ struct hid_device *sibling)
{
- int port1;
- struct usb_device *sibling;
-
- if (vendor == 0 && product == 0)
- return dev;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_features *features = &wacom->wacom_wac.features;
+ int vid = features->oVid;
+ int pid = features->oPid;
+ int n1,n2;
- if (dev->parent == NULL)
- return NULL;
+ if (vid == 0 && pid == 0) {
+ vid = hdev->vendor;
+ pid = hdev->product;
+ }
- usb_hub_for_each_child(dev->parent, port1, sibling) {
- struct usb_device_descriptor *d;
- if (sibling == NULL)
- continue;
+ if (vid != sibling->vendor || pid != sibling->product)
+ return false;
- d = &sibling->descriptor;
- if (d->idVendor == vendor && d->idProduct == product)
- return sibling;
- }
+ /* Compare the physical path. */
+ n1 = strrchr(hdev->phys, '.') - hdev->phys;
+ n2 = strrchr(sibling->phys, '.') - sibling->phys;
+ if (n1 != n2 || n1 <= 0 || n2 <= 0)
+ return false;
- return NULL;
+ return !strncmp(hdev->phys, sibling->phys, n1);
}
-static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
+static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
{
- struct wacom_usbdev_data *data;
+ struct wacom_hdev_data *data;
list_for_each_entry(data, &wacom_udev_list, list) {
- if (data->dev == dev) {
+ if (wacom_are_sibling(hdev, data->dev)) {
kref_get(&data->kref);
return data;
}
@@ -536,28 +538,29 @@ static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
return NULL;
}
-static int wacom_add_shared_data(struct wacom_wac *wacom,
- struct usb_device *dev)
+static int wacom_add_shared_data(struct hid_device *hdev)
{
- struct wacom_usbdev_data *data;
+ struct wacom *wacom = hid_get_drvdata(hdev);
+ struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+ struct wacom_hdev_data *data;
int retval = 0;
mutex_lock(&wacom_udev_list_lock);
- data = wacom_get_usbdev_data(dev);
+ data = wacom_get_hdev_data(hdev);
if (!data) {
- data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct wacom_hdev_data), GFP_KERNEL);
if (!data) {
retval = -ENOMEM;
goto out;
}
kref_init(&data->kref);
- data->dev = dev;
+ data->dev = hdev;
list_add_tail(&data->list, &wacom_udev_list);
}
- wacom->shared = &data->shared;
+ wacom_wac->shared = &data->shared;
out:
mutex_unlock(&wacom_udev_list_lock);
@@ -566,8 +569,8 @@ out:
static void wacom_release_shared_data(struct kref *kref)
{
- struct wacom_usbdev_data *data =
- container_of(kref, struct wacom_usbdev_data, kref);
+ struct wacom_hdev_data *data =
+ container_of(kref, struct wacom_hdev_data, kref);
mutex_lock(&wacom_udev_list_lock);
list_del(&data->list);
@@ -578,10 +581,10 @@ static void wacom_release_shared_data(struct kref *kref)
static void wacom_remove_shared_data(struct wacom_wac *wacom)
{
- struct wacom_usbdev_data *data;
+ struct wacom_hdev_data *data;
if (wacom->shared) {
- data = container_of(wacom->shared, struct wacom_usbdev_data, shared);
+ data = container_of(wacom->shared, struct wacom_hdev_data, shared);
kref_put(&data->kref, wacom_release_shared_data);
wacom->shared = NULL;
}
@@ -1308,8 +1311,6 @@ static int wacom_probe(struct hid_device *hdev,
"%s Pad", features->name);
if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
- struct usb_device *other_dev;
-
/* Append the device type to the name */
if (features->device_type != BTN_TOOL_FINGER)
strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX);
@@ -1318,10 +1319,7 @@ static int wacom_probe(struct hid_device *hdev,
else
strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX);
- other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
- if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
- other_dev = dev;
- error = wacom_add_shared_data(wacom_wac, other_dev);
+ error = wacom_add_shared_data(hdev);
if (error)
goto fail1;
}
--
2.0.0
^ permalink raw reply related
* [PATCH v2 17/23] Input - wacom: register power device at the HID level
From: Benjamin Tissoires @ 2014-07-15 18:45 UTC (permalink / raw)
To: Dmitry Torokhov, Jiri Kosina, Ping Cheng, Jason Gerecke
Cc: linux-kernel, linux-input
In-Reply-To: <1405449946-11515-1-git-send-email-benjamin.tissoires@redhat.com>
Use the HID device as the parent for the power device when dealing with
a wireless receiver.
Removes one more usb dependency and does not break user space.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Jason Gerecke <killertofu@gmail.com>
Tested-by: Jason Gerecke <killertofu@gmail.com>
---
no changes in v2
drivers/input/tablet/wacom_sys.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index 8065bac..b871059 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -966,12 +966,12 @@ static int wacom_initialize_battery(struct wacom *wacom)
wacom->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wacom->battery.use_for_apm = 0;
- error = power_supply_register(&wacom->usbdev->dev,
+ error = power_supply_register(&wacom->hdev->dev,
&wacom->battery);
if (!error)
power_supply_powers(&wacom->battery,
- &wacom->usbdev->dev);
+ &wacom->hdev->dev);
}
return error;
--
2.0.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox