* Re: [PATCH] Bluetooth: hidp: make sure input buffers are big enough
From: Marcel Holtmann @ 2013-12-20 13:36 UTC (permalink / raw)
To: David Herrmann
Cc: linux-input, Jiri Kosina,
linux-bluetooth@vger.kernel.org development, Gustavo F. Padovan
In-Reply-To: <1387451372-6881-1-git-send-email-dh.herrmann@gmail.com>
Hi David,
> HID core expects the input buffers to be at least of size 4096
> (HID_MAX_BUFFER_SIZE). Other sizes will result in buffer-overflows if an
> input-report is smaller than advertised. We could, like i2c, compute the
> biggest report-size instead of using HID_MAX_BUFFER_SIZE, but this will
> blow up if report-descriptors are changed after ->start() has been called.
> So lets be safe and just use the biggest buffer we have.
>
> Note that this adds an additional copy to the HIDP input path. If there is
> a way to make sure the skb-buf is big enough, we should use that instead.
>
> The best way would be to make hid-core honor the @size argument, though,
> that sounds easier than it is. So lets just fix the buffer-overflows for
> now and afterwards look for a faster way for all transport drivers.
>
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
> ---
> Hi
>
> Any ideas how to improve this patch? I'd like to avoid the extra copy but I have
> no clue how the skb stuff works exactly.
the buffers are coming straight from L2CAP. They might come in fragments. We have to reassemble them and while there are large packets for sure, we rather not want to allocate 4096 for every reassembled packet to make HID happy.
I am not super familiar with the underlying memory management of SKBs, but I assume they use slices of some sort internally. So uses large SKBs for 20 byte HID report will cause an issue with all other protocols running on top of L2CAP>
> I also haven't figured out a nice way to make HID-core honor the "size"
> parameter. hid-input depends on getting the whole input-report.
I think this needs clearly fixing.
> Comments welcome!
> David
>
> net/bluetooth/hidp/core.c | 16 ++++++++++++++--
> net/bluetooth/hidp/hidp.h | 4 ++++
> 2 files changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
> index 292e619..d9fb934 100644
> --- a/net/bluetooth/hidp/core.c
> +++ b/net/bluetooth/hidp/core.c
> @@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session)
> del_timer(&session->timer);
> }
>
> +static void hidp_process_report(struct hidp_session *session,
> + int type, const u8 *data, int len, int intr)
> +{
> + if (len > HID_MAX_BUFFER_SIZE)
> + len = HID_MAX_BUFFER_SIZE;
> +
> + memcpy(session->input_buf, data, len);
> + hid_input_report(session->hid, type, session->input_buf, len, intr);
> +}
> +
> static void hidp_process_handshake(struct hidp_session *session,
> unsigned char param)
> {
> @@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
> hidp_input_report(session, skb);
>
> if (session->hid)
> - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
> + hidp_process_report(session, HID_INPUT_REPORT,
> + skb->data, skb->len, 0);
> break;
>
> case HIDP_DATA_RTYPE_OTHER:
> @@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session,
> hidp_input_report(session, skb);
>
> if (session->hid) {
> - hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
> + hidp_process_report(session, HID_INPUT_REPORT,
> + skb->data, skb->len, 1);
> BT_DBG("report len %d", skb->len);
> }
> } else {
> diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
> index ab52414..8798492 100644
> --- a/net/bluetooth/hidp/hidp.h
> +++ b/net/bluetooth/hidp/hidp.h
> @@ -24,6 +24,7 @@
> #define __HIDP_H
>
> #include <linux/types.h>
> +#include <linux/hid.h>
> #include <linux/kref.h>
> #include <net/bluetooth/bluetooth.h>
> #include <net/bluetooth/l2cap.h>
> @@ -179,6 +180,9 @@ struct hidp_session {
>
> /* Used in hidp_output_raw_report() */
> int output_report_success; /* boolean */
> +
> + /* temporary input buffer */
> + u8 input_buf[HID_MAX_BUFFER_SIZE];
> };
The report does not need any specific alignment?
Regards
Marcel
^ permalink raw reply
* Re: [PATCH v4 1/1] Input: Improve the performance of alps v5-protocol's touchpad
From: Tommy Will @ 2013-12-20 9:35 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Kevin Cernekee, david turvene, linux-input, Niels de Vos,
Yunkang Tang
In-Reply-To: <CA+F6ckOSfTed-0cVYgNdv6k3=NuE1CQcwTHT51KM0p9Zd+0TKQ@mail.gmail.com>
Hi Dmitry,
Could you please share me your opinion of below idea?
If it's acceptable, I'd prepare a new patch that including both below
update and previous Kevin's suggestions.
Thanks !
Best Regards,
Tommy
2013/12/2 Tommy Will <tommywill2011@gmail.com>:
> Hi Dmitry,
>
> I'm suddenly aware that change like below would be better.
> Do you think so?
>
> { { 0x73, 0x03, 0x50 }, 0x0d, ALPS_PROTO_V5, 0xc8, 0xc8, 0 }
> => { { 0x73, 0x03, 0x50 }, 0x0d, ALPS_PROTO_V5, 0xc8, 0xd8, 0 }
>
> Thanks
> --
> Best Regards,
> Tommy
>
>
> 2013/12/2 Tommy Will <tommywill2011@gmail.com>:
>> Hi Dmitry,
>>
>> Thanks for your review.
>>
>> 2013/12/2 Dmitry Torokhov <dmitry.torokhov@gmail.com>:
>>
>>>> + /* Ignore stick point data */
>>>> + if (packet[0] == 0xD8)
>>>> + return;
>>
>>> Why are we ignoring trackstick data? If there Dolphin models with
>>> tracksticks that would basically "break" the device for users compared
>>> withe the emulated Explorer PS/2 mode.
>>
>> I'm sorry, I think I used the wrong comment here...
>> Use comment /* Check if it's an valid touchpad packet */ would be better
>>
>> From the V5's spec, "0xC8" is the checkmask for 6byte Raw mode and
>> 0x10 is the mask for trackpoint's / touchpad's packet.
>> So, 0xC8 means current packet is from touchpad and 0xD8 for trackpoint.
>> In current source code, what I wanted to do is just add a protection
>> logic to double check if it's a valid touchpad packet.
>>
>> About your concern, I think there would be no problem because:
>> 1) In initialization, we did not initialize trackpoint device as Raw
>> mode and it should always report 3Byte-packet. And in the first of
>> alps_process_byte(), 3byte packet would be processed separately.
>> 2) I checked with my Japanese colleague and in fact, there is no V5
>> device with trackpoint + touchpad in the world, although V5's spec
>> designed the case of trackpoint's packet.
>>
>> Thanks
>> --
>> Best Regards,
>> Tommy
^ permalink raw reply
* [PATCH 1/3] mkbp: Fix problems with backslash
From: Doug Anderson @ 2013-12-19 22:36 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Simon Glass, Samuel Ortiz, Olof Johansson, Kukjin Kim,
Doug Anderson, Vincent Palatin, Luigi Semenzato, linux-input,
linux-kernel
The mkbp code (post 3.4) has an issue where it can't deal with two
keys on the keyboard having the same keycode. When this happens it
will get confused about whether the key is down or up and will cause
some screwy behavior.
We need to have two keys on the keyboard with the same keycode for UK
keyboards. Specifically:
* On the US keyboard the backslash key (above enter) is r3 c11 and is
supposed to be reported as BACKSLASH.
* On the UK keyboard the # key (left of enter) is r4 c10 and is
supposed to be reported as BACKSLASH.
* On the UK keyboard the \ key (left of Z) is r2 c7 and is supposed to
be reported as KEY_102ND.
The above may be crazy, but that's how it's supposed to work so we
need to handle two KEY_BACKSLASH keycodes. Luckily this is easy to
handle.
Signed-off-by: Doug Anderson <dianders@chromium.org>
(cherry picked from commit 3c56a5a6c1c69306371a4d5f37762044c87e4216)
---
drivers/input/keyboard/cros_ec_keyb.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 7e8b0a5..65f6e52 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -38,6 +38,7 @@
* @row_shift: log2 or number of rows, rounded up
* @keymap_data: Matrix keymap data used to convert to keyscan values
* @ghost_filter: true to enable the matrix key-ghosting filter
+ * @old_kb_state: bitmap of keys pressed last scan
* @dev: Device pointer
* @idev: Input device
* @ec: Top level ChromeOS device to use to talk to EC
@@ -49,6 +50,7 @@ struct cros_ec_keyb {
int row_shift;
const struct matrix_keymap_data *keymap_data;
bool ghost_filter;
+ uint8_t *old_kb_state;
struct device *dev;
struct input_dev *idev;
@@ -135,6 +137,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
struct input_dev *idev = ckdev->idev;
int col, row;
int new_state;
+ int old_state;
int num_cols;
num_cols = len;
@@ -157,7 +160,8 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
code = keycodes[pos];
new_state = kb_state[col] & (1 << row);
- if (!!new_state != test_bit(code, idev->key)) {
+ old_state = ckdev->old_kb_state[col] & (1 << row);
+ if (new_state != old_state) {
dev_dbg(ckdev->dev,
"changed: [r%d c%d]: byte %02x\n",
row, col, new_state);
@@ -165,6 +169,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
input_report_key(idev, code, new_state);
}
}
+ ckdev->old_kb_state[col] = kb_state[col];
}
input_sync(ckdev->idev);
}
@@ -226,6 +231,9 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
&ckdev->cols);
if (err)
return err;
+ ckdev->old_kb_state = devm_kzalloc(&pdev->dev, ckdev->cols, GFP_KERNEL);
+ if (!ckdev->old_kb_state)
+ return -ENOMEM;
idev = devm_input_allocate_device(&pdev->dev);
if (!idev)
--
1.8.5.1
^ permalink raw reply related
* Re: [PATCH 5/5] mfd: input: iio: ti_amm335x: Rework TSC/ADC synchronization
From: Zubair Lutfullah : @ 2013-12-19 19:01 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Lee Jones, Samuel Ortiz, Jonathan Cameron, Dmitry Torokhov,
Zubair Lutfullah, Felipe Balbi, linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1387466911-3732-6-git-send-email-bigeasy-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org>
On Thu, Dec 19, 2013 at 04:28:31PM +0100, Sebastian Andrzej Siewior wrote:
> The ADC driver always programs all possible ADC values and discards
> them except for the value IIO asked for. On the am335x-evm the driver
> programs four values and it takes 500us to gather them. Reducing the number
> of conversations down to the (required) one also reduces the busy loop down
> to 125us.
>
> This leads to another error, namely the FIFOCOUNT register is sometimes
> (like one out of 10 attempts) not updated in time leading to EBUSY.
> The next read has the FIFOCOUNT register updated.
> Checking for the ADCSTAT register for being idle isn't a good choice either.
> The problem is that if TSC is used at the same time, the HW completes the
> conversation for ADC *and* before the driver noticed it, the HW begins to
> perform a TSC conversation and so the driver never seen the HW idle. The
> next time we would have two values in the FIFO but since the driver reads
> everything we always see the current one.
> So instead of polling for the IDLE bit in ADCStatus register, we should
> check the FIFOCOUNT register. It should be one instead of zero because we
> request one value.
>
> This change in turn leads to another error. Sometimes if TSC & ADC are
> used together the TSC starts becoming interrupts even if nobody
> actually touched the touchscreen. The interrupts seem valid because TSC's
> FIFO is filled with values for each channel of the TSC. This condition stops
> after a few ADC reads but will occur again. Not good.
>
> On top of this (even without the changes I just mentioned) there is a ADC
> & TSC lockup condition which was reported to me by Jeff Lance including the
> following test case:
> A busy loop of "cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw"
> and a mug on touch screen. With this setup, the hardware will lockup after
> something between 20 minutes and it could take up to a couple of hours.
> During that lockup, the ADCSTAT register says 0x30 (or 0x70) which means
> STEP_ID = IDLE and FSM_BUSY = yes. That means the hardware says that it is
> idle and busy at the same time which is an invalid condition.
I knew about FSM messing up. But couldn't investigate thouroughly
and didn't want to rework so much while adding continuous mode.
Good work :)
>
> For all this reasons I decided to rework this TSC/ADC part and add a
> handshake / synchronization here:
> First the ADC signals that it needs the HW and writes a 0 mask into the
> SE register. The HW (if active) will complete the current conversation
> and become idle. The TSC driver will gather the values from the FIFO
> (woken up by an interrupt) and won't "enable" another conversation.
> Instead it will wake up the ADC driver which is already waiting. The ADC
> driver will start "its" conversation and once it is done, it will
> enable the TSC steps so the TSC will work again.
>
> After this rework I haven't observed the lockup so far. Plus the busy
> loop has been reduced from 500us to 125us.
>
> The continues-read mode remains unchanged.
For one-shot reading from ADC, the TSC is 'disabled' for that moment.
Ok. But for continuous mode, reading from ADC disables TSC for that long time?
If it doesn't disable the TSC, does that mean that this fix would
correct the one-shot read. But the continuous mode is still prone to the
FSM hanging up?
>
> diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
...
> @@ -329,34 +347,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
> unsigned int fifo1count, read, stepid;
> bool found = false;
> u32 step_en;
> - unsigned long timeout = jiffies + usecs_to_jiffies
> - (IDLE_TIMEOUT * adc_dev->channels);
> + unsigned long timeout;
>
> if (iio_buffer_enabled(indio_dev))
> return -EBUSY;
>
> - step_en = get_adc_step_mask(adc_dev);
> + step_en = get_adc_chan_step_mask(adc_dev, chan);
> + if (!step_en)
> + return -EINVAL;
> +
> + fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
> + while (fifo1count--)
> + tiadc_readl(adc_dev, REG_FIFO1);
> +
Would this flush be needed ideally?
Thanks
Zubair
^ permalink raw reply
* Re: [PATCH 5/5] mfd: input: iio: ti_amm335x: Rework TSC/ADC synchronization
From: Sebastian Andrzej Siewior @ 2013-12-19 18:53 UTC (permalink / raw)
To: Lee Jones
Cc: Samuel Ortiz, Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah,
Felipe Balbi, linux-iio, linux-input, linux-kernel
In-Reply-To: <20131219171823.GC16145@lee--X1>
On 12/19/2013 06:18 PM, Lee Jones wrote:
> Assuming nothing else has changed since the answers you gave me:
> Acked-by: Lee Jones <lee.jones@linaro.org>
>
> Once we have the remaining Acks I'll happily apply this patch-set.
Thank you.
Sebastian
^ permalink raw reply
* Re: [PATCH 5/5] mfd: input: iio: ti_amm335x: Rework TSC/ADC synchronization
From: Lee Jones @ 2013-12-19 17:18 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Samuel Ortiz, Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah,
Felipe Balbi, linux-iio, linux-input, linux-kernel
In-Reply-To: <1387466911-3732-6-git-send-email-bigeasy@linutronix.de>
On Thu, 19 Dec 2013, Sebastian Andrzej Siewior wrote:
> The ADC driver always programs all possible ADC values and discards
> them except for the value IIO asked for. On the am335x-evm the driver
> programs four values and it takes 500us to gather them. Reducing the number
> of conversations down to the (required) one also reduces the busy loop down
> to 125us.
>
> This leads to another error, namely the FIFOCOUNT register is sometimes
> (like one out of 10 attempts) not updated in time leading to EBUSY.
> The next read has the FIFOCOUNT register updated.
> Checking for the ADCSTAT register for being idle isn't a good choice either.
> The problem is that if TSC is used at the same time, the HW completes the
> conversation for ADC *and* before the driver noticed it, the HW begins to
> perform a TSC conversation and so the driver never seen the HW idle. The
> next time we would have two values in the FIFO but since the driver reads
> everything we always see the current one.
> So instead of polling for the IDLE bit in ADCStatus register, we should
> check the FIFOCOUNT register. It should be one instead of zero because we
> request one value.
>
> This change in turn leads to another error. Sometimes if TSC & ADC are
> used together the TSC starts becoming interrupts even if nobody
> actually touched the touchscreen. The interrupts seem valid because TSC's
> FIFO is filled with values for each channel of the TSC. This condition stops
> after a few ADC reads but will occur again. Not good.
>
> On top of this (even without the changes I just mentioned) there is a ADC
> & TSC lockup condition which was reported to me by Jeff Lance including the
> following test case:
> A busy loop of "cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw"
> and a mug on touch screen. With this setup, the hardware will lockup after
> something between 20 minutes and it could take up to a couple of hours.
> During that lockup, the ADCSTAT register says 0x30 (or 0x70) which means
> STEP_ID = IDLE and FSM_BUSY = yes. That means the hardware says that it is
> idle and busy at the same time which is an invalid condition.
>
> For all this reasons I decided to rework this TSC/ADC part and add a
> handshake / synchronization here:
> First the ADC signals that it needs the HW and writes a 0 mask into the
> SE register. The HW (if active) will complete the current conversation
> and become idle. The TSC driver will gather the values from the FIFO
> (woken up by an interrupt) and won't "enable" another conversation.
> Instead it will wake up the ADC driver which is already waiting. The ADC
> driver will start "its" conversation and once it is done, it will
> enable the TSC steps so the TSC will work again.
>
> After this rework I haven't observed the lockup so far. Plus the busy
> loop has been reduced from 500us to 125us.
>
> The continues-read mode remains unchanged.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> drivers/iio/adc/ti_am335x_adc.c | 64 ++++++++++++++++++++++++++----------
> drivers/mfd/ti_am335x_tscadc.c | 63 +++++++++++++++++++++++++++++------
> include/linux/mfd/ti_am335x_tscadc.h | 4 +++
Assuming nothing else has changed since the answers you gave me:
Acked-by: Lee Jones <lee.jones@linaro.org>
Once we have the remaining Acks I'll happily apply this patch-set.
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 2/5] mfd: ti_am335x_tscadc: Make am335x_tsc_se_update() local
From: Lee Jones @ 2013-12-19 17:16 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Samuel Ortiz, Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah,
Felipe Balbi, linux-iio, linux-input, linux-kernel
In-Reply-To: <1387466911-3732-3-git-send-email-bigeasy@linutronix.de>
On Thu, 19 Dec 2013, Sebastian Andrzej Siewior wrote:
> Since the "recent" changes, am335x_tsc_se_update() has no longer any
> users outside of this file so make it local.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
I'm pretty sure I Acked this already.
> ---
> drivers/mfd/ti_am335x_tscadc.c | 3 +--
> include/linux/mfd/ti_am335x_tscadc.h | 1 -
> 2 files changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
> index 88718ab..67d0eb4 100644
> --- a/drivers/mfd/ti_am335x_tscadc.c
> +++ b/drivers/mfd/ti_am335x_tscadc.c
> @@ -48,11 +48,10 @@ static const struct regmap_config tscadc_regmap_config = {
> .val_bits = 32,
> };
>
> -void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
> +static void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
> {
> tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
> }
> -EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
>
> void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
> {
> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
> index d498d98f..1fe7219 100644
> --- a/include/linux/mfd/ti_am335x_tscadc.h
> +++ b/include/linux/mfd/ti_am335x_tscadc.h
> @@ -176,7 +176,6 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
> return *tscadc_dev;
> }
>
> -void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc);
> void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
> void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: [PATCH] HID: hyperv: make sure input buffer is big enough
From: KY Srinivasan @ 2013-12-19 16:58 UTC (permalink / raw)
To: David Herrmann, linux-input@vger.kernel.org
Cc: Jiri Kosina, Dan Carpenter, Joseph Salisbury, Haiyang Zhang,
linux-kernel@vger.kernel.org
In-Reply-To: <1387452744-8860-1-git-send-email-dh.herrmann@gmail.com>
> -----Original Message-----
> From: David Herrmann [mailto:dh.herrmann@gmail.com]
> Sent: Thursday, December 19, 2013 3:32 AM
> To: linux-input@vger.kernel.org
> Cc: Jiri Kosina; Dan Carpenter; Joseph Salisbury; KY Srinivasan; Haiyang Zhang;
> linux-kernel@vger.kernel.org; David Herrmann
> Subject: [PATCH] HID: hyperv: make sure input buffer is big enough
>
> We need at least HID_MAX_BUFFER_SIZE (4096) bytes as input buffer. HID
> core depends on this as it requires every input report to be at least as
> big as advertised.
>
> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> ---
> Hi
>
> Same as for the HIDP patch, if there's a way to avoid the extra copy, please
> provide a better patch.
>
> Thanks
> David
>
> drivers/hid/hid-hyperv.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
> index 8fae6d1..c24908f 100644
> --- a/drivers/hid/hid-hyperv.c
> +++ b/drivers/hid/hid-hyperv.c
> @@ -157,6 +157,7 @@ struct mousevsc_dev {
> u32 report_desc_size;
> struct hv_input_dev_info hid_dev_info;
> struct hid_device *hid_device;
> + u8 input_buf[HID_MAX_BUFFER_SIZE];
> };
>
>
> @@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device
> *device,
> struct synthhid_msg *hid_msg;
> struct mousevsc_dev *input_dev = hv_get_drvdata(device);
> struct synthhid_input_report *input_report;
> + size_t len;
>
> pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
> (packet->offset8 << 3));
> @@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device
> *device,
> (struct synthhid_input_report *)pipe_msg->data;
> if (!input_dev->init_complete)
> break;
> - hid_input_report(input_dev->hid_device,
> - HID_INPUT_REPORT, input_report->buffer,
> - input_report->header.size, 1);
> +
> + len = min(input_report->header.size,
> + (u32)sizeof(input_dev->input_buf));
> + memcpy(input_dev->input_buf, input_report->buffer, len);
> + hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
> + input_dev->input_buf, len, 1);
> break;
> default:
> pr_err("unsupported hid msg type - type %d len %d",
> --
> 1.8.5.1
^ permalink raw reply
* Re: [PATCH] HID: input: fix input sysfs path for hid devices
From: David Herrmann @ 2013-12-19 16:33 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Benjamin Tissoires, Jiri Kosina, open list:HID CORE LAYER,
linux-kernel
In-Reply-To: <1387469113-4129-1-git-send-email-benjamin.tissoires@redhat.com>
Hi
On Thu, Dec 19, 2013 at 5:05 PM, Benjamin Tissoires
<benjamin.tissoires@redhat.com> wrote:
> we used to set the parent of the input device as the parent of
> the hid bus. This was introduced when we created hid as a real bus, and
> to keep backward compatibility. Now, it's time to proper set the parent
> so that sysfs has an idea of which input device is attached to
> which hid device.
>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>
> Hi Jiri,
>
> well, the regression test did not showed anything bad, and a look at the hid
> drivers also showed that no drivers should be armed by that.
>
> I think this is valuable because it will give a better understanding of the
> actual mapping hardware/inputs. Like a touchscreen with pen + touch will have
> the same hid parent, and I expect X/Wayland to be able to detect this at some
> point to keep the mapping correctly between the two input devices and the screen.
>
> I also need that for hid-replay, so that I can be sure which input is attached
> to which uhid device, and give up the heuristics I currently use.
I was just wondering where we have multiple HID devices on a single
parent, but yeah, uhid is a good example. I actually have no
objections to this patch and it looks fine. But I cannot tell whether
anyone relies on this.
I'd say we should give it a try.
David
> Cheers,
> Benjamin
>
> drivers/hid/hid-input.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index d97f232..d50e731 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -1279,7 +1279,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
> input_dev->id.vendor = hid->vendor;
> input_dev->id.product = hid->product;
> input_dev->id.version = hid->version;
> - input_dev->dev.parent = hid->dev.parent;
> + input_dev->dev.parent = &hid->dev;
> hidinput->input = input_dev;
> list_add_tail(&hidinput->list, &hid->inputs);
>
> --
> 1.8.3.1
>
^ permalink raw reply
* [patch 3/3] HID: multitouch: add support of other generic collections in hid-mt
From: Benjamin Tissoires @ 2013-12-19 16:23 UTC (permalink / raw)
To: Benjamin Tissoires, Jiri Kosina, Edel Maks, Henrik Rydberg,
linux-input, linux-kernel
In-Reply-To: <1387470191-9725-1-git-send-email-benjamin.tissoires@redhat.com>
The ANTEC Touch Pad is a device which can switch from a multitouch
touchpad to a mouse. It thus presents several generic collections which
are currently ignored by hid-multitouch. Enable them by using the generic
protocol. Adding also a suffix for them depending on their application.
Reported-by: Edel Maks <edelmaks@gmail.com>
Tested-by: Edel Maks <edelmaks@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/hid-ids.h | 3 +++
drivers/hid/hid-multitouch.c | 43 ++++++++++++++++++++++++++++++++++++++++---
include/linux/hid.h | 3 +++
3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 2bf397f..4221494 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -67,6 +67,9 @@
#define USB_VENDOR_ID_ALPS 0x0433
#define USB_DEVICE_ID_IBM_GAMEPAD 0x1101
+#define USB_VENDOR_ID_ANTON 0x1130
+#define USB_DEVICE_ID_ANTON_TOUCH_PAD 0x3101
+
#define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 4dd6c6c..502e5bb 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -84,6 +84,7 @@ struct mt_class {
__s32 sn_pressure; /* Signal/noise ratio for pressure events */
__u8 maxcontacts;
bool is_indirect; /* true for touchpads */
+ bool export_all_inputs; /* do not ignore mouse, keyboards, etc... */
};
struct mt_fields {
@@ -217,6 +218,7 @@ static struct mt_protocol mt_protocol_ignore = { 0 };
#define MT_CLS_FLATFROG 0x0107
#define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
+#define MT_CLS_ANTON_TP 0x010a
#define MT_DEFAULT_MAXCONTACT 10
#define MT_MAX_MAXCONTACT 250
@@ -329,13 +331,18 @@ static struct mt_class mt_classes[] = {
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_SLOT_IS_CONTACTID
},
-
{ .name = MT_CLS_FLATFROG,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_NO_AREA,
.sn_move = 2048,
.maxcontacts = 40,
},
+ { .name = MT_CLS_ANTON_TP,
+ .quirks = MT_QUIRK_ALWAYS_VALID |
+ MT_QUIRK_CONTACT_CNT_ACCURATE,
+ .is_indirect = true,
+ .export_all_inputs = true,
+ },
{ }
};
@@ -846,10 +853,32 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct mt_device *td = hid_get_drvdata(hdev);
unsigned report_id = field->report->id;
+ if (td->mtclass.export_all_inputs) {
+ td->protocols[report_id] = mt_protocol_generic;
+ switch (field->application) {
+ case HID_GD_KEYPAD:
+ td->protocols[report_id].suffix = "Keypad";
+ break;
+ case HID_GD_MOUSE:
+ td->protocols[report_id].suffix = "Mouse";
+ break;
+ case HID_DG_TOUCHSCREEN:
+ td->protocols[report_id].suffix = "Touchscreen";
+ break;
+ case HID_GD_SYSTEM_CONTROL:
+ td->protocols[report_id].suffix = "System Control";
+ break;
+ case HID_CP_CONSUMER_CONTROL:
+ td->protocols[report_id].suffix = "Consumer Control";
+ break;
+ }
+ }
+
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
- if (field->application != HID_DG_TOUCHSCREEN &&
+ if (!td->mtclass.export_all_inputs &&
+ field->application != HID_DG_TOUCHSCREEN &&
field->application != HID_DG_PEN &&
field->application != HID_DG_TOUCHPAD)
td->protocols[report_id] = mt_protocol_ignore;
@@ -859,8 +888,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
else if (field->application == HID_DG_TOUCHSCREEN ||
field->application == HID_DG_PEN ||
- field->application == HID_DG_TOUCHPAD)
+ field->application == HID_DG_TOUCHPAD) {
td->protocols[report_id] = mt_protocol_touch;
+ if (td->mtclass.export_all_inputs)
+ td->protocols[report_id].suffix = "Touch";
+ }
if (td->protocols[report_id].input_mapping)
return td->protocols[report_id].input_mapping(hdev, hi,
@@ -1128,6 +1160,11 @@ static const struct hid_device_id mt_devices[] = {
MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
USB_DEVICE_ID_ACTIONSTAR_1011) },
+ /* Anton Touch Pad */
+ { .driver_data = MT_CLS_ANTON_TP,
+ MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
+ USB_DEVICE_ID_ANTON_TOUCH_PAD) },
+
/* Atmel panels */
{ .driver_data = MT_CLS_SERIAL,
MT_USB_DEVICE(USB_VENDOR_ID_ATMEL,
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 31b9d29..2b2041a 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -201,6 +201,7 @@ struct hid_item {
#define HID_GD_VBRZ 0x00010045
#define HID_GD_VNO 0x00010046
#define HID_GD_FEATURE 0x00010047
+#define HID_GD_SYSTEM_CONTROL 0x00010080
#define HID_GD_UP 0x00010090
#define HID_GD_DOWN 0x00010091
#define HID_GD_RIGHT 0x00010092
@@ -208,6 +209,8 @@ struct hid_item {
#define HID_DC_BATTERYSTRENGTH 0x00060020
+#define HID_CP_CONSUMER_CONTROL 0x000c0001
+
#define HID_DG_DIGITIZER 0x000d0001
#define HID_DG_PEN 0x000d0002
#define HID_DG_LIGHTPEN 0x000d0003
--
1.8.3.1
^ permalink raw reply related
* [PATCH 2/3] HID: multitouch: introduce mt_protocol_generic
From: Benjamin Tissoires @ 2013-12-19 16:23 UTC (permalink / raw)
To: Benjamin Tissoires, Jiri Kosina, Edel Maks, Henrik Rydberg,
linux-input, linux-kernel
In-Reply-To: <1387470191-9725-1-git-send-email-benjamin.tissoires@redhat.com>
most of the protocol callbacks used by the pen protocol are generic,
they just ask hid-input to treat the incoming data.
Introduce a generic protocol to avoid having to copy/paste the pens
callbacks for other kinds of input reports.
Tested-by: Edel Maks <edelmaks@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/hid-multitouch.c | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 1cdc21a..4dd6c6c 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -156,26 +156,36 @@ static struct mt_protocol mt_protocol_touch = {
.input_configured = mt_touch_input_configured,
};
-static int mt_pen_input_mapping(struct hid_device *hdev,
+static int mt_generic_input_mapping(struct hid_device *hdev,
struct hid_input *hi, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max);
-static int mt_pen_input_mapped(struct hid_device *hdev,
+static int mt_generic_input_mapped(struct hid_device *hdev,
struct hid_input *hi, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max);
-static int mt_pen_event(struct hid_device *hid,
+static int mt_generic_event(struct hid_device *hid,
struct hid_field *field, struct hid_usage *usage,
__s32 value);
-static void mt_pen_report(struct hid_device *hid,
+static void mt_generic_report(struct hid_device *hid,
struct hid_report *report);
+
+static struct mt_protocol mt_protocol_generic = {
+ .suffix = NULL,
+ .event = mt_generic_event,
+ .report = mt_generic_report,
+ .input_mapping = mt_generic_input_mapping,
+ .input_mapped = mt_generic_input_mapped,
+ .input_configured = NULL,
+};
+
static void mt_pen_input_configured(struct hid_device *hdev,
struct hid_input *hi);
static struct mt_protocol mt_protocol_pen = {
.suffix = "Pen",
- .event = mt_pen_event,
- .report = mt_pen_report,
- .input_mapping = mt_pen_input_mapping,
- .input_mapped = mt_pen_input_mapped,
+ .event = mt_generic_event,
+ .report = mt_generic_report,
+ .input_mapping = mt_generic_input_mapping,
+ .input_mapped = mt_generic_input_mapped,
.input_configured = mt_pen_input_configured,
};
@@ -422,28 +432,28 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
f->usages[f->length++] = usage->hid;
}
-static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- struct hid_field *field, struct hid_usage *usage,
- unsigned long **bit, int *max)
+static int mt_generic_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
{
return 0;
}
-static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- struct hid_field *field, struct hid_usage *usage,
- unsigned long **bit, int *max)
+static int mt_generic_input_mapped(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max)
{
return 0;
}
-static int mt_pen_event(struct hid_device *hid, struct hid_field *field,
+static int mt_generic_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
/* let hid-input handle it */
return 0;
}
-static void mt_pen_report(struct hid_device *hid, struct hid_report *report)
+static void mt_generic_report(struct hid_device *hid, struct hid_report *report)
{
struct hid_field *field = report->field[0];
--
1.8.3.1
^ permalink raw reply related
* [PATCH 1/3] HID: multitouch: switch to a callback system for handling events
From: Benjamin Tissoires @ 2013-12-19 16:23 UTC (permalink / raw)
To: Benjamin Tissoires, Jiri Kosina, Edel Maks, Henrik Rydberg,
linux-input, linux-kernel
In-Reply-To: <1387470191-9725-1-git-send-email-benjamin.tissoires@redhat.com>
In kernel v3.10, we added the support of pen in addition to touch because
some devices presents both pen and touch on the same HID device.
Now, we are seeing at least one device (ANTON Touch Pad) which presents
a multitouch collection and a mouse collection which are both valid.
Instead of adding a lot of ifs and messing up with the code, we can switch
to a callback system which allows to define in a better way each protocol
used by each input report.
Tested-by: Edel Maks <edelmaks@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/hid/hid-multitouch.c | 136 ++++++++++++++++++++++++++++++++-----------
1 file changed, 101 insertions(+), 35 deletions(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 1f0ba5c..1cdc21a 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -91,6 +91,21 @@ struct mt_fields {
unsigned int length;
};
+struct mt_protocol {
+ char *suffix;
+ int (*event)(struct hid_device *hdev, struct hid_field *field,
+ struct hid_usage *usage, __s32 value);
+ void (*report)(struct hid_device *hdev, struct hid_report *report);
+ int (*input_mapping)(struct hid_device *hdev,
+ struct hid_input *hidinput, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max);
+ int (*input_mapped)(struct hid_device *hdev,
+ struct hid_input *hidinput, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max);
+ void (*input_configured)(struct hid_device *hdev,
+ struct hid_input *hidinput);
+};
+
struct mt_device {
struct mt_slot curdata; /* placeholder of incoming data */
struct mt_class mtclass; /* our mt device class */
@@ -99,8 +114,7 @@ struct mt_device {
int cc_index; /* contact count field index in the report */
int cc_value_index; /* contact count value index in the field */
unsigned last_slot_field; /* the last field of a slot */
- unsigned mt_report_id; /* the report ID of the multitouch device */
- unsigned pen_report_id; /* the report ID of the pen device */
+ struct mt_protocol protocols[HID_MAX_IDS]; /* per-id callbacks */
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
__s16 inputmode_index; /* InputMode HID feature index in the report */
__s16 maxcontact_report_id; /* Maximum Contact Number HID feature,
@@ -119,6 +133,54 @@ struct mt_device {
static void mt_post_parse_default_settings(struct mt_device *td);
static void mt_post_parse(struct mt_device *td);
+static int mt_touch_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max);
+static int mt_touch_input_mapped(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max);
+static int mt_touch_event(struct hid_device *hid,
+ struct hid_field *field, struct hid_usage *usage,
+ __s32 value);
+static void mt_touch_report(struct hid_device *hid,
+ struct hid_report *report);
+static void mt_touch_input_configured(struct hid_device *hdev,
+ struct hid_input *hi);
+
+static struct mt_protocol mt_protocol_touch = {
+ .suffix = NULL,
+ .event = mt_touch_event,
+ .report = mt_touch_report,
+ .input_mapping = mt_touch_input_mapping,
+ .input_mapped = mt_touch_input_mapped,
+ .input_configured = mt_touch_input_configured,
+};
+
+static int mt_pen_input_mapping(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max);
+static int mt_pen_input_mapped(struct hid_device *hdev,
+ struct hid_input *hi, struct hid_field *field,
+ struct hid_usage *usage, unsigned long **bit, int *max);
+static int mt_pen_event(struct hid_device *hid,
+ struct hid_field *field, struct hid_usage *usage,
+ __s32 value);
+static void mt_pen_report(struct hid_device *hid,
+ struct hid_report *report);
+static void mt_pen_input_configured(struct hid_device *hdev,
+ struct hid_input *hi);
+
+static struct mt_protocol mt_protocol_pen = {
+ .suffix = "Pen",
+ .event = mt_pen_event,
+ .report = mt_pen_report,
+ .input_mapping = mt_pen_input_mapping,
+ .input_mapped = mt_pen_input_mapped,
+ .input_configured = mt_pen_input_configured,
+};
+
+static struct mt_protocol mt_protocol_ignore = { 0 };
+
/* classes of device behavior */
#define MT_CLS_DEFAULT 0x0001
@@ -364,10 +426,6 @@ static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- struct mt_device *td = hid_get_drvdata(hdev);
-
- td->pen_report_id = field->report->id;
-
return 0;
}
@@ -480,7 +538,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_DG_CONTACTID:
mt_store_field(usage, td, hi);
td->touches_by_report++;
- td->mt_report_id = field->report->id;
return 1;
case HID_DG_WIDTH:
hid_map_usage(hi, usage, bit, max,
@@ -776,57 +833,71 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
+ struct mt_device *td = hid_get_drvdata(hdev);
+ unsigned report_id = field->report->id;
+
/* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections
* such as Mouse that might have the same GenericDesktop usages. */
if (field->application != HID_DG_TOUCHSCREEN &&
field->application != HID_DG_PEN &&
field->application != HID_DG_TOUCHPAD)
- return -1;
+ td->protocols[report_id] = mt_protocol_ignore;
if (field->physical == HID_DG_STYLUS)
- return mt_pen_input_mapping(hdev, hi, field, usage, bit, max);
+ td->protocols[report_id] = mt_protocol_pen;
+
+ else if (field->application == HID_DG_TOUCHSCREEN ||
+ field->application == HID_DG_PEN ||
+ field->application == HID_DG_TOUCHPAD)
+ td->protocols[report_id] = mt_protocol_touch;
- return mt_touch_input_mapping(hdev, hi, field, usage, bit, max);
+ if (td->protocols[report_id].input_mapping)
+ return td->protocols[report_id].input_mapping(hdev, hi,
+ field, usage, bit, max);
+
+ /* ignore if no protocol is given */
+ return -1;
}
static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
- if (field->physical == HID_DG_STYLUS)
- return mt_pen_input_mapped(hdev, hi, field, usage, bit, max);
+ struct mt_device *td = hid_get_drvdata(hdev);
+ unsigned report_id = field->report->id;
+
+ if (td->protocols[report_id].input_mapped)
+ return td->protocols[report_id].input_mapped(hdev, hi, field,
+ usage, bit, max);
- return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
+ /* ignore if no protocol is given */
+ return -1;
}
static int mt_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct mt_device *td = hid_get_drvdata(hid);
+ unsigned report_id = field->report->id;
- if (field->report->id == td->mt_report_id)
- return mt_touch_event(hid, field, usage, value);
-
- if (field->report->id == td->pen_report_id)
- return mt_pen_event(hid, field, usage, value);
+ if (td->protocols[report_id].event)
+ return td->protocols[report_id].event(hid, field, usage, value);
- /* ignore other reports */
+ /* ignore if no protocol is given */
return 1;
}
static void mt_report(struct hid_device *hid, struct hid_report *report)
{
struct mt_device *td = hid_get_drvdata(hid);
+ unsigned report_id = report->id;
if (!(hid->claimed & HID_CLAIMED_INPUT))
return;
- if (report->id == td->mt_report_id)
- mt_touch_report(hid, report);
-
- if (report->id == td->pen_report_id)
- mt_pen_report(hid, report);
+ if (td->protocols[report_id].report)
+ return td->protocols[report_id].report(hid, report);
}
static void mt_set_input_mode(struct hid_device *hdev)
@@ -906,17 +977,14 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct mt_device *td = hid_get_drvdata(hdev);
char *name;
- const char *suffix = NULL;
-
- if (hi->report->id == td->mt_report_id)
- mt_touch_input_configured(hdev, hi);
+ const char *suffix;
+ unsigned report_id = hi->report->id;
- if (hi->report->field[0]->physical == HID_DG_STYLUS) {
- suffix = "Pen";
- mt_pen_input_configured(hdev, hi);
- }
+ if (td->protocols[report_id].input_configured)
+ td->protocols[report_id].input_configured(hdev, hi);
- if (suffix) {
+ if (td->protocols[report_id].suffix) {
+ suffix = td->protocols[report_id].suffix;
name = devm_kzalloc(&hi->input->dev,
strlen(hdev->name) + strlen(suffix) + 2,
GFP_KERNEL);
@@ -974,8 +1042,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
td->inputmode = -1;
td->maxcontact_report_id = -1;
td->cc_index = -1;
- td->mt_report_id = -1;
- td->pen_report_id = -1;
hid_set_drvdata(hdev, td);
td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
--
1.8.3.1
^ permalink raw reply related
* [PATCH 0/3] Change in handling different input device in hid-multitouch
From: Benjamin Tissoires @ 2013-12-19 16:23 UTC (permalink / raw)
To: Benjamin Tissoires, Jiri Kosina, Edel Maks, Henrik Rydberg,
linux-input, linux-kernel
Hi guys,
well, I have been reported a brand new device, which, as always presents a new
way of dealing with multitouch and mouse and soever.
The new fancy stuff is capable to report mouse and touch, whereas by default,
we consider mouse as garbage.
if you want to get an idea of the device:
http://www.pearl.de/a-PX2569-1002.shtml
So, we need to add a quirk for it, as usual, but I also cleaned up the way we
treat the different input devices within the driver. I expect some bikesheding
here, so I fire this right now until it's too late for 3.14 or 3.15 :)
Cheers,
Benjamin
Benjamin Tissoires (3):
HID: multitouch: switch to a callback system for handling events
HID: multitouch: introduce mt_protocol_generic
HID: multitouch: add support of other generic collections in hid-mt
drivers/hid/hid-ids.h | 3 +
drivers/hid/hid-multitouch.c | 205 +++++++++++++++++++++++++++++++++----------
include/linux/hid.h | 3 +
3 files changed, 166 insertions(+), 45 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH] HID: input: fix input sysfs path for hid devices
From: Benjamin Tissoires @ 2013-12-19 16:05 UTC (permalink / raw)
To: Benjamin Tissoires, Jiri Kosina, David Herrmann, linux-input,
linux-kernel
we used to set the parent of the input device as the parent of
the hid bus. This was introduced when we created hid as a real bus, and
to keep backward compatibility. Now, it's time to proper set the parent
so that sysfs has an idea of which input device is attached to
which hid device.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
Hi Jiri,
well, the regression test did not showed anything bad, and a look at the hid
drivers also showed that no drivers should be armed by that.
I think this is valuable because it will give a better understanding of the
actual mapping hardware/inputs. Like a touchscreen with pen + touch will have
the same hid parent, and I expect X/Wayland to be able to detect this at some
point to keep the mapping correctly between the two input devices and the screen.
I also need that for hid-replay, so that I can be sure which input is attached
to which uhid device, and give up the heuristics I currently use.
Cheers,
Benjamin
drivers/hid/hid-input.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d97f232..d50e731 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1279,7 +1279,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
input_dev->id.vendor = hid->vendor;
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
- input_dev->dev.parent = hid->dev.parent;
+ input_dev->dev.parent = &hid->dev;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
--
1.8.3.1
^ permalink raw reply related
* [PATCH 5/5] mfd: input: iio: ti_amm335x: Rework TSC/ADC synchronization
From: Sebastian Andrzej Siewior @ 2013-12-19 15:28 UTC (permalink / raw)
To: Lee Jones, Samuel Ortiz
Cc: Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah, Felipe Balbi,
linux-iio, linux-input, linux-kernel, Sebastian Andrzej Siewior
In-Reply-To: <1387466911-3732-1-git-send-email-bigeasy@linutronix.de>
The ADC driver always programs all possible ADC values and discards
them except for the value IIO asked for. On the am335x-evm the driver
programs four values and it takes 500us to gather them. Reducing the number
of conversations down to the (required) one also reduces the busy loop down
to 125us.
This leads to another error, namely the FIFOCOUNT register is sometimes
(like one out of 10 attempts) not updated in time leading to EBUSY.
The next read has the FIFOCOUNT register updated.
Checking for the ADCSTAT register for being idle isn't a good choice either.
The problem is that if TSC is used at the same time, the HW completes the
conversation for ADC *and* before the driver noticed it, the HW begins to
perform a TSC conversation and so the driver never seen the HW idle. The
next time we would have two values in the FIFO but since the driver reads
everything we always see the current one.
So instead of polling for the IDLE bit in ADCStatus register, we should
check the FIFOCOUNT register. It should be one instead of zero because we
request one value.
This change in turn leads to another error. Sometimes if TSC & ADC are
used together the TSC starts becoming interrupts even if nobody
actually touched the touchscreen. The interrupts seem valid because TSC's
FIFO is filled with values for each channel of the TSC. This condition stops
after a few ADC reads but will occur again. Not good.
On top of this (even without the changes I just mentioned) there is a ADC
& TSC lockup condition which was reported to me by Jeff Lance including the
following test case:
A busy loop of "cat /sys/bus/iio/devices/iio\:device0/in_voltage4_raw"
and a mug on touch screen. With this setup, the hardware will lockup after
something between 20 minutes and it could take up to a couple of hours.
During that lockup, the ADCSTAT register says 0x30 (or 0x70) which means
STEP_ID = IDLE and FSM_BUSY = yes. That means the hardware says that it is
idle and busy at the same time which is an invalid condition.
For all this reasons I decided to rework this TSC/ADC part and add a
handshake / synchronization here:
First the ADC signals that it needs the HW and writes a 0 mask into the
SE register. The HW (if active) will complete the current conversation
and become idle. The TSC driver will gather the values from the FIFO
(woken up by an interrupt) and won't "enable" another conversation.
Instead it will wake up the ADC driver which is already waiting. The ADC
driver will start "its" conversation and once it is done, it will
enable the TSC steps so the TSC will work again.
After this rework I haven't observed the lockup so far. Plus the busy
loop has been reduced from 500us to 125us.
The continues-read mode remains unchanged.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/iio/adc/ti_am335x_adc.c | 64 ++++++++++++++++++++++++++----------
drivers/mfd/ti_am335x_tscadc.c | 63 +++++++++++++++++++++++++++++------
include/linux/mfd/ti_am335x_tscadc.h | 4 +++
3 files changed, 103 insertions(+), 28 deletions(-)
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 6822b9f..31e786e 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -60,6 +60,24 @@ static u32 get_adc_step_mask(struct tiadc_device *adc_dev)
return step_en;
}
+static u32 get_adc_chan_step_mask(struct tiadc_device *adc_dev,
+ struct iio_chan_spec const *chan)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adc_dev->channel_step); i++) {
+ if (chan->channel == adc_dev->channel_line[i]) {
+ u32 step;
+
+ step = adc_dev->channel_step[i];
+ /* +1 for the charger */
+ return 1 << (step + 1);
+ }
+ }
+ WARN_ON(1);
+ return 0;
+}
+
static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan)
{
return 1 << adc_dev->channel_step[chan];
@@ -329,34 +347,43 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
unsigned int fifo1count, read, stepid;
bool found = false;
u32 step_en;
- unsigned long timeout = jiffies + usecs_to_jiffies
- (IDLE_TIMEOUT * adc_dev->channels);
+ unsigned long timeout;
if (iio_buffer_enabled(indio_dev))
return -EBUSY;
- step_en = get_adc_step_mask(adc_dev);
+ step_en = get_adc_chan_step_mask(adc_dev, chan);
+ if (!step_en)
+ return -EINVAL;
+
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ while (fifo1count--)
+ tiadc_readl(adc_dev, REG_FIFO1);
+
am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
- /* Wait for ADC sequencer to complete sampling */
- while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
- if (time_after(jiffies, timeout))
+ timeout = jiffies + usecs_to_jiffies
+ (IDLE_TIMEOUT * adc_dev->channels);
+ /* Wait for Fifo threshold interrupt */
+ while (1) {
+ fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
+ if (fifo1count)
+ break;
+
+ if (time_after(jiffies, timeout)) {
+ am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
return -EAGAIN;
+ }
}
map_val = chan->channel + TOTAL_CHANNELS;
/*
- * When the sub-system is first enabled,
- * the sequencer will always start with the
- * lowest step (1) and continue until step (16).
- * For ex: If we have enabled 4 ADC channels and
- * currently use only 1 out of them, the
- * sequencer still configures all the 4 steps,
- * leading to 3 unwanted data.
- * Hence we need to flush out this data.
+ * We check the complete FIFO. We programmed just one entry but in case
+ * something went wrong we left empty handed (-EAGAIN previously) and
+ * then the value apeared somehow in the FIFO we would have two entries.
+ * Therefore we read every item and keep only the latest version of the
+ * requested channel.
*/
-
- fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
for (i = 0; i < fifo1count; i++) {
read = tiadc_readl(adc_dev, REG_FIFO1);
stepid = read & FIFOREAD_CHNLID_MASK;
@@ -368,6 +395,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
*val = (u16) read;
}
}
+ am335x_tsc_se_adc_done(adc_dev->mfd_tscadc);
if (found == false)
return -EBUSY;
@@ -495,8 +523,8 @@ static int tiadc_resume(struct device *dev)
tiadc_writel(adc_dev, REG_CTRL, restore);
tiadc_step_config(indio_dev);
- am335x_tsc_se_set(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
-
+ am335x_tsc_se_set_cache(adc_dev->mfd_tscadc,
+ adc_dev->buffer_en_ch_steps);
return 0;
}
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 157f569..d4e8604 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -24,6 +24,7 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/sched.h>
#include <linux/mfd/ti_am335x_tscadc.h>
@@ -48,31 +49,71 @@ static const struct regmap_config tscadc_regmap_config = {
.val_bits = 32,
};
-static void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
-{
- tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
-}
-
void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
{
unsigned long flags;
spin_lock_irqsave(&tsadc->reg_lock, flags);
- tsadc->reg_se_cache |= val;
- am335x_tsc_se_update(tsadc);
+ tsadc->reg_se_cache = val;
+ if (tsadc->adc_waiting)
+ wake_up(&tsadc->reg_se_wait);
+ else if (!tsadc->adc_in_use)
+ tscadc_writel(tsadc, REG_SE, val);
+
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
+static void am335x_tscadc_need_adc(struct ti_tscadc_dev *tsadc)
+{
+ DEFINE_WAIT(wait);
+ u32 reg;
+
+ /*
+ * disable TSC steps so it does not run while the ADC is using it. If
+ * write 0 while it is running (it just started or was already running)
+ * then it completes all steps that were enabled and stops then.
+ */
+ tscadc_writel(tsadc, REG_SE, 0);
+ reg = tscadc_readl(tsadc, REG_ADCFSM);
+ if (reg & SEQ_STATUS) {
+ tsadc->adc_waiting = true;
+ prepare_to_wait(&tsadc->reg_se_wait, &wait,
+ TASK_UNINTERRUPTIBLE);
+ spin_unlock_irq(&tsadc->reg_lock);
+
+ schedule();
+
+ spin_lock_irq(&tsadc->reg_lock);
+ finish_wait(&tsadc->reg_se_wait, &wait);
+
+ reg = tscadc_readl(tsadc, REG_ADCFSM);
+ WARN_ON(reg & SEQ_STATUS);
+ tsadc->adc_waiting = false;
+ }
+ tsadc->adc_in_use = true;
+}
+
void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
{
+ spin_lock_irq(&tsadc->reg_lock);
+ am335x_tscadc_need_adc(tsadc);
+
+ tscadc_writel(tsadc, REG_SE, val);
+ spin_unlock_irq(&tsadc->reg_lock);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
+
+void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc)
+{
unsigned long flags;
spin_lock_irqsave(&tsadc->reg_lock, flags);
- tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache | val);
+ tsadc->adc_in_use = false;
+ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
}
-EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
+EXPORT_SYMBOL_GPL(am335x_tsc_se_adc_done);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
{
@@ -80,7 +121,7 @@ void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
spin_lock_irqsave(&tsadc->reg_lock, flags);
tsadc->reg_se_cache &= ~val;
- am335x_tsc_se_update(tsadc);
+ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
}
EXPORT_SYMBOL_GPL(am335x_tsc_se_clr);
@@ -188,6 +229,8 @@ static int ti_tscadc_probe(struct platform_device *pdev)
}
spin_lock_init(&tscadc->reg_lock);
+ init_waitqueue_head(&tscadc->reg_se_wait);
+
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 2fa9c06..fb96c84 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -159,6 +159,9 @@ struct ti_tscadc_dev {
int adc_cell; /* -1 if not used */
struct mfd_cell cells[TSCADC_CELLS];
u32 reg_se_cache;
+ bool adc_waiting;
+ bool adc_in_use;
+ wait_queue_head_t reg_se_wait;
spinlock_t reg_lock;
unsigned int clk_div;
@@ -179,5 +182,6 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val);
void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
+void am335x_tsc_se_adc_done(struct ti_tscadc_dev *tsadc);
#endif
--
1.8.5.1
^ permalink raw reply related
* [PATCH 4/5] mfd: ti_am335x: Drop am335x_tsc_se_update() from resume path
From: Sebastian Andrzej Siewior @ 2013-12-19 15:28 UTC (permalink / raw)
To: Lee Jones, Samuel Ortiz
Cc: Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah, Felipe Balbi,
linux-iio, linux-input, linux-kernel, Sebastian Andrzej Siewior
In-Reply-To: <1387466911-3732-1-git-send-email-bigeasy@linutronix.de>
The update of the SE register in MFD doesn't look right as it has
nothing to do with it. The better place to do it is in TSC driver (which
is already doing it) and in the ADC driver which needs this only in the
continues mode.
Acked-by: Lee Jones <lee.jones@linaro.org> [MFD part]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/iio/adc/ti_am335x_adc.c | 2 ++
drivers/mfd/ti_am335x_tscadc.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index b5197a0..6822b9f 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -199,6 +199,7 @@ static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
+ adc_dev->buffer_en_ch_steps = 0;
/* Flush FIFO of leftover data in the time it takes to disable adc */
fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
@@ -494,6 +495,7 @@ static int tiadc_resume(struct device *dev)
tiadc_writel(adc_dev, REG_CTRL, restore);
tiadc_step_config(indio_dev);
+ am335x_tsc_se_set(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
return 0;
}
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index cb0c211..157f569 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -309,7 +309,6 @@ static int tscadc_resume(struct device *dev)
if (tscadc_dev->tsc_cell != -1)
tscadc_idle_config(tscadc_dev);
- am335x_tsc_se_update(tscadc_dev);
restore = tscadc_readl(tscadc_dev, REG_CTRL);
tscadc_writel(tscadc_dev, REG_CTRL,
(restore | CNTRLREG_TSCSSENB));
--
1.8.5.1
^ permalink raw reply related
* [PATCH 3/5] mfd: ti_am335x_tscadc: Don't read back REG_SE
From: Sebastian Andrzej Siewior @ 2013-12-19 15:28 UTC (permalink / raw)
To: Lee Jones, Samuel Ortiz
Cc: Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah, Felipe Balbi,
linux-iio, linux-input, linux-kernel, Sebastian Andrzej Siewior
In-Reply-To: <1387466911-3732-1-git-send-email-bigeasy@linutronix.de>
The purpose of reg_se_cache has been defeated. It should avoid the
read-back of the register to avoid the latency and the fact that the
bits are reset to 0 after the individual conversation took place.
The reason why this is required like this to work, is that read-back of
the register removes the bits of the ADC so they do not start another
conversation after the register is re-written from the TSC side for the
update.
To avoid the not required read-back I introduce a "set once" variant which
does not update the cache mask. After the conversation completes, the
bit is removed from the SE register anyway and we don't plan a new
conversation "any time soon". The current set function is renamed to
set_cache to distinguish the two operations.
This is a small preparation for a larger sync-rework.
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/iio/adc/ti_am335x_adc.c | 4 ++--
drivers/input/touchscreen/ti_am335x_tsc.c | 4 ++--
drivers/mfd/ti_am335x_tscadc.c | 16 ++++++++++++----
include/linux/mfd/ti_am335x_tscadc.h | 3 ++-
4 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index e948454..b5197a0 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -181,7 +181,7 @@ static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
enb |= (get_adc_step_bit(adc_dev, bit) << 1);
adc_dev->buffer_en_ch_steps = enb;
- am335x_tsc_se_set(adc_dev->mfd_tscadc, enb);
+ am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
tiadc_writel(adc_dev, REG_IRQSTATUS, IRQENB_FIFO1THRES
| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
@@ -335,7 +335,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
return -EBUSY;
step_en = get_adc_step_mask(adc_dev);
- am335x_tsc_se_set(adc_dev->mfd_tscadc, step_en);
+ am335x_tsc_se_set_once(adc_dev->mfd_tscadc, step_en);
/* Wait for ADC sequencer to complete sampling */
while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 68beada..2ca5a7b 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -198,7 +198,7 @@ static void titsc_step_config(struct titsc *ts_dev)
/* The steps1 … end and bit 0 for TS_Charge */
stepenable = (1 << (end_step + 2)) - 1;
ts_dev->step_mask = stepenable;
- am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
+ am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
}
static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -322,7 +322,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
if (irqclr) {
titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
- am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
+ am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
return IRQ_HANDLED;
}
return IRQ_NONE;
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 67d0eb4..cb0c211 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -53,24 +53,32 @@ static void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
}
-void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
+void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val)
{
unsigned long flags;
spin_lock_irqsave(&tsadc->reg_lock, flags);
- tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
tsadc->reg_se_cache |= val;
am335x_tsc_se_update(tsadc);
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
}
-EXPORT_SYMBOL_GPL(am335x_tsc_se_set);
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set_cache);
+
+void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tsadc->reg_lock, flags);
+ tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache | val);
+ spin_unlock_irqrestore(&tsadc->reg_lock, flags);
+}
+EXPORT_SYMBOL_GPL(am335x_tsc_se_set_once);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val)
{
unsigned long flags;
spin_lock_irqsave(&tsadc->reg_lock, flags);
- tsadc->reg_se_cache = tscadc_readl(tsadc, REG_SE);
tsadc->reg_se_cache &= ~val;
am335x_tsc_se_update(tsadc);
spin_unlock_irqrestore(&tsadc->reg_lock, flags);
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 1fe7219..2fa9c06 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -176,7 +176,8 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
return *tscadc_dev;
}
-void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
+void am335x_tsc_se_set_cache(struct ti_tscadc_dev *tsadc, u32 val);
+void am335x_tsc_se_set_once(struct ti_tscadc_dev *tsadc, u32 val);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
#endif
--
1.8.5.1
^ permalink raw reply related
* [PATCH 2/5] mfd: ti_am335x_tscadc: Make am335x_tsc_se_update() local
From: Sebastian Andrzej Siewior @ 2013-12-19 15:28 UTC (permalink / raw)
To: Lee Jones, Samuel Ortiz
Cc: Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah, Felipe Balbi,
linux-iio, linux-input, linux-kernel, Sebastian Andrzej Siewior
In-Reply-To: <1387466911-3732-1-git-send-email-bigeasy@linutronix.de>
Since the "recent" changes, am335x_tsc_se_update() has no longer any
users outside of this file so make it local.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/mfd/ti_am335x_tscadc.c | 3 +--
include/linux/mfd/ti_am335x_tscadc.h | 1 -
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 88718ab..67d0eb4 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -48,11 +48,10 @@ static const struct regmap_config tscadc_regmap_config = {
.val_bits = 32,
};
-void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
+static void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc)
{
tscadc_writel(tsadc, REG_SE, tsadc->reg_se_cache);
}
-EXPORT_SYMBOL_GPL(am335x_tsc_se_update);
void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val)
{
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index d498d98f..1fe7219 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -176,7 +176,6 @@ static inline struct ti_tscadc_dev *ti_tscadc_dev_get(struct platform_device *p)
return *tscadc_dev;
}
-void am335x_tsc_se_update(struct ti_tscadc_dev *tsadc);
void am335x_tsc_se_set(struct ti_tscadc_dev *tsadc, u32 val);
void am335x_tsc_se_clr(struct ti_tscadc_dev *tsadc, u32 val);
--
1.8.5.1
^ permalink raw reply related
* [PATCH 1/5] iio: ti_am335x_adc: Adjust the closing bracket in tiadc_read_raw()
From: Sebastian Andrzej Siewior @ 2013-12-19 15:28 UTC (permalink / raw)
To: Lee Jones, Samuel Ortiz
Cc: Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah, Felipe Balbi,
linux-iio, linux-input, linux-kernel, Sebastian Andrzej Siewior
In-Reply-To: <1387466911-3732-1-git-send-email-bigeasy@linutronix.de>
It somehow looks like the ending bracket belongs to the if statement but
it does belong to the while loop. This patch moves the bracket where it
belongs.
Reviewed-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
drivers/iio/adc/ti_am335x_adc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index d4d7482..e948454 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -341,7 +341,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
while (tiadc_readl(adc_dev, REG_ADCFSM) & SEQ_STATUS) {
if (time_after(jiffies, timeout))
return -EAGAIN;
- }
+ }
map_val = chan->channel + TOTAL_CHANNELS;
/*
--
1.8.5.1
^ permalink raw reply related
* am335x: IIO/ADC fixes if used together with TSC, v2
From: Sebastian Andrzej Siewior @ 2013-12-19 15:28 UTC (permalink / raw)
To: Lee Jones, Samuel Ortiz
Cc: Jonathan Cameron, Dmitry Torokhov, Zubair Lutfullah, Felipe Balbi,
linux-iio-u79uwXL29TY76Z2rM5mHXA,
linux-input-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
The two bigger issues here are fixed by the last patch incuding
- time outs on the iio/adc side while TSC&ADC is used together
- a lockup issue which occurs while TSC&ADC is used together.
v1…v2:
- spelled checked and re-read each commit message and formated to
subject line as Lee suggested.
- removed am335x_tsc_se_set(), replaced am335x_tsc_se_tsc_set() by
am335x_tsc_se_set_cache() and adc variant is now named
am335x_tsc_se_set_once()
- Added Lee Jones' tags
Sebastian
^ permalink raw reply
* Re: [v3.11][Regression] HID: hyperv: convert alloc+memcpy to memdup
From: Jiri Kosina @ 2013-12-19 12:59 UTC (permalink / raw)
To: David Herrmann
Cc: Joseph Salisbury, Dan Carpenter, thomas, Haiyang Zhang, LKML,
open, HID CORE LAYER, driverdev-devel@linuxdriverproject.org
In-Reply-To: <CANq1E4R3LSx7pYncZ1dWf-BYY5gvC15=AjhFvurFqp0jaTUqYg@mail.gmail.com>
On Thu, 19 Dec 2013, David Herrmann wrote:
> As this thread doesn't really contain any oops message nor the exact
> driver name (except mentioning hyperv and magicmouse),
FWIW I recall the oopses being present somewhere in the ubuntu bug
tracker, referenced in this thread.
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 1/2] joydev: Map ABS_{THROTTLE,GAS,BREAK} to positive values.
From: Benjamin Franzke @ 2013-12-19 12:50 UTC (permalink / raw)
To: linux-input; +Cc: Benjamin Franzke
In-Reply-To: <1386749731-6500-1-git-send-email-benjaminfranzke@googlemail.com>
Hi List,
may I ask for some (other) comments that actually help fix this bug?
Some vague concerns dont really help.
Thanks, Ben
2013/12/11 Benjamin Franzke <benjaminfranzke@googlemail.com>:
> Gamepads like XInput devices have triggers with a range from
> e.g. 0 to 255.
> When the conventional joydev AXES correction/mapping method is used,
> the default state 0 (i.e. when the user does not press a button or trigger)
> is mapped to -32767 (and 255 to 32767).
> You'll get 0 only when pressing the trigger half-way down.
> This has several drawbacks:
> - A trigger is not usable at all when configured to have 2 directions
> when there is physically only one.
> - Applications that let the user configure joystick input assignments
> may register the mapped non-zero default state as a press,
> preventing the user from configuring any sensible value.
>
> Traditonal calibration e.g. with jscal does not help to get a usable
> experience either, it'll map the default state to -32767 as well.
> Only manually editing the calibration data does work currently.
>
> This patch tries to fix this issue by calculating a positive-only range for
> the throttle break and gas ABS bits.
> Maybe other ABS types need to be added to this scheme as well(?)
>
> Note:
> Although joydev is considered obsolete and people are encouraged to just
> use evdev, joydev should still be fixed, because
> 1. many applications still use it.
> 2. userspace already copies the joydev correction code to evdev (e.g. libSDL).
>
> This bug should be fixed here in joydev first, and when we have a good
> sensible state, this should be propagated to the application/libraries
> that copied the joydev correction code.
>
> Gamepad drivers will need to advertise triggers as THROTTLE,GAS,BREAK instead
> of e.g. ABS_{RZ,Z} where phyisically appropriate, to make use of this.
>
> I've considered changing the current joydev correction calculation for all ABS
> types, to have only a scaling functionality by default, no translation
> (all positive values remain positive, negatives negative and zero remains zero),
> so that drivers would need to expose zero-centered ABS values.
> It turned out to many drivers would need to be adjusted, which i cant
> test.
>
> Signed-off-by: Benjamin Franzke <benjaminfranzke@googlemail.com>
> ---
> drivers/input/joydev.c | 59 +++++++++++++++++++++++++++++++++++++-------------
> 1 file changed, 44 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
> index f362883..8352bee 100644
> --- a/drivers/input/joydev.c
> +++ b/drivers/input/joydev.c
> @@ -761,11 +761,50 @@ static bool joydev_match(struct input_handler *handler, struct input_dev *dev)
> return true;
> }
>
> +static void joydev_calculate_correction(struct input_dev *dev, __u8 abs,
> + struct js_corr *corr)
> +{
> + int t;
> +
> + corr->type = JS_CORR_BROKEN;
> + corr->prec = input_abs_get_fuzz(dev, abs);
> +
> + switch (abs) {
> + /* Map [min - max] => [0 - 32767]. */
> + case ABS_THROTTLE:
> + case ABS_GAS:
> + case ABS_BRAKE:
> + corr->coef[0] = input_abs_get_min(dev, abs);
> + corr->coef[1] = corr->coef[0] + input_abs_get_flat(dev, abs);
> + corr->coef[2] = 0;
> +
> + t = input_abs_get_max(dev, abs) - input_abs_get_min(dev, abs)
> + - input_abs_get_flat(dev, abs);
> + if (t)
> + corr->coef[3] = (1 << 29) / t;
> + break;
> + /* Map [min - max] => [-32768 - 32767]. */
> + default:
> + t = (input_abs_get_max(dev, abs) +
> + input_abs_get_min(dev, abs)) / 2;
> + corr->coef[0] = t - input_abs_get_flat(dev, abs);
> + corr->coef[1] = t + input_abs_get_flat(dev, abs);
> + t = (input_abs_get_max(dev, abs) -
> + input_abs_get_min(dev, abs)) / 2
> + - 2 * input_abs_get_flat(dev, abs);
> + if (t) {
> + corr->coef[2] = (1 << 29) / t;
> + corr->coef[3] = (1 << 29) / t;
> + }
> + break;
> + }
> +}
> +
> static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
> const struct input_device_id *id)
> {
> struct joydev *joydev;
> - int i, j, t, minor, dev_no;
> + int i, j, minor, dev_no;
> int error;
>
> minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true);
> @@ -826,23 +865,13 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
> joydev->abs[i] = input_abs_get_val(dev, j);
> continue;
> }
> - joydev->corr[i].type = JS_CORR_BROKEN;
> - joydev->corr[i].prec = input_abs_get_fuzz(dev, j);
>
> - t = (input_abs_get_max(dev, j) + input_abs_get_min(dev, j)) / 2;
> - joydev->corr[i].coef[0] = t - input_abs_get_flat(dev, j);
> - joydev->corr[i].coef[1] = t + input_abs_get_flat(dev, j);
> + joydev_calculate_correction(dev, j, &joydev->corr[i]);
>
> - t = (input_abs_get_max(dev, j) - input_abs_get_min(dev, j)) / 2
> - - 2 * input_abs_get_flat(dev, j);
> - if (t) {
> - joydev->corr[i].coef[2] = (1 << 29) / t;
> - joydev->corr[i].coef[3] = (1 << 29) / t;
> + joydev->abs[i] =
> + joydev_correct(input_abs_get_val(dev, j),
> + joydev->corr + i);
>
> - joydev->abs[i] =
> - joydev_correct(input_abs_get_val(dev, j),
> - joydev->corr + i);
> - }
> }
>
> joydev->dev.devt = MKDEV(INPUT_MAJOR, minor);
> --
> 1.8.1.5
>
^ permalink raw reply
* [Patch v2 10/13] ACPI, i2c-hid: replace open-coded _DSM specific code with helper functions
From: Jiang Liu @ 2013-12-19 12:38 UTC (permalink / raw)
To: Rafael J . Wysocki, Bjorn Helgaas, Lv Zheng, Len Brown,
Jiri Kosina, Benjamin Tissoires, Mika Westerberg
Cc: Jiang Liu, Tony Luck, linux-acpi, linux-kernel, linux-input
In-Reply-To: <1387456702-4709-1-git-send-email-jiang.liu@linux.intel.com>
Use helper functions to simplify _DSM related code in i2c-hid driver.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
drivers/hid/i2c-hid/i2c-hid.c | 26 ++++++--------------------
1 file changed, 6 insertions(+), 20 deletions(-)
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 5f7e55f..d22668f 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -850,37 +850,23 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
};
- union acpi_object params[4];
- struct acpi_object_list input;
+ union acpi_object *obj;
struct acpi_device *adev;
- unsigned long long value;
acpi_handle handle;
handle = ACPI_HANDLE(&client->dev);
if (!handle || acpi_bus_get_device(handle, &adev))
return -ENODEV;
- input.count = ARRAY_SIZE(params);
- input.pointer = params;
-
- params[0].type = ACPI_TYPE_BUFFER;
- params[0].buffer.length = sizeof(i2c_hid_guid);
- params[0].buffer.pointer = i2c_hid_guid;
- params[1].type = ACPI_TYPE_INTEGER;
- params[1].integer.value = 1;
- params[2].type = ACPI_TYPE_INTEGER;
- params[2].integer.value = 1; /* HID function */
- params[3].type = ACPI_TYPE_PACKAGE;
- params[3].package.count = 0;
- params[3].package.elements = NULL;
-
- if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_DSM", &input,
- &value))) {
+ obj = acpi_evaluate_dsm_typed(handle, i2c_hid_guid, 1, 1, NULL,
+ ACPI_TYPE_INTEGER);
+ if (!obj) {
dev_err(&client->dev, "device _DSM execution failed\n");
return -ENODEV;
}
- pdata->hid_descriptor_address = value;
+ pdata->hid_descriptor_address = obj->integer.value;
+ ACPI_FREE(obj);
return 0;
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH] HID: hyperv: make sure input buffer is big enough
From: David Herrmann @ 2013-12-19 11:32 UTC (permalink / raw)
To: linux-input
Cc: Jiri Kosina, Dan Carpenter, Joseph Salisbury, K. Y. Srinivasan,
Haiyang Zhang, linux-kernel, David Herrmann
We need at least HID_MAX_BUFFER_SIZE (4096) bytes as input buffer. HID
core depends on this as it requires every input report to be at least as
big as advertised.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
---
Hi
Same as for the HIDP patch, if there's a way to avoid the extra copy, please
provide a better patch.
Thanks
David
drivers/hid/hid-hyperv.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index 8fae6d1..c24908f 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -157,6 +157,7 @@ struct mousevsc_dev {
u32 report_desc_size;
struct hv_input_dev_info hid_dev_info;
struct hid_device *hid_device;
+ u8 input_buf[HID_MAX_BUFFER_SIZE];
};
@@ -256,6 +257,7 @@ static void mousevsc_on_receive(struct hv_device *device,
struct synthhid_msg *hid_msg;
struct mousevsc_dev *input_dev = hv_get_drvdata(device);
struct synthhid_input_report *input_report;
+ size_t len;
pipe_msg = (struct pipe_prt_msg *)((unsigned long)packet +
(packet->offset8 << 3));
@@ -300,9 +302,12 @@ static void mousevsc_on_receive(struct hv_device *device,
(struct synthhid_input_report *)pipe_msg->data;
if (!input_dev->init_complete)
break;
- hid_input_report(input_dev->hid_device,
- HID_INPUT_REPORT, input_report->buffer,
- input_report->header.size, 1);
+
+ len = min(input_report->header.size,
+ (u32)sizeof(input_dev->input_buf));
+ memcpy(input_dev->input_buf, input_report->buffer, len);
+ hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
+ input_dev->input_buf, len, 1);
break;
default:
pr_err("unsupported hid msg type - type %d len %d",
--
1.8.5.1
^ permalink raw reply related
* Re: [v3.11][Regression] HID: hyperv: convert alloc+memcpy to memdup
From: David Herrmann @ 2013-12-19 11:22 UTC (permalink / raw)
To: Jiri Kosina
Cc: Joseph Salisbury, Haiyang Zhang, LKML, open, Dan Carpenter,
HID CORE LAYER, driverdev-devel@linuxdriverproject.org, thomas
In-Reply-To: <CANq1E4RuteNfo23DQ5SvGXpsrpTmotLoJ6Wv1L8hAbE1ict6aA@mail.gmail.com>
Hi
On Thu, Dec 19, 2013 at 11:08 AM, David Herrmann <dh.herrmann@gmail.com> wrote:
> Hi
>
> On Thu, Dec 19, 2013 at 10:59 AM, Jiri Kosina <jkosina@suse.cz> wrote:
>> On Thu, 19 Dec 2013, David Herrmann wrote:
>>
>>> > diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
>>> > index 253fe23..81eacd3 100644
>>> > --- a/drivers/hid/hid-core.c
>>> > +++ b/drivers/hid/hid-core.c
>>> > @@ -1334,7 +1334,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
>>> > csize--;
>>> > }
>>> >
>>> > - rsize = ((report->size - 1) >> 3) + 1;
>>> > + rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
>>>
>>> Isn't "report->id" already covered by "if (report_enum->numbered)"
>>> above? The test for "id > 0" won't work here as in this case
>>> "report_enum->numbered" must already be set to true by the hid-desc
>>> parser, doesn't it?
>>
>> Right, that one is not correct here, thanks.
>>
>>> Where exactly did you get the +7 from?
>>
>> Please see commit (the one I am not really proud of) 27ce405039bfe6d3.
>
> Eh, I remember.. Ok, but the magic-mouse is BT right? So this commit
> really breaks BT drivers:
>
> commit b1a1442a23776756b254b69786848a94d92445ba
> Author: Jiri Kosina <jkosina@suse.cz>
> Date: Mon Jun 3 11:27:48 2013 +0200
>
> HID: core: fix reporting of raw events
>
> Problem is, if the raw_event() callback returned 0 earlier, we just
> skipped raw input reports. However, we now always call the
> hid_report_raw_event() helper. Which is normally fine, but the helper
> expects the input buffer to be of size HID_MAX_REPORT_SIZE, which is
> *not* true for HIDP. So the memset() writes over some random memory.
>
> I don't know exactly how to fix it. HID_MAX_BUFFER_SIZE is too big to
> be allocated on the stack, but we're in atomic-context here so a
> kzalloc(rsize, GFP_ATOMIC) seems overkill. So I guess we'd have to
> look into HIDP to make the skb big enough, but I'm not sure how we can
> achieve that.
>
> So off the top of my head, the best idea is to add "char
> inbuf[HID_MAX_BUFFER_SIZE];" to the hidp_session object in HIDP and
> copy every input-report into the buffer before passing to
> hid_input_report().
As this thread doesn't really contain any oops message nor the exact
driver name (except mentioning hyperv and magicmouse), I fixed a
related bug for HIDP:
http://thread.gmane.org/gmane.linux.bluez.kernel/41969
A similar patch is *really* required for hid-hyperv.c as it also does
not provide a properly sized buffer to hid_input_report().
David
^ permalink raw reply
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