Commit e413b210 authored by Linus Torvalds's avatar Linus Torvalds

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: (55 commits)
  HID: build drivers for all quirky devices by default
  HID: add missing blacklist entry for Apple ATV ircontrol
  HID: add support for Bright ABNT2 brazilian device
  HID: Don't let Avermedia Radio FM800 be handled by usb hid drivers
  HID: fix numlock led on Dell device 0x413c/0x2105
  HID: remove warn() macro from usb hid drivers
  HID: remove info() macro from usb HID drivers
  HID: add appletv IR receiver quirk
  HID: fix a lockup regression when using force feedback on a PID device
  HID: hiddev.h: Fix example code.
  HID: hiddev.h: Fix mixed space and tabs in example code.
  HID: convert to dev_* prints
  HID: remove hid-ff
  HID: move zeroplus FF processing
  HID: move thrustmaster FF processing
  HID: move pantherlord FF processing
  HID: fix incorrent length condition in hidraw_write()
  HID: fix tty<->hid deadlock
  HID: ignore iBuddy devices
  HID: report descriptor fix for remaining MacBook JIS keyboards
  ...
parents acd15a83 9be7bbd5
...@@ -287,6 +287,13 @@ Who: Glauber Costa <gcosta@redhat.com> ...@@ -287,6 +287,13 @@ Who: Glauber Costa <gcosta@redhat.com>
--------------------------- ---------------------------
What: remove HID compat support
When: 2.6.29
Why: needed only as a temporary solution until distros fix themselves up
Who: Jiri Slaby <jirislaby@gmail.com>
---------------------------
What: /sys/o2cb symlink What: /sys/o2cb symlink
When: January 2010 When: January 2010
Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb
......
...@@ -17,6 +17,25 @@ config HID ...@@ -17,6 +17,25 @@ config HID
tristate "Generic HID support" tristate "Generic HID support"
depends on INPUT depends on INPUT
default y default y
select HID_A4TECH if !EMBEDDED
select HID_APPLE if !EMBEDDED
select HID_BELKIN if !EMBEDDED
select HID_BRIGHT if !EMBEDDED
select HID_CHERRY if !EMBEDDED
select HID_CHICONY if !EMBEDDED
select HID_CYPRESS if !EMBEDDED
select HID_DELL if !EMBEDDED
select HID_EZKEY if !EMBEDDED
select HID_GYRATION if !EMBEDDED
select HID_LOGITECH if !EMBEDDED
select HID_MICROSOFT if !EMBEDDED
select HID_MONTEREY if !EMBEDDED
select HID_PANTHERLORD if !EMBEDDED
select HID_PETALYNX if !EMBEDDED
select HID_SAMSUNG if !EMBEDDED
select HID_SONY if !EMBEDDED
select HID_SUNPLUS if !EMBEDDED
---help--- ---help---
A human interface device (HID) is a type of computer device that A human interface device (HID) is a type of computer device that
interacts directly with and takes input from humans. The term "HID" interacts directly with and takes input from humans. The term "HID"
...@@ -67,4 +86,206 @@ config HIDRAW ...@@ -67,4 +86,206 @@ config HIDRAW
source "drivers/hid/usbhid/Kconfig" source "drivers/hid/usbhid/Kconfig"
menu "Special HID drivers"
depends on HID
config HID_COMPAT
bool "Load all HID drivers on hid core load"
default y
---help---
Compatible option for older userspace. If you have system without udev
support of module loading through aliases and also old
module-init-tools which can't handle hid bus, choose Y here. Otherwise
say N. If you say N and your userspace is old enough, the only
functionality you lose is modules autoloading.
If unsure, say Y.
config HID_A4TECH
tristate "A4 tech"
default m
depends on USB_HID
---help---
Support for A4 tech X5 and WOP-35 / Trust 450L mice.
config HID_APPLE
tristate "Apple"
default m
depends on (USB_HID || BT_HIDP)
---help---
Support for some Apple devices which less or more break
HID specification.
Say Y here if you want support for the special keys (Fn, Numlock) on
Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB
keyboards.
If unsure, say M.
config HID_BELKIN
tristate "Belkin"
default m
depends on USB_HID
---help---
Support for Belkin Flip KVM and Wireless keyboard.
config HID_BRIGHT
tristate "Bright"
default m
depends on USB_HID
---help---
Support for Bright ABNT-2 keyboard.
config HID_CHERRY
tristate "Cherry"
default m
depends on USB_HID
---help---
Support for Cherry Cymotion.
config HID_CHICONY
tristate "Chicony"
default m
depends on USB_HID
---help---
Support for Chicony Tactical pad.
config HID_CYPRESS
tristate "Cypress"
default m
depends on USB_HID
---help---
Support for Cypress mouse and barcodes.
config HID_DELL
tristate "Dell"
default m
depends on USB_HID
---help---
Support for Dell W7658.
config HID_EZKEY
tristate "Ezkey"
default m
depends on USB_HID
---help---
Support for Ezkey mouse and barcodes.
config HID_GYRATION
tristate "Gyration"
default m
depends on USB_HID
---help---
Support for Gyration remote.
config HID_LOGITECH
tristate "Logitech"
default m
depends on USB_HID
---help---
Support for some Logitech devices which breaks less or more
HID specification.
config LOGITECH_FF
bool "Logitech force feedback"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
Say Y here if you have one of these devices:
- Logitech WingMan Cordless RumblePad
- Logitech WingMan Cordless RumblePad 2
- Logitech WingMan Force 3D
- Logitech Formula Force EX
- Logitech MOMO Force wheel
and if you want to enable force feedback for them.
Note: if you say N here, this device will still be supported, but without
force feedback.
config LOGIRUMBLEPAD2_FF
bool "Logitech Rumblepad 2 force feedback"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
Say Y here if you want to enable force feedback support for Logitech
Rumblepad 2 devices.
config HID_MICROSOFT
tristate "Microsoft"
default m
depends on USB_HID
---help---
Support for some Microsoft devices which breaks less or more
HID specification.
config HID_MONTEREY
tristate "Monterey"
default m
depends on USB_HID
---help---
Support for Monterey Genius KB29E.
config HID_PANTHERLORD
tristate "Pantherlord devices support"
default m
depends on USB_HID
---help---
Support for PantherLord/GreenAsia based device support.
config PANTHERLORD_FF
bool "Pantherlord force feedback support"
depends on HID_PANTHERLORD
select INPUT_FF_MEMLESS
help
Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter and want to enable force feedback support for it.
config HID_PETALYNX
tristate "Petalynx"
default m
depends on USB_HID
---help---
Support for Petalynx Maxter remote.
config HID_SAMSUNG
tristate "Samsung"
default m
depends on USB_HID
---help---
Support for Samsung IR remote.
config HID_SONY
tristate "Sony"
default m
depends on USB_HID
---help---
Support for Sony PS3 controller.
config HID_SUNPLUS
tristate "Sunplus"
default m
depends on USB_HID
---help---
Support for Sunplus WDesktop input device.
config THRUSTMASTER_FF
tristate "ThrustMaster devices support"
default m
depends on USB_HID
select INPUT_FF_MEMLESS
help
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
config ZEROPLUS_FF
tristate "Zeroplus based game controller support"
default m
depends on USB_HID
select INPUT_FF_MEMLESS
help
Say Y here if you have a Zeroplus based game controller.
endmenu
endif # HID_SUPPORT endif # HID_SUPPORT
# #
# Makefile for the HID driver # Makefile for the HID driver
# #
hid-objs := hid-core.o hid-input.o hid-input-quirks.o hid-objs := hid-core.o hid-input.o
obj-$(CONFIG_HID) += hid.o obj-$(CONFIG_HID) += hid.o
hid-$(CONFIG_HID_DEBUG) += hid-debug.o hid-$(CONFIG_HID_DEBUG) += hid-debug.o
hid-$(CONFIG_HIDRAW) += hidraw.o hid-$(CONFIG_HIDRAW) += hidraw.o
ifdef CONFIG_HID_COMPAT
obj-m += hid-dummy.o
endif
hid-logitech-objs := hid-lg.o
ifdef CONFIG_LOGITECH_FF
hid-logitech-objs += hid-lgff.o
endif
ifdef CONFIG_LOGIRUMBLEPAD2_FF
hid-logitech-objs += hid-lg2ff.o
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_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_THRUSTMASTER_FF) += hid-tmff.o
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/
obj-$(CONFIG_USB_KBD) += usbhid/ obj-$(CONFIG_USB_KBD) += usbhid/
......
/*
* HID driver for some a4tech "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/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define A4_2WHEEL_MOUSE_HACK_7 0x01
#define A4_2WHEEL_MOUSE_HACK_B8 0x02
struct a4tech_sc {
unsigned long quirks;
unsigned int hw_wheel;
__s32 delayed_value;
};
static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
struct a4tech_sc *a4 = hid_get_drvdata(hdev);
if (usage->type == EV_REL && usage->code == REL_WHEEL)
set_bit(REL_HWHEEL, *bit);
if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007)
return -1;
return 0;
}
static int a4_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct a4tech_sc *a4 = hid_get_drvdata(hdev);
struct input_dev *input;
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
!usage->type)
return 0;
input = field->hidinput->input;
if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) {
if (usage->type == EV_REL && usage->code == REL_WHEEL) {
a4->delayed_value = value;
return 1;
}
if (usage->hid == 0x000100b8) {
input_event(input, EV_REL, value ? REL_HWHEEL :
REL_WHEEL, a4->delayed_value);
return 1;
}
}
if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) {
a4->hw_wheel = !!value;
return 1;
}
if (usage->code == REL_WHEEL && a4->hw_wheel) {
input_event(input, usage->type, REL_HWHEEL, value);
return 1;
}
return 0;
}
static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
struct a4tech_sc *a4;
int ret;
a4 = kzalloc(sizeof(*a4), GFP_KERNEL);
if (a4 == NULL) {
dev_err(&hdev->dev, "can't alloc device descriptor\n");
ret = -ENOMEM;
goto err_free;
}
a4->quirks = id->driver_data;
hid_set_drvdata(hdev, a4);
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;
}
return 0;
err_free:
kfree(a4);
return ret;
}
static void a4_remove(struct hid_device *hdev)
{
struct a4tech_sc *a4 = hid_get_drvdata(hdev);
hid_hw_stop(hdev);
kfree(a4);
}
static const struct hid_device_id a4_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU),
.driver_data = A4_2WHEEL_MOUSE_HACK_7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),
.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
{ }
};
MODULE_DEVICE_TABLE(hid, a4_devices);
static struct hid_driver a4_driver = {
.name = "a4tech",
.id_table = a4_devices,
.input_mapped = a4_input_mapped,
.event = a4_event,
.probe = a4_probe,
.remove = a4_remove,
};
static int a4_init(void)
{
return hid_register_driver(&a4_driver);
}
static void a4_exit(void)
{
hid_unregister_driver(&a4_driver);
}
module_init(a4_init);
module_exit(a4_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(a4tech);
This diff is collapsed.
/*
* HID driver for some belkin "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"
#define BELKIN_HIDDEV 0x01
#define BELKIN_WKBD 0x02
#define belkin_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int belkin_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER ||
!(quirks & BELKIN_WKBD))
return 0;
switch (usage->hid & HID_USAGE) {
case 0x03a: belkin_map_key_clear(KEY_SOUND); break;
case 0x03b: belkin_map_key_clear(KEY_CAMERA); break;
case 0x03c: belkin_map_key_clear(KEY_DOCUMENTS); break;
default:
return 0;
}
return 1;
}
static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
unsigned long quirks = id->driver_data;
int ret;
hid_set_drvdata(hdev, (void *)quirks);
ret = hid_parse(hdev);
if (ret) {
dev_err(&hdev->dev, "parse failed\n");
goto err_free;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
((quirks & BELKIN_HIDDEV) ? HID_CONNECT_HIDDEV_FORCE : 0));
if (ret) {
dev_err(&hdev->dev, "hw start failed\n");
goto err_free;
}
return 0;
err_free:
return ret;
}
static const struct hid_device_id belkin_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM),
.driver_data = BELKIN_HIDDEV },
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD),
.driver_data = BELKIN_WKBD },
{ }
};
MODULE_DEVICE_TABLE(hid, belkin_devices);
static struct hid_driver belkin_driver = {
.name = "belkin",
.id_table = belkin_devices,
.input_mapping = belkin_input_mapping,
.probe = belkin_probe,
};
static int belkin_init(void)
{
return hid_register_driver(&belkin_driver);
}
static void belkin_exit(void)
{
hid_unregister_driver(&belkin_driver);
}
module_init(belkin_init);
module_exit(belkin_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(belkin);
/*
* 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);
/*
* HID driver for some cherry "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"
/*
* Cherry Cymotion keyboard have an invalid HID report descriptor,
* that needs fixing before we can parse it.
*/
static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int rsize)
{
if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
dev_info(&hdev->dev, "fixing up Cherry Cymotion report "
"descriptor\n");
rdesc[11] = rdesc[16] = 0xff;
rdesc[12] = rdesc[17] = 0x03;
}
}
#define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int ch_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_CONSUMER)
return 0;
switch (usage->hid & HID_USAGE) {
case 0x301: ch_map_key_clear(KEY_PROG1); break;
case 0x302: ch_map_key_clear(KEY_PROG2); break;
case 0x303: ch_map_key_clear(KEY_PROG3); break;
default:
return 0;
}
return 1;
}
static const struct hid_device_id ch_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) },
{ }
};
MODULE_DEVICE_TABLE(hid, ch_devices);
static struct hid_driver ch_driver = {
.name = "cherry",
.id_table = ch_devices,
.report_fixup = ch_report_fixup,
.input_mapping = ch_input_mapping,
};
static int ch_init(void)
{
return hid_register_driver(&ch_driver);
}
static void ch_exit(void)
{
hid_unregister_driver(&ch_driver);
}
module_init(ch_init);
module_exit(ch_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(cherry);
/*
* HID driver for some chicony "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/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int ch_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_MSVENDOR)
return 0;
set_bit(EV_REP, hi->input->evbit);
switch (usage->hid & HID_USAGE) {
case 0xff01: ch_map_key_clear(BTN_1); break;
case 0xff02: ch_map_key_clear(BTN_2); break;
case 0xff03: ch_map_key_clear(BTN_3); break;
case 0xff04: ch_map_key_clear(BTN_4); break;
case 0xff05: ch_map_key_clear(BTN_5); break;
case 0xff06: ch_map_key_clear(BTN_6); break;
case 0xff07: ch_map_key_clear(BTN_7); break;
case 0xff08: ch_map_key_clear(BTN_8); break;
case 0xff09: ch_map_key_clear(BTN_9); break;
case 0xff0a: ch_map_key_clear(BTN_A); break;
case 0xff0b: ch_map_key_clear(BTN_B); break;
default:
return 0;
}
return 1;
}
static const struct hid_device_id ch_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ }
};
MODULE_DEVICE_TABLE(hid, ch_devices);
static struct hid_driver ch_driver = {
.name = "chicony",
.id_table = ch_devices,
.input_mapping = ch_input_mapping,
};
static int ch_init(void)
{
return hid_register_driver(&ch_driver);
}
static void ch_exit(void)
{
hid_unregister_driver(&ch_driver);
}
module_init(ch_init);
module_exit(ch_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(chicony);
This diff is collapsed.
/*
* HID driver for some cypress "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/input.h>
#include <linux/module.h>
#include "hid-ids.h"
#define CP_RDESC_SWAPPED_MIN_MAX 0x01
#define CP_2WHEEL_MOUSE_HACK 0x02
#define CP_2WHEEL_MOUSE_HACK_ON 0x04
/*
* Some USB barcode readers from cypress have usage min and usage max in
* the wrong order
*/
static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int rsize)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
unsigned int i;
if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
return;
for (i = 0; i < rsize - 4; i++)
if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
__u8 tmp;
rdesc[i] = 0x19;
rdesc[i + 2] = 0x29;
tmp = rdesc[i + 3];
rdesc[i + 3] = rdesc[i + 1];
rdesc[i + 1] = tmp;
}
}
static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if (!(quirks & CP_2WHEEL_MOUSE_HACK))
return 0;
if (usage->type == EV_REL && usage->code == REL_WHEEL)
set_bit(REL_HWHEEL, *bit);
if (usage->hid == 0x00090005)
return -1;
return 0;
}
static int cp_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
!usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK))
return 0;
if (usage->hid == 0x00090005) {
if (value)
quirks |= CP_2WHEEL_MOUSE_HACK_ON;
else
quirks &= ~CP_2WHEEL_MOUSE_HACK_ON;
hid_set_drvdata(hdev, (void *)quirks);
return 1;
}
if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) {
struct input_dev *input = field->hidinput->input;
input_event(input, usage->type, REL_HWHEEL, value);
return 1;
}
return 0;
}
static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
unsigned long quirks = id->driver_data;
int ret;
hid_set_drvdata(hdev, (void *)quirks);
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;
}
return 0;
err_free:
return ret;
}
static const struct hid_device_id cp_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1),
.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2),
.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
.driver_data = CP_2WHEEL_MOUSE_HACK },
{ }
};
MODULE_DEVICE_TABLE(hid, cp_devices);
static struct hid_driver cp_driver = {
.name = "cypress",
.id_table = cp_devices,
.report_fixup = cp_report_fixup,
.input_mapped = cp_input_mapped,
.event = cp_event,
.probe = cp_probe,
};
static int cp_init(void)
{
return hid_register_driver(&cp_driver);
}
static void cp_exit(void)
{
hid_unregister_driver(&cp_driver);
}
module_init(cp_init);
module_exit(cp_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(cypress);
/*
* 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) },
{ }
};
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);
#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/hid.h>
static int __init hid_dummy_init(void)
{
#ifdef CONFIG_HID_A4TECH_MODULE
HID_COMPAT_CALL_DRIVER(a4tech);
#endif
#ifdef CONFIG_HID_APPLE_MODULE
HID_COMPAT_CALL_DRIVER(apple);
#endif
#ifdef CONFIG_HID_BELKIN_MODULE
HID_COMPAT_CALL_DRIVER(belkin);
#endif
#ifdef CONFIG_HID_BRIGHT_MODULE
HID_COMPAT_CALL_DRIVER(bright);
#endif
#ifdef CONFIG_HID_CHERRY_MODULE
HID_COMPAT_CALL_DRIVER(cherry);
#endif
#ifdef CONFIG_HID_CHICONY_MODULE
HID_COMPAT_CALL_DRIVER(chicony);
#endif
#ifdef CONFIG_HID_CYPRESS_MODULE
HID_COMPAT_CALL_DRIVER(cypress);
#endif
#ifdef CONFIG_HID_DELL_MODULE
HID_COMPAT_CALL_DRIVER(dell);
#endif
#ifdef CONFIG_HID_EZKEY_MODULE
HID_COMPAT_CALL_DRIVER(ezkey);
#endif
#ifdef CONFIG_HID_GYRATION_MODULE
HID_COMPAT_CALL_DRIVER(gyration);
#endif
#ifdef CONFIG_HID_LOGITECH_MODULE
HID_COMPAT_CALL_DRIVER(logitech);
#endif
#ifdef CONFIG_HID_MICROSOFT_MODULE
HID_COMPAT_CALL_DRIVER(microsoft);
#endif
#ifdef CONFIG_HID_MONTEREY_MODULE
HID_COMPAT_CALL_DRIVER(monterey);
#endif
#ifdef CONFIG_HID_PANTHERLORD_MODULE
HID_COMPAT_CALL_DRIVER(pantherlord);
#endif
#ifdef CONFIG_HID_PETALYNX_MODULE
HID_COMPAT_CALL_DRIVER(petalynx);
#endif
#ifdef CONFIG_HID_SAMSUNG_MODULE
HID_COMPAT_CALL_DRIVER(samsung);
#endif
#ifdef CONFIG_HID_SONY_MODULE
HID_COMPAT_CALL_DRIVER(sony);
#endif
#ifdef CONFIG_HID_SUNPLUS_MODULE
HID_COMPAT_CALL_DRIVER(sunplus);
#endif
#ifdef CONFIG_THRUSTMASTER_FF_MODULE
HID_COMPAT_CALL_DRIVER(thrustmaster);
#endif
#ifdef CONFIG_ZEROPLUS_FF_MODULE
HID_COMPAT_CALL_DRIVER(zeroplus);
#endif
return -EIO;
}
module_init(hid_dummy_init);
MODULE_LICENSE("GPL");
/*
* HID driver for some ezkey "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/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define ez_map_rel(c) hid_map_usage(hi, usage, bit, max, EV_REL, (c))
#define ez_map_key(c) hid_map_usage(hi, usage, bit, max, EV_KEY, (c))
static int ez_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_CONSUMER)
return 0;
switch (usage->hid & HID_USAGE) {
case 0x230: ez_map_key(BTN_MOUSE); break;
case 0x231: ez_map_rel(REL_WHEEL); break;
/*
* this keyboard has a scrollwheel implemented in
* totally broken way. We map this usage temporarily
* to HWHEEL and handle it in the event quirk handler
*/
case 0x232: ez_map_rel(REL_HWHEEL); break;
default:
return 0;
}
return 1;
}
static int ez_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
!usage->type)
return 0;
/* handle the temporary quirky mapping to HWHEEL */
if (usage->type == EV_REL && usage->code == REL_HWHEEL) {
struct input_dev *input = field->hidinput->input;
input_event(input, usage->type, REL_WHEEL, -value);
return 1;
}
return 0;
}
static const struct hid_device_id ez_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
{ }
};
MODULE_DEVICE_TABLE(hid, ez_devices);
static struct hid_driver ez_driver = {
.name = "ezkey",
.id_table = ez_devices,
.input_mapping = ez_input_mapping,
.event = ez_event,
};
static int ez_init(void)
{
return hid_register_driver(&ez_driver);
}
static void ez_exit(void)
{
hid_unregister_driver(&ez_driver);
}
module_init(ez_init);
module_exit(ez_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(ezkey);
/*
* HID driver for some gyration "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/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define gy_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int gyration_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_LOGIVENDOR)
return 0;
set_bit(EV_REP, hi->input->evbit);
switch (usage->hid & HID_USAGE) {
/* Reported on Gyration MCE Remote */
case 0x00d: gy_map_key_clear(KEY_HOME); break;
case 0x024: gy_map_key_clear(KEY_DVD); break;
case 0x025: gy_map_key_clear(KEY_PVR); break;
case 0x046: gy_map_key_clear(KEY_MEDIA); break;
case 0x047: gy_map_key_clear(KEY_MP3); break;
case 0x049: gy_map_key_clear(KEY_CAMERA); break;
case 0x04a: gy_map_key_clear(KEY_VIDEO); break;
default:
return 0;
}
return 1;
}
static int gyration_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
struct input_dev *input = field->hidinput->input;
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK &&
(usage->hid & 0xff) == 0x82) {
input_event(input, usage->type, usage->code, 1);
input_sync(input);
input_event(input, usage->type, usage->code, 0);
input_sync(input);
return 1;
}
return 0;
}
static const struct hid_device_id gyration_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
{ }
};
MODULE_DEVICE_TABLE(hid, gyration_devices);
static struct hid_driver gyration_driver = {
.name = "gyration",
.id_table = gyration_devices,
.input_mapping = gyration_input_mapping,
.event = gyration_event,
};
static int gyration_init(void)
{
return hid_register_driver(&gyration_driver);
}
static void gyration_exit(void)
{
hid_unregister_driver(&gyration_driver);
}
module_init(gyration_init);
module_exit(gyration_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(gyration);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef __HID_LG_H
#define __HID_LG_H
#include <linux/autoconf.h>
#ifdef CONFIG_LOGITECH_FF
int lgff_init(struct hid_device *hdev);
#else
static inline int lgff_init(struct hid_device *hdev) { return -1; }
#endif
#ifdef CONFIG_LOGIRUMBLEPAD2_FF
int lg2ff_init(struct hid_device *hdev);
#else
static inline int lg2ff_init(struct hid_device *hdev) { return -1; }
#endif
#endif
...@@ -24,7 +24,9 @@ ...@@ -24,7 +24,9 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid.h"
#include "usbhid/usbhid.h"
#include "hid-lg.h"
struct lg2ff_device { struct lg2ff_device {
struct hid_report *report; struct hid_report *report;
...@@ -57,7 +59,7 @@ static int play_effect(struct input_dev *dev, void *data, ...@@ -57,7 +59,7 @@ static int play_effect(struct input_dev *dev, void *data,
return 0; return 0;
} }
int hid_lg2ff_init(struct hid_device *hid) int lg2ff_init(struct hid_device *hid)
{ {
struct lg2ff_device *lg2ff; struct lg2ff_device *lg2ff;
struct hid_report *report; struct hid_report *report;
...@@ -69,18 +71,18 @@ int hid_lg2ff_init(struct hid_device *hid) ...@@ -69,18 +71,18 @@ int hid_lg2ff_init(struct hid_device *hid)
int error; int error;
if (list_empty(report_list)) { if (list_empty(report_list)) {
printk(KERN_ERR "hid-lg2ff: no output report found\n"); dev_err(&hid->dev, "no output report found\n");
return -ENODEV; return -ENODEV;
} }
report = list_entry(report_list->next, struct hid_report, list); report = list_entry(report_list->next, struct hid_report, list);
if (report->maxfield < 1) { if (report->maxfield < 1) {
printk(KERN_ERR "hid-lg2ff: output report is empty\n"); dev_err(&hid->dev, "output report is empty\n");
return -ENODEV; return -ENODEV;
} }
if (report->field[0]->report_count < 7) { if (report->field[0]->report_count < 7) {
printk(KERN_ERR "hid-lg2ff: not enough values in the field\n"); dev_err(&hid->dev, "not enough values in the field\n");
return -ENODEV; return -ENODEV;
} }
...@@ -107,7 +109,7 @@ int hid_lg2ff_init(struct hid_device *hid) ...@@ -107,7 +109,7 @@ int hid_lg2ff_init(struct hid_device *hid)
usbhid_submit_report(hid, report, USB_DIR_OUT); usbhid_submit_report(hid, report, USB_DIR_OUT);
printk(KERN_INFO "Force feedback for Logitech Rumblepad 2 by " dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by "
"Anssi Hannula <anssi.hannula@gmail.com>\n"); "Anssi Hannula <anssi.hannula@gmail.com>\n");
return 0; return 0;
......
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/hid.h> #include <linux/hid.h>
#include "usbhid.h"
#include "usbhid/usbhid.h"
#include "hid-lg.h"
struct dev_type { struct dev_type {
u16 idVendor; u16 idVendor;
...@@ -48,6 +50,12 @@ static const signed short ff_joystick[] = { ...@@ -48,6 +50,12 @@ static const signed short ff_joystick[] = {
-1 -1
}; };
static const signed short ff_wheel[] = {
FF_CONSTANT,
FF_AUTOCENTER,
-1
};
static const struct dev_type devices[] = { static const struct dev_type devices[] = {
{ 0x046d, 0xc211, ff_rumble }, { 0x046d, 0xc211, ff_rumble },
{ 0x046d, 0xc219, ff_rumble }, { 0x046d, 0xc219, ff_rumble },
...@@ -55,7 +63,7 @@ static const struct dev_type devices[] = { ...@@ -55,7 +63,7 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc286, ff_joystick }, { 0x046d, 0xc286, ff_joystick },
{ 0x046d, 0xc294, ff_joystick }, { 0x046d, 0xc294, ff_joystick },
{ 0x046d, 0xc295, ff_joystick }, { 0x046d, 0xc295, ff_joystick },
{ 0x046d, 0xca03, ff_joystick }, { 0x046d, 0xca03, ff_wheel },
}; };
static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect) static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
...@@ -100,7 +108,24 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef ...@@ -100,7 +108,24 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
return 0; return 0;
} }
int hid_lgff_init(struct hid_device* hid) static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude)
{
struct hid_device *hid = input_get_drvdata(dev);
struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
__s32 *value = report->field[0]->value;
magnitude = (magnitude >> 12) & 0xf;
*value++ = 0xfe;
*value++ = 0x0d;
*value++ = magnitude; /* clockwise strength */
*value++ = magnitude; /* counter-clockwise strength */
*value++ = 0x80;
*value++ = 0x00;
*value = 0x00;
usbhid_submit_report(hid, report, USB_DIR_OUT);
}
int lgff_init(struct hid_device* hid)
{ {
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 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_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
...@@ -145,6 +170,9 @@ int hid_lgff_init(struct hid_device* hid) ...@@ -145,6 +170,9 @@ int hid_lgff_init(struct hid_device* hid)
if (error) if (error)
return error; return error;
if ( test_bit(FF_AUTOCENTER, dev->ffbit) )
dev->ff->set_autocenter = hid_lgff_set_autocenter;
printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n");
return 0; return 0;
......
/*
* HID driver for some microsoft "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/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
#define MS_HIDINPUT 0x01
#define MS_ERGONOMY 0x02
#define MS_PRESENTER 0x04
#define MS_RDESC 0x08
#define MS_NOGET 0x10
/*
* Microsoft Wireless Desktop Receiver (Model 1028) has several
* 'Usage Min/Max' where it ought to have 'Physical Min/Max'
*/
static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int rsize)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if ((quirks & MS_RDESC) && rsize == 571 && rdesc[284] == 0x19 &&
rdesc[286] == 0x2a && rdesc[304] == 0x19 &&
rdesc[306] == 0x29 && rdesc[352] == 0x1a &&
rdesc[355] == 0x2a && rdesc[557] == 0x19 &&
rdesc[559] == 0x29) {
dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver "
"Model 1028 report descriptor\n");
rdesc[284] = rdesc[304] = rdesc[557] = 0x35;
rdesc[352] = 0x36;
rdesc[286] = rdesc[355] = 0x46;
rdesc[306] = rdesc[559] = 0x45;
}
}
#define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int ms_ergonomy_kb_quirk(struct hid_input *hi, struct hid_usage *usage,
unsigned long **bit, int *max)
{
struct input_dev *input = hi->input;
switch (usage->hid & HID_USAGE) {
case 0xfd06: ms_map_key_clear(KEY_CHAT); break;
case 0xfd07: ms_map_key_clear(KEY_PHONE); break;
case 0xff05:
set_bit(EV_REP, input->evbit);
ms_map_key_clear(KEY_F13);
set_bit(KEY_F14, input->keybit);
set_bit(KEY_F15, input->keybit);
set_bit(KEY_F16, input->keybit);
set_bit(KEY_F17, input->keybit);
set_bit(KEY_F18, input->keybit);
default:
return 0;
}
return 1;
}
static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage,
unsigned long **bit, int *max)
{
set_bit(EV_REP, hi->input->evbit);
switch (usage->hid & HID_USAGE) {
case 0xfd08: ms_map_key_clear(KEY_FORWARD); break;
case 0xfd09: ms_map_key_clear(KEY_BACK); break;
case 0xfd0b: ms_map_key_clear(KEY_PLAYPAUSE); break;
case 0xfd0e: ms_map_key_clear(KEY_CLOSE); break;
case 0xfd0f: ms_map_key_clear(KEY_PLAY); break;
default:
return 0;
}
return 1;
}
static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
return 0;
if (quirks & MS_ERGONOMY) {
int ret = ms_ergonomy_kb_quirk(hi, usage, bit, max);
if (ret)
return ret;
}
if ((quirks & MS_PRESENTER) &&
ms_presenter_8k_quirk(hi, usage, bit, max))
return 1;
return 0;
}
static int ms_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
!usage->type)
return 0;
/* Handling MS keyboards special buttons */
if (quirks & MS_ERGONOMY && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
struct input_dev *input = field->hidinput->input;
static unsigned int last_key = 0;
unsigned int key = 0;
switch (value) {
case 0x01: key = KEY_F14; break;
case 0x02: key = KEY_F15; break;
case 0x04: key = KEY_F16; break;
case 0x08: key = KEY_F17; break;
case 0x10: key = KEY_F18; break;
}
if (key) {
input_event(input, usage->type, key, 1);
last_key = key;
} else
input_event(input, usage->type, last_key, 0);
return 1;
}
return 0;
}
static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
unsigned long quirks = id->driver_data;
int ret;
hid_set_drvdata(hdev, (void *)quirks);
if (quirks & MS_NOGET)
hdev->quirks |= HID_QUIRK_NOGET;
ret = hid_parse(hdev);
if (ret) {
dev_err(&hdev->dev, "parse failed\n");
goto err_free;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | ((quirks & MS_HIDINPUT) ?
HID_CONNECT_HIDINPUT_FORCE : 0));
if (ret) {
dev_err(&hdev->dev, "hw start failed\n");
goto err_free;
}
return 0;
err_free:
return ret;
}
static const struct hid_device_id ms_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV),
.driver_data = MS_HIDINPUT },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K),
.driver_data = MS_ERGONOMY },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K),
.driver_data = MS_ERGONOMY | MS_RDESC },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
.driver_data = MS_PRESENTER },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
.driver_data = MS_NOGET },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
.driver_data = MS_PRESENTER },
{ }
};
MODULE_DEVICE_TABLE(hid, ms_devices);
static struct hid_driver ms_driver = {
.name = "microsoft",
.id_table = ms_devices,
.report_fixup = ms_report_fixup,
.input_mapping = ms_input_mapping,
.event = ms_event,
.probe = ms_probe,
};
static int ms_init(void)
{
return hid_register_driver(&ms_driver);
}
static void ms_exit(void)
{
hid_unregister_driver(&ms_driver);
}
module_init(ms_init);
module_exit(ms_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(microsoft);
/*
* HID driver for some monterey "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 void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int rsize)
{
if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) {
dev_info(&hdev->dev, "fixing up button/consumer in HID report "
"descriptor\n");
rdesc[30] = 0x0c;
}
}
#define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int mr_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_CONSUMER)
return 0;
switch (usage->hid & HID_USAGE) {
case 0x156: mr_map_key_clear(KEY_WORDPROCESSOR); break;
case 0x157: mr_map_key_clear(KEY_SPREADSHEET); break;
case 0x158: mr_map_key_clear(KEY_PRESENTATION); break;
case 0x15c: mr_map_key_clear(KEY_STOP); break;
default:
return 0;
}
return 1;
}
static const struct hid_device_id mr_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) },
{ }
};
MODULE_DEVICE_TABLE(hid, mr_devices);
static struct hid_driver mr_driver = {
.name = "monterey",
.id_table = mr_devices,
.report_fixup = mr_report_fixup,
.input_mapping = mr_input_mapping,
};
static int mr_init(void)
{
return hid_register_driver(&mr_driver);
}
static void mr_exit(void)
{
hid_unregister_driver(&mr_driver);
}
module_init(mr_init);
module_exit(mr_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(monterey);
/*
* HID driver for some petalynx "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"
/* Petalynx Maxter Remote has maximum for consumer page set too low */
static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int rsize)
{
if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 &&
rdesc[41] == 0x00 && rdesc[59] == 0x26 &&
rdesc[60] == 0xf9 && rdesc[61] == 0x00) {
dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report "
"descriptor\n");
rdesc[60] = 0xfa;
rdesc[40] = 0xfa;
}
}
#define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
EV_KEY, (c))
static int pl_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_LOGIVENDOR) {
switch (usage->hid & HID_USAGE) {
case 0x05a: pl_map_key_clear(KEY_TEXT); break;
case 0x05b: pl_map_key_clear(KEY_RED); break;
case 0x05c: pl_map_key_clear(KEY_GREEN); break;
case 0x05d: pl_map_key_clear(KEY_YELLOW); break;
case 0x05e: pl_map_key_clear(KEY_BLUE); break;
default:
return 0;
}
return 1;
}
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) {
switch (usage->hid & HID_USAGE) {
case 0x0f6: pl_map_key_clear(KEY_NEXT); break;
case 0x0fa: pl_map_key_clear(KEY_BACK); break;
default:
return 0;
}
return 1;
}
return 0;
}
static int pl_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
hdev->quirks |= HID_QUIRK_NOGET;
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;
}
return 0;
err_free:
return ret;
}
static const struct hid_device_id pl_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
{ }
};
MODULE_DEVICE_TABLE(hid, pl_devices);
static struct hid_driver pl_driver = {
.name = "petalynx",
.id_table = pl_devices,
.report_fixup = pl_report_fixup,
.input_mapping = pl_input_mapping,
.probe = pl_probe,
};
static int pl_init(void)
{
return hid_register_driver(&pl_driver);
}
static void pl_exit(void)
{
hid_unregister_driver(&pl_driver);
}
module_init(pl_init);
module_exit(pl_exit);
MODULE_LICENSE("GPL");
HID_COMPAT_LOAD_DRIVER(petalynx);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -113,7 +113,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t ...@@ -113,7 +113,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
if (!dev->hid_output_raw_report) if (!dev->hid_output_raw_report)
return -ENODEV; return -ENODEV;
if (count > HID_MIN_BUFFER_SIZE) { if (count > HID_MAX_BUFFER_SIZE) {
printk(KERN_WARNING "hidraw: pid %d passed too large report\n", printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
task_pid_nr(current)); task_pid_nr(current));
return -EINVAL; return -EINVAL;
...@@ -181,7 +181,7 @@ static int hidraw_open(struct inode *inode, struct file *file) ...@@ -181,7 +181,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
dev = hidraw_table[minor]; dev = hidraw_table[minor];
if (!dev->open++) if (!dev->open++)
dev->hid->hid_open(dev->hid); dev->hid->ll_driver->open(dev->hid);
out_unlock: out_unlock:
spin_unlock(&minors_lock); spin_unlock(&minors_lock);
...@@ -207,7 +207,7 @@ static int hidraw_release(struct inode * inode, struct file * file) ...@@ -207,7 +207,7 @@ static int hidraw_release(struct inode * inode, struct file * file)
dev = hidraw_table[minor]; dev = hidraw_table[minor];
if (!dev->open--) { if (!dev->open--) {
if (list->hidraw->exist) if (list->hidraw->exist)
dev->hid->hid_close(dev->hid); dev->hid->ll_driver->close(dev->hid);
else else
kfree(list->hidraw); kfree(list->hidraw);
} }
...@@ -367,7 +367,7 @@ void hidraw_disconnect(struct hid_device *hid) ...@@ -367,7 +367,7 @@ void hidraw_disconnect(struct hid_device *hid)
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
if (hidraw->open) { if (hidraw->open) {
hid->hid_close(hid); hid->ll_driver->close(hid);
wake_up_interruptible(&hidraw->wait); wake_up_interruptible(&hidraw->wait);
} else { } else {
kfree(hidraw); kfree(hidraw);
......
This diff is collapsed.
...@@ -13,24 +13,6 @@ endif ...@@ -13,24 +13,6 @@ endif
ifeq ($(CONFIG_HID_PID),y) ifeq ($(CONFIG_HID_PID),y)
usbhid-objs += hid-pidff.o usbhid-objs += hid-pidff.o
endif endif
ifeq ($(CONFIG_LOGITECH_FF),y)
usbhid-objs += hid-lgff.o
endif
ifeq ($(CONFIG_LOGIRUMBLEPAD2_FF),y)
usbhid-objs += hid-lg2ff.o
endif
ifeq ($(CONFIG_PANTHERLORD_FF),y)
usbhid-objs += hid-plff.o
endif
ifeq ($(CONFIG_THRUSTMASTER_FF),y)
usbhid-objs += hid-tmff.o
endif
ifeq ($(CONFIG_ZEROPLUS_FF),y)
usbhid-objs += hid-zpff.o
endif
ifeq ($(CONFIG_HID_FF),y)
usbhid-objs += hid-ff.o
endif
obj-$(CONFIG_USB_HID) += usbhid.o obj-$(CONFIG_USB_HID) += usbhid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o obj-$(CONFIG_USB_KBD) += usbkbd.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -151,6 +151,8 @@ struct hidp_session { ...@@ -151,6 +151,8 @@ struct hidp_session {
struct sk_buff_head ctrl_transmit; struct sk_buff_head ctrl_transmit;
struct sk_buff_head intr_transmit; struct sk_buff_head intr_transmit;
struct hidp_connadd_req *req;
}; };
static inline void hidp_schedule(struct hidp_session *session) static inline void hidp_schedule(struct hidp_session *session)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment