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
ee5f68e6
Commit
ee5f68e6
authored
Apr 01, 2014
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-3.15/ll-driver-new-callbacks' into for-linus
parents
f74346a0
0a7f364e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
202 additions
and
1 deletion
+202
-1
drivers/hid/uhid.c
drivers/hid/uhid.c
+27
-0
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-core.c
+78
-0
include/linux/hid.h
include/linux/hid.h
+7
-1
net/bluetooth/hidp/core.c
net/bluetooth/hidp/core.c
+90
-0
No files found.
drivers/hid/uhid.c
View file @
ee5f68e6
...
@@ -244,12 +244,39 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
...
@@ -244,12 +244,39 @@ static int uhid_hid_output_raw(struct hid_device *hid, __u8 *buf, size_t count,
return
count
;
return
count
;
}
}
static
int
uhid_hid_output_report
(
struct
hid_device
*
hid
,
__u8
*
buf
,
size_t
count
)
{
struct
uhid_device
*
uhid
=
hid
->
driver_data
;
unsigned
long
flags
;
struct
uhid_event
*
ev
;
if
(
count
<
1
||
count
>
UHID_DATA_MAX
)
return
-
EINVAL
;
ev
=
kzalloc
(
sizeof
(
*
ev
),
GFP_KERNEL
);
if
(
!
ev
)
return
-
ENOMEM
;
ev
->
type
=
UHID_OUTPUT
;
ev
->
u
.
output
.
size
=
count
;
ev
->
u
.
output
.
rtype
=
UHID_OUTPUT_REPORT
;
memcpy
(
ev
->
u
.
output
.
data
,
buf
,
count
);
spin_lock_irqsave
(
&
uhid
->
qlock
,
flags
);
uhid_queue
(
uhid
,
ev
);
spin_unlock_irqrestore
(
&
uhid
->
qlock
,
flags
);
return
count
;
}
static
struct
hid_ll_driver
uhid_hid_driver
=
{
static
struct
hid_ll_driver
uhid_hid_driver
=
{
.
start
=
uhid_hid_start
,
.
start
=
uhid_hid_start
,
.
stop
=
uhid_hid_stop
,
.
stop
=
uhid_hid_stop
,
.
open
=
uhid_hid_open
,
.
open
=
uhid_hid_open
,
.
close
=
uhid_hid_close
,
.
close
=
uhid_hid_close
,
.
parse
=
uhid_hid_parse
,
.
parse
=
uhid_hid_parse
,
.
output_report
=
uhid_hid_output_report
,
};
};
#ifdef CONFIG_COMPAT
#ifdef CONFIG_COMPAT
...
...
drivers/hid/usbhid/hid-core.c
View file @
ee5f68e6
...
@@ -884,6 +884,38 @@ static int usbhid_get_raw_report(struct hid_device *hid,
...
@@ -884,6 +884,38 @@ static int usbhid_get_raw_report(struct hid_device *hid,
return
ret
;
return
ret
;
}
}
static
int
usbhid_set_raw_report
(
struct
hid_device
*
hid
,
unsigned
int
reportnum
,
__u8
*
buf
,
size_t
count
,
unsigned
char
rtype
)
{
struct
usbhid_device
*
usbhid
=
hid
->
driver_data
;
struct
usb_device
*
dev
=
hid_to_usb_dev
(
hid
);
struct
usb_interface
*
intf
=
usbhid
->
intf
;
struct
usb_host_interface
*
interface
=
intf
->
cur_altsetting
;
int
ret
,
skipped_report_id
=
0
;
/* Byte 0 is the report number. Report data starts at byte 1.*/
buf
[
0
]
=
reportnum
;
if
(
buf
[
0
]
==
0x0
)
{
/* Don't send the Report ID */
buf
++
;
count
--
;
skipped_report_id
=
1
;
}
ret
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
HID_REQ_SET_REPORT
,
USB_DIR_OUT
|
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
((
rtype
+
1
)
<<
8
)
|
reportnum
,
interface
->
desc
.
bInterfaceNumber
,
buf
,
count
,
USB_CTRL_SET_TIMEOUT
);
/* count also the report id, if this was a numbered report. */
if
(
ret
>
0
&&
skipped_report_id
)
ret
++
;
return
ret
;
}
static
int
usbhid_output_raw_report
(
struct
hid_device
*
hid
,
__u8
*
buf
,
size_t
count
,
static
int
usbhid_output_raw_report
(
struct
hid_device
*
hid
,
__u8
*
buf
,
size_t
count
,
unsigned
char
report_type
)
unsigned
char
report_type
)
{
{
...
@@ -936,6 +968,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
...
@@ -936,6 +968,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
return
ret
;
return
ret
;
}
}
static
int
usbhid_output_report
(
struct
hid_device
*
hid
,
__u8
*
buf
,
size_t
count
)
{
struct
usbhid_device
*
usbhid
=
hid
->
driver_data
;
struct
usb_device
*
dev
=
hid_to_usb_dev
(
hid
);
int
actual_length
,
skipped_report_id
=
0
,
ret
;
if
(
!
usbhid
->
urbout
)
return
-
EIO
;
if
(
buf
[
0
]
==
0x0
)
{
/* Don't send the Report ID */
buf
++
;
count
--
;
skipped_report_id
=
1
;
}
ret
=
usb_interrupt_msg
(
dev
,
usbhid
->
urbout
->
pipe
,
buf
,
count
,
&
actual_length
,
USB_CTRL_SET_TIMEOUT
);
/* return the number of bytes transferred */
if
(
ret
==
0
)
{
ret
=
actual_length
;
/* count also the report id */
if
(
skipped_report_id
)
ret
++
;
}
return
ret
;
}
static
void
usbhid_restart_queues
(
struct
usbhid_device
*
usbhid
)
static
void
usbhid_restart_queues
(
struct
usbhid_device
*
usbhid
)
{
{
if
(
usbhid
->
urbout
&&
!
test_bit
(
HID_OUT_RUNNING
,
&
usbhid
->
iofl
))
if
(
usbhid
->
urbout
&&
!
test_bit
(
HID_OUT_RUNNING
,
&
usbhid
->
iofl
))
...
@@ -1200,6 +1262,20 @@ static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int r
...
@@ -1200,6 +1262,20 @@ static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int r
}
}
}
}
static
int
usbhid_raw_request
(
struct
hid_device
*
hid
,
unsigned
char
reportnum
,
__u8
*
buf
,
size_t
len
,
unsigned
char
rtype
,
int
reqtype
)
{
switch
(
reqtype
)
{
case
HID_REQ_GET_REPORT
:
return
usbhid_get_raw_report
(
hid
,
reportnum
,
buf
,
len
,
rtype
);
case
HID_REQ_SET_REPORT
:
return
usbhid_set_raw_report
(
hid
,
reportnum
,
buf
,
len
,
rtype
);
default:
return
-
EIO
;
}
}
static
int
usbhid_idle
(
struct
hid_device
*
hid
,
int
report
,
int
idle
,
static
int
usbhid_idle
(
struct
hid_device
*
hid
,
int
report
,
int
idle
,
int
reqtype
)
int
reqtype
)
{
{
...
@@ -1223,6 +1299,8 @@ static struct hid_ll_driver usb_hid_driver = {
...
@@ -1223,6 +1299,8 @@ static struct hid_ll_driver usb_hid_driver = {
.
power
=
usbhid_power
,
.
power
=
usbhid_power
,
.
request
=
usbhid_request
,
.
request
=
usbhid_request
,
.
wait
=
usbhid_wait_io
,
.
wait
=
usbhid_wait_io
,
.
raw_request
=
usbhid_raw_request
,
.
output_report
=
usbhid_output_report
,
.
idle
=
usbhid_idle
,
.
idle
=
usbhid_idle
,
};
};
...
...
include/linux/hid.h
View file @
ee5f68e6
...
@@ -700,8 +700,14 @@ struct hid_ll_driver {
...
@@ -700,8 +700,14 @@ struct hid_ll_driver {
struct
hid_report
*
report
,
int
reqtype
);
struct
hid_report
*
report
,
int
reqtype
);
int
(
*
wait
)(
struct
hid_device
*
hdev
);
int
(
*
wait
)(
struct
hid_device
*
hdev
);
int
(
*
idle
)(
struct
hid_device
*
hdev
,
int
report
,
int
idle
,
int
reqtype
);
int
(
*
raw_request
)
(
struct
hid_device
*
hdev
,
unsigned
char
reportnum
,
__u8
*
buf
,
size_t
len
,
unsigned
char
rtype
,
int
reqtype
);
int
(
*
output_report
)
(
struct
hid_device
*
hdev
,
__u8
*
buf
,
size_t
len
);
int
(
*
idle
)(
struct
hid_device
*
hdev
,
int
report
,
int
idle
,
int
reqtype
);
};
};
#define PM_HINT_FULLON 1<<5
#define PM_HINT_FULLON 1<<5
...
...
net/bluetooth/hidp/core.c
View file @
ee5f68e6
...
@@ -353,6 +353,71 @@ static int hidp_get_raw_report(struct hid_device *hid,
...
@@ -353,6 +353,71 @@ static int hidp_get_raw_report(struct hid_device *hid,
return
ret
;
return
ret
;
}
}
static
int
hidp_set_raw_report
(
struct
hid_device
*
hid
,
unsigned
char
reportnum
,
unsigned
char
*
data
,
size_t
count
,
unsigned
char
report_type
)
{
struct
hidp_session
*
session
=
hid
->
driver_data
;
int
ret
;
switch
(
report_type
)
{
case
HID_FEATURE_REPORT
:
report_type
=
HIDP_TRANS_SET_REPORT
|
HIDP_DATA_RTYPE_FEATURE
;
break
;
case
HID_INPUT_REPORT
:
report_type
=
HIDP_TRANS_SET_REPORT
|
HIDP_DATA_RTYPE_INPUT
;
break
;
case
HID_OUTPUT_REPORT
:
report_type
=
HIDP_TRANS_SET_REPORT
|
HIDP_DATA_RTYPE_OUPUT
;
break
;
default:
return
-
EINVAL
;
}
if
(
mutex_lock_interruptible
(
&
session
->
report_mutex
))
return
-
ERESTARTSYS
;
/* Set up our wait, and send the report request to the device. */
data
[
0
]
=
reportnum
;
set_bit
(
HIDP_WAITING_FOR_SEND_ACK
,
&
session
->
flags
);
ret
=
hidp_send_ctrl_message
(
session
,
report_type
,
data
,
count
);
if
(
ret
)
goto
err
;
/* Wait for the ACK from the device. */
while
(
test_bit
(
HIDP_WAITING_FOR_SEND_ACK
,
&
session
->
flags
)
&&
!
atomic_read
(
&
session
->
terminate
))
{
int
res
;
res
=
wait_event_interruptible_timeout
(
session
->
report_queue
,
!
test_bit
(
HIDP_WAITING_FOR_SEND_ACK
,
&
session
->
flags
)
||
atomic_read
(
&
session
->
terminate
),
10
*
HZ
);
if
(
res
==
0
)
{
/* timeout */
ret
=
-
EIO
;
goto
err
;
}
if
(
res
<
0
)
{
/* signal */
ret
=
-
ERESTARTSYS
;
goto
err
;
}
}
if
(
!
session
->
output_report_success
)
{
ret
=
-
EIO
;
goto
err
;
}
ret
=
count
;
err:
clear_bit
(
HIDP_WAITING_FOR_SEND_ACK
,
&
session
->
flags
);
mutex_unlock
(
&
session
->
report_mutex
);
return
ret
;
}
static
int
hidp_output_raw_report
(
struct
hid_device
*
hid
,
unsigned
char
*
data
,
size_t
count
,
static
int
hidp_output_raw_report
(
struct
hid_device
*
hid
,
unsigned
char
*
data
,
size_t
count
,
unsigned
char
report_type
)
unsigned
char
report_type
)
{
{
...
@@ -411,6 +476,29 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
...
@@ -411,6 +476,29 @@ static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, s
return
ret
;
return
ret
;
}
}
static
int
hidp_raw_request
(
struct
hid_device
*
hid
,
unsigned
char
reportnum
,
__u8
*
buf
,
size_t
len
,
unsigned
char
rtype
,
int
reqtype
)
{
switch
(
reqtype
)
{
case
HID_REQ_GET_REPORT
:
return
hidp_get_raw_report
(
hid
,
reportnum
,
buf
,
len
,
rtype
);
case
HID_REQ_SET_REPORT
:
return
hidp_set_raw_report
(
hid
,
reportnum
,
buf
,
len
,
rtype
);
default:
return
-
EIO
;
}
}
static
int
hidp_output_report
(
struct
hid_device
*
hid
,
__u8
*
data
,
size_t
count
)
{
struct
hidp_session
*
session
=
hid
->
driver_data
;
return
hidp_send_intr_message
(
session
,
HIDP_TRANS_DATA
|
HIDP_DATA_RTYPE_OUPUT
,
data
,
count
);
}
static
void
hidp_idle_timeout
(
unsigned
long
arg
)
static
void
hidp_idle_timeout
(
unsigned
long
arg
)
{
{
struct
hidp_session
*
session
=
(
struct
hidp_session
*
)
arg
;
struct
hidp_session
*
session
=
(
struct
hidp_session
*
)
arg
;
...
@@ -739,6 +827,8 @@ static struct hid_ll_driver hidp_hid_driver = {
...
@@ -739,6 +827,8 @@ static struct hid_ll_driver hidp_hid_driver = {
.
stop
=
hidp_stop
,
.
stop
=
hidp_stop
,
.
open
=
hidp_open
,
.
open
=
hidp_open
,
.
close
=
hidp_close
,
.
close
=
hidp_close
,
.
raw_request
=
hidp_raw_request
,
.
output_report
=
hidp_output_report
,
.
hidinput_input_event
=
hidp_hidinput_event
,
.
hidinput_input_event
=
hidp_hidinput_event
,
};
};
...
...
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