Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (22 commits) HID: fix error condition propagation in hid-sony driver HID: fix reference count leak hidraw HID: add proper support for pensketch 12x9 tablet HID: don't allow DealExtreme usb-radio be handled by usb hid driver HID: fix default Kconfig setting for TopSpeed driver HID: driver for TopSeed Cyberlink quirky remote HID: make boot protocol drivers depend on EMBEDDED HID: avoid sparse warning in HID_COMPAT_LOAD_DRIVER HID: hiddev cleanup -- handle all error conditions properly HID: force feedback driver for GreenAsia 0x12 PID HID: switch specialized drivers from "default y" to !EMBEDDED HID: set proper dev.parent in hidraw HID: add dynids facility HID: use GFP_KERNEL in hid_alloc_buffers HID: usbhid, use usb_endpoint_xfer_int HID: move usbhid flags to usbhid.h HID: add n-trig digitizer support HID: add phys and name ioctls to hidraw HID: struct device - replace bus_id with dev_name(), dev_set_name() HID: automatically call usbhid_set_leds in usbhid driver ...
This commit is contained in:
Коммит
8606ab6d30
|
@ -85,14 +85,14 @@ config HID_COMPAT
|
|||
config HID_A4TECH
|
||||
tristate "A4 tech" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
|
||||
|
||||
config HID_APPLE
|
||||
tristate "Apple" if EMBEDDED
|
||||
depends on (USB_HID || BT_HIDP)
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for some Apple devices which less or more break
|
||||
HID specification.
|
||||
|
@ -103,64 +103,49 @@ config HID_APPLE
|
|||
config HID_BELKIN
|
||||
tristate "Belkin" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Belkin Flip KVM and Wireless keyboard.
|
||||
|
||||
config HID_BRIGHT
|
||||
tristate "Bright" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
---help---
|
||||
Support for Bright ABNT-2 keyboard.
|
||||
|
||||
config HID_CHERRY
|
||||
tristate "Cherry" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Cherry Cymotion keyboard.
|
||||
|
||||
config HID_CHICONY
|
||||
tristate "Chicony" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Chicony Tactical pad.
|
||||
|
||||
config HID_CYPRESS
|
||||
tristate "Cypress" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for cypress mouse and barcode readers.
|
||||
|
||||
config HID_DELL
|
||||
tristate "Dell" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
---help---
|
||||
Support for quirky Dell HID hardware that require
|
||||
special LED handling (W7658 and SK8115 models)
|
||||
|
||||
config HID_EZKEY
|
||||
tristate "Ezkey" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Ezkey BTC 8193 keyboard.
|
||||
|
||||
config HID_GYRATION
|
||||
tristate "Gyration" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Gyration remote control.
|
||||
|
||||
config HID_LOGITECH
|
||||
tristate "Logitech" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Logitech devices that are not fully compliant with HID standard.
|
||||
|
||||
|
@ -191,21 +176,28 @@ config LOGIRUMBLEPAD2_FF
|
|||
config HID_MICROSOFT
|
||||
tristate "Microsoft" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Microsoft devices that are not fully compliant with HID standard.
|
||||
|
||||
config HID_MONTEREY
|
||||
tristate "Monterey" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Monterey Genius KB29E.
|
||||
|
||||
config HID_NTRIG
|
||||
tristate "NTrig" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for N-Trig touch screen.
|
||||
|
||||
config HID_PANTHERLORD
|
||||
tristate "Pantherlord devices support" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for PantherLord/GreenAsia based device support.
|
||||
|
||||
|
@ -220,31 +212,47 @@ config PANTHERLORD_FF
|
|||
config HID_PETALYNX
|
||||
tristate "Petalynx" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Petalynx Maxter remote control.
|
||||
|
||||
config HID_SAMSUNG
|
||||
tristate "Samsung" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Samsung InfraRed remote control.
|
||||
|
||||
config HID_SONY
|
||||
tristate "Sony" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Sony PS3 controller.
|
||||
|
||||
config HID_SUNPLUS
|
||||
tristate "Sunplus" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default y
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Support for Sunplus wireless desktop.
|
||||
|
||||
config GREENASIA_FF
|
||||
tristate "GreenAsia (Product ID 0x12) force feedback support"
|
||||
depends on USB_HID
|
||||
select INPUT_FF_MEMLESS
|
||||
---help---
|
||||
Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
|
||||
(like MANTA Warior MM816 and SpeedLink Strike2 SL-6635) or adapter
|
||||
and want to enable force feedback support for it.
|
||||
|
||||
config HID_TOPSEED
|
||||
tristate "TopSeed Cyberlink remote control support" if EMBEDDED
|
||||
depends on USB_HID
|
||||
default !EMBEDDED
|
||||
---help---
|
||||
Say Y if you have a TopSeed Cyberlink remote control.
|
||||
|
||||
config THRUSTMASTER_FF
|
||||
tristate "ThrustMaster devices support"
|
||||
depends on USB_HID
|
||||
|
|
|
@ -23,22 +23,23 @@ endif
|
|||
obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o
|
||||
obj-$(CONFIG_HID_APPLE) += hid-apple.o
|
||||
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
|
||||
obj-$(CONFIG_HID_BRIGHT) += hid-bright.o
|
||||
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
|
||||
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
|
||||
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
||||
obj-$(CONFIG_HID_DELL) += hid-dell.o
|
||||
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
||||
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
||||
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
|
||||
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
|
||||
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
|
||||
obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
|
||||
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
|
||||
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
|
||||
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
||||
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
||||
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
|
||||
obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
|
||||
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
|
||||
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
|
||||
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
|
||||
|
||||
obj-$(CONFIG_USB_HID) += usbhid/
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* HID driver for some bright "special" devices
|
||||
*
|
||||
* Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* Based on hid-dell driver
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
static int bright_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
usbhid_set_leds(hdev);
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hid_device_id bright_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, bright_devices);
|
||||
|
||||
static struct hid_driver bright_driver = {
|
||||
.name = "bright",
|
||||
.id_table = bright_devices,
|
||||
.probe = bright_probe,
|
||||
};
|
||||
|
||||
static int bright_init(void)
|
||||
{
|
||||
return hid_register_driver(&bright_driver);
|
||||
}
|
||||
|
||||
static void bright_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&bright_driver);
|
||||
}
|
||||
|
||||
module_init(bright_init);
|
||||
module_exit(bright_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
HID_COMPAT_LOAD_DRIVER(bright);
|
|
@ -1256,19 +1256,16 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
{ 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_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
|
||||
|
@ -1279,7 +1276,6 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_DESKTOP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_EDGE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) },
|
||||
|
@ -1297,23 +1293,105 @@ static const struct hid_device_id hid_blacklist[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
|
||||
{ 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_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
||||
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
|
||||
{ }
|
||||
};
|
||||
|
||||
struct hid_dynid {
|
||||
struct list_head list;
|
||||
struct hid_device_id id;
|
||||
};
|
||||
|
||||
/**
|
||||
* store_new_id - add a new HID device ID to this driver and re-probe devices
|
||||
* @driver: target device driver
|
||||
* @buf: buffer for scanning device ID data
|
||||
* @count: input size
|
||||
*
|
||||
* Adds a new dynamic hid device ID to this driver,
|
||||
* and causes the driver to probe for all devices again.
|
||||
*/
|
||||
static ssize_t store_new_id(struct device_driver *drv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
|
||||
struct hid_dynid *dynid;
|
||||
__u32 bus, vendor, product;
|
||||
unsigned long driver_data = 0;
|
||||
int ret;
|
||||
|
||||
ret = sscanf(buf, "%x %x %x %lx",
|
||||
&bus, &vendor, &product, &driver_data);
|
||||
if (ret < 3)
|
||||
return -EINVAL;
|
||||
|
||||
dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
||||
dynid->id.bus = bus;
|
||||
dynid->id.vendor = vendor;
|
||||
dynid->id.product = product;
|
||||
dynid->id.driver_data = driver_data;
|
||||
|
||||
spin_lock(&hdrv->dyn_lock);
|
||||
list_add_tail(&dynid->list, &hdrv->dyn_list);
|
||||
spin_unlock(&hdrv->dyn_lock);
|
||||
|
||||
ret = 0;
|
||||
if (get_driver(&hdrv->driver)) {
|
||||
ret = driver_attach(&hdrv->driver);
|
||||
put_driver(&hdrv->driver);
|
||||
}
|
||||
|
||||
return ret ? : count;
|
||||
}
|
||||
static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
|
||||
|
||||
static void hid_free_dynids(struct hid_driver *hdrv)
|
||||
{
|
||||
struct hid_dynid *dynid, *n;
|
||||
|
||||
spin_lock(&hdrv->dyn_lock);
|
||||
list_for_each_entry_safe(dynid, n, &hdrv->dyn_list, list) {
|
||||
list_del(&dynid->list);
|
||||
kfree(dynid);
|
||||
}
|
||||
spin_unlock(&hdrv->dyn_lock);
|
||||
}
|
||||
|
||||
static const struct hid_device_id *hid_match_device(struct hid_device *hdev,
|
||||
struct hid_driver *hdrv)
|
||||
{
|
||||
struct hid_dynid *dynid;
|
||||
|
||||
spin_lock(&hdrv->dyn_lock);
|
||||
list_for_each_entry(dynid, &hdrv->dyn_list, list) {
|
||||
if (hid_match_one_id(hdev, &dynid->id)) {
|
||||
spin_unlock(&hdrv->dyn_lock);
|
||||
return &dynid->id;
|
||||
}
|
||||
}
|
||||
spin_unlock(&hdrv->dyn_lock);
|
||||
|
||||
return hid_match_id(hdev, hdrv->id_table);
|
||||
}
|
||||
|
||||
static int hid_bus_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct hid_driver *hdrv = container_of(drv, struct hid_driver, driver);
|
||||
struct hid_device *hdev = container_of(dev, struct hid_device, dev);
|
||||
|
||||
if (!hid_match_id(hdev, hdrv->id_table))
|
||||
if (!hid_match_device(hdev, hdrv))
|
||||
return 0;
|
||||
|
||||
/* generic wants all non-blacklisted */
|
||||
|
@ -1332,7 +1410,7 @@ static int hid_device_probe(struct device *dev)
|
|||
int ret = 0;
|
||||
|
||||
if (!hdev->driver) {
|
||||
id = hid_match_id(hdev, hdrv->id_table);
|
||||
id = hid_match_device(hdev, hdrv);
|
||||
if (id == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -1420,6 +1498,7 @@ static const struct hid_device_id hid_ignore_list[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DEALEXTREAME, USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
|
||||
|
@ -1577,6 +1656,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
|
||||
{ }
|
||||
|
@ -1618,9 +1700,10 @@ int hid_add_device(struct hid_device *hdev)
|
|||
if (hid_ignore(hdev))
|
||||
return -ENODEV;
|
||||
|
||||
/* XXX hack, any other cleaner solution < 20 bus_id bytes? */
|
||||
sprintf(hdev->dev.bus_id, "%04X:%04X:%04X.%04X", hdev->bus,
|
||||
hdev->vendor, hdev->product, atomic_inc_return(&id));
|
||||
/* XXX hack, any other cleaner solution after the driver core
|
||||
* is converted to allow more than 20 bytes as the device name? */
|
||||
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
|
||||
hdev->vendor, hdev->product, atomic_inc_return(&id));
|
||||
|
||||
ret = device_add(&hdev->dev);
|
||||
if (!ret)
|
||||
|
@ -1695,18 +1778,33 @@ EXPORT_SYMBOL_GPL(hid_destroy_device);
|
|||
int __hid_register_driver(struct hid_driver *hdrv, struct module *owner,
|
||||
const char *mod_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hdrv->driver.name = hdrv->name;
|
||||
hdrv->driver.bus = &hid_bus_type;
|
||||
hdrv->driver.owner = owner;
|
||||
hdrv->driver.mod_name = mod_name;
|
||||
|
||||
return driver_register(&hdrv->driver);
|
||||
INIT_LIST_HEAD(&hdrv->dyn_list);
|
||||
spin_lock_init(&hdrv->dyn_lock);
|
||||
|
||||
ret = driver_register(&hdrv->driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = driver_create_file(&hdrv->driver, &driver_attr_new_id);
|
||||
if (ret)
|
||||
driver_unregister(&hdrv->driver);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__hid_register_driver);
|
||||
|
||||
void hid_unregister_driver(struct hid_driver *hdrv)
|
||||
{
|
||||
driver_remove_file(&hdrv->driver, &driver_attr_new_id);
|
||||
driver_unregister(&hdrv->driver);
|
||||
hid_free_dynids(hdrv);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_unregister_driver);
|
||||
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* HID driver for some dell "special" devices
|
||||
*
|
||||
* Copyright (c) 1999 Andreas Gal
|
||||
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
|
||||
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
|
||||
* Copyright (c) 2006-2007 Jiri Kosina
|
||||
* Copyright (c) 2007 Paul Walmsley
|
||||
* Copyright (c) 2008 Jiri Slaby
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
usbhid_set_leds(hdev);
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hid_device_id dell_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, dell_devices);
|
||||
|
||||
static struct hid_driver dell_driver = {
|
||||
.name = "dell",
|
||||
.id_table = dell_devices,
|
||||
.probe = dell_probe,
|
||||
};
|
||||
|
||||
static int dell_init(void)
|
||||
{
|
||||
return hid_register_driver(&dell_driver);
|
||||
}
|
||||
|
||||
static void dell_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&dell_driver);
|
||||
}
|
||||
|
||||
module_init(dell_init);
|
||||
module_exit(dell_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
HID_COMPAT_LOAD_DRIVER(dell);
|
|
@ -43,6 +43,9 @@ static int __init hid_dummy_init(void)
|
|||
#ifdef CONFIG_HID_MONTEREY_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(monterey);
|
||||
#endif
|
||||
#ifdef CONFIG_HID_NTRIG_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(ntrig);
|
||||
#endif
|
||||
#ifdef CONFIG_HID_PANTHERLORD_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(pantherlord);
|
||||
#endif
|
||||
|
@ -58,6 +61,9 @@ static int __init hid_dummy_init(void)
|
|||
#ifdef CONFIG_HID_SUNPLUS_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(sunplus);
|
||||
#endif
|
||||
#ifdef CONFIG_GREENASIA_FF_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(greenasia);
|
||||
#endif
|
||||
#ifdef CONFIG_THRUSTMASTER_FF_MODULE
|
||||
HID_COMPAT_CALL_DRIVER(thrustmaster);
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Force feedback support for GreenAsia (Product ID 0x12) based devices
|
||||
*
|
||||
* The devices are distributed under various names and the same USB device ID
|
||||
* can be used in many game controllers.
|
||||
*
|
||||
*
|
||||
* 0e8f:0012 "GreenAsia Inc. USB Joystick "
|
||||
* - tested with MANTA Warior MM816 and SpeedLink Strike2 SL-6635.
|
||||
*
|
||||
* Copyright (c) 2008 Lukasz Lubojanski <lukasz@lubojanski.info>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/hid.h>
|
||||
#include "hid-ids.h"
|
||||
#include "usbhid/usbhid.h"
|
||||
|
||||
struct gaff_device {
|
||||
struct hid_report *report;
|
||||
};
|
||||
|
||||
static int hid_gaff_play(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
struct gaff_device *gaff = data;
|
||||
int left, right;
|
||||
|
||||
left = effect->u.rumble.strong_magnitude;
|
||||
right = effect->u.rumble.weak_magnitude;
|
||||
|
||||
dbg_hid("called with 0x%04x 0x%04x", left, right);
|
||||
|
||||
left = left * 0xfe / 0xffff;
|
||||
right = right * 0xfe / 0xffff;
|
||||
|
||||
gaff->report->field[0]->value[0] = 0x51;
|
||||
gaff->report->field[0]->value[1] = 0x0;
|
||||
gaff->report->field[0]->value[2] = right;
|
||||
gaff->report->field[0]->value[3] = 0;
|
||||
gaff->report->field[0]->value[4] = left;
|
||||
gaff->report->field[0]->value[5] = 0;
|
||||
dbg_hid("running with 0x%02x 0x%02x", left, right);
|
||||
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
|
||||
|
||||
gaff->report->field[0]->value[0] = 0xfa;
|
||||
gaff->report->field[0]->value[1] = 0xfe;
|
||||
gaff->report->field[0]->value[2] = 0x0;
|
||||
gaff->report->field[0]->value[4] = 0x0;
|
||||
|
||||
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gaff_init(struct hid_device *hid)
|
||||
{
|
||||
struct gaff_device *gaff;
|
||||
struct hid_report *report;
|
||||
struct hid_input *hidinput = list_entry(hid->inputs.next,
|
||||
struct hid_input, list);
|
||||
struct list_head *report_list =
|
||||
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
|
||||
struct list_head *report_ptr = report_list;
|
||||
struct input_dev *dev = hidinput->input;
|
||||
int error;
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
dev_err(&hid->dev, "no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report_ptr = report_ptr->next;
|
||||
|
||||
report = list_entry(report_ptr, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
dev_err(&hid->dev, "no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (report->field[0]->report_count < 6) {
|
||||
dev_err(&hid->dev, "not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
gaff = kzalloc(sizeof(struct gaff_device), GFP_KERNEL);
|
||||
if (!gaff)
|
||||
return -ENOMEM;
|
||||
|
||||
set_bit(FF_RUMBLE, dev->ffbit);
|
||||
|
||||
error = input_ff_create_memless(dev, gaff, hid_gaff_play);
|
||||
if (error) {
|
||||
kfree(gaff);
|
||||
return error;
|
||||
}
|
||||
|
||||
gaff->report = report;
|
||||
gaff->report->field[0]->value[0] = 0x51;
|
||||
gaff->report->field[0]->value[1] = 0x00;
|
||||
gaff->report->field[0]->value[2] = 0x00;
|
||||
gaff->report->field[0]->value[3] = 0x00;
|
||||
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
|
||||
|
||||
gaff->report->field[0]->value[0] = 0xfa;
|
||||
gaff->report->field[0]->value[1] = 0xfe;
|
||||
|
||||
usbhid_submit_report(hid, gaff->report, USB_DIR_OUT);
|
||||
|
||||
dev_info(&hid->dev, "Force Feedback for GreenAsia 0x12"
|
||||
" devices by Lukasz Lubojanski <lukasz@lubojanski.info>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(&hdev->dev, "Greenasia HID hardware probe...");
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "hw start failed\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
gaff_init(hdev);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct hid_device_id ga_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012), },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ga_devices);
|
||||
|
||||
static struct hid_driver ga_driver = {
|
||||
.name = "greenasia",
|
||||
.id_table = ga_devices,
|
||||
.probe = ga_probe,
|
||||
};
|
||||
|
||||
static int __init ga_init(void)
|
||||
{
|
||||
return hid_register_driver(&ga_driver);
|
||||
}
|
||||
|
||||
static void __exit ga_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&ga_driver);
|
||||
}
|
||||
|
||||
module_init(ga_init);
|
||||
module_exit(ga_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
HID_COMPAT_LOAD_DRIVER(greenasia);
|
|
@ -107,9 +107,6 @@
|
|||
#define USB_VENDOR_ID_BELKIN 0x050d
|
||||
#define USB_DEVICE_ID_FLIP_KVM 0x3201
|
||||
|
||||
#define USB_VENDOR_ID_BRIGHT 0x1241
|
||||
#define USB_DEVICE_ID_BRIGHT_ABNT2 0x1503
|
||||
|
||||
#define USB_VENDOR_ID_BERKSHIRE 0x0c98
|
||||
#define USB_DEVICE_ID_BERKSHIRE_PCWD 0x1140
|
||||
|
||||
|
@ -141,9 +138,8 @@
|
|||
#define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61
|
||||
#define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64
|
||||
|
||||
#define USB_VENDOR_ID_DELL 0x413c
|
||||
#define USB_DEVICE_ID_DELL_W7658 0x2005
|
||||
#define USB_DEVICE_ID_DELL_SK8115 0x2105
|
||||
#define USB_VENDOR_ID_DEALEXTREAME 0x10c5
|
||||
#define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701 0x819a
|
||||
|
||||
#define USB_VENDOR_ID_DELORME 0x1163
|
||||
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
|
||||
|
@ -167,9 +163,6 @@
|
|||
|
||||
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
|
||||
|
||||
#define USB_VENDOR_ID_GENERIC_13BA 0x13ba
|
||||
#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017
|
||||
|
||||
#define USB_VENDOR_ID_GLAB 0x06c2
|
||||
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
|
||||
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
|
||||
|
@ -292,7 +285,6 @@
|
|||
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
|
||||
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
|
||||
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
|
||||
#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
|
||||
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
|
||||
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
|
||||
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
|
||||
|
@ -339,6 +331,9 @@
|
|||
#define USB_VENDOR_ID_NEC 0x073e
|
||||
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
|
||||
|
||||
#define USB_VENDOR_ID_NTRIG 0x1b96
|
||||
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_ONTRAK 0x0a07
|
||||
#define USB_DEVICE_ID_ONTRAK_ADU100 0x0064
|
||||
|
||||
|
@ -383,9 +378,15 @@
|
|||
#define USB_VENDOR_ID_TOPMAX 0x0663
|
||||
#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
|
||||
|
||||
#define USB_VENDOR_ID_TOPSEED 0x0766
|
||||
#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
|
||||
|
||||
#define USB_VENDOR_ID_TURBOX 0x062a
|
||||
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
|
||||
|
||||
#define USB_VENDOR_ID_UCLOGIC 0x5543
|
||||
#define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042
|
||||
|
||||
#define USB_VENDOR_ID_VERNIER 0x08f7
|
||||
#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
|
||||
#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#define LG_RDESC 0x001
|
||||
#define LG_BAD_RELATIVE_KEYS 0x002
|
||||
#define LG_DUPLICATE_USAGES 0x004
|
||||
#define LG_RESET_LEDS 0x008
|
||||
#define LG_EXPANDED_KEYMAP 0x010
|
||||
#define LG_IGNORE_DOUBLED_WHEEL 0x020
|
||||
#define LG_WIRELESS 0x040
|
||||
|
@ -248,9 +247,6 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
if (quirks & LG_RESET_LEDS)
|
||||
usbhid_set_leds(hdev);
|
||||
|
||||
if (quirks & LG_FF)
|
||||
lgff_init(hdev);
|
||||
if (quirks & LG_FF2)
|
||||
|
@ -279,9 +275,6 @@ static const struct hid_device_id lg_devices[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_DINOVO_MINI),
|
||||
.driver_data = LG_DUPLICATE_USAGES },
|
||||
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD),
|
||||
.driver_data = LG_RESET_LEDS },
|
||||
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD),
|
||||
.driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500),
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* HID driver for some ntrig "special" devices
|
||||
*
|
||||
* Copyright (c) 1999 Andreas Gal
|
||||
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
|
||||
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
|
||||
* Copyright (c) 2006-2007 Jiri Kosina
|
||||
* Copyright (c) 2007 Paul Walmsley
|
||||
* Copyright (c) 2008 Jiri Slaby
|
||||
* Copyright (c) 2008 Rafi Rubin
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define NTRIG_DUPLICATE_USAGES 0x001
|
||||
|
||||
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
|
||||
EV_KEY, (c))
|
||||
|
||||
static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
|
||||
(usage->hid & 0xff) == 0x47) {
|
||||
nt_map_key_clear(BTN_TOOL_DOUBLETAP);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if (usage->type == EV_KEY || usage->type == EV_REL
|
||||
|| usage->type == EV_ABS)
|
||||
clear_bit(usage->code, *bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static const struct hid_device_id ntrig_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
|
||||
.driver_data = NTRIG_DUPLICATE_USAGES },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ntrig_devices);
|
||||
|
||||
static struct hid_driver ntrig_driver = {
|
||||
.name = "ntrig",
|
||||
.id_table = ntrig_devices,
|
||||
.input_mapping = ntrig_input_mapping,
|
||||
.input_mapped = ntrig_input_mapped,
|
||||
};
|
||||
|
||||
static int ntrig_init(void)
|
||||
{
|
||||
return hid_register_driver(&ntrig_driver);
|
||||
}
|
||||
|
||||
static void ntrig_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&ntrig_driver);
|
||||
}
|
||||
|
||||
module_init(ntrig_init);
|
||||
module_exit(ntrig_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
HID_COMPAT_LOAD_DRIVER(ntrig);
|
|
@ -102,7 +102,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
}
|
||||
|
||||
ret = sony_set_operational(hdev);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
goto err_stop;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* HID driver for TopSeed Cyberlink remote
|
||||
*
|
||||
* Copyright (c) 2008 Lev Babiev
|
||||
* based on hid-cherry driver
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
#define ts_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
|
||||
EV_KEY, (c))
|
||||
static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
struct hid_field *field, struct hid_usage *usage,
|
||||
unsigned long **bit, int *max)
|
||||
{
|
||||
if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
|
||||
return 0;
|
||||
|
||||
switch (usage->hid & HID_USAGE) {
|
||||
case 0x00d: ts_map_key_clear(KEY_HOME); break;
|
||||
case 0x024: ts_map_key_clear(KEY_MENU); break;
|
||||
case 0x025: ts_map_key_clear(KEY_TV); break;
|
||||
case 0x048: ts_map_key_clear(KEY_RED); break;
|
||||
case 0x047: ts_map_key_clear(KEY_GREEN); break;
|
||||
case 0x049: ts_map_key_clear(KEY_YELLOW); break;
|
||||
case 0x04a: ts_map_key_clear(KEY_BLUE); break;
|
||||
case 0x04b: ts_map_key_clear(KEY_ANGLE); break;
|
||||
case 0x04c: ts_map_key_clear(KEY_LANGUAGE); break;
|
||||
case 0x04d: ts_map_key_clear(KEY_SUBTITLE); break;
|
||||
case 0x031: ts_map_key_clear(KEY_AUDIO); break;
|
||||
case 0x032: ts_map_key_clear(KEY_TEXT); break;
|
||||
case 0x033: ts_map_key_clear(KEY_CHANNEL); break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct hid_device_id ts_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ts_devices);
|
||||
|
||||
static struct hid_driver ts_driver = {
|
||||
.name = "topseed",
|
||||
.id_table = ts_devices,
|
||||
.input_mapping = ts_input_mapping,
|
||||
};
|
||||
|
||||
static int ts_init(void)
|
||||
{
|
||||
return hid_register_driver(&ts_driver);
|
||||
}
|
||||
|
||||
static void ts_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&ts_driver);
|
||||
}
|
||||
|
||||
module_init(ts_init);
|
||||
module_exit(ts_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
HID_COMPAT_LOAD_DRIVER(topseed);
|
|
@ -208,7 +208,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
|
|||
|
||||
list_del(&list->node);
|
||||
dev = hidraw_table[minor];
|
||||
if (!dev->open--) {
|
||||
if (!--dev->open) {
|
||||
if (list->hidraw->exist)
|
||||
dev->hid->ll_driver->close(dev->hid);
|
||||
else
|
||||
|
@ -265,6 +265,34 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
struct hid_device *hid = dev->hid;
|
||||
if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
|
||||
return -EINVAL;
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
|
||||
int len;
|
||||
if (!hid->name)
|
||||
return 0;
|
||||
len = strlen(hid->name) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
return copy_to_user(user_arg, hid->name, len) ?
|
||||
-EFAULT : len;
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
|
||||
int len;
|
||||
if (!hid->phys)
|
||||
return 0;
|
||||
len = strlen(hid->phys) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
return copy_to_user(user_arg, hid->phys, len) ?
|
||||
-EFAULT : len;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -ENOTTY;
|
||||
}
|
||||
unlock_kernel();
|
||||
|
@ -329,7 +357,7 @@ int hidraw_connect(struct hid_device *hid)
|
|||
goto out;
|
||||
}
|
||||
|
||||
dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
|
||||
dev->dev = device_create(hidraw_class, &hid->dev, MKDEV(hidraw_major, minor),
|
||||
NULL, "%s%d", "hidraw", minor);
|
||||
|
||||
if (IS_ERR(dev->dev)) {
|
||||
|
|
|
@ -45,7 +45,7 @@ config USB_HIDDEV
|
|||
If unsure, say Y.
|
||||
|
||||
menu "USB HID Boot Protocol drivers"
|
||||
depends on USB!=n && USB_HID!=y
|
||||
depends on USB!=n && USB_HID!=y && EMBEDDED
|
||||
|
||||
config USB_KBD
|
||||
tristate "USB HIDBP Keyboard (simple Boot) support"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Copyright (c) 1999 Andreas Gal
|
||||
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
|
||||
* Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
|
||||
* Copyright (c) 2006-2007 Jiri Kosina
|
||||
* Copyright (c) 2006-2008 Jiri Kosina
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -641,9 +641,7 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type,
|
|||
unsigned int size;
|
||||
|
||||
list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
|
||||
size = ((report->size - 1) >> 3) + 1;
|
||||
if (type == HID_INPUT_REPORT && hid->report_enum[type].numbered)
|
||||
size++;
|
||||
size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
|
||||
if (*max < size)
|
||||
*max = size;
|
||||
}
|
||||
|
@ -653,13 +651,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
|
|||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
|
||||
return -1;
|
||||
if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
|
||||
return -1;
|
||||
if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
|
||||
return -1;
|
||||
if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
|
||||
usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
|
||||
&usbhid->inbuf_dma);
|
||||
usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
|
||||
&usbhid->outbuf_dma);
|
||||
usbhid->cr = usb_buffer_alloc(dev, sizeof(*usbhid->cr), GFP_KERNEL,
|
||||
&usbhid->cr_dma);
|
||||
usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_KERNEL,
|
||||
&usbhid->ctrlbuf_dma);
|
||||
if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
|
||||
!usbhid->ctrlbuf)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
@ -807,7 +808,7 @@ static int usbhid_start(struct hid_device *hid)
|
|||
int interval;
|
||||
|
||||
endpoint = &interface->endpoint[n].desc;
|
||||
if ((endpoint->bmAttributes & 3) != 3) /* Not an interrupt endpoint */
|
||||
if (!usb_endpoint_xfer_int(endpoint))
|
||||
continue;
|
||||
|
||||
interval = endpoint->bInterval;
|
||||
|
@ -876,6 +877,15 @@ static int usbhid_start(struct hid_device *hid)
|
|||
|
||||
set_bit(HID_STARTED, &usbhid->iofl);
|
||||
|
||||
/* Some keyboards don't work until their LEDs have been set.
|
||||
* Since BIOSes do set the LEDs, it must be safe for any device
|
||||
* that supports the keyboard boot protocol.
|
||||
*/
|
||||
if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
|
||||
interface->desc.bInterfaceProtocol ==
|
||||
USB_INTERFACE_PROTOCOL_KEYBOARD)
|
||||
usbhid_set_leds(hid);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
|
@ -54,6 +54,7 @@ static const struct hid_blacklist {
|
|||
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
|
||||
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
|
||||
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
|
||||
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
struct hiddev {
|
||||
int exist;
|
||||
int open;
|
||||
struct mutex existancelock;
|
||||
wait_queue_head_t wait;
|
||||
struct hid_device *hid;
|
||||
struct list_head list;
|
||||
|
@ -63,6 +64,7 @@ struct hiddev_list {
|
|||
struct fasync_struct *fasync;
|
||||
struct hiddev *hiddev;
|
||||
struct list_head node;
|
||||
struct mutex thread_lock;
|
||||
};
|
||||
|
||||
static struct hiddev *hiddev_table[HIDDEV_MINORS];
|
||||
|
@ -264,29 +266,48 @@ static int hiddev_release(struct inode * inode, struct file * file)
|
|||
static int hiddev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct hiddev_list *list;
|
||||
unsigned long flags;
|
||||
int res;
|
||||
|
||||
int i = iminor(inode) - HIDDEV_MINOR_BASE;
|
||||
|
||||
if (i >= HIDDEV_MINORS || !hiddev_table[i])
|
||||
if (i >= HIDDEV_MINORS || i < 0 || !hiddev_table[i])
|
||||
return -ENODEV;
|
||||
|
||||
if (!(list = kzalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
mutex_init(&list->thread_lock);
|
||||
|
||||
list->hiddev = hiddev_table[i];
|
||||
|
||||
spin_lock_irqsave(&list->hiddev->list_lock, flags);
|
||||
list_add_tail(&list->node, &hiddev_table[i]->list);
|
||||
spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
|
||||
|
||||
file->private_data = list;
|
||||
|
||||
if (!list->hiddev->open++)
|
||||
if (list->hiddev->exist)
|
||||
usbhid_open(hiddev_table[i]->hid);
|
||||
/*
|
||||
* no need for locking because the USB major number
|
||||
* is shared which usbcore guards against disconnect
|
||||
*/
|
||||
if (list->hiddev->exist) {
|
||||
if (!list->hiddev->open++) {
|
||||
res = usbhid_open(hiddev_table[i]->hid);
|
||||
if (res < 0) {
|
||||
res = -EIO;
|
||||
goto bail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = -ENODEV;
|
||||
goto bail;
|
||||
}
|
||||
|
||||
spin_lock_irq(&list->hiddev->list_lock);
|
||||
list_add_tail(&list->node, &hiddev_table[i]->list);
|
||||
spin_unlock_irq(&list->hiddev->list_lock);
|
||||
|
||||
return 0;
|
||||
bail:
|
||||
file->private_data = NULL;
|
||||
kfree(list->hiddev);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -305,7 +326,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
|
|||
DECLARE_WAITQUEUE(wait, current);
|
||||
struct hiddev_list *list = file->private_data;
|
||||
int event_size;
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
|
||||
sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
|
||||
|
@ -313,10 +334,14 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
|
|||
if (count < event_size)
|
||||
return 0;
|
||||
|
||||
/* lock against other threads */
|
||||
retval = mutex_lock_interruptible(&list->thread_lock);
|
||||
if (retval)
|
||||
return -ERESTARTSYS;
|
||||
|
||||
while (retval == 0) {
|
||||
if (list->head == list->tail) {
|
||||
add_wait_queue(&list->hiddev->wait, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
|
||||
|
||||
while (list->head == list->tail) {
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
|
@ -332,35 +357,45 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
|
|||
break;
|
||||
}
|
||||
|
||||
/* let O_NONBLOCK tasks run */
|
||||
mutex_unlock(&list->thread_lock);
|
||||
schedule();
|
||||
if (mutex_lock_interruptible(&list->thread_lock))
|
||||
return -EINTR;
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
}
|
||||
finish_wait(&list->hiddev->wait, &wait);
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&list->hiddev->wait, &wait);
|
||||
}
|
||||
|
||||
if (retval)
|
||||
if (retval) {
|
||||
mutex_unlock(&list->thread_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
while (list->head != list->tail &&
|
||||
retval + event_size <= count) {
|
||||
if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
|
||||
if (list->buffer[list->tail].field_index !=
|
||||
HID_FIELD_INDEX_NONE) {
|
||||
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE) {
|
||||
struct hiddev_event event;
|
||||
|
||||
event.hid = list->buffer[list->tail].usage_code;
|
||||
event.value = list->buffer[list->tail].value;
|
||||
if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
|
||||
if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event))) {
|
||||
mutex_unlock(&list->thread_lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
retval += sizeof(struct hiddev_event);
|
||||
}
|
||||
} else {
|
||||
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
|
||||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
|
||||
if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
|
||||
|
||||
if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref))) {
|
||||
mutex_unlock(&list->thread_lock);
|
||||
return -EFAULT;
|
||||
}
|
||||
retval += sizeof(struct hiddev_usage_ref);
|
||||
}
|
||||
}
|
||||
|
@ -368,6 +403,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
|
|||
}
|
||||
|
||||
}
|
||||
mutex_unlock(&list->thread_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -555,7 +591,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
struct hid_field *field;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
void __user *user_arg = (void __user *)arg;
|
||||
int i;
|
||||
int i, r;
|
||||
|
||||
/* Called without BKL by compat methods so no BKL taken */
|
||||
|
||||
|
@ -619,10 +655,22 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
}
|
||||
|
||||
case HIDIOCGSTRING:
|
||||
return hiddev_ioctl_string(hiddev, cmd, user_arg);
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (!hiddev->exist)
|
||||
r = hiddev_ioctl_string(hiddev, cmd, user_arg);
|
||||
else
|
||||
r = -ENODEV;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return r;
|
||||
|
||||
case HIDIOCINITREPORT:
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (!hiddev->exist) {
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return -ENODEV;
|
||||
}
|
||||
usbhid_init_reports(hid);
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -636,8 +684,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
usbhid_submit_report(hid, report, USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist) {
|
||||
usbhid_submit_report(hid, report, USB_DIR_IN);
|
||||
usbhid_wait_io(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -651,8 +703,12 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
usbhid_wait_io(hid);
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist) {
|
||||
usbhid_submit_report(hid, report, USB_DIR_OUT);
|
||||
usbhid_wait_io(hid);
|
||||
}
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -710,7 +766,13 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case HIDIOCGUSAGES:
|
||||
case HIDIOCSUSAGES:
|
||||
case HIDIOCGCOLLECTIONINDEX:
|
||||
return hiddev_ioctl_usage(hiddev, cmd, user_arg);
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
if (hiddev->exist)
|
||||
r = hiddev_ioctl_usage(hiddev, cmd, user_arg);
|
||||
else
|
||||
r = -ENODEV;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
return r;
|
||||
|
||||
case HIDIOCGCOLLECTIONINFO:
|
||||
if (copy_from_user(&cinfo, user_arg, sizeof(cinfo)))
|
||||
|
@ -808,24 +870,23 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
|
|||
if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
|
||||
return -1;
|
||||
|
||||
init_waitqueue_head(&hiddev->wait);
|
||||
INIT_LIST_HEAD(&hiddev->list);
|
||||
spin_lock_init(&hiddev->list_lock);
|
||||
mutex_init(&hiddev->existancelock);
|
||||
hiddev->hid = hid;
|
||||
hiddev->exist = 1;
|
||||
|
||||
retval = usb_register_dev(usbhid->intf, &hiddev_class);
|
||||
if (retval) {
|
||||
err_hid("Not able to get a minor for this device.");
|
||||
kfree(hiddev);
|
||||
return -1;
|
||||
} else {
|
||||
hid->minor = usbhid->intf->minor;
|
||||
hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&hiddev->wait);
|
||||
INIT_LIST_HEAD(&hiddev->list);
|
||||
spin_lock_init(&hiddev->list_lock);
|
||||
hiddev->hid = hid;
|
||||
hiddev->exist = 1;
|
||||
|
||||
hid->minor = usbhid->intf->minor;
|
||||
hid->hiddev = hiddev;
|
||||
|
||||
hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -839,7 +900,9 @@ void hiddev_disconnect(struct hid_device *hid)
|
|||
struct hiddev *hiddev = hid->hiddev;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
mutex_lock(&hiddev->existancelock);
|
||||
hiddev->exist = 0;
|
||||
mutex_unlock(&hiddev->existancelock);
|
||||
|
||||
hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
|
||||
usb_deregister_dev(usbhid->intf, &hiddev_class);
|
||||
|
|
|
@ -40,6 +40,16 @@ int usbhid_open(struct hid_device *hid);
|
|||
void usbhid_init_reports(struct hid_device *hid);
|
||||
void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
|
||||
|
||||
/* iofl flags */
|
||||
#define HID_CTRL_RUNNING 1
|
||||
#define HID_OUT_RUNNING 2
|
||||
#define HID_IN_RUNNING 3
|
||||
#define HID_RESET_PENDING 4
|
||||
#define HID_SUSPENDED 5
|
||||
#define HID_CLEAR_HALT 6
|
||||
#define HID_DISCONNECTED 7
|
||||
#define HID_STARTED 8
|
||||
|
||||
/*
|
||||
* USB-specific HID struct, to be pointed to
|
||||
* from struct hid_device->driver_data
|
||||
|
|
|
@ -403,15 +403,6 @@ struct hid_output_fifo {
|
|||
#define HID_STAT_ADDED 1
|
||||
#define HID_STAT_PARSED 2
|
||||
|
||||
#define HID_CTRL_RUNNING 1
|
||||
#define HID_OUT_RUNNING 2
|
||||
#define HID_IN_RUNNING 3
|
||||
#define HID_RESET_PENDING 4
|
||||
#define HID_SUSPENDED 5
|
||||
#define HID_CLEAR_HALT 6
|
||||
#define HID_DISCONNECTED 7
|
||||
#define HID_STARTED 8
|
||||
|
||||
struct hid_input {
|
||||
struct list_head list;
|
||||
struct hid_report *report;
|
||||
|
@ -540,6 +531,8 @@ struct hid_usage_id {
|
|||
* @name: driver name (e.g. "Footech_bar-wheel")
|
||||
* @id_table: which devices is this driver for (must be non-NULL for probe
|
||||
* to be called)
|
||||
* @dyn_list: list of dynamically added device ids
|
||||
* @dyn_lock: lock protecting @dyn_list
|
||||
* @probe: new device inserted
|
||||
* @remove: device removed (NULL if not a hot-plug capable driver)
|
||||
* @report_table: on which reports to call raw_event (NULL means all)
|
||||
|
@ -567,6 +560,9 @@ struct hid_driver {
|
|||
char *name;
|
||||
const struct hid_device_id *id_table;
|
||||
|
||||
struct list_head dyn_list;
|
||||
spinlock_t dyn_lock;
|
||||
|
||||
int (*probe)(struct hid_device *dev, const struct hid_device_id *id);
|
||||
void (*remove)(struct hid_device *dev);
|
||||
|
||||
|
@ -797,6 +793,8 @@ dbg_hid(const char *fmt, ...)
|
|||
|
||||
#ifdef CONFIG_HID_COMPAT
|
||||
#define HID_COMPAT_LOAD_DRIVER(name) \
|
||||
/* prototype to avoid sparse warning */ \
|
||||
extern void hid_compat_##name(void); \
|
||||
void hid_compat_##name(void) { } \
|
||||
EXPORT_SYMBOL(hid_compat_##name)
|
||||
#else
|
||||
|
|
|
@ -33,6 +33,8 @@ struct hidraw_devinfo {
|
|||
#define HIDIOCGRDESCSIZE _IOR('H', 0x01, int)
|
||||
#define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor)
|
||||
#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
|
||||
#define HIDIOCGRAWNAME(len) _IOC(_IOC_READ, 'H', 0x04, len)
|
||||
#define HIDIOCGRAWPHYS(len) _IOC(_IOC_READ, 'H', 0x05, len)
|
||||
|
||||
#define HIDRAW_FIRST_MINOR 0
|
||||
#define HIDRAW_MAX_DEVICES 64
|
||||
|
|
Загрузка…
Ссылка в новой задаче