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:
  HID: fix inverted wheel for bluetooth version of apple mighty mouse
  HID: no more reinitializtion is needed in post_reset
  HID: hidraw -- fix comment about accepted devices
  HID: Multitouch support for the N-Trig touchscreen
  HID: add new multitouch and digitizer contants
  HID: autocentering support for Logitech Force 3D Pro
  HID: fix hid-ff drivers so that devices work even without ff support
  HID: force feedback support for SmartJoy PLUS PS2/USB adapter
  HID: Wacom Graphire Bluetooth driver
  HID: autocentering support for Logitech G25 Racing Wheel
This commit is contained in:
Linus Torvalds 2009-06-14 13:45:49 -07:00
commit b322b78169
17 changed files with 842 additions and 52 deletions

View File

@ -116,9 +116,16 @@ config HID_CYPRESS
---help---
Support for cypress mouse and barcode readers.
config DRAGONRISE_FF
tristate "DragonRise Inc. force feedback support"
config HID_DRAGONRISE
tristate "DragonRise Inc. support" if EMBEDDED
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
---help---
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.
config LOGITECH_FF
bool "Logitech force feedback"
bool "Logitech force feedback support"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
@ -176,7 +183,7 @@ config LOGITECH_FF
force feedback.
config LOGIRUMBLEPAD2_FF
bool "Logitech Rumblepad 2 force feedback"
bool "Logitech Rumblepad 2 force feedback support"
depends on HID_LOGITECH
select INPUT_FF_MEMLESS
help
@ -211,11 +218,19 @@ config HID_PANTHERLORD
---help---
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
bool "Pantherlord force feedback support"
depends on HID_PANTHERLORD
select INPUT_FF_MEMLESS
help
---help---
Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter and want to enable force feedback support for it.
@ -247,15 +262,38 @@ config HID_SUNPLUS
---help---
Support for Sunplus wireless desktop.
config GREENASIA_FF
tristate "GreenAsia (Product ID 0x12) force feedback support"
config HID_GREENASIA
tristate "GreenAsia (Product ID 0x12) support" if EMBEDDED
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
---help---
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
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
tristate "TopSeed Cyberlink remote control support" if EMBEDDED
depends on USB_HID
@ -263,20 +301,44 @@ config HID_TOPSEED
---help---
Say Y if you have a TopSeed Cyberlink remote control.
config THRUSTMASTER_FF
tristate "ThrustMaster devices support"
config HID_THRUSTMASTER
tristate "ThrustMaster devices support" if EMBEDDED
depends on USB_HID
select INPUT_FF_MEMLESS
help
default !EMBEDDED
---help---
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
tristate "Zeroplus based game controller support"
depends on USB_HID
bool "Zeroplus based game controller force feedback support"
depends on HID_ZEROPLUS
select INPUT_FF_MEMLESS
help
Say Y here if you have a Zeroplus based game controller.
---help---
Say Y here if you have a Zeroplus based game controller and want
to have force feedback support for it.
endmenu

View File

@ -22,7 +22,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.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_GYRATION) += hid-gyration.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_PETALYNX) += hid-petalynx.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_SUNPLUS) += hid-sunplus.o
obj-$(CONFIG_GREENASIA_FF) += hid-gaff.o
obj-$(CONFIG_THRUSTMASTER_FF) += hid-tmff.o
obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.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_MOUSE) += usbhid/

View File

@ -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),
.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);

View File

@ -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, 0xb654) },
{ 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, 0x0030) },

View File

@ -137,6 +137,14 @@ static const struct hid_usage_entry hid_usage_table[] = {
{0, 0x44, "BarrelSwitch"},
{0, 0x45, "Eraser"},
{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" },
{0, 0x00, "Undefined"},
{0, 0x01, "Physical_Interface_Device"},
@ -514,9 +522,11 @@ static const char *events[EV_MAX + 1] = {
[EV_FF_STATUS] = "ForceFeedbackStatus",
};
static const char *syncs[2] = {
static const char *syncs[3] = {
[SYN_REPORT] = "Report", [SYN_CONFIG] = "Config",
[SYN_MT_REPORT] = "MT Report",
};
static const char *keys[KEY_MAX + 1] = {
[KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc",
[KEY_1] = "1", [KEY_2] = "2",
@ -734,8 +744,17 @@ static const char *absolutes[ABS_MAX + 1] = {
[ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X",
[ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure",
[ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt",
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width",
[ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "ToolWidth",
[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] = {

View File

@ -32,6 +32,8 @@
#include <linux/hid.h>
#include "hid-ids.h"
#ifdef CONFIG_DRAGONRISE_FF
#include "usbhid/usbhid.h"
struct drff_device {
@ -135,6 +137,12 @@ static int drff_init(struct hid_device *hid)
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)
{

View File

@ -31,6 +31,8 @@
#include <linux/usb.h>
#include <linux/hid.h>
#include "hid-ids.h"
#ifdef CONFIG_GREENASIA_FF
#include "usbhid/usbhid.h"
struct gaff_device {
@ -130,6 +132,12 @@ static int gaff_init(struct hid_device *hid)
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)
{

View File

@ -414,8 +414,10 @@
#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006
#define USB_VENDOR_ID_WACOM 0x056a
#define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81
#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_4_PHIDGETSERVO_20 0x8104
#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201

View File

@ -50,6 +50,12 @@ static const signed short ff_joystick[] = {
-1
};
static const signed short ff_joystick_ac[] = {
FF_CONSTANT,
FF_AUTOCENTER,
-1
};
static const signed short ff_wheel[] = {
FF_CONSTANT,
FF_AUTOCENTER,
@ -60,8 +66,8 @@ static const struct dev_type devices[] = {
{ 0x046d, 0xc211, ff_rumble },
{ 0x046d, 0xc219, ff_rumble },
{ 0x046d, 0xc283, ff_joystick },
{ 0x046d, 0xc286, ff_joystick },
{ 0x046d, 0xc294, ff_joystick },
{ 0x046d, 0xc286, ff_joystick_ac },
{ 0x046d, 0xc294, ff_wheel },
{ 0x046d, 0xc295, ff_joystick },
{ 0x046d, 0xca03, ff_wheel },
};

View File

@ -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) 2009 Stephane Chatty
*
*/
@ -29,15 +24,79 @@
#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
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,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_DIGITIZER &&
(usage->hid & 0xff) == 0x47) {
nt_map_key_clear(BTN_TOOL_DOUBLETAP);
return 1;
switch (usage->hid & HID_USAGE_PAGE) {
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 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;
}
@ -51,6 +110,138 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
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[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN),
.driver_data = NTRIG_DUPLICATE_USAGES },
@ -58,11 +249,20 @@ static const struct hid_device_id 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 = {
.name = "ntrig",
.id_table = ntrig_devices,
.probe = ntrig_probe,
.remove = ntrig_remove,
.input_mapping = ntrig_input_mapping,
.input_mapped = ntrig_input_mapped,
.usage_table = ntrig_grabbed_usages,
.event = ntrig_event,
};
static int ntrig_init(void)

180
drivers/hid/hid-sjoy.c Normal file
View 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");

View File

@ -33,11 +33,6 @@
#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[] = {
FF_RUMBLE,
-1
@ -48,6 +43,12 @@ static const signed short ff_joystick[] = {
-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 hid_report *report;
struct hid_field *ff_field;
@ -209,6 +210,12 @@ static int tmff_init(struct hid_device *hid, const signed short *ff_bits)
kfree(tmff);
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)
{

259
drivers/hid/hid-wacom.c Normal file
View 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");

View File

@ -27,6 +27,7 @@
#include "hid-ids.h"
#ifdef CONFIG_ZEROPLUS_FF
#include "usbhid/usbhid.h"
struct zpff_device {
@ -108,6 +109,12 @@ static int zpff_init(struct hid_device *hid)
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)
{

View File

@ -349,10 +349,7 @@ int hidraw_connect(struct hid_device *hid)
int minor, result;
struct hidraw *dev;
/* TODO currently we accept any HID device. This should later
* probably be fixed to accept only those devices which provide
* non-input applications
*/
/* we accept any HID device, no matter the applications */
dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
if (!dev)

View File

@ -1234,12 +1234,11 @@ static int hid_post_reset(struct usb_interface *intf)
struct hid_device *hid = usb_get_intfdata(intf);
struct usbhid_device *usbhid = hid->driver_data;
int status;
spin_lock_irq(&usbhid->lock);
clear_bit(HID_RESET_PENDING, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock);
hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
/* FIXME: Any more reinitialization needed? */
status = hid_start_in(hid);
if (status < 0)
hid_io_error(hid);
@ -1251,14 +1250,14 @@ static int hid_post_reset(struct usb_interface *intf)
int usbhid_get_power(struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
return usb_autopm_get_interface(usbhid->intf);
}
void usbhid_put_power(struct hid_device *hid)
{
struct usbhid_device *usbhid = hid->driver_data;
usb_autopm_put_interface(usbhid->intf);
}

View File

@ -238,6 +238,42 @@ struct hid_item {
#define HID_GD_RIGHT 0x00010092
#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!
*/