From: David Herrmann <hidden> Date: 2011-06-27 14:30:50
Add stub driver for the Nintendo Wii Remote. The wii remote uses
the HID protocol to communicate with the host over bluetooth. Hence,
add dependency for HIDP and place driver in hid subsystem.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/Kconfig | 6 ++++++
drivers/hid/Makefile | 1 +
drivers/hid/hid-wiimote.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 39 insertions(+), 0 deletions(-)
create mode 100644 drivers/hid/hid-wiimote.c
From: David Herrmann <hidden> Date: 2011-06-27 14:30:53
Allocate wiimote device structure with all wiimote related data
when registering new wiimote devices.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 41 +++++++++++++++++++++++++++++++++++++++--
1 files changed, 39 insertions(+), 2 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:30:53
The wiimote uses a fake HID protocol. Hence, we need to prevent
HIDINPUT and HIDDEV from parsing wiimote data and instead parse
raw hid events.
Add VID/PID to hid-core so the special driver is loaded on new
wiimotes.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-core.c | 1 +
drivers/hid/hid-ids.h | 3 ++
drivers/hid/hid-wiimote.c | 62 ++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 65 insertions(+), 1 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:30:54
Register input device so the wiimote can report input events on
it. We do not use HIDINPUT because the wiimote does not provide any
descriptor table which might be used by HIDINPUT. So we avoid
having HIDINPUT parse the wiimote descriptor and create unrelated
or unknown event flags. Instead we register our own input device
that we have full control of.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 34 ++++++++++++++++++++++++++++++++++
1 files changed, 34 insertions(+), 0 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:30:59
The wiimote driver needs to send raw output reports to the wiimote
device. Otherwise we could not manage the peripherals of the wiimote
or perform memory operations on the wiimote.
We cannot use hidinput_input_event of the lowlevel hid driver, since
this does not accept raw input. Therefore, we need to use the same
function that hidraw uses to send output. Side effect is, the raw
output function is not buffered and can sleep.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:31:01
The raw hid output function that is supported by bluetooth low-level
hid driver does not provide an output queue and also may sleep. The
wiimote driver, though, may need to send data in atomic context so
this patch adds a buffered output queue for the wiimote driver.
We use the shared workqueue to send our buffer to the hid device.
There is always only one active worker which reschedules itself until
the wiimote queue is empty. This prevents the worker from occupying
the shared workqueue for too long. If our queue is full, every further
output is discarded.
Special care is needed in the deinitialization routine. When
wiimote_hid_remove is called, HID input is already disabled, but HID
output may still be used from our worker and is then discarded by the
lower HID layers. Therefore, we can safely disable the input layer since it
is the only layer that still sends input events.
Future sysfs attributes must be freed before unregistering input to
avoid the sysfs handlers to send input events to a non-existing input
layer.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 86 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 86 insertions(+), 0 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:31:03
Create array of all event handlers and call each handler when we
receive the related event.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:31:05
Parse input report 0x30 from the wiimote as button input. We need to
send events for all buttons on every input report because the wiimote
does not send events for single buttons but always for all buttons
to us. The input layer, however, filters redundant events.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:31:07
Add new request that sets the leds on the target device. Also, per
default, set led1 after initializing a device.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
From: David Herrmann <hidden> Date: 2011-06-27 14:31:08
Save the current state of the leds in the wiimote data structure. This
allows us to discard new led requests that wouldn't change anything.
Protect the whole state structure by a spinlock. Every wiiproto_*
function expects this spinlock to be held when called.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
@@ -334,7 +355,12 @@ static int wiimote_hid_probe(struct hid_device *hdev,smp_wmb();atomic_set(&wdata->ready,1);hid_info(hdev,"New device registered\n");++/* by default set led1 after device initialization */+spin_lock_irq(&wdata->state.lock);wiiproto_req_leds(wdata,WIIPROTO_FLAG_LED1);+spin_unlock_irq(&wdata->state.lock);+return0;err_stop:
From: David Herrmann <hidden> Date: 2011-06-27 14:31:10
Add sysfs files for each led of the wiimote. Writing 1 to the file
enables the led and 0 disables the led.
We do not need memory barriers when checking wdata->ready since we use
a spinlock directly after it.
Signed-off-by: David Herrmann <redacted>
---
Documentation/ABI/testing/sysfs-driver-hid-wiimote | 10 +++
drivers/hid/hid-wiimote.c | 74 ++++++++++++++++++++
2 files changed, 84 insertions(+), 0 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-wiimote
@@ -0,0 +1,10 @@+What: /sys/bus/hid/drivers/wiimote/<dev>/led1+What: /sys/bus/hid/drivers/wiimote/<dev>/led2+What: /sys/bus/hid/drivers/wiimote/<dev>/led3+What: /sys/bus/hid/drivers/wiimote/<dev>/led4+Date: July 2011+KernelVersion: 3.1+Contact: David Herrmann <dh.herrmann@googlemail.com>+Description: Make it possible to set/get current led state. Reading from it+ returns 0 if led is off and 1 if it is on. Writing 0 to it+ disables the led, writing 1 enables it.
From: David Herrmann <hidden> Date: 2011-06-27 14:31:46
The wiimote first starts HID hardware and then registers the input
device. We need to synchronize the startup so no event handler will
start parsing events when the wiimote device is not ready, yet.
Signed-off-by: David Herrmann <redacted>
---
drivers/hid/hid-wiimote.c | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)
@@ -27,12 +29,26 @@ struct wiimote_data {staticintwiimote_input_event(structinput_dev*dev,unsignedinttype,unsignedintcode,intvalue){+structwiimote_data*wdata=input_get_drvdata(dev);++if(!atomic_read(&wdata->ready))+return-EBUSY;+/* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */+smp_rmb();+return0;}staticintwiimote_hid_event(structhid_device*hdev,structhid_report*report,u8*raw_data,intsize){+structwiimote_data*wdata=hid_get_drvdata(hdev);++if(!atomic_read(&wdata->ready))+return-EBUSY;+/* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */+smp_rmb();+if(size<1)return-EINVAL;
@@ -103,6 +119,9 @@ static int wiimote_hid_probe(struct hid_device *hdev,gotoerr_stop;}+/* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */+smp_wmb();+atomic_set(&wdata->ready,1);hid_info(hdev,"New device registered\n");return0;
The raw hid output function that is supported by bluetooth low-level
hid driver does not provide an output queue and also may sleep. The
wiimote driver, though, may need to send data in atomic context so
this patch adds a buffered output queue for the wiimote driver.
We use the shared workqueue to send our buffer to the hid device.
There is always only one active worker which reschedules itself until
the wiimote queue is empty. This prevents the worker from occupying
the shared workqueue for too long.
With CWQ this is not a concern anymore, you should be able to flush your buffer at once.
--
Dmitry
The wiimote first starts HID hardware and then registers the input
device. We need to synchronize the startup so no event handler will
start parsing events when the wiimote device is not ready, yet.
I believe this is generic HID layer problem. Would it be possible to fix this issue there?
Thanks.
--
Dmitry
From: David Herrmann <hidden> Date: 2011-06-29 12:39:08
On Tue, Jun 28, 2011 at 7:49 AM, Dmitry Torokhov
[off-list ref] wrote:
David Herrmann [off-list ref] wrote:
quoted
The wiimote first starts HID hardware and then registers the input
device. We need to synchronize the startup so no event handler will
start parsing events when the wiimote device is not ready, yet.
I believe this is generic HID layer problem. Would it be possible to fix this issue there?
The point is, I do not use HIDINPUT/HIDDEV (see commit message 2/12).
The wiimote has no valid report-descriptor table so hidinput/hiddev do
not make sense. I could set up a valid report-descriptor-table, use
input_mapping, input_mapped, report_fixup callbacks and then use
HIDINPUT. However, that would be far more complex than my current
solution, which is creating my own input instance and also my own
synchronization.
Furthermore, the wiimote provides input/output features that cannot be
handled by the generic HID handler, so I would need to extend the
input_mapping, anyway.
But, thanks to your hint, I looked at hid_hw_start() again and as far
as I can see the synchronization issue exists there, too.
The ll_driver->start() function is called first and after that, the
input instance is registered.
If the ll_driver reports an event before the input instance is
registered, the hidinput/other-driver will call input_event() on an
invalid input instance (probably even a NULL dereference).
This may not be a problem for usbhid, because usbhid_open() has to be
called first, however, hidp (bluetooth hid) ignores the *_open()
callback and therefore may fail.
I will look at this again and send a separate mail to this list,
however, I don't think this is related to my driver? Or do you think I
should replace my input-handling with HIDINPUT to be more homogeneous
with the other hid drivers?
Thanks, I've fixed that.
David
--
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
From: David Herrmann <hidden> Date: 2011-06-29 12:53:50
On Tue, Jun 28, 2011 at 6:51 AM, Dmitry Torokhov
[off-list ref] wrote:
avid Herrmann [off-list ref] wrote:
quoted
The raw hid output function that is supported by bluetooth low-level
hid driver does not provide an output queue and also may sleep. The
wiimote driver, though, may need to send data in atomic context so
this patch adds a buffered output queue for the wiimote driver.
We use the shared workqueue to send our buffer to the hid device.
There is always only one active worker which reschedules itself until
the wiimote queue is empty. This prevents the worker from occupying
the shared workqueue for too long.
With CWQ this is not a concern anymore, you should be able to flush your buffer at once.
Thanks, I wasn't sure about this. I've now changed:
- if (wdata->head != wdata->tail) {
+ while (wdata->head != wdata->tail) {
and removed the if(...) schedule_work(...);
But, thanks to your hint, I looked at hid_hw_start() again and as far
as I can see the synchronization issue exists there, too.
The ll_driver->start() function is called first and after that, the
input instance is registered.
If the ll_driver reports an event before the input instance is
registered, the hidinput/other-driver will call input_event() on an
invalid input instance (probably even a NULL dereference).
This may not be a problem for usbhid, because usbhid_open() has to be
called first, however, hidp (bluetooth hid) ignores the *_open()
callback and therefore may fail.
Indeed, this looks like a proper analysis. Thanks a lot for looking into
it.
Are you planning on submitting the fix for that? Otherwise I'll add it to
my TODO list, independently on the wiimote driver.
Thanks,
--
Jiri Kosina
SUSE Labs