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
Kirill Smelkov
linux
Commits
ef77ad5e
Commit
ef77ad5e
authored
May 19, 2010
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'upstream-fixes', 'bkl-removal', 'debugfs-fixes' and 'hid-suspend' into for-linus
parents
7426ef52
23d02116
da54a0ce
f77e347b
6a740aa4
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
86 additions
and
41 deletions
+86
-41
drivers/hid/hid-core.c
drivers/hid/hid-core.c
+8
-15
drivers/hid/hid-magicmouse.c
drivers/hid/hid-magicmouse.c
+4
-1
drivers/hid/hidraw.c
drivers/hid/hidraw.c
+26
-22
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-core.c
+23
-1
drivers/hid/usbhid/hiddev.c
drivers/hid/usbhid/hiddev.c
+17
-2
include/linux/hid.h
include/linux/hid.h
+8
-0
No files found.
drivers/hid/hid-core.c
View file @
ef77ad5e
...
...
@@ -1081,35 +1081,28 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
buf
=
kmalloc
(
sizeof
(
char
)
*
HID_DEBUG_BUFSIZE
,
GFP_ATOMIC
);
if
(
!
buf
)
{
report
=
hid_get_report
(
report_enum
,
data
);
if
(
!
buf
)
goto
nomem
;
}
snprintf
(
buf
,
HID_DEBUG_BUFSIZE
-
1
,
"
\n
report (size %u) (%snumbered)
\n
"
,
size
,
report_enum
->
numbered
?
""
:
"un"
);
hid_debug_event
(
hid
,
buf
);
report
=
hid_get_report
(
report_enum
,
data
);
if
(
!
report
)
{
kfree
(
buf
);
return
-
1
;
}
/* dump the report */
snprintf
(
buf
,
HID_DEBUG_BUFSIZE
-
1
,
"
report %d (size %u) = "
,
report
->
id
,
size
);
"
\n
report (size %u) (%snumbered) = "
,
size
,
report_enum
->
numbered
?
""
:
"un"
);
hid_debug_event
(
hid
,
buf
);
for
(
i
=
0
;
i
<
size
;
i
++
)
{
snprintf
(
buf
,
HID_DEBUG_BUFSIZE
-
1
,
" %02x"
,
data
[
i
]);
hid_debug_event
(
hid
,
buf
);
}
hid_debug_event
(
hid
,
"
\n
"
);
kfree
(
buf
);
nomem:
report
=
hid_get_report
(
report_enum
,
data
);
if
(
!
report
)
return
-
1
;
if
(
hdrv
&&
hdrv
->
raw_event
&&
hid_match_report
(
hid
,
report
))
{
ret
=
hdrv
->
raw_event
(
hid
,
report
,
data
,
size
);
if
(
ret
!=
0
)
...
...
drivers/hid/hid-magicmouse.c
View file @
ef77ad5e
...
...
@@ -354,12 +354,15 @@ static int magicmouse_probe(struct hid_device *hdev,
goto
err_free
;
}
ret
=
hid_hw_start
(
hdev
,
HID_CONNECT_DEFAULT
&
~
HID_CONNECT_HIDINPUT
);
ret
=
hid_hw_start
(
hdev
,
HID_CONNECT_DEFAULT
);
if
(
ret
)
{
dev_err
(
&
hdev
->
dev
,
"magicmouse hw start failed
\n
"
);
goto
err_free
;
}
/* we are handling the input ourselves */
hidinput_disconnect
(
hdev
);
report
=
hid_register_report
(
hdev
,
HID_INPUT_REPORT
,
TOUCH_REPORT_ID
);
if
(
!
report
)
{
dev_err
(
&
hdev
->
dev
,
"unable to register touch report
\n
"
);
...
...
drivers/hid/hidraw.c
View file @
ef77ad5e
...
...
@@ -106,38 +106,48 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
static
ssize_t
hidraw_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
unsigned
int
minor
=
iminor
(
file
->
f_path
.
dentry
->
d_inode
);
/* FIXME: What stops hidraw_table going NULL */
struct
hid_device
*
dev
=
hidraw_table
[
minor
]
->
hid
;
struct
hid_device
*
dev
;
__u8
*
buf
;
int
ret
=
0
;
if
(
!
dev
->
hid_output_raw_report
)
return
-
ENODEV
;
mutex_lock
(
&
minors_lock
);
dev
=
hidraw_table
[
minor
]
->
hid
;
if
(
!
dev
->
hid_output_raw_report
)
{
ret
=
-
ENODEV
;
goto
out
;
}
if
(
count
>
HID_MAX_BUFFER_SIZE
)
{
printk
(
KERN_WARNING
"hidraw: pid %d passed too large report
\n
"
,
task_pid_nr
(
current
));
return
-
EINVAL
;
ret
=
-
EINVAL
;
goto
out
;
}
if
(
count
<
2
)
{
printk
(
KERN_WARNING
"hidraw: pid %d passed too short report
\n
"
,
task_pid_nr
(
current
));
return
-
EINVAL
;
ret
=
-
EINVAL
;
goto
out
;
}
buf
=
kmalloc
(
count
*
sizeof
(
__u8
),
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
if
(
!
buf
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
if
(
copy_from_user
(
buf
,
buffer
,
count
))
{
ret
=
-
EFAULT
;
goto
out
;
goto
out
_free
;
}
ret
=
dev
->
hid_output_raw_report
(
dev
,
buf
,
count
,
HID_OUTPUT_REPORT
);
out:
out
_free
:
kfree
(
buf
);
out:
mutex_unlock
(
&
minors_lock
);
return
ret
;
}
...
...
@@ -165,11 +175,8 @@ static int hidraw_open(struct inode *inode, struct file *file)
goto
out
;
}
lock_kernel
();
mutex_lock
(
&
minors_lock
);
if
(
!
hidraw_table
[
minor
])
{
printk
(
KERN_EMERG
"hidraw device with minor %d doesn't exist
\n
"
,
minor
);
kfree
(
list
);
err
=
-
ENODEV
;
goto
out_unlock
;
...
...
@@ -197,7 +204,6 @@ static int hidraw_open(struct inode *inode, struct file *file)
out_unlock:
mutex_unlock
(
&
minors_lock
);
unlock_kernel
();
out:
return
err
;
...
...
@@ -209,11 +215,8 @@ static int hidraw_release(struct inode * inode, struct file * file)
struct
hidraw
*
dev
;
struct
hidraw_list
*
list
=
file
->
private_data
;
if
(
!
hidraw_table
[
minor
])
{
printk
(
KERN_EMERG
"hidraw device with minor %d doesn't exist
\n
"
,
minor
);
if
(
!
hidraw_table
[
minor
])
return
-
ENODEV
;
}
list_del
(
&
list
->
node
);
dev
=
hidraw_table
[
minor
];
...
...
@@ -238,11 +241,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
unsigned
int
minor
=
iminor
(
inode
);
long
ret
=
0
;
/* FIXME: What stops hidraw_table going NULL */
struct
hidraw
*
dev
=
hidraw_table
[
minor
];
struct
hidraw
*
dev
;
void
__user
*
user_arg
=
(
void
__user
*
)
arg
;
lock_kernel
();
mutex_lock
(
&
minors_lock
);
dev
=
hidraw_table
[
minor
];
switch
(
cmd
)
{
case
HIDIOCGRDESCSIZE
:
if
(
put_user
(
dev
->
hid
->
rsize
,
(
int
__user
*
)
arg
))
...
...
@@ -315,7 +319,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
ret
=
-
ENOTTY
;
}
unlock_kernel
(
);
mutex_unlock
(
&
minors_lock
);
return
ret
;
}
...
...
drivers/hid/usbhid/hid-core.c
View file @
ef77ad5e
...
...
@@ -1313,6 +1313,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
{
set_bit
(
HID_REPORTED_IDLE
,
&
usbhid
->
iofl
);
spin_unlock_irq
(
&
usbhid
->
lock
);
if
(
hid
->
driver
&&
hid
->
driver
->
suspend
)
{
status
=
hid
->
driver
->
suspend
(
hid
,
message
);
if
(
status
<
0
)
return
status
;
}
}
else
{
usbhid_mark_busy
(
usbhid
);
spin_unlock_irq
(
&
usbhid
->
lock
);
...
...
@@ -1320,6 +1325,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
}
}
else
{
if
(
hid
->
driver
&&
hid
->
driver
->
suspend
)
{
status
=
hid
->
driver
->
suspend
(
hid
,
message
);
if
(
status
<
0
)
return
status
;
}
spin_lock_irq
(
&
usbhid
->
lock
);
set_bit
(
HID_REPORTED_IDLE
,
&
usbhid
->
iofl
);
spin_unlock_irq
(
&
usbhid
->
lock
);
...
...
@@ -1374,6 +1384,11 @@ static int hid_resume(struct usb_interface *intf)
hid_io_error
(
hid
);
usbhid_restart_queues
(
usbhid
);
if
(
status
>=
0
&&
hid
->
driver
&&
hid
->
driver
->
resume
)
{
int
ret
=
hid
->
driver
->
resume
(
hid
);
if
(
ret
<
0
)
status
=
ret
;
}
dev_dbg
(
&
intf
->
dev
,
"resume status %d
\n
"
,
status
);
return
0
;
}
...
...
@@ -1382,9 +1397,16 @@ static int hid_reset_resume(struct usb_interface *intf)
{
struct
hid_device
*
hid
=
usb_get_intfdata
(
intf
);
struct
usbhid_device
*
usbhid
=
hid
->
driver_data
;
int
status
;
clear_bit
(
HID_REPORTED_IDLE
,
&
usbhid
->
iofl
);
return
hid_post_reset
(
intf
);
status
=
hid_post_reset
(
intf
);
if
(
status
>=
0
&&
hid
->
driver
&&
hid
->
driver
->
reset_resume
)
{
int
ret
=
hid
->
driver
->
reset_resume
(
hid
);
if
(
ret
<
0
)
status
=
ret
;
}
return
status
;
}
#endif
/* CONFIG_PM */
...
...
drivers/hid/usbhid/hiddev.c
View file @
ef77ad5e
...
...
@@ -267,6 +267,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
struct
hiddev_list
*
list
;
int
res
,
i
;
/* See comment in hiddev_connect() for BKL explanation */
lock_kernel
();
i
=
iminor
(
inode
)
-
HIDDEV_MINOR_BASE
;
...
...
@@ -894,8 +895,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
hiddev
->
hid
=
hid
;
hiddev
->
exist
=
1
;
/* when lock_kernel() usage is fixed in usb_open(),
* we could also fix it here */
/*
* BKL here is used to avoid race after usb_register_dev().
* Once the device node has been created, open() could happen on it.
* The code below will then fail, as hiddev_table hasn't been
* updated.
*
* The obvious fix -- introducing mutex to guard hiddev_table[]
* doesn't work, as usb_open() and usb_register_dev() both take
* minor_rwsem, thus we'll have ABBA deadlock.
*
* Before BKL pushdown, usb_open() had been acquiring it in right
* order, so _open() was safe to use it to protect from this race.
* Now the order is different, but AB-BA deadlock still doesn't occur
* as BKL is dropped on schedule() (i.e. while sleeping on
* minor_rwsem). Fugly.
*/
lock_kernel
();
retval
=
usb_register_dev
(
usbhid
->
intf
,
&
hiddev_class
);
if
(
retval
)
{
...
...
include/linux/hid.h
View file @
ef77ad5e
...
...
@@ -591,6 +591,9 @@ struct hid_usage_id {
* @report_fixup: called before report descriptor parsing (NULL means nop)
* @input_mapping: invoked on input registering before mapping an usage
* @input_mapped: invoked on input registering after mapping an usage
* @suspend: invoked on suspend (NULL means nop)
* @resume: invoked on resume if device was not reset (NULL means nop)
* @reset_resume: invoked on resume if device was reset (NULL means nop)
*
* raw_event and event should return 0 on no action performed, 1 when no
* further processing should be done and negative on error
...
...
@@ -631,6 +634,11 @@ struct hid_driver {
int
(
*
input_mapped
)(
struct
hid_device
*
hdev
,
struct
hid_input
*
hidinput
,
struct
hid_field
*
field
,
struct
hid_usage
*
usage
,
unsigned
long
**
bit
,
int
*
max
);
#ifdef CONFIG_PM
int
(
*
suspend
)(
struct
hid_device
*
hdev
,
pm_message_t
message
);
int
(
*
resume
)(
struct
hid_device
*
hdev
);
int
(
*
reset_resume
)(
struct
hid_device
*
hdev
);
#endif
/* private: */
struct
device_driver
driver
;
};
...
...
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