Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
1f17689c
Commit
1f17689c
authored
May 29, 2003
by
Ben Collins
Committed by
Greg Kroah-Hartman
May 29, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] USB Multi-input quirk
parent
a98b28b1
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
141 additions
and
51 deletions
+141
-51
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+3
-5
drivers/usb/input/hid-input.c
drivers/usb/input/hid-input.c
+110
-29
drivers/usb/input/hid-lgff.c
drivers/usb/input/hid-lgff.c
+6
-5
drivers/usb/input/hid-tmff.c
drivers/usb/input/hid-tmff.c
+6
-5
drivers/usb/input/hid.h
drivers/usb/input/hid.h
+9
-1
drivers/usb/input/pid.c
drivers/usb/input/pid.c
+7
-6
No files found.
drivers/usb/input/hid-core.c
View file @
1f17689c
...
...
@@ -1387,9 +1387,9 @@ struct hid_blacklist {
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_MGE
,
USB_DEVICE_ID_MGE_UPS1
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_TOPMAX
,
USB_DEVICE_ID_TOPMAX_COBRAPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_DRIVING
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FLYING
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FIGHTING
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_DRIVING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FLYING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FIGHTING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
100
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ONTRAK
,
USB_DEVICE_ID_ONTRAK_ADU100
+
200
,
HID_QUIRK_IGNORE
},
...
...
@@ -1629,8 +1629,6 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
hid_init_reports
(
hid
);
hid_dump_device
(
hid
);
hid_ff_init
(
hid
);
if
(
!
hidinput_connect
(
hid
))
hid
->
claimed
|=
HID_CLAIMED_INPUT
;
if
(
!
hiddev_connect
(
hid
))
...
...
drivers/usb/input/hid-input.c
View file @
1f17689c
...
...
@@ -60,9 +60,36 @@ static struct {
__s32
y
;
}
hid_hat_to_axis
[]
=
{{
0
,
0
},
{
0
,
-
1
},
{
1
,
-
1
},
{
1
,
0
},
{
1
,
1
},
{
0
,
1
},
{
-
1
,
1
},
{
-
1
,
0
},
{
-
1
,
-
1
}};
static
void
hidinput_configure_usage
(
struct
hid_device
*
device
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
)
static
struct
input_dev
*
find_input
(
struct
hid_device
*
hid
,
struct
hid_field
*
field
)
{
struct
input_dev
*
input
=
&
device
->
input
;
struct
list_head
*
lh
;
struct
hid_input
*
hidinput
;
list_for_each
(
lh
,
&
hid
->
inputs
)
{
int
i
;
hidinput
=
list_entry
(
lh
,
struct
hid_input
,
list
);
for
(
i
=
0
;
i
<
hidinput
->
maxfield
;
i
++
)
if
(
hidinput
->
fields
[
i
]
==
field
)
return
&
hidinput
->
input
;
}
/* Assume we only have one input and use it */
if
(
!
list_empty
(
&
hid
->
inputs
))
{
hidinput
=
list_entry
(
hid
->
inputs
.
next
,
struct
hid_input
,
list
);
return
&
hidinput
->
input
;
}
/* This is really a bug */
return
NULL
;
}
static
void
hidinput_configure_usage
(
struct
hid_input
*
hidinput
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
)
{
struct
input_dev
*
input
=
&
hidinput
->
input
;
struct
hid_device
*
device
=
hidinput
->
input
.
private
;
int
max
;
int
is_abs
=
0
;
unsigned
long
*
bit
;
...
...
@@ -388,9 +415,12 @@ static void hidinput_configure_usage(struct hid_device *device, struct hid_field
void
hidinput_hid_event
(
struct
hid_device
*
hid
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
__s32
value
,
struct
pt_regs
*
regs
)
{
struct
input_dev
*
input
=
&
hid
->
input
;
struct
input_dev
*
input
=
find_input
(
hid
,
field
)
;
int
*
quirks
=
&
hid
->
quirks
;
if
(
!
input
)
return
;
input_regs
(
input
,
regs
);
if
(
usage
->
hat_min
!=
usage
->
hat_max
)
{
...
...
@@ -443,7 +473,13 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
void
hidinput_report_event
(
struct
hid_device
*
hid
,
struct
hid_report
*
report
)
{
input_sync
(
&
hid
->
input
);
struct
list_head
*
lh
;
struct
hid_input
*
hidinput
;
list_for_each
(
lh
,
&
hid
->
inputs
)
{
hidinput
=
list_entry
(
lh
,
struct
hid_input
,
list
);
input_sync
(
&
hidinput
->
input
);
}
}
static
int
hidinput_input_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
...
...
@@ -490,7 +526,10 @@ int hidinput_connect(struct hid_device *hid)
struct
hid_report_enum
*
report_enum
;
struct
hid_report
*
report
;
struct
list_head
*
list
;
int
i
,
j
,
k
;
struct
hid_input
*
hidinput
=
NULL
;
int
i
,
j
;
INIT_LIST_HEAD
(
&
hid
->
inputs
);
for
(
i
=
0
;
i
<
hid
->
maxcollection
;
i
++
)
if
(
hid
->
collection
[
i
].
type
==
HID_COLLECTION_APPLICATION
&&
...
...
@@ -500,37 +539,79 @@ int hidinput_connect(struct hid_device *hid)
if
(
i
==
hid
->
maxcollection
)
return
-
1
;
hid
->
input
.
private
=
hid
;
hid
->
input
.
event
=
hidinput_input_event
;
hid
->
input
.
open
=
hidinput_open
;
hid
->
input
.
close
=
hidinput_close
;
hid
->
input
.
name
=
hid
->
name
;
hid
->
input
.
phys
=
hid
->
phys
;
hid
->
input
.
uniq
=
hid
->
uniq
;
hid
->
input
.
id
.
bustype
=
BUS_USB
;
hid
->
input
.
id
.
vendor
=
dev
->
descriptor
.
idVendor
;
hid
->
input
.
id
.
product
=
dev
->
descriptor
.
idProduct
;
hid
->
input
.
id
.
version
=
dev
->
descriptor
.
bcdDevice
;
for
(
k
=
HID_INPUT_REPORT
;
k
<=
HID_OUTPUT_REPORT
;
k
++
)
{
report_enum
=
hid
->
report_enum
+
k
;
list
=
report_enum
->
report_list
.
next
;
while
(
list
!=
&
report_enum
->
report_list
)
{
report
=
(
struct
hid_report
*
)
list
;
for
(
i
=
0
;
i
<
report
->
maxfield
;
i
++
)
for
(
j
=
0
;
j
<
report
->
field
[
i
]
->
maxusage
;
j
++
)
hidinput_configure_usage
(
hid
,
report
->
field
[
i
],
report
->
field
[
i
]
->
usage
+
j
);
list
=
list
->
next
;
report_enum
=
hid
->
report_enum
+
HID_INPUT_REPORT
;
list
=
report_enum
->
report_list
.
next
;
while
(
list
!=
&
report_enum
->
report_list
)
{
report
=
(
struct
hid_report
*
)
list
;
if
(
!
report
->
maxfield
)
continue
;
if
(
!
hidinput
)
{
hidinput
=
kmalloc
(
sizeof
(
*
hidinput
),
GFP_KERNEL
);
if
(
!
hidinput
)
{
err
(
"Out of memory during hid input probe"
);
return
-
1
;
}
memset
(
hidinput
,
0
,
sizeof
(
*
hidinput
));
list_add_tail
(
&
hidinput
->
list
,
&
hid
->
inputs
);
hidinput
->
input
.
private
=
hid
;
hidinput
->
input
.
event
=
hidinput_input_event
;
hidinput
->
input
.
open
=
hidinput_open
;
hidinput
->
input
.
close
=
hidinput_close
;
hidinput
->
input
.
name
=
hid
->
name
;
hidinput
->
input
.
phys
=
hid
->
phys
;
hidinput
->
input
.
uniq
=
hid
->
uniq
;
hidinput
->
input
.
id
.
bustype
=
BUS_USB
;
hidinput
->
input
.
id
.
vendor
=
dev
->
descriptor
.
idVendor
;
hidinput
->
input
.
id
.
product
=
dev
->
descriptor
.
idProduct
;
hidinput
->
input
.
id
.
version
=
dev
->
descriptor
.
bcdDevice
;
}
for
(
i
=
0
;
i
<
report
->
maxfield
;
i
++
)
for
(
j
=
0
;
j
<
report
->
field
[
i
]
->
maxusage
;
j
++
)
hidinput_configure_usage
(
hidinput
,
report
->
field
[
i
],
report
->
field
[
i
]
->
usage
+
j
);
if
(
hid
->
quirks
&
HID_QUIRK_MULTI_INPUT
)
{
/* This will leave hidinput NULL, so that it
* allocates another one if we have more inputs on
* the same interface. Some devices (e.g. Happ's
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput
->
fields
=
report
->
field
;
hidinput
->
maxfield
=
report
->
maxfield
;
input_register_device
(
&
hidinput
->
input
);
hidinput
=
NULL
;
}
list
=
list
->
next
;
}
input_register_device
(
&
hid
->
input
);
/* 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
(
hidinput
)
{
hid_ff_init
(
hid
);
input_register_device
(
&
hidinput
->
input
);
}
return
0
;
}
void
hidinput_disconnect
(
struct
hid_device
*
hid
)
{
input_unregister_device
(
&
hid
->
input
);
struct
list_head
*
lh
,
*
next
;
struct
hid_input
*
hidinput
;
list_for_each_safe
(
lh
,
next
,
&
hid
->
inputs
)
{
hidinput
=
list_entry
(
lh
,
struct
hid_input
,
list
);
input_unregister_device
(
&
hidinput
->
input
);
list_del
(
&
hidinput
->
list
);
kfree
(
hidinput
);
}
}
drivers/usb/input/hid-lgff.c
View file @
1f17689c
...
...
@@ -254,6 +254,7 @@ static void hid_lgff_input_init(struct hid_device* hid)
signed
short
*
ff
;
u16
idVendor
=
hid
->
dev
->
descriptor
.
idVendor
;
u16
idProduct
=
hid
->
dev
->
descriptor
.
idProduct
;
struct
hid_input
*
hidinput
=
list_entry
(
&
hid
->
inputs
,
struct
hid_input
,
list
);
while
(
dev
->
idVendor
&&
(
idVendor
!=
dev
->
idVendor
||
idProduct
!=
dev
->
idProduct
))
dev
++
;
...
...
@@ -261,15 +262,15 @@ static void hid_lgff_input_init(struct hid_device* hid)
ff
=
dev
->
ff
;
while
(
*
ff
>=
0
)
{
set_bit
(
*
ff
,
hid
->
input
.
ffbit
);
set_bit
(
*
ff
,
hid
input
->
input
.
ffbit
);
++
ff
;
}
hid
->
input
.
upload_effect
=
hid_lgff_upload_effect
;
hid
->
input
.
flush
=
hid_lgff_flush
;
hid
input
->
input
.
upload_effect
=
hid_lgff_upload_effect
;
hid
input
->
input
.
flush
=
hid_lgff_flush
;
set_bit
(
EV_FF
,
hid
->
input
.
evbit
);
hid
->
input
.
ff_effects_max
=
LGFF_EFFECTS
;
set_bit
(
EV_FF
,
hid
input
->
input
.
evbit
);
hid
input
->
input
.
ff_effects_max
=
LGFF_EFFECTS
;
}
static
void
hid_lgff_exit
(
struct
hid_device
*
hid
)
...
...
drivers/usb/input/hid-tmff.c
View file @
1f17689c
...
...
@@ -110,6 +110,7 @@ int hid_tmff_init(struct hid_device *hid)
{
struct
tmff_device
*
private
;
struct
list_head
*
pos
;
struct
hid_input
*
hidinput
=
list_entry
(
&
hid
->
inputs
,
struct
hid_input
,
list
);
private
=
kmalloc
(
sizeof
(
struct
tmff_device
),
GFP_KERNEL
);
if
(
!
private
)
...
...
@@ -154,7 +155,7 @@ int hid_tmff_init(struct hid_device *hid)
private
->
report
=
report
;
private
->
rumble
=
field
;
set_bit
(
FF_RUMBLE
,
hid
->
input
.
ffbit
);
set_bit
(
FF_RUMBLE
,
hid
input
->
input
.
ffbit
);
break
;
default:
...
...
@@ -163,11 +164,11 @@ int hid_tmff_init(struct hid_device *hid)
}
/* Fallthrough to here only when a valid usage is found */
hid
->
input
.
upload_effect
=
hid_tmff_upload_effect
;
hid
->
input
.
flush
=
hid_tmff_flush
;
hid
input
->
input
.
upload_effect
=
hid_tmff_upload_effect
;
hid
input
->
input
.
flush
=
hid_tmff_flush
;
set_bit
(
EV_FF
,
hid
->
input
.
evbit
);
hid
->
input
.
ff_effects_max
=
TMFF_EFFECTS
;
set_bit
(
EV_FF
,
hid
input
->
input
.
evbit
);
hid
input
->
input
.
ff_effects_max
=
TMFF_EFFECTS
;
}
}
...
...
drivers/usb/input/hid.h
View file @
1f17689c
...
...
@@ -207,6 +207,7 @@ struct hid_item {
#define HID_QUIRK_NOGET 0x08
#define HID_QUIRK_HIDDEV 0x10
#define HID_QUIRK_BADPAD 0x20
#define HID_QUIRK_MULTI_INPUT 0x40
/*
* This is the global environment of the parser. This information is
...
...
@@ -321,6 +322,13 @@ struct hid_control_fifo {
#define HID_CTRL_RUNNING 1
#define HID_OUT_RUNNING 2
struct
hid_input
{
struct
list_head
list
;
struct
hid_field
**
fields
;
int
maxfield
;
struct
input_dev
input
;
};
struct
hid_device
{
/* device report descriptor */
__u8
*
rdesc
;
unsigned
rsize
;
...
...
@@ -360,7 +368,7 @@ struct hid_device { /* device report descriptor */
unsigned
claimed
;
/* Claimed by hidinput, hiddev? */
unsigned
quirks
;
/* Various quirks the device can pull on us */
struct
input_dev
input
;
/* The input structure
*/
struct
list_head
inputs
;
/* The list of inputs
*/
void
*
hiddev
;
/* The hiddev structure */
int
minor
;
/* Hiddev minor number */
...
...
drivers/usb/input/pid.c
View file @
1f17689c
...
...
@@ -269,7 +269,8 @@ static int hid_pid_upload_effect(struct input_dev *dev,
int
hid_pid_init
(
struct
hid_device
*
hid
)
{
struct
hid_ff_pid
*
private
;
struct
hid_input
*
hidinput
=
list_entry
(
&
hid
->
inputs
,
struct
hid_input
,
list
);
private
=
hid
->
ff_private
=
kmalloc
(
sizeof
(
struct
hid_ff_pid
),
GFP_KERNEL
);
if
(
!
private
)
return
-
1
;
...
...
@@ -289,11 +290,11 @@ int hid_pid_init(struct hid_device *hid)
}
usb_fill_control_urb
(
private
->
urbffout
,
hid
->
dev
,
0
,(
void
*
)
&
private
->
ffcr
,
private
->
ctrl_buffer
,
8
,
hid_pid_ctrl_out
,
hid
);
hid
->
input
.
upload_effect
=
hid_pid_upload_effect
;
hid
->
input
.
flush
=
hid_pid_flush
;
hid
->
input
.
ff_effects_max
=
8
;
// A random default
set_bit
(
EV_FF
,
hid
->
input
.
evbit
);
set_bit
(
EV_FF_STATUS
,
hid
->
input
.
evbit
);
hid
input
->
input
.
upload_effect
=
hid_pid_upload_effect
;
hid
input
->
input
.
flush
=
hid_pid_flush
;
hid
input
->
input
.
ff_effects_max
=
8
;
// A random default
set_bit
(
EV_FF
,
hid
input
->
input
.
evbit
);
set_bit
(
EV_FF_STATUS
,
hid
input
->
input
.
evbit
);
spin_lock_init
(
&
private
->
lock
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment