config HID_A4TECH
tristate "A4 tech mice" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
config HID_ACRUX
tristate "ACRUX game controller support"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y here if you want to enable support for ACRUX game controllers.
config HID_APPLE
tristate "Apple {i,Power,Mac}Books" if EXPERT
-- - depends on (USB_HID || BT_HIDP)
++ + depends on HID
default !EXPERT
---help---
Support for some Apple devices which less or more break
Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
MacBooks, MacBook Pros and Apple Aluminum.
+++config HID_APPLEIR
+++ tristate "Apple infrared receiver"
+++ depends on (USB_HID)
+++ ---help---
+++ Support for Apple infrared remote control. All the Apple computers from
+++ 2005 onwards include such a port, except the unibody Macbook (2009),
+++ and Mac Pros. This receiver is also used in the Apple TV set-top box
+++ prior to the 2010 model.
+++
+++ Say Y here if you want support for Apple infrared remote control.
+++
config HID_AUREAL
tristate "Aureal"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
config HID_BELKIN
tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Belkin Flip KVM and Wireless keyboard.
config HID_CHERRY
tristate "Cherry Cymotion keyboard" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Cherry Cymotion keyboard.
config HID_CHICONY
tristate "Chicony Tactical pad" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Chicony Tactical pad.
config HID_PRODIKEYS
tristate "Prodikeys PC-MIDI Keyboard support"
-- - depends on USB_HID && SND
++ + depends on HID && SND
select SND_RAWMIDI
---help---
Support for Prodikeys PC-MIDI Keyboard device support.
config HID_CYPRESS
tristate "Cypress mouse and barcode readers" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for cypress mouse and barcode readers.
config HID_DRAGONRISE
tristate "DragonRise Inc. game controller"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y here if you have DragonRise Inc. game controllers.
These might be branded as:
config HID_EMS_FF
tristate "EMS Production Inc. force feedback support"
-- - depends on USB_HID
++ + depends on HID
select INPUT_FF_MEMLESS
---help---
Say Y here if you want to enable force feedback support for devices by
config HID_ELECOM
tristate "ELECOM BM084 bluetooth mouse"
-- - depends on BT_HIDP
++ + depends on HID
---help---
Support for the ELECOM BM084 (bluetooth mouse).
config HID_EZKEY
tristate "Ezkey BTC 8193 keyboard" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Ezkey BTC 8193 keyboard.
config HID_KEYTOUCH
tristate "Keytouch HID devices"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Keytouch HID devices not fully compliant with
the specification. Currently supported:
config HID_KYE
tristate "KYE/Genius devices"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for KYE/Genius devices not fully compliant with HID standard:
- Ergo Mouse
config HID_UCLOGIC
tristate "UC-Logic"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for UC-Logic tablets.
config HID_WALTOP
tristate "Waltop"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Waltop tablets.
config HID_GYRATION
tristate "Gyration remote control"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Gyration remote control.
config HID_ICADE
tristate "ION iCade arcade controller"
-- - depends on BT_HIDP
++ + depends on HID
---help---
Support for the ION iCade arcade controller to work as a joystick.
config HID_TWINHAN
tristate "Twinhan IR remote control"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Twinhan IR remote control.
config HID_KENSINGTON
tristate "Kensington Slimblade Trackball" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Kensington Slimblade Trackball.
config HID_LCPOWER
tristate "LC-Power"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for LC-Power RC1000MCE RF remote control.
config HID_LOGITECH
tristate "Logitech devices" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Logitech devices that are not fully compliant with HID standard.
config HID_MAGICMOUSE
tristate "Apple MagicMouse multi-touch support"
-- - depends on BT_HIDP
++ + depends on HID
---help---
Support for the Apple Magic Mouse multi-touch.
config HID_MICROSOFT
tristate "Microsoft non-fully HID-compliant devices" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Microsoft devices that are not fully compliant with HID standard.
config HID_MONTEREY
tristate "Monterey Genius KB29E keyboard" if EXPERT
-- - depends on USB_HID
++ + depends on HID
default !EXPERT
---help---
Support for Monterey Genius KB29E.
config HID_MULTITOUCH
tristate "HID Multitouch panels"
-- - depends on USB_HID
++ + depends on HID
---help---
Generic support for HID multitouch panels.
config HID_ORTEK
tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
-- - depends on USB_HID
++ + depends on HID
---help---
There are certain devices which have LogicalMaximum wrong in the keyboard
usage page of their report descriptor. The most prevailing ones so far
config HID_PANTHERLORD
tristate "Pantherlord/GreenAsia game controller"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter.
config HID_PETALYNX
tristate "Petalynx Maxter remote control"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Petalynx Maxter remote control.
config HID_PICOLCD
tristate "PicoLCD (graphic version)"
-- - depends on USB_HID
++ + depends on HID
---help---
This provides support for Minibox PicoLCD devices, currently
only the graphical ones are supported.
config HID_PRIMAX
tristate "Primax non-fully HID-compliant devices"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Primax devices that are not fully compliant with the
HID standard.
config HID_PS3REMOTE
tristate "Sony PS3 BD Remote Control"
-- - depends on BT_HIDP
++ + depends on HID
---help---
Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech
Harmony Adapter for PS3, which connect over Bluetooth.
config HID_SAITEK
tristate "Saitek non-fully HID-compliant devices"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Saitek devices that are not fully compliant with the
HID standard.
config HID_SAMSUNG
tristate "Samsung InfraRed remote control or keyboards"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Samsung InfraRed remote control or keyboards.
config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Speedlink Vicious and Divine Cezanne mouse.
config HID_STEELSERIES
tristate "Steelseries SRW-S1 steering wheel support"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Steelseries SRW-S1 steering wheel
config HID_SUNPLUS
tristate "Sunplus wireless desktop"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Sunplus wireless desktop.
config HID_GREENASIA
tristate "GreenAsia (Product ID 0x12) game controller support"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y here if you have a GreenAsia (Product ID 0x12) based game
controller or adapter.
config HID_SMARTJOYPLUS
tristate "SmartJoy PLUS PS2/USB adapter support"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
config HID_TIVO
tristate "TiVo Slide Bluetooth remote control support"
-- - depends on (USB_HID || BT_HIDP)
++ + depends on HID
---help---
Say Y if you have a TiVo Slide Bluetooth remote control.
config HID_TOPSEED
tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
CLLRCMCE remote control.
config HID_THINGM
tristate "ThingM blink(1) USB RGB LED"
-- - depends on USB_HID
++ + depends on HID
depends on LEDS_CLASS
---help---
Support for the ThingM blink(1) USB RGB LED. This driver registers a
config HID_THRUSTMASTER
tristate "ThrustMaster devices support"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
a THRUSTMASTER Ferrari GT Rumble Wheel.
config HID_WACOM
tristate "Wacom Bluetooth devices support"
-- - depends on BT_HIDP
++ + depends on HID
depends on LEDS_CLASS
select POWER_SUPPLY
---help---
config HID_WIIMOTE
tristate "Nintendo Wii Remote support"
-- - depends on BT_HIDP
++ + depends on HID
depends on LEDS_CLASS
select POWER_SUPPLY
select INPUT_FF_MEMLESS
config HID_ZEROPLUS
tristate "Zeroplus based game controller support"
-- - depends on USB_HID
++ + depends on HID
---help---
Say Y here if you have a Zeroplus based game controller.
config HID_ZYDACRON
tristate "Zydacron remote control support"
-- - depends on USB_HID
++ + depends on HID
---help---
Support for Zydacron remote control.
config HID_SENSOR_HUB
tristate "HID Sensors framework support"
-- - depends on USB_HID && GENERIC_HARDIRQS
++ + depends on HID && GENERIC_HARDIRQS
select MFD_CORE
default n
-- help---
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
-- -#include <linux/usb.h>
#include "hid-ids.h"
}
static const struct hid_device_id apple_devices[] = {
--- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL),
--- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
--- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
--- .driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
} else if (page == HID_UP_SENSOR &&
item.type == HID_ITEM_TYPE_MAIN &&
item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
-- - (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
-- - (hid->bus == BUS_USB || hid->bus == BUS_I2C))
++ + (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL)
hid->group = HID_GROUP_SENSOR_HUB;
}
struct hid_report_enum *report_enum;
struct hid_driver *hdrv;
struct hid_report *report;
- -- char *buf;
- -- unsigned int i;
int ret = 0;
if (!hid)
return -ENODEV;
--- if (down_trylock(&hid->driver_lock))
+++ if (down_trylock(&hid->driver_input_lock))
return -EBUSY;
if (!hid->driver) {
}
/* Avoid unnecessary overhead if debugfs is disabled */
- -- if (list_empty(&hid->debug_list))
- -- goto nomem;
- --
- -- buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
- --
- -- if (!buf)
- -- goto nomem;
- --
- -- /* dump the report */
- -- snprintf(buf, HID_DEBUG_BUFSIZE - 1,
- -- "\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un");
- -- hid_debug_event(hid, buf);
- --
- -- for (i = 0; i < size; i++) {
- -- snprintf(buf, HID_DEBUG_BUFSIZE - 1,
- -- " %02x", data[i]);
- -- hid_debug_event(hid, buf);
- -- }
- -- hid_debug_event(hid, "\n");
- -- kfree(buf);
+ ++ if (!list_empty(&hid->debug_list))
+ ++ hid_dump_report(hid, type, data, size);
- --nomem:
report = hid_get_report(report_enum, data);
if (!report) {
ret = hid_report_raw_event(hid, type, data, size, interrupt);
unlock:
--- up(&hid->driver_lock);
+++ up(&hid->driver_input_lock);
return ret;
}
EXPORT_SYMBOL_GPL(hid_input_report);
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
--- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
--- { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS) },
+++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
+++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL2) },
+++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL3) },
+++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
+++ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL5) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS) },
if (down_interruptible(&hdev->driver_lock))
return -EINTR;
+++ if (down_interruptible(&hdev->driver_input_lock)) {
+++ ret = -EINTR;
+++ goto unlock_driver_lock;
+++ }
+++ hdev->io_started = false;
if (!hdev->driver) {
id = hid_match_device(hdev, hdrv);
}
}
unlock:
+++ if (!hdev->io_started)
+++ up(&hdev->driver_input_lock);
+++ unlock_driver_lock:
up(&hdev->driver_lock);
return ret;
}
{
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
struct hid_driver *hdrv;
+++ int ret = 0;
if (down_interruptible(&hdev->driver_lock))
return -EINTR;
+++ if (down_interruptible(&hdev->driver_input_lock)) {
+++ ret = -EINTR;
+++ goto unlock_driver_lock;
+++ }
+++ hdev->io_started = false;
hdrv = hdev->driver;
if (hdrv) {
hdev->driver = NULL;
}
+++ if (!hdev->io_started)
+++ up(&hdev->driver_input_lock);
+++ unlock_driver_lock:
up(&hdev->driver_lock);
--- return 0;
+++ return ret;
}
static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
- { HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST))
return true;
break;
++ case USB_VENDOR_ID_ATMEL_V_USB:
++ /* Masterkit MA901 usb radio based on Atmel tiny85 chip and
++ * it has the same USB ID as many Atmel V-USB devices. This
++ * usb radio is handled by radio-ma901.c driver so we want
++ * ignore the hid. Check the name, bus, product and ignore
++ * if we have MA901 usb radio.
++ */
++ if (hdev->product == USB_DEVICE_ID_ATMEL_V_USB &&
++ hdev->bus == BUS_USB &&
++ strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
++ return true;
++ break;
}
if (hdev->type == HID_TYPE_USBMOUSE &&
init_waitqueue_head(&hdev->debug_wait);
INIT_LIST_HEAD(&hdev->debug_list);
+ ++ mutex_init(&hdev->debug_list_lock);
sema_init(&hdev->driver_lock, 1);
+++ sema_init(&hdev->driver_input_lock, 1);
return hdev;
}
#define DFGT_REV_MAJ 0x13
#define DFGT_REV_MIN 0x22
+++ #define DFGT2_REV_MIN 0x26
#define DFP_REV_MAJ 0x11
#define DFP_REV_MIN 0x06
#define FFEX_REV_MAJ 0x21
static const struct lg4ff_usb_revision lg4ff_revs[] = {
{DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */
+++ {DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt}, /* Driving Force GT v2 */
{DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */
{G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */
{G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */
value[5] = 0x00;
value[6] = 0x00;
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
break;
}
return 0;
value[5] = 0x00;
value[6] = 0x00;
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
/* Sends autocentering command compatible with Formula Force EX */
value[5] = 0x00;
value[6] = 0x00;
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
/* Sends command to set range compatible with G25/G27/Driving Force GT */
value[5] = 0x00;
value[6] = 0x00;
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
/* Sends commands to set range compatible with Driving Force Pro wheel */
report->field[0]->value[1] = 0x02;
full_range = 200;
}
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
/* Prepare "fine" limit command */
value[0] = 0x81;
value[6] = 0x00;
if (range == 200 || range == 900) { /* Do not apply any fine limit */
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
return;
}
value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
value[6] = 0xff;
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd)
for (i = 0; i < 7; i++)
report->field[0]->value[i] = cmd->cmd[j++];
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
}
value[4] = 0x00;
value[5] = 0x00;
value[6] = 0x00;
-- - usbhid_submit_report(hid, report, USB_DIR_OUT);
++ + hid_hw_request(hid, report, HID_REQ_SET_REPORT);
}
static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
#include <linux/module.h>
#include <linux/usb.h>
#include <asm/unaligned.h>
-- -#include "usbhid/usbhid.h"
#include "hid-ids.h"
#include "hid-logitech-dj.h"
static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
size_t count,
unsigned char report_type);
--- static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
struct dj_report *dj_report)
if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
SPFUNCTION_DEVICE_LIST_EMPTY) {
dbg_hid("%s: device list is empty\n", __func__);
--- djrcv_dev->querying_devices = false;
return;
}
return;
}
--- if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
--- /* The device is already known. No need to reallocate it. */
--- dbg_hid("%s: device is already known\n", __func__);
--- return;
--- }
---
dj_hiddev = hid_allocate_device();
if (IS_ERR(dj_hiddev)) {
dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
struct dj_report dj_report;
unsigned long flags;
int count;
--- int retval;
dbg_hid("%s\n", __func__);
logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
break;
default:
--- /* A normal report (i. e. not belonging to a pair/unpair notification)
--- * arriving here, means that the report arrived but we did not have a
--- * paired dj_device associated to the report's device_index, this
--- * means that the original "device paired" notification corresponding
--- * to this dj_device never arrived to this driver. The reason is that
--- * hid-core discards all packets coming from a device while probe() is
--- * executing. */
--- if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
--- /* ok, we don't know the device, just re-ask the
--- * receiver for the list of connected devices. */
--- retval = logi_dj_recv_query_paired_devices(djrcv_dev);
--- if (!retval) {
--- /* everything went fine, so just leave */
--- break;
--- }
--- dev_err(&djrcv_dev->hdev->dev,
--- "%s:logi_dj_recv_query_paired_devices "
--- "error:%d\n", __func__, retval);
--- }
dbg_hid("%s: unexpected report type\n", __func__);
}
}
if (!djdev) {
dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
" is NULL, index %d\n", dj_report->device_index);
--- kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
---
--- if (schedule_work(&djrcv_dev->work) == 0) {
--- dbg_hid("%s: did not schedule the work item, was already "
--- "queued\n", __func__);
--- }
return;
}
if (dj_device == NULL) {
dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
" is NULL, index %d\n", dj_report->device_index);
--- kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
---
--- if (schedule_work(&djrcv_dev->work) == 0) {
--- dbg_hid("%s: did not schedule the work item, was already "
--- "queued\n", __func__);
--- }
return;
}
struct dj_report *dj_report)
{
struct hid_device *hdev = djrcv_dev->hdev;
- int sent_bytes;
+ struct hid_report *report;
+ struct hid_report_enum *output_report_enum;
+ u8 *data = (u8 *)(&dj_report->device_index);
+ int i;
+
+ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
+ report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
- if (!hdev->hid_output_raw_report) {
- dev_err(&hdev->dev, "%s:"
- "hid_output_raw_report is null\n", __func__);
+ if (!report) {
+ dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
return -ENODEV;
}
- sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report,
- sizeof(struct dj_report),
- HID_OUTPUT_REPORT);
+ for (i = 0; i < report->field[0]->report_count; i++)
+ report->field[0]->value[i] = data[i];
+
-- usbhid_submit_report(hdev, report, USB_DIR_OUT);
++ + hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
- return (sent_bytes < 0) ? sent_bytes : 0;
+ return 0;
}
static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
struct dj_report *dj_report;
int retval;
--- /* no need to protect djrcv_dev->querying_devices */
--- if (djrcv_dev->querying_devices)
--- return 0;
---
dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
if (!dj_report)
return -ENOMEM;
return retval;
}
---
static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
unsigned timeout)
{
hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
hid_set_field(report->field[0], 2, data[1]);
-- - usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);
++ + hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);
return 0;
goto llopen_failed;
}
+++ /* Allow incoming packets to arrive: */
+++ hid_device_io_start(hdev);
+++
retval = logi_dj_recv_query_paired_devices(djrcv_dev);
if (retval < 0) {
dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/slab.h>
-- -#include <linux/usb.h>
#include "hid-ids.h"
return 0;
}
++static void magicmouse_input_configured(struct hid_device *hdev,
++ struct hid_input *hi)
++
++{
++ struct magicmouse_sc *msc = hid_get_drvdata(hdev);
++
++ int ret = magicmouse_setup_input(msc->input, hdev);
++ if (ret) {
++ hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
++ /* clean msc->input to notify probe() of the failure */
++ msc->input = NULL;
++ }
++}
++
++
static int magicmouse_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
goto err_free;
}
-- /* We do this after hid-input is done parsing reports so that
-- * hid-input uses the most natural button and axis IDs.
-- */
-- if (msc->input) {
-- ret = magicmouse_setup_input(msc->input, hdev);
-- if (ret) {
-- hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
-- goto err_stop_hw;
-- }
++ if (!msc->input) {
++ hid_err(hdev, "magicmouse input not registered\n");
++ ret = -ENOMEM;
++ goto err_stop_hw;
}
if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
.remove = magicmouse_remove,
.raw_event = magicmouse_raw_event,
.input_mapping = magicmouse_input_mapping,
++ .input_configured = magicmouse_input_configured,
};
module_hid_driver(magicmouse_driver);
* HID driver for multitouch panels
*
* Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
++ + * Copyright (c) 2012-2013 Red Hat, Inc
*
* This code is partly based on hid-egalax.c:
*
* any later version.
*/
++ +/*
++ + * This driver is regularly tested thanks to the tool hid-test[1].
++ + * This tool relies on hid-replay[2] and a database of hid devices[3].
++ + * Please run these regression tests before patching this module so that
++ + * your patch won't break existing known devices.
++ + *
++ + * [1] https://github.com/bentiss/hid-test
++ + * [2] https://github.com/bentiss/hid-replay
++ + * [3] https://github.com/bentiss/hid-devices
++ + */
++ +
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/input/mt.h>
-- -#include "usbhid/usbhid.h"
{
struct mt_device *td = hid_get_drvdata(hid);
__s32 quirks = td->mtclass.quirks;
++ struct input_dev *input = field->hidinput->input;
if (hid->claimed & HID_CLAIMED_INPUT) {
switch (usage->hid) {
break;
default:
++ if (usage->type)
++ input_event(input, usage->type, usage->code,
++ value);
return;
}
if (usage->usage_index + 1 == field->report_count) {
/* we only take into account the last report. */
if (usage->hid == td->last_slot_field)
-- mt_complete_slot(td, field->hidinput->input);
++ mt_complete_slot(td, input);
if (field->index == td->last_field_index
&& td->num_received >= td->num_expected)
r = re->report_id_hash[td->inputmode];
if (r) {
r->field[0]->value[td->inputmode_index] = 0x02;
-- - usbhid_submit_report(hdev, r, USB_DIR_OUT);
++ + hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
}
}
max = min(fieldmax, max);
if (r->field[0]->value[0] != max) {
r->field[0]->value[0] = max;
-- - usbhid_submit_report(hdev, r, USB_DIR_OUT);
++ + hid_hw_request(hdev, r, HID_REQ_SET_REPORT);
}
}
}
static int mt_resume(struct hid_device *hdev)
{
-- - struct usb_interface *intf;
-- - struct usb_host_interface *interface;
-- - struct usb_device *dev;
-- -
-- - if (hdev->bus != BUS_USB)
-- - return 0;
-- -
-- - intf = to_usb_interface(hdev->dev.parent);
-- - interface = intf->cur_altsetting;
-- - dev = hid_to_usb_dev(hdev);
-- -
/* Some Elan legacy devices require SET_IDLE to be set on resume.
* It should be safe to send it to other devices too.
* Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
-- - usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-- - HID_REQ_SET_IDLE,
-- - USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-- - 0, interface->desc.bInterfaceNumber,
-- - NULL, 0, USB_CTRL_SET_TIMEOUT);
++ + hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE);
return 0;
}
unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES];
--- struct semaphore driver_lock; /* protects the current driver */
+++ struct semaphore driver_lock; /* protects the current driver, except during input */
+++ struct semaphore driver_input_lock; /* protects the current driver */
struct device dev; /* device */
struct hid_driver *driver;
struct hid_ll_driver *ll_driver;
unsigned int status; /* see STAT flags above */
unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */
+++ bool io_started; /* Protected by driver_lock. If IO has started */
struct list_head inputs; /* The list of inputs */
void *hiddev; /* The hiddev structure */
struct dentry *debug_rdesc;
struct dentry *debug_events;
struct list_head debug_list;
+ ++ struct mutex debug_list_lock;
wait_queue_head_t debug_wait;
};
* @resume: invoked on resume if device was not reset (NULL means nop)
* @reset_resume: invoked on resume if device was reset (NULL means nop)
*
+++ * probe should return -errno on error, or 0 on success. During probe,
+++ * input will not be passed to raw_event unless hid_device_io_start is
+++ * called.
+++ *
* raw_event and event should return 0 on no action performed, 1 when no
* further processing should be done and negative on error
*
* @hidinput_input_event: event input event (e.g. ff or leds)
* @parse: this method is called only once to parse the device data,
* shouldn't allocate anything to not leak memory
++ + * @request: send report request to device (e.g. feature report)
++ + * @wait: wait for buffered io to complete (send/recv reports)
++ + * @idle: send idle request to device
*/
struct hid_ll_driver {
int (*start)(struct hid_device *hdev);
unsigned int code, int value);
int (*parse)(struct hid_device *hdev);
++ +
++ + void (*request)(struct hid_device *hdev,
++ + struct hid_report *report, int reqtype);
++ +
++ + int (*wait)(struct hid_device *hdev);
++ + int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype);
++ +
};
#define PM_HINT_FULLON 1<<5
const struct hid_device_id *id);
s32 hid_snto32(__u32 value, unsigned n);
+++ /**
+++ * hid_device_io_start - enable HID input during probe, remove
+++ *
+++ * @hid - the device
+++ *
+++ * This should only be called during probe or remove and only be
+++ * called by the thread calling probe or remove. It will allow
+++ * incoming packets to be delivered to the driver.
+++ */
+++ static inline void hid_device_io_start(struct hid_device *hid) {
+++ if (hid->io_started) {
+++ dev_warn(&hid->dev, "io already started");
+++ return;
+++ }
+++ hid->io_started = true;
+++ up(&hid->driver_input_lock);
+++ }
+++
+++ /**
+++ * hid_device_io_stop - disable HID input during probe, remove
+++ *
+++ * @hid - the device
+++ *
+++ * Should only be called after hid_device_io_start. It will prevent
+++ * incoming packets from going to the driver for the duration of
+++ * probe, remove. If called during probe, packets will still go to the
+++ * driver after probe is complete. This function should only be called
+++ * by the thread calling probe or remove.
+++ */
+++ static inline void hid_device_io_stop(struct hid_device *hid) {
+++ if (!hid->io_started) {
+++ dev_warn(&hid->dev, "io already stopped");
+++ return;
+++ }
+++ hid->io_started = false;
+++ down(&hid->driver_input_lock);
+++ }
+++
/**
* hid_map_usage - map usage input bits
*
return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0;
}
++ +
++ +/**
++ + * hid_hw_request - send report request to device
++ + *
++ + * @hdev: hid device
++ + * @report: report to send
++ + * @reqtype: hid request type
++ + */
++ +static inline void hid_hw_request(struct hid_device *hdev,
++ + struct hid_report *report, int reqtype)
++ +{
++ + if (hdev->ll_driver->request)
++ + hdev->ll_driver->request(hdev, report, reqtype);
++ +}
++ +
++ +/**
++ + * hid_hw_idle - send idle request to device
++ + *
++ + * @hdev: hid device
++ + * @report: report to control
++ + * @idle: idle state
++ + * @reqtype: hid request type
++ + */
++ +static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle,
++ + int reqtype)
++ +{
++ + if (hdev->ll_driver->idle)
++ + return hdev->ll_driver->idle(hdev, report, idle, reqtype);
++ +
++ + return 0;
++ +}
++ +
++ +/**
++ + * hid_hw_wait - wait for buffered io to complete
++ + *
++ + * @hdev: hid device
++ + */
++ +static inline void hid_hw_wait(struct hid_device *hdev)
++ +{
++ + if (hdev->ll_driver->wait)
++ + hdev->ll_driver->wait(hdev);
++ +}
++ +
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt);