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
4c0e799a
Commit
4c0e799a
authored
Oct 15, 2008
by
Dmitry Torokhov
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' into for-linus
parents
3fa8749e
b8d055a8
Changes
51
Hide whitespace changes
Inline
Side-by-side
Showing
51 changed files
with
2309 additions
and
352 deletions
+2309
-352
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+1
-0
MAINTAINERS
MAINTAINERS
+1
-1
drivers/char/keyboard.c
drivers/char/keyboard.c
+1
-1
drivers/input/gameport/gameport.c
drivers/input/gameport/gameport.c
+67
-21
drivers/input/joystick/a3d.c
drivers/input/joystick/a3d.c
+1
-2
drivers/input/joystick/adi.c
drivers/input/joystick/adi.c
+1
-2
drivers/input/joystick/analog.c
drivers/input/joystick/analog.c
+1
-3
drivers/input/joystick/cobra.c
drivers/input/joystick/cobra.c
+1
-2
drivers/input/joystick/gf2k.c
drivers/input/joystick/gf2k.c
+1
-2
drivers/input/joystick/grip.c
drivers/input/joystick/grip.c
+1
-2
drivers/input/joystick/grip_mp.c
drivers/input/joystick/grip_mp.c
+1
-2
drivers/input/joystick/guillemot.c
drivers/input/joystick/guillemot.c
+1
-2
drivers/input/joystick/interact.c
drivers/input/joystick/interact.c
+1
-2
drivers/input/joystick/joydump.c
drivers/input/joystick/joydump.c
+1
-2
drivers/input/joystick/sidewinder.c
drivers/input/joystick/sidewinder.c
+1
-2
drivers/input/joystick/tmdc.c
drivers/input/joystick/tmdc.c
+1
-2
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+10
-20
drivers/input/keyboard/bf54x-keys.c
drivers/input/keyboard/bf54x-keys.c
+12
-1
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys.c
+16
-26
drivers/input/misc/Kconfig
drivers/input/misc/Kconfig
+13
-0
drivers/input/misc/Makefile
drivers/input/misc/Makefile
+1
-0
drivers/input/misc/ati_remote2.c
drivers/input/misc/ati_remote2.c
+228
-35
drivers/input/misc/cm109.c
drivers/input/misc/cm109.c
+882
-0
drivers/input/misc/wistron_btns.c
drivers/input/misc/wistron_btns.c
+19
-0
drivers/input/misc/yealink.c
drivers/input/misc/yealink.c
+1
-1
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+10
-0
drivers/input/mouse/Makefile
drivers/input/mouse/Makefile
+1
-0
drivers/input/mouse/alps.c
drivers/input/mouse/alps.c
+1
-0
drivers/input/mouse/appletouch.c
drivers/input/mouse/appletouch.c
+222
-77
drivers/input/mouse/hgpk.c
drivers/input/mouse/hgpk.c
+477
-0
drivers/input/mouse/hgpk.h
drivers/input/mouse/hgpk.h
+49
-0
drivers/input/mouse/logips2pp.c
drivers/input/mouse/logips2pp.c
+1
-3
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/psmouse-base.c
+53
-28
drivers/input/mouse/psmouse.h
drivers/input/mouse/psmouse.h
+11
-3
drivers/input/mouse/trackpoint.c
drivers/input/mouse/trackpoint.c
+2
-6
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042-x86ia64io.h
+7
-0
drivers/input/serio/serio_raw.c
drivers/input/serio/serio_raw.c
+6
-0
drivers/input/tablet/aiptek.c
drivers/input/tablet/aiptek.c
+38
-15
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/ads7846.c
+109
-53
drivers/input/touchscreen/atmel_tsadcc.c
drivers/input/touchscreen/atmel_tsadcc.c
+24
-13
drivers/input/touchscreen/mainstone-wm97xx.c
drivers/input/touchscreen/mainstone-wm97xx.c
+2
-3
drivers/input/touchscreen/wm9705.c
drivers/input/touchscreen/wm9705.c
+2
-3
drivers/input/touchscreen/wm9712.c
drivers/input/touchscreen/wm9712.c
+2
-3
drivers/input/touchscreen/wm9713.c
drivers/input/touchscreen/wm9713.c
+2
-3
drivers/input/touchscreen/wm97xx-core.c
drivers/input/touchscreen/wm97xx-core.c
+2
-3
include/linux/Kbuild
include/linux/Kbuild
+1
-0
include/linux/gameport.h
include/linux/gameport.h
+4
-3
include/linux/input.h
include/linux/input.h
+14
-1
include/linux/map_to_7segment.h
include/linux/map_to_7segment.h
+1
-3
include/linux/mod_devicetable.h
include/linux/mod_devicetable.h
+1
-1
include/linux/spi/ads7846.h
include/linux/spi/ads7846.h
+3
-0
No files found.
Documentation/kernel-parameters.txt
View file @
4c0e799a
...
...
@@ -796,6 +796,7 @@ and is between 256 and 4096 characters. It is defined in the file
Defaults to the default architecture's huge page size
if not specified.
i8042.debug [HW] Toggle i8042 debug mode
i8042.direct [HW] Put keyboard port into non-translated mode
i8042.dumbkbd [HW] Pretend that controller can only read data from
keyboard and cannot control its state
...
...
MAINTAINERS
View file @
4c0e799a
...
...
@@ -4548,7 +4548,7 @@ WM97XX TOUCHSCREEN DRIVERS
P: Mark Brown
M: broonie@opensource.wolfsonmicro.com
P: Liam Girdwood
M: l
iam.girdwood@wolfsonmicro.com
M: l
rg@slimlogic.co.uk
L: linux-input@vger.kernel.org
T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
W: http://opensource.wolfsonmicro.com/node/7
...
...
drivers/char/keyboard.c
View file @
4c0e799a
...
...
@@ -1249,7 +1249,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
return
;
}
if
(
keycode
>
NR_KEYS
)
if
(
keycode
>
=
NR_KEYS
)
if
(
keycode
>=
KEY_BRL_DOT1
&&
keycode
<=
KEY_BRL_DOT8
)
keysym
=
K
(
KT_BRL
,
keycode
-
KEY_BRL_DOT1
+
1
);
else
...
...
drivers/input/gameport/gameport.c
View file @
4c0e799a
...
...
@@ -231,6 +231,7 @@ static void gameport_find_driver(struct gameport *gameport)
enum
gameport_event_type
{
GAMEPORT_REGISTER_PORT
,
GAMEPORT_REGISTER_DRIVER
,
GAMEPORT_ATTACH_DRIVER
,
};
struct
gameport_event
{
...
...
@@ -245,11 +246,12 @@ static LIST_HEAD(gameport_event_list);
static
DECLARE_WAIT_QUEUE_HEAD
(
gameport_wait
);
static
struct
task_struct
*
gameport_task
;
static
void
gameport_queue_event
(
void
*
object
,
struct
module
*
owner
,
enum
gameport_event_type
event_type
)
static
int
gameport_queue_event
(
void
*
object
,
struct
module
*
owner
,
enum
gameport_event_type
event_type
)
{
unsigned
long
flags
;
struct
gameport_event
*
event
;
int
retval
=
0
;
spin_lock_irqsave
(
&
gameport_event_lock
,
flags
);
...
...
@@ -268,24 +270,34 @@ static void gameport_queue_event(void *object, struct module *owner,
}
}
if
((
event
=
kmalloc
(
sizeof
(
struct
gameport_event
),
GFP_ATOMIC
)))
{
if
(
!
try_module_get
(
owner
))
{
printk
(
KERN_WARNING
"gameport: Can't get module reference, dropping event %d
\n
"
,
event_type
);
kfree
(
event
);
goto
out
;
}
event
->
type
=
event_type
;
event
->
object
=
object
;
event
->
owner
=
owner
;
event
=
kmalloc
(
sizeof
(
struct
gameport_event
),
GFP_ATOMIC
);
if
(
!
event
)
{
printk
(
KERN_ERR
"gameport: Not enough memory to queue event %d
\n
"
,
event_type
);
retval
=
-
ENOMEM
;
goto
out
;
}
list_add_tail
(
&
event
->
node
,
&
gameport_event_list
);
wake_up
(
&
gameport_wait
);
}
else
{
printk
(
KERN_ERR
"gameport: Not enough memory to queue event %d
\n
"
,
event_type
);
if
(
!
try_module_get
(
owner
))
{
printk
(
KERN_WARNING
"gameport: Can't get module reference, dropping event %d
\n
"
,
event_type
);
kfree
(
event
);
retval
=
-
EINVAL
;
goto
out
;
}
event
->
type
=
event_type
;
event
->
object
=
object
;
event
->
owner
=
owner
;
list_add_tail
(
&
event
->
node
,
&
gameport_event_list
);
wake_up
(
&
gameport_wait
);
out:
spin_unlock_irqrestore
(
&
gameport_event_lock
,
flags
);
return
retval
;
}
static
void
gameport_free_event
(
struct
gameport_event
*
event
)
...
...
@@ -378,9 +390,10 @@ static void gameport_handle_event(void)
}
/*
* Remove all events that have been submitted for a given gameport port.
* Remove all events that have been submitted for a given object,
* be it a gameport port or a driver.
*/
static
void
gameport_remove_pending_events
(
struct
gameport
*
gamepor
t
)
static
void
gameport_remove_pending_events
(
void
*
objec
t
)
{
struct
list_head
*
node
,
*
next
;
struct
gameport_event
*
event
;
...
...
@@ -390,7 +403,7 @@ static void gameport_remove_pending_events(struct gameport *gameport)
list_for_each_safe
(
node
,
next
,
&
gameport_event_list
)
{
event
=
list_entry
(
node
,
struct
gameport_event
,
node
);
if
(
event
->
object
==
gamepor
t
)
{
if
(
event
->
object
==
objec
t
)
{
list_del_init
(
node
);
gameport_free_event
(
event
);
}
...
...
@@ -705,10 +718,40 @@ static void gameport_add_driver(struct gameport_driver *drv)
drv
->
driver
.
name
,
error
);
}
void
__gameport_register_driver
(
struct
gameport_driver
*
drv
,
struct
module
*
owner
)
int
__gameport_register_driver
(
struct
gameport_driver
*
drv
,
struct
module
*
owner
,
const
char
*
mod_name
)
{
int
error
;
drv
->
driver
.
bus
=
&
gameport_bus
;
gameport_queue_event
(
drv
,
owner
,
GAMEPORT_REGISTER_DRIVER
);
drv
->
driver
.
owner
=
owner
;
drv
->
driver
.
mod_name
=
mod_name
;
/*
* Temporarily disable automatic binding because probing
* takes long time and we are better off doing it in kgameportd
*/
drv
->
ignore
=
1
;
error
=
driver_register
(
&
drv
->
driver
);
if
(
error
)
{
printk
(
KERN_ERR
"gameport: driver_register() failed for %s, error: %d
\n
"
,
drv
->
driver
.
name
,
error
);
return
error
;
}
/*
* Reset ignore flag and let kgameportd bind the driver to free ports
*/
drv
->
ignore
=
0
;
error
=
gameport_queue_event
(
drv
,
NULL
,
GAMEPORT_ATTACH_DRIVER
);
if
(
error
)
{
driver_unregister
(
&
drv
->
driver
);
return
error
;
}
return
0
;
}
void
gameport_unregister_driver
(
struct
gameport_driver
*
drv
)
...
...
@@ -716,7 +759,9 @@ void gameport_unregister_driver(struct gameport_driver *drv)
struct
gameport
*
gameport
;
mutex_lock
(
&
gameport_mutex
);
drv
->
ignore
=
1
;
/* so gameport_find_driver ignores it */
gameport_remove_pending_events
(
drv
);
start_over:
list_for_each_entry
(
gameport
,
&
gameport_list
,
node
)
{
...
...
@@ -729,6 +774,7 @@ void gameport_unregister_driver(struct gameport_driver *drv)
}
driver_unregister
(
&
drv
->
driver
);
mutex_unlock
(
&
gameport_mutex
);
}
...
...
drivers/input/joystick/a3d.c
View file @
4c0e799a
...
...
@@ -414,8 +414,7 @@ static struct gameport_driver a3d_drv = {
static
int
__init
a3d_init
(
void
)
{
gameport_register_driver
(
&
a3d_drv
);
return
0
;
return
gameport_register_driver
(
&
a3d_drv
);
}
static
void
__exit
a3d_exit
(
void
)
...
...
drivers/input/joystick/adi.c
View file @
4c0e799a
...
...
@@ -572,8 +572,7 @@ static struct gameport_driver adi_drv = {
static
int
__init
adi_init
(
void
)
{
gameport_register_driver
(
&
adi_drv
);
return
0
;
return
gameport_register_driver
(
&
adi_drv
);
}
static
void
__exit
adi_exit
(
void
)
...
...
drivers/input/joystick/analog.c
View file @
4c0e799a
...
...
@@ -761,9 +761,7 @@ static struct gameport_driver analog_drv = {
static
int
__init
analog_init
(
void
)
{
analog_parse_options
();
gameport_register_driver
(
&
analog_drv
);
return
0
;
return
gameport_register_driver
(
&
analog_drv
);
}
static
void
__exit
analog_exit
(
void
)
...
...
drivers/input/joystick/cobra.c
View file @
4c0e799a
...
...
@@ -263,8 +263,7 @@ static struct gameport_driver cobra_drv = {
static
int
__init
cobra_init
(
void
)
{
gameport_register_driver
(
&
cobra_drv
);
return
0
;
return
gameport_register_driver
(
&
cobra_drv
);
}
static
void
__exit
cobra_exit
(
void
)
...
...
drivers/input/joystick/gf2k.c
View file @
4c0e799a
...
...
@@ -375,8 +375,7 @@ static struct gameport_driver gf2k_drv = {
static
int
__init
gf2k_init
(
void
)
{
gameport_register_driver
(
&
gf2k_drv
);
return
0
;
return
gameport_register_driver
(
&
gf2k_drv
);
}
static
void
__exit
gf2k_exit
(
void
)
...
...
drivers/input/joystick/grip.c
View file @
4c0e799a
...
...
@@ -426,8 +426,7 @@ static struct gameport_driver grip_drv = {
static
int
__init
grip_init
(
void
)
{
gameport_register_driver
(
&
grip_drv
);
return
0
;
return
gameport_register_driver
(
&
grip_drv
);
}
static
void
__exit
grip_exit
(
void
)
...
...
drivers/input/joystick/grip_mp.c
View file @
4c0e799a
...
...
@@ -689,8 +689,7 @@ static struct gameport_driver grip_drv = {
static
int
__init
grip_init
(
void
)
{
gameport_register_driver
(
&
grip_drv
);
return
0
;
return
gameport_register_driver
(
&
grip_drv
);
}
static
void
__exit
grip_exit
(
void
)
...
...
drivers/input/joystick/guillemot.c
View file @
4c0e799a
...
...
@@ -283,8 +283,7 @@ static struct gameport_driver guillemot_drv = {
static
int
__init
guillemot_init
(
void
)
{
gameport_register_driver
(
&
guillemot_drv
);
return
0
;
return
gameport_register_driver
(
&
guillemot_drv
);
}
static
void
__exit
guillemot_exit
(
void
)
...
...
drivers/input/joystick/interact.c
View file @
4c0e799a
...
...
@@ -317,8 +317,7 @@ static struct gameport_driver interact_drv = {
static
int
__init
interact_init
(
void
)
{
gameport_register_driver
(
&
interact_drv
);
return
0
;
return
gameport_register_driver
(
&
interact_drv
);
}
static
void
__exit
interact_exit
(
void
)
...
...
drivers/input/joystick/joydump.c
View file @
4c0e799a
...
...
@@ -161,8 +161,7 @@ static struct gameport_driver joydump_drv = {
static
int
__init
joydump_init
(
void
)
{
gameport_register_driver
(
&
joydump_drv
);
return
0
;
return
gameport_register_driver
(
&
joydump_drv
);
}
static
void
__exit
joydump_exit
(
void
)
...
...
drivers/input/joystick/sidewinder.c
View file @
4c0e799a
...
...
@@ -818,8 +818,7 @@ static struct gameport_driver sw_drv = {
static
int
__init
sw_init
(
void
)
{
gameport_register_driver
(
&
sw_drv
);
return
0
;
return
gameport_register_driver
(
&
sw_drv
);
}
static
void
__exit
sw_exit
(
void
)
...
...
drivers/input/joystick/tmdc.c
View file @
4c0e799a
...
...
@@ -438,8 +438,7 @@ static struct gameport_driver tmdc_drv = {
static
int
__init
tmdc_init
(
void
)
{
gameport_register_driver
(
&
tmdc_drv
);
return
0
;
return
gameport_register_driver
(
&
tmdc_drv
);
}
static
void
__exit
tmdc_exit
(
void
)
...
...
drivers/input/keyboard/atkbd.c
View file @
4c0e799a
...
...
@@ -834,10 +834,10 @@ static void atkbd_disconnect(struct serio *serio)
}
/*
* Most special keys (Fn+F?) on Dell
Latitude
s do not generate release
* Most special keys (Fn+F?) on Dell
laptop
s do not generate release
* events so we have to do it ourselves.
*/
static
void
atkbd_
latitude
_keymap_fixup
(
struct
atkbd
*
atkbd
)
static
void
atkbd_
dell_laptop
_keymap_fixup
(
struct
atkbd
*
atkbd
)
{
const
unsigned
int
forced_release_keys
[]
=
{
0x85
,
0x86
,
0x87
,
0x88
,
0x89
,
0x8a
,
0x8b
,
0x8f
,
0x93
,
...
...
@@ -1207,15 +1207,13 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
{
struct
input_dev
*
old_dev
,
*
new_dev
;
unsigned
long
value
;
char
*
rest
;
int
err
;
unsigned
char
old_extra
,
old_set
;
if
(
!
atkbd
->
write
)
return
-
EIO
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
1
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
1
)
return
-
EINVAL
;
if
(
atkbd
->
extra
!=
value
)
{
...
...
@@ -1264,12 +1262,10 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
{
struct
input_dev
*
old_dev
,
*
new_dev
;
unsigned
long
value
;
char
*
rest
;
int
err
;
unsigned
char
old_scroll
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
1
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
1
)
return
-
EINVAL
;
if
(
atkbd
->
scroll
!=
value
)
{
...
...
@@ -1310,15 +1306,13 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{
struct
input_dev
*
old_dev
,
*
new_dev
;
unsigned
long
value
;
char
*
rest
;
int
err
;
unsigned
char
old_set
,
old_extra
;
if
(
!
atkbd
->
write
)
return
-
EIO
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
(
value
!=
2
&&
value
!=
3
))
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
(
value
!=
2
&&
value
!=
3
))
return
-
EINVAL
;
if
(
atkbd
->
set
!=
value
)
{
...
...
@@ -1361,15 +1355,13 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
{
struct
input_dev
*
old_dev
,
*
new_dev
;
unsigned
long
value
;
char
*
rest
;
int
err
;
unsigned
char
old_softrepeat
,
old_softraw
;
if
(
!
atkbd
->
write
)
return
-
EIO
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
1
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
1
)
return
-
EINVAL
;
if
(
atkbd
->
softrepeat
!=
value
)
{
...
...
@@ -1413,12 +1405,10 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
{
struct
input_dev
*
old_dev
,
*
new_dev
;
unsigned
long
value
;
char
*
rest
;
int
err
;
unsigned
char
old_softraw
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
1
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
1
)
return
-
EINVAL
;
if
(
atkbd
->
softraw
!=
value
)
{
...
...
@@ -1461,13 +1451,13 @@ static int __init atkbd_setup_fixup(const struct dmi_system_id *id)
static
struct
dmi_system_id
atkbd_dmi_quirk_table
[]
__initdata
=
{
{
.
ident
=
"Dell La
titude series
"
,
.
ident
=
"Dell La
ptop
"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Dell Inc."
),
DMI_MATCH
(
DMI_
PRODUCT_NAME
,
"Latitude"
),
DMI_MATCH
(
DMI_
CHASSIS_TYPE
,
"8"
),
/* Portable */
},
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_
latitude
_keymap_fixup
,
.
driver_data
=
atkbd_
dell_laptop
_keymap_fixup
,
},
{
.
ident
=
"HP 2133"
,
...
...
drivers/input/keyboard/bf54x-keys.c
View file @
4c0e799a
...
...
@@ -8,7 +8,7 @@
*
*
* Modified:
* Copyright 2007 Analog Devices Inc.
* Copyright 2007
-2008
Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
...
...
@@ -81,6 +81,9 @@ struct bf54x_kpad {
unsigned
short
*
keycode
;
struct
timer_list
timer
;
unsigned
int
keyup_test_jiffies
;
unsigned
short
kpad_msel
;
unsigned
short
kpad_prescale
;
unsigned
short
kpad_ctl
;
};
static
inline
int
bfin_kpad_find_key
(
struct
bf54x_kpad
*
bf54x_kpad
,
...
...
@@ -360,6 +363,10 @@ static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
{
struct
bf54x_kpad
*
bf54x_kpad
=
platform_get_drvdata
(
pdev
);
bf54x_kpad
->
kpad_msel
=
bfin_read_KPAD_MSEL
();
bf54x_kpad
->
kpad_prescale
=
bfin_read_KPAD_PRESCALE
();
bf54x_kpad
->
kpad_ctl
=
bfin_read_KPAD_CTL
();
if
(
device_may_wakeup
(
&
pdev
->
dev
))
enable_irq_wake
(
bf54x_kpad
->
irq
);
...
...
@@ -370,6 +377,10 @@ static int bfin_kpad_resume(struct platform_device *pdev)
{
struct
bf54x_kpad
*
bf54x_kpad
=
platform_get_drvdata
(
pdev
);
bfin_write_KPAD_MSEL
(
bf54x_kpad
->
kpad_msel
);
bfin_write_KPAD_PRESCALE
(
bf54x_kpad
->
kpad_prescale
);
bfin_write_KPAD_CTL
(
bf54x_kpad
->
kpad_ctl
);
if
(
device_may_wakeup
(
&
pdev
->
dev
))
disable_irq_wake
(
bf54x_kpad
->
irq
);
...
...
drivers/input/keyboard/gpio_keys.c
View file @
4c0e799a
...
...
@@ -36,9 +36,10 @@ struct gpio_keys_drvdata {
struct
gpio_button_data
data
[
0
];
};
static
void
gpio_keys_report_event
(
struct
gpio_keys_button
*
button
,
struct
input_dev
*
input
)
static
void
gpio_keys_report_event
(
struct
gpio_button_data
*
bdata
)
{
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
(
button
->
gpio
)
?
1
:
0
)
^
button
->
active_low
;
...
...
@@ -50,34 +51,23 @@ static void gpio_check_button(unsigned long _data)
{
struct
gpio_button_data
*
data
=
(
struct
gpio_button_data
*
)
_data
;
gpio_keys_report_event
(
data
->
button
,
data
->
input
);
gpio_keys_report_event
(
data
);
}
static
irqreturn_t
gpio_keys_isr
(
int
irq
,
void
*
dev_id
)
{
struct
platform_device
*
pdev
=
dev_id
;
struct
gpio_keys_platform_data
*
pdata
=
pdev
->
dev
.
platform_data
;
struct
gpio_keys_drvdata
*
ddata
=
platform_get_drvdata
(
pdev
);
int
i
;
struct
gpio_button_data
*
bdata
=
dev_id
;
struct
gpio_keys_button
*
button
=
bdata
->
button
;
for
(
i
=
0
;
i
<
pdata
->
nbuttons
;
i
++
)
{
struct
gpio_keys_button
*
button
=
&
pdata
->
buttons
[
i
];
BUG_ON
(
irq
!=
gpio_to_irq
(
button
->
gpio
));
if
(
irq
==
gpio_to_irq
(
button
->
gpio
))
{
struct
gpio_button_data
*
bdata
=
&
ddata
->
data
[
i
];
if
(
button
->
debounce_interval
)
mod_timer
(
&
bdata
->
timer
,
jiffies
+
msecs_to_jiffies
(
button
->
debounce_interval
));
else
gpio_keys_report_event
(
button
,
bdata
->
input
);
return
IRQ_HANDLED
;
}
}
if
(
button
->
debounce_interval
)
mod_timer
(
&
bdata
->
timer
,
jiffies
+
msecs_to_jiffies
(
button
->
debounce_interval
));
else
gpio_keys_report_event
(
bdata
);
return
IRQ_
NONE
;
return
IRQ_
HANDLED
;
}
static
int
__devinit
gpio_keys_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -151,7 +141,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
IRQF_SAMPLE_RANDOM
|
IRQF_TRIGGER_RISING
|
IRQF_TRIGGER_FALLING
,
button
->
desc
?
button
->
desc
:
"gpio_keys"
,
pdev
);
bdata
);
if
(
error
)
{
pr_err
(
"gpio-keys: Unable to claim irq %d; error %d
\n
"
,
irq
,
error
);
...
...
@@ -178,7 +168,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail2:
while
(
--
i
>=
0
)
{
free_irq
(
gpio_to_irq
(
pdata
->
buttons
[
i
].
gpio
),
pdev
);
free_irq
(
gpio_to_irq
(
pdata
->
buttons
[
i
].
gpio
),
&
ddata
->
data
[
i
]
);
if
(
pdata
->
buttons
[
i
].
debounce_interval
)
del_timer_sync
(
&
ddata
->
data
[
i
].
timer
);
gpio_free
(
pdata
->
buttons
[
i
].
gpio
);
...
...
@@ -203,7 +193,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for
(
i
=
0
;
i
<
pdata
->
nbuttons
;
i
++
)
{
int
irq
=
gpio_to_irq
(
pdata
->
buttons
[
i
].
gpio
);
free_irq
(
irq
,
pdev
);
free_irq
(
irq
,
&
ddata
->
data
[
i
]
);
if
(
pdata
->
buttons
[
i
].
debounce_interval
)
del_timer_sync
(
&
ddata
->
data
[
i
].
timer
);
gpio_free
(
pdata
->
buttons
[
i
].
gpio
);
...
...
drivers/input/misc/Kconfig
View file @
4c0e799a
...
...
@@ -180,6 +180,19 @@ config INPUT_YEALINK
To compile this driver as a module, choose M here: the module will be
called yealink.
config INPUT_CM109
tristate "C-Media CM109 USB I/O Controller"
depends on EXPERIMENTAL
depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to enable keyboard and buzzer functions of the
C-Media CM109 usb phones. The audio part is enabled by the generic
usb sound driver, so you might want to enable that as well.
To compile this driver as a module, choose M here: the module will be
called cm109.
config INPUT_UINPUT
tristate "User level driver support"
help
...
...
drivers/input/misc/Makefile
View file @
4c0e799a
...
...
@@ -16,6 +16,7 @@ obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)
+=
keyspan_remote.o
obj-$(CONFIG_INPUT_POWERMATE)
+=
powermate.o
obj-$(CONFIG_INPUT_YEALINK)
+=
yealink.o
obj-$(CONFIG_INPUT_CM109)
+=
cm109.o
obj-$(CONFIG_HP_SDC_RTC)
+=
hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT)
+=
uinput.o
obj-$(CONFIG_INPUT_APANEL)
+=
apanel.o
...
...
drivers/input/misc/ati_remote2.c
View file @
4c0e799a
/*
* ati_remote2 - ATI/Philips USB RF remote driver
*
* Copyright (C) 2005 Ville Syrjala <syrjala@sci.fi>
* Copyright (C) 2007
Peter Stokes <linux@dadeos.freeserve
.co.uk>
* Copyright (C) 2005
-2008
Ville Syrjala <syrjala@sci.fi>
* Copyright (C) 2007
-2008 Peter Stokes <linux@dadeos
.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
...
...
@@ -12,7 +12,7 @@
#include <linux/usb/input.h>
#define DRIVER_DESC "ATI/Philips USB RF remote driver"
#define DRIVER_VERSION "0.
2
"
#define DRIVER_VERSION "0.
3
"
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_VERSION
(
DRIVER_VERSION
);
...
...
@@ -27,7 +27,7 @@ MODULE_LICENSE("GPL");
* A remote's "channel" may be altered by pressing and holding the "PC" button for
* approximately 3 seconds, after which the button will slowly flash the count of the
* currently configured "channel", using the numeric keypad enter a number between 1 and
* 16 and then the "PC" button again, the button will slowly flash the count of the
* 16 and then
press
the "PC" button again, the button will slowly flash the count of the
* newly configured "channel".
*/
...
...
@@ -45,9 +45,25 @@ static struct usb_device_id ati_remote2_id_table[] = {
};
MODULE_DEVICE_TABLE
(
usb
,
ati_remote2_id_table
);
static
struct
{
int
hw_code
;
int
key_code
;
static
DEFINE_MUTEX
(
ati_remote2_mutex
);
enum
{
ATI_REMOTE2_OPENED
=
0x1
,
ATI_REMOTE2_SUSPENDED
=
0x2
,
};
enum
{
ATI_REMOTE2_AUX1
,
ATI_REMOTE2_AUX2
,
ATI_REMOTE2_AUX3
,
ATI_REMOTE2_AUX4
,
ATI_REMOTE2_PC
,
ATI_REMOTE2_MODES
,
};
static
const
struct
{
u8
hw_code
;
u16
keycode
;
}
ati_remote2_key_table
[]
=
{
{
0x00
,
KEY_0
},
{
0x01
,
KEY_1
},
...
...
@@ -73,6 +89,7 @@ static struct {
{
0x37
,
KEY_RECORD
},
{
0x38
,
KEY_DVD
},
{
0x39
,
KEY_TV
},
{
0x3f
,
KEY_PROG1
},
/* AUX1-AUX4 and PC */
{
0x54
,
KEY_MENU
},
{
0x58
,
KEY_UP
},
{
0x59
,
KEY_DOWN
},
...
...
@@ -91,15 +108,9 @@ static struct {
{
0xa9
,
BTN_LEFT
},
{
0xaa
,
BTN_RIGHT
},
{
0xbe
,
KEY_QUESTION
},
{
0xd5
,
KEY_FRONT
},
{
0xd0
,
KEY_EDIT
},
{
0xd5
,
KEY_FRONT
},
{
0xf9
,
KEY_INFO
},
{
(
0x00
<<
8
)
|
0x3f
,
KEY_PROG1
},
{
(
0x01
<<
8
)
|
0x3f
,
KEY_PROG2
},
{
(
0x02
<<
8
)
|
0x3f
,
KEY_PROG3
},
{
(
0x03
<<
8
)
|
0x3f
,
KEY_PROG4
},
{
(
0x04
<<
8
)
|
0x3f
,
KEY_PC
},
{
0
,
KEY_RESERVED
}
};
struct
ati_remote2
{
...
...
@@ -117,46 +128,106 @@ struct ati_remote2 {
char
name
[
64
];
char
phys
[
64
];
/* Each mode (AUX1-AUX4 and PC) can have an independent keymap. */
u16
keycode
[
ATI_REMOTE2_MODES
][
ARRAY_SIZE
(
ati_remote2_key_table
)];
unsigned
int
flags
;
};
static
int
ati_remote2_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
);
static
void
ati_remote2_disconnect
(
struct
usb_interface
*
interface
);
static
int
ati_remote2_suspend
(
struct
usb_interface
*
interface
,
pm_message_t
message
);
static
int
ati_remote2_resume
(
struct
usb_interface
*
interface
);
static
struct
usb_driver
ati_remote2_driver
=
{
.
name
=
"ati_remote2"
,
.
probe
=
ati_remote2_probe
,
.
disconnect
=
ati_remote2_disconnect
,
.
id_table
=
ati_remote2_id_table
,
.
suspend
=
ati_remote2_suspend
,
.
resume
=
ati_remote2_resume
,
.
supports_autosuspend
=
1
,
};
static
int
ati_remote2_
open
(
struct
input_dev
*
idev
)
static
int
ati_remote2_
submit_urbs
(
struct
ati_remote2
*
ar2
)
{
struct
ati_remote2
*
ar2
=
input_get_drvdata
(
idev
);
int
r
;
r
=
usb_submit_urb
(
ar2
->
urb
[
0
],
GFP_KERNEL
);
if
(
r
)
{
dev_err
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s: usb_submit_urb() = %d
\n
"
,
__func__
,
r
);
"%s
()
: usb_submit_urb() = %d
\n
"
,
__func__
,
r
);
return
r
;
}
r
=
usb_submit_urb
(
ar2
->
urb
[
1
],
GFP_KERNEL
);
if
(
r
)
{
usb_kill_urb
(
ar2
->
urb
[
0
]);
dev_err
(
&
ar2
->
intf
[
1
]
->
dev
,
"%s: usb_submit_urb() = %d
\n
"
,
__func__
,
r
);
"%s
()
: usb_submit_urb() = %d
\n
"
,
__func__
,
r
);
return
r
;
}
return
0
;
}
static
void
ati_remote2_kill_urbs
(
struct
ati_remote2
*
ar2
)
{
usb_kill_urb
(
ar2
->
urb
[
1
]);
usb_kill_urb
(
ar2
->
urb
[
0
]);
}
static
int
ati_remote2_open
(
struct
input_dev
*
idev
)
{
struct
ati_remote2
*
ar2
=
input_get_drvdata
(
idev
);
int
r
;
dev_dbg
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s()
\n
"
,
__func__
);
r
=
usb_autopm_get_interface
(
ar2
->
intf
[
0
]);
if
(
r
)
{
dev_err
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s(): usb_autopm_get_interface() = %d
\n
"
,
__func__
,
r
);
goto
fail1
;
}
mutex_lock
(
&
ati_remote2_mutex
);
if
(
!
(
ar2
->
flags
&
ATI_REMOTE2_SUSPENDED
))
{
r
=
ati_remote2_submit_urbs
(
ar2
);
if
(
r
)
goto
fail2
;
}
ar2
->
flags
|=
ATI_REMOTE2_OPENED
;
mutex_unlock
(
&
ati_remote2_mutex
);
usb_autopm_put_interface
(
ar2
->
intf
[
0
]);
return
0
;
fail2:
mutex_unlock
(
&
ati_remote2_mutex
);
usb_autopm_put_interface
(
ar2
->
intf
[
0
]);
fail1:
return
r
;
}
static
void
ati_remote2_close
(
struct
input_dev
*
idev
)
{
struct
ati_remote2
*
ar2
=
input_get_drvdata
(
idev
);
usb_kill_urb
(
ar2
->
urb
[
0
]);
usb_kill_urb
(
ar2
->
urb
[
1
]);
dev_dbg
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s()
\n
"
,
__func__
);
mutex_lock
(
&
ati_remote2_mutex
);
if
(
!
(
ar2
->
flags
&
ATI_REMOTE2_SUSPENDED
))
ati_remote2_kill_urbs
(
ar2
);
ar2
->
flags
&=
~
ATI_REMOTE2_OPENED
;
mutex_unlock
(
&
ati_remote2_mutex
);
}
static
void
ati_remote2_input_mouse
(
struct
ati_remote2
*
ar2
)
...
...
@@ -172,7 +243,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2)
mode
=
data
[
0
]
&
0x0F
;
if
(
mode
>
4
)
{
if
(
mode
>
ATI_REMOTE2_PC
)
{
dev_err
(
&
ar2
->
intf
[
0
]
->
dev
,
"Unknown mode byte (%02x %02x %02x %02x)
\n
"
,
data
[
3
],
data
[
2
],
data
[
1
],
data
[
0
]);
...
...
@@ -191,7 +262,7 @@ static int ati_remote2_lookup(unsigned int hw_code)
{
int
i
;
for
(
i
=
0
;
ati_remote2_key_table
[
i
].
key_code
!=
KEY_RESERVED
;
i
++
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
ati_remote2_key_table
)
;
i
++
)
if
(
ati_remote2_key_table
[
i
].
hw_code
==
hw_code
)
return
i
;
...
...
@@ -211,7 +282,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
mode
=
data
[
0
]
&
0x0F
;
if
(
mode
>
4
)
{
if
(
mode
>
ATI_REMOTE2_PC
)
{
dev_err
(
&
ar2
->
intf
[
1
]
->
dev
,
"Unknown mode byte (%02x %02x %02x %02x)
\n
"
,
data
[
3
],
data
[
2
],
data
[
1
],
data
[
0
]);
...
...
@@ -219,10 +290,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
}
hw_code
=
data
[
2
];
/*
* Mode keys (AUX1-AUX4, PC) all generate the same code byte.
* Use the mode byte to figure out which one was pressed.
*/
if
(
hw_code
==
0x3f
)
{
/*
* For some incomprehensible reason the mouse pad generates
...
...
@@ -236,8 +303,6 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
if
(
data
[
1
]
==
0
)
ar2
->
mode
=
mode
;
hw_code
|=
mode
<<
8
;
}
if
(
!
((
1
<<
mode
)
&
mode_mask
))
...
...
@@ -260,8 +325,8 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
case
2
:
/* repeat */
/* No repeat for mouse buttons. */
if
(
a
ti_remote2_key_table
[
index
].
key_code
==
BTN_LEFT
||
a
ti_remote2_key_table
[
index
].
key_code
==
BTN_RIGHT
)
if
(
a
r2
->
keycode
[
mode
][
index
]
==
BTN_LEFT
||
a
r2
->
keycode
[
mode
][
index
]
==
BTN_RIGHT
)
return
;
if
(
!
time_after_eq
(
jiffies
,
ar2
->
jiffies
))
...
...
@@ -276,7 +341,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2)
return
;
}
input_event
(
idev
,
EV_KEY
,
a
ti_remote2_key_table
[
index
].
key_code
,
data
[
1
]);
input_event
(
idev
,
EV_KEY
,
a
r2
->
keycode
[
mode
][
index
]
,
data
[
1
]);
input_sync
(
idev
);
}
...
...
@@ -287,6 +352,7 @@ static void ati_remote2_complete_mouse(struct urb *urb)
switch
(
urb
->
status
)
{
case
0
:
usb_mark_last_busy
(
ar2
->
udev
);
ati_remote2_input_mouse
(
ar2
);
break
;
case
-
ENOENT
:
...
...
@@ -297,6 +363,7 @@ static void ati_remote2_complete_mouse(struct urb *urb)
"%s(): urb status = %d
\n
"
,
__func__
,
urb
->
status
);
return
;
default:
usb_mark_last_busy
(
ar2
->
udev
);
dev_err
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s(): urb status = %d
\n
"
,
__func__
,
urb
->
status
);
}
...
...
@@ -314,6 +381,7 @@ static void ati_remote2_complete_key(struct urb *urb)
switch
(
urb
->
status
)
{
case
0
:
usb_mark_last_busy
(
ar2
->
udev
);
ati_remote2_input_key
(
ar2
);
break
;
case
-
ENOENT
:
...
...
@@ -324,6 +392,7 @@ static void ati_remote2_complete_key(struct urb *urb)
"%s(): urb status = %d
\n
"
,
__func__
,
urb
->
status
);
return
;
default:
usb_mark_last_busy
(
ar2
->
udev
);
dev_err
(
&
ar2
->
intf
[
1
]
->
dev
,
"%s(): urb status = %d
\n
"
,
__func__
,
urb
->
status
);
}
...
...
@@ -334,10 +403,60 @@ static void ati_remote2_complete_key(struct urb *urb)
"%s(): usb_submit_urb() = %d
\n
"
,
__func__
,
r
);
}
static
int
ati_remote2_getkeycode
(
struct
input_dev
*
idev
,
int
scancode
,
int
*
keycode
)
{
struct
ati_remote2
*
ar2
=
input_get_drvdata
(
idev
);
int
index
,
mode
;
mode
=
scancode
>>
8
;
if
(
mode
>
ATI_REMOTE2_PC
||
!
((
1
<<
mode
)
&
mode_mask
))
return
-
EINVAL
;
index
=
ati_remote2_lookup
(
scancode
&
0xFF
);
if
(
index
<
0
)
return
-
EINVAL
;
*
keycode
=
ar2
->
keycode
[
mode
][
index
];
return
0
;
}
static
int
ati_remote2_setkeycode
(
struct
input_dev
*
idev
,
int
scancode
,
int
keycode
)
{
struct
ati_remote2
*
ar2
=
input_get_drvdata
(
idev
);
int
index
,
mode
,
old_keycode
;
mode
=
scancode
>>
8
;
if
(
mode
>
ATI_REMOTE2_PC
||
!
((
1
<<
mode
)
&
mode_mask
))
return
-
EINVAL
;
index
=
ati_remote2_lookup
(
scancode
&
0xFF
);
if
(
index
<
0
)
return
-
EINVAL
;
if
(
keycode
<
KEY_RESERVED
||
keycode
>
KEY_MAX
)
return
-
EINVAL
;
old_keycode
=
ar2
->
keycode
[
mode
][
index
];
ar2
->
keycode
[
mode
][
index
]
=
keycode
;
set_bit
(
keycode
,
idev
->
keybit
);
for
(
mode
=
0
;
mode
<
ATI_REMOTE2_MODES
;
mode
++
)
{
for
(
index
=
0
;
index
<
ARRAY_SIZE
(
ati_remote2_key_table
);
index
++
)
{
if
(
ar2
->
keycode
[
mode
][
index
]
==
old_keycode
)
return
0
;
}
}
clear_bit
(
old_keycode
,
idev
->
keybit
);
return
0
;
}
static
int
ati_remote2_input_init
(
struct
ati_remote2
*
ar2
)
{
struct
input_dev
*
idev
;
int
i
,
retval
;
int
i
ndex
,
mode
,
retval
;
idev
=
input_allocate_device
();
if
(
!
idev
)
...
...
@@ -350,8 +469,26 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
idev
->
keybit
[
BIT_WORD
(
BTN_MOUSE
)]
=
BIT_MASK
(
BTN_LEFT
)
|
BIT_MASK
(
BTN_RIGHT
);
idev
->
relbit
[
0
]
=
BIT_MASK
(
REL_X
)
|
BIT_MASK
(
REL_Y
);
for
(
i
=
0
;
ati_remote2_key_table
[
i
].
key_code
!=
KEY_RESERVED
;
i
++
)
set_bit
(
ati_remote2_key_table
[
i
].
key_code
,
idev
->
keybit
);
for
(
mode
=
0
;
mode
<
ATI_REMOTE2_MODES
;
mode
++
)
{
for
(
index
=
0
;
index
<
ARRAY_SIZE
(
ati_remote2_key_table
);
index
++
)
{
ar2
->
keycode
[
mode
][
index
]
=
ati_remote2_key_table
[
index
].
keycode
;
set_bit
(
ar2
->
keycode
[
mode
][
index
],
idev
->
keybit
);
}
}
/* AUX1-AUX4 and PC generate the same scancode. */
index
=
ati_remote2_lookup
(
0x3f
);
ar2
->
keycode
[
ATI_REMOTE2_AUX1
][
index
]
=
KEY_PROG1
;
ar2
->
keycode
[
ATI_REMOTE2_AUX2
][
index
]
=
KEY_PROG2
;
ar2
->
keycode
[
ATI_REMOTE2_AUX3
][
index
]
=
KEY_PROG3
;
ar2
->
keycode
[
ATI_REMOTE2_AUX4
][
index
]
=
KEY_PROG4
;
ar2
->
keycode
[
ATI_REMOTE2_PC
][
index
]
=
KEY_PC
;
set_bit
(
KEY_PROG1
,
idev
->
keybit
);
set_bit
(
KEY_PROG2
,
idev
->
keybit
);
set_bit
(
KEY_PROG3
,
idev
->
keybit
);
set_bit
(
KEY_PROG4
,
idev
->
keybit
);
set_bit
(
KEY_PC
,
idev
->
keybit
);
idev
->
rep
[
REP_DELAY
]
=
250
;
idev
->
rep
[
REP_PERIOD
]
=
33
;
...
...
@@ -359,6 +496,9 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
idev
->
open
=
ati_remote2_open
;
idev
->
close
=
ati_remote2_close
;
idev
->
getkeycode
=
ati_remote2_getkeycode
;
idev
->
setkeycode
=
ati_remote2_setkeycode
;
idev
->
name
=
ar2
->
name
;
idev
->
phys
=
ar2
->
phys
;
...
...
@@ -490,6 +630,8 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d
usb_set_intfdata
(
interface
,
ar2
);
interface
->
needs_remote_wakeup
=
1
;
return
0
;
fail2:
...
...
@@ -522,6 +664,57 @@ static void ati_remote2_disconnect(struct usb_interface *interface)
kfree
(
ar2
);
}
static
int
ati_remote2_suspend
(
struct
usb_interface
*
interface
,
pm_message_t
message
)
{
struct
ati_remote2
*
ar2
;
struct
usb_host_interface
*
alt
=
interface
->
cur_altsetting
;
if
(
alt
->
desc
.
bInterfaceNumber
)
return
0
;
ar2
=
usb_get_intfdata
(
interface
);
dev_dbg
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s()
\n
"
,
__func__
);
mutex_lock
(
&
ati_remote2_mutex
);
if
(
ar2
->
flags
&
ATI_REMOTE2_OPENED
)
ati_remote2_kill_urbs
(
ar2
);
ar2
->
flags
|=
ATI_REMOTE2_SUSPENDED
;
mutex_unlock
(
&
ati_remote2_mutex
);
return
0
;
}
static
int
ati_remote2_resume
(
struct
usb_interface
*
interface
)
{
struct
ati_remote2
*
ar2
;
struct
usb_host_interface
*
alt
=
interface
->
cur_altsetting
;
int
r
=
0
;
if
(
alt
->
desc
.
bInterfaceNumber
)
return
0
;
ar2
=
usb_get_intfdata
(
interface
);
dev_dbg
(
&
ar2
->
intf
[
0
]
->
dev
,
"%s()
\n
"
,
__func__
);
mutex_lock
(
&
ati_remote2_mutex
);
if
(
ar2
->
flags
&
ATI_REMOTE2_OPENED
)
r
=
ati_remote2_submit_urbs
(
ar2
);
if
(
!
r
)
ar2
->
flags
&=
~
ATI_REMOTE2_SUSPENDED
;
mutex_unlock
(
&
ati_remote2_mutex
);
return
r
;
}
static
int
__init
ati_remote2_init
(
void
)
{
int
r
;
...
...
drivers/input/misc/cm109.c
0 → 100644
View file @
4c0e799a
/*
* Driver for the VoIP USB phones with CM109 chipsets.
*
* Copyright (C) 2007 - 2008 Alfred E. Heggestad <aeh@db.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, version 2.
*/
/*
* Tested devices:
* - Komunikate KIP1000
* - Genius G-talk
* - Allied-Telesis Corega USBPH01
* - ...
*
* This driver is based on the yealink.c driver
*
* Thanks to:
* - Authors of yealink.c
* - Thomas Reitmayr
* - Oliver Neukum for good review comments and code
* - Shaun Jackman <sjackman@gmail.com> for Genius G-talk keymap
* - Dmitry Torokhov for valuable input and review
*
* Todo:
* - Read/write EEPROM
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/rwsem.h>
#include <linux/usb/input.h>
#define DRIVER_VERSION "20080805"
#define DRIVER_AUTHOR "Alfred E. Heggestad"
#define DRIVER_DESC "CM109 phone driver"
static
char
*
phone
=
"kip1000"
;
module_param
(
phone
,
charp
,
S_IRUSR
);
MODULE_PARM_DESC
(
phone
,
"Phone name {kip1000, gtalk, usbph01}"
);
enum
{
/* HID Registers */
HID_IR0
=
0x00
,
/* Record/Playback-mute button, Volume up/down */
HID_IR1
=
0x01
,
/* GPI, generic registers or EEPROM_DATA0 */
HID_IR2
=
0x02
,
/* Generic registers or EEPROM_DATA1 */
HID_IR3
=
0x03
,
/* Generic registers or EEPROM_CTRL */
HID_OR0
=
0x00
,
/* Mapping control, buzzer, SPDIF (offset 0x04) */
HID_OR1
=
0x01
,
/* GPO - General Purpose Output */
HID_OR2
=
0x02
,
/* Set GPIO to input/output mode */
HID_OR3
=
0x03
,
/* SPDIF status channel or EEPROM_CTRL */
/* HID_IR0 */
RECORD_MUTE
=
1
<<
3
,
PLAYBACK_MUTE
=
1
<<
2
,
VOLUME_DOWN
=
1
<<
1
,
VOLUME_UP
=
1
<<
0
,
/* HID_OR0 */
/* bits 7-6
0: HID_OR1-2 are used for GPO; HID_OR0, 3 are used for buzzer
and SPDIF
1: HID_OR0-3 are used as generic HID registers
2: Values written to HID_OR0-3 are also mapped to MCU_CTRL,
EEPROM_DATA0-1, EEPROM_CTRL (see Note)
3: Reserved
*/
HID_OR_GPO_BUZ_SPDIF
=
0
<<
6
,
HID_OR_GENERIC_HID_REG
=
1
<<
6
,
HID_OR_MAP_MCU_EEPROM
=
2
<<
6
,
BUZZER_ON
=
1
<<
5
,
/* up to 256 normal keys, up to 16 special keys */
KEYMAP_SIZE
=
256
+
16
,
};
/* CM109 protocol packet */
struct
cm109_ctl_packet
{
u8
byte
[
4
];
}
__attribute__
((
packed
));
enum
{
USB_PKT_LEN
=
sizeof
(
struct
cm109_ctl_packet
)
};
/* CM109 device structure */
struct
cm109_dev
{
struct
input_dev
*
idev
;
/* input device */
struct
usb_device
*
udev
;
/* usb device */
struct
usb_interface
*
intf
;
/* irq input channel */
struct
cm109_ctl_packet
*
irq_data
;
dma_addr_t
irq_dma
;
struct
urb
*
urb_irq
;
/* control output channel */
struct
cm109_ctl_packet
*
ctl_data
;
dma_addr_t
ctl_dma
;
struct
usb_ctrlrequest
*
ctl_req
;
dma_addr_t
ctl_req_dma
;
struct
urb
*
urb_ctl
;
/*
* The 3 bitfields below are protected by ctl_submit_lock.
* They have to be separate since they are accessed from IRQ
* context.
*/
unsigned
irq_urb_pending
:
1
;
/* irq_urb is in flight */
unsigned
ctl_urb_pending
:
1
;
/* ctl_urb is in flight */
unsigned
buzzer_pending
:
1
;
/* need to issue buzz command */
spinlock_t
ctl_submit_lock
;
unsigned
char
buzzer_state
;
/* on/off */
/* flags */
unsigned
open
:
1
;
unsigned
resetting
:
1
;
unsigned
shutdown
:
1
;
/* This mutex protects writes to the above flags */
struct
mutex
pm_mutex
;
unsigned
short
keymap
[
KEYMAP_SIZE
];
char
phys
[
64
];
/* physical device path */
int
key_code
;
/* last reported key */
int
keybit
;
/* 0=new scan 1,2,4,8=scan columns */
u8
gpi
;
/* Cached value of GPI (high nibble) */
};
/******************************************************************************
* CM109 key interface
*****************************************************************************/
static
unsigned
short
special_keymap
(
int
code
)
{
if
(
code
>
0xff
)
{
switch
(
code
-
0xff
)
{
case
RECORD_MUTE
:
return
KEY_MUTE
;
case
PLAYBACK_MUTE
:
return
KEY_MUTE
;
case
VOLUME_DOWN
:
return
KEY_VOLUMEDOWN
;
case
VOLUME_UP
:
return
KEY_VOLUMEUP
;
}
}
return
KEY_RESERVED
;
}
/* Map device buttons to internal key events.
*
* The "up" and "down" keys, are symbolised by arrows on the button.
* The "pickup" and "hangup" keys are symbolised by a green and red phone
* on the button.
Komunikate KIP1000 Keyboard Matrix
-> -- 1 -- 2 -- 3 --> GPI pin 4 (0x10)
| | | |
<- -- 4 -- 5 -- 6 --> GPI pin 5 (0x20)
| | | |
END - 7 -- 8 -- 9 --> GPI pin 6 (0x40)
| | | |
OK -- * -- 0 -- # --> GPI pin 7 (0x80)
| | | |
/|\ /|\ /|\ /|\
| | | |
GPO
pin: 3 2 1 0
0x8 0x4 0x2 0x1
*/
static
unsigned
short
keymap_kip1000
(
int
scancode
)
{
switch
(
scancode
)
{
/* phone key: */
case
0x82
:
return
KEY_NUMERIC_0
;
/* 0 */
case
0x14
:
return
KEY_NUMERIC_1
;
/* 1 */
case
0x12
:
return
KEY_NUMERIC_2
;
/* 2 */
case
0x11
:
return
KEY_NUMERIC_3
;
/* 3 */
case
0x24
:
return
KEY_NUMERIC_4
;
/* 4 */
case
0x22
:
return
KEY_NUMERIC_5
;
/* 5 */
case
0x21
:
return
KEY_NUMERIC_6
;
/* 6 */
case
0x44
:
return
KEY_NUMERIC_7
;
/* 7 */
case
0x42
:
return
KEY_NUMERIC_8
;
/* 8 */
case
0x41
:
return
KEY_NUMERIC_9
;
/* 9 */
case
0x81
:
return
KEY_NUMERIC_POUND
;
/* # */
case
0x84
:
return
KEY_NUMERIC_STAR
;
/* * */
case
0x88
:
return
KEY_ENTER
;
/* pickup */
case
0x48
:
return
KEY_ESC
;
/* hangup */
case
0x28
:
return
KEY_LEFT
;
/* IN */
case
0x18
:
return
KEY_RIGHT
;
/* OUT */
default:
return
special_keymap
(
scancode
);
}
}
/*
Contributed by Shaun Jackman <sjackman@gmail.com>
Genius G-Talk keyboard matrix
0 1 2 3
4: 0 4 8 Talk
5: 1 5 9 End
6: 2 6 # Up
7: 3 7 * Down
*/
static
unsigned
short
keymap_gtalk
(
int
scancode
)
{
switch
(
scancode
)
{
case
0x11
:
return
KEY_NUMERIC_0
;
case
0x21
:
return
KEY_NUMERIC_1
;
case
0x41
:
return
KEY_NUMERIC_2
;
case
0x81
:
return
KEY_NUMERIC_3
;
case
0x12
:
return
KEY_NUMERIC_4
;
case
0x22
:
return
KEY_NUMERIC_5
;
case
0x42
:
return
KEY_NUMERIC_6
;
case
0x82
:
return
KEY_NUMERIC_7
;
case
0x14
:
return
KEY_NUMERIC_8
;
case
0x24
:
return
KEY_NUMERIC_9
;
case
0x44
:
return
KEY_NUMERIC_POUND
;
/* # */
case
0x84
:
return
KEY_NUMERIC_STAR
;
/* * */
case
0x18
:
return
KEY_ENTER
;
/* Talk (green handset) */
case
0x28
:
return
KEY_ESC
;
/* End (red handset) */
case
0x48
:
return
KEY_UP
;
/* Menu up (rocker switch) */
case
0x88
:
return
KEY_DOWN
;
/* Menu down (rocker switch) */
default:
return
special_keymap
(
scancode
);
}
}
/*
* Keymap for Allied-Telesis Corega USBPH01
* http://www.alliedtelesis-corega.com/2/1344/1437/1360/chprd.html
*
* Contributed by july@nat.bg
*/
static
unsigned
short
keymap_usbph01
(
int
scancode
)
{
switch
(
scancode
)
{
case
0x11
:
return
KEY_NUMERIC_0
;
/* 0 */
case
0x21
:
return
KEY_NUMERIC_1
;
/* 1 */
case
0x41
:
return
KEY_NUMERIC_2
;
/* 2 */
case
0x81
:
return
KEY_NUMERIC_3
;
/* 3 */
case
0x12
:
return
KEY_NUMERIC_4
;
/* 4 */
case
0x22
:
return
KEY_NUMERIC_5
;
/* 5 */
case
0x42
:
return
KEY_NUMERIC_6
;
/* 6 */
case
0x82
:
return
KEY_NUMERIC_7
;
/* 7 */
case
0x14
:
return
KEY_NUMERIC_8
;
/* 8 */
case
0x24
:
return
KEY_NUMERIC_9
;
/* 9 */
case
0x44
:
return
KEY_NUMERIC_POUND
;
/* # */
case
0x84
:
return
KEY_NUMERIC_STAR
;
/* * */
case
0x18
:
return
KEY_ENTER
;
/* pickup */
case
0x28
:
return
KEY_ESC
;
/* hangup */
case
0x48
:
return
KEY_LEFT
;
/* IN */
case
0x88
:
return
KEY_RIGHT
;
/* OUT */
default:
return
special_keymap
(
scancode
);
}
}
static
unsigned
short
(
*
keymap
)(
int
)
=
keymap_kip1000
;
/*
* Completes a request by converting the data into events for the
* input subsystem.
*/
static
void
report_key
(
struct
cm109_dev
*
dev
,
int
key
)
{
struct
input_dev
*
idev
=
dev
->
idev
;
if
(
dev
->
key_code
>=
0
)
{
/* old key up */
input_report_key
(
idev
,
dev
->
key_code
,
0
);
}
dev
->
key_code
=
key
;
if
(
key
>=
0
)
{
/* new valid key */
input_report_key
(
idev
,
key
,
1
);
}
input_sync
(
idev
);
}
/******************************************************************************
* CM109 usb communication interface
*****************************************************************************/
static
void
cm109_submit_buzz_toggle
(
struct
cm109_dev
*
dev
)
{
int
error
;
if
(
dev
->
buzzer_state
)
dev
->
ctl_data
->
byte
[
HID_OR0
]
|=
BUZZER_ON
;
else
dev
->
ctl_data
->
byte
[
HID_OR0
]
&=
~
BUZZER_ON
;
error
=
usb_submit_urb
(
dev
->
urb_ctl
,
GFP_ATOMIC
);
if
(
error
)
err
(
"%s: usb_submit_urb (urb_ctl) failed %d"
,
__func__
,
error
);
}
/*
* IRQ handler
*/
static
void
cm109_urb_irq_callback
(
struct
urb
*
urb
)
{
struct
cm109_dev
*
dev
=
urb
->
context
;
const
int
status
=
urb
->
status
;
int
error
;
dev_dbg
(
&
urb
->
dev
->
dev
,
"### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x
\n
"
,
dev
->
irq_data
->
byte
[
0
],
dev
->
irq_data
->
byte
[
1
],
dev
->
irq_data
->
byte
[
2
],
dev
->
irq_data
->
byte
[
3
],
dev
->
keybit
);
if
(
status
)
{
if
(
status
==
-
ESHUTDOWN
)
return
;
err
(
"%s: urb status %d"
,
__func__
,
status
);
}
/* Special keys */
if
(
dev
->
irq_data
->
byte
[
HID_IR0
]
&
0x0f
)
{
const
int
code
=
(
dev
->
irq_data
->
byte
[
HID_IR0
]
&
0x0f
);
report_key
(
dev
,
dev
->
keymap
[
0xff
+
code
]);
}
/* Scan key column */
if
(
dev
->
keybit
==
0xf
)
{
/* Any changes ? */
if
((
dev
->
gpi
&
0xf0
)
==
(
dev
->
irq_data
->
byte
[
HID_IR1
]
&
0xf0
))
goto
out
;
dev
->
gpi
=
dev
->
irq_data
->
byte
[
HID_IR1
]
&
0xf0
;
dev
->
keybit
=
0x1
;
}
else
{
report_key
(
dev
,
dev
->
keymap
[
dev
->
irq_data
->
byte
[
HID_IR1
]]);
dev
->
keybit
<<=
1
;
if
(
dev
->
keybit
>
0x8
)
dev
->
keybit
=
0xf
;
}
out:
spin_lock
(
&
dev
->
ctl_submit_lock
);
dev
->
irq_urb_pending
=
0
;
if
(
likely
(
!
dev
->
shutdown
))
{
if
(
dev
->
buzzer_state
)
dev
->
ctl_data
->
byte
[
HID_OR0
]
|=
BUZZER_ON
;
else
dev
->
ctl_data
->
byte
[
HID_OR0
]
&=
~
BUZZER_ON
;
dev
->
ctl_data
->
byte
[
HID_OR1
]
=
dev
->
keybit
;
dev
->
ctl_data
->
byte
[
HID_OR2
]
=
dev
->
keybit
;
dev
->
buzzer_pending
=
0
;
dev
->
ctl_urb_pending
=
1
;
error
=
usb_submit_urb
(
dev
->
urb_ctl
,
GFP_ATOMIC
);
if
(
error
)
err
(
"%s: usb_submit_urb (urb_ctl) failed %d"
,
__func__
,
error
);
}
spin_unlock
(
&
dev
->
ctl_submit_lock
);
}
static
void
cm109_urb_ctl_callback
(
struct
urb
*
urb
)
{
struct
cm109_dev
*
dev
=
urb
->
context
;
const
int
status
=
urb
->
status
;
int
error
;
dev_dbg
(
&
urb
->
dev
->
dev
,
"### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]
\n
"
,
dev
->
ctl_data
->
byte
[
0
],
dev
->
ctl_data
->
byte
[
1
],
dev
->
ctl_data
->
byte
[
2
],
dev
->
ctl_data
->
byte
[
3
]);
if
(
status
)
err
(
"%s: urb status %d"
,
__func__
,
status
);
spin_lock
(
&
dev
->
ctl_submit_lock
);
dev
->
ctl_urb_pending
=
0
;
if
(
likely
(
!
dev
->
shutdown
))
{
if
(
dev
->
buzzer_pending
)
{
dev
->
buzzer_pending
=
0
;
dev
->
ctl_urb_pending
=
1
;
cm109_submit_buzz_toggle
(
dev
);
}
else
if
(
likely
(
!
dev
->
irq_urb_pending
))
{
/* ask for key data */
dev
->
irq_urb_pending
=
1
;
error
=
usb_submit_urb
(
dev
->
urb_irq
,
GFP_ATOMIC
);
if
(
error
)
err
(
"%s: usb_submit_urb (urb_irq) failed %d"
,
__func__
,
error
);
}
}
spin_unlock
(
&
dev
->
ctl_submit_lock
);
}
static
void
cm109_toggle_buzzer_async
(
struct
cm109_dev
*
dev
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
dev
->
ctl_submit_lock
,
flags
);
if
(
dev
->
ctl_urb_pending
)
{
/* URB completion will resubmit */
dev
->
buzzer_pending
=
1
;
}
else
{
dev
->
ctl_urb_pending
=
1
;
cm109_submit_buzz_toggle
(
dev
);
}
spin_unlock_irqrestore
(
&
dev
->
ctl_submit_lock
,
flags
);
}
static
void
cm109_toggle_buzzer_sync
(
struct
cm109_dev
*
dev
,
int
on
)
{
int
error
;
if
(
on
)
dev
->
ctl_data
->
byte
[
HID_OR0
]
|=
BUZZER_ON
;
else
dev
->
ctl_data
->
byte
[
HID_OR0
]
&=
~
BUZZER_ON
;
error
=
usb_control_msg
(
dev
->
udev
,
usb_sndctrlpipe
(
dev
->
udev
,
0
),
dev
->
ctl_req
->
bRequest
,
dev
->
ctl_req
->
bRequestType
,
le16_to_cpu
(
dev
->
ctl_req
->
wValue
),
le16_to_cpu
(
dev
->
ctl_req
->
wIndex
),
dev
->
ctl_data
,
USB_PKT_LEN
,
USB_CTRL_SET_TIMEOUT
);
if
(
error
&&
error
!=
EINTR
)
err
(
"%s: usb_control_msg() failed %d"
,
__func__
,
error
);
}
static
void
cm109_stop_traffic
(
struct
cm109_dev
*
dev
)
{
dev
->
shutdown
=
1
;
/*
* Make sure other CPUs see this
*/
smp_wmb
();
usb_kill_urb
(
dev
->
urb_ctl
);
usb_kill_urb
(
dev
->
urb_irq
);
cm109_toggle_buzzer_sync
(
dev
,
0
);
dev
->
shutdown
=
0
;
smp_wmb
();
}
static
void
cm109_restore_state
(
struct
cm109_dev
*
dev
)
{
if
(
dev
->
open
)
{
/*
* Restore buzzer state.
* This will also kick regular URB submission
*/
cm109_toggle_buzzer_async
(
dev
);
}
}
/******************************************************************************
* input event interface
*****************************************************************************/
static
int
cm109_input_open
(
struct
input_dev
*
idev
)
{
struct
cm109_dev
*
dev
=
input_get_drvdata
(
idev
);
int
error
;
error
=
usb_autopm_get_interface
(
dev
->
intf
);
if
(
error
<
0
)
{
err
(
"%s - cannot autoresume, result %d"
,
__func__
,
error
);
return
error
;
}
mutex_lock
(
&
dev
->
pm_mutex
);
dev
->
buzzer_state
=
0
;
dev
->
key_code
=
-
1
;
/* no keys pressed */
dev
->
keybit
=
0xf
;
/* issue INIT */
dev
->
ctl_data
->
byte
[
HID_OR0
]
=
HID_OR_GPO_BUZ_SPDIF
;
dev
->
ctl_data
->
byte
[
HID_OR1
]
=
dev
->
keybit
;
dev
->
ctl_data
->
byte
[
HID_OR2
]
=
dev
->
keybit
;
dev
->
ctl_data
->
byte
[
HID_OR3
]
=
0x00
;
error
=
usb_submit_urb
(
dev
->
urb_ctl
,
GFP_KERNEL
);
if
(
error
)
err
(
"%s: usb_submit_urb (urb_ctl) failed %d"
,
__func__
,
error
);
else
dev
->
open
=
1
;
mutex_unlock
(
&
dev
->
pm_mutex
);
if
(
error
)
usb_autopm_put_interface
(
dev
->
intf
);
return
error
;
}
static
void
cm109_input_close
(
struct
input_dev
*
idev
)
{
struct
cm109_dev
*
dev
=
input_get_drvdata
(
idev
);
mutex_lock
(
&
dev
->
pm_mutex
);
/*
* Once we are here event delivery is stopped so we
* don't need to worry about someone starting buzzer
* again
*/
cm109_stop_traffic
(
dev
);
dev
->
open
=
0
;
mutex_unlock
(
&
dev
->
pm_mutex
);
usb_autopm_put_interface
(
dev
->
intf
);
}
static
int
cm109_input_ev
(
struct
input_dev
*
idev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
struct
cm109_dev
*
dev
=
input_get_drvdata
(
idev
);
dev_dbg
(
&
dev
->
udev
->
dev
,
"input_ev: type=%u code=%u value=%d
\n
"
,
type
,
code
,
value
);
if
(
type
!=
EV_SND
)
return
-
EINVAL
;
switch
(
code
)
{
case
SND_TONE
:
case
SND_BELL
:
dev
->
buzzer_state
=
!!
value
;
if
(
!
dev
->
resetting
)
cm109_toggle_buzzer_async
(
dev
);
return
0
;
default:
return
-
EINVAL
;
}
}
/******************************************************************************
* Linux interface and usb initialisation
*****************************************************************************/
struct
driver_info
{
char
*
name
;
};
static
const
struct
driver_info
info_cm109
=
{
.
name
=
"CM109 USB driver"
,
};
enum
{
VENDOR_ID
=
0x0d8c
,
/* C-Media Electronics */
PRODUCT_ID_CM109
=
0x000e
,
/* CM109 defines range 0x0008 - 0x000f */
};
/* table of devices that work with this driver */
static
const
struct
usb_device_id
cm109_usb_table
[]
=
{
{
.
match_flags
=
USB_DEVICE_ID_MATCH_DEVICE
|
USB_DEVICE_ID_MATCH_INT_INFO
,
.
idVendor
=
VENDOR_ID
,
.
idProduct
=
PRODUCT_ID_CM109
,
.
bInterfaceClass
=
USB_CLASS_HID
,
.
bInterfaceSubClass
=
0
,
.
bInterfaceProtocol
=
0
,
.
driver_info
=
(
kernel_ulong_t
)
&
info_cm109
},
/* you can add more devices here with product ID 0x0008 - 0x000f */
{
}
};
static
void
cm109_usb_cleanup
(
struct
cm109_dev
*
dev
)
{
if
(
dev
->
ctl_req
)
usb_buffer_free
(
dev
->
udev
,
sizeof
(
*
(
dev
->
ctl_req
)),
dev
->
ctl_req
,
dev
->
ctl_req_dma
);
if
(
dev
->
ctl_data
)
usb_buffer_free
(
dev
->
udev
,
USB_PKT_LEN
,
dev
->
ctl_data
,
dev
->
ctl_dma
);
if
(
dev
->
irq_data
)
usb_buffer_free
(
dev
->
udev
,
USB_PKT_LEN
,
dev
->
irq_data
,
dev
->
irq_dma
);
usb_free_urb
(
dev
->
urb_irq
);
/* parameter validation in core/urb */
usb_free_urb
(
dev
->
urb_ctl
);
/* parameter validation in core/urb */
kfree
(
dev
);
}
static
void
cm109_usb_disconnect
(
struct
usb_interface
*
interface
)
{
struct
cm109_dev
*
dev
=
usb_get_intfdata
(
interface
);
usb_set_intfdata
(
interface
,
NULL
);
input_unregister_device
(
dev
->
idev
);
cm109_usb_cleanup
(
dev
);
}
static
int
cm109_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
udev
=
interface_to_usbdev
(
intf
);
struct
driver_info
*
nfo
=
(
struct
driver_info
*
)
id
->
driver_info
;
struct
usb_host_interface
*
interface
;
struct
usb_endpoint_descriptor
*
endpoint
;
struct
cm109_dev
*
dev
;
struct
input_dev
*
input_dev
=
NULL
;
int
ret
,
pipe
,
i
;
int
error
=
-
ENOMEM
;
interface
=
intf
->
cur_altsetting
;
endpoint
=
&
interface
->
endpoint
[
0
].
desc
;
if
(
!
usb_endpoint_is_int_in
(
endpoint
))
return
-
ENODEV
;
dev
=
kzalloc
(
sizeof
(
*
dev
),
GFP_KERNEL
);
if
(
!
dev
)
return
-
ENOMEM
;
spin_lock_init
(
&
dev
->
ctl_submit_lock
);
mutex_init
(
&
dev
->
pm_mutex
);
dev
->
udev
=
udev
;
dev
->
intf
=
intf
;
dev
->
idev
=
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
goto
err_out
;
/* allocate usb buffers */
dev
->
irq_data
=
usb_buffer_alloc
(
udev
,
USB_PKT_LEN
,
GFP_KERNEL
,
&
dev
->
irq_dma
);
if
(
!
dev
->
irq_data
)
goto
err_out
;
dev
->
ctl_data
=
usb_buffer_alloc
(
udev
,
USB_PKT_LEN
,
GFP_KERNEL
,
&
dev
->
ctl_dma
);
if
(
!
dev
->
ctl_data
)
goto
err_out
;
dev
->
ctl_req
=
usb_buffer_alloc
(
udev
,
sizeof
(
*
(
dev
->
ctl_req
)),
GFP_KERNEL
,
&
dev
->
ctl_req_dma
);
if
(
!
dev
->
ctl_req
)
goto
err_out
;
/* allocate urb structures */
dev
->
urb_irq
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
dev
->
urb_irq
)
goto
err_out
;
dev
->
urb_ctl
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
dev
->
urb_ctl
)
goto
err_out
;
/* get a handle to the interrupt data pipe */
pipe
=
usb_rcvintpipe
(
udev
,
endpoint
->
bEndpointAddress
);
ret
=
usb_maxpacket
(
udev
,
pipe
,
usb_pipeout
(
pipe
));
if
(
ret
!=
USB_PKT_LEN
)
err
(
"invalid payload size %d, expected %d"
,
ret
,
USB_PKT_LEN
);
/* initialise irq urb */
usb_fill_int_urb
(
dev
->
urb_irq
,
udev
,
pipe
,
dev
->
irq_data
,
USB_PKT_LEN
,
cm109_urb_irq_callback
,
dev
,
endpoint
->
bInterval
);
dev
->
urb_irq
->
transfer_dma
=
dev
->
irq_dma
;
dev
->
urb_irq
->
transfer_flags
|=
URB_NO_TRANSFER_DMA_MAP
;
dev
->
urb_irq
->
dev
=
udev
;
/* initialise ctl urb */
dev
->
ctl_req
->
bRequestType
=
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
|
USB_DIR_OUT
;
dev
->
ctl_req
->
bRequest
=
USB_REQ_SET_CONFIGURATION
;
dev
->
ctl_req
->
wValue
=
cpu_to_le16
(
0x200
);
dev
->
ctl_req
->
wIndex
=
cpu_to_le16
(
interface
->
desc
.
bInterfaceNumber
);
dev
->
ctl_req
->
wLength
=
cpu_to_le16
(
USB_PKT_LEN
);
usb_fill_control_urb
(
dev
->
urb_ctl
,
udev
,
usb_sndctrlpipe
(
udev
,
0
),
(
void
*
)
dev
->
ctl_req
,
dev
->
ctl_data
,
USB_PKT_LEN
,
cm109_urb_ctl_callback
,
dev
);
dev
->
urb_ctl
->
setup_dma
=
dev
->
ctl_req_dma
;
dev
->
urb_ctl
->
transfer_dma
=
dev
->
ctl_dma
;
dev
->
urb_ctl
->
transfer_flags
|=
URB_NO_SETUP_DMA_MAP
|
URB_NO_TRANSFER_DMA_MAP
;
dev
->
urb_ctl
->
dev
=
udev
;
/* find out the physical bus location */
usb_make_path
(
udev
,
dev
->
phys
,
sizeof
(
dev
->
phys
));
strlcat
(
dev
->
phys
,
"/input0"
,
sizeof
(
dev
->
phys
));
/* register settings for the input device */
input_dev
->
name
=
nfo
->
name
;
input_dev
->
phys
=
dev
->
phys
;
usb_to_input_id
(
udev
,
&
input_dev
->
id
);
input_dev
->
dev
.
parent
=
&
intf
->
dev
;
input_set_drvdata
(
input_dev
,
dev
);
input_dev
->
open
=
cm109_input_open
;
input_dev
->
close
=
cm109_input_close
;
input_dev
->
event
=
cm109_input_ev
;
input_dev
->
keycode
=
dev
->
keymap
;
input_dev
->
keycodesize
=
sizeof
(
unsigned
char
);
input_dev
->
keycodemax
=
ARRAY_SIZE
(
dev
->
keymap
);
input_dev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
)
|
BIT_MASK
(
EV_SND
);
input_dev
->
sndbit
[
0
]
=
BIT_MASK
(
SND_BELL
)
|
BIT_MASK
(
SND_TONE
);
/* register available key events */
for
(
i
=
0
;
i
<
KEYMAP_SIZE
;
i
++
)
{
unsigned
short
k
=
keymap
(
i
);
dev
->
keymap
[
i
]
=
k
;
__set_bit
(
k
,
input_dev
->
keybit
);
}
__clear_bit
(
KEY_RESERVED
,
input_dev
->
keybit
);
error
=
input_register_device
(
dev
->
idev
);
if
(
error
)
goto
err_out
;
usb_set_intfdata
(
intf
,
dev
);
return
0
;
err_out:
input_free_device
(
input_dev
);
cm109_usb_cleanup
(
dev
);
return
error
;
}
static
int
cm109_usb_suspend
(
struct
usb_interface
*
intf
,
pm_message_t
message
)
{
struct
cm109_dev
*
dev
=
usb_get_intfdata
(
intf
);
dev_info
(
&
intf
->
dev
,
"cm109: usb_suspend (event=%d)
\n
"
,
message
.
event
);
mutex_lock
(
&
dev
->
pm_mutex
);
cm109_stop_traffic
(
dev
);
mutex_unlock
(
&
dev
->
pm_mutex
);
return
0
;
}
static
int
cm109_usb_resume
(
struct
usb_interface
*
intf
)
{
struct
cm109_dev
*
dev
=
usb_get_intfdata
(
intf
);
dev_info
(
&
intf
->
dev
,
"cm109: usb_resume
\n
"
);
mutex_lock
(
&
dev
->
pm_mutex
);
cm109_restore_state
(
dev
);
mutex_unlock
(
&
dev
->
pm_mutex
);
return
0
;
}
static
int
cm109_usb_pre_reset
(
struct
usb_interface
*
intf
)
{
struct
cm109_dev
*
dev
=
usb_get_intfdata
(
intf
);
mutex_lock
(
&
dev
->
pm_mutex
);
/*
* Make sure input events don't try to toggle buzzer
* while we are resetting
*/
dev
->
resetting
=
1
;
smp_wmb
();
cm109_stop_traffic
(
dev
);
return
0
;
}
static
int
cm109_usb_post_reset
(
struct
usb_interface
*
intf
)
{
struct
cm109_dev
*
dev
=
usb_get_intfdata
(
intf
);
dev
->
resetting
=
0
;
smp_wmb
();
cm109_restore_state
(
dev
);
mutex_unlock
(
&
dev
->
pm_mutex
);
return
0
;
}
static
struct
usb_driver
cm109_driver
=
{
.
name
=
"cm109"
,
.
probe
=
cm109_usb_probe
,
.
disconnect
=
cm109_usb_disconnect
,
.
suspend
=
cm109_usb_suspend
,
.
resume
=
cm109_usb_resume
,
.
reset_resume
=
cm109_usb_resume
,
.
pre_reset
=
cm109_usb_pre_reset
,
.
post_reset
=
cm109_usb_post_reset
,
.
id_table
=
cm109_usb_table
,
.
supports_autosuspend
=
1
,
};
static
int
__init
cm109_select_keymap
(
void
)
{
/* Load the phone keymap */
if
(
!
strcasecmp
(
phone
,
"kip1000"
))
{
keymap
=
keymap_kip1000
;
printk
(
KERN_INFO
KBUILD_MODNAME
": "
"Keymap for Komunikate KIP1000 phone loaded
\n
"
);
}
else
if
(
!
strcasecmp
(
phone
,
"gtalk"
))
{
keymap
=
keymap_gtalk
;
printk
(
KERN_INFO
KBUILD_MODNAME
": "
"Keymap for Genius G-talk phone loaded
\n
"
);
}
else
if
(
!
strcasecmp
(
phone
,
"usbph01"
))
{
keymap
=
keymap_usbph01
;
printk
(
KERN_INFO
KBUILD_MODNAME
": "
"Keymap for Allied-Telesis Corega USBPH01 phone loaded
\n
"
);
}
else
{
printk
(
KERN_ERR
KBUILD_MODNAME
": "
"Unsupported phone: %s
\n
"
,
phone
);
return
-
EINVAL
;
}
return
0
;
}
static
int
__init
cm109_init
(
void
)
{
int
err
;
err
=
cm109_select_keymap
();
if
(
err
)
return
err
;
err
=
usb_register
(
&
cm109_driver
);
if
(
err
)
return
err
;
printk
(
KERN_INFO
KBUILD_MODNAME
": "
DRIVER_DESC
": "
DRIVER_VERSION
" (C) "
DRIVER_AUTHOR
"
\n
"
);
return
0
;
}
static
void
__exit
cm109_exit
(
void
)
{
usb_deregister
(
&
cm109_driver
);
}
module_init
(
cm109_init
);
module_exit
(
cm109_exit
);
MODULE_DEVICE_TABLE
(
usb
,
cm109_usb_table
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/misc/wistron_btns.c
View file @
4c0e799a
...
...
@@ -277,6 +277,16 @@ static struct key_entry keymap_fs_amilo_pro_v2000[] __initdata = {
{
KE_END
,
0
}
};
static
struct
key_entry
keymap_fs_amilo_pro_v3505
[]
__initdata
=
{
{
KE_KEY
,
0x01
,
{
KEY_HELP
}
},
/* Fn+F1 */
{
KE_KEY
,
0x06
,
{
KEY_DISPLAYTOGGLE
}
},
/* Fn+F4 */
{
KE_BLUETOOTH
,
0x30
},
/* Fn+F10 */
{
KE_KEY
,
0x31
,
{
KEY_MAIL
}
},
/* mail button */
{
KE_KEY
,
0x36
,
{
KEY_WWW
}
},
/* www button */
{
KE_WIFI
,
0x78
},
/* satelite dish button */
{
KE_END
,
0
}
};
static
struct
key_entry
keymap_fujitsu_n3510
[]
__initdata
=
{
{
KE_KEY
,
0x11
,
{
KEY_PROG1
}
},
{
KE_KEY
,
0x12
,
{
KEY_PROG2
}
},
...
...
@@ -616,6 +626,15 @@ static struct dmi_system_id dmi_ids[] __initdata = {
},
.
driver_data
=
keymap_fs_amilo_pro_v2000
},
{
.
callback
=
dmi_matched
,
.
ident
=
"Fujitsu-Siemens Amilo Pro Edition V3505"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"FUJITSU SIEMENS"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"AMILO Pro Edition V3505"
),
},
.
driver_data
=
keymap_fs_amilo_pro_v3505
},
{
.
callback
=
dmi_matched
,
.
ident
=
"Fujitsu-Siemens Amilo M7400"
,
...
...
drivers/input/misc/yealink.c
View file @
4c0e799a
...
...
@@ -52,8 +52,8 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/usb/input.h>
#include <linux/map_to_7segment.h>
#include "map_to_7segment.h"
#include "yealink.h"
#define DRIVER_VERSION "yld-20051230"
...
...
drivers/input/mouse/Kconfig
View file @
4c0e799a
...
...
@@ -96,6 +96,16 @@ config MOUSE_PS2_TOUCHKIT
If unsure, say N.
config MOUSE_PS2_OLPC
bool "OLPC PS/2 mouse protocol extension"
depends on MOUSE_PS2 && OLPC
help
Say Y here if you have an OLPC XO-1 laptop (with built-in
PS/2 touchpad/tablet device). The manufacturer calls the
touchpad an HGPK.
If unsure, say N.
config MOUSE_SERIAL
tristate "Serial mouse"
select SERIO
...
...
drivers/input/mouse/Makefile
View file @
4c0e799a
...
...
@@ -21,6 +21,7 @@ obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o
psmouse-objs
:=
psmouse-base.o synaptics.o
psmouse-$(CONFIG_MOUSE_PS2_ALPS)
+=
alps.o
psmouse-$(CONFIG_MOUSE_PS2_OLPC)
+=
hgpk.o
psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP)
+=
logips2pp.o
psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK)
+=
lifebook.o
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)
+=
trackpoint.o
...
...
drivers/input/mouse/alps.c
View file @
4c0e799a
...
...
@@ -54,6 +54,7 @@ static const struct alps_model_info alps_model_data[] = {
{
{
0x20
,
0x02
,
0x0e
},
0xf8
,
0xf8
,
ALPS_PASS
|
ALPS_DUALPOINT
},
/* XXX */
{
{
0x22
,
0x02
,
0x0a
},
0xf8
,
0xf8
,
ALPS_PASS
|
ALPS_DUALPOINT
},
{
{
0x22
,
0x02
,
0x14
},
0xff
,
0xff
,
ALPS_PASS
|
ALPS_DUALPOINT
},
/* Dell Latitude D600 */
{
{
0x62
,
0x02
,
0x14
},
0xcf
,
0xcf
,
ALPS_PASS
|
ALPS_DUALPOINT
},
/* Dell Latitude E6500 */
{
{
0x73
,
0x02
,
0x50
},
0xcf
,
0xcf
,
ALPS_FW_BK_1
}
/* Dell Vostro 1400 */
};
...
...
drivers/input/mouse/appletouch.c
View file @
4c0e799a
...
...
@@ -136,12 +136,28 @@ MODULE_DEVICE_TABLE(usb, atp_table);
#define ATP_GEYSER_MODE_REQUEST_INDEX 0
#define ATP_GEYSER_MODE_VENDOR_VALUE 0x04
/**
* enum atp_status_bits - status bit meanings
*
* These constants represent the meaning of the status bits.
* (only Geyser 3/4)
*
* @ATP_STATUS_BUTTON: The button was pressed
* @ATP_STATUS_BASE_UPDATE: Update of the base values (untouched pad)
* @ATP_STATUS_FROM_RESET: Reset previously performed
*/
enum
atp_status_bits
{
ATP_STATUS_BUTTON
=
BIT
(
0
),
ATP_STATUS_BASE_UPDATE
=
BIT
(
2
),
ATP_STATUS_FROM_RESET
=
BIT
(
4
),
};
/* Structure to hold all of our device specific stuff */
struct
atp
{
char
phys
[
64
];
struct
usb_device
*
udev
;
/* usb device */
struct
urb
*
urb
;
/* usb request block */
signed
char
*
data
;
/* transferred data */
u8
*
data
;
/* transferred data */
struct
input_dev
*
input
;
/* input dev */
enum
atp_touchpad_type
type
;
/* type of touchpad */
bool
open
;
...
...
@@ -251,8 +267,6 @@ static void atp_reinit(struct work_struct *work)
int
retval
;
dprintk
(
"appletouch: putting appletouch to sleep (reinit)
\n
"
);
dev
->
idlecount
=
0
;
atp_geyser_init
(
udev
);
retval
=
usb_submit_urb
(
dev
->
urb
,
GFP_ATOMIC
);
...
...
@@ -327,11 +341,14 @@ static inline void atp_report_fingers(struct input_dev *input, int fingers)
input_report_key
(
input
,
BTN_TOOL_TRIPLETAP
,
fingers
>
2
);
}
static
void
atp_complete
(
struct
urb
*
urb
)
/* Check URB status and for correct length of data package */
#define ATP_URB_STATUS_SUCCESS 0
#define ATP_URB_STATUS_ERROR 1
#define ATP_URB_STATUS_ERROR_FATAL 2
static
int
atp_status_check
(
struct
urb
*
urb
)
{
int
x
,
y
,
x_z
,
y_z
,
x_f
,
y_f
;
int
retval
,
i
,
j
;
int
key
;
struct
atp
*
dev
=
urb
->
context
;
switch
(
urb
->
status
)
{
...
...
@@ -351,11 +368,12 @@ static void atp_complete(struct urb *urb)
/* This urb is terminated, clean up */
dbg
(
"atp_complete: urb shutting down with status: %d"
,
urb
->
status
);
return
;
return
ATP_URB_STATUS_ERROR_FATAL
;
default:
dbg
(
"atp_complete: nonzero urb status received: %d"
,
urb
->
status
);
goto
exit
;
return
ATP_URB_STATUS_ERROR
;
}
/* drop incomplete datasets */
...
...
@@ -363,30 +381,33 @@ static void atp_complete(struct urb *urb)
dprintk
(
"appletouch: incomplete data package"
" (first byte: %d, length: %d).
\n
"
,
dev
->
data
[
0
],
dev
->
urb
->
actual_length
);
goto
exit
;
return
ATP_URB_STATUS_ERROR
;
}
/* reorder the sensors values */
if
(
dev
->
type
==
ATP_GEYSER3
||
dev
->
type
==
ATP_GEYSER4
)
{
memset
(
dev
->
xy_cur
,
0
,
sizeof
(
dev
->
xy_cur
));
return
ATP_URB_STATUS_SUCCESS
;
}
/*
* The values are laid out like this:
* -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
* '-' is an unused value.
*/
/*
* USB interrupt callback functions
*/
/* read X values */
for
(
i
=
0
,
j
=
19
;
i
<
20
;
i
+=
2
,
j
+=
3
)
{
dev
->
xy_cur
[
i
]
=
dev
->
data
[
j
+
1
];
dev
->
xy_cur
[
i
+
1
]
=
dev
->
data
[
j
+
2
];
}
/* read Y values */
for
(
i
=
0
,
j
=
1
;
i
<
9
;
i
+=
2
,
j
+=
3
)
{
dev
->
xy_cur
[
ATP_XSENSORS
+
i
]
=
dev
->
data
[
j
+
1
];
dev
->
xy_cur
[
ATP_XSENSORS
+
i
+
1
]
=
dev
->
data
[
j
+
2
];
}
}
else
if
(
dev
->
type
==
ATP_GEYSER2
)
{
/* Interrupt function for older touchpads: FOUNTAIN/GEYSER1/GEYSER2 */
static
void
atp_complete_geyser_1_2
(
struct
urb
*
urb
)
{
int
x
,
y
,
x_z
,
y_z
,
x_f
,
y_f
;
int
retval
,
i
,
j
;
int
key
;
struct
atp
*
dev
=
urb
->
context
;
int
status
=
atp_status_check
(
urb
);
if
(
status
==
ATP_URB_STATUS_ERROR_FATAL
)
return
;
else
if
(
status
==
ATP_URB_STATUS_ERROR
)
goto
exit
;
/* reorder the sensors values */
if
(
dev
->
type
==
ATP_GEYSER2
)
{
memset
(
dev
->
xy_cur
,
0
,
sizeof
(
dev
->
xy_cur
));
/*
...
...
@@ -427,34 +448,40 @@ static void atp_complete(struct urb *urb)
/* first sample */
dev
->
valid
=
true
;
dev
->
x_old
=
dev
->
y_old
=
-
1
;
/* Store first sample */
memcpy
(
dev
->
xy_old
,
dev
->
xy_cur
,
sizeof
(
dev
->
xy_old
));
if
(
dev
->
size_detect_done
||
dev
->
type
==
ATP_GEYSER3
)
/* No 17" Macbooks (yet) */
goto
exit
;
/* Perform size detection, if not done already */
if
(
!
dev
->
size_detect_done
)
{
/* 17" Powerbooks have extra X sensors */
for
(
i
=
(
dev
->
type
==
ATP_GEYSER2
?
15
:
16
);
i
<
ATP_XSENSORS
;
i
++
)
{
if
(
!
dev
->
xy_cur
[
i
])
continue
;
printk
(
KERN_INFO
"appletouch: 17
\"
model detected.
\n
"
);
if
(
dev
->
type
==
ATP_GEYSER2
)
input_set_abs_params
(
dev
->
input
,
ABS_X
,
0
,
(
20
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
else
input_set_abs_params
(
dev
->
input
,
ABS_X
,
0
,
(
26
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
break
;
}
/* 17" Powerbooks have extra X sensors */
for
(
i
=
(
dev
->
type
==
ATP_GEYSER2
?
15
:
16
);
i
<
ATP_XSENSORS
;
i
++
)
{
if
(
!
dev
->
xy_cur
[
i
])
continue
;
printk
(
KERN_INFO
"appletouch: 17
\"
model detected.
\n
"
);
if
(
dev
->
type
==
ATP_GEYSER2
)
input_set_abs_params
(
dev
->
input
,
ABS_X
,
0
,
(
20
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
else
input_set_abs_params
(
dev
->
input
,
ABS_X
,
0
,
(
ATP_XSENSORS
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
break
;
dev
->
size_detect_done
=
1
;
goto
exit
;
}
dev
->
size_detect_done
=
1
;
goto
exit
;
}
for
(
i
=
0
;
i
<
ATP_XSENSORS
+
ATP_YSENSORS
;
i
++
)
{
...
...
@@ -475,7 +502,118 @@ static void atp_complete(struct urb *urb)
ATP_XFACT
,
&
x_z
,
&
x_f
);
y
=
atp_calculate_abs
(
dev
->
xy_acc
+
ATP_XSENSORS
,
ATP_YSENSORS
,
ATP_YFACT
,
&
y_z
,
&
y_f
);
key
=
dev
->
data
[
dev
->
datalen
-
1
]
&
1
;
key
=
dev
->
data
[
dev
->
datalen
-
1
]
&
ATP_STATUS_BUTTON
;
if
(
x
&&
y
)
{
if
(
dev
->
x_old
!=
-
1
)
{
x
=
(
dev
->
x_old
*
3
+
x
)
>>
2
;
y
=
(
dev
->
y_old
*
3
+
y
)
>>
2
;
dev
->
x_old
=
x
;
dev
->
y_old
=
y
;
if
(
debug
>
1
)
printk
(
KERN_DEBUG
"appletouch: "
"X: %3d Y: %3d Xz: %3d Yz: %3d
\n
"
,
x
,
y
,
x_z
,
y_z
);
input_report_key
(
dev
->
input
,
BTN_TOUCH
,
1
);
input_report_abs
(
dev
->
input
,
ABS_X
,
x
);
input_report_abs
(
dev
->
input
,
ABS_Y
,
y
);
input_report_abs
(
dev
->
input
,
ABS_PRESSURE
,
min
(
ATP_PRESSURE
,
x_z
+
y_z
));
atp_report_fingers
(
dev
->
input
,
max
(
x_f
,
y_f
));
}
dev
->
x_old
=
x
;
dev
->
y_old
=
y
;
}
else
if
(
!
x
&&
!
y
)
{
dev
->
x_old
=
dev
->
y_old
=
-
1
;
input_report_key
(
dev
->
input
,
BTN_TOUCH
,
0
);
input_report_abs
(
dev
->
input
,
ABS_PRESSURE
,
0
);
atp_report_fingers
(
dev
->
input
,
0
);
/* reset the accumulator on release */
memset
(
dev
->
xy_acc
,
0
,
sizeof
(
dev
->
xy_acc
));
}
input_report_key
(
dev
->
input
,
BTN_LEFT
,
key
);
input_sync
(
dev
->
input
);
exit:
retval
=
usb_submit_urb
(
dev
->
urb
,
GFP_ATOMIC
);
if
(
retval
)
err
(
"atp_complete: usb_submit_urb failed with result %d"
,
retval
);
}
/* Interrupt function for older touchpads: GEYSER3/GEYSER4 */
static
void
atp_complete_geyser_3_4
(
struct
urb
*
urb
)
{
int
x
,
y
,
x_z
,
y_z
,
x_f
,
y_f
;
int
retval
,
i
,
j
;
int
key
;
struct
atp
*
dev
=
urb
->
context
;
int
status
=
atp_status_check
(
urb
);
if
(
status
==
ATP_URB_STATUS_ERROR_FATAL
)
return
;
else
if
(
status
==
ATP_URB_STATUS_ERROR
)
goto
exit
;
/* Reorder the sensors values:
*
* The values are laid out like this:
* -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
* '-' is an unused value.
*/
/* read X values */
for
(
i
=
0
,
j
=
19
;
i
<
20
;
i
+=
2
,
j
+=
3
)
{
dev
->
xy_cur
[
i
]
=
dev
->
data
[
j
+
1
];
dev
->
xy_cur
[
i
+
1
]
=
dev
->
data
[
j
+
2
];
}
/* read Y values */
for
(
i
=
0
,
j
=
1
;
i
<
9
;
i
+=
2
,
j
+=
3
)
{
dev
->
xy_cur
[
ATP_XSENSORS
+
i
]
=
dev
->
data
[
j
+
1
];
dev
->
xy_cur
[
ATP_XSENSORS
+
i
+
1
]
=
dev
->
data
[
j
+
2
];
}
dbg_dump
(
"sample"
,
dev
->
xy_cur
);
/* Just update the base values (i.e. touchpad in untouched state) */
if
(
dev
->
data
[
dev
->
datalen
-
1
]
&
ATP_STATUS_BASE_UPDATE
)
{
dprintk
(
KERN_DEBUG
"appletouch: updated base values
\n
"
);
memcpy
(
dev
->
xy_old
,
dev
->
xy_cur
,
sizeof
(
dev
->
xy_old
));
goto
exit
;
}
for
(
i
=
0
;
i
<
ATP_XSENSORS
+
ATP_YSENSORS
;
i
++
)
{
/* calculate the change */
dev
->
xy_acc
[
i
]
=
dev
->
xy_cur
[
i
]
-
dev
->
xy_old
[
i
];
/* this is a round-robin value, so couple with that */
if
(
dev
->
xy_acc
[
i
]
>
127
)
dev
->
xy_acc
[
i
]
-=
256
;
if
(
dev
->
xy_acc
[
i
]
<
-
127
)
dev
->
xy_acc
[
i
]
+=
256
;
/* prevent down drifting */
if
(
dev
->
xy_acc
[
i
]
<
0
)
dev
->
xy_acc
[
i
]
=
0
;
}
dbg_dump
(
"accumulator"
,
dev
->
xy_acc
);
x
=
atp_calculate_abs
(
dev
->
xy_acc
,
ATP_XSENSORS
,
ATP_XFACT
,
&
x_z
,
&
x_f
);
y
=
atp_calculate_abs
(
dev
->
xy_acc
+
ATP_XSENSORS
,
ATP_YSENSORS
,
ATP_YFACT
,
&
y_z
,
&
y_f
);
key
=
dev
->
data
[
dev
->
datalen
-
1
]
&
ATP_STATUS_BUTTON
;
if
(
x
&&
y
)
{
if
(
dev
->
x_old
!=
-
1
)
{
...
...
@@ -514,28 +652,27 @@ static void atp_complete(struct urb *urb)
input_sync
(
dev
->
input
);
/*
*
Many Geysers
will continue to send packets continually after
*
Geysers 3/4
will continue to send packets continually after
* the first touch unless reinitialised. Do so if it's been
* idle for a while in order to avoid waking the kernel up
* several hundred times a second. Re-initialization does not
* work on Fountain touchpads.
* several hundred times a second.
*/
if
(
dev
->
type
!=
ATP_FOUNTAIN
)
{
/*
* Button must not be pressed when entering suspend,
* otherwise we will never release the button.
*/
if
(
!
x
&&
!
y
&&
!
key
)
{
dev
->
idlecount
++
;
if
(
dev
->
idlecount
==
10
)
{
dev
->
valid
=
false
;
schedule_work
(
&
dev
->
work
);
/* Don't resubmit urb here, wait for reinit */
return
;
}
}
else
/*
* Button must not be pressed when entering suspend,
* otherwise we will never release the button.
*/
if
(
!
x
&&
!
y
&&
!
key
)
{
dev
->
idlecount
++
;
if
(
dev
->
idlecount
==
10
)
{
dev
->
x_old
=
dev
->
y_old
=
-
1
;
dev
->
idlecount
=
0
;
}
schedule_work
(
&
dev
->
work
);
/* Don't resubmit urb here, wait for reinit */
return
;
}
}
else
dev
->
idlecount
=
0
;
exit:
retval
=
usb_submit_urb
(
dev
->
urb
,
GFP_ATOMIC
);
...
...
@@ -632,9 +769,19 @@ static int atp_probe(struct usb_interface *iface,
if
(
!
dev
->
data
)
goto
err_free_urb
;
usb_fill_int_urb
(
dev
->
urb
,
udev
,
usb_rcvintpipe
(
udev
,
int_in_endpointAddr
),
dev
->
data
,
dev
->
datalen
,
atp_complete
,
dev
,
1
);
/* Select the USB complete (callback) function */
if
(
dev
->
type
==
ATP_FOUNTAIN
||
dev
->
type
==
ATP_GEYSER1
||
dev
->
type
==
ATP_GEYSER2
)
usb_fill_int_urb
(
dev
->
urb
,
udev
,
usb_rcvintpipe
(
udev
,
int_in_endpointAddr
),
dev
->
data
,
dev
->
datalen
,
atp_complete_geyser_1_2
,
dev
,
1
);
else
usb_fill_int_urb
(
dev
->
urb
,
udev
,
usb_rcvintpipe
(
udev
,
int_in_endpointAddr
),
dev
->
data
,
dev
->
datalen
,
atp_complete_geyser_3_4
,
dev
,
1
);
error
=
atp_handle_geyser
(
dev
);
if
(
error
)
...
...
@@ -751,8 +898,6 @@ static int atp_suspend(struct usb_interface *iface, pm_message_t message)
struct
atp
*
dev
=
usb_get_intfdata
(
iface
);
usb_kill_urb
(
dev
->
urb
);
dev
->
valid
=
false
;
return
0
;
}
...
...
drivers/input/mouse/hgpk.c
0 → 100644
View file @
4c0e799a
/*
* OLPC HGPK (XO-1) touchpad PS/2 mouse driver
*
* Copyright (c) 2006-2008 One Laptop Per Child
* Authors:
* Zephaniah E. Hull
* Andres Salomon <dilinger@debian.org>
*
* This driver is partly based on the ALPS driver, which is:
*
* Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
* Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
* Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
* Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* The spec from ALPS is available from
* <http://wiki.laptop.org/go/Touch_Pad/Tablet>. It refers to this
* device as HGPK (Hybrid GS, PT, and Keymatrix).
*
* The earliest versions of the device had simultaneous reporting; that
* was removed. After that, the device used the Advanced Mode GS/PT streaming
* stuff. That turned out to be too buggy to support, so we've finally
* switched to Mouse Mode (which utilizes only the center 1/3 of the touchpad).
*/
#define DEBUG
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/libps2.h>
#include <linux/delay.h>
#include <asm/olpc.h>
#include "psmouse.h"
#include "hgpk.h"
static
int
tpdebug
;
module_param
(
tpdebug
,
int
,
0644
);
MODULE_PARM_DESC
(
tpdebug
,
"enable debugging, dumping packets to KERN_DEBUG."
);
static
int
recalib_delta
=
100
;
module_param
(
recalib_delta
,
int
,
0644
);
MODULE_PARM_DESC
(
recalib_delta
,
"packets containing a delta this large will cause a recalibration."
);
/*
* When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
* above the pad and still have it send packets. This causes a jump cursor
* when one places their finger on the pad. We can probably detect the
* jump as we see a large deltas (>= 100px). In mouse mode, I've been
* unable to even come close to 100px deltas during normal usage, so I think
* this threshold is safe. If a large delta occurs, trigger a recalibration.
*/
static
void
hgpk_jumpy_hack
(
struct
psmouse
*
psmouse
,
int
x
,
int
y
)
{
struct
hgpk_data
*
priv
=
psmouse
->
private
;
if
(
abs
(
x
)
>
recalib_delta
||
abs
(
y
)
>
recalib_delta
)
{
hgpk_err
(
psmouse
,
">%dpx jump detected (%d,%d)
\n
"
,
recalib_delta
,
x
,
y
);
/* My car gets forty rods to the hogshead and that's the
* way I likes it! */
psmouse_queue_work
(
psmouse
,
&
priv
->
recalib_wq
,
msecs_to_jiffies
(
1000
));
}
}
/*
* We have no idea why this particular hardware bug occurs. The touchpad
* will randomly start spewing packets without anything touching the
* pad. This wouldn't necessarily be bad, but it's indicative of a
* severely miscalibrated pad; attempting to use the touchpad while it's
* spewing means the cursor will jump all over the place, and act "drunk".
*
* The packets that are spewed tend to all have deltas between -2 and 2, and
* the cursor will move around without really going very far. It will
* tend to end up in the same location; if we tally up the changes over
* 100 packets, we end up w/ a final delta of close to 0. This happens
* pretty regularly when the touchpad is spewing, and is pretty hard to
* manually trigger (at least for *my* fingers). So, it makes a perfect
* scheme for detecting spews.
*/
static
void
hgpk_spewing_hack
(
struct
psmouse
*
psmouse
,
int
l
,
int
r
,
int
x
,
int
y
)
{
struct
hgpk_data
*
priv
=
psmouse
->
private
;
/* ignore button press packets; many in a row could trigger
* a false-positive! */
if
(
l
||
r
)
return
;
priv
->
x_tally
+=
x
;
priv
->
y_tally
+=
y
;
if
(
++
priv
->
count
>
100
)
{
if
(
abs
(
priv
->
x_tally
)
<
3
&&
abs
(
priv
->
y_tally
)
<
3
)
{
hgpk_dbg
(
psmouse
,
"packet spew detected (%d,%d)
\n
"
,
priv
->
x_tally
,
priv
->
y_tally
);
psmouse_queue_work
(
psmouse
,
&
priv
->
recalib_wq
,
msecs_to_jiffies
(
1000
));
}
/* reset every 100 packets */
priv
->
count
=
0
;
priv
->
x_tally
=
0
;
priv
->
y_tally
=
0
;
}
}
/*
* HGPK Mouse Mode format (standard mouse format, sans middle button)
*
* byte 0: y-over x-over y-neg x-neg 1 0 swr swl
* byte 1: x7 x6 x5 x4 x3 x2 x1 x0
* byte 2: y7 y6 y5 y4 y3 y2 y1 y0
*
* swr/swl are the left/right buttons.
* x-neg/y-neg are the x and y delta negative bits
* x-over/y-over are the x and y overflow bits
*/
static
int
hgpk_validate_byte
(
unsigned
char
*
packet
)
{
return
(
packet
[
0
]
&
0x0C
)
==
0x08
;
}
static
void
hgpk_process_packet
(
struct
psmouse
*
psmouse
)
{
struct
input_dev
*
dev
=
psmouse
->
dev
;
unsigned
char
*
packet
=
psmouse
->
packet
;
int
x
,
y
,
left
,
right
;
left
=
packet
[
0
]
&
1
;
right
=
(
packet
[
0
]
>>
1
)
&
1
;
x
=
packet
[
1
]
-
((
packet
[
0
]
<<
4
)
&
0x100
);
y
=
((
packet
[
0
]
<<
3
)
&
0x100
)
-
packet
[
2
];
hgpk_jumpy_hack
(
psmouse
,
x
,
y
);
hgpk_spewing_hack
(
psmouse
,
left
,
right
,
x
,
y
);
if
(
tpdebug
)
hgpk_dbg
(
psmouse
,
"l=%d r=%d x=%d y=%d
\n
"
,
left
,
right
,
x
,
y
);
input_report_key
(
dev
,
BTN_LEFT
,
left
);
input_report_key
(
dev
,
BTN_RIGHT
,
right
);
input_report_rel
(
dev
,
REL_X
,
x
);
input_report_rel
(
dev
,
REL_Y
,
y
);
input_sync
(
dev
);
}
static
psmouse_ret_t
hgpk_process_byte
(
struct
psmouse
*
psmouse
)
{
struct
hgpk_data
*
priv
=
psmouse
->
private
;
if
(
hgpk_validate_byte
(
psmouse
->
packet
))
{
hgpk_dbg
(
psmouse
,
"%s: (%d) %02x %02x %02x
\n
"
,
__func__
,
psmouse
->
pktcnt
,
psmouse
->
packet
[
0
],
psmouse
->
packet
[
1
],
psmouse
->
packet
[
2
]);
return
PSMOUSE_BAD_DATA
;
}
if
(
psmouse
->
pktcnt
>=
psmouse
->
pktsize
)
{
hgpk_process_packet
(
psmouse
);
return
PSMOUSE_FULL_PACKET
;
}
if
(
priv
->
recalib_window
)
{
if
(
time_before
(
jiffies
,
priv
->
recalib_window
))
{
/*
* ugh, got a packet inside our recalibration
* window, schedule another recalibration.
*/
hgpk_dbg
(
psmouse
,
"packet inside calibration window, "
"queueing another recalibration
\n
"
);
psmouse_queue_work
(
psmouse
,
&
priv
->
recalib_wq
,
msecs_to_jiffies
(
1000
));
}
priv
->
recalib_window
=
0
;
}
return
PSMOUSE_GOOD_DATA
;
}
static
int
hgpk_force_recalibrate
(
struct
psmouse
*
psmouse
)
{
struct
ps2dev
*
ps2dev
=
&
psmouse
->
ps2dev
;
struct
hgpk_data
*
priv
=
psmouse
->
private
;
/* C-series touchpads added the recalibrate command */
if
(
psmouse
->
model
<
HGPK_MODEL_C
)
return
0
;
/* we don't want to race with the irq handler, nor with resyncs */
psmouse_set_state
(
psmouse
,
PSMOUSE_INITIALIZING
);
/* start by resetting the device */
psmouse_reset
(
psmouse
);
/* send the recalibrate request */
if
(
ps2_command
(
ps2dev
,
NULL
,
0xf5
)
||
ps2_command
(
ps2dev
,
NULL
,
0xf5
)
||
ps2_command
(
ps2dev
,
NULL
,
0xe6
)
||
ps2_command
(
ps2dev
,
NULL
,
0xf5
))
{
return
-
1
;
}
/* according to ALPS, 150mS is required for recalibration */
msleep
(
150
);
/* XXX: If a finger is down during this delay, recalibration will
* detect capacitance incorrectly. This is a hardware bug, and
* we don't have a good way to deal with it. The 2s window stuff
* (below) is our best option for now.
*/
if
(
ps2_command
(
ps2dev
,
NULL
,
PSMOUSE_CMD_ENABLE
))
return
-
1
;
psmouse_set_state
(
psmouse
,
PSMOUSE_ACTIVATED
);
/* After we recalibrate, we shouldn't get any packets for 2s. If
* we do, it's likely that someone's finger was on the touchpad.
* If someone's finger *was* on the touchpad, it's probably
* miscalibrated. So, we should schedule another recalibration
*/
priv
->
recalib_window
=
jiffies
+
msecs_to_jiffies
(
2000
);
return
0
;
}
/*
* This kills power to the touchpad; according to ALPS, current consumption
* goes down to 50uA after running this. To turn power back on, we drive
* MS-DAT low.
*/
static
int
hgpk_toggle_power
(
struct
psmouse
*
psmouse
,
int
enable
)
{
struct
ps2dev
*
ps2dev
=
&
psmouse
->
ps2dev
;
int
timeo
;
/* Added on D-series touchpads */
if
(
psmouse
->
model
<
HGPK_MODEL_D
)
return
0
;
if
(
enable
)
{
psmouse_set_state
(
psmouse
,
PSMOUSE_INITIALIZING
);
/*
* Sending a byte will drive MS-DAT low; this will wake up
* the controller. Once we get an ACK back from it, it
* means we can continue with the touchpad re-init. ALPS
* tells us that 1s should be long enough, so set that as
* the upper bound.
*/
for
(
timeo
=
20
;
timeo
>
0
;
timeo
--
)
{
if
(
!
ps2_sendbyte
(
&
psmouse
->
ps2dev
,
PSMOUSE_CMD_DISABLE
,
20
))
break
;
msleep
(
50
);
}
psmouse_reset
(
psmouse
);
/* should be all set, enable the touchpad */
ps2_command
(
&
psmouse
->
ps2dev
,
NULL
,
PSMOUSE_CMD_ENABLE
);
psmouse_set_state
(
psmouse
,
PSMOUSE_ACTIVATED
);
}
else
{
hgpk_dbg
(
psmouse
,
"Powering off touchpad.
\n
"
);
psmouse_set_state
(
psmouse
,
PSMOUSE_IGNORE
);
if
(
ps2_command
(
ps2dev
,
NULL
,
0xec
)
||
ps2_command
(
ps2dev
,
NULL
,
0xec
)
||
ps2_command
(
ps2dev
,
NULL
,
0xea
))
{
return
-
1
;
}
/* probably won't see an ACK, the touchpad will be off */
ps2_sendbyte
(
&
psmouse
->
ps2dev
,
0xec
,
20
);
}
return
0
;
}
static
int
hgpk_poll
(
struct
psmouse
*
psmouse
)
{
/* We can't poll, so always return failure. */
return
-
1
;
}
static
int
hgpk_reconnect
(
struct
psmouse
*
psmouse
)
{
/* During suspend/resume the ps2 rails remain powered. We don't want
* to do a reset because it's flush data out of buffers; however,
* earlier prototypes (B1) had some brokenness that required a reset. */
if
(
olpc_board_at_least
(
olpc_board
(
0xb2
)))
if
(
psmouse
->
ps2dev
.
serio
->
dev
.
power
.
power_state
.
event
!=
PM_EVENT_ON
)
return
0
;
psmouse_reset
(
psmouse
);
return
0
;
}
static
ssize_t
hgpk_show_powered
(
struct
psmouse
*
psmouse
,
void
*
data
,
char
*
buf
)
{
struct
hgpk_data
*
priv
=
psmouse
->
private
;
return
sprintf
(
buf
,
"%d
\n
"
,
priv
->
powered
);
}
static
ssize_t
hgpk_set_powered
(
struct
psmouse
*
psmouse
,
void
*
data
,
const
char
*
buf
,
size_t
count
)
{
struct
hgpk_data
*
priv
=
psmouse
->
private
;
unsigned
long
value
;
int
err
;
err
=
strict_strtoul
(
buf
,
10
,
&
value
);
if
(
err
||
value
>
1
)
return
-
EINVAL
;
if
(
value
!=
priv
->
powered
)
{
/*
* hgpk_toggle_power will deal w/ state so
* we're not racing w/ irq
*/
err
=
hgpk_toggle_power
(
psmouse
,
value
);
if
(
!
err
)
priv
->
powered
=
value
;
}
return
err
?
err
:
count
;
}
__PSMOUSE_DEFINE_ATTR
(
powered
,
S_IWUSR
|
S_IRUGO
,
NULL
,
hgpk_show_powered
,
hgpk_set_powered
,
0
);
static
void
hgpk_disconnect
(
struct
psmouse
*
psmouse
)
{
struct
hgpk_data
*
priv
=
psmouse
->
private
;
device_remove_file
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
&
psmouse_attr_powered
.
dattr
);
psmouse_reset
(
psmouse
);
kfree
(
priv
);
}
static
void
hgpk_recalib_work
(
struct
work_struct
*
work
)
{
struct
delayed_work
*
w
=
container_of
(
work
,
struct
delayed_work
,
work
);
struct
hgpk_data
*
priv
=
container_of
(
w
,
struct
hgpk_data
,
recalib_wq
);
struct
psmouse
*
psmouse
=
priv
->
psmouse
;
hgpk_dbg
(
psmouse
,
"recalibrating touchpad..
\n
"
);
if
(
hgpk_force_recalibrate
(
psmouse
))
hgpk_err
(
psmouse
,
"recalibration failed!
\n
"
);
}
static
int
hgpk_register
(
struct
psmouse
*
psmouse
)
{
struct
input_dev
*
dev
=
psmouse
->
dev
;
int
err
;
/* unset the things that psmouse-base sets which we don't have */
__clear_bit
(
BTN_MIDDLE
,
dev
->
keybit
);
/* set the things we do have */
__set_bit
(
EV_KEY
,
dev
->
evbit
);
__set_bit
(
EV_REL
,
dev
->
evbit
);
__set_bit
(
REL_X
,
dev
->
relbit
);
__set_bit
(
REL_Y
,
dev
->
relbit
);
__set_bit
(
BTN_LEFT
,
dev
->
keybit
);
__set_bit
(
BTN_RIGHT
,
dev
->
keybit
);
/* register handlers */
psmouse
->
protocol_handler
=
hgpk_process_byte
;
psmouse
->
poll
=
hgpk_poll
;
psmouse
->
disconnect
=
hgpk_disconnect
;
psmouse
->
reconnect
=
hgpk_reconnect
;
psmouse
->
pktsize
=
3
;
/* Disable the idle resync. */
psmouse
->
resync_time
=
0
;
/* Reset after a lot of bad bytes. */
psmouse
->
resetafter
=
1024
;
err
=
device_create_file
(
&
psmouse
->
ps2dev
.
serio
->
dev
,
&
psmouse_attr_powered
.
dattr
);
if
(
err
)
hgpk_err
(
psmouse
,
"Failed to create sysfs attribute
\n
"
);
return
err
;
}
int
hgpk_init
(
struct
psmouse
*
psmouse
)
{
struct
hgpk_data
*
priv
;
int
err
=
-
ENOMEM
;
priv
=
kzalloc
(
sizeof
(
struct
hgpk_data
),
GFP_KERNEL
);
if
(
!
priv
)
goto
alloc_fail
;
psmouse
->
private
=
priv
;
priv
->
psmouse
=
psmouse
;
priv
->
powered
=
1
;
INIT_DELAYED_WORK
(
&
priv
->
recalib_wq
,
hgpk_recalib_work
);
err
=
psmouse_reset
(
psmouse
);
if
(
err
)
goto
init_fail
;
err
=
hgpk_register
(
psmouse
);
if
(
err
)
goto
init_fail
;
return
0
;
init_fail:
kfree
(
priv
);
alloc_fail:
return
err
;
}
static
enum
hgpk_model_t
hgpk_get_model
(
struct
psmouse
*
psmouse
)
{
struct
ps2dev
*
ps2dev
=
&
psmouse
->
ps2dev
;
unsigned
char
param
[
3
];
/* E7, E7, E7, E9 gets us a 3 byte identifier */
if
(
ps2_command
(
ps2dev
,
NULL
,
PSMOUSE_CMD_SETSCALE21
)
||
ps2_command
(
ps2dev
,
NULL
,
PSMOUSE_CMD_SETSCALE21
)
||
ps2_command
(
ps2dev
,
NULL
,
PSMOUSE_CMD_SETSCALE21
)
||
ps2_command
(
ps2dev
,
param
,
PSMOUSE_CMD_GETINFO
))
{
return
-
EIO
;
}
hgpk_dbg
(
psmouse
,
"ID: %02x %02x %02x"
,
param
[
0
],
param
[
1
],
param
[
2
]);
/* HGPK signature: 0x67, 0x00, 0x<model> */
if
(
param
[
0
]
!=
0x67
||
param
[
1
]
!=
0x00
)
return
-
ENODEV
;
hgpk_info
(
psmouse
,
"OLPC touchpad revision 0x%x
\n
"
,
param
[
2
]);
return
param
[
2
];
}
int
hgpk_detect
(
struct
psmouse
*
psmouse
,
int
set_properties
)
{
int
version
;
version
=
hgpk_get_model
(
psmouse
);
if
(
version
<
0
)
return
version
;
if
(
set_properties
)
{
psmouse
->
vendor
=
"ALPS"
;
psmouse
->
name
=
"HGPK"
;
psmouse
->
model
=
version
;
}
return
0
;
}
drivers/input/mouse/hgpk.h
0 → 100644
View file @
4c0e799a
/*
* OLPC HGPK (XO-1) touchpad PS/2 mouse driver
*/
#ifndef _HGPK_H
#define _HGPK_H
enum
hgpk_model_t
{
HGPK_MODEL_PREA
=
0x0a
,
/* pre-B1s */
HGPK_MODEL_A
=
0x14
,
/* found on B1s, PT disabled in hardware */
HGPK_MODEL_B
=
0x28
,
/* B2s, has capacitance issues */
HGPK_MODEL_C
=
0x3c
,
HGPK_MODEL_D
=
0x50
,
/* C1, mass production */
};
struct
hgpk_data
{
struct
psmouse
*
psmouse
;
int
powered
;
int
count
,
x_tally
,
y_tally
;
/* hardware workaround stuff */
unsigned
long
recalib_window
;
struct
delayed_work
recalib_wq
;
};
#define hgpk_dbg(psmouse, format, arg...) \
dev_dbg(&(psmouse)->ps2dev.serio->dev, format, ## arg)
#define hgpk_err(psmouse, format, arg...) \
dev_err(&(psmouse)->ps2dev.serio->dev, format, ## arg)
#define hgpk_info(psmouse, format, arg...) \
dev_info(&(psmouse)->ps2dev.serio->dev, format, ## arg)
#define hgpk_warn(psmouse, format, arg...) \
dev_warn(&(psmouse)->ps2dev.serio->dev, format, ## arg)
#define hgpk_notice(psmouse, format, arg...) \
dev_notice(&(psmouse)->ps2dev.serio->dev, format, ## arg)
#ifdef CONFIG_MOUSE_PS2_OLPC
int
hgpk_detect
(
struct
psmouse
*
psmouse
,
int
set_properties
);
int
hgpk_init
(
struct
psmouse
*
psmouse
);
#else
static
inline
int
hgpk_detect
(
struct
psmouse
*
psmouse
,
int
set_properties
)
{
return
-
ENODEV
;
}
static
inline
int
hgpk_init
(
struct
psmouse
*
psmouse
)
{
return
-
ENODEV
;
}
#endif
#endif
drivers/input/mouse/logips2pp.c
View file @
4c0e799a
...
...
@@ -157,10 +157,8 @@ static ssize_t ps2pp_attr_show_smartscroll(struct psmouse *psmouse, void *data,
static
ssize_t
ps2pp_attr_set_smartscroll
(
struct
psmouse
*
psmouse
,
void
*
data
,
const
char
*
buf
,
size_t
count
)
{
unsigned
long
value
;
char
*
rest
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
1
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
1
)
return
-
EINVAL
;
ps2pp_set_smartscroll
(
psmouse
,
value
);
...
...
drivers/input/mouse/psmouse-base.c
View file @
4c0e799a
...
...
@@ -25,6 +25,7 @@
#include "synaptics.h"
#include "logips2pp.h"
#include "alps.h"
#include "hgpk.h"
#include "lifebook.h"
#include "trackpoint.h"
#include "touchkit_ps2.h"
...
...
@@ -201,6 +202,12 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse)
return
PSMOUSE_FULL_PACKET
;
}
void
psmouse_queue_work
(
struct
psmouse
*
psmouse
,
struct
delayed_work
*
work
,
unsigned
long
delay
)
{
queue_delayed_work
(
kpsmoused_wq
,
work
,
delay
);
}
/*
* __psmouse_set_state() sets new psmouse state and resets all flags.
*/
...
...
@@ -220,7 +227,7 @@ static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_sta
* is not a concern.
*/
static
void
psmouse_set_state
(
struct
psmouse
*
psmouse
,
enum
psmouse_state
new_state
)
void
psmouse_set_state
(
struct
psmouse
*
psmouse
,
enum
psmouse_state
new_state
)
{
serio_pause_rx
(
psmouse
->
ps2dev
.
serio
);
__psmouse_set_state
(
psmouse
,
new_state
);
...
...
@@ -305,7 +312,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
psmouse
->
name
,
psmouse
->
phys
,
psmouse
->
pktcnt
);
psmouse
->
badbyte
=
psmouse
->
packet
[
0
];
__psmouse_set_state
(
psmouse
,
PSMOUSE_RESYNCING
);
queue_work
(
kpsmoused_wq
,
&
psmouse
->
resync_work
);
psmouse_queue_work
(
psmouse
,
&
psmouse
->
resync_work
,
0
);
goto
out
;
}
...
...
@@ -342,7 +349,7 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
time_after
(
jiffies
,
psmouse
->
last
+
psmouse
->
resync_time
*
HZ
))
{
psmouse
->
badbyte
=
psmouse
->
packet
[
0
];
__psmouse_set_state
(
psmouse
,
PSMOUSE_RESYNCING
);
queue_work
(
kpsmoused_wq
,
&
psmouse
->
resync_work
);
psmouse_queue_work
(
psmouse
,
&
psmouse
->
resync_work
,
0
);
goto
out
;
}
...
...
@@ -630,8 +637,20 @@ static int psmouse_extensions(struct psmouse *psmouse,
}
}
if
(
max_proto
>
PSMOUSE_IMEX
)
{
/*
* Try OLPC HGPK touchpad.
*/
if
(
max_proto
>
PSMOUSE_IMEX
&&
hgpk_detect
(
psmouse
,
set_properties
)
==
0
)
{
if
(
!
set_properties
||
hgpk_init
(
psmouse
)
==
0
)
return
PSMOUSE_HGPK
;
/*
* Init failed, try basic relative protocols
*/
max_proto
=
PSMOUSE_IMEX
;
}
if
(
max_proto
>
PSMOUSE_IMEX
)
{
if
(
genius_detect
(
psmouse
,
set_properties
)
==
0
)
return
PSMOUSE_GENPS
;
...
...
@@ -761,6 +780,14 @@ static const struct psmouse_protocol psmouse_protocols[] = {
.
alias
=
"touchkit"
,
.
detect
=
touchkit_ps2_detect
,
},
#endif
#ifdef CONFIG_MOUSE_PS2_OLPC
{
.
type
=
PSMOUSE_HGPK
,
.
name
=
"OLPC HGPK"
,
.
alias
=
"hgpk"
,
.
detect
=
hgpk_detect
,
},
#endif
{
.
type
=
PSMOUSE_CORTRON
,
...
...
@@ -935,7 +962,7 @@ static int psmouse_poll(struct psmouse *psmouse)
static
void
psmouse_resync
(
struct
work_struct
*
work
)
{
struct
psmouse
*
parent
=
NULL
,
*
psmouse
=
container_of
(
work
,
struct
psmouse
,
resync_work
);
container_of
(
work
,
struct
psmouse
,
resync_work
.
work
);
struct
serio
*
serio
=
psmouse
->
ps2dev
.
serio
;
psmouse_ret_t
rc
=
PSMOUSE_GOOD_DATA
;
int
failed
=
0
,
enabled
=
0
;
...
...
@@ -1194,7 +1221,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
goto
err_free
;
ps2_init
(
&
psmouse
->
ps2dev
,
serio
);
INIT_WORK
(
&
psmouse
->
resync_work
,
psmouse_resync
);
INIT_
DELAYED_
WORK
(
&
psmouse
->
resync_work
,
psmouse_resync
);
psmouse
->
dev
=
input_dev
;
snprintf
(
psmouse
->
phys
,
sizeof
(
psmouse
->
phys
),
"%s/input0"
,
serio
->
phys
);
...
...
@@ -1395,25 +1422,29 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
psmouse
=
serio_get_drvdata
(
serio
);
if
(
psmouse
->
state
==
PSMOUSE_IGNORE
)
{
retval
=
-
ENODEV
;
goto
out_unlock
;
}
if
(
attr
->
protect
)
{
if
(
psmouse
->
state
==
PSMOUSE_IGNORE
)
{
retval
=
-
ENODEV
;
goto
out_unlock
;
}
if
(
serio
->
parent
&&
serio
->
id
.
type
==
SERIO_PS_PSTHRU
)
{
parent
=
serio_get_drvdata
(
serio
->
parent
);
psmouse_deactivate
(
parent
);
}
if
(
serio
->
parent
&&
serio
->
id
.
type
==
SERIO_PS_PSTHRU
)
{
parent
=
serio_get_drvdata
(
serio
->
parent
);
psmouse_deactivate
(
parent
);
}
psmouse_deactivate
(
psmouse
);
psmouse_deactivate
(
psmouse
);
}
retval
=
attr
->
set
(
psmouse
,
attr
->
data
,
buf
,
count
);
if
(
retval
!=
-
ENODEV
)
psmouse_activate
(
psmouse
);
if
(
attr
->
protect
)
{
if
(
retval
!=
-
ENODEV
)
psmouse_activate
(
psmouse
);
if
(
parent
)
psmouse_activate
(
parent
);
if
(
parent
)
psmouse_activate
(
parent
);
}
out_unlock:
mutex_unlock
(
&
psmouse_mutex
);
...
...
@@ -1433,10 +1464,8 @@ static ssize_t psmouse_set_int_attr(struct psmouse *psmouse, void *offset, const
{
unsigned
int
*
field
=
(
unsigned
int
*
)((
char
*
)
psmouse
+
(
size_t
)
offset
);
unsigned
long
value
;
char
*
rest
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
))
return
-
EINVAL
;
if
((
unsigned
int
)
value
!=
value
)
...
...
@@ -1549,10 +1578,8 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
static
ssize_t
psmouse_attr_set_rate
(
struct
psmouse
*
psmouse
,
void
*
data
,
const
char
*
buf
,
size_t
count
)
{
unsigned
long
value
;
char
*
rest
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
))
return
-
EINVAL
;
psmouse
->
set_rate
(
psmouse
,
value
);
...
...
@@ -1562,10 +1589,8 @@ static ssize_t psmouse_attr_set_rate(struct psmouse *psmouse, void *data, const
static
ssize_t
psmouse_attr_set_resolution
(
struct
psmouse
*
psmouse
,
void
*
data
,
const
char
*
buf
,
size_t
count
)
{
unsigned
long
value
;
char
*
rest
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
))
return
-
EINVAL
;
psmouse
->
set_resolution
(
psmouse
,
value
);
...
...
drivers/input/mouse/psmouse.h
View file @
4c0e799a
...
...
@@ -39,7 +39,7 @@ struct psmouse {
void
*
private
;
struct
input_dev
*
dev
;
struct
ps2dev
ps2dev
;
struct
work_struct
resync_work
;
struct
delayed_work
resync_work
;
char
*
vendor
;
char
*
name
;
unsigned
char
packet
[
8
];
...
...
@@ -89,20 +89,24 @@ enum psmouse_type {
PSMOUSE_TRACKPOINT
,
PSMOUSE_TOUCHKIT_PS2
,
PSMOUSE_CORTRON
,
PSMOUSE_HGPK
,
PSMOUSE_AUTO
/* This one should always be last */
};
void
psmouse_queue_work
(
struct
psmouse
*
psmouse
,
struct
delayed_work
*
work
,
unsigned
long
delay
);
int
psmouse_sliced_command
(
struct
psmouse
*
psmouse
,
unsigned
char
command
);
int
psmouse_reset
(
struct
psmouse
*
psmouse
);
void
psmouse_set_state
(
struct
psmouse
*
psmouse
,
enum
psmouse_state
new_state
);
void
psmouse_set_resolution
(
struct
psmouse
*
psmouse
,
unsigned
int
resolution
);
struct
psmouse_attribute
{
struct
device_attribute
dattr
;
void
*
data
;
ssize_t
(
*
show
)(
struct
psmouse
*
psmouse
,
void
*
data
,
char
*
buf
);
ssize_t
(
*
set
)(
struct
psmouse
*
psmouse
,
void
*
data
,
const
char
*
buf
,
size_t
count
);
int
protect
;
};
#define to_psmouse_attr(a) container_of((a), struct psmouse_attribute, dattr)
...
...
@@ -111,7 +115,7 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *at
ssize_t
psmouse_attr_set_helper
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
);
#define
PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set)
\
#define
__PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, _protect)
\
static ssize_t _show(struct psmouse *, void *data, char *); \
static ssize_t _set(struct psmouse *, void *data, const char *, size_t); \
static struct psmouse_attribute psmouse_attr_##_name = { \
...
...
@@ -126,6 +130,10 @@ static struct psmouse_attribute psmouse_attr_##_name = { \
.data = _data, \
.show = _show, \
.set = _set, \
.protect = _protect, \
}
#define PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set) \
__PSMOUSE_DEFINE_ATTR(_name, _mode, _data, _show, _set, 1)
#endif
/* _PSMOUSE_H */
drivers/input/mouse/trackpoint.c
View file @
4c0e799a
...
...
@@ -89,10 +89,8 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data,
struct
trackpoint_attr_data
*
attr
=
data
;
unsigned
char
*
field
=
(
unsigned
char
*
)((
char
*
)
tp
+
attr
->
field_offset
);
unsigned
long
value
;
char
*
rest
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
255
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
255
)
return
-
EINVAL
;
*
field
=
value
;
...
...
@@ -117,10 +115,8 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data,
struct
trackpoint_attr_data
*
attr
=
data
;
unsigned
char
*
field
=
(
unsigned
char
*
)((
char
*
)
tp
+
attr
->
field_offset
);
unsigned
long
value
;
char
*
rest
;
value
=
simple_strtoul
(
buf
,
&
rest
,
10
);
if
(
*
rest
||
value
>
1
)
if
(
strict_strtoul
(
buf
,
10
,
&
value
)
||
value
>
1
)
return
-
EINVAL
;
if
(
attr
->
inverted
)
...
...
drivers/input/serio/i8042-x86ia64io.h
View file @
4c0e799a
...
...
@@ -322,6 +322,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"N34AS6"
),
},
},
{
.
ident
=
"IBM 2656"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"IBM"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"2656"
),
},
},
{
}
};
...
...
drivers/input/serio/serio_raw.c
View file @
4c0e799a
...
...
@@ -373,6 +373,12 @@ static struct serio_device_id serio_raw_serio_ids[] = {
.
id
=
SERIO_ANY
,
.
extra
=
SERIO_ANY
,
},
{
.
type
=
SERIO_8042_XL
,
.
proto
=
SERIO_ANY
,
.
id
=
SERIO_ANY
,
.
extra
=
SERIO_ANY
,
},
{
0
}
};
...
...
drivers/input/tablet/aiptek.c
View file @
4c0e799a
...
...
@@ -1202,16 +1202,22 @@ static ssize_t
store_tabletXtilt
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
aiptek
*
aiptek
=
dev_get_drvdata
(
dev
);
int
x
;
long
x
;
if
(
strict_strtol
(
buf
,
10
,
&
x
))
{
size_t
len
=
buf
[
count
-
1
]
==
'\n'
?
count
-
1
:
count
;
if
(
strncmp
(
buf
,
"disable"
,
len
))
return
-
EINVAL
;
if
(
strcmp
(
buf
,
"disable"
)
==
0
)
{
aiptek
->
newSetting
.
xTilt
=
AIPTEK_TILT_DISABLE
;
}
else
{
x
=
(
int
)
simple_strtol
(
buf
,
NULL
,
10
);
if
(
x
>=
AIPTEK_TILT_MIN
&&
x
<=
AIPTEK_TILT_MAX
)
{
aiptek
->
newSetting
.
xTilt
=
x
;
}
if
(
x
<
AIPTEK_TILT_MIN
||
x
>
AIPTEK_TILT_MAX
)
return
-
EINVAL
;
aiptek
->
newSetting
.
xTilt
=
x
;
}
return
count
;
}
...
...
@@ -1238,16 +1244,22 @@ static ssize_t
store_tabletYtilt
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
aiptek
*
aiptek
=
dev_get_drvdata
(
dev
);
int
y
;
long
y
;
if
(
strict_strtol
(
buf
,
10
,
&
y
))
{
size_t
len
=
buf
[
count
-
1
]
==
'\n'
?
count
-
1
:
count
;
if
(
strncmp
(
buf
,
"disable"
,
len
))
return
-
EINVAL
;
if
(
strcmp
(
buf
,
"disable"
)
==
0
)
{
aiptek
->
newSetting
.
yTilt
=
AIPTEK_TILT_DISABLE
;
}
else
{
y
=
(
int
)
simple_strtol
(
buf
,
NULL
,
10
);
if
(
y
>=
AIPTEK_TILT_MIN
&&
y
<=
AIPTEK_TILT_MAX
)
{
aiptek
->
newSetting
.
yTilt
=
y
;
}
if
(
y
<
AIPTEK_TILT_MIN
||
y
>
AIPTEK_TILT_MAX
)
return
-
EINVAL
;
aiptek
->
newSetting
.
yTilt
=
y
;
}
return
count
;
}
...
...
@@ -1269,8 +1281,12 @@ static ssize_t
store_tabletJitterDelay
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
aiptek
*
aiptek
=
dev_get_drvdata
(
dev
);
long
j
;
if
(
strict_strtol
(
buf
,
10
,
&
j
))
return
-
EINVAL
;
aiptek
->
newSetting
.
jitterDelay
=
(
int
)
simple_strtol
(
buf
,
NULL
,
10
)
;
aiptek
->
newSetting
.
jitterDelay
=
(
int
)
j
;
return
count
;
}
...
...
@@ -1294,8 +1310,12 @@ static ssize_t
store_tabletProgrammableDelay
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
aiptek
*
aiptek
=
dev_get_drvdata
(
dev
);
long
d
;
aiptek
->
newSetting
.
programmableDelay
=
(
int
)
simple_strtol
(
buf
,
NULL
,
10
);
if
(
strict_strtol
(
buf
,
10
,
&
d
))
return
-
EINVAL
;
aiptek
->
newSetting
.
programmableDelay
=
(
int
)
d
;
return
count
;
}
...
...
@@ -1541,8 +1561,11 @@ static ssize_t
store_tabletWheel
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
{
struct
aiptek
*
aiptek
=
dev_get_drvdata
(
dev
);
long
w
;
if
(
strict_strtol
(
buf
,
10
,
&
w
))
return
-
EINVAL
;
aiptek
->
newSetting
.
wheel
=
(
int
)
simple_strtol
(
buf
,
NULL
,
10
)
;
aiptek
->
newSetting
.
wheel
=
(
int
)
w
;
return
count
;
}
...
...
drivers/input/touchscreen/ads7846.c
View file @
4c0e799a
...
...
@@ -24,6 +24,7 @@
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <asm/irq.h>
...
...
@@ -68,6 +69,17 @@ struct ts_event {
int
ignore
;
};
/*
* We allocate this separately to avoid cache line sharing issues when
* driver is used with DMA-based SPI controllers (like atmel_spi) on
* systems where main memory is not DMA-coherent (most non-x86 boards).
*/
struct
ads7846_packet
{
u8
read_x
,
read_y
,
read_z1
,
read_z2
,
pwrdown
;
u16
dummy
;
/* for the pwrdown read */
struct
ts_event
tc
;
};
struct
ads7846
{
struct
input_dev
*
input
;
char
phys
[
32
];
...
...
@@ -85,9 +97,7 @@ struct ads7846 {
u16
x_plate_ohms
;
u16
pressure_max
;
u8
read_x
,
read_y
,
read_z1
,
read_z2
,
pwrdown
;
u16
dummy
;
/* for the pwrdown read */
struct
ts_event
tc
;
struct
ads7846_packet
*
packet
;
struct
spi_transfer
xfer
[
18
];
struct
spi_message
msg
[
5
];
...
...
@@ -116,6 +126,7 @@ struct ads7846 {
void
*
filter_data
;
void
(
*
filter_cleanup
)(
void
*
data
);
int
(
*
get_pendown_state
)(
void
);
int
gpio_pendown
;
};
/* leave chip selected when we're done, for quicker re-select? */
...
...
@@ -461,10 +472,11 @@ static ssize_t ads7846_disable_store(struct device *dev,
const
char
*
buf
,
size_t
count
)
{
struct
ads7846
*
ts
=
dev_get_drvdata
(
dev
);
char
*
endp
;
int
i
;
long
i
;
if
(
strict_strtoul
(
buf
,
10
,
&
i
))
return
-
EINVAL
;
i
=
simple_strtoul
(
buf
,
&
endp
,
10
);
spin_lock_irq
(
&
ts
->
lock
);
if
(
i
)
...
...
@@ -491,6 +503,14 @@ static struct attribute_group ads784x_attr_group = {
/*--------------------------------------------------------------------------*/
static
int
get_pendown_state
(
struct
ads7846
*
ts
)
{
if
(
ts
->
get_pendown_state
)
return
ts
->
get_pendown_state
();
return
!
gpio_get_value
(
ts
->
gpio_pendown
);
}
/*
* PENIRQ only kicks the timer. The timer only reissues the SPI transfer,
* to retrieve touchscreen status.
...
...
@@ -502,16 +522,17 @@ static struct attribute_group ads784x_attr_group = {
static
void
ads7846_rx
(
void
*
ads
)
{
struct
ads7846
*
ts
=
ads
;
struct
ads7846_packet
*
packet
=
ts
->
packet
;
unsigned
Rt
;
u16
x
,
y
,
z1
,
z2
;
/* ads7846_rx_val() did in-place conversion (including byteswap) from
* on-the-wire format as part of debouncing to get stable readings.
*/
x
=
ts
->
tc
.
x
;
y
=
ts
->
tc
.
y
;
z1
=
ts
->
tc
.
z1
;
z2
=
ts
->
tc
.
z2
;
x
=
packet
->
tc
.
x
;
y
=
packet
->
tc
.
y
;
z1
=
packet
->
tc
.
z1
;
z2
=
packet
->
tc
.
z2
;
/* range filtering */
if
(
x
==
MAX_12BIT
)
...
...
@@ -535,10 +556,10 @@ static void ads7846_rx(void *ads)
* the maximum. Don't report it to user space, repeat at least
* once more the measurement
*/
if
(
ts
->
tc
.
ignore
||
Rt
>
ts
->
pressure_max
)
{
if
(
packet
->
tc
.
ignore
||
Rt
>
ts
->
pressure_max
)
{
#ifdef VERBOSE
pr_debug
(
"%s: ignored %d pressure %d
\n
"
,
ts
->
spi
->
dev
.
bus_id
,
ts
->
tc
.
ignore
,
Rt
);
ts
->
spi
->
dev
.
bus_id
,
packet
->
tc
.
ignore
,
Rt
);
#endif
hrtimer_start
(
&
ts
->
timer
,
ktime_set
(
0
,
TS_POLL_PERIOD
),
HRTIMER_MODE_REL
);
...
...
@@ -550,7 +571,7 @@ static void ads7846_rx(void *ads)
*/
if
(
ts
->
penirq_recheck_delay_usecs
)
{
udelay
(
ts
->
penirq_recheck_delay_usecs
);
if
(
!
ts
->
get_pendown_state
(
))
if
(
!
get_pendown_state
(
ts
))
Rt
=
0
;
}
...
...
@@ -631,6 +652,7 @@ static int ads7846_no_filter(void *ads, int data_idx, int *val)
static
void
ads7846_rx_val
(
void
*
ads
)
{
struct
ads7846
*
ts
=
ads
;
struct
ads7846_packet
*
packet
=
ts
->
packet
;
struct
spi_message
*
m
;
struct
spi_transfer
*
t
;
int
val
;
...
...
@@ -650,7 +672,7 @@ static void ads7846_rx_val(void *ads)
case
ADS7846_FILTER_REPEAT
:
break
;
case
ADS7846_FILTER_IGNORE
:
ts
->
tc
.
ignore
=
1
;
packet
->
tc
.
ignore
=
1
;
/* Last message will contain ads7846_rx() as the
* completion function.
*/
...
...
@@ -658,7 +680,7 @@ static void ads7846_rx_val(void *ads)
break
;
case
ADS7846_FILTER_OK
:
*
(
u16
*
)
t
->
rx_buf
=
val
;
ts
->
tc
.
ignore
=
0
;
packet
->
tc
.
ignore
=
0
;
m
=
&
ts
->
msg
[
++
ts
->
msg_idx
];
break
;
default:
...
...
@@ -677,7 +699,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
spin_lock_irq
(
&
ts
->
lock
);
if
(
unlikely
(
!
ts
->
get_pendown_state
(
)
||
if
(
unlikely
(
!
get_pendown_state
(
ts
)
||
device_suspended
(
&
ts
->
spi
->
dev
)))
{
if
(
ts
->
pendown
)
{
struct
input_dev
*
input
=
ts
->
input
;
...
...
@@ -716,7 +738,7 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
unsigned
long
flags
;
spin_lock_irqsave
(
&
ts
->
lock
,
flags
);
if
(
likely
(
ts
->
get_pendown_state
(
)))
{
if
(
likely
(
get_pendown_state
(
ts
)))
{
if
(
!
ts
->
irq_disabled
)
{
/* The ARM do_simple_IRQ() dispatcher doesn't act
* like the other dispatchers: it will report IRQs
...
...
@@ -763,7 +785,6 @@ static void ads7846_disable(struct ads7846 *ts)
/* we know the chip's in lowpower mode since we always
* leave it that way after every request
*/
}
/* Must be called with ts->lock held */
...
...
@@ -806,9 +827,40 @@ static int ads7846_resume(struct spi_device *spi)
return
0
;
}
static
int
__devinit
setup_pendown
(
struct
spi_device
*
spi
,
struct
ads7846
*
ts
)
{
struct
ads7846_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
int
err
;
/* REVISIT when the irq can be triggered active-low, or if for some
* reason the touchscreen isn't hooked up, we don't need to access
* the pendown state.
*/
if
(
!
pdata
->
get_pendown_state
&&
!
gpio_is_valid
(
pdata
->
gpio_pendown
))
{
dev_err
(
&
spi
->
dev
,
"no get_pendown_state nor gpio_pendown?
\n
"
);
return
-
EINVAL
;
}
if
(
pdata
->
get_pendown_state
)
{
ts
->
get_pendown_state
=
pdata
->
get_pendown_state
;
return
0
;
}
err
=
gpio_request
(
pdata
->
gpio_pendown
,
"ads7846_pendown"
);
if
(
err
)
{
dev_err
(
&
spi
->
dev
,
"failed to request pendown GPIO%d
\n
"
,
pdata
->
gpio_pendown
);
return
err
;
}
ts
->
gpio_pendown
=
pdata
->
gpio_pendown
;
return
0
;
}
static
int
__devinit
ads7846_probe
(
struct
spi_device
*
spi
)
{
struct
ads7846
*
ts
;
struct
ads7846_packet
*
packet
;
struct
input_dev
*
input_dev
;
struct
ads7846_platform_data
*
pdata
=
spi
->
dev
.
platform_data
;
struct
spi_message
*
m
;
...
...
@@ -833,15 +885,6 @@ static int __devinit ads7846_probe(struct spi_device *spi)
return
-
EINVAL
;
}
/* REVISIT when the irq can be triggered active-low, or if for some
* reason the touchscreen isn't hooked up, we don't need to access
* the pendown state.
*/
if
(
pdata
->
get_pendown_state
==
NULL
)
{
dev_dbg
(
&
spi
->
dev
,
"no get_pendown_state function?
\n
"
);
return
-
EINVAL
;
}
/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
* that even if the hardware can do that, the SPI controller driver
* may not. So we stick to very-portable 8 bit words, both RX and TX.
...
...
@@ -853,14 +896,16 @@ static int __devinit ads7846_probe(struct spi_device *spi)
return
err
;
ts
=
kzalloc
(
sizeof
(
struct
ads7846
),
GFP_KERNEL
);
packet
=
kzalloc
(
sizeof
(
struct
ads7846_packet
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
ts
||
!
input_dev
)
{
if
(
!
ts
||
!
packet
||
!
input_dev
)
{
err
=
-
ENOMEM
;
goto
err_free_mem
;
}
dev_set_drvdata
(
&
spi
->
dev
,
ts
);
ts
->
packet
=
packet
;
ts
->
spi
=
spi
;
ts
->
input
=
input_dev
;
ts
->
vref_mv
=
pdata
->
vref_mv
;
...
...
@@ -893,7 +938,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts
->
filter_data
=
ts
;
}
else
ts
->
filter
=
ads7846_no_filter
;
ts
->
get_pendown_state
=
pdata
->
get_pendown_state
;
err
=
setup_pendown
(
spi
,
ts
);
if
(
err
)
goto
err_cleanup_filter
;
if
(
pdata
->
penirq_recheck_delay_usecs
)
ts
->
penirq_recheck_delay_usecs
=
...
...
@@ -929,13 +977,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init
(
m
);
/* y- still on; turn on only y+ (and ADC) */
ts
->
read_y
=
READ_Y
(
vref
);
x
->
tx_buf
=
&
ts
->
read_y
;
packet
->
read_y
=
READ_Y
(
vref
);
x
->
tx_buf
=
&
packet
->
read_y
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
y
;
x
->
rx_buf
=
&
packet
->
tc
.
y
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
...
...
@@ -947,12 +995,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x
->
delay_usecs
=
pdata
->
settle_delay_usecs
;
x
++
;
x
->
tx_buf
=
&
ts
->
read_y
;
x
->
tx_buf
=
&
packet
->
read_y
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
y
;
x
->
rx_buf
=
&
packet
->
tc
.
y
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
}
...
...
@@ -965,13 +1013,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
/* turn y- off, x+ on, then leave in lowpower */
x
++
;
ts
->
read_x
=
READ_X
(
vref
);
x
->
tx_buf
=
&
ts
->
read_x
;
packet
->
read_x
=
READ_X
(
vref
);
x
->
tx_buf
=
&
packet
->
read_x
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
x
;
x
->
rx_buf
=
&
packet
->
tc
.
x
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
...
...
@@ -980,12 +1028,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x
->
delay_usecs
=
pdata
->
settle_delay_usecs
;
x
++
;
x
->
tx_buf
=
&
ts
->
read_x
;
x
->
tx_buf
=
&
packet
->
read_x
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
x
;
x
->
rx_buf
=
&
packet
->
tc
.
x
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
}
...
...
@@ -999,13 +1047,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init
(
m
);
x
++
;
ts
->
read_z1
=
READ_Z1
(
vref
);
x
->
tx_buf
=
&
ts
->
read_z1
;
packet
->
read_z1
=
READ_Z1
(
vref
);
x
->
tx_buf
=
&
packet
->
read_z1
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
z1
;
x
->
rx_buf
=
&
packet
->
tc
.
z1
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
...
...
@@ -1014,12 +1062,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x
->
delay_usecs
=
pdata
->
settle_delay_usecs
;
x
++
;
x
->
tx_buf
=
&
ts
->
read_z1
;
x
->
tx_buf
=
&
packet
->
read_z1
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
z1
;
x
->
rx_buf
=
&
packet
->
tc
.
z1
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
}
...
...
@@ -1031,13 +1079,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init
(
m
);
x
++
;
ts
->
read_z2
=
READ_Z2
(
vref
);
x
->
tx_buf
=
&
ts
->
read_z2
;
packet
->
read_z2
=
READ_Z2
(
vref
);
x
->
tx_buf
=
&
packet
->
read_z2
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
z2
;
x
->
rx_buf
=
&
packet
->
tc
.
z2
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
...
...
@@ -1046,12 +1094,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
x
->
delay_usecs
=
pdata
->
settle_delay_usecs
;
x
++
;
x
->
tx_buf
=
&
ts
->
read_z2
;
x
->
tx_buf
=
&
packet
->
read_z2
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
tc
.
z2
;
x
->
rx_buf
=
&
packet
->
tc
.
z2
;
x
->
len
=
2
;
spi_message_add_tail
(
x
,
m
);
}
...
...
@@ -1065,13 +1113,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi_message_init
(
m
);
x
++
;
ts
->
pwrdown
=
PWRDOWN
;
x
->
tx_buf
=
&
ts
->
pwrdown
;
packet
->
pwrdown
=
PWRDOWN
;
x
->
tx_buf
=
&
packet
->
pwrdown
;
x
->
len
=
1
;
spi_message_add_tail
(
x
,
m
);
x
++
;
x
->
rx_buf
=
&
ts
->
dummy
;
x
->
rx_buf
=
&
packet
->
dummy
;
x
->
len
=
2
;
CS_CHANGE
(
*
x
);
spi_message_add_tail
(
x
,
m
);
...
...
@@ -1085,7 +1133,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
spi
->
dev
.
driver
->
name
,
ts
))
{
dev_dbg
(
&
spi
->
dev
,
"irq %d busy?
\n
"
,
spi
->
irq
);
err
=
-
EBUSY
;
goto
err_
cleanup_filter
;
goto
err_
free_gpio
;
}
err
=
ads784x_hwmon_register
(
spi
,
ts
);
...
...
@@ -1116,11 +1164,15 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ads784x_hwmon_unregister
(
spi
,
ts
);
err_free_irq:
free_irq
(
spi
->
irq
,
ts
);
err_free_gpio:
if
(
ts
->
gpio_pendown
!=
-
1
)
gpio_free
(
ts
->
gpio_pendown
);
err_cleanup_filter:
if
(
ts
->
filter_cleanup
)
ts
->
filter_cleanup
(
ts
->
filter_data
);
err_free_mem:
input_free_device
(
input_dev
);
kfree
(
packet
);
kfree
(
ts
);
return
err
;
}
...
...
@@ -1140,9 +1192,13 @@ static int __devexit ads7846_remove(struct spi_device *spi)
/* suspend left the IRQ disabled */
enable_irq
(
ts
->
spi
->
irq
);
if
(
ts
->
gpio_pendown
!=
-
1
)
gpio_free
(
ts
->
gpio_pendown
);
if
(
ts
->
filter_cleanup
)
ts
->
filter_cleanup
(
ts
->
filter_data
);
kfree
(
ts
->
packet
);
kfree
(
ts
);
dev_dbg
(
&
spi
->
dev
,
"unregistered touchscreen
\n
"
);
...
...
drivers/input/touchscreen/atmel_tsadcc.c
View file @
4c0e799a
...
...
@@ -91,6 +91,9 @@ struct atmel_tsadcc {
char
phys
[
32
];
struct
clk
*
clk
;
int
irq
;
unsigned
int
prev_absx
;
unsigned
int
prev_absy
;
unsigned
char
bufferedmeasure
;
};
static
void
__iomem
*
tsc_base
;
...
...
@@ -100,10 +103,9 @@ static void __iomem *tsc_base;
static
irqreturn_t
atmel_tsadcc_interrupt
(
int
irq
,
void
*
dev
)
{
struct
input_dev
*
input_dev
=
((
struct
atmel_tsadcc
*
)
dev
)
->
input
;
struct
atmel_tsadcc
*
ts_dev
=
(
struct
atmel_tsadcc
*
)
dev
;
struct
input_dev
*
input_dev
=
ts_dev
->
input
;
unsigned
int
absx
;
unsigned
int
absy
;
unsigned
int
status
;
unsigned
int
reg
;
...
...
@@ -121,6 +123,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
atmel_tsadcc_write
(
ATMEL_TSADCC_IER
,
ATMEL_TSADCC_PENCNT
);
input_report_key
(
input_dev
,
BTN_TOUCH
,
0
);
ts_dev
->
bufferedmeasure
=
0
;
input_sync
(
input_dev
);
}
else
if
(
status
&
ATMEL_TSADCC_PENCNT
)
{
...
...
@@ -138,16 +141,23 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
}
else
if
(
status
&
ATMEL_TSADCC_EOC
(
3
))
{
/* Conversion finished */
absx
=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR3
)
<<
10
;
absx
/=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR2
);
absy
=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR1
)
<<
10
;
absy
/=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR0
);
input_report_abs
(
input_dev
,
ABS_X
,
absx
);
input_report_abs
(
input_dev
,
ABS_Y
,
absy
);
input_report_key
(
input_dev
,
BTN_TOUCH
,
1
);
input_sync
(
input_dev
);
if
(
ts_dev
->
bufferedmeasure
)
{
/* Last measurement is always discarded, since it can
* be erroneous.
* Always report previous measurement */
input_report_abs
(
input_dev
,
ABS_X
,
ts_dev
->
prev_absx
);
input_report_abs
(
input_dev
,
ABS_Y
,
ts_dev
->
prev_absy
);
input_report_key
(
input_dev
,
BTN_TOUCH
,
1
);
input_sync
(
input_dev
);
}
else
ts_dev
->
bufferedmeasure
=
1
;
/* Now make new measurement */
ts_dev
->
prev_absx
=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR3
)
<<
10
;
ts_dev
->
prev_absx
/=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR2
);
ts_dev
->
prev_absy
=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR1
)
<<
10
;
ts_dev
->
prev_absy
/=
atmel_tsadcc_read
(
ATMEL_TSADCC_CDR0
);
}
return
IRQ_HANDLED
;
...
...
@@ -223,6 +233,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev)
}
ts_dev
->
input
=
input_dev
;
ts_dev
->
bufferedmeasure
=
0
;
snprintf
(
ts_dev
->
phys
,
sizeof
(
ts_dev
->
phys
),
"%s/input0"
,
pdev
->
dev
.
bus_id
);
...
...
drivers/input/touchscreen/mainstone-wm97xx.c
View file @
4c0e799a
...
...
@@ -3,8 +3,7 @@
* Wolfson WM97xx AC97 Codecs.
*
* Copyright 2004, 2007 Wolfson Microelectronics PLC.
* Author: Liam Girdwood
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
*
...
...
@@ -296,6 +295,6 @@ module_init(mainstone_wm97xx_init);
module_exit
(
mainstone_wm97xx_exit
);
/* Module information */
MODULE_AUTHOR
(
"Liam Girdwood <l
iam.girdwood@wolfsonmicro.com
>"
);
MODULE_AUTHOR
(
"Liam Girdwood <l
rg@slimlogic.co.uk
>"
);
MODULE_DESCRIPTION
(
"wm97xx continuous touch driver for mainstone"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/touchscreen/wm9705.c
View file @
4c0e799a
...
...
@@ -2,8 +2,7 @@
* wm9705.c -- Codec driver for Wolfson WM9705 AC97 Codec.
*
* Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
* Author: Liam Girdwood
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
...
...
@@ -347,6 +346,6 @@ struct wm97xx_codec_drv wm9705_codec = {
EXPORT_SYMBOL_GPL
(
wm9705_codec
);
/* Module information */
MODULE_AUTHOR
(
"Liam Girdwood <l
iam.girdwood@wolfsonmicro.com
>"
);
MODULE_AUTHOR
(
"Liam Girdwood <l
rg@slimlogic.co.uk
>"
);
MODULE_DESCRIPTION
(
"WM9705 Touch Screen Driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/touchscreen/wm9712.c
View file @
4c0e799a
...
...
@@ -2,8 +2,7 @@
* wm9712.c -- Codec driver for Wolfson WM9712 AC97 Codecs.
*
* Copyright 2003, 2004, 2005, 2006, 2007 Wolfson Microelectronics PLC.
* Author: Liam Girdwood
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
...
...
@@ -462,6 +461,6 @@ struct wm97xx_codec_drv wm9712_codec = {
EXPORT_SYMBOL_GPL
(
wm9712_codec
);
/* Module information */
MODULE_AUTHOR
(
"Liam Girdwood <l
iam.girdwood@wolfsonmicro.com
>"
);
MODULE_AUTHOR
(
"Liam Girdwood <l
rg@slimlogic.co.uk
>"
);
MODULE_DESCRIPTION
(
"WM9712 Touch Screen Driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/touchscreen/wm9713.c
View file @
4c0e799a
...
...
@@ -2,8 +2,7 @@
* wm9713.c -- Codec touch driver for Wolfson WM9713 AC97 Codec.
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
* Author: Liam Girdwood
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
...
...
@@ -476,6 +475,6 @@ struct wm97xx_codec_drv wm9713_codec = {
EXPORT_SYMBOL_GPL
(
wm9713_codec
);
/* Module information */
MODULE_AUTHOR
(
"Liam Girdwood <l
iam.girdwood@wolfsonmicro.com
>"
);
MODULE_AUTHOR
(
"Liam Girdwood <l
rg@slimlogic.co.uk
>"
);
MODULE_DESCRIPTION
(
"WM9713 Touch Screen Driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/touchscreen/wm97xx-core.c
View file @
4c0e799a
...
...
@@ -3,8 +3,7 @@
* and WM9713 AC97 Codecs.
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008 Wolfson Microelectronics PLC.
* Author: Liam Girdwood
* liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
* Parts Copyright : Ian Molton <spyro@f2s.com>
* Andrew Zabolotny <zap@homelink.ru>
* Russell King <rmk@arm.linux.org.uk>
...
...
@@ -824,6 +823,6 @@ module_init(wm97xx_init);
module_exit
(
wm97xx_exit
);
/* Module information */
MODULE_AUTHOR
(
"Liam Girdwood <l
iam.girdwood@wolfsonmicro.com
>"
);
MODULE_AUTHOR
(
"Liam Girdwood <l
rg@slimlogic.co.uk
>"
);
MODULE_DESCRIPTION
(
"WM97xx Core - Touch Screen / AUX ADC / GPIO Driver"
);
MODULE_LICENSE
(
"GPL"
);
include/linux/Kbuild
View file @
4c0e799a
...
...
@@ -107,6 +107,7 @@ header-y += keyctl.h
header-y += limits.h
header-y += magic.h
header-y += major.h
header-y += map_to_7segment.h
header-y += matroxfb.h
header-y += meye.h
header-y += minix_fs.h
...
...
include/linux/gameport.h
View file @
4c0e799a
...
...
@@ -146,10 +146,11 @@ static inline void gameport_unpin_driver(struct gameport *gameport)
mutex_unlock
(
&
gameport
->
drv_mutex
);
}
void
__gameport_register_driver
(
struct
gameport_driver
*
drv
,
struct
module
*
owner
);
static
inline
void
gameport_register_driver
(
struct
gameport_driver
*
drv
)
int
__gameport_register_driver
(
struct
gameport_driver
*
drv
,
struct
module
*
owner
,
const
char
*
mod_name
);
static
inline
int
__must_check
gameport_register_driver
(
struct
gameport_driver
*
drv
)
{
__gameport_register_driver
(
drv
,
THIS_MODUL
E
);
return
__gameport_register_driver
(
drv
,
THIS_MODULE
,
KBUILD_MODNAM
E
);
}
void
gameport_unregister_driver
(
struct
gameport_driver
*
drv
);
...
...
include/linux/input.h
View file @
4c0e799a
...
...
@@ -577,9 +577,22 @@ struct input_absinfo {
#define KEY_BRL_DOT9 0x1f9
#define KEY_BRL_DOT10 0x1fa
#define KEY_NUMERIC_0 0x200
/* used by phones, remote controls, */
#define KEY_NUMERIC_1 0x201
/* and other keypads */
#define KEY_NUMERIC_2 0x202
#define KEY_NUMERIC_3 0x203
#define KEY_NUMERIC_4 0x204
#define KEY_NUMERIC_5 0x205
#define KEY_NUMERIC_6 0x206
#define KEY_NUMERIC_7 0x207
#define KEY_NUMERIC_8 0x208
#define KEY_NUMERIC_9 0x209
#define KEY_NUMERIC_STAR 0x20a
#define KEY_NUMERIC_POUND 0x20b
/* We avoid low common keys in module aliases so they don't get huge. */
#define KEY_MIN_INTERESTING KEY_MUTE
#define KEY_MAX 0x
1
ff
#define KEY_MAX 0x
2
ff
#define KEY_CNT (KEY_MAX+1)
/*
...
...
drivers/input/misc
/map_to_7segment.h
→
include/linux
/map_to_7segment.h
View file @
4c0e799a
/*
* drivers/usb/input/map_to_7segment.h
*
* Copyright (c) 2005 Henk Vergonet <Henk.Vergonet@gmail.com>
*
* This program is free software; you can redistribute it and/or
...
...
@@ -36,7 +34,7 @@
* Usage:
*
* Register a map variable, and fill it with a character set:
*
static SEG7_DEFAULT_MAP(map_seg7);
* static SEG7_DEFAULT_MAP(map_seg7);
*
*
* Then use for conversion:
...
...
include/linux/mod_devicetable.h
View file @
4c0e799a
...
...
@@ -274,7 +274,7 @@ struct pcmcia_device_id {
/* Input */
#define INPUT_DEVICE_ID_EV_MAX 0x1f
#define INPUT_DEVICE_ID_KEY_MIN_INTERESTING 0x71
#define INPUT_DEVICE_ID_KEY_MAX 0x
1
ff
#define INPUT_DEVICE_ID_KEY_MAX 0x
2
ff
#define INPUT_DEVICE_ID_REL_MAX 0x0f
#define INPUT_DEVICE_ID_ABS_MAX 0x3f
#define INPUT_DEVICE_ID_MSC_MAX 0x07
...
...
include/linux/spi/ads7846.h
View file @
4c0e799a
...
...
@@ -43,6 +43,9 @@ struct ads7846_platform_data {
u16
debounce_tol
;
/* tolerance used for filtering */
u16
debounce_rep
;
/* additional consecutive good readings
* required after the first two */
int
gpio_pendown
;
/* the GPIO used to decide the pendown
* state if get_pendown_state == NULL
*/
int
(
*
get_pendown_state
)(
void
);
int
(
*
filter_init
)
(
struct
ads7846_platform_data
*
pdata
,
void
**
filter_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