Commit 0f1b1e6d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID updates from Jiri Kosina:
 - substantial cleanup of the generic and transport layers, in the
   direction of an ultimate goal of making struct hid_device completely
   transport independent, by Benjamin Tissoires
 - cp2112 driver from David Barksdale
 - a lot of fixes and new hardware support (Dualshock 4) to hid-sony
   driver, by Frank Praznik
 - support for Win 8.1 multitouch protocol by Andrew Duggan
 - other smaller fixes / device ID additions

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (75 commits)
  HID: sony: fix force feedback mismerge
  HID: sony: Set the quriks flag for Bluetooth controllers
  HID: sony: Fix Sixaxis cable state detection
  HID: uhid: Add UHID_CREATE2 + UHID_INPUT2
  HID: hyperv: fix _raw_request() prototype
  HID: hyperv: Implement a stub raw_request() entry point
  HID: hid-sensor-hub: fix sleeping function called from invalid context
  HID: multitouch: add support for Win 8.1 multitouch touchpads
  HID: remove hid_output_raw_report transport implementations
  HID: sony: do not rely on hid_output_raw_report
  HID: cp2112: remove the last hid_output_raw_report() call
  HID: cp2112: remove various hid_out_raw_report calls
  HID: multitouch: add support of other generic collections in hid-mt
  HID: multitouch: remove pen special handling
  HID: multitouch: remove registered devices with default behavior
  HID: hidp: Add a comment that some devices depend on the current behavior of uniq
  HID: sony: Prevent duplicate controller connections.
  HID: sony: Perform a boundry check on the sixaxis battery level index.
  HID: sony: Fix work queue issues
  HID: sony: Fix multi-line comment styling
  ...
parents 159d8133 3ae821ef
HID I/O Transport Drivers
===========================
The HID subsystem is independent of the underlying transport driver. Initially,
only USB was supported, but other specifications adopted the HID design and
provided new transport drivers. The kernel includes at least support for USB,
Bluetooth, I2C and user-space I/O drivers.
1) HID Bus
==========
The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
devices and register them with the HID bus. HID core then loads generic device
drivers on top of it. The transport drivers are responsible of raw data
transport and device setup/management. HID core is responsible of
report-parsing, report interpretation and the user-space API. Device specifics
and quirks are handled by all layers depending on the quirk.
+-----------+ +-----------+ +-----------+ +-----------+
| Device #1 | | Device #i | | Device #j | | Device #k |
+-----------+ +-----------+ +-----------+ +-----------+
\\ // \\ //
+------------+ +------------+
| I/O Driver | | I/O Driver |
+------------+ +------------+
|| ||
+------------------+ +------------------+
| Transport Driver | | Transport Driver |
+------------------+ +------------------+
\___ ___/
\ /
+----------------+
| HID Core |
+----------------+
/ | | \
/ | | \
____________/ | | \_________________
/ | | \
/ | | \
+----------------+ +-----------+ +------------------+ +------------------+
| Generic Driver | | MT Driver | | Custom Driver #1 | | Custom Driver #2 |
+----------------+ +-----------+ +------------------+ +------------------+
Example Drivers:
I/O: USB, I2C, Bluetooth-l2cap
Transport: USB-HID, I2C-HID, BT-HIDP
Everything below "HID Core" is simplified in this graph as it is only of
interest to HID device drivers. Transport drivers do not need to know the
specifics.
1.1) Device Setup
-----------------
I/O drivers normally provide hotplug detection or device enumeration APIs to the
transport drivers. Transport drivers use this to find any suitable HID device.
They allocate HID device objects and register them with HID core. Transport
drivers are not required to register themselves with HID core. HID core is never
aware of which transport drivers are available and is not interested in it. It
is only interested in devices.
Transport drivers attach a constant "struct hid_ll_driver" object with each
device. Once a device is registered with HID core, the callbacks provided via
this struct are used by HID core to communicate with the device.
Transport drivers are responsible of detecting device failures and unplugging.
HID core will operate a device as long as it is registered regardless of any
device failures. Once transport drivers detect unplug or failure events, they
must unregister the device from HID core and HID core will stop using the
provided callbacks.
1.2) Transport Driver Requirements
----------------------------------
The terms "asynchronous" and "synchronous" in this document describe the
transmission behavior regarding acknowledgements. An asynchronous channel must
not perform any synchronous operations like waiting for acknowledgements or
verifications. Generally, HID calls operating on asynchronous channels must be
running in atomic-context just fine.
On the other hand, synchronous channels can be implemented by the transport
driver in whatever way they like. They might just be the same as asynchronous
channels, but they can also provide acknowledgement reports, automatic
retransmission on failure, etc. in a blocking manner. If such functionality is
required on asynchronous channels, a transport-driver must implement that via
its own worker threads.
HID core requires transport drivers to follow a given design. A Transport
driver must provide two bi-directional I/O channels to each HID device. These
channels must not necessarily be bi-directional in the hardware itself. A
transport driver might just provide 4 uni-directional channels. Or it might
multiplex all four on a single physical channel. However, in this document we
will describe them as two bi-directional channels as they have several
properties in common.
- Interrupt Channel (intr): The intr channel is used for asynchronous data
reports. No management commands or data acknowledgements are sent on this
channel. Any unrequested incoming or outgoing data report must be sent on
this channel and is never acknowledged by the remote side. Devices usually
send their input events on this channel. Outgoing events are normally
not send via intr, except if high throughput is required.
- Control Channel (ctrl): The ctrl channel is used for synchronous requests and
device management. Unrequested data input events must not be sent on this
channel and are normally ignored. Instead, devices only send management
events or answers to host requests on this channel.
The control-channel is used for direct blocking queries to the device
independent of any events on the intr-channel.
Outgoing reports are usually sent on the ctrl channel via synchronous
SET_REPORT requests.
Communication between devices and HID core is mostly done via HID reports. A
report can be of one of three types:
- INPUT Report: Input reports provide data from device to host. This
data may include button events, axis events, battery status or more. This
data is generated by the device and sent to the host with or without
requiring explicit requests. Devices can choose to send data continuously or
only on change.
- OUTPUT Report: Output reports change device states. They are sent from host
to device and may include LED requests, rumble requests or more. Output
reports are never sent from device to host, but a host can retrieve their
current state.
Hosts may choose to send output reports either continuously or only on
change.
- FEATURE Report: Feature reports are used for specific static device features
and never reported spontaneously. A host can read and/or write them to access
data like battery-state or device-settings.
Feature reports are never sent without requests. A host must explicitly set
or retrieve a feature report. This also means, feature reports are never sent
on the intr channel as this channel is asynchronous.
INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
For INPUT reports this is the usual operational mode. But for OUTPUT reports,
this is rarely done as OUTPUT reports are normally quite scarce. But devices are
free to make excessive use of asynchronous OUTPUT reports (for instance, custom
HID audio speakers make great use of it).
Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
channel provides synchronous GET/SET_REPORT requests. Plain reports are only
allowed on the intr channel and are the only means of data there.
- GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
from host to device. The device must answer with a data report for the
requested report ID on the ctrl channel as a synchronous acknowledgement.
Only one GET_REPORT request can be pending for each device. This restriction
is enforced by HID core as several transport drivers don't allow multiple
simultaneous GET_REPORT requests.
Note that data reports which are sent as answer to a GET_REPORT request are
not handled as generic device events. That is, if a device does not operate
in continuous data reporting mode, an answer to GET_REPORT does not replace
the raw data report on the intr channel on state change.
GET_REPORT is only used by custom HID device drivers to query device state.
Normally, HID core caches any device state so this request is not necessary
on devices that follow the HID specs except during device initialization to
retrieve the current state.
GET_REPORT requests can be sent for any of the 3 report types and shall
return the current report state of the device. However, OUTPUT reports as
payload may be blocked by the underlying transport driver if the
specification does not allow them.
- SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
sent from host to device and a device must update it's current report state
according to the given data. Any of the 3 report types can be used. However,
INPUT reports as payload might be blocked by the underlying transport driver
if the specification does not allow them.
A device must answer with a synchronous acknowledgement. However, HID core
does not require transport drivers to forward this acknowledgement to HID
core.
Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
restriction is enforced by HID core as some transport drivers do not support
multiple synchronous SET_REPORT requests.
Other ctrl-channel requests are supported by USB-HID but are not available
(or deprecated) in most other transport level specifications:
- GET/SET_IDLE: Only used by USB-HID and I2C-HID.
- GET/SET_PROTOCOL: Not used by HID core.
- RESET: Used by I2C-HID, not hooked up in HID core.
- SET_POWER: Used by I2C-HID, not hooked up in HID core.
2) HID API
==========
2.1) Initialization
-------------------
Transport drivers normally use the following procedure to register a new device
with HID core:
struct hid_device *hid;
int ret;
hid = hid_allocate_device();
if (IS_ERR(hid)) {
ret = PTR_ERR(hid);
goto err_<...>;
}
strlcpy(hid->name, <device-name-src>, 127);
strlcpy(hid->phys, <device-phys-src>, 63);
strlcpy(hid->uniq, <device-uniq-src>, 63);
hid->ll_driver = &custom_ll_driver;
hid->bus = <device-bus>;
hid->vendor = <device-vendor>;
hid->product = <device-product>;
hid->version = <device-version>;
hid->country = <device-country>;
hid->dev.parent = <pointer-to-parent-device>;
hid->driver_data = <transport-driver-data-field>;
ret = hid_add_device(hid);
if (ret)
goto err_<...>;
Once hid_add_device() is entered, HID core might use the callbacks provided in
"custom_ll_driver". Note that fields like "country" can be ignored by underlying
transport-drivers if not supported.
To unregister a device, use:
hid_destroy_device(hid);
Once hid_destroy_device() returns, HID core will no longer make use of any
driver callbacks.
2.2) hid_ll_driver operations
-----------------------------
The available HID callbacks are:
- int (*start) (struct hid_device *hdev)
Called from HID device drivers once they want to use the device. Transport
drivers can choose to setup their device in this callback. However, normally
devices are already set up before transport drivers register them to HID core
so this is mostly only used by USB-HID.
- void (*stop) (struct hid_device *hdev)
Called from HID device drivers once they are done with a device. Transport
drivers can free any buffers and deinitialize the device. But note that
->start() might be called again if another HID device driver is loaded on the
device.
Transport drivers are free to ignore it and deinitialize devices after they
destroyed them via hid_destroy_device().
- int (*open) (struct hid_device *hdev)
Called from HID device drivers once they are interested in data reports.
Usually, while user-space didn't open any input API/etc., device drivers are
not interested in device data and transport drivers can put devices asleep.
However, once ->open() is called, transport drivers must be ready for I/O.
->open() calls are nested for each client that opens the HID device.
- void (*close) (struct hid_device *hdev)
Called from HID device drivers after ->open() was called but they are no
longer interested in device reports. (Usually if user-space closed any input
devices of the driver).
Transport drivers can put devices asleep and terminate any I/O of all
->open() calls have been followed by a ->close() call. However, ->start() may
be called again if the device driver is interested in input reports again.
- int (*parse) (struct hid_device *hdev)
Called once during device setup after ->start() has been called. Transport
drivers must read the HID report-descriptor from the device and tell HID core
about it via hid_parse_report().
- int (*power) (struct hid_device *hdev, int level)
Called by HID core to give PM hints to transport drivers. Usually this is
analogical to the ->open() and ->close() hints and redundant.
- void (*request) (struct hid_device *hdev, struct hid_report *report,
int reqtype)
Send an HID request on the ctrl channel. "report" contains the report that
should be sent and "reqtype" the request type. Request-type can be
HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.
This callback is optional. If not provided, HID core will assemble a raw
report following the HID specs and send it via the ->raw_request() callback.
The transport driver is free to implement this asynchronously.
- int (*wait) (struct hid_device *hdev)
Used by HID core before calling ->request() again. A transport driver can use
it to wait for any pending requests to complete if only one request is
allowed at a time.
- int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
__u8 *buf, size_t count, unsigned char rtype,
int reqtype)
Same as ->request() but provides the report as raw buffer. This request shall
be synchronous. A transport driver must not use ->wait() to complete such
requests. This request is mandatory and hid core will reject the device if
it is missing.
- int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)
Send raw output report via intr channel. Used by some HID device drivers
which require high throughput for outgoing requests on the intr channel. This
must not cause SET_REPORT calls! This must be implemented as asynchronous
output report on the intr channel!
- int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)
Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!
2.3) Data Path
--------------
Transport drivers are responsible of reading data from I/O devices. They must
handle any I/O-related state-tracking themselves. HID core does not implement
protocol handshakes or other management commands which can be required by the
given HID transport specification.
Every raw data packet read from a device must be fed into HID core via
hid_input_report(). You must specify the channel-type (intr or ctrl) and report
type (input/output/feature). Under normal conditions, only input reports are
provided via this API.
Responses to GET_REPORT requests via ->request() must also be provided via this
API. Responses to ->raw_request() are synchronous and must be intercepted by the
transport driver and not passed to hid_input_report().
Acknowledgements to SET_REPORT requests are not of interest to HID core.
----------------------------------------------------
Written 2013, David Herrmann <dh.herrmann@gmail.com>
......@@ -93,6 +93,11 @@ the request was handled successfully.
event to the kernel. The payload is of type struct uhid_create_req and
contains information about your device. You can start I/O now.
UHID_CREATE2:
Same as UHID_CREATE, but the HID report descriptor data (rd_data) is an array
inside struct uhid_create2_req, instead of a pointer to a separate array.
Enables use from languages that don't support pointers, e.g. Python.
UHID_DESTROY:
This destroys the internal HID device. No further I/O will be accepted. There
may still be pending messages that you can receive with read() but no further
......@@ -105,6 +110,12 @@ the request was handled successfully.
contains a data-payload. This is the raw data that you read from your device.
The kernel will parse the HID reports and react on it.
UHID_INPUT2:
Same as UHID_INPUT, but the data array is the last field of uhid_input2_req.
Enables userspace to write only the required bytes to kernel (ev.type +
ev.u.input2.size + the part of the data array that matters), instead of
the entire struct uhid_input2_req.
UHID_FEATURE_ANSWER:
If you receive a UHID_FEATURE request you must answer with this request. You
must copy the "id" field from the request into the answer. Set the "err" field
......
......@@ -175,6 +175,15 @@ config HID_PRODIKEYS
multimedia keyboard, but will lack support for the musical keyboard
and some additional multimedia keys.
config HID_CP2112
tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
depends on USB_HID && I2C && GPIOLIB
---help---
Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
This is a HID device driver which registers as an i2c adapter
and gpiochip to expose these functions of the CP2112. The
customizable USB descriptor fields are exposed as sysfs attributes.
config HID_CYPRESS
tristate "Cypress mouse and barcode readers" if EXPERT
depends on HID
......@@ -608,25 +617,27 @@ config HID_SAMSUNG
Support for Samsung InfraRed remote control or keyboards.
config HID_SONY
tristate "Sony PS2/3 accessories"
tristate "Sony PS2/3/4 accessories"
depends on USB_HID
depends on NEW_LEDS
depends on LEDS_CLASS
select POWER_SUPPLY
---help---
Support for
* Sony PS3 6-axis controllers
* Sony PS4 DualShock 4 controllers
* Buzz controllers
* Sony PS3 Blue-ray Disk Remote Control (Bluetooth)
* Logitech Harmony adapter for Sony Playstation 3 (Bluetooth)
config SONY_FF
bool "Sony PS2/3 accessories force feedback support"
bool "Sony PS2/3/4 accessories force feedback support"
depends on HID_SONY
select INPUT_FF_MEMLESS
---help---
Say Y here if you have a Sony PS2/3 accessory and want to enable force
feedback support for it.
Say Y here if you have a Sony PS2/3/4 accessory and want to enable
force feedback support for it.
config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support"
......
......@@ -41,6 +41,7 @@ obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o
......
......@@ -1248,6 +1248,11 @@ void hid_output_report(struct hid_report *report, __u8 *data)
}
EXPORT_SYMBOL_GPL(hid_output_report);
static int hid_report_len(struct hid_report *report)
{
return ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
}
/*
* Allocator for buffer that is going to be passed to hid_output_report()
*/
......@@ -1258,7 +1263,7 @@ u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags)
* of implement() working on 8 byte chunks
*/
int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7;
int len = hid_report_len(report);
return kmalloc(len, flags);
}
......@@ -1314,6 +1319,41 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
return report;
}
/*
* Implement a generic .request() callback, using .raw_request()
* DO NOT USE in hid drivers directly, but through hid_hw_request instead.
*/
void __hid_request(struct hid_device *hid, struct hid_report *report,
int reqtype)
{
char *buf;
int ret;
int len;
buf = hid_alloc_report_buf(report, GFP_KERNEL);
if (!buf)
return;
len = hid_report_len(report);
if (reqtype == HID_REQ_SET_REPORT)
hid_output_report(report, buf);
ret = hid->ll_driver->raw_request(hid, report->id, buf, len,
report->type, reqtype);
if (ret < 0) {
dbg_hid("unable to complete request: %d\n", ret);
goto out;
}
if (reqtype == HID_REQ_GET_REPORT)
hid_input_report(hid, report->type, buf, ret, 0);
out:
kfree(buf);
}
EXPORT_SYMBOL_GPL(__hid_request);
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt)
{
......@@ -1693,6 +1733,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) },
......@@ -1782,6 +1823,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) },
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1) },
......@@ -2433,6 +2475,14 @@ int hid_add_device(struct hid_device *hdev)
if (hid_ignore(hdev))
return -ENODEV;
/*
* Check for the mandatory transport channel.
*/
if (!hdev->ll_driver->raw_request) {
hid_err(hdev, "transport driver missing .raw_request()\n");
return -EINVAL;
}
/*
* Read the device report descriptor once and use as template
* for the driver-specific modifications.
......
This diff is collapsed.
......@@ -460,12 +460,22 @@ static void mousevsc_hid_stop(struct hid_device *hid)
{
}
static int mousevsc_hid_raw_request(struct hid_device *hid,
unsigned char report_num,
__u8 *buf, size_t len,
unsigned char rtype,
int reqtype)
{
return 0;
}
static struct hid_ll_driver mousevsc_ll_driver = {
.parse = mousevsc_hid_parse,
.open = mousevsc_hid_open,
.close = mousevsc_hid_close,
.start = mousevsc_hid_start,
.stop = mousevsc_hid_stop,
.raw_request = mousevsc_hid_raw_request,
};
static struct hid_driver mousevsc_hid_driver;
......
......@@ -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
......@@ -242,6 +245,7 @@
#define USB_VENDOR_ID_CYGNAL 0x10c4
#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X 0x818a
#define USB_DEVICE_ID_FOCALTECH_FTXXXX_MULTITOUCH 0x81b9
#define USB_DEVICE_ID_CYGNAL_CP2112 0xea90
#define USB_DEVICE_ID_CYGNAL_RADIO_SI4713 0x8244
......@@ -616,6 +620,7 @@
#define USB_VENDOR_ID_MICROSOFT 0x045e
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
#define USB_DEVICE_ID_MS_OFFICE_KB 0x0048
#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
#define USB_DEVICE_ID_MS_NE4K 0x00db
#define USB_DEVICE_ID_MS_NE4K_JP 0x00dc
......
......@@ -350,9 +350,9 @@ static int hidinput_get_battery_property(struct power_supply *psy,
ret = -ENOMEM;
break;
}
ret = dev->hid_get_raw_report(dev, dev->battery_report_id,
buf, 2,
dev->battery_report_type);
ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
dev->battery_report_type,
HID_REQ_GET_REPORT);
if (ret != 2) {
ret = -ENODATA;
......@@ -789,10 +789,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case 0x199: map_key_clear(KEY_CHAT); break;
case 0x19c: map_key_clear(KEY_LOGOFF); break;
case 0x19e: map_key_clear(KEY_COFFEE); break;
case 0x1a3: map_key_clear(KEY_NEXT); break;
case 0x1a4: map_key_clear(KEY_PREVIOUS); break;
case 0x1a6: map_key_clear(KEY_HELP); break;
case 0x1a7: map_key_clear(KEY_DOCUMENTS); break;
case 0x1ab: map_key_clear(KEY_SPELLCHECK); break;
case 0x1ae: map_key_clear(KEY_KEYBOARD); break;
case 0x1b4: map_key_clear(KEY_FILE); break;
case 0x1b6: map_key_clear(KEY_IMAGES); break;
case 0x1b7: map_key_clear(KEY_AUDIO); break;
case 0x1b8: map_key_clear(KEY_VIDEO); break;
......@@ -1150,7 +1153,7 @@ static void hidinput_led_worker(struct work_struct *work)
led_work);
struct hid_field *field;
struct hid_report *report;
int len;
int len, ret;
__u8 *buf;
field = hidinput_get_led_field(hid);
......@@ -1184,7 +1187,10 @@ static void hidinput_led_worker(struct work_struct *work)
hid_output_report(report, buf);
/* synchronous output report */
hid->hid_output_raw_report(hid, buf, len, HID_OUTPUT_REPORT);
ret = hid_hw_output_report(hid, buf, len);
if (ret == -ENOSYS)
hid_hw_raw_request(hid, report->id, buf, len, HID_OUTPUT_REPORT,
HID_REQ_SET_REPORT);
kfree(buf);
}
......@@ -1263,10 +1269,7 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid)
}
input_set_drvdata(input_dev, hid);
if (hid->ll_driver->hidinput_input_event)
input_dev->event = hid->ll_driver->hidinput_input_event;
else if (hid->ll_driver->request || hid->hid_output_raw_report)
input_dev->event = hidinput_input_event;
input_dev->event = hidinput_input_event;
input_dev->open = hidinput_open;
input_dev->close = hidinput_close;
input_dev->setkeycode = hidinput_setkeycode;
......
......@@ -692,7 +692,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
if (ret >= 0) {
/* insert a little delay of 10 jiffies ~ 40ms */
......@@ -704,7 +705,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
buf[1] = 0xB2;
get_random_bytes(&buf[2], 2);
ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
}
}
......
......@@ -44,14 +44,6 @@ static const char kbd_descriptor[] = {
0x19, 0xE0, /* USAGE_MINIMUM (Left Control) */
0x29, 0xE7, /* USAGE_MAXIMUM (Right GUI) */
0x81, 0x02, /* INPUT (Data,Var,Abs) */
0x95, 0x05, /* REPORT COUNT (5) */
0x05, 0x08, /* USAGE PAGE (LED page) */
0x19, 0x01, /* USAGE MINIMUM (1) */
0x29, 0x05, /* USAGE MAXIMUM (5) */
0x91, 0x02, /* OUTPUT (Data, Variable, Absolute) */
0x95, 0x01, /* REPORT COUNT (1) */