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
56ccd186
Commit
56ccd186
authored
May 22, 2012
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'upstream' into for-linus
Conflicts: drivers/hid/hid-core.c
parents
b3d07e03
d1257081
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
307 additions
and
32 deletions
+307
-32
drivers/hid/Kconfig
drivers/hid/Kconfig
+6
-0
drivers/hid/Makefile
drivers/hid/Makefile
+1
-0
drivers/hid/hid-apple.c
drivers/hid/hid-apple.c
+1
-1
drivers/hid/hid-aureal.c
drivers/hid/hid-aureal.c
+54
-0
drivers/hid/hid-core.c
drivers/hid/hid-core.c
+23
-8
drivers/hid/hid-ids.h
drivers/hid/hid-ids.h
+4
-0
drivers/hid/hid-uclogic.c
drivers/hid/hid-uclogic.c
+141
-0
drivers/hid/hidraw.c
drivers/hid/hidraw.c
+13
-6
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-core.c
+55
-10
drivers/hid/usbhid/hiddev.c
drivers/hid/usbhid/hiddev.c
+5
-4
drivers/hid/usbhid/usbhid.h
drivers/hid/usbhid/usbhid.h
+1
-0
include/linux/hid.h
include/linux/hid.h
+1
-1
include/linux/hidraw.h
include/linux/hidraw.h
+2
-2
No files found.
drivers/hid/Kconfig
View file @
56ccd186
...
...
@@ -104,6 +104,12 @@ config HID_APPLE
Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
MacBooks, MacBook Pros and Apple Aluminum.
config HID_AUREAL
tristate "Aureal"
depends on USB_HID
---help---
Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
config HID_BELKIN
tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT
depends on USB_HID
...
...
drivers/hid/Makefile
View file @
56ccd186
...
...
@@ -38,6 +38,7 @@ endif
obj-$(CONFIG_HID_A4TECH)
+=
hid-a4tech.o
obj-$(CONFIG_HID_ACRUX)
+=
hid-axff.o
obj-$(CONFIG_HID_APPLE)
+=
hid-apple.o
obj-$(CONFIG_HID_AUREAL)
+=
hid-aureal.o
obj-$(CONFIG_HID_BELKIN)
+=
hid-belkin.o
obj-$(CONFIG_HID_CHERRY)
+=
hid-cherry.o
obj-$(CONFIG_HID_CHICONY)
+=
hid-chicony.o
...
...
drivers/hid/hid-apple.c
View file @
56ccd186
drivers/hid/hid-aureal.c
0 → 100644
View file @
56ccd186
/*
* HID driver for Aureal Cy se W-01RN USB_V3.1 devices
*
* Copyright (c) 2010 Franco Catrin <fcatrin@gmail.com>
* Copyright (c) 2010 Ben Cropley <bcropley@internode.on.net>
*
* Based on HID sunplus driver by
* 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
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
static
__u8
*
aureal_report_fixup
(
struct
hid_device
*
hdev
,
__u8
*
rdesc
,
unsigned
int
*
rsize
)
{
if
(
*
rsize
>=
54
&&
rdesc
[
52
]
==
0x25
&&
rdesc
[
53
]
==
0x01
)
{
dev_info
(
&
hdev
->
dev
,
"fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.
\n
"
);
rdesc
[
53
]
=
0x65
;
}
return
rdesc
;
}
static
const
struct
hid_device_id
aureal_devices
[]
=
{
{
HID_USB_DEVICE
(
USB_VENDOR_ID_AUREAL
,
USB_DEVICE_ID_AUREAL_W01RN
)
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
aureal_devices
);
static
struct
hid_driver
aureal_driver
=
{
.
name
=
"aureal"
,
.
id_table
=
aureal_devices
,
.
report_fixup
=
aureal_report_fixup
,
};
static
int
__init
aureal_init
(
void
)
{
return
hid_register_driver
(
&
aureal_driver
);
}
static
void
__exit
aureal_exit
(
void
)
{
hid_unregister_driver
(
&
aureal_driver
);
}
module_init
(
aureal_init
);
module_exit
(
aureal_exit
);
MODULE_LICENSE
(
"GPL"
);
drivers/hid/hid-core.c
View file @
56ccd186
...
...
@@ -230,9 +230,16 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
return
-
1
;
}
if
(
parser
->
global
.
logical_maximum
<
parser
->
global
.
logical_minimum
)
{
hid_err
(
parser
->
device
,
"logical range invalid %d %d
\n
"
,
parser
->
global
.
logical_minimum
,
parser
->
global
.
logical_maximum
);
/* Handle both signed and unsigned cases properly */
if
((
parser
->
global
.
logical_minimum
<
0
&&
parser
->
global
.
logical_maximum
<
parser
->
global
.
logical_minimum
)
||
(
parser
->
global
.
logical_minimum
>=
0
&&
(
__u32
)
parser
->
global
.
logical_maximum
<
(
__u32
)
parser
->
global
.
logical_minimum
))
{
dbg_hid
(
"logical range invalid 0x%x 0x%x
\n
"
,
parser
->
global
.
logical_minimum
,
parser
->
global
.
logical_maximum
);
return
-
1
;
}
...
...
@@ -1149,7 +1156,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
return
report
;
}
void
hid_report_raw_event
(
struct
hid_device
*
hid
,
int
type
,
u8
*
data
,
int
size
,
int
hid_report_raw_event
(
struct
hid_device
*
hid
,
int
type
,
u8
*
data
,
int
size
,
int
interrupt
)
{
struct
hid_report_enum
*
report_enum
=
hid
->
report_enum
+
type
;
...
...
@@ -1157,10 +1164,11 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
unsigned
int
a
;
int
rsize
,
csize
=
size
;
u8
*
cdata
=
data
;
int
ret
=
0
;
report
=
hid_get_report
(
report_enum
,
data
);
if
(
!
report
)
return
;
goto
out
;
if
(
report_enum
->
numbered
)
{
cdata
++
;
...
...
@@ -1180,14 +1188,19 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
if
((
hid
->
claimed
&
HID_CLAIMED_HIDDEV
)
&&
hid
->
hiddev_report_event
)
hid
->
hiddev_report_event
(
hid
,
report
);
if
(
hid
->
claimed
&
HID_CLAIMED_HIDRAW
)
hidraw_report_event
(
hid
,
data
,
size
);
if
(
hid
->
claimed
&
HID_CLAIMED_HIDRAW
)
{
ret
=
hidraw_report_event
(
hid
,
data
,
size
);
if
(
ret
)
goto
out
;
}
for
(
a
=
0
;
a
<
report
->
maxfield
;
a
++
)
hid_input_field
(
hid
,
report
->
field
[
a
],
cdata
,
interrupt
);
if
(
hid
->
claimed
&
HID_CLAIMED_INPUT
)
hidinput_report_event
(
hid
,
report
);
out:
return
ret
;
}
EXPORT_SYMBOL_GPL
(
hid_report_raw_event
);
...
...
@@ -1264,7 +1277,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
}
}
hid_report_raw_event
(
hid
,
type
,
data
,
size
,
interrupt
);
ret
=
hid_report_raw_event
(
hid
,
type
,
data
,
size
,
interrupt
);
unlock:
up
(
&
hid
->
driver_lock
);
...
...
@@ -1496,6 +1509,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{
HID_BLUETOOTH_DEVICE
(
USB_VENDOR_ID_APPLE
,
USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_APPLE
,
USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_APPLE
,
USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_AUREAL
,
USB_DEVICE_ID_AUREAL_W01RN
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_BELKIN
,
USB_DEVICE_ID_FLIP_KVM
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_BAANTO
,
USB_DEVICE_ID_BAANTO_MT_190W2
),
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_BTC
,
USB_DEVICE_ID_BTC_EMPREX_REMOTE
)
},
...
...
@@ -1631,6 +1645,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UCLOGIC
,
USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UCLOGIC
,
USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UCLOGIC
,
USB_DEVICE_ID_UCLOGIC_TABLET_WP1062
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UCLOGIC
,
USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_WISEGROUP
,
USB_DEVICE_ID_SMARTJOY_PLUS
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_WISEGROUP
,
USB_DEVICE_ID_SUPER_JOY_BOX_3
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_WISEGROUP
,
USB_DEVICE_ID_DUAL_USB_JOYPAD
)
},
...
...
drivers/hid/hid-ids.h
View file @
56ccd186
...
...
@@ -154,6 +154,9 @@
#define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
#define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER 0x2118
#define USB_VENDOR_ID_AUREAL 0x0755
#define USB_DEVICE_ID_AUREAL_W01RN 0x2626
#define USB_VENDOR_ID_AVERMEDIA 0x07ca
#define USB_DEVICE_ID_AVER_FM_MR800 0xb800
...
...
@@ -729,6 +732,7 @@
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005
#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064
#define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522
#define USB_VENDOR_ID_UNITEC 0x227d
#define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709
...
...
drivers/hid/hid-uclogic.c
View file @
56ccd186
...
...
@@ -14,6 +14,7 @@
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
#include "hid-ids.h"
...
...
@@ -352,9 +353,125 @@ static __u8 pf1209_rdesc_fixed[] = {
0xC0
/* End Collection */
};
/*
* See TWHL850 description, device and HID report descriptors at
* http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850
*/
/* Size of the original descriptors of TWHL850 tablet */
#define TWHL850_RDESC_ORIG_SIZE0 182
#define TWHL850_RDESC_ORIG_SIZE1 161
#define TWHL850_RDESC_ORIG_SIZE2 92
/* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */
static
__u8
twhl850_rdesc_fixed0
[]
=
{
0x05
,
0x0D
,
/* Usage Page (Digitizer), */
0x09
,
0x02
,
/* Usage (Pen), */
0xA1
,
0x01
,
/* Collection (Application), */
0x85
,
0x09
,
/* Report ID (9), */
0x09
,
0x20
,
/* Usage (Stylus), */
0xA0
,
/* Collection (Physical), */
0x14
,
/* Logical Minimum (0), */
0x25
,
0x01
,
/* Logical Maximum (1), */
0x75
,
0x01
,
/* Report Size (1), */
0x95
,
0x03
,
/* Report Count (3), */
0x09
,
0x42
,
/* Usage (Tip Switch), */
0x09
,
0x44
,
/* Usage (Barrel Switch), */
0x09
,
0x46
,
/* Usage (Tablet Pick), */
0x81
,
0x02
,
/* Input (Variable), */
0x81
,
0x03
,
/* Input (Constant, Variable), */
0x95
,
0x01
,
/* Report Count (1), */
0x09
,
0x32
,
/* Usage (In Range), */
0x81
,
0x02
,
/* Input (Variable), */
0x81
,
0x03
,
/* Input (Constant, Variable), */
0x75
,
0x10
,
/* Report Size (16), */
0xA4
,
/* Push, */
0x05
,
0x01
,
/* Usage Page (Desktop), */
0x65
,
0x13
,
/* Unit (Inch), */
0x55
,
0xFD
,
/* Unit Exponent (-3), */
0x34
,
/* Physical Minimum (0), */
0x09
,
0x30
,
/* Usage (X), */
0x46
,
0x40
,
0x1F
,
/* Physical Maximum (8000), */
0x26
,
0x00
,
0x7D
,
/* Logical Maximum (32000), */
0x81
,
0x02
,
/* Input (Variable), */
0x09
,
0x31
,
/* Usage (Y), */
0x46
,
0x88
,
0x13
,
/* Physical Maximum (5000), */
0x26
,
0x20
,
0x4E
,
/* Logical Maximum (20000), */
0x81
,
0x02
,
/* Input (Variable), */
0xB4
,
/* Pop, */
0x09
,
0x30
,
/* Usage (Tip Pressure), */
0x26
,
0xFF
,
0x03
,
/* Logical Maximum (1023), */
0x81
,
0x02
,
/* Input (Variable), */
0xC0
,
/* End Collection, */
0xC0
/* End Collection */
};
/* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */
static
__u8
twhl850_rdesc_fixed1
[]
=
{
0x05
,
0x01
,
/* Usage Page (Desktop), */
0x09
,
0x02
,
/* Usage (Mouse), */
0xA1
,
0x01
,
/* Collection (Application), */
0x85
,
0x01
,
/* Report ID (1), */
0x09
,
0x01
,
/* Usage (Pointer), */
0xA0
,
/* Collection (Physical), */
0x05
,
0x09
,
/* Usage Page (Button), */
0x75
,
0x01
,
/* Report Size (1), */
0x95
,
0x03
,
/* Report Count (3), */
0x19
,
0x01
,
/* Usage Minimum (01h), */
0x29
,
0x03
,
/* Usage Maximum (03h), */
0x14
,
/* Logical Minimum (0), */
0x25
,
0x01
,
/* Logical Maximum (1), */
0x81
,
0x02
,
/* Input (Variable), */
0x95
,
0x05
,
/* Report Count (5), */
0x81
,
0x03
,
/* Input (Constant, Variable), */
0x05
,
0x01
,
/* Usage Page (Desktop), */
0x09
,
0x30
,
/* Usage (X), */
0x09
,
0x31
,
/* Usage (Y), */
0x16
,
0x00
,
0x80
,
/* Logical Minimum (-32768), */
0x26
,
0xFF
,
0x7F
,
/* Logical Maximum (32767), */
0x75
,
0x10
,
/* Report Size (16), */
0x95
,
0x02
,
/* Report Count (2), */
0x81
,
0x06
,
/* Input (Variable, Relative), */
0x09
,
0x38
,
/* Usage (Wheel), */
0x15
,
0xFF
,
/* Logical Minimum (-1), */
0x25
,
0x01
,
/* Logical Maximum (1), */
0x95
,
0x01
,
/* Report Count (1), */
0x75
,
0x08
,
/* Report Size (8), */
0x81
,
0x06
,
/* Input (Variable, Relative), */
0x81
,
0x03
,
/* Input (Constant, Variable), */
0xC0
,
/* End Collection, */
0xC0
/* End Collection */
};
/* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */
static
__u8
twhl850_rdesc_fixed2
[]
=
{
0x05
,
0x01
,
/* Usage Page (Desktop), */
0x09
,
0x06
,
/* Usage (Keyboard), */
0xA1
,
0x01
,
/* Collection (Application), */
0x85
,
0x03
,
/* Report ID (3), */
0x05
,
0x07
,
/* Usage Page (Keyboard), */
0x14
,
/* Logical Minimum (0), */
0x19
,
0xE0
,
/* Usage Minimum (KB Leftcontrol), */
0x29
,
0xE7
,
/* Usage Maximum (KB Right GUI), */
0x25
,
0x01
,
/* Logical Maximum (1), */
0x75
,
0x01
,
/* Report Size (1), */
0x95
,
0x08
,
/* Report Count (8), */
0x81
,
0x02
,
/* Input (Variable), */
0x18
,
/* Usage Minimum (None), */
0x29
,
0xFF
,
/* Usage Maximum (FFh), */
0x26
,
0xFF
,
0x00
,
/* Logical Maximum (255), */
0x75
,
0x08
,
/* Report Size (8), */
0x95
,
0x06
,
/* Report Count (6), */
0x80
,
/* Input, */
0xC0
/* End Collection */
};
static
__u8
*
uclogic_report_fixup
(
struct
hid_device
*
hdev
,
__u8
*
rdesc
,
unsigned
int
*
rsize
)
{
struct
usb_interface
*
iface
=
to_usb_interface
(
hdev
->
dev
.
parent
);
__u8
iface_num
=
iface
->
cur_altsetting
->
desc
.
bInterfaceNumber
;
switch
(
hdev
->
product
)
{
case
USB_DEVICE_ID_UCLOGIC_TABLET_PF1209
:
if
(
*
rsize
==
PF1209_RDESC_ORIG_SIZE
)
{
...
...
@@ -386,6 +503,28 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*
rsize
=
sizeof
(
wp1062_rdesc_fixed
);
}
break
;
case
USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850
:
switch
(
iface_num
)
{
case
0
:
if
(
*
rsize
==
TWHL850_RDESC_ORIG_SIZE0
)
{
rdesc
=
twhl850_rdesc_fixed0
;
*
rsize
=
sizeof
(
twhl850_rdesc_fixed0
);
}
break
;
case
1
:
if
(
*
rsize
==
TWHL850_RDESC_ORIG_SIZE1
)
{
rdesc
=
twhl850_rdesc_fixed1
;
*
rsize
=
sizeof
(
twhl850_rdesc_fixed1
);
}
break
;
case
2
:
if
(
*
rsize
==
TWHL850_RDESC_ORIG_SIZE2
)
{
rdesc
=
twhl850_rdesc_fixed2
;
*
rsize
=
sizeof
(
twhl850_rdesc_fixed2
);
}
break
;
}
break
;
}
return
rdesc
;
...
...
@@ -402,6 +541,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UCLOGIC
,
USB_DEVICE_ID_UCLOGIC_TABLET_WP1062
)
},
{
HID_USB_DEVICE
(
USB_VENDOR_ID_UCLOGIC
,
USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850
)
},
{
}
};
MODULE_DEVICE_TABLE
(
hid
,
uclogic_devices
);
...
...
drivers/hid/hidraw.c
View file @
56ccd186
...
...
@@ -87,11 +87,13 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
len
=
list
->
buffer
[
list
->
tail
].
len
>
count
?
count
:
list
->
buffer
[
list
->
tail
].
len
;
if
(
list
->
buffer
[
list
->
tail
].
value
)
{
if
(
copy_to_user
(
buffer
,
list
->
buffer
[
list
->
tail
].
value
,
len
))
{
ret
=
-
EFAULT
;
goto
out
;
}
ret
=
len
;
}
kfree
(
list
->
buffer
[
list
->
tail
].
value
);
list
->
tail
=
(
list
->
tail
+
1
)
&
(
HIDRAW_BUFFER_SIZE
-
1
);
...
...
@@ -437,19 +439,24 @@ static const struct file_operations hidraw_ops = {
.
llseek
=
noop_llseek
,
};
void
hidraw_report_event
(
struct
hid_device
*
hid
,
u8
*
data
,
int
len
)
int
hidraw_report_event
(
struct
hid_device
*
hid
,
u8
*
data
,
int
len
)
{
struct
hidraw
*
dev
=
hid
->
hidraw
;
struct
hidraw_list
*
list
;
int
ret
=
0
;
list_for_each_entry
(
list
,
&
dev
->
list
,
node
)
{
list
->
buffer
[
list
->
head
].
value
=
kmemdup
(
data
,
len
,
GFP_ATOMIC
);
if
(
!
(
list
->
buffer
[
list
->
head
].
value
=
kmemdup
(
data
,
len
,
GFP_ATOMIC
)))
{
ret
=
-
ENOMEM
;
break
;
}
list
->
buffer
[
list
->
head
].
len
=
len
;
list
->
head
=
(
list
->
head
+
1
)
&
(
HIDRAW_BUFFER_SIZE
-
1
);
kill_fasync
(
&
list
->
fasync
,
SIGIO
,
POLL_IN
);
}
wake_up_interruptible
(
&
dev
->
wait
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
hidraw_report_event
);
...
...
drivers/hid/usbhid/hid-core.c
View file @
56ccd186
...
...
@@ -28,6 +28,7 @@
#include <linux/input.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/string.h>
#include <linux/usb.h>
...
...
@@ -86,8 +87,13 @@ static int hid_start_in(struct hid_device *hid)
!
test_bit
(
HID_REPORTED_IDLE
,
&
usbhid
->
iofl
)
&&
!
test_and_set_bit
(
HID_IN_RUNNING
,
&
usbhid
->
iofl
))
{
rc
=
usb_submit_urb
(
usbhid
->
urbin
,
GFP_ATOMIC
);
if
(
rc
!=
0
)
if
(
rc
!=
0
)
{
clear_bit
(
HID_IN_RUNNING
,
&
usbhid
->
iofl
);
if
(
rc
==
-
ENOSPC
)
set_bit
(
HID_NO_BANDWIDTH
,
&
usbhid
->
iofl
);
}
else
{
clear_bit
(
HID_NO_BANDWIDTH
,
&
usbhid
->
iofl
);
}
}
spin_unlock_irqrestore
(
&
usbhid
->
lock
,
flags
);
return
rc
;
...
...
@@ -173,8 +179,10 @@ static void hid_io_error(struct hid_device *hid)
if
(
time_after
(
jiffies
,
usbhid
->
stop_retry
))
{
/* Retries failed, so do a port reset */
if
(
!
test_and_set_bit
(
HID_RESET_PENDING
,
&
usbhid
->
iofl
))
{
/* Retries failed, so do a port reset unless we lack bandwidth*/
if
(
test_bit
(
HID_NO_BANDWIDTH
,
&
usbhid
->
iofl
)
&&
!
test_and_set_bit
(
HID_RESET_PENDING
,
&
usbhid
->
iofl
))
{
schedule_work
(
&
usbhid
->
reset_work
);
goto
done
;
}
...
...
@@ -700,7 +708,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
int
usbhid_open
(
struct
hid_device
*
hid
)
{
struct
usbhid_device
*
usbhid
=
hid
->
driver_data
;
int
res
;
int
res
=
0
;
mutex_lock
(
&
hid_open_mut
);
if
(
!
hid
->
open
++
)
{
...
...
@@ -708,17 +716,27 @@ int usbhid_open(struct hid_device *hid)
/* the device must be awake to reliably request remote wakeup */
if
(
res
<
0
)
{
hid
->
open
--
;
mutex_unlock
(
&
hid_open_mut
)
;
return
-
EIO
;
res
=
-
EIO
;
goto
done
;
}
usbhid
->
intf
->
needs_remote_wakeup
=
1
;
if
(
hid_start_in
(
hid
))
res
=
hid_start_in
(
hid
);
if
(
res
)
{
if
(
res
!=
-
ENOSPC
)
{
hid_io_error
(
hid
);
res
=
0
;
}
else
{
/* no use opening if resources are insufficient */
hid
->
open
--
;
res
=
-
EBUSY
;
usbhid
->
intf
->
needs_remote_wakeup
=
0
;
}
}
usb_autopm_put_interface
(
usbhid
->
intf
);
}
done:
mutex_unlock
(
&
hid_open_mut
);
return
0
;
return
res
;
}
void
usbhid_close
(
struct
hid_device
*
hid
)
...
...
@@ -1347,7 +1365,34 @@ static int hid_post_reset(struct usb_interface *intf)
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
hid_device
*
hid
=
usb_get_intfdata
(
intf
);
struct
usbhid_device
*
usbhid
=
hid
->
driver_data
;
struct
usb_host_interface
*
interface
=
intf
->
cur_altsetting
;
int
status
;
char
*
rdesc
;
/* Fetch and examine the HID report descriptor. If this
* has changed, then rebind. Since usbcore's check of the
* configuration descriptors passed, we already know that
* the size of the HID report descriptor has not changed.
*/
rdesc
=
kmalloc
(
hid
->
rsize
,
GFP_KERNEL
);
if
(
!
rdesc
)
{
dbg_hid
(
"couldn't allocate rdesc memory (post_reset)
\n
"
);
return
1
;
}
status
=
hid_get_class_descriptor
(
dev
,
interface
->
desc
.
bInterfaceNumber
,
HID_DT_REPORT
,
rdesc
,
hid
->
rsize
);
if
(
status
<
0
)
{
dbg_hid
(
"reading report descriptor failed (post_reset)
\n
"
);
kfree
(
rdesc
);
return
1
;
}
status
=
memcmp
(
rdesc
,
hid
->
rdesc
,
hid
->
rsize
);
kfree
(
rdesc
);
if
(
status
!=
0
)
{
dbg_hid
(
"report descriptor changed
\n
"
);
return
1
;
}
spin_lock_irq
(
&
usbhid
->
lock
);
clear_bit
(
HID_RESET_PENDING
,
&
usbhid
->
iofl
);
...
...
drivers/hid/usbhid/hiddev.c
View file @
56ccd186
...
...
@@ -34,6 +34,7 @@
#include <linux/hid.h>
#include <linux/hiddev.h>
#include <linux/compat.h>
#include <linux/vmalloc.h>
#include "usbhid.h"
#ifdef CONFIG_USB_DYNAMIC_MINORS
...
...
@@ -250,13 +251,13 @@ static int hiddev_release(struct inode * inode, struct file * file)
}
else
{
mutex_unlock
(
&
list
->
hiddev
->
existancelock
);
kfree
(
list
->
hiddev
);
k
free
(
list
);
v
free
(
list
);
return
0
;
}
}
mutex_unlock
(
&
list
->
hiddev
->
existancelock
);
k
free
(
list
);
v
free
(
list
);
return
0
;
}
...
...
@@ -278,7 +279,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
hid
=
usb_get_intfdata
(
intf
);
hiddev
=
hid
->
hiddev
;
if
(
!
(
list
=
kzalloc
(
sizeof
(
struct
hiddev_list
),
GFP_KERNEL
)))
if
(
!
(
list
=
vzalloc
(
sizeof
(
struct
hiddev_list
)
)))
return
-
ENOMEM
;
mutex_init
(
&
list
->
thread_lock
);
list
->
hiddev
=
hiddev
;
...
...
@@ -322,7 +323,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
mutex_unlock
(
&
hiddev
->
existancelock
);
bail:
file
->
private_data
=
NULL
;
k
free
(
list
);
v
free
(
list
);
return
res
;
}
...
...
drivers/hid/usbhid/usbhid.h
View file @
56ccd186
...
...
@@ -55,6 +55,7 @@ struct usb_interface *usbhid_find_interface(int minor);
#define HID_STARTED 8
#define HID_REPORTED_IDLE 9
#define HID_KEYS_PRESSED 10
#define HID_NO_BANDWIDTH 11
/*
* USB-specific HID struct, to be pointed to
...
...
include/linux/hid.h
View file @
56ccd186
...
...
@@ -896,7 +896,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
return
hdev
->
ll_driver
->
power
?
hdev
->
ll_driver
->
power
(
hdev
,
level
)
:
0
;
}
void
hid_report_raw_event
(
struct
hid_device
*
hid
,
int
type
,
u8
*
data
,
int
size
,
int
hid_report_raw_event
(
struct
hid_device
*
hid
,
int
type
,
u8
*
data
,
int
size
,
int
interrupt
);
extern
int
hid_generic_init
(
void
);
...
...
include/linux/hidraw.h
View file @
56ccd186
...
...
@@ -76,13 +76,13 @@ struct hidraw_list {
#ifdef CONFIG_HIDRAW
int
hidraw_init
(
void
);
void
hidraw_exit
(
void
);
void
hidraw_report_event
(
struct
hid_device
*
,
u8
*
,
int
);
int
hidraw_report_event
(
struct
hid_device
*
,
u8
*
,
int
);
int
hidraw_connect
(
struct
hid_device
*
);
void
hidraw_disconnect
(
struct
hid_device
*
);
#else
static
inline
int
hidraw_init
(
void
)
{
return
0
;
}
static
inline
void
hidraw_exit
(
void
)
{
}
static
inline
void
hidraw_report_event
(
struct
hid_device
*
hid
,
u8
*
data
,
int
len
)
{
}
static
inline
int
hidraw_report_event
(
struct
hid_device
*
hid
,
u8
*
data
,
int
len
)
{
return
0
;
}
static
inline
int
hidraw_connect
(
struct
hid_device
*
hid
)
{
return
-
1
;
}
static
inline
void
hidraw_disconnect
(
struct
hid_device
*
hid
)
{
}
#endif
...
...
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