mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jikos/hid: USB HID: handle multi-interface devices for Apple macbook pro properly HID: move away from DEBUG defines in favor of CONFIG_HID_DEBUG USB HID: fix bogus comment in hid_get_class_descriptor() USB HID: remove hid_find_field_by_usage() HID: API - fix leftovers of hidinput API in USB HID HID: hid debug from hid-debug.h to hid layer hid: force feedback driver for PantherLord USB/PS2 2in1 Adapter hid: quirk for multi-input devices with unneeded output reports hid: allow force feedback for multi-input devices
This commit is contained in:
@@ -22,5 +22,19 @@ config HID
|
||||
|
||||
If unsure, say Y
|
||||
|
||||
config HID_DEBUG
|
||||
bool "HID debugging support"
|
||||
depends on HID
|
||||
---help---
|
||||
This option lets the HID layer output diagnostics about its internal
|
||||
state, resolve HID usages, dump HID fields, etc. Individual HID drivers
|
||||
use this debugging facility to output information about individual HID
|
||||
devices, etc.
|
||||
|
||||
This feature is useful for those who are either debugging the HID parser
|
||||
or any HID hardware device.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
#
|
||||
# Makefile for the HID driver
|
||||
#
|
||||
|
||||
# Multipart objects.
|
||||
hid-objs := hid-core.o hid-input.o
|
||||
|
||||
# Optional parts of multipart objects.
|
||||
hid-objs := hid-core.o hid-input.o
|
||||
|
||||
obj-$(CONFIG_HID) += hid.o
|
||||
|
||||
ifeq ($(CONFIG_INPUT_DEBUG),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
endif
|
||||
hid-$(CONFIG_HID_DEBUG) += hid-debug.o
|
||||
|
||||
|
||||
@@ -28,11 +28,9 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#undef DEBUG
|
||||
#undef DEBUG_DATA
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/hiddev.h>
|
||||
#include <linux/hid-debug.h>
|
||||
|
||||
/*
|
||||
* Version Information
|
||||
@@ -951,7 +949,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DATA
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
|
||||
#endif
|
||||
|
||||
@@ -961,7 +959,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
|
||||
size--;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DATA
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
{
|
||||
int i;
|
||||
printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
|
||||
|
||||
764
drivers/hid/hid-debug.c
Normal file
764
drivers/hid/hid-debug.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,9 +31,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/hid-debug.h>
|
||||
|
||||
static int hid_pb_fnmode = 1;
|
||||
module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
|
||||
@@ -252,9 +251,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
|
||||
field->hidinput = hidinput;
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk(KERN_DEBUG "Mapping: ");
|
||||
resolv_usage(usage->hid);
|
||||
hid_resolv_usage(usage->hid);
|
||||
printk(" ---> ");
|
||||
#endif
|
||||
|
||||
@@ -682,14 +681,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
field->dpad = usage->code;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
resolv_event(usage->type, usage->code);
|
||||
hid_resolv_event(usage->type, usage->code);
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk("\n");
|
||||
#endif
|
||||
return;
|
||||
|
||||
ignore:
|
||||
#ifdef DEBUG
|
||||
#ifdef CONFIG_HID_DEBUG
|
||||
printk("IGNORED\n");
|
||||
#endif
|
||||
return;
|
||||
@@ -804,6 +803,18 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hidinput_find_field);
|
||||
|
||||
static int hidinput_open(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = dev->private;
|
||||
return hid->hid_open(hid);
|
||||
}
|
||||
|
||||
static void hidinput_close(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = dev->private;
|
||||
hid->hid_close(hid);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the input device; print a message.
|
||||
* Configure the input layer interface
|
||||
@@ -816,6 +827,7 @@ int hidinput_connect(struct hid_device *hid)
|
||||
struct hid_input *hidinput = NULL;
|
||||
struct input_dev *input_dev;
|
||||
int i, j, k;
|
||||
int max_report_type = HID_OUTPUT_REPORT;
|
||||
|
||||
INIT_LIST_HEAD(&hid->inputs);
|
||||
|
||||
@@ -828,7 +840,10 @@ int hidinput_connect(struct hid_device *hid)
|
||||
if (i == hid->maxcollection)
|
||||
return -1;
|
||||
|
||||
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
|
||||
if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
|
||||
max_report_type = HID_INPUT_REPORT;
|
||||
|
||||
for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
|
||||
list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
|
||||
|
||||
if (!report->maxfield)
|
||||
@@ -846,8 +861,8 @@ int hidinput_connect(struct hid_device *hid)
|
||||
|
||||
input_dev->private = hid;
|
||||
input_dev->event = hid->hidinput_input_event;
|
||||
input_dev->open = hid->hidinput_open;
|
||||
input_dev->close = hid->hidinput_close;
|
||||
input_dev->open = hidinput_open;
|
||||
input_dev->close = hidinput_close;
|
||||
|
||||
input_dev->name = hid->name;
|
||||
input_dev->phys = hid->phys;
|
||||
|
||||
@@ -69,6 +69,14 @@ config LOGITECH_FF
|
||||
Note: if you say N here, this device will still be supported, but without
|
||||
force feedback.
|
||||
|
||||
config PANTHERLORD_FF
|
||||
bool "PantherLord USB/PS2 2in1 Adapter support"
|
||||
depends on HID_FF
|
||||
select INPUT_FF_MEMLESS if USB_HID
|
||||
help
|
||||
Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want
|
||||
to enable force feedback support for it.
|
||||
|
||||
config THRUSTMASTER_FF
|
||||
bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)"
|
||||
depends on HID_FF && EXPERIMENTAL
|
||||
|
||||
@@ -17,6 +17,9 @@ endif
|
||||
ifeq ($(CONFIG_LOGITECH_FF),y)
|
||||
usbhid-objs += hid-lgff.o
|
||||
endif
|
||||
ifeq ($(CONFIG_PANTHERLORD_FF),y)
|
||||
usbhid-objs += hid-plff.o
|
||||
endif
|
||||
ifeq ($(CONFIG_THRUSTMASTER_FF),y)
|
||||
usbhid-objs += hid-tmff.o
|
||||
endif
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <linux/hid.h>
|
||||
#include <linux/hiddev.h>
|
||||
#include <linux/hid-debug.h>
|
||||
#include "usbhid.h"
|
||||
|
||||
/*
|
||||
@@ -220,23 +221,6 @@ static void hid_irq_in(struct urb *urb)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a report field with a specified HID usage.
|
||||
*/
|
||||
#if 0
|
||||
struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type)
|
||||
{
|
||||
struct hid_report *report;
|
||||
int i;
|
||||
|
||||
list_for_each_entry(report, &hid->report_enum[type].report_list, list)
|
||||
for (i = 0; i < report->maxfield; i++)
|
||||
if (report->field[i]->logical == wanted_usage)
|
||||
return report->field[i];
|
||||
return NULL;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
static int hid_submit_out(struct hid_device *hid)
|
||||
{
|
||||
struct hid_report *report;
|
||||
@@ -501,7 +485,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
|
||||
{
|
||||
int result, retries = 4;
|
||||
|
||||
memset(buf,0,size); // Make sure we parse really received data
|
||||
memset(buf, 0, size);
|
||||
|
||||
do {
|
||||
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
|
||||
@@ -528,18 +512,6 @@ void usbhid_close(struct hid_device *hid)
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
}
|
||||
|
||||
static int hidinput_open(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = dev->private;
|
||||
return usbhid_open(hid);
|
||||
}
|
||||
|
||||
static void hidinput_close(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = dev->private;
|
||||
usbhid_close(hid);
|
||||
}
|
||||
|
||||
#define USB_VENDOR_ID_PANJIT 0x134c
|
||||
|
||||
#define USB_VENDOR_ID_TURBOX 0x062a
|
||||
@@ -770,6 +742,7 @@ void usbhid_init_reports(struct hid_device *hid)
|
||||
#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
|
||||
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
|
||||
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
|
||||
#define USB_DEVICE_ID_APPLE_IR 0x8240
|
||||
|
||||
#define USB_VENDOR_ID_CHERRY 0x046a
|
||||
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
|
||||
@@ -792,6 +765,9 @@ void usbhid_init_reports(struct hid_device *hid)
|
||||
#define USB_VENDOR_ID_IMATION 0x0718
|
||||
#define USB_DEVICE_ID_DISC_STAKKA 0xd000
|
||||
|
||||
#define USB_VENDOR_ID_PANTHERLORD 0x0810
|
||||
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
|
||||
|
||||
/*
|
||||
* Alphabetically sorted blacklist by quirk type.
|
||||
*/
|
||||
@@ -946,19 +922,21 @@ static const struct hid_blacklist {
|
||||
|
||||
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE },
|
||||
|
||||
{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
|
||||
@@ -969,6 +947,8 @@ static const struct hid_blacklist {
|
||||
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
|
||||
|
||||
{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -1064,6 +1044,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||
if (quirks & HID_QUIRK_IGNORE)
|
||||
return NULL;
|
||||
|
||||
if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
|
||||
(interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
|
||||
return NULL;
|
||||
|
||||
|
||||
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
|
||||
(!interface->desc.bNumEndpoints ||
|
||||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
|
||||
@@ -1235,8 +1220,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
|
||||
usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
|
||||
usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
|
||||
hid->hidinput_input_event = usb_hidinput_input_event;
|
||||
hid->hidinput_open = hidinput_open;
|
||||
hid->hidinput_close = hidinput_close;
|
||||
hid->hid_open = usbhid_open;
|
||||
hid->hid_close = usbhid_close;
|
||||
#ifdef CONFIG_USB_HIDDEV
|
||||
hid->hiddev_hid_event = hiddev_hid_event;
|
||||
hid->hiddev_report_event = hiddev_report_event;
|
||||
@@ -1315,11 +1300,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* This only gets called when we are a single-input (most of the
|
||||
* time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
|
||||
* only useful in this case, and not for multi-input quirks. */
|
||||
if ((hid->claimed & HID_CLAIMED_INPUT) &&
|
||||
!(hid->quirks & HID_QUIRK_MULTI_INPUT))
|
||||
if ((hid->claimed & HID_CLAIMED_INPUT))
|
||||
hid_ff_init(hid);
|
||||
|
||||
printk(KERN_INFO);
|
||||
|
||||
@@ -58,6 +58,9 @@ static struct hid_ff_initializer inits[] = {
|
||||
{ 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
|
||||
{ 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
|
||||
#endif
|
||||
#ifdef CONFIG_PANTHERLORD_FF
|
||||
{ 0x810, 0x0001, hid_plff_init },
|
||||
#endif
|
||||
#ifdef CONFIG_THRUSTMASTER_FF
|
||||
{ 0x44f, 0xb304, hid_tmff_init },
|
||||
#endif
|
||||
|
||||
129
drivers/usb/input/hid-plff.c
Normal file
129
drivers/usb/input/hid-plff.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Force feedback support for PantherLord USB/PS2 2in1 Adapter devices
|
||||
*
|
||||
* Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg)
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/hid.h>
|
||||
#include "usbhid.h"
|
||||
|
||||
struct plff_device {
|
||||
struct hid_report *report;
|
||||
};
|
||||
|
||||
static int hid_plff_play(struct input_dev *dev, void *data,
|
||||
struct ff_effect *effect)
|
||||
{
|
||||
struct hid_device *hid = dev->private;
|
||||
struct plff_device *plff = data;
|
||||
int left, right;
|
||||
|
||||
left = effect->u.rumble.strong_magnitude;
|
||||
right = effect->u.rumble.weak_magnitude;
|
||||
debug("called with 0x%04x 0x%04x", left, right);
|
||||
|
||||
left = left * 0x7f / 0xffff;
|
||||
right = right * 0x7f / 0xffff;
|
||||
|
||||
plff->report->field[0]->value[2] = left;
|
||||
plff->report->field[0]->value[3] = right;
|
||||
debug("running with 0x%02x 0x%02x", left, right);
|
||||
usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hid_plff_init(struct hid_device *hid)
|
||||
{
|
||||
struct plff_device *plff;
|
||||
struct hid_report *report;
|
||||
struct hid_input *hidinput;
|
||||
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;
|
||||
|
||||
/* The device contains 2 output reports (one for each
|
||||
HID_QUIRK_MULTI_INPUT device), both containing 1 field, which
|
||||
contains 4 ff00.0002 usages and 4 16bit absolute values.
|
||||
|
||||
The 2 input reports also contain a field which contains
|
||||
8 ff00.0001 usages and 8 boolean values. Their meaning is
|
||||
currently unknown. */
|
||||
|
||||
if (list_empty(report_list)) {
|
||||
printk(KERN_ERR "hid-plff: no output reports found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
list_for_each_entry(hidinput, &hid->inputs, list) {
|
||||
|
||||
report_ptr = report_ptr->next;
|
||||
|
||||
if (report_ptr == report_list) {
|
||||
printk(KERN_ERR "hid-plff: required output report is missing\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
report = list_entry(report_ptr, struct hid_report, list);
|
||||
if (report->maxfield < 1) {
|
||||
printk(KERN_ERR "hid-plff: no fields in the report\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (report->field[0]->report_count < 4) {
|
||||
printk(KERN_ERR "hid-plff: not enough values in the field\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL);
|
||||
if (!plff)
|
||||
return -ENOMEM;
|
||||
|
||||
dev = hidinput->input;
|
||||
|
||||
set_bit(FF_RUMBLE, dev->ffbit);
|
||||
|
||||
error = input_ff_create_memless(dev, plff, hid_plff_play);
|
||||
if (error) {
|
||||
kfree(plff);
|
||||
return error;
|
||||
}
|
||||
|
||||
plff->report = report;
|
||||
plff->report->field[0]->value[0] = 0x00;
|
||||
plff->report->field[0]->value[1] = 0x00;
|
||||
plff->report->field[0]->value[2] = 0x00;
|
||||
plff->report->field[0]->value[3] = 0x00;
|
||||
usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 "
|
||||
"2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -264,6 +264,8 @@ struct hid_item {
|
||||
#define HID_QUIRK_INVERT_HWHEEL 0x00004000
|
||||
#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
|
||||
#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
|
||||
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
|
||||
#define HID_QUIRK_IGNORE_MOUSE 0x00040000
|
||||
|
||||
/*
|
||||
* This is the global environment of the parser. This information is
|
||||
@@ -430,8 +432,8 @@ struct hid_device { /* device report descriptor */
|
||||
|
||||
/* device-specific function pointers */
|
||||
int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
|
||||
int (*hidinput_open) (struct input_dev *);
|
||||
void (*hidinput_close) (struct input_dev *);
|
||||
int (*hid_open) (struct hid_device *);
|
||||
void (*hid_close) (struct hid_device *);
|
||||
|
||||
/* hiddev event handler */
|
||||
void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
|
||||
@@ -471,16 +473,6 @@ struct hid_descriptor {
|
||||
struct hid_class_descriptor desc[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "hid-debug.h"
|
||||
#else
|
||||
#define hid_dump_input(a,b) do { } while (0)
|
||||
#define hid_dump_device(c) do { } while (0)
|
||||
#define hid_dump_field(a,b) do { } while (0)
|
||||
#define resolv_usage(a) do { } while (0)
|
||||
#define resolv_event(a,b) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
|
||||
/* We ignore a few input applications that are not widely used */
|
||||
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
|
||||
@@ -503,6 +495,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size);
|
||||
int hid_ff_init(struct hid_device *hid);
|
||||
|
||||
int hid_lgff_init(struct hid_device *hid);
|
||||
int hid_plff_init(struct hid_device *hid);
|
||||
int hid_tmff_init(struct hid_device *hid);
|
||||
int hid_zpff_init(struct hid_device *hid);
|
||||
#ifdef CONFIG_HID_PID
|
||||
|
||||
Reference in New Issue
Block a user