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
dda5202b
Commit
dda5202b
authored
Jul 12, 2017
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
Prepare second round of input updates for 4.13 merge window.
parents
ede2e7cd
340d394a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
204 additions
and
44 deletions
+204
-44
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys.c
+16
-1
drivers/input/misc/xen-kbdfront.c
drivers/input/misc/xen-kbdfront.c
+179
-40
drivers/input/serio/i8042.c
drivers/input/serio/i8042.c
+9
-3
No files found.
drivers/input/keyboard/gpio_keys.c
View file @
dda5202b
...
...
@@ -48,6 +48,7 @@ struct gpio_button_data {
spinlock_t
lock
;
bool
disabled
;
bool
key_pressed
;
bool
suspended
;
};
struct
gpio_keys_drvdata
{
...
...
@@ -396,8 +397,20 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
BUG_ON
(
irq
!=
bdata
->
irq
);
if
(
bdata
->
button
->
wakeup
)
if
(
bdata
->
button
->
wakeup
)
{
const
struct
gpio_keys_button
*
button
=
bdata
->
button
;
pm_stay_awake
(
bdata
->
input
->
dev
.
parent
);
if
(
bdata
->
suspended
&&
(
button
->
type
==
0
||
button
->
type
==
EV_KEY
))
{
/*
* Simulate wakeup key press in case the key has
* already released by the time we got interrupt
* handler to run.
*/
input_report_key
(
bdata
->
input
,
button
->
code
,
1
);
}
}
mod_delayed_work
(
system_wq
,
&
bdata
->
work
,
...
...
@@ -855,6 +868,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
if
(
bdata
->
button
->
wakeup
)
enable_irq_wake
(
bdata
->
irq
);
bdata
->
suspended
=
true
;
}
}
else
{
mutex_lock
(
&
input
->
mutex
);
...
...
@@ -878,6 +892,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
if
(
bdata
->
button
->
wakeup
)
disable_irq_wake
(
bdata
->
irq
);
bdata
->
suspended
=
false
;
}
}
else
{
mutex_lock
(
&
input
->
mutex
);
...
...
drivers/input/misc/xen-kbdfront.c
View file @
dda5202b
...
...
@@ -17,6 +17,7 @@
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/slab.h>
#include <asm/xen/hypervisor.h>
...
...
@@ -34,11 +35,14 @@
struct
xenkbd_info
{
struct
input_dev
*
kbd
;
struct
input_dev
*
ptr
;
struct
input_dev
*
mtouch
;
struct
xenkbd_page
*
page
;
int
gref
;
int
irq
;
struct
xenbus_device
*
xbdev
;
char
phys
[
32
];
/* current MT slot/contact ID we are injecting events in */
int
mtouch_cur_contact_id
;
};
enum
{
KPARAM_X
,
KPARAM_Y
,
KPARAM_CNT
};
...
...
@@ -56,6 +60,112 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
* to do that.
*/
static
void
xenkbd_handle_motion_event
(
struct
xenkbd_info
*
info
,
struct
xenkbd_motion
*
motion
)
{
input_report_rel
(
info
->
ptr
,
REL_X
,
motion
->
rel_x
);
input_report_rel
(
info
->
ptr
,
REL_Y
,
motion
->
rel_y
);
if
(
motion
->
rel_z
)
input_report_rel
(
info
->
ptr
,
REL_WHEEL
,
-
motion
->
rel_z
);
input_sync
(
info
->
ptr
);
}
static
void
xenkbd_handle_position_event
(
struct
xenkbd_info
*
info
,
struct
xenkbd_position
*
pos
)
{
input_report_abs
(
info
->
ptr
,
ABS_X
,
pos
->
abs_x
);
input_report_abs
(
info
->
ptr
,
ABS_Y
,
pos
->
abs_y
);
if
(
pos
->
rel_z
)
input_report_rel
(
info
->
ptr
,
REL_WHEEL
,
-
pos
->
rel_z
);
input_sync
(
info
->
ptr
);
}
static
void
xenkbd_handle_key_event
(
struct
xenkbd_info
*
info
,
struct
xenkbd_key
*
key
)
{
struct
input_dev
*
dev
;
if
(
test_bit
(
key
->
keycode
,
info
->
ptr
->
keybit
))
{
dev
=
info
->
ptr
;
}
else
if
(
test_bit
(
key
->
keycode
,
info
->
kbd
->
keybit
))
{
dev
=
info
->
kbd
;
}
else
{
pr_warn
(
"unhandled keycode 0x%x
\n
"
,
key
->
keycode
);
return
;
}
input_report_key
(
dev
,
key
->
keycode
,
key
->
pressed
);
input_sync
(
dev
);
}
static
void
xenkbd_handle_mt_event
(
struct
xenkbd_info
*
info
,
struct
xenkbd_mtouch
*
mtouch
)
{
if
(
unlikely
(
!
info
->
mtouch
))
return
;
if
(
mtouch
->
contact_id
!=
info
->
mtouch_cur_contact_id
)
{
info
->
mtouch_cur_contact_id
=
mtouch
->
contact_id
;
input_mt_slot
(
info
->
mtouch
,
mtouch
->
contact_id
);
}
switch
(
mtouch
->
event_type
)
{
case
XENKBD_MT_EV_DOWN
:
input_mt_report_slot_state
(
info
->
mtouch
,
MT_TOOL_FINGER
,
true
);
/* fall through */
case
XENKBD_MT_EV_MOTION
:
input_report_abs
(
info
->
mtouch
,
ABS_MT_POSITION_X
,
mtouch
->
u
.
pos
.
abs_x
);
input_report_abs
(
info
->
mtouch
,
ABS_MT_POSITION_Y
,
mtouch
->
u
.
pos
.
abs_y
);
break
;
case
XENKBD_MT_EV_SHAPE
:
input_report_abs
(
info
->
mtouch
,
ABS_MT_TOUCH_MAJOR
,
mtouch
->
u
.
shape
.
major
);
input_report_abs
(
info
->
mtouch
,
ABS_MT_TOUCH_MINOR
,
mtouch
->
u
.
shape
.
minor
);
break
;
case
XENKBD_MT_EV_ORIENT
:
input_report_abs
(
info
->
mtouch
,
ABS_MT_ORIENTATION
,
mtouch
->
u
.
orientation
);
break
;
case
XENKBD_MT_EV_UP
:
input_mt_report_slot_state
(
info
->
mtouch
,
MT_TOOL_FINGER
,
false
);
break
;
case
XENKBD_MT_EV_SYN
:
input_mt_sync_frame
(
info
->
mtouch
);
input_sync
(
info
->
mtouch
);
break
;
}
}
static
void
xenkbd_handle_event
(
struct
xenkbd_info
*
info
,
union
xenkbd_in_event
*
event
)
{
switch
(
event
->
type
)
{
case
XENKBD_TYPE_MOTION
:
xenkbd_handle_motion_event
(
info
,
&
event
->
motion
);
break
;
case
XENKBD_TYPE_KEY
:
xenkbd_handle_key_event
(
info
,
&
event
->
key
);
break
;
case
XENKBD_TYPE_POS
:
xenkbd_handle_position_event
(
info
,
&
event
->
pos
);
break
;
case
XENKBD_TYPE_MTOUCH
:
xenkbd_handle_mt_event
(
info
,
&
event
->
mtouch
);
break
;
}
}
static
irqreturn_t
input_handler
(
int
rq
,
void
*
dev_id
)
{
struct
xenkbd_info
*
info
=
dev_id
;
...
...
@@ -66,44 +176,8 @@ static irqreturn_t input_handler(int rq, void *dev_id)
if
(
prod
==
page
->
in_cons
)
return
IRQ_HANDLED
;
rmb
();
/* ensure we see ring contents up to prod */
for
(
cons
=
page
->
in_cons
;
cons
!=
prod
;
cons
++
)
{
union
xenkbd_in_event
*
event
;
struct
input_dev
*
dev
;
event
=
&
XENKBD_IN_RING_REF
(
page
,
cons
);
dev
=
info
->
ptr
;
switch
(
event
->
type
)
{
case
XENKBD_TYPE_MOTION
:
input_report_rel
(
dev
,
REL_X
,
event
->
motion
.
rel_x
);
input_report_rel
(
dev
,
REL_Y
,
event
->
motion
.
rel_y
);
if
(
event
->
motion
.
rel_z
)
input_report_rel
(
dev
,
REL_WHEEL
,
-
event
->
motion
.
rel_z
);
break
;
case
XENKBD_TYPE_KEY
:
dev
=
NULL
;
if
(
test_bit
(
event
->
key
.
keycode
,
info
->
kbd
->
keybit
))
dev
=
info
->
kbd
;
if
(
test_bit
(
event
->
key
.
keycode
,
info
->
ptr
->
keybit
))
dev
=
info
->
ptr
;
if
(
dev
)
input_report_key
(
dev
,
event
->
key
.
keycode
,
event
->
key
.
pressed
);
else
pr_warn
(
"unhandled keycode 0x%x
\n
"
,
event
->
key
.
keycode
);
break
;
case
XENKBD_TYPE_POS
:
input_report_abs
(
dev
,
ABS_X
,
event
->
pos
.
abs_x
);
input_report_abs
(
dev
,
ABS_Y
,
event
->
pos
.
abs_y
);
if
(
event
->
pos
.
rel_z
)
input_report_rel
(
dev
,
REL_WHEEL
,
-
event
->
pos
.
rel_z
);
break
;
}
if
(
dev
)
input_sync
(
dev
);
}
for
(
cons
=
page
->
in_cons
;
cons
!=
prod
;
cons
++
)
xenkbd_handle_event
(
info
,
&
XENKBD_IN_RING_REF
(
page
,
cons
));
mb
();
/* ensure we got ring contents */
page
->
in_cons
=
cons
;
notify_remote_via_irq
(
info
->
irq
);
...
...
@@ -115,9 +189,9 @@ static int xenkbd_probe(struct xenbus_device *dev,
const
struct
xenbus_device_id
*
id
)
{
int
ret
,
i
;
unsigned
int
abs
;
unsigned
int
abs
,
touch
;
struct
xenkbd_info
*
info
;
struct
input_dev
*
kbd
,
*
ptr
;
struct
input_dev
*
kbd
,
*
ptr
,
*
mtouch
;
info
=
kzalloc
(
sizeof
(
*
info
),
GFP_KERNEL
);
if
(
!
info
)
{
...
...
@@ -152,6 +226,17 @@ static int xenkbd_probe(struct xenbus_device *dev,
}
}
touch
=
xenbus_read_unsigned
(
dev
->
nodename
,
XENKBD_FIELD_FEAT_MTOUCH
,
0
);
if
(
touch
)
{
ret
=
xenbus_write
(
XBT_NIL
,
dev
->
nodename
,
XENKBD_FIELD_REQ_MTOUCH
,
"1"
);
if
(
ret
)
{
pr_warn
(
"xenkbd: can't request multi-touch"
);
touch
=
0
;
}
}
/* keyboard */
kbd
=
input_allocate_device
();
if
(
!
kbd
)
...
...
@@ -208,6 +293,58 @@ static int xenkbd_probe(struct xenbus_device *dev,
}
info
->
ptr
=
ptr
;
/* multi-touch device */
if
(
touch
)
{
int
num_cont
,
width
,
height
;
mtouch
=
input_allocate_device
();
if
(
!
mtouch
)
goto
error_nomem
;
num_cont
=
xenbus_read_unsigned
(
info
->
xbdev
->
nodename
,
XENKBD_FIELD_MT_NUM_CONTACTS
,
1
);
width
=
xenbus_read_unsigned
(
info
->
xbdev
->
nodename
,
XENKBD_FIELD_MT_WIDTH
,
XENFB_WIDTH
);
height
=
xenbus_read_unsigned
(
info
->
xbdev
->
nodename
,
XENKBD_FIELD_MT_HEIGHT
,
XENFB_HEIGHT
);
mtouch
->
name
=
"Xen Virtual Multi-touch"
;
mtouch
->
phys
=
info
->
phys
;
mtouch
->
id
.
bustype
=
BUS_PCI
;
mtouch
->
id
.
vendor
=
0x5853
;
mtouch
->
id
.
product
=
0xfffd
;
input_set_abs_params
(
mtouch
,
ABS_MT_TOUCH_MAJOR
,
0
,
255
,
0
,
0
);
input_set_abs_params
(
mtouch
,
ABS_MT_POSITION_X
,
0
,
width
,
0
,
0
);
input_set_abs_params
(
mtouch
,
ABS_MT_POSITION_Y
,
0
,
height
,
0
,
0
);
input_set_abs_params
(
mtouch
,
ABS_MT_PRESSURE
,
0
,
255
,
0
,
0
);
ret
=
input_mt_init_slots
(
mtouch
,
num_cont
,
INPUT_MT_DIRECT
);
if
(
ret
)
{
input_free_device
(
mtouch
);
xenbus_dev_fatal
(
info
->
xbdev
,
ret
,
"input_mt_init_slots"
);
goto
error
;
}
ret
=
input_register_device
(
mtouch
);
if
(
ret
)
{
input_free_device
(
mtouch
);
xenbus_dev_fatal
(
info
->
xbdev
,
ret
,
"input_register_device(mtouch)"
);
goto
error
;
}
info
->
mtouch_cur_contact_id
=
-
1
;
info
->
mtouch
=
mtouch
;
}
ret
=
xenkbd_connect_backend
(
dev
,
info
);
if
(
ret
<
0
)
goto
error
;
...
...
@@ -240,6 +377,8 @@ static int xenkbd_remove(struct xenbus_device *dev)
input_unregister_device
(
info
->
kbd
);
if
(
info
->
ptr
)
input_unregister_device
(
info
->
ptr
);
if
(
info
->
mtouch
)
input_unregister_device
(
info
->
mtouch
);
free_page
((
unsigned
long
)
info
->
page
);
kfree
(
info
);
return
0
;
...
...
drivers/input/serio/i8042.c
View file @
dda5202b
...
...
@@ -436,8 +436,10 @@ static int i8042_start(struct serio *serio)
{
struct
i8042_port
*
port
=
serio
->
port_data
;
spin_lock_irq
(
&
i8042_lock
);
port
->
exists
=
true
;
mb
();
spin_unlock_irq
(
&
i8042_lock
);
return
0
;
}
...
...
@@ -450,16 +452,20 @@ static void i8042_stop(struct serio *serio)
{
struct
i8042_port
*
port
=
serio
->
port_data
;
spin_lock_irq
(
&
i8042_lock
);
port
->
exists
=
false
;
port
->
serio
=
NULL
;
spin_unlock_irq
(
&
i8042_lock
);
/*
* We need to make sure that interrupt handler finishes using
* our serio port before we return from this function.
* We synchronize with both AUX and KBD IRQs because there is
* a (very unlikely) chance that AUX IRQ is raised for KBD port
* and vice versa.
*/
synchronize_irq
(
I8042_AUX_IRQ
);
synchronize_irq
(
I8042_KBD_IRQ
);
port
->
serio
=
NULL
;
}
/*
...
...
@@ -576,7 +582,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
spin_unlock_irqrestore
(
&
i8042_lock
,
flags
);
if
(
likely
(
port
->
exists
&&
!
filtered
))
if
(
likely
(
serio
&&
!
filtered
))
serio_interrupt
(
serio
,
data
,
dfl
);
out:
...
...
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