mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 04:06:22 +00:00
Merge branches 'upstream' and 'ntrig-multitouch' into for-linus
This commit is contained in:
commit
6341de0527
17 changed files with 842 additions and 52 deletions
|
@ -116,9 +116,16 @@ config HID_CYPRESS
|
||||||
---help---
|
---help---
|
||||||
Support for cypress mouse and barcode readers.
|
Support for cypress mouse and barcode readers.
|
||||||
|
|
||||||
config DRAGONRISE_FF
|
config HID_DRAGONRISE
|
||||||
tristate "DragonRise Inc. force feedback support"
|
tristate "DragonRise Inc. support" if EMBEDDED
|
||||||
depends on USB_HID
|
depends on USB_HID
|
||||||
|
default !EMBEDDED
|
||||||
|
---help---
|
||||||
|
Say Y here if you have DragonRise Inc.game controllers.
|
||||||
|
|
||||||
|
config DRAGONRISE_FF
|
||||||
|
bool "DragonRise Inc. force feedback support"
|
||||||
|
depends on HID_DRAGONRISE
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
---help---
|
---help---
|
||||||
Say Y here if you want to enable force feedback support for DragonRise Inc.
|
Say Y here if you want to enable force feedback support for DragonRise Inc.
|
||||||
|
@ -160,7 +167,7 @@ config HID_LOGITECH
|
||||||
Support for Logitech devices that are not fully compliant with HID standard.
|
Support for Logitech devices that are not fully compliant with HID standard.
|
||||||
|
|
||||||
config LOGITECH_FF
|
config LOGITECH_FF
|
||||||
bool "Logitech force feedback"
|
bool "Logitech force feedback support"
|
||||||
depends on HID_LOGITECH
|
depends on HID_LOGITECH
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
help
|
help
|
||||||
|
@ -176,7 +183,7 @@ config LOGITECH_FF
|
||||||
force feedback.
|
force feedback.
|
||||||
|
|
||||||
config LOGIRUMBLEPAD2_FF
|
config LOGIRUMBLEPAD2_FF
|
||||||
bool "Logitech Rumblepad 2 force feedback"
|
bool "Logitech Rumblepad 2 force feedback support"
|
||||||
depends on HID_LOGITECH
|
depends on HID_LOGITECH
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
help
|
help
|
||||||
|
@ -211,11 +218,19 @@ config HID_PANTHERLORD
|
||||||
---help---
|
---help---
|
||||||
Support for PantherLord/GreenAsia based device support.
|
Support for PantherLord/GreenAsia based device support.
|
||||||
|
|
||||||
|
config HID_PANTHERLORD
|
||||||
|
tristate "Pantherlord support" if EMBEDDED
|
||||||
|
depends on USB_HID
|
||||||
|
default !EMBEDDED
|
||||||
|
---help---
|
||||||
|
Say Y here if you have a PantherLord/GreenAsia based game controller
|
||||||
|
or adapter.
|
||||||
|
|
||||||
config PANTHERLORD_FF
|
config PANTHERLORD_FF
|
||||||
bool "Pantherlord force feedback support"
|
bool "Pantherlord force feedback support"
|
||||||
depends on HID_PANTHERLORD
|
depends on HID_PANTHERLORD
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
help
|
---help---
|
||||||
Say Y here if you have a PantherLord/GreenAsia based game controller
|
Say Y here if you have a PantherLord/GreenAsia based game controller
|
||||||
or adapter and want to enable force feedback support for it.
|
or adapter and want to enable force feedback support for it.
|
||||||
|
|
||||||
|
@ -247,15 +262,38 @@ config HID_SUNPLUS
|
||||||
---help---
|
---help---
|
||||||
Support for Sunplus wireless desktop.
|
Support for Sunplus wireless desktop.
|
||||||
|
|
||||||
config GREENASIA_FF
|
config HID_GREENASIA
|
||||||
tristate "GreenAsia (Product ID 0x12) force feedback support"
|
tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED
|
||||||
depends on USB_HID
|
depends on USB_HID
|
||||||
|
default !EMBEDDED
|
||||||
|
---help---
|
||||||
|
Say Y here if you have a GreenAsia (Product ID 0x12) based game
|
||||||
|
controller or adapter.
|
||||||
|
|
||||||
|
config GREENASIA_FF
|
||||||
|
bool "GreenAsia (Product ID 0x12) force feedback support"
|
||||||
|
depends on HID_GREENASIA
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
---help---
|
---help---
|
||||||
Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
|
Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
|
||||||
(like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
|
(like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
|
||||||
and want to enable force feedback support for it.
|
and want to enable force feedback support for it.
|
||||||
|
|
||||||
|
config HID_SMARTJOYPLUS
|
||||||
|
tristate "SmartJoy PLUS PS2/USB adapter support" if EMBEDDED
|
||||||
|
depends on USB_HID
|
||||||
|
default !EMBEDDED
|
||||||
|
---help---
|
||||||
|
Support for SmartJoy PLUS PS2/USB adapter.
|
||||||
|
|
||||||
|
config SMARTJOYPLUS_FF
|
||||||
|
bool "SmartJoy PLUS PS2/USB adapter force feedback support"
|
||||||
|
depends on HID_SMARTJOYPLUS
|
||||||
|
select INPUT_FF_MEMLESS
|
||||||
|
---help---
|
||||||
|
Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
|
||||||
|
enable force feedback support for it.
|
||||||
|
|
||||||
config HID_TOPSEED
|
config HID_TOPSEED
|
||||||
tristate "TopSeed Cyberlink remote control support" if EMBEDDED
|
tristate "TopSeed Cyberlink remote control support" if EMBEDDED
|
||||||
depends on USB_HID
|
depends on USB_HID
|
||||||
|
@ -263,20 +301,44 @@ config HID_TOPSEED
|
||||||
---help---
|
---help---
|
||||||
Say Y if you have a TopSeed Cyberlink remote control.
|
Say Y if you have a TopSeed Cyberlink remote control.
|
||||||
|
|
||||||
config THRUSTMASTER_FF
|
config HID_THRUSTMASTER
|
||||||
tristate "ThrustMaster devices support"
|
tristate "ThrustMaster devices support" if EMBEDDED
|
||||||
depends on USB_HID
|
depends on USB_HID
|
||||||
select INPUT_FF_MEMLESS
|
default !EMBEDDED
|
||||||
help
|
---help---
|
||||||
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
|
Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or
|
||||||
a THRUSTMASTER Ferrari GT Rumble Force or Force Feedback Wheel.
|
a THRUSTMASTER Ferrari GT Rumble Wheel.
|
||||||
|
|
||||||
|
config THRUSTMASTER_FF
|
||||||
|
bool "ThrustMaster devices force feedback support"
|
||||||
|
depends on HID_THRUSTMASTER
|
||||||
|
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 and
|
||||||
|
want to enable force feedback support for it.
|
||||||
|
|
||||||
|
config HID_WACOM
|
||||||
|
tristate "Wacom Bluetooth devices support" if EMBEDDED
|
||||||
|
depends on BT_HIDP
|
||||||
|
default !EMBEDDED
|
||||||
|
---help---
|
||||||
|
Support for Wacom Graphire Bluetooth tablet.
|
||||||
|
|
||||||
|
config HID_ZEROPLUS
|
||||||
|
tristate "Zeroplus based game controller support" if EMBEDDED
|
||||||
|
depends on USB_HID
|
||||||
|
default !EMBEDDED
|
||||||
|
---help---
|
||||||
|
Say Y here if you have a Zeroplus based game controller.
|
||||||
|
|
||||||
config ZEROPLUS_FF
|
config ZEROPLUS_FF
|
||||||
tristate "Zeroplus based game controller support"
|
bool "Zeroplus based game controller force feedback support"
|
||||||
depends on USB_HID
|
depends on HID_ZEROPLUS
|
||||||
select INPUT_FF_MEMLESS
|
select INPUT_FF_MEMLESS
|
||||||
help
|
---help---
|
||||||
Say Y here if you have a Zeroplus based game controller.
|
Say Y here if you have a Zeroplus based game controller and want
|
||||||
|
to have force feedback support for it.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
|
||||||
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
|
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
|
||||||
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
|
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
|
||||||
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
|
||||||
obj-$(CONFIG_DRAGONRISE_FF) += hid-drff.o
|
obj-$(CONFIG_HID_DRAGONRISE) += hid-drff.o
|
||||||
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o
|
||||||
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
||||||
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
|
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
|
||||||
|
@ -34,12 +34,14 @@ obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o
|
||||||
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
|
obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o
|
||||||
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
|
obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o
|
||||||
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
|
||||||
|
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
|
||||||
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
obj-$(CONFIG_HID_SONY) += hid-sony.o
|
||||||
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
|
obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o
|
||||||
obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
|
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
|
||||||
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
|
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
|
||||||
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
|
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
|
||||||
obj-$(CONFIG_ZEROPLUS_FF) += hid-zpff.o
|
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
|
||||||
|
obj-$(CONFIG_HID_WACOM) += hid-wacom.o
|
||||||
|
|
||||||
obj-$(CONFIG_USB_HID) += usbhid/
|
obj-$(CONFIG_USB_HID) += usbhid/
|
||||||
obj-$(CONFIG_USB_MOUSE) += usbhid/
|
obj-$(CONFIG_USB_MOUSE) += usbhid/
|
||||||
|
|
|
@ -436,10 +436,6 @@ static const struct hid_device_id apple_devices[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
|
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
|
||||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||||
|
|
||||||
/* Apple wireless Mighty Mouse */
|
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
|
|
||||||
.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
|
|
||||||
|
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(hid, apple_devices);
|
MODULE_DEVICE_TABLE(hid, apple_devices);
|
||||||
|
|
|
@ -1312,6 +1312,8 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
|
||||||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,14 @@ static const struct hid_usage_entry hid_usage_table[] = {
|
||||||
{0, 0x44, "BarrelSwitch"},
|
{0, 0x44, "BarrelSwitch"},
|
||||||
{0, 0x45, "Eraser"},
|
{0, 0x45, "Eraser"},
|
||||||
{0, 0x46, "TabletPick"},
|
{0, 0x46, "TabletPick"},
|
||||||
|
{0, 0x47, "Confidence"},
|
||||||
|
{0, 0x48, "Width"},
|
||||||
|
{0, 0x49, "Height"},
|
||||||
|
{0, 0x51, "ContactID"},
|
||||||
|
{0, 0x52, "InputMode"},
|
||||||
|
{0, 0x53, "DeviceIndex"},
|
||||||
|
{0, 0x54, "ContactCount"},
|
||||||
|
{0, 0x55, "ContactMaximumNumber"},
|
||||||
{ 15, 0, "PhysicalInterfaceDevice" },
|
{ 15, 0, "PhysicalInterfaceDevice" },
|
||||||
{0, 0x00, "Undefined"},
|
{0, 0x00, "Undefined"},
|
||||||
{0, 0x01, "Physical_Interface_Device"},
|
{0, 0x01, "Physical_Interface_Device"},
|
||||||
|
@ -514,9 +522,11 @@ static const char *events[EV_MAX + 1] = {
|
||||||
[EV_FF_STATUS] = "ForceFeedbackStatus",
|
[EV_FF_STATUS] = "ForceFeedbackStatus",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *syncs[2] = {
|
static const char *syncs[3] = {
|
||||||
[SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
|
[SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
|
||||||
|
[SYN_MT_REPORT] = "MT Report",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *keys[KEY_MAX + 1] = {
|
static const char *keys[KEY_MAX + 1] = {
|
||||||
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
|
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
|
||||||
[KEY_1] = "1", [KEY_2] = "2",
|
[KEY_1] = "1", [KEY_2] = "2",
|
||||||
|
@ -736,6 +746,15 @@ static const char *absolutes[ABS_MAX + 1] = {
|
||||||
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
|
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
|
||||||
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth",
|
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth",
|
||||||
[ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
|
[ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc",
|
||||||
|
[ABS_MT_TOUCH_MAJOR] = "MTMajor",
|
||||||
|
[ABS_MT_TOUCH_MINOR] = "MTMinor",
|
||||||
|
[ABS_MT_WIDTH_MAJOR] = "MTMajorW",
|
||||||
|
[ABS_MT_WIDTH_MINOR] = "MTMinorW",
|
||||||
|
[ABS_MT_ORIENTATION] = "MTOrientation",
|
||||||
|
[ABS_MT_POSITION_X] = "MTPositionX",
|
||||||
|
[ABS_MT_POSITION_Y] = "MTPositionY",
|
||||||
|
[ABS_MT_TOOL_TYPE] = "MTToolType",
|
||||||
|
[ABS_MT_BLOB_ID] = "MTBlobID",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *misc[MSC_MAX + 1] = {
|
static const char *misc[MSC_MAX + 1] = {
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include <linux/hid.h>
|
#include <linux/hid.h>
|
||||||
|
|
||||||
#include "hid-ids.h"
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_DRAGONRISE_FF
|
||||||
#include "usbhid/usbhid.h"
|
#include "usbhid/usbhid.h"
|
||||||
|
|
||||||
struct drff_device {
|
struct drff_device {
|
||||||
|
@ -135,6 +137,12 @@ static int drff_init(struct hid_device *hid)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline int drff_init(struct hid_device *hid)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/hid.h>
|
#include <linux/hid.h>
|
||||||
#include "hid-ids.h"
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_GREENASIA_FF
|
||||||
#include "usbhid/usbhid.h"
|
#include "usbhid/usbhid.h"
|
||||||
|
|
||||||
struct gaff_device {
|
struct gaff_device {
|
||||||
|
@ -130,6 +132,12 @@ static int gaff_init(struct hid_device *hid)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline int gaff_init(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int ga_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -414,8 +414,10 @@
|
||||||
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
|
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
|
||||||
|
|
||||||
#define USB_VENDOR_ID_WACOM 0x056a
|
#define USB_VENDOR_ID_WACOM 0x056a
|
||||||
|
#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81
|
||||||
|
|
||||||
#define USB_VENDOR_ID_WISEGROUP 0x0925
|
#define USB_VENDOR_ID_WISEGROUP 0x0925
|
||||||
|
#define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005
|
||||||
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
|
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
|
||||||
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
|
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
|
||||||
#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201
|
#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201
|
||||||
|
|
|
@ -50,6 +50,12 @@ static const signed short ff_joystick[] = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const signed short ff_joystick_ac[] = {
|
||||||
|
FF_CONSTANT,
|
||||||
|
FF_AUTOCENTER,
|
||||||
|
-1
|
||||||
|
};
|
||||||
|
|
||||||
static const signed short ff_wheel[] = {
|
static const signed short ff_wheel[] = {
|
||||||
FF_CONSTANT,
|
FF_CONSTANT,
|
||||||
FF_AUTOCENTER,
|
FF_AUTOCENTER,
|
||||||
|
@ -60,8 +66,8 @@ static const struct dev_type devices[] = {
|
||||||
{ 0x046d, 0xc211, ff_rumble },
|
{ 0x046d, 0xc211, ff_rumble },
|
||||||
{ 0x046d, 0xc219, ff_rumble },
|
{ 0x046d, 0xc219, ff_rumble },
|
||||||
{ 0x046d, 0xc283, ff_joystick },
|
{ 0x046d, 0xc283, ff_joystick },
|
||||||
{ 0x046d, 0xc286, ff_joystick },
|
{ 0x046d, 0xc286, ff_joystick_ac },
|
||||||
{ 0x046d, 0xc294, ff_joystick },
|
{ 0x046d, 0xc294, ff_wheel },
|
||||||
{ 0x046d, 0xc295, ff_joystick },
|
{ 0x046d, 0xc295, ff_joystick },
|
||||||
{ 0x046d, 0xca03, ff_wheel },
|
{ 0x046d, 0xca03, ff_wheel },
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* HID driver for some ntrig "special" devices
|
* HID driver for N-Trig touchscreens
|
||||||
*
|
*
|
||||||
* 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
|
* Copyright (c) 2008 Rafi Rubin
|
||||||
|
* Copyright (c) 2009 Stephane Chatty
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -29,16 +24,80 @@
|
||||||
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
|
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
|
||||||
EV_KEY, (c))
|
EV_KEY, (c))
|
||||||
|
|
||||||
|
struct ntrig_data {
|
||||||
|
__s32 x, y, id, w, h;
|
||||||
|
char reading_a_point, found_contact_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this driver is aimed at two firmware versions in circulation:
|
||||||
|
* - dual pen/finger single touch
|
||||||
|
* - finger multitouch, pen not working
|
||||||
|
*/
|
||||||
|
|
||||||
static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||||
struct hid_field *field, struct hid_usage *usage,
|
struct hid_field *field, struct hid_usage *usage,
|
||||||
unsigned long **bit, int *max)
|
unsigned long **bit, int *max)
|
||||||
{
|
{
|
||||||
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
|
switch (usage->hid & HID_USAGE_PAGE) {
|
||||||
(usage->hid & 0xff) == 0x47) {
|
|
||||||
nt_map_key_clear(BTN_TOOL_DOUBLETAP);
|
case HID_UP_GENDESK:
|
||||||
|
switch (usage->hid) {
|
||||||
|
case HID_GD_X:
|
||||||
|
hid_map_usage(hi, usage, bit, max,
|
||||||
|
EV_ABS, ABS_MT_POSITION_X);
|
||||||
|
input_set_abs_params(hi->input, ABS_X,
|
||||||
|
field->logical_minimum,
|
||||||
|
field->logical_maximum, 0, 0);
|
||||||
|
return 1;
|
||||||
|
case HID_GD_Y:
|
||||||
|
hid_map_usage(hi, usage, bit, max,
|
||||||
|
EV_ABS, ABS_MT_POSITION_Y);
|
||||||
|
input_set_abs_params(hi->input, ABS_Y,
|
||||||
|
field->logical_minimum,
|
||||||
|
field->logical_maximum, 0, 0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case HID_UP_DIGITIZER:
|
||||||
|
switch (usage->hid) {
|
||||||
|
/* we do not want to map these for now */
|
||||||
|
case HID_DG_INVERT: /* value is always 0 */
|
||||||
|
case HID_DG_ERASER: /* value is always 0 */
|
||||||
|
case HID_DG_CONTACTID: /* value is useless */
|
||||||
|
case HID_DG_BARRELSWITCH: /* doubtful */
|
||||||
|
case HID_DG_INPUTMODE:
|
||||||
|
case HID_DG_DEVICEINDEX:
|
||||||
|
case HID_DG_CONTACTCOUNT:
|
||||||
|
case HID_DG_CONTACTMAX:
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* original mapping by Rafi Rubin */
|
||||||
|
case HID_DG_CONFIDENCE:
|
||||||
|
nt_map_key_clear(BTN_TOOL_DOUBLETAP);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* width/height mapped on TouchMajor/TouchMinor/Orientation */
|
||||||
|
case HID_DG_WIDTH:
|
||||||
|
hid_map_usage(hi, usage, bit, max,
|
||||||
|
EV_ABS, ABS_MT_TOUCH_MAJOR);
|
||||||
|
return 1;
|
||||||
|
case HID_DG_HEIGHT:
|
||||||
|
hid_map_usage(hi, usage, bit, max,
|
||||||
|
EV_ABS, ABS_MT_TOUCH_MINOR);
|
||||||
|
input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
|
||||||
|
0, 1, 0, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 0xff000000:
|
||||||
|
/* we do not want to map these: no input-oriented meaning */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||||
|
@ -51,6 +110,138 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this function is called upon all reports
|
||||||
|
* so that we can filter contact point information,
|
||||||
|
* decide whether we are in multi or single touch mode
|
||||||
|
* and call input_mt_sync after each point if necessary
|
||||||
|
*/
|
||||||
|
static int ntrig_event (struct hid_device *hid, struct hid_field *field,
|
||||||
|
struct hid_usage *usage, __s32 value)
|
||||||
|
{
|
||||||
|
struct input_dev *input = field->hidinput->input;
|
||||||
|
struct ntrig_data *nd = hid_get_drvdata(hid);
|
||||||
|
|
||||||
|
if (hid->claimed & HID_CLAIMED_INPUT) {
|
||||||
|
switch (usage->hid) {
|
||||||
|
case HID_GD_X:
|
||||||
|
nd->x = value;
|
||||||
|
nd->reading_a_point = 1;
|
||||||
|
break;
|
||||||
|
case HID_GD_Y:
|
||||||
|
nd->y = value;
|
||||||
|
break;
|
||||||
|
case HID_DG_CONTACTID:
|
||||||
|
nd->id = value;
|
||||||
|
/* we receive this only when in multitouch mode */
|
||||||
|
nd->found_contact_id = 1;
|
||||||
|
break;
|
||||||
|
case HID_DG_WIDTH:
|
||||||
|
nd->w = value;
|
||||||
|
break;
|
||||||
|
case HID_DG_HEIGHT:
|
||||||
|
nd->h = value;
|
||||||
|
/*
|
||||||
|
* when in single touch mode, this is the last
|
||||||
|
* report received in a finger event. We want
|
||||||
|
* to emit a normal (X, Y) position
|
||||||
|
*/
|
||||||
|
if (! nd->found_contact_id) {
|
||||||
|
input_event(input, EV_ABS, ABS_X, nd->x);
|
||||||
|
input_event(input, EV_ABS, ABS_Y, nd->y);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HID_DG_TIPPRESSURE:
|
||||||
|
/*
|
||||||
|
* when in single touch mode, this is the last
|
||||||
|
* report received in a pen event. We want
|
||||||
|
* to emit a normal (X, Y) position
|
||||||
|
*/
|
||||||
|
if (! nd->found_contact_id) {
|
||||||
|
input_event(input, EV_ABS, ABS_X, nd->x);
|
||||||
|
input_event(input, EV_ABS, ABS_Y, nd->y);
|
||||||
|
input_event(input, EV_ABS, ABS_PRESSURE, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xff000002:
|
||||||
|
/*
|
||||||
|
* we receive this when the device is in multitouch
|
||||||
|
* mode. The first of the three values tagged with
|
||||||
|
* this usage tells if the contact point is real
|
||||||
|
* or a placeholder
|
||||||
|
*/
|
||||||
|
if (!nd->reading_a_point || value != 1)
|
||||||
|
break;
|
||||||
|
/* emit a normal (X, Y) for the first point only */
|
||||||
|
if (nd->id == 0) {
|
||||||
|
input_event(input, EV_ABS, ABS_X, nd->x);
|
||||||
|
input_event(input, EV_ABS, ABS_Y, nd->y);
|
||||||
|
}
|
||||||
|
input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
|
||||||
|
input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
|
||||||
|
if (nd->w > nd->h) {
|
||||||
|
input_event(input, EV_ABS,
|
||||||
|
ABS_MT_ORIENTATION, 1);
|
||||||
|
input_event(input, EV_ABS,
|
||||||
|
ABS_MT_TOUCH_MAJOR, nd->w);
|
||||||
|
input_event(input, EV_ABS,
|
||||||
|
ABS_MT_TOUCH_MINOR, nd->h);
|
||||||
|
} else {
|
||||||
|
input_event(input, EV_ABS,
|
||||||
|
ABS_MT_ORIENTATION, 0);
|
||||||
|
input_event(input, EV_ABS,
|
||||||
|
ABS_MT_TOUCH_MAJOR, nd->h);
|
||||||
|
input_event(input, EV_ABS,
|
||||||
|
ABS_MT_TOUCH_MINOR, nd->w);
|
||||||
|
}
|
||||||
|
input_mt_sync(field->hidinput->input);
|
||||||
|
nd->reading_a_point = 0;
|
||||||
|
nd->found_contact_id = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* fallback to the generic hidinput handling */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we have handled the hidinput part, now remains hiddev */
|
||||||
|
if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
|
||||||
|
hid->hiddev_hid_event(hid, field, usage, value);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ntrig_data *nd;
|
||||||
|
|
||||||
|
nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
|
||||||
|
if (!nd) {
|
||||||
|
dev_err(&hdev->dev, "cannot allocate N-Trig data\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
nd->reading_a_point = 0;
|
||||||
|
nd->found_contact_id = 0;
|
||||||
|
hid_set_drvdata(hdev, nd);
|
||||||
|
|
||||||
|
ret = hid_parse(hdev);
|
||||||
|
if (!ret)
|
||||||
|
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
kfree (nd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ntrig_remove(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
hid_hw_stop(hdev);
|
||||||
|
kfree(hid_get_drvdata(hdev));
|
||||||
|
}
|
||||||
|
|
||||||
static const struct hid_device_id ntrig_devices[] = {
|
static const struct hid_device_id ntrig_devices[] = {
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
|
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
|
||||||
.driver_data = NTRIG_DUPLICATE_USAGES },
|
.driver_data = NTRIG_DUPLICATE_USAGES },
|
||||||
|
@ -58,11 +249,20 @@ static const struct hid_device_id ntrig_devices[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(hid, ntrig_devices);
|
MODULE_DEVICE_TABLE(hid, ntrig_devices);
|
||||||
|
|
||||||
|
static const struct hid_usage_id ntrig_grabbed_usages[] = {
|
||||||
|
{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
|
||||||
|
{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
|
||||||
|
};
|
||||||
|
|
||||||
static struct hid_driver ntrig_driver = {
|
static struct hid_driver ntrig_driver = {
|
||||||
.name = "ntrig",
|
.name = "ntrig",
|
||||||
.id_table = ntrig_devices,
|
.id_table = ntrig_devices,
|
||||||
|
.probe = ntrig_probe,
|
||||||
|
.remove = ntrig_remove,
|
||||||
.input_mapping = ntrig_input_mapping,
|
.input_mapping = ntrig_input_mapping,
|
||||||
.input_mapped = ntrig_input_mapped,
|
.input_mapped = ntrig_input_mapped,
|
||||||
|
.usage_table = ntrig_grabbed_usages,
|
||||||
|
.event = ntrig_event,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ntrig_init(void)
|
static int ntrig_init(void)
|
||||||
|
|
180
drivers/hid/hid-sjoy.c
Normal file
180
drivers/hid/hid-sjoy.c
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* Force feedback support for SmartJoy PLUS PS2->USB adapter
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
|
||||||
|
*
|
||||||
|
* Based of hid-pl.c and hid-gaff.c
|
||||||
|
* Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com>
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define DEBUG */
|
||||||
|
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
|
#include <linux/hid.h>
|
||||||
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMARTJOYPLUS_FF
|
||||||
|
#include "usbhid/usbhid.h"
|
||||||
|
|
||||||
|
struct sjoyff_device {
|
||||||
|
struct hid_report *report;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int hid_sjoyff_play(struct input_dev *dev, void *data,
|
||||||
|
struct ff_effect *effect)
|
||||||
|
{
|
||||||
|
struct hid_device *hid = input_get_drvdata(dev);
|
||||||
|
struct sjoyff_device *sjoyff = data;
|
||||||
|
u32 left, right;
|
||||||
|
|
||||||
|
left = effect->u.rumble.strong_magnitude;
|
||||||
|
right = effect->u.rumble.weak_magnitude;
|
||||||
|
dev_dbg(&dev->dev, "called with 0x%08x 0x%08x\n", left, right);
|
||||||
|
|
||||||
|
left = left * 0xff / 0xffff;
|
||||||
|
right = (right != 0); /* on/off only */
|
||||||
|
|
||||||
|
sjoyff->report->field[0]->value[1] = right;
|
||||||
|
sjoyff->report->field[0]->value[2] = left;
|
||||||
|
dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right);
|
||||||
|
usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sjoyff_init(struct hid_device *hid)
|
||||||
|
{
|
||||||
|
struct sjoyff_device *sjoyff;
|
||||||
|
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;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (list_empty(report_list)) {
|
||||||
|
dev_err(&hid->dev, "no output reports found\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
report_ptr = report_ptr->next;
|
||||||
|
|
||||||
|
if (report_ptr == report_list) {
|
||||||
|
dev_err(&hid->dev, "required output report is "
|
||||||
|
"missing\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 < 3) {
|
||||||
|
dev_err(&hid->dev, "not enough values in the field\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjoyff = kzalloc(sizeof(struct sjoyff_device), GFP_KERNEL);
|
||||||
|
if (!sjoyff)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev = hidinput->input;
|
||||||
|
|
||||||
|
set_bit(FF_RUMBLE, dev->ffbit);
|
||||||
|
|
||||||
|
error = input_ff_create_memless(dev, sjoyff, hid_sjoyff_play);
|
||||||
|
if (error) {
|
||||||
|
kfree(sjoyff);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjoyff->report = report;
|
||||||
|
sjoyff->report->field[0]->value[0] = 0x01;
|
||||||
|
sjoyff->report->field[0]->value[1] = 0x00;
|
||||||
|
sjoyff->report->field[0]->value[2] = 0x00;
|
||||||
|
usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT);
|
||||||
|
|
||||||
|
dev_info(&hid->dev,
|
||||||
|
"Force feedback for SmartJoy PLUS PS2/USB adapter\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline int sjoyff_init(struct hid_device *hid)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int sjoy_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&hdev->dev, "hw start failed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
sjoyff_init(hdev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hid_device_id sjoy_devices[] = {
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(hid, sjoy_devices);
|
||||||
|
|
||||||
|
static struct hid_driver sjoy_driver = {
|
||||||
|
.name = "smartjoyplus",
|
||||||
|
.id_table = sjoy_devices,
|
||||||
|
.probe = sjoy_probe,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sjoy_init(void)
|
||||||
|
{
|
||||||
|
return hid_register_driver(&sjoy_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sjoy_exit(void)
|
||||||
|
{
|
||||||
|
hid_unregister_driver(&sjoy_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(sjoy_init);
|
||||||
|
module_exit(sjoy_exit);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_AUTHOR("Jussi Kivilinna");
|
||||||
|
|
|
@ -33,11 +33,6 @@
|
||||||
|
|
||||||
#include "hid-ids.h"
|
#include "hid-ids.h"
|
||||||
|
|
||||||
#include "usbhid/usbhid.h"
|
|
||||||
|
|
||||||
/* Usages for thrustmaster devices I know about */
|
|
||||||
#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
|
|
||||||
|
|
||||||
static const signed short ff_rumble[] = {
|
static const signed short ff_rumble[] = {
|
||||||
FF_RUMBLE,
|
FF_RUMBLE,
|
||||||
-1
|
-1
|
||||||
|
@ -48,6 +43,12 @@ static const signed short ff_joystick[] = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_THRUSTMASTER_FF
|
||||||
|
#include "usbhid/usbhid.h"
|
||||||
|
|
||||||
|
/* Usages for thrustmaster devices I know about */
|
||||||
|
#define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb)
|
||||||
|
|
||||||
struct tmff_device {
|
struct tmff_device {
|
||||||
struct hid_report *report;
|
struct hid_report *report;
|
||||||
struct hid_field *ff_field;
|
struct hid_field *ff_field;
|
||||||
|
@ -209,6 +210,12 @@ fail:
|
||||||
kfree(tmff);
|
kfree(tmff);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline int tmff_init(struct hid_device *hid, const signed short *ff_bits)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
|
|
259
drivers/hid/hid-wacom.c
Normal file
259
drivers/hid/hid-wacom.c
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
/*
|
||||||
|
* Bluetooth Wacom Tablet support
|
||||||
|
*
|
||||||
|
* 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 <jirislaby@gmail.com>
|
||||||
|
* Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
|
||||||
|
* Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
struct wacom_data {
|
||||||
|
__u16 tool;
|
||||||
|
unsigned char butstate;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report,
|
||||||
|
u8 *raw_data, int size)
|
||||||
|
{
|
||||||
|
struct wacom_data *wdata = hid_get_drvdata(hdev);
|
||||||
|
struct hid_input *hidinput;
|
||||||
|
struct input_dev *input;
|
||||||
|
unsigned char *data = (unsigned char *) raw_data;
|
||||||
|
int tool, x, y, rw;
|
||||||
|
|
||||||
|
if (!(hdev->claimed & HID_CLAIMED_INPUT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tool = 0;
|
||||||
|
hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
|
||||||
|
input = hidinput->input;
|
||||||
|
|
||||||
|
/* Check if this is a tablet report */
|
||||||
|
if (data[0] != 0x03)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Get X & Y positions */
|
||||||
|
x = le16_to_cpu(*(__le16 *) &data[2]);
|
||||||
|
y = le16_to_cpu(*(__le16 *) &data[4]);
|
||||||
|
|
||||||
|
/* Get current tool identifier */
|
||||||
|
if (data[1] & 0x90) { /* If pen is in the in/active area */
|
||||||
|
switch ((data[1] >> 5) & 3) {
|
||||||
|
case 0: /* Pen */
|
||||||
|
tool = BTN_TOOL_PEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: /* Rubber */
|
||||||
|
tool = BTN_TOOL_RUBBER;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* Mouse with wheel */
|
||||||
|
case 3: /* Mouse without wheel */
|
||||||
|
tool = BTN_TOOL_MOUSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset tool if out of active tablet area */
|
||||||
|
if (!(data[1] & 0x10))
|
||||||
|
tool = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If tool changed, notify input subsystem */
|
||||||
|
if (wdata->tool != tool) {
|
||||||
|
if (wdata->tool) {
|
||||||
|
/* Completely reset old tool state */
|
||||||
|
if (wdata->tool == BTN_TOOL_MOUSE) {
|
||||||
|
input_report_key(input, BTN_LEFT, 0);
|
||||||
|
input_report_key(input, BTN_RIGHT, 0);
|
||||||
|
input_report_key(input, BTN_MIDDLE, 0);
|
||||||
|
input_report_abs(input, ABS_DISTANCE,
|
||||||
|
input->absmax[ABS_DISTANCE]);
|
||||||
|
} else {
|
||||||
|
input_report_key(input, BTN_TOUCH, 0);
|
||||||
|
input_report_key(input, BTN_STYLUS, 0);
|
||||||
|
input_report_key(input, BTN_STYLUS2, 0);
|
||||||
|
input_report_abs(input, ABS_PRESSURE, 0);
|
||||||
|
}
|
||||||
|
input_report_key(input, wdata->tool, 0);
|
||||||
|
input_sync(input);
|
||||||
|
}
|
||||||
|
wdata->tool = tool;
|
||||||
|
if (tool)
|
||||||
|
input_report_key(input, tool, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tool) {
|
||||||
|
input_report_abs(input, ABS_X, x);
|
||||||
|
input_report_abs(input, ABS_Y, y);
|
||||||
|
|
||||||
|
switch ((data[1] >> 5) & 3) {
|
||||||
|
case 2: /* Mouse with wheel */
|
||||||
|
input_report_key(input, BTN_MIDDLE, data[1] & 0x04);
|
||||||
|
rw = (data[6] & 0x01) ? -1 :
|
||||||
|
(data[6] & 0x02) ? 1 : 0;
|
||||||
|
input_report_rel(input, REL_WHEEL, rw);
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case 3: /* Mouse without wheel */
|
||||||
|
input_report_key(input, BTN_LEFT, data[1] & 0x01);
|
||||||
|
input_report_key(input, BTN_RIGHT, data[1] & 0x02);
|
||||||
|
/* Compute distance between mouse and tablet */
|
||||||
|
rw = 44 - (data[6] >> 2);
|
||||||
|
if (rw < 0)
|
||||||
|
rw = 0;
|
||||||
|
else if (rw > 31)
|
||||||
|
rw = 31;
|
||||||
|
input_report_abs(input, ABS_DISTANCE, rw);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
input_report_abs(input, ABS_PRESSURE,
|
||||||
|
data[6] | (((__u16) (data[1] & 0x08)) << 5));
|
||||||
|
input_report_key(input, BTN_TOUCH, data[1] & 0x01);
|
||||||
|
input_report_key(input, BTN_STYLUS, data[1] & 0x02);
|
||||||
|
input_report_key(input, BTN_STYLUS2, (tool == BTN_TOOL_PEN) && data[1] & 0x04);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_sync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Report the state of the two buttons at the top of the tablet
|
||||||
|
* as two extra fingerpad keys (buttons 4 & 5). */
|
||||||
|
rw = data[7] & 0x03;
|
||||||
|
if (rw != wdata->butstate) {
|
||||||
|
wdata->butstate = rw;
|
||||||
|
input_report_key(input, BTN_0, rw & 0x02);
|
||||||
|
input_report_key(input, BTN_1, rw & 0x01);
|
||||||
|
input_event(input, EV_MSC, MSC_SERIAL, 0xf0);
|
||||||
|
input_sync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wacom_probe(struct hid_device *hdev,
|
||||||
|
const struct hid_device_id *id)
|
||||||
|
{
|
||||||
|
struct hid_input *hidinput;
|
||||||
|
struct input_dev *input;
|
||||||
|
struct wacom_data *wdata;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
|
||||||
|
if (wdata == NULL) {
|
||||||
|
dev_err(&hdev->dev, "can't alloc wacom descriptor\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
hid_set_drvdata(hdev, wdata);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
|
||||||
|
input = hidinput->input;
|
||||||
|
|
||||||
|
/* Basics */
|
||||||
|
input->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
|
||||||
|
input->absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) |
|
||||||
|
BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
|
||||||
|
input->relbit[0] |= BIT(REL_WHEEL);
|
||||||
|
set_bit(BTN_TOOL_PEN, input->keybit);
|
||||||
|
set_bit(BTN_TOUCH, input->keybit);
|
||||||
|
set_bit(BTN_STYLUS, input->keybit);
|
||||||
|
set_bit(BTN_STYLUS2, input->keybit);
|
||||||
|
set_bit(BTN_LEFT, input->keybit);
|
||||||
|
set_bit(BTN_RIGHT, input->keybit);
|
||||||
|
set_bit(BTN_MIDDLE, input->keybit);
|
||||||
|
|
||||||
|
/* Pad */
|
||||||
|
input->evbit[0] |= BIT(EV_MSC);
|
||||||
|
input->mscbit[0] |= BIT(MSC_SERIAL);
|
||||||
|
|
||||||
|
/* Distance, rubber and mouse */
|
||||||
|
input->absbit[0] |= BIT(ABS_DISTANCE);
|
||||||
|
set_bit(BTN_TOOL_RUBBER, input->keybit);
|
||||||
|
set_bit(BTN_TOOL_MOUSE, input->keybit);
|
||||||
|
|
||||||
|
input->absmax[ABS_PRESSURE] = 511;
|
||||||
|
input->absmax[ABS_DISTANCE] = 32;
|
||||||
|
|
||||||
|
input->absmax[ABS_X] = 16704;
|
||||||
|
input->absmax[ABS_Y] = 12064;
|
||||||
|
input->absfuzz[ABS_X] = 4;
|
||||||
|
input->absfuzz[ABS_Y] = 4;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err_free:
|
||||||
|
kfree(wdata);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wacom_remove(struct hid_device *hdev)
|
||||||
|
{
|
||||||
|
hid_hw_stop(hdev);
|
||||||
|
kfree(hid_get_drvdata(hdev));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct hid_device_id wacom_devices[] = {
|
||||||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) },
|
||||||
|
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(hid, wacom_devices);
|
||||||
|
|
||||||
|
static struct hid_driver wacom_driver = {
|
||||||
|
.name = "wacom",
|
||||||
|
.id_table = wacom_devices,
|
||||||
|
.probe = wacom_probe,
|
||||||
|
.remove = wacom_remove,
|
||||||
|
.raw_event = wacom_raw_event,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int wacom_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = hid_register_driver(&wacom_driver);
|
||||||
|
if (ret)
|
||||||
|
printk(KERN_ERR "can't register wacom driver\n");
|
||||||
|
printk(KERN_ERR "wacom driver registered\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wacom_exit(void)
|
||||||
|
{
|
||||||
|
hid_unregister_driver(&wacom_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(wacom_init);
|
||||||
|
module_exit(wacom_exit);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "hid-ids.h"
|
#include "hid-ids.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_ZEROPLUS_FF
|
||||||
#include "usbhid/usbhid.h"
|
#include "usbhid/usbhid.h"
|
||||||
|
|
||||||
struct zpff_device {
|
struct zpff_device {
|
||||||
|
@ -108,6 +109,12 @@ static int zpff_init(struct hid_device *hid)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
static inline int zpff_init(struct hid_device *hid)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
static int zp_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -349,10 +349,7 @@ int hidraw_connect(struct hid_device *hid)
|
||||||
int minor, result;
|
int minor, result;
|
||||||
struct hidraw *dev;
|
struct hidraw *dev;
|
||||||
|
|
||||||
/* TODO currently we accept any HID device. This should later
|
/* we accept any HID device, no matter the applications */
|
||||||
* probably be fixed to accept only those devices which provide
|
|
||||||
* non-input applications
|
|
||||||
*/
|
|
||||||
|
|
||||||
dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
|
dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
|
|
|
@ -1239,7 +1239,6 @@ static int hid_post_reset(struct usb_interface *intf)
|
||||||
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
|
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
|
||||||
spin_unlock_irq(&usbhid->lock);
|
spin_unlock_irq(&usbhid->lock);
|
||||||
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
|
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
|
||||||
/* FIXME: Any more reinitialization needed? */
|
|
||||||
status = hid_start_in(hid);
|
status = hid_start_in(hid);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
hid_io_error(hid);
|
hid_io_error(hid);
|
||||||
|
|
|
@ -238,6 +238,42 @@ struct hid_item {
|
||||||
#define HID_GD_RIGHT 0x00010092
|
#define HID_GD_RIGHT 0x00010092
|
||||||
#define HID_GD_LEFT 0x00010093
|
#define HID_GD_LEFT 0x00010093
|
||||||
|
|
||||||
|
#define HID_DG_DIGITIZER 0x000d0001
|
||||||
|
#define HID_DG_PEN 0x000d0002
|
||||||
|
#define HID_DG_LIGHTPEN 0x000d0003
|
||||||
|
#define HID_DG_TOUCHSCREEN 0x000d0004
|
||||||
|
#define HID_DG_TOUCHPAD 0x000d0005
|
||||||
|
#define HID_DG_STYLUS 0x000d0020
|
||||||
|
#define HID_DG_PUCK 0x000d0021
|
||||||
|
#define HID_DG_FINGER 0x000d0022
|
||||||
|
#define HID_DG_TIPPRESSURE 0x000d0030
|
||||||
|
#define HID_DG_BARRELPRESSURE 0x000d0031
|
||||||
|
#define HID_DG_INRANGE 0x000d0032
|
||||||
|
#define HID_DG_TOUCH 0x000d0033
|
||||||
|
#define HID_DG_UNTOUCH 0x000d0034
|
||||||
|
#define HID_DG_TAP 0x000d0035
|
||||||
|
#define HID_DG_TABLETFUNCTIONKEY 0x000d0039
|
||||||
|
#define HID_DG_PROGRAMCHANGEKEY 0x000d003a
|
||||||
|
#define HID_DG_INVERT 0x000d003c
|
||||||
|
#define HID_DG_TIPSWITCH 0x000d0042
|
||||||
|
#define HID_DG_TIPSWITCH2 0x000d0043
|
||||||
|
#define HID_DG_BARRELSWITCH 0x000d0044
|
||||||
|
#define HID_DG_ERASER 0x000d0045
|
||||||
|
#define HID_DG_TABLETPICK 0x000d0046
|
||||||
|
/*
|
||||||
|
* as of May 20, 2009 the usages below are not yet in the official USB spec
|
||||||
|
* but are being pushed by Microsft as described in their paper "Digitizer
|
||||||
|
* Drivers for Windows Touch and Pen-Based Computers"
|
||||||
|
*/
|
||||||
|
#define HID_DG_CONFIDENCE 0x000d0047
|
||||||
|
#define HID_DG_WIDTH 0x000d0048
|
||||||
|
#define HID_DG_HEIGHT 0x000d0049
|
||||||
|
#define HID_DG_CONTACTID 0x000d0051
|
||||||
|
#define HID_DG_INPUTMODE 0x000d0052
|
||||||
|
#define HID_DG_DEVICEINDEX 0x000d0053
|
||||||
|
#define HID_DG_CONTACTCOUNT 0x000d0054
|
||||||
|
#define HID_DG_CONTACTMAX 0x000d0055
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HID report types --- Ouch! HID spec says 1 2 3!
|
* HID report types --- Ouch! HID spec says 1 2 3!
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue