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
99380825
Commit
99380825
authored
Mar 27, 2012
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
Conflicts: drivers/input/tablet/wacom_sys.c
parents
10ce3cc9
131c713f
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
694 additions
and
202 deletions
+694
-202
arch/arm/plat-spear/include/plat/keyboard.h
arch/arm/plat-spear/include/plat/keyboard.h
+0
-7
drivers/input/joystick/amijoy.c
drivers/input/joystick/amijoy.c
+3
-0
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys.c
+169
-90
drivers/input/keyboard/tegra-kbc.c
drivers/input/keyboard/tegra-kbc.c
+1
-0
drivers/input/mouse/sentelic.c
drivers/input/mouse/sentelic.c
+224
-70
drivers/input/mouse/sentelic.h
drivers/input/mouse/sentelic.h
+33
-2
drivers/input/tablet/Kconfig
drivers/input/tablet/Kconfig
+1
-0
drivers/input/tablet/wacom.h
drivers/input/tablet/wacom.h
+9
-0
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_sys.c
+198
-31
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.c
+48
-1
drivers/input/tablet/wacom_wac.h
drivers/input/tablet/wacom_wac.h
+6
-0
include/linux/gpio_keys.h
include/linux/gpio_keys.h
+2
-1
No files found.
arch/arm/plat-spear/include/plat/keyboard.h
View file @
99380825
...
...
@@ -159,11 +159,4 @@ struct kbd_platform_data {
unsigned
int
mode
;
};
/* This function is used to set platform data field of pdev->dev */
static
inline
void
kbd_set_plat_data
(
struct
platform_device
*
pdev
,
struct
kbd_platform_data
*
data
)
{
pdev
->
dev
.
platform_data
=
data
;
}
#endif
/* __PLAT_KEYBOARD_H */
drivers/input/joystick/amijoy.c
View file @
99380825
...
...
@@ -108,6 +108,9 @@ static int __init amijoy_init(void)
int
i
,
j
;
int
err
;
if
(
!
MACH_IS_AMIGA
)
return
-
ENODEV
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
!
amijoy
[
i
])
continue
;
...
...
drivers/input/keyboard/gpio_keys.c
View file @
99380825
...
...
@@ -28,14 +28,18 @@
#include <linux/gpio.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/spinlock.h>
struct
gpio_button_data
{
struct
gpio_keys_button
*
button
;
const
struct
gpio_keys_button
*
button
;
struct
input_dev
*
input
;
struct
timer_list
timer
;
struct
work_struct
work
;
int
timer_debounce
;
/* in msecs */
unsigned
int
timer_debounce
;
/* in msecs */
unsigned
int
irq
;
spinlock_t
lock
;
bool
disabled
;
bool
key_pressed
;
};
struct
gpio_keys_drvdata
{
...
...
@@ -114,7 +118,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
/*
* Disable IRQ and possible debouncing timer.
*/
disable_irq
(
gpio_to_irq
(
bdata
->
button
->
gpio
)
);
disable_irq
(
bdata
->
irq
);
if
(
bdata
->
timer_debounce
)
del_timer_sync
(
&
bdata
->
timer
);
...
...
@@ -135,7 +139,7 @@ static void gpio_keys_disable_button(struct gpio_button_data *bdata)
static
void
gpio_keys_enable_button
(
struct
gpio_button_data
*
bdata
)
{
if
(
bdata
->
disabled
)
{
enable_irq
(
gpio_to_irq
(
bdata
->
button
->
gpio
)
);
enable_irq
(
bdata
->
irq
);
bdata
->
disabled
=
false
;
}
}
...
...
@@ -195,7 +199,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
* @type: button type (%EV_KEY, %EV_SW)
*
* This function parses stringified bitmap from @buf and disables/enables
* GPIO buttons accordinly. Returns 0 on success and negative error
* GPIO buttons accordin
g
ly. Returns 0 on success and negative error
* on failure.
*/
static
ssize_t
gpio_keys_attr_store_helper
(
struct
gpio_keys_drvdata
*
ddata
,
...
...
@@ -320,9 +324,9 @@ static struct attribute_group gpio_keys_attr_group = {
.
attrs
=
gpio_keys_attrs
,
};
static
void
gpio_keys_report_event
(
struct
gpio_button_data
*
bdata
)
static
void
gpio_keys_
gpio_
report_event
(
struct
gpio_button_data
*
bdata
)
{
struct
gpio_keys_button
*
button
=
bdata
->
button
;
const
struct
gpio_keys_button
*
button
=
bdata
->
button
;
struct
input_dev
*
input
=
bdata
->
input
;
unsigned
int
type
=
button
->
type
?:
EV_KEY
;
int
state
=
(
gpio_get_value_cansleep
(
button
->
gpio
)
?
1
:
0
)
^
button
->
active_low
;
...
...
@@ -336,27 +340,26 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata)
input_sync
(
input
);
}
static
void
gpio_keys_work_func
(
struct
work_struct
*
work
)
static
void
gpio_keys_
gpio_
work_func
(
struct
work_struct
*
work
)
{
struct
gpio_button_data
*
bdata
=
container_of
(
work
,
struct
gpio_button_data
,
work
);
gpio_keys_report_event
(
bdata
);
gpio_keys_
gpio_
report_event
(
bdata
);
}
static
void
gpio_keys_timer
(
unsigned
long
_data
)
static
void
gpio_keys_
gpio_
timer
(
unsigned
long
_data
)
{
struct
gpio_button_data
*
data
=
(
struct
gpio_button_data
*
)
_data
;
struct
gpio_button_data
*
b
data
=
(
struct
gpio_button_data
*
)
_data
;
schedule_work
(
&
data
->
work
);
schedule_work
(
&
b
data
->
work
);
}
static
irqreturn_t
gpio_keys_isr
(
int
irq
,
void
*
dev_id
)
static
irqreturn_t
gpio_keys_
gpio_
isr
(
int
irq
,
void
*
dev_id
)
{
struct
gpio_button_data
*
bdata
=
dev_id
;
struct
gpio_keys_button
*
button
=
bdata
->
button
;
BUG_ON
(
irq
!=
gpio_to_irq
(
button
->
gpio
)
);
BUG_ON
(
irq
!=
bdata
->
irq
);
if
(
bdata
->
timer_debounce
)
mod_timer
(
&
bdata
->
timer
,
...
...
@@ -367,50 +370,133 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
return
IRQ_HANDLED
;
}
static
void
gpio_keys_irq_timer
(
unsigned
long
_data
)
{
struct
gpio_button_data
*
bdata
=
(
struct
gpio_button_data
*
)
_data
;
struct
input_dev
*
input
=
bdata
->
input
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
bdata
->
lock
,
flags
);
if
(
bdata
->
key_pressed
)
{
input_event
(
input
,
EV_KEY
,
bdata
->
button
->
code
,
0
);
input_sync
(
input
);
bdata
->
key_pressed
=
false
;
}
spin_unlock_irqrestore
(
&
bdata
->
lock
,
flags
);
}
static
irqreturn_t
gpio_keys_irq_isr
(
int
irq
,
void
*
dev_id
)
{
struct
gpio_button_data
*
bdata
=
dev_id
;
const
struct
gpio_keys_button
*
button
=
bdata
->
button
;
struct
input_dev
*
input
=
bdata
->
input
;
unsigned
long
flags
;
BUG_ON
(
irq
!=
bdata
->
irq
);
spin_lock_irqsave
(
&
bdata
->
lock
,
flags
);
if
(
!
bdata
->
key_pressed
)
{
input_event
(
input
,
EV_KEY
,
button
->
code
,
1
);
input_sync
(
input
);
if
(
!
bdata
->
timer_debounce
)
{
input_event
(
input
,
EV_KEY
,
button
->
code
,
0
);
input_sync
(
input
);
goto
out
;
}
bdata
->
key_pressed
=
true
;
}
if
(
bdata
->
timer_debounce
)
mod_timer
(
&
bdata
->
timer
,
jiffies
+
msecs_to_jiffies
(
bdata
->
timer_debounce
));
out:
spin_unlock_irqrestore
(
&
bdata
->
lock
,
flags
);
return
IRQ_HANDLED
;
}
static
int
__devinit
gpio_keys_setup_key
(
struct
platform_device
*
pdev
,
struct
input_dev
*
input
,
struct
gpio_button_data
*
bdata
,
struct
gpio_keys_button
*
button
)
const
struct
gpio_keys_button
*
button
)
{
const
char
*
desc
=
button
->
desc
?
button
->
desc
:
"gpio_keys"
;
struct
device
*
dev
=
&
pdev
->
dev
;
irq_handler_t
isr
;
unsigned
long
irqflags
;
int
irq
,
error
;
setup_timer
(
&
bdata
->
timer
,
gpio_keys_timer
,
(
unsigned
long
)
bdata
);
INIT_WORK
(
&
bdata
->
work
,
gpio_keys_work_func
);
bdata
->
input
=
input
;
bdata
->
button
=
button
;
spin_lock_init
(
&
bdata
->
lock
);
error
=
gpio_request
(
button
->
gpio
,
desc
);
if
(
error
<
0
)
{
dev_err
(
dev
,
"failed to request GPIO %d, error %d
\n
"
,
button
->
gpio
,
error
);
goto
fail2
;
}
if
(
gpio_is_valid
(
button
->
gpio
))
{
error
=
gpio_direction_input
(
button
->
gpio
);
if
(
error
<
0
)
{
dev_err
(
dev
,
"failed to configure"
" direction for GPIO %d, error %d
\n
"
,
button
->
gpio
,
error
);
goto
fail3
;
}
error
=
gpio_request
(
button
->
gpio
,
desc
);
if
(
error
<
0
)
{
dev_err
(
dev
,
"Failed to request GPIO %d, error %d
\n
"
,
button
->
gpio
,
error
);
return
error
;
}
if
(
button
->
debounce_interval
)
{
error
=
gpio_set_debounce
(
button
->
gpio
,
button
->
debounce_interval
*
1000
);
/* use timer if gpiolib doesn't provide debounce */
if
(
error
<
0
)
bdata
->
timer_debounce
=
button
->
debounce_interva
l
;
}
error
=
gpio_direction_input
(
button
->
gpio
);
if
(
error
<
0
)
{
dev_err
(
dev
,
"Failed to configure direction for GPIO %d, error %d
\n
"
,
button
->
gpio
,
error
);
goto
fai
l
;
}
irq
=
gpio_to_irq
(
button
->
gpio
);
if
(
irq
<
0
)
{
error
=
irq
;
dev_err
(
dev
,
"Unable to get irq number for GPIO %d, error %d
\n
"
,
button
->
gpio
,
error
);
goto
fail3
;
if
(
button
->
debounce_interval
)
{
error
=
gpio_set_debounce
(
button
->
gpio
,
button
->
debounce_interval
*
1000
);
/* use timer if gpiolib doesn't provide debounce */
if
(
error
<
0
)
bdata
->
timer_debounce
=
button
->
debounce_interval
;
}
irq
=
gpio_to_irq
(
button
->
gpio
);
if
(
irq
<
0
)
{
error
=
irq
;
dev_err
(
dev
,
"Unable to get irq number for GPIO %d, error %d
\n
"
,
button
->
gpio
,
error
);
goto
fail
;
}
bdata
->
irq
=
irq
;
INIT_WORK
(
&
bdata
->
work
,
gpio_keys_gpio_work_func
);
setup_timer
(
&
bdata
->
timer
,
gpio_keys_gpio_timer
,
(
unsigned
long
)
bdata
);
isr
=
gpio_keys_gpio_isr
;
irqflags
=
IRQF_TRIGGER_RISING
|
IRQF_TRIGGER_FALLING
;
}
else
{
if
(
!
button
->
irq
)
{
dev_err
(
dev
,
"No IRQ specified
\n
"
);
return
-
EINVAL
;
}
bdata
->
irq
=
button
->
irq
;
if
(
button
->
type
&&
button
->
type
!=
EV_KEY
)
{
dev_err
(
dev
,
"Only EV_KEY allowed for IRQ buttons.
\n
"
);
return
-
EINVAL
;
}
bdata
->
timer_debounce
=
button
->
debounce_interval
;
setup_timer
(
&
bdata
->
timer
,
gpio_keys_irq_timer
,
(
unsigned
long
)
bdata
);
isr
=
gpio_keys_irq_isr
;
irqflags
=
0
;
}
irqflags
=
IRQF_TRIGGER_RISING
|
IRQF_TRIGGER_FALLING
;
input_set_capability
(
input
,
button
->
type
?:
EV_KEY
,
button
->
code
);
/*
* If platform has specified that the button can be disabled,
* we don't want it to share the interrupt line.
...
...
@@ -418,18 +504,19 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
if
(
!
button
->
can_disable
)
irqflags
|=
IRQF_SHARED
;
error
=
request_
threaded_irq
(
irq
,
NULL
,
gpio_keys_
isr
,
irqflags
,
desc
,
bdata
);
error
=
request_
any_context_irq
(
bdata
->
irq
,
isr
,
irqflags
,
desc
,
bdata
);
if
(
error
<
0
)
{
dev_err
(
dev
,
"Unable to claim irq %d; error %d
\n
"
,
irq
,
error
);
goto
fail
3
;
bdata
->
irq
,
error
);
goto
fail
;
}
return
0
;
fail3:
gpio_free
(
button
->
gpio
);
fail2:
fail:
if
(
gpio_is_valid
(
button
->
gpio
))
gpio_free
(
button
->
gpio
);
return
error
;
}
...
...
@@ -547,9 +634,19 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
#endif
static
void
gpio_remove_key
(
struct
gpio_button_data
*
bdata
)
{
free_irq
(
bdata
->
irq
,
bdata
);
if
(
bdata
->
timer_debounce
)
del_timer_sync
(
&
bdata
->
timer
);
cancel_work_sync
(
&
bdata
->
work
);
if
(
gpio_is_valid
(
bdata
->
button
->
gpio
))
gpio_free
(
bdata
->
button
->
gpio
);
}
static
int
__devinit
gpio_keys_probe
(
struct
platform_device
*
pdev
)
{
struct
gpio_keys_platform_data
*
pdata
=
pdev
->
dev
.
platform_data
;
const
struct
gpio_keys_platform_data
*
pdata
=
pdev
->
dev
.
platform_data
;
struct
gpio_keys_drvdata
*
ddata
;
struct
device
*
dev
=
&
pdev
->
dev
;
struct
gpio_keys_platform_data
alt_pdata
;
...
...
@@ -599,21 +696,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
__set_bit
(
EV_REP
,
input
->
evbit
);
for
(
i
=
0
;
i
<
pdata
->
nbuttons
;
i
++
)
{
struct
gpio_keys_button
*
button
=
&
pdata
->
buttons
[
i
];
const
struct
gpio_keys_button
*
button
=
&
pdata
->
buttons
[
i
];
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
unsigned
int
type
=
button
->
type
?:
EV_KEY
;
bdata
->
input
=
input
;
bdata
->
button
=
button
;
error
=
gpio_keys_setup_key
(
pdev
,
bdata
,
button
);
error
=
gpio_keys_setup_key
(
pdev
,
input
,
bdata
,
button
);
if
(
error
)
goto
fail2
;
if
(
button
->
wakeup
)
wakeup
=
1
;
input_set_capability
(
input
,
type
,
button
->
code
);
}
error
=
sysfs_create_group
(
&
pdev
->
dev
.
kobj
,
&
gpio_keys_attr_group
);
...
...
@@ -630,9 +721,12 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
goto
fail3
;
}
/* get current state of buttons */
for
(
i
=
0
;
i
<
pdata
->
nbuttons
;
i
++
)
gpio_keys_report_event
(
&
ddata
->
data
[
i
]);
/* get current state of buttons that are connected to GPIOs */
for
(
i
=
0
;
i
<
pdata
->
nbuttons
;
i
++
)
{
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
if
(
gpio_is_valid
(
bdata
->
button
->
gpio
))
gpio_keys_gpio_report_event
(
bdata
);
}
input_sync
(
input
);
device_init_wakeup
(
&
pdev
->
dev
,
wakeup
);
...
...
@@ -642,13 +736,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail3:
sysfs_remove_group
(
&
pdev
->
dev
.
kobj
,
&
gpio_keys_attr_group
);
fail2:
while
(
--
i
>=
0
)
{
free_irq
(
gpio_to_irq
(
pdata
->
buttons
[
i
].
gpio
),
&
ddata
->
data
[
i
]);
if
(
ddata
->
data
[
i
].
timer_debounce
)
del_timer_sync
(
&
ddata
->
data
[
i
].
timer
);
cancel_work_sync
(
&
ddata
->
data
[
i
].
work
);
gpio_free
(
pdata
->
buttons
[
i
].
gpio
);
}
while
(
--
i
>=
0
)
gpio_remove_key
(
&
ddata
->
data
[
i
]);
platform_set_drvdata
(
pdev
,
NULL
);
fail1:
...
...
@@ -671,14 +760,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
device_init_wakeup
(
&
pdev
->
dev
,
0
);
for
(
i
=
0
;
i
<
ddata
->
n_buttons
;
i
++
)
{
int
irq
=
gpio_to_irq
(
ddata
->
data
[
i
].
button
->
gpio
);
free_irq
(
irq
,
&
ddata
->
data
[
i
]);
if
(
ddata
->
data
[
i
].
timer_debounce
)
del_timer_sync
(
&
ddata
->
data
[
i
].
timer
);
cancel_work_sync
(
&
ddata
->
data
[
i
].
work
);
gpio_free
(
ddata
->
data
[
i
].
button
->
gpio
);
}
for
(
i
=
0
;
i
<
ddata
->
n_buttons
;
i
++
)
gpio_remove_key
(
&
ddata
->
data
[
i
]);
input_unregister_device
(
input
);
...
...
@@ -703,11 +786,9 @@ static int gpio_keys_suspend(struct device *dev)
if
(
device_may_wakeup
(
dev
))
{
for
(
i
=
0
;
i
<
ddata
->
n_buttons
;
i
++
)
{
struct
gpio_keys_button
*
button
=
ddata
->
data
[
i
].
button
;
if
(
button
->
wakeup
)
{
int
irq
=
gpio_to_irq
(
button
->
gpio
);
enable_irq_wake
(
irq
);
}
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
if
(
bdata
->
button
->
wakeup
)
enable_irq_wake
(
bdata
->
irq
);
}
}
...
...
@@ -720,14 +801,12 @@ static int gpio_keys_resume(struct device *dev)
int
i
;
for
(
i
=
0
;
i
<
ddata
->
n_buttons
;
i
++
)
{
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
if
(
bdata
->
button
->
wakeup
&&
device_may_wakeup
(
dev
))
disable_irq_wake
(
bdata
->
irq
);
struct
gpio_keys_button
*
button
=
ddata
->
data
[
i
].
button
;
if
(
button
->
wakeup
&&
device_may_wakeup
(
dev
))
{
int
irq
=
gpio_to_irq
(
button
->
gpio
);
disable_irq_wake
(
irq
);
}
gpio_keys_report_event
(
&
ddata
->
data
[
i
]);
if
(
gpio_is_valid
(
bdata
->
button
->
gpio
))
gpio_keys_gpio_report_event
(
bdata
);
}
input_sync
(
ddata
->
input
);
...
...
drivers/input/keyboard/tegra-kbc.c
View file @
99380825
...
...
@@ -630,6 +630,7 @@ tegra_kbc_dt_parse_pdata(struct platform_device *pdev)
if
(
!
np
)
return
NULL
;
pdata
=
kzalloc
(
sizeof
(
*
pdata
),
GFP_KERNEL
);
if
(
!
pdata
)
return
NULL
;
...
...
drivers/input/mouse/sentelic.c
View file @
99380825
...
...
@@ -2,7 +2,7 @@
* Finger Sensing Pad PS/2 mouse driver.
*
* Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
* Copyright (C) 2005-201
1
Tai-hwa Liang, Sentelic Corporation.
* Copyright (C) 2005-201
2
Tai-hwa Liang, Sentelic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
...
...
@@ -21,6 +21,7 @@
#include <linux/module.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/ctype.h>
#include <linux/libps2.h>
#include <linux/serio.h>
...
...
@@ -36,6 +37,9 @@
#define FSP_CMD_TIMEOUT 200
#define FSP_CMD_TIMEOUT2 30
#define GET_ABS_X(packet) ((packet[1] << 2) | ((packet[3] >> 2) & 0x03))
#define GET_ABS_Y(packet) ((packet[2] << 2) | (packet[3] & 0x03))
/** Driver version. */
static
const
char
fsp_drv_ver
[]
=
"1.0.0-K"
;
...
...
@@ -128,8 +132,9 @@ static int fsp_reg_read(struct psmouse *psmouse, int reg_addr, int *reg_val)
out:
ps2_end_command
(
ps2dev
);
psmouse_activate
(
psmouse
);
dev_dbg
(
&
ps2dev
->
serio
->
dev
,
"READ REG: 0x%02x is 0x%02x (rc = %d)
\n
"
,
reg_addr
,
*
reg_val
,
rc
);
psmouse_dbg
(
psmouse
,
"READ REG: 0x%02x is 0x%02x (rc = %d)
\n
"
,
reg_addr
,
*
reg_val
,
rc
);
return
rc
;
}
...
...
@@ -179,8 +184,9 @@ static int fsp_reg_write(struct psmouse *psmouse, int reg_addr, int reg_val)
out:
ps2_end_command
(
ps2dev
);
dev_dbg
(
&
ps2dev
->
serio
->
dev
,
"WRITE REG: 0x%02x to 0x%02x (rc = %d)
\n
"
,
reg_addr
,
reg_val
,
rc
);
psmouse_dbg
(
psmouse
,
"WRITE REG: 0x%02x to 0x%02x (rc = %d)
\n
"
,
reg_addr
,
reg_val
,
rc
);
return
rc
;
}
...
...
@@ -237,8 +243,9 @@ static int fsp_page_reg_read(struct psmouse *psmouse, int *reg_val)
out:
ps2_end_command
(
ps2dev
);
psmouse_activate
(
psmouse
);
dev_dbg
(
&
ps2dev
->
serio
->
dev
,
"READ PAGE REG: 0x%02x (rc = %d)
\n
"
,
*
reg_val
,
rc
);
psmouse_dbg
(
psmouse
,
"READ PAGE REG: 0x%02x (rc = %d)
\n
"
,
*
reg_val
,
rc
);
return
rc
;
}
...
...
@@ -274,8 +281,9 @@ static int fsp_page_reg_write(struct psmouse *psmouse, int reg_val)
out:
ps2_end_command
(
ps2dev
);
dev_dbg
(
&
ps2dev
->
serio
->
dev
,
"WRITE PAGE REG: to 0x%02x (rc = %d)
\n
"
,
reg_val
,
rc
);
psmouse_dbg
(
psmouse
,
"WRITE PAGE REG: to 0x%02x (rc = %d)
\n
"
,
reg_val
,
rc
);
return
rc
;
}
...
...
@@ -319,7 +327,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable)
int
res
=
0
;
if
(
fsp_reg_read
(
psmouse
,
FSP_REG_OPC_QDOWN
,
&
v
)
==
-
1
)
{
dev_err
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Unable get OPC state.
\n
"
);
psmouse_err
(
psmouse
,
"Unable get OPC state.
\n
"
);
return
-
EIO
;
}
...
...
@@ -336,8 +344,7 @@ static int fsp_opc_tag_enable(struct psmouse *psmouse, bool enable)
}
if
(
res
!=
0
)
{
dev_err
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Unable to enable OPC tag.
\n
"
);
psmouse_err
(
psmouse
,
"Unable to enable OPC tag.
\n
"
);
res
=
-
EIO
;
}
...
...
@@ -615,18 +622,40 @@ static struct attribute_group fsp_attribute_group = {
.
attrs
=
fsp_attributes
,
};
#ifdef
FSP_DEBUG
static
void
fsp_packet_debug
(
unsigned
char
packet
[])
#ifdef
FSP_DEBUG
static
void
fsp_packet_debug
(
struct
psmouse
*
psmouse
,
unsigned
char
packet
[])
{
static
unsigned
int
ps2_packet_cnt
;
static
unsigned
int
ps2_last_second
;
unsigned
int
jiffies_msec
;
const
char
*
packet_type
=
"UNKNOWN"
;
unsigned
short
abs_x
=
0
,
abs_y
=
0
;
/* Interpret & dump the packet data. */
switch
(
packet
[
0
]
>>
FSP_PKT_TYPE_SHIFT
)
{
case
FSP_PKT_TYPE_ABS
:
packet_type
=
"Absolute"
;
abs_x
=
GET_ABS_X
(
packet
);
abs_y
=
GET_ABS_Y
(
packet
);
break
;
case
FSP_PKT_TYPE_NORMAL
:
packet_type
=
"Normal"
;
break
;
case
FSP_PKT_TYPE_NOTIFY
:
packet_type
=
"Notify"
;
break
;
case
FSP_PKT_TYPE_NORMAL_OPC
:
packet_type
=
"Normal-OPC"
;
break
;
}
ps2_packet_cnt
++
;
jiffies_msec
=
jiffies_to_msecs
(
jiffies
);
psmouse_dbg
(
psmouse
,
"%08dms PS/2 packets: %02x, %02x, %02x, %02x
\n
"
,
jiffies_msec
,
packet
[
0
],
packet
[
1
],
packet
[
2
],
packet
[
3
]);
"%08dms %s packets: %02x, %02x, %02x, %02x; "
"abs_x: %d, abs_y: %d
\n
"
,
jiffies_msec
,
packet_type
,
packet
[
0
],
packet
[
1
],
packet
[
2
],
packet
[
3
],
abs_x
,
abs_y
);
if
(
jiffies_msec
-
ps2_last_second
>
1000
)
{
psmouse_dbg
(
psmouse
,
"PS/2 packets/sec = %d
\n
"
,
ps2_packet_cnt
);
...
...
@@ -635,17 +664,29 @@ static void fsp_packet_debug(unsigned char packet[])
}
}
#else
static
void
fsp_packet_debug
(
unsigned
char
packet
[])
static
void
fsp_packet_debug
(
struct
psmouse
*
psmouse
,
unsigned
char
packet
[])
{
}
#endif
static
void
fsp_set_slot
(
struct
input_dev
*
dev
,
int
slot
,
bool
active
,
unsigned
int
x
,
unsigned
int
y
)
{
input_mt_slot
(
dev
,
slot
);
input_mt_report_slot_state
(
dev
,
MT_TOOL_FINGER
,
active
);
if
(
active
)
{
input_report_abs
(
dev
,
ABS_MT_POSITION_X
,
x
);
input_report_abs
(
dev
,
ABS_MT_POSITION_Y
,
y
);
}
}
static
psmouse_ret_t
fsp_process_byte
(
struct
psmouse
*
psmouse
)
{
struct
input_dev
*
dev
=
psmouse
->
dev
;
struct
fsp_data
*
ad
=
psmouse
->
private
;
unsigned
char
*
packet
=
psmouse
->
packet
;
unsigned
char
button_status
=
0
,
lscroll
=
0
,
rscroll
=
0
;
unsigned
short
abs_x
,
abs_y
,
fgrs
=
0
;
int
rel_x
,
rel_y
;
if
(
psmouse
->
pktcnt
<
4
)
...
...
@@ -655,16 +696,76 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
* Full packet accumulated, process it
*/
fsp_packet_debug
(
psmouse
,
packet
);
switch
(
psmouse
->
packet
[
0
]
>>
FSP_PKT_TYPE_SHIFT
)
{
case
FSP_PKT_TYPE_ABS
:
dev_warn
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Unexpected absolute mode packet, ignored.
\n
"
);
abs_x
=
GET_ABS_X
(
packet
);
abs_y
=
GET_ABS_Y
(
packet
);
if
(
packet
[
0
]
&
FSP_PB0_MFMC
)
{
/*
* MFMC packet: assume that there are two fingers on
* pad
*/
fgrs
=
2
;
/* MFMC packet */
if
(
packet
[
0
]
&
FSP_PB0_MFMC_FGR2
)
{
/* 2nd finger */
if
(
ad
->
last_mt_fgr
==
2
)
{
/*
* workaround for buggy firmware
* which doesn't clear MFMC bit if
* the 1st finger is up
*/
fgrs
=
1
;
fsp_set_slot
(
dev
,
0
,
false
,
0
,
0
);
}
ad
->
last_mt_fgr
=
2
;
fsp_set_slot
(
dev
,
1
,
fgrs
==
2
,
abs_x
,
abs_y
);
}
else
{
/* 1st finger */
if
(
ad
->
last_mt_fgr
==
1
)
{
/*
* workaround for buggy firmware
* which doesn't clear MFMC bit if
* the 2nd finger is up
*/
fgrs
=
1
;
fsp_set_slot
(
dev
,
1
,
false
,
0
,
0
);
}
ad
->
last_mt_fgr
=
1
;
fsp_set_slot
(
dev
,
0
,
fgrs
!=
0
,
abs_x
,
abs_y
);
}
}
else
{
/* SFAC packet */
/* no multi-finger information */
ad
->
last_mt_fgr
=
0
;
if
(
abs_x
!=
0
&&
abs_y
!=
0
)
fgrs
=
1
;
fsp_set_slot
(
dev
,
0
,
fgrs
>
0
,
abs_x
,
abs_y
);
fsp_set_slot
(
dev
,
1
,
false
,
0
,
0
);
}
if
(
fgrs
>
0
)
{
input_report_abs
(
dev
,
ABS_X
,
abs_x
);
input_report_abs
(
dev
,
ABS_Y
,
abs_y
);
}
input_report_key
(
dev
,
BTN_LEFT
,
packet
[
0
]
&
0x01
);
input_report_key
(
dev
,
BTN_RIGHT
,
packet
[
0
]
&
0x02
);
input_report_key
(
dev
,
BTN_TOUCH
,
fgrs
);
input_report_key
(
dev
,
BTN_TOOL_FINGER
,
fgrs
==
1
);
input_report_key
(
dev
,
BTN_TOOL_DOUBLETAP
,
fgrs
==
2
);
break
;
case
FSP_PKT_TYPE_NORMAL_OPC
:
/* on-pad click, filter it if necessary */
if
((
ad
->
flags
&
FSPDRV_FLAG_EN_OPC
)
!=
FSPDRV_FLAG_EN_OPC
)
packet
[
0
]
&=
~
BIT
(
0
)
;
packet
[
0
]
&=
~
FSP_PB0_LBTN
;
/* fall through */
case
FSP_PKT_TYPE_NORMAL
:
...
...
@@ -711,8 +812,6 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
input_sync
(
dev
);
fsp_packet_debug
(
packet
);
return
PSMOUSE_FULL_PACKET
;
}
...
...
@@ -736,42 +835,106 @@ static int fsp_activate_protocol(struct psmouse *psmouse)
ps2_command
(
ps2dev
,
param
,
PSMOUSE_CMD_GETID
);
if
(
param
[
0
]
!=
0x04
)
{
dev_err
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Unable to enable 4 bytes packet format.
\n
"
);
psmouse_err
(
psmouse
,
"Unable to enable 4 bytes packet format.
\n
"
);
return
-
EIO
;
}
if
(
fsp_reg_read
(
psmouse
,
FSP_REG_SYSCTL5
,
&
val
))
{
dev_err
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Unable to read SYSCTL5 register.
\n
"
);
return
-
EIO
;
}
if
(
pad
->
ver
<
FSP_VER_STL3888_C0
)
{
/* Preparing relative coordinates output for older hardware */
if
(
fsp_reg_read
(
psmouse
,
FSP_REG_SYSCTL5
,
&
val
))
{
psmouse_err
(
psmouse
,
"Unable to read SYSCTL5 register.
\n
"
);
return
-
EIO
;
}
val
&=
~
(
FSP_BIT_EN_MSID7
|
FSP_BIT_EN_MSID8
|
FSP_BIT_EN_AUTO_MSID8
);
/* Ensure we are not in absolute mode */
val
&=
~
FSP_BIT_EN_PKT_G0
;
if
(
pad
->
buttons
==
0x06
)
{
/* Left/Middle/Right & Scroll Up/Down/Right/Left */
val
|=
FSP_BIT_EN_MSID6
;
}
if
(
fsp_get_buttons
(
psmouse
,
&
pad
->
buttons
))
{
psmouse_err
(
psmouse
,
"Unable to retrieve number of buttons.
\n
"
);
return
-
EIO
;
}
if
(
fsp_reg_write
(
psmouse
,
FSP_REG_SYSCTL5
,
val
))
{
dev_err
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Unable to set up required mode bits.
\n
"
);
return
-
EIO
;
val
&=
~
(
FSP_BIT_EN_MSID7
|
FSP_BIT_EN_MSID8
|
FSP_BIT_EN_AUTO_MSID8
);
/* Ensure we are not in absolute mode */
val
&=
~
FSP_BIT_EN_PKT_G0
;
if
(
pad
->
buttons
==
0x06
)
{
/* Left/Middle/Right & Scroll Up/Down/Right/Left */
val
|=
FSP_BIT_EN_MSID6
;
}
if
(
fsp_reg_write
(
psmouse
,
FSP_REG_SYSCTL5
,
val
))
{
psmouse_err
(
psmouse
,
"Unable to set up required mode bits.
\n
"
);
return
-
EIO
;
}
/*
* Enable OPC tags such that driver can tell the difference
* between on-pad and real button click
*/
if
(
fsp_opc_tag_enable
(
psmouse
,
true
))
psmouse_warn
(
psmouse
,
"Failed to enable OPC tag mode.
\n
"
);
/* enable on-pad click by default */
pad
->
flags
|=
FSPDRV_FLAG_EN_OPC
;
/* Enable on-pad vertical and horizontal scrolling */
fsp_onpad_vscr
(
psmouse
,
true
);
fsp_onpad_hscr
(
psmouse
,
true
);
}
else
{
/* Enable absolute coordinates output for Cx/Dx hardware */
if
(
fsp_reg_write
(
psmouse
,
FSP_REG_SWC1
,
FSP_BIT_SWC1_EN_ABS_1F
|
FSP_BIT_SWC1_EN_ABS_2F
|
FSP_BIT_SWC1_EN_FUP_OUT
|
FSP_BIT_SWC1_EN_ABS_CON
))
{
psmouse_err
(
psmouse
,
"Unable to enable absolute coordinates output.
\n
"
);
return
-
EIO
;
}
}
/*
* Enable OPC tags such that driver can tell the difference between
* on-pad and real button click
*/
if
(
fsp_opc_tag_enable
(
psmouse
,
true
))
dev_warn
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Failed to enable OPC tag mode.
\n
"
);
return
0
;
}
/* Enable on-pad vertical and horizontal scrolling */
fsp_onpad_vscr
(
psmouse
,
true
);
fsp_onpad_hscr
(
psmouse
,
true
);
static
int
fsp_set_input_params
(
struct
psmouse
*
psmouse
)
{
struct
input_dev
*
dev
=
psmouse
->
dev
;
struct
fsp_data
*
pad
=
psmouse
->
private
;
if
(
pad
->
ver
<
FSP_VER_STL3888_C0
)
{
__set_bit
(
BTN_MIDDLE
,
dev
->
keybit
);
__set_bit
(
BTN_BACK
,
dev
->
keybit
);
__set_bit
(
BTN_FORWARD
,
dev
->
keybit
);
__set_bit
(
REL_WHEEL
,
dev
->
relbit
);
__set_bit
(
REL_HWHEEL
,
dev
->
relbit
);
}
else
{
/*
* Hardware prior to Cx performs much better in relative mode;
* hence, only enable absolute coordinates output as well as
* multi-touch output for the newer hardware.
*
* Maximum coordinates can be computed as:
*
* number of scanlines * 64 - 57
*
* where number of X/Y scanline lines are 16/12.
*/
int
abs_x
=
967
,
abs_y
=
711
;
__set_bit
(
EV_ABS
,
dev
->
evbit
);
__clear_bit
(
EV_REL
,
dev
->
evbit
);
__set_bit
(
BTN_TOUCH
,
dev
->
keybit
);
__set_bit
(
BTN_TOOL_FINGER
,
dev
->
keybit
);
__set_bit
(
BTN_TOOL_DOUBLETAP
,
dev
->
keybit
);
__set_bit
(
INPUT_PROP_SEMI_MT
,
dev
->
propbit
);
input_set_abs_params
(
dev
,
ABS_X
,
0
,
abs_x
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_Y
,
0
,
abs_y
,
0
,
0
);
input_mt_init_slots
(
dev
,
2
);
input_set_abs_params
(
dev
,
ABS_MT_POSITION_X
,
0
,
abs_x
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_MT_POSITION_Y
,
0
,
abs_y
,
0
,
0
);
}
return
0
;
}
...
...
@@ -829,18 +992,16 @@ static int fsp_reconnect(struct psmouse *psmouse)
int
fsp_init
(
struct
psmouse
*
psmouse
)
{
struct
fsp_data
*
priv
;
int
ver
,
rev
,
buttons
;
int
ver
,
rev
;
int
error
;
if
(
fsp_get_version
(
psmouse
,
&
ver
)
||
fsp_get_revision
(
psmouse
,
&
rev
)
||
fsp_get_buttons
(
psmouse
,
&
buttons
))
{
fsp_get_revision
(
psmouse
,
&
rev
))
{
return
-
ENODEV
;
}
psmouse_info
(
psmouse
,
"Finger Sensing Pad, hw: %d.%d.%d, sw: %s, buttons: %d
\n
"
,
ver
>>
4
,
ver
&
0x0F
,
rev
,
fsp_drv_ver
,
buttons
&
7
);
psmouse_info
(
psmouse
,
"Finger Sensing Pad, hw: %d.%d.%d, sw: %s
\n
"
,
ver
>>
4
,
ver
&
0x0F
,
rev
,
fsp_drv_ver
);
psmouse
->
private
=
priv
=
kzalloc
(
sizeof
(
struct
fsp_data
),
GFP_KERNEL
);
if
(
!
priv
)
...
...
@@ -848,17 +1009,6 @@ int fsp_init(struct psmouse *psmouse)
priv
->
ver
=
ver
;
priv
->
rev
=
rev
;
priv
->
buttons
=
buttons
;
/* enable on-pad click by default */
priv
->
flags
|=
FSPDRV_FLAG_EN_OPC
;
/* Set up various supported input event bits */
__set_bit
(
BTN_MIDDLE
,
psmouse
->
dev
->
keybit
);
__set_bit
(
BTN_BACK
,
psmouse
->
dev
->
keybit
);
__set_bit
(
BTN_FORWARD
,
psmouse
->
dev
->
keybit
);
__set_bit
(
REL_WHEEL
,
psmouse
->
dev
->
relbit
);
__set_bit
(
REL_HWHEEL
,
psmouse
->
dev
->
relbit
);
psmouse
->
protocol_handler
=
fsp_process_byte
;
psmouse
->
disconnect
=
fsp_disconnect
;
...
...
@@ -866,16 +1016,20 @@ int fsp_init(struct psmouse *psmouse)
psmouse
->
cleanup
=
fsp_reset
;
psmouse
->
pktsize
=
4
;
/* set default packet output based on number of buttons we found */
error
=
fsp_activate_protocol
(
psmouse
);
if
(
error
)
goto
err_out
;
/* Set up various supported input event bits */
error
=
fsp_set_input_params
(
psmouse
);
if
(
error
)
goto
err_out
;
error
=
sysfs_create_group
(
&
psmouse
->
ps2dev
.
serio
->
dev
.
kobj
,
&
fsp_attribute_group
);
if
(
error
)
{
dev_err
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
"Failed to create sysfs attributes (%d)"
,
error
);
psmouse_err
(
psmouse
,
"Failed to create sysfs attributes (%d)"
,
error
);
goto
err_out
;
}
...
...
drivers/input/mouse/sentelic.h
View file @
99380825
...
...
@@ -2,7 +2,7 @@
* Finger Sensing Pad PS/2 mouse driver.
*
* Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
* Copyright (C) 2005-201
1
Tai-hwa Liang, Sentelic Corporation.
* Copyright (C) 2005-201
2
Tai-hwa Liang, Sentelic Corporation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
...
...
@@ -55,6 +55,16 @@
#define FSP_BIT_FIX_HSCR BIT(5)
#define FSP_BIT_DRAG_LOCK BIT(6)
#define FSP_REG_SWC1 (0x90)
#define FSP_BIT_SWC1_EN_ABS_1F BIT(0)
#define FSP_BIT_SWC1_EN_GID BIT(1)
#define FSP_BIT_SWC1_EN_ABS_2F BIT(2)
#define FSP_BIT_SWC1_EN_FUP_OUT BIT(3)
#define FSP_BIT_SWC1_EN_ABS_CON BIT(4)
#define FSP_BIT_SWC1_GST_GRP0 BIT(5)
#define FSP_BIT_SWC1_GST_GRP1 BIT(6)
#define FSP_BIT_SWC1_BX_COMPAT BIT(7)
/* Finger-sensing Pad packet formating related definitions */
/* absolute packet type */
...
...
@@ -64,12 +74,32 @@
#define FSP_PKT_TYPE_NORMAL_OPC (0x03)
#define FSP_PKT_TYPE_SHIFT (6)
/* bit definitions for the first byte of report packet */
#define FSP_PB0_LBTN BIT(0)
#define FSP_PB0_RBTN BIT(1)
#define FSP_PB0_MBTN BIT(2)
#define FSP_PB0_MFMC_FGR2 FSP_PB0_MBTN
#define FSP_PB0_MUST_SET BIT(3)
#define FSP_PB0_PHY_BTN BIT(4)
#define FSP_PB0_MFMC BIT(5)
/* hardware revisions */
#define FSP_VER_STL3888_A4 (0xC1)
#define FSP_VER_STL3888_B0 (0xD0)
#define FSP_VER_STL3888_B1 (0xD1)
#define FSP_VER_STL3888_B2 (0xD2)
#define FSP_VER_STL3888_C0 (0xE0)
#define FSP_VER_STL3888_C1 (0xE1)
#define FSP_VER_STL3888_D0 (0xE2)
#define FSP_VER_STL3888_D1 (0xE3)
#define FSP_VER_STL3888_E0 (0xE4)
#ifdef __KERNEL__
struct
fsp_data
{
unsigned
char
ver
;
/* hardware version */
unsigned
char
rev
;
/* hardware revison */
unsigned
char
buttons
;
/* Number of buttons */
unsigned
int
buttons
;
/* Number of buttons */
unsigned
int
flags
;
#define FSPDRV_FLAG_EN_OPC (0x001)
/* enable on-pad clicking */
...
...
@@ -78,6 +108,7 @@ struct fsp_data {
unsigned
char
last_reg
;
/* Last register we requested read from */
unsigned
char
last_val
;
unsigned
int
last_mt_fgr
;
/* Last seen finger(multitouch) */
};
#ifdef CONFIG_MOUSE_PS2_SENTELIC
...
...
drivers/input/tablet/Kconfig
View file @
99380825
...
...
@@ -76,6 +76,7 @@ config TABLET_USB_KBTAB
config TABLET_USB_WACOM
tristate "Wacom Intuos/Graphire tablet support (USB)"
depends on USB_ARCH_HAS_HCD
select POWER_SUPPLY
select USB
select NEW_LEDS
select LEDS_CLASS
...
...
drivers/input/tablet/wacom.h
View file @
99380825
...
...
@@ -88,6 +88,7 @@
#include <linux/mod_devicetable.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/power_supply.h>
#include <asm/unaligned.h>
/*
...
...
@@ -112,6 +113,7 @@ struct wacom {
struct
urb
*
irq
;
struct
wacom_wac
wacom_wac
;
struct
mutex
lock
;
struct
work_struct
work
;
bool
open
;
char
phys
[
32
];
struct
wacom_led
{
...
...
@@ -120,8 +122,15 @@ struct wacom {
u8
hlv
;
/* status led brightness button pressed (1..127) */
u8
img_lum
;
/* OLED matrix display brightness */
}
led
;
struct
power_supply
battery
;
};
static
inline
void
wacom_schedule_work
(
struct
wacom_wac
*
wacom_wac
)
{
struct
wacom
*
wacom
=
container_of
(
wacom_wac
,
struct
wacom
,
wacom_wac
);
schedule_work
(
&
wacom
->
work
);
}
extern
const
struct
usb_device_id
wacom_ids
[];
void
wacom_wac_irq
(
struct
wacom_wac
*
wacom_wac
,
size_t
len
);
...
...
drivers/input/tablet/wacom_sys.c
View file @
99380825
...
...
@@ -167,6 +167,19 @@ static void wacom_close(struct input_dev *dev)
usb_autopm_put_interface
(
wacom
->
intf
);
}
/*
* Static values for max X/Y and resolution of Pen interface is stored in
* features. This mean physical size of active area can be computed.
* This is useful to do when Pen and Touch have same active area of tablet.
* This means for Touch device, we only need to find max X/Y value and we
* have enough information to compute resolution of touch.
*/
static
void
wacom_set_phy_from_res
(
struct
wacom_features
*
features
)
{
features
->
x_phy
=
(
features
->
x_max
*
100
)
/
features
->
x_resolution
;
features
->
y_phy
=
(
features
->
y_max
*
100
)
/
features
->
y_resolution
;
}
static
int
wacom_parse_logical_collection
(
unsigned
char
*
report
,
struct
wacom_features
*
features
)
{
...
...
@@ -178,15 +191,7 @@ static int wacom_parse_logical_collection(unsigned char *report,
features
->
pktlen
=
WACOM_PKGLEN_BBTOUCH3
;
features
->
device_type
=
BTN_TOOL_FINGER
;
/*
* Stylus and Touch have same active area
* so compute physical size based on stylus
* data before its overwritten.
*/
features
->
x_phy
=
(
features
->
x_max
*
100
)
/
features
->
x_resolution
;
features
->
y_phy
=
(
features
->
y_max
*
100
)
/
features
->
y_resolution
;
wacom_set_phy_from_res
(
features
);
features
->
x_max
=
features
->
y_max
=
get_unaligned_le16
(
&
report
[
10
]);
...
...
@@ -422,6 +427,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
report_id
,
rep_data
,
4
,
1
);
}
while
((
error
<
0
||
rep_data
[
1
]
!=
4
)
&&
limit
++
<
WAC_MSG_RETRIES
);
}
else
if
(
features
->
type
!=
TABLETPC
&&
features
->
type
!=
WIRELESS
&&
features
->
device_type
==
BTN_TOOL_PEN
)
{
do
{
rep_data
[
0
]
=
2
;
...
...
@@ -454,6 +460,21 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
features
->
pressure_fuzz
=
0
;
features
->
distance_fuzz
=
0
;
/*
* The wireless device HID is basic and layout conflicts with
* other tablets (monitor and touch interface can look like pen).
* Skip the query for this type and modify defaults based on
* interface number.
*/
if
(
features
->
type
==
WIRELESS
)
{
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceNumber
==
0
)
{
features
->
device_type
=
0
;
}
else
if
(
intf
->
cur_altsetting
->
desc
.
bInterfaceNumber
==
2
)
{
features
->
device_type
=
BTN_TOOL_DOUBLETAP
;
features
->
pktlen
=
WACOM_PKGLEN_BBTOUCH3
;
}
}
/* only Tablet PCs and Bamboo P&T need to retrieve the info */
if
((
features
->
type
!=
TABLETPC
)
&&
(
features
->
type
!=
TABLETPC2FG
)
&&
(
features
->
type
!=
BAMBOO_PT
))
...
...
@@ -822,6 +843,152 @@ static void wacom_destroy_leds(struct wacom *wacom)
}
}
static
enum
power_supply_property
wacom_battery_props
[]
=
{
POWER_SUPPLY_PROP_CAPACITY
};
static
int
wacom_battery_get_property
(
struct
power_supply
*
psy
,
enum
power_supply_property
psp
,
union
power_supply_propval
*
val
)
{
struct
wacom
*
wacom
=
container_of
(
psy
,
struct
wacom
,
battery
);
int
ret
=
0
;
switch
(
psp
)
{
case
POWER_SUPPLY_PROP_CAPACITY
:
val
->
intval
=
wacom
->
wacom_wac
.
battery_capacity
*
100
/
31
;
break
;
default:
ret
=
-
EINVAL
;
break
;
}
return
ret
;
}
static
int
wacom_initialize_battery
(
struct
wacom
*
wacom
)
{
int
error
=
0
;
if
(
wacom
->
wacom_wac
.
features
.
quirks
&
WACOM_QUIRK_MONITOR
)
{
wacom
->
battery
.
properties
=
wacom_battery_props
;
wacom
->
battery
.
num_properties
=
ARRAY_SIZE
(
wacom_battery_props
);
wacom
->
battery
.
get_property
=
wacom_battery_get_property
;
wacom
->
battery
.
name
=
"wacom_battery"
;
wacom
->
battery
.
type
=
POWER_SUPPLY_TYPE_BATTERY
;
wacom
->
battery
.
use_for_apm
=
0
;
error
=
power_supply_register
(
&
wacom
->
usbdev
->
dev
,
&
wacom
->
battery
);
}
return
error
;
}
static
void
wacom_destroy_battery
(
struct
wacom
*
wacom
)
{
if
(
wacom
->
wacom_wac
.
features
.
quirks
&
WACOM_QUIRK_MONITOR
)
power_supply_unregister
(
&
wacom
->
battery
);
}
static
int
wacom_register_input
(
struct
wacom
*
wacom
)
{
struct
input_dev
*
input_dev
;
struct
usb_interface
*
intf
=
wacom
->
intf
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
wacom_wac
*
wacom_wac
=
&
(
wacom
->
wacom_wac
);
int
error
;
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
return
-
ENOMEM
;
input_dev
->
name
=
wacom_wac
->
name
;
input_dev
->
dev
.
parent
=
&
intf
->
dev
;
input_dev
->
open
=
wacom_open
;
input_dev
->
close
=
wacom_close
;
usb_to_input_id
(
dev
,
&
input_dev
->
id
);
input_set_drvdata
(
input_dev
,
wacom
);
wacom_wac
->
input
=
input_dev
;
wacom_setup_input_capabilities
(
input_dev
,
wacom_wac
);
error
=
input_register_device
(
input_dev
);
if
(
error
)
{
input_free_device
(
input_dev
);
wacom_wac
->
input
=
NULL
;
}
return
error
;
}
static
void
wacom_wireless_work
(
struct
work_struct
*
work
)
{
struct
wacom
*
wacom
=
container_of
(
work
,
struct
wacom
,
work
);
struct
usb_device
*
usbdev
=
wacom
->
usbdev
;
struct
wacom_wac
*
wacom_wac
=
&
wacom
->
wacom_wac
;
/*
* Regardless if this is a disconnect or a new tablet,
* remove any existing input devices.
*/
/* Stylus interface */
wacom
=
usb_get_intfdata
(
usbdev
->
config
->
interface
[
1
]);
if
(
wacom
->
wacom_wac
.
input
)
input_unregister_device
(
wacom
->
wacom_wac
.
input
);
wacom
->
wacom_wac
.
input
=
0
;
/* Touch interface */
wacom
=
usb_get_intfdata
(
usbdev
->
config
->
interface
[
2
]);
if
(
wacom
->
wacom_wac
.
input
)
input_unregister_device
(
wacom
->
wacom_wac
.
input
);
wacom
->
wacom_wac
.
input
=
0
;
if
(
wacom_wac
->
pid
==
0
)
{
printk
(
KERN_INFO
"wacom: wireless tablet disconnected
\n
"
);
}
else
{
const
struct
usb_device_id
*
id
=
wacom_ids
;
printk
(
KERN_INFO
"wacom: wireless tablet connected with PID %x
\n
"
,
wacom_wac
->
pid
);
while
(
id
->
match_flags
)
{
if
(
id
->
idVendor
==
USB_VENDOR_ID_WACOM
&&
id
->
idProduct
==
wacom_wac
->
pid
)
break
;
id
++
;
}
if
(
!
id
->
match_flags
)
{
printk
(
KERN_INFO
"wacom: ignorning unknown PID.
\n
"
);
return
;
}
/* Stylus interface */
wacom
=
usb_get_intfdata
(
usbdev
->
config
->
interface
[
1
]);
wacom_wac
=
&
wacom
->
wacom_wac
;
wacom_wac
->
features
=
*
((
struct
wacom_features
*
)
id
->
driver_info
);
wacom_wac
->
features
.
device_type
=
BTN_TOOL_PEN
;
wacom_register_input
(
wacom
);
/* Touch interface */
wacom
=
usb_get_intfdata
(
usbdev
->
config
->
interface
[
2
]);
wacom_wac
=
&
wacom
->
wacom_wac
;
wacom_wac
->
features
=
*
((
struct
wacom_features
*
)
id
->
driver_info
);
wacom_wac
->
features
.
pktlen
=
WACOM_PKGLEN_BBTOUCH3
;
wacom_wac
->
features
.
device_type
=
BTN_TOOL_FINGER
;
wacom_set_phy_from_res
(
&
wacom_wac
->
features
);
wacom_wac
->
features
.
x_max
=
wacom_wac
->
features
.
y_max
=
4096
;
wacom_register_input
(
wacom
);
}
}
static
int
wacom_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
...
...
@@ -829,18 +996,12 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
struct
wacom
*
wacom
;
struct
wacom_wac
*
wacom_wac
;
struct
wacom_features
*
features
;
struct
input_dev
*
input_dev
;
int
error
;
if
(
!
id
->
driver_info
)
return
-
EINVAL
;
wacom
=
kzalloc
(
sizeof
(
struct
wacom
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
wacom
||
!
input_dev
)
{
error
=
-
ENOMEM
;
goto
fail1
;
}
wacom_wac
=
&
wacom
->
wacom_wac
;
wacom_wac
->
features
=
*
((
struct
wacom_features
*
)
id
->
driver_info
);
...
...
@@ -866,11 +1027,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom
->
usbdev
=
dev
;
wacom
->
intf
=
intf
;
mutex_init
(
&
wacom
->
lock
);
INIT_WORK
(
&
wacom
->
work
,
wacom_wireless_work
);
usb_make_path
(
dev
,
wacom
->
phys
,
sizeof
(
wacom
->
phys
));
strlcat
(
wacom
->
phys
,
"/input0"
,
sizeof
(
wacom
->
phys
));
wacom_wac
->
input
=
input_dev
;
endpoint
=
&
intf
->
cur_altsetting
->
endpoint
[
0
].
desc
;
/* Retrieve the physical and logical size for OEM devices */
...
...
@@ -894,15 +1054,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
goto
fail3
;
}
input_dev
->
name
=
wacom_wac
->
name
;
input_dev
->
dev
.
parent
=
&
intf
->
dev
;
input_dev
->
open
=
wacom_open
;
input_dev
->
close
=
wacom_close
;
usb_to_input_id
(
dev
,
&
input_dev
->
id
);
input_set_drvdata
(
input_dev
,
wacom
);
wacom_setup_input_capabilities
(
input_dev
,
wacom_wac
);
usb_fill_int_urb
(
wacom
->
irq
,
dev
,
usb_rcvintpipe
(
dev
,
endpoint
->
bEndpointAddress
),
wacom_wac
->
data
,
features
->
pktlen
,
...
...
@@ -914,22 +1065,34 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
if
(
error
)
goto
fail4
;
error
=
input_register_device
(
input_dev
);
error
=
wacom_initialize_battery
(
wacom
);
if
(
error
)
goto
fail5
;
if
(
!
(
features
->
quirks
&
WACOM_QUIRK_NO_INPUT
))
{
error
=
wacom_register_input
(
wacom
);
if
(
error
)
goto
fail6
;
}
/* Note that if query fails it is not a hard failure */
wacom_query_tablet_data
(
intf
,
features
);
usb_set_intfdata
(
intf
,
wacom
);
if
(
features
->
quirks
&
WACOM_QUIRK_MONITOR
)
{
if
(
usb_submit_urb
(
wacom
->
irq
,
GFP_KERNEL
))
goto
fail5
;
}
return
0
;
fail6:
wacom_destroy_battery
(
wacom
);
fail5:
wacom_destroy_leds
(
wacom
);
fail4:
wacom_remove_shared_data
(
wacom_wac
);
fail3:
usb_free_urb
(
wacom
->
irq
);
fail2:
usb_free_coherent
(
dev
,
WACOM_PKGLEN_MAX
,
wacom_wac
->
data
,
wacom
->
data_dma
);
fail1:
input_free_device
(
input_dev
);
kfree
(
wacom
);
fail1:
kfree
(
wacom
);
return
error
;
}
...
...
@@ -940,7 +1103,10 @@ static void wacom_disconnect(struct usb_interface *intf)
usb_set_intfdata
(
intf
,
NULL
);
usb_kill_urb
(
wacom
->
irq
);
input_unregister_device
(
wacom
->
wacom_wac
.
input
);
cancel_work_sync
(
&
wacom
->
work
);
if
(
wacom
->
wacom_wac
.
input
)
input_unregister_device
(
wacom
->
wacom_wac
.
input
);
wacom_destroy_battery
(
wacom
);
wacom_destroy_leds
(
wacom
);
usb_free_urb
(
wacom
->
irq
);
usb_free_coherent
(
interface_to_usbdev
(
intf
),
WACOM_PKGLEN_MAX
,
...
...
@@ -972,7 +1138,8 @@ static int wacom_resume(struct usb_interface *intf)
wacom_query_tablet_data
(
intf
,
features
);
wacom_led_control
(
wacom
);
if
(
wacom
->
open
&&
usb_submit_urb
(
wacom
->
irq
,
GFP_NOIO
)
<
0
)
if
((
wacom
->
open
||
features
->
quirks
&
WACOM_QUIRK_MONITOR
)
&&
usb_submit_urb
(
wacom
->
irq
,
GFP_NOIO
)
<
0
)
rv
=
-
EIO
;
mutex_unlock
(
&
wacom
->
lock
);
...
...
drivers/input/tablet/wacom_wac.c
View file @
99380825
...
...
@@ -1044,6 +1044,35 @@ static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
return
0
;
}
static
int
wacom_wireless_irq
(
struct
wacom_wac
*
wacom
,
size_t
len
)
{
unsigned
char
*
data
=
wacom
->
data
;
int
connected
;
if
(
len
!=
WACOM_PKGLEN_WIRELESS
||
data
[
0
]
!=
0x80
)
return
0
;
connected
=
data
[
1
]
&
0x01
;
if
(
connected
)
{
int
pid
,
battery
;
pid
=
get_unaligned_be16
(
&
data
[
6
]);
battery
=
data
[
5
]
&
0x3f
;
if
(
wacom
->
pid
!=
pid
)
{
wacom
->
pid
=
pid
;
wacom_schedule_work
(
wacom
);
}
wacom
->
battery_capacity
=
battery
;
}
else
if
(
wacom
->
pid
!=
0
)
{
/* disconnected while previously connected */
wacom
->
pid
=
0
;
wacom_schedule_work
(
wacom
);
wacom
->
battery_capacity
=
0
;
}
return
0
;
}
void
wacom_wac_irq
(
struct
wacom_wac
*
wacom_wac
,
size_t
len
)
{
bool
sync
;
...
...
@@ -1094,6 +1123,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
sync
=
wacom_bpt_irq
(
wacom_wac
,
len
);
break
;
case
WIRELESS
:
sync
=
wacom_wireless_irq
(
wacom_wac
,
len
);
break
;
default:
sync
=
false
;
break
;
...
...
@@ -1155,7 +1188,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
/* these device have multiple inputs */
if
(
features
->
type
==
TABLETPC
||
features
->
type
==
TABLETPC2FG
||
features
->
type
==
BAMBOO_PT
)
features
->
type
==
BAMBOO_PT
||
features
->
type
==
WIRELESS
)
features
->
quirks
|=
WACOM_QUIRK_MULTI_INPUT
;
/* quirk for bamboo touch with 2 low res touches */
...
...
@@ -1167,6 +1200,16 @@ void wacom_setup_device_quirks(struct wacom_features *features)
features
->
y_fuzz
<<=
5
;
features
->
quirks
|=
WACOM_QUIRK_BBTOUCH_LOWRES
;
}
if
(
features
->
type
==
WIRELESS
)
{
/* monitor never has input and pen/touch have delayed create */
features
->
quirks
|=
WACOM_QUIRK_NO_INPUT
;
/* must be monitor interface if no device_type set */
if
(
!
features
->
device_type
)
features
->
quirks
|=
WACOM_QUIRK_MONITOR
;
}
}
static
unsigned
int
wacom_calculate_touch_res
(
unsigned
int
logical_max
,
...
...
@@ -1640,6 +1683,9 @@ static const struct wacom_features wacom_features_0xEC =
static
const
struct
wacom_features
wacom_features_0x47
=
{
"Wacom Intuos2 6x8"
,
WACOM_PKGLEN_INTUOS
,
20320
,
16240
,
1023
,
31
,
INTUOS
,
WACOM_INTUOS_RES
,
WACOM_INTUOS_RES
};
static
const
struct
wacom_features
wacom_features_0x84
=
{
"Wacom Wireless Receiver"
,
WACOM_PKGLEN_WIRELESS
,
0
,
0
,
0
,
0
,
WIRELESS
,
0
,
0
};
static
const
struct
wacom_features
wacom_features_0xD0
=
{
"Wacom Bamboo 2FG"
,
WACOM_PKGLEN_BBFUN
,
14720
,
9200
,
1023
,
31
,
BAMBOO_PT
,
WACOM_INTUOS_RES
,
WACOM_INTUOS_RES
};
...
...
@@ -1766,6 +1812,7 @@ const struct usb_device_id wacom_ids[] = {
{
USB_DEVICE_DETAILED
(
0xCE
,
USB_CLASS_HID
,
USB_INTERFACE_SUBCLASS_BOOT
,
USB_INTERFACE_PROTOCOL_MOUSE
)
},
{
USB_DEVICE_WACOM
(
0x84
)
},
{
USB_DEVICE_WACOM
(
0xD0
)
},
{
USB_DEVICE_WACOM
(
0xD1
)
},
{
USB_DEVICE_WACOM
(
0xD2
)
},
...
...
drivers/input/tablet/wacom_wac.h
View file @
99380825
...
...
@@ -24,6 +24,7 @@
#define WACOM_PKGLEN_BBTOUCH 20
#define WACOM_PKGLEN_BBTOUCH3 64
#define WACOM_PKGLEN_BBPEN 10
#define WACOM_PKGLEN_WIRELESS 32
/* device IDs */
#define STYLUS_DEVICE_ID 0x02
...
...
@@ -45,6 +46,8 @@
/* device quirks */
#define WACOM_QUIRK_MULTI_INPUT 0x0001
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
#define WACOM_QUIRK_NO_INPUT 0x0004
#define WACOM_QUIRK_MONITOR 0x0008
enum
{
PENPARTNER
=
0
,
...
...
@@ -54,6 +57,7 @@ enum {
PL
,
DTU
,
BAMBOO_PT
,
WIRELESS
,
INTUOS
,
INTUOS3S
,
INTUOS3
,
...
...
@@ -107,6 +111,8 @@ struct wacom_wac {
struct
wacom_features
features
;
struct
wacom_shared
*
shared
;
struct
input_dev
*
input
;
int
pid
;
int
battery_capacity
;
};
#endif
include/linux/gpio_keys.h
View file @
99380825
...
...
@@ -6,7 +6,7 @@ struct device;
struct
gpio_keys_button
{
/* Configuration parameters */
unsigned
int
code
;
/* input event code (KEY_*, SW_*) */
int
gpio
;
int
gpio
;
/* -1 if this key does not support gpio */
int
active_low
;
const
char
*
desc
;
unsigned
int
type
;
/* input event type (EV_KEY, EV_SW, EV_ABS) */
...
...
@@ -14,6 +14,7 @@ struct gpio_keys_button {
int
debounce_interval
;
/* debounce ticks interval in msecs */
bool
can_disable
;
int
value
;
/* axis value for EV_ABS */
unsigned
int
irq
;
/* Irq number in case of interrupt keys */
};
struct
gpio_keys_platform_data
{
...
...
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