Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
1dd32946
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
1dd32946
编写于
12月 30, 2008
作者:
D
Dmitry Torokhov
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into for-linus
上级
4a6908a3
e941da31
变更
54
隐藏空白更改
内联
并排
Showing
54 changed file
with
3098 addition
and
522 deletion
+3098
-522
Documentation/input/walkera0701.txt
Documentation/input/walkera0701.txt
+109
-0
arch/arm/mach-pxa/include/mach/pxa930_rotary.h
arch/arm/mach-pxa/include/mach/pxa930_rotary.h
+20
-0
arch/arm/mach-pxa/include/mach/pxa930_trkball.h
arch/arm/mach-pxa/include/mach/pxa930_trkball.h
+10
-0
drivers/input/Makefile
drivers/input/Makefile
+1
-1
drivers/input/evbug.c
drivers/input/evbug.c
+3
-3
drivers/input/evdev.c
drivers/input/evdev.c
+9
-190
drivers/input/gameport/gameport.c
drivers/input/gameport/gameport.c
+1
-2
drivers/input/gameport/ns558.c
drivers/input/gameport/ns558.c
+1
-1
drivers/input/input-compat.c
drivers/input/input-compat.c
+135
-0
drivers/input/input-compat.h
drivers/input/input-compat.h
+94
-0
drivers/input/input.c
drivers/input/input.c
+2
-2
drivers/input/joydev.c
drivers/input/joydev.c
+1
-1
drivers/input/joystick/Kconfig
drivers/input/joystick/Kconfig
+24
-0
drivers/input/joystick/Makefile
drivers/input/joystick/Makefile
+2
-0
drivers/input/joystick/maplecontrol.c
drivers/input/joystick/maplecontrol.c
+193
-0
drivers/input/joystick/walkera0701.c
drivers/input/joystick/walkera0701.c
+292
-0
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Kconfig
+9
-0
drivers/input/keyboard/Makefile
drivers/input/keyboard/Makefile
+1
-0
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/atkbd.c
+60
-0
drivers/input/keyboard/gpio_keys.c
drivers/input/keyboard/gpio_keys.c
+4
-0
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/hil_kbd.c
+1
-0
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/omap-keypad.c
+1
-5
drivers/input/keyboard/pxa930_rotary.c
drivers/input/keyboard/pxa930_rotary.c
+212
-0
drivers/input/misc/pcspkr.c
drivers/input/misc/pcspkr.c
+2
-2
drivers/input/misc/uinput.c
drivers/input/misc/uinput.c
+145
-27
drivers/input/mouse/Kconfig
drivers/input/mouse/Kconfig
+6
-0
drivers/input/mouse/Makefile
drivers/input/mouse/Makefile
+14
-13
drivers/input/mouse/appletouch.c
drivers/input/mouse/appletouch.c
+136
-138
drivers/input/mouse/gpio_mouse.c
drivers/input/mouse/gpio_mouse.c
+1
-1
drivers/input/mouse/hgpk.c
drivers/input/mouse/hgpk.c
+28
-4
drivers/input/mouse/hil_ptr.c
drivers/input/mouse/hil_ptr.c
+1
-1
drivers/input/mouse/pxa930_trkball.c
drivers/input/mouse/pxa930_trkball.c
+269
-0
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.c
+10
-6
drivers/input/mousedev.c
drivers/input/mousedev.c
+1
-2
drivers/input/serio/hil_mlc.c
drivers/input/serio/hil_mlc.c
+1
-0
drivers/input/serio/i8042-x86ia64io.h
drivers/input/serio/i8042-x86ia64io.h
+8
-0
drivers/input/serio/libps2.c
drivers/input/serio/libps2.c
+16
-4
drivers/input/serio/pcips2.c
drivers/input/serio/pcips2.c
+1
-1
drivers/input/serio/serio.c
drivers/input/serio/serio.c
+2
-2
drivers/input/serio/xilinx_ps2.c
drivers/input/serio/xilinx_ps2.c
+113
-107
drivers/input/tablet/gtco.c
drivers/input/tablet/gtco.c
+1
-1
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.c
+1
-1
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Kconfig
+32
-0
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/Makefile
+3
-0
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/ads7846.c
+3
-3
drivers/input/touchscreen/da9034-ts.c
drivers/input/touchscreen/da9034-ts.c
+389
-0
drivers/input/touchscreen/tsc2007.c
drivers/input/touchscreen/tsc2007.c
+381
-0
drivers/input/touchscreen/usbtouchscreen.c
drivers/input/touchscreen/usbtouchscreen.c
+2
-3
drivers/input/touchscreen/wacom_w8001.c
drivers/input/touchscreen/wacom_w8001.c
+325
-0
include/linux/gpio_keys.h
include/linux/gpio_keys.h
+1
-0
include/linux/i2c/tsc2007.h
include/linux/i2c/tsc2007.h
+17
-0
include/linux/libps2.h
include/linux/libps2.h
+2
-0
include/linux/map_to_7segment.h
include/linux/map_to_7segment.h
+1
-1
include/linux/serio.h
include/linux/serio.h
+1
-0
未找到文件。
Documentation/input/walkera0701.txt
0 → 100644
浏览文件 @
1dd32946
Walkera WK-0701 transmitter is supplied with a ready to fly Walkera
helicopters such as HM36, HM37, HM60. The walkera0701 module enables to use
this transmitter as joystick
Devel homepage and download:
http://zub.fei.tuke.sk/walkera-wk0701/
or use cogito:
cg-clone http://zub.fei.tuke.sk/GIT/walkera0701-joystick
Connecting to PC:
At back side of transmitter S-video connector can be found. Modulation
pulses from processor to HF part can be found at pin 2 of this connector,
pin 3 is GND. Between pin 3 and CPU 5k6 resistor can be found. To get
modulation pulses to PC, signal pulses must be amplified.
Cable: (walkera TX to parport)
Walkera WK-0701 TX S-VIDEO connector:
(back side of TX)
__ __ S-video: canon25
/ |_| \ pin 2 (signal) NPN parport
/ O 4 3 O \ pin 3 (GND) LED ________________ 10 ACK
( O 2 1 O ) | C
\ ___ / 2 ________________________|\|_____|/
| [___] | |/| B |\
------- 3 __________________________________|________________ 25 GND
E
I use green LED and BC109 NPN transistor.
Software:
Build kernel with walkera0701 module. Module walkera0701 need exclusive
access to parport, modules like lp must be unloaded before loading
walkera0701 module, check dmesg for error messages. Connect TX to PC by
cable and run jstest /dev/input/js0 to see values from TX. If no value can
be changed by TX "joystick", check output from /proc/interrupts. Value for
(usually irq7) parport must increase if TX is on.
Technical details:
Driver use interrupt from parport ACK input bit to measure pulse length
using hrtimers.
Frame format:
Based on walkera WK-0701 PCM Format description by Shaul Eizikovich.
(downloaded from http://www.smartpropoplus.com/Docs/Walkera_Wk-0701_PCM.pdf)
Signal pulses:
(ANALOG)
SYNC BIN OCT
+---------+ +------+
| | | |
--+ +------+ +---
Frame:
SYNC , BIN1, OCT1, BIN2, OCT2 ... BIN24, OCT24, BIN25, next frame SYNC ..
pulse length:
Binary values: Analog octal values:
288 uS Binary 0 318 uS 000
438 uS Binary 1 398 uS 001
478 uS 010
558 uS 011
638 uS 100
1306 uS SYNC 718 uS 101
798 uS 110
878 uS 111
24 bin+oct values + 1 bin value = 24*4+1 bits = 97 bits
(Warning, pulses on ACK ar inverted by transistor, irq is rised up on sync
to bin change or octal value to bin change).
Binary data representations:
One binary and octal value can be grouped to nibble. 24 nibbles + one binary
values can be sampled between sync pulses.
Values for first four channels (analog joystick values) can be found in
first 10 nibbles. Analog value is represented by one sign bit and 9 bit
absolute binary value. (10 bits per channel). Next nibble is checksum for
first ten nibbles.
Next nibbles 12 .. 21 represents four channels (not all channels can be
directly controlled from TX). Binary representations ar the same as in first
four channels. In nibbles 22 and 23 is a special magic number. Nibble 24 is
checksum for nibbles 12..23.
After last octal value for nibble 24 and next sync pulse one additional
binary value can be sampled. This bit and magic number is not used in
software driver. Some details about this magic numbers can be found in
Walkera_Wk-0701_PCM.pdf.
Checksum calculation:
Summary of octal values in nibbles must be same as octal value in checksum
nibble (only first 3 bits are used). Binary value for checksum nibble is
calculated by sum of binary values in checked nibbles + sum of octal values
in checked nibbles divided by 8. Only bit 0 of this sum is used.
arch/arm/mach-pxa/include/mach/pxa930_rotary.h
0 → 100644
浏览文件 @
1dd32946
#ifndef __ASM_ARCH_PXA930_ROTARY_H
#define __ASM_ARCH_PXA930_ROTARY_H
/* NOTE:
*
* rotary can be either interpreted as a ralative input event (e.g.
* REL_WHEEL or REL_HWHEEL) or a specific key event (e.g. UP/DOWN
* or LEFT/RIGHT), depending on if up_key & down_key are assigned
* or rel_code is assigned a non-zero value. When all are non-zero,
* up_key and down_key will be preferred.
*/
struct
pxa930_rotary_platform_data
{
int
up_key
;
int
down_key
;
int
rel_code
;
};
void
__init
pxa930_set_rotarykey_info
(
struct
pxa930_rotary_platform_data
*
info
);
#endif
/* __ASM_ARCH_PXA930_ROTARY_H */
arch/arm/mach-pxa/include/mach/pxa930_trkball.h
0 → 100644
浏览文件 @
1dd32946
#ifndef __ASM_ARCH_PXA930_TRKBALL_H
#define __ASM_ARCH_PXA930_TRKBALL_H
struct
pxa930_trkball_platform_data
{
int
x_filter
;
int
y_filter
;
};
#endif
/* __ASM_ARCH_PXA930_TRKBALL_H */
drivers/input/Makefile
浏览文件 @
1dd32946
...
...
@@ -5,7 +5,7 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_INPUT)
+=
input-core.o
input-core-objs
:=
input.o ff-core.o
input-core-objs
:=
input.o
input-compat.o
ff-core.o
obj-$(CONFIG_INPUT_FF_MEMLESS)
+=
ff-memless.o
obj-$(CONFIG_INPUT_POLLDEV)
+=
input-polldev.o
...
...
drivers/input/evbug.c
浏览文件 @
1dd32946
...
...
@@ -39,7 +39,7 @@ MODULE_LICENSE("GPL");
static
void
evbug_event
(
struct
input_handle
*
handle
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
printk
(
KERN_DEBUG
"evbug.c: Event. Dev: %s, Type: %d, Code: %d, Value: %d
\n
"
,
handle
->
dev
->
dev
.
bus_id
,
type
,
code
,
value
);
dev_name
(
&
handle
->
dev
->
dev
)
,
type
,
code
,
value
);
}
static
int
evbug_connect
(
struct
input_handler
*
handler
,
struct
input_dev
*
dev
,
...
...
@@ -65,7 +65,7 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
goto
err_unregister_handle
;
printk
(
KERN_DEBUG
"evbug.c: Connected device: %s (%s at %s)
\n
"
,
dev
->
dev
.
bus_id
,
dev
_name
(
&
dev
->
dev
)
,
dev
->
name
?:
"unknown"
,
dev
->
phys
?:
"unknown"
);
...
...
@@ -81,7 +81,7 @@ static int evbug_connect(struct input_handler *handler, struct input_dev *dev,
static
void
evbug_disconnect
(
struct
input_handle
*
handle
)
{
printk
(
KERN_DEBUG
"evbug.c: Disconnected device: %s
\n
"
,
handle
->
dev
->
dev
.
bus_id
);
dev_name
(
&
handle
->
dev
->
dev
)
);
input_close_device
(
handle
);
input_unregister_handle
(
handle
);
...
...
drivers/input/evdev.c
浏览文件 @
1dd32946
...
...
@@ -19,7 +19,7 @@
#include <linux/input.h>
#include <linux/major.h>
#include <linux/device.h>
#include
<linux/compat.h>
#include
"input-compat.h"
struct
evdev
{
int
exist
;
...
...
@@ -290,187 +290,6 @@ static int evdev_open(struct inode *inode, struct file *file)
return
error
;
}
#ifdef CONFIG_COMPAT
struct
input_event_compat
{
struct
compat_timeval
time
;
__u16
type
;
__u16
code
;
__s32
value
;
};
struct
ff_periodic_effect_compat
{
__u16
waveform
;
__u16
period
;
__s16
magnitude
;
__s16
offset
;
__u16
phase
;
struct
ff_envelope
envelope
;
__u32
custom_len
;
compat_uptr_t
custom_data
;
};
struct
ff_effect_compat
{
__u16
type
;
__s16
id
;
__u16
direction
;
struct
ff_trigger
trigger
;
struct
ff_replay
replay
;
union
{
struct
ff_constant_effect
constant
;
struct
ff_ramp_effect
ramp
;
struct
ff_periodic_effect_compat
periodic
;
struct
ff_condition_effect
condition
[
2
];
/* One for each axis */
struct
ff_rumble_effect
rumble
;
}
u
;
};
/* Note to the author of this code: did it ever occur to
you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
# define COMPAT_TEST is_compat_task()
#elif defined(CONFIG_IA64)
# define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
#elif defined(CONFIG_S390)
# define COMPAT_TEST test_thread_flag(TIF_31BIT)
#elif defined(CONFIG_MIPS)
# define COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
#else
# define COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
static
inline
size_t
evdev_event_size
(
void
)
{
return
COMPAT_TEST
?
sizeof
(
struct
input_event_compat
)
:
sizeof
(
struct
input_event
);
}
static
int
evdev_event_from_user
(
const
char
__user
*
buffer
,
struct
input_event
*
event
)
{
if
(
COMPAT_TEST
)
{
struct
input_event_compat
compat_event
;
if
(
copy_from_user
(
&
compat_event
,
buffer
,
sizeof
(
struct
input_event_compat
)))
return
-
EFAULT
;
event
->
time
.
tv_sec
=
compat_event
.
time
.
tv_sec
;
event
->
time
.
tv_usec
=
compat_event
.
time
.
tv_usec
;
event
->
type
=
compat_event
.
type
;
event
->
code
=
compat_event
.
code
;
event
->
value
=
compat_event
.
value
;
}
else
{
if
(
copy_from_user
(
event
,
buffer
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
}
return
0
;
}
static
int
evdev_event_to_user
(
char
__user
*
buffer
,
const
struct
input_event
*
event
)
{
if
(
COMPAT_TEST
)
{
struct
input_event_compat
compat_event
;
compat_event
.
time
.
tv_sec
=
event
->
time
.
tv_sec
;
compat_event
.
time
.
tv_usec
=
event
->
time
.
tv_usec
;
compat_event
.
type
=
event
->
type
;
compat_event
.
code
=
event
->
code
;
compat_event
.
value
=
event
->
value
;
if
(
copy_to_user
(
buffer
,
&
compat_event
,
sizeof
(
struct
input_event_compat
)))
return
-
EFAULT
;
}
else
{
if
(
copy_to_user
(
buffer
,
event
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
}
return
0
;
}
static
int
evdev_ff_effect_from_user
(
const
char
__user
*
buffer
,
size_t
size
,
struct
ff_effect
*
effect
)
{
if
(
COMPAT_TEST
)
{
struct
ff_effect_compat
*
compat_effect
;
if
(
size
!=
sizeof
(
struct
ff_effect_compat
))
return
-
EINVAL
;
/*
* It so happens that the pointer which needs to be changed
* is the last field in the structure, so we can copy the
* whole thing and replace just the pointer.
*/
compat_effect
=
(
struct
ff_effect_compat
*
)
effect
;
if
(
copy_from_user
(
compat_effect
,
buffer
,
sizeof
(
struct
ff_effect_compat
)))
return
-
EFAULT
;
if
(
compat_effect
->
type
==
FF_PERIODIC
&&
compat_effect
->
u
.
periodic
.
waveform
==
FF_CUSTOM
)
effect
->
u
.
periodic
.
custom_data
=
compat_ptr
(
compat_effect
->
u
.
periodic
.
custom_data
);
}
else
{
if
(
size
!=
sizeof
(
struct
ff_effect
))
return
-
EINVAL
;
if
(
copy_from_user
(
effect
,
buffer
,
sizeof
(
struct
ff_effect
)))
return
-
EFAULT
;
}
return
0
;
}
#else
static
inline
size_t
evdev_event_size
(
void
)
{
return
sizeof
(
struct
input_event
);
}
static
int
evdev_event_from_user
(
const
char
__user
*
buffer
,
struct
input_event
*
event
)
{
if
(
copy_from_user
(
event
,
buffer
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
return
0
;
}
static
int
evdev_event_to_user
(
char
__user
*
buffer
,
const
struct
input_event
*
event
)
{
if
(
copy_to_user
(
buffer
,
event
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
return
0
;
}
static
int
evdev_ff_effect_from_user
(
const
char
__user
*
buffer
,
size_t
size
,
struct
ff_effect
*
effect
)
{
if
(
size
!=
sizeof
(
struct
ff_effect
))
return
-
EINVAL
;
if
(
copy_from_user
(
effect
,
buffer
,
sizeof
(
struct
ff_effect
)))
return
-
EFAULT
;
return
0
;
}
#endif
/* CONFIG_COMPAT */
static
ssize_t
evdev_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
...
...
@@ -490,14 +309,14 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
while
(
retval
<
count
)
{
if
(
evdev
_event_from_user
(
buffer
+
retval
,
&
event
))
{
if
(
input
_event_from_user
(
buffer
+
retval
,
&
event
))
{
retval
=
-
EFAULT
;
goto
out
;
}
input_inject_event
(
&
evdev
->
handle
,
event
.
type
,
event
.
code
,
event
.
value
);
retval
+=
evdev
_event_size
();
retval
+=
input
_event_size
();
}
out:
...
...
@@ -531,7 +350,7 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
struct
input_event
event
;
int
retval
;
if
(
count
<
evdev
_event_size
())
if
(
count
<
input
_event_size
())
return
-
EINVAL
;
if
(
client
->
head
==
client
->
tail
&&
evdev
->
exist
&&
...
...
@@ -546,13 +365,13 @@ static ssize_t evdev_read(struct file *file, char __user *buffer,
if
(
!
evdev
->
exist
)
return
-
ENODEV
;
while
(
retval
+
evdev
_event_size
()
<=
count
&&
while
(
retval
+
input
_event_size
()
<=
count
&&
evdev_fetch_next_event
(
client
,
&
event
))
{
if
(
evdev
_event_to_user
(
buffer
+
retval
,
&
event
))
if
(
input
_event_to_user
(
buffer
+
retval
,
&
event
))
return
-
EFAULT
;
retval
+=
evdev
_event_size
();
retval
+=
input
_event_size
();
}
return
retval
;
...
...
@@ -823,7 +642,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if
(
_IOC_NR
(
cmd
)
==
_IOC_NR
(
EVIOCSFF
))
{
if
(
evdev
_ff_effect_from_user
(
p
,
_IOC_SIZE
(
cmd
),
&
effect
))
if
(
input
_ff_effect_from_user
(
p
,
_IOC_SIZE
(
cmd
),
&
effect
))
return
-
EFAULT
;
error
=
input_ff_upload
(
dev
,
&
effect
,
file
);
...
...
@@ -1000,7 +819,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
evdev
->
handle
.
handler
=
handler
;
evdev
->
handle
.
private
=
evdev
;
strlcpy
(
evdev
->
dev
.
bus_id
,
evdev
->
name
,
sizeof
(
evdev
->
dev
.
bus_id
)
);
dev_set_name
(
&
evdev
->
dev
,
evdev
->
name
);
evdev
->
dev
.
devt
=
MKDEV
(
INPUT_MAJOR
,
EVDEV_MINOR_BASE
+
minor
);
evdev
->
dev
.
class
=
&
input_class
;
evdev
->
dev
.
parent
=
&
dev
->
dev
;
...
...
drivers/input/gameport/gameport.c
浏览文件 @
1dd32946
...
...
@@ -530,8 +530,7 @@ static void gameport_init_port(struct gameport *gameport)
mutex_init
(
&
gameport
->
drv_mutex
);
device_initialize
(
&
gameport
->
dev
);
snprintf
(
gameport
->
dev
.
bus_id
,
sizeof
(
gameport
->
dev
.
bus_id
),
"gameport%lu"
,
(
unsigned
long
)
atomic_inc_return
(
&
gameport_no
)
-
1
);
dev_set_name
(
&
gameport
->
dev
,
"gameport%lu"
,
(
unsigned
long
)
atomic_inc_return
(
&
gameport_no
)
-
1
);
gameport
->
dev
.
bus
=
&
gameport_bus
;
gameport
->
dev
.
release
=
gameport_release_port
;
if
(
gameport
->
parent
)
...
...
drivers/input/gameport/ns558.c
浏览文件 @
1dd32946
...
...
@@ -226,7 +226,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
ns558
->
gameport
=
port
;
gameport_set_name
(
port
,
"NS558 PnP Gameport"
);
gameport_set_phys
(
port
,
"pnp%s/gameport0"
,
dev
->
dev
.
bus_id
);
gameport_set_phys
(
port
,
"pnp%s/gameport0"
,
dev
_name
(
&
dev
->
dev
)
);
port
->
dev
.
parent
=
&
dev
->
dev
;
port
->
io
=
ioport
;
...
...
drivers/input/input-compat.c
0 → 100644
浏览文件 @
1dd32946
/*
* 32bit compatibility wrappers for the input subsystem.
*
* Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
*
* 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.
*/
#include <asm/uaccess.h>
#include "input-compat.h"
#ifdef CONFIG_COMPAT
int
input_event_from_user
(
const
char
__user
*
buffer
,
struct
input_event
*
event
)
{
if
(
INPUT_COMPAT_TEST
)
{
struct
input_event_compat
compat_event
;
if
(
copy_from_user
(
&
compat_event
,
buffer
,
sizeof
(
struct
input_event_compat
)))
return
-
EFAULT
;
event
->
time
.
tv_sec
=
compat_event
.
time
.
tv_sec
;
event
->
time
.
tv_usec
=
compat_event
.
time
.
tv_usec
;
event
->
type
=
compat_event
.
type
;
event
->
code
=
compat_event
.
code
;
event
->
value
=
compat_event
.
value
;
}
else
{
if
(
copy_from_user
(
event
,
buffer
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
}
return
0
;
}
int
input_event_to_user
(
char
__user
*
buffer
,
const
struct
input_event
*
event
)
{
if
(
INPUT_COMPAT_TEST
)
{
struct
input_event_compat
compat_event
;
compat_event
.
time
.
tv_sec
=
event
->
time
.
tv_sec
;
compat_event
.
time
.
tv_usec
=
event
->
time
.
tv_usec
;
compat_event
.
type
=
event
->
type
;
compat_event
.
code
=
event
->
code
;
compat_event
.
value
=
event
->
value
;
if
(
copy_to_user
(
buffer
,
&
compat_event
,
sizeof
(
struct
input_event_compat
)))
return
-
EFAULT
;
}
else
{
if
(
copy_to_user
(
buffer
,
event
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
}
return
0
;
}
int
input_ff_effect_from_user
(
const
char
__user
*
buffer
,
size_t
size
,
struct
ff_effect
*
effect
)
{
if
(
INPUT_COMPAT_TEST
)
{
struct
ff_effect_compat
*
compat_effect
;
if
(
size
!=
sizeof
(
struct
ff_effect_compat
))
return
-
EINVAL
;
/*
* It so happens that the pointer which needs to be changed
* is the last field in the structure, so we can retrieve the
* whole thing and replace just the pointer.
*/
compat_effect
=
(
struct
ff_effect_compat
*
)
effect
;
if
(
copy_from_user
(
compat_effect
,
buffer
,
sizeof
(
struct
ff_effect_compat
)))
return
-
EFAULT
;
if
(
compat_effect
->
type
==
FF_PERIODIC
&&
compat_effect
->
u
.
periodic
.
waveform
==
FF_CUSTOM
)
effect
->
u
.
periodic
.
custom_data
=
compat_ptr
(
compat_effect
->
u
.
periodic
.
custom_data
);
}
else
{
if
(
size
!=
sizeof
(
struct
ff_effect
))
return
-
EINVAL
;
if
(
copy_from_user
(
effect
,
buffer
,
sizeof
(
struct
ff_effect
)))
return
-
EFAULT
;
}
return
0
;
}
#else
int
input_event_from_user
(
const
char
__user
*
buffer
,
struct
input_event
*
event
)
{
if
(
copy_from_user
(
event
,
buffer
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
return
0
;
}
int
input_event_to_user
(
char
__user
*
buffer
,
const
struct
input_event
*
event
)
{
if
(
copy_to_user
(
buffer
,
event
,
sizeof
(
struct
input_event
)))
return
-
EFAULT
;
return
0
;
}
int
input_ff_effect_from_user
(
const
char
__user
*
buffer
,
size_t
size
,
struct
ff_effect
*
effect
)
{
if
(
size
!=
sizeof
(
struct
ff_effect
))
return
-
EINVAL
;
if
(
copy_from_user
(
effect
,
buffer
,
sizeof
(
struct
ff_effect
)))
return
-
EFAULT
;
return
0
;
}
#endif
/* CONFIG_COMPAT */
EXPORT_SYMBOL_GPL
(
input_event_from_user
);
EXPORT_SYMBOL_GPL
(
input_event_to_user
);
EXPORT_SYMBOL_GPL
(
input_ff_effect_from_user
);
drivers/input/input-compat.h
0 → 100644
浏览文件 @
1dd32946
#ifndef _INPUT_COMPAT_H
#define _INPUT_COMPAT_H
/*
* 32bit compatibility wrappers for the input subsystem.
*
* Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
*
* 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.
*/
#include <linux/compiler.h>
#include <linux/compat.h>
#include <linux/input.h>
#ifdef CONFIG_COMPAT
/* Note to the author of this code: did it ever occur to
you why the ifdefs are needed? Think about it again. -AK */
#ifdef CONFIG_X86_64
# define INPUT_COMPAT_TEST is_compat_task()
#elif defined(CONFIG_IA64)
# define INPUT_COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current))
#elif defined(CONFIG_S390)
# define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT)
#elif defined(CONFIG_MIPS)
# define INPUT_COMPAT_TEST test_thread_flag(TIF_32BIT_ADDR)
#else
# define INPUT_COMPAT_TEST test_thread_flag(TIF_32BIT)
#endif
struct
input_event_compat
{
struct
compat_timeval
time
;
__u16
type
;
__u16
code
;
__s32
value
;
};
struct
ff_periodic_effect_compat
{
__u16
waveform
;
__u16
period
;
__s16
magnitude
;
__s16
offset
;
__u16
phase
;
struct
ff_envelope
envelope
;
__u32
custom_len
;
compat_uptr_t
custom_data
;
};
struct
ff_effect_compat
{
__u16
type
;
__s16
id
;
__u16
direction
;
struct
ff_trigger
trigger
;
struct
ff_replay
replay
;
union
{
struct
ff_constant_effect
constant
;
struct
ff_ramp_effect
ramp
;
struct
ff_periodic_effect_compat
periodic
;
struct
ff_condition_effect
condition
[
2
];
/* One for each axis */
struct
ff_rumble_effect
rumble
;
}
u
;
};
static
inline
size_t
input_event_size
(
void
)
{
return
INPUT_COMPAT_TEST
?
sizeof
(
struct
input_event_compat
)
:
sizeof
(
struct
input_event
);
}
#else
static
inline
size_t
input_event_size
(
void
)
{
return
sizeof
(
struct
input_event
);
}
#endif
/* CONFIG_COMPAT */
int
input_event_from_user
(
const
char
__user
*
buffer
,
struct
input_event
*
event
);
int
input_event_to_user
(
char
__user
*
buffer
,
const
struct
input_event
*
event
);
int
input_ff_effect_from_user
(
const
char
__user
*
buffer
,
size_t
size
,
struct
ff_effect
*
effect
);
#endif
/* _INPUT_COMPAT_H */
drivers/input/input.c
浏览文件 @
1dd32946
...
...
@@ -1389,8 +1389,8 @@ int input_register_device(struct input_dev *dev)
if
(
!
dev
->
setkeycode
)
dev
->
setkeycode
=
input_default_setkeycode
;
snprintf
(
dev
->
dev
.
bus_id
,
sizeof
(
dev
->
dev
.
bus_id
)
,
"input%ld"
,
(
unsigned
long
)
atomic_inc_return
(
&
input_no
)
-
1
);
dev_set_name
(
&
dev
->
dev
,
"input%ld"
,
(
unsigned
long
)
atomic_inc_return
(
&
input_no
)
-
1
);
error
=
device_add
(
&
dev
->
dev
);
if
(
error
)
...
...
drivers/input/joydev.c
浏览文件 @
1dd32946
...
...
@@ -800,7 +800,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
}
}
strlcpy
(
joydev
->
dev
.
bus_id
,
joydev
->
name
,
sizeof
(
joydev
->
dev
.
bus_id
)
);
dev_set_name
(
&
joydev
->
dev
,
joydev
->
name
);
joydev
->
dev
.
devt
=
MKDEV
(
INPUT_MAJOR
,
JOYDEV_MINOR_BASE
+
minor
);
joydev
->
dev
.
class
=
&
input_class
;
joydev
->
dev
.
parent
=
&
dev
->
dev
;
...
...
drivers/input/joystick/Kconfig
浏览文件 @
1dd32946
...
...
@@ -294,4 +294,28 @@ config JOYSTICK_XPAD_LEDS
This option enables support for the LED which surrounds the Big X on
XBox 360 controller.
config JOYSTICK_WALKERA0701
tristate "Walkera WK-0701 RC transmitter"
depends on HIGH_RES_TIMERS && PARPORT
help
Say Y or M here if you have a Walkera WK-0701 transmitter which is
supplied with a ready to fly Walkera helicopters such as HM36,
HM37, HM60 and want to use it via parport as a joystick. More
information is available: <file:Documentation/input/walkera0701.txt>
To compile this driver as a module, choose M here: the
module will be called walkera0701.
config JOYSTICK_MAPLE
tristate "Dreamcast control pad"
depends on MAPLE
help
Say Y here if you have a SEGA Dreamcast and want to use your
controller as a joystick.
Most Dreamcast users will say Y.
To compile this as a module choose M here: the module will be called
maplecontrol.
endif
drivers/input/joystick/Makefile
浏览文件 @
1dd32946
...
...
@@ -19,6 +19,7 @@ obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
obj-$(CONFIG_JOYSTICK_INTERACT)
+=
interact.o
obj-$(CONFIG_JOYSTICK_JOYDUMP)
+=
joydump.o
obj-$(CONFIG_JOYSTICK_MAGELLAN)
+=
magellan.o
obj-$(CONFIG_JOYSTICK_MAPLE)
+=
maplecontrol.o
obj-$(CONFIG_JOYSTICK_SIDEWINDER)
+=
sidewinder.o
obj-$(CONFIG_JOYSTICK_SPACEBALL)
+=
spaceball.o
obj-$(CONFIG_JOYSTICK_SPACEORB)
+=
spaceorb.o
...
...
@@ -29,4 +30,5 @@ obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
obj-$(CONFIG_JOYSTICK_WARRIOR)
+=
warrior.o
obj-$(CONFIG_JOYSTICK_XPAD)
+=
xpad.o
obj-$(CONFIG_JOYSTICK_ZHENHUA)
+=
zhenhua.o
obj-$(CONFIG_JOYSTICK_WALKERA0701)
+=
walkera0701.o
drivers/input/joystick/maplecontrol.c
0 → 100644
浏览文件 @
1dd32946
/*
* SEGA Dreamcast controller driver
* Based on drivers/usb/iforce.c
*
* Copyright Yaegashi Takeshi, 2001
* Adrian McMenamin, 2008
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/maple.h>
MODULE_AUTHOR
(
"Adrian McMenamin <adrian@mcmen.demon.co.uk>"
);
MODULE_DESCRIPTION
(
"SEGA Dreamcast controller driver"
);
MODULE_LICENSE
(
"GPL"
);
struct
dc_pad
{
struct
input_dev
*
dev
;
struct
maple_device
*
mdev
;
};
static
void
dc_pad_callback
(
struct
mapleq
*
mq
)
{
unsigned
short
buttons
;
struct
maple_device
*
mapledev
=
mq
->
dev
;
struct
dc_pad
*
pad
=
maple_get_drvdata
(
mapledev
);
struct
input_dev
*
dev
=
pad
->
dev
;
unsigned
char
*
res
=
mq
->
recvbuf
;
buttons
=
~
le16_to_cpup
((
__le16
*
)(
res
+
8
));
input_report_abs
(
dev
,
ABS_HAT0Y
,
(
buttons
&
0x0010
?
-
1
:
0
)
+
(
buttons
&
0x0020
?
1
:
0
));
input_report_abs
(
dev
,
ABS_HAT0X
,
(
buttons
&
0x0040
?
-
1
:
0
)
+
(
buttons
&
0x0080
?
1
:
0
));
input_report_abs
(
dev
,
ABS_HAT1Y
,
(
buttons
&
0x1000
?
-
1
:
0
)
+
(
buttons
&
0x2000
?
1
:
0
));
input_report_abs
(
dev
,
ABS_HAT1X
,
(
buttons
&
0x4000
?
-
1
:
0
)
+
(
buttons
&
0x8000
?
1
:
0
));
input_report_key
(
dev
,
BTN_C
,
buttons
&
0x0001
);
input_report_key
(
dev
,
BTN_B
,
buttons
&
0x0002
);
input_report_key
(
dev
,
BTN_A
,
buttons
&
0x0004
);
input_report_key
(
dev
,
BTN_START
,
buttons
&
0x0008
);
input_report_key
(
dev
,
BTN_Z
,
buttons
&
0x0100
);
input_report_key
(
dev
,
BTN_Y
,
buttons
&
0x0200
);
input_report_key
(
dev
,
BTN_X
,
buttons
&
0x0400
);
input_report_key
(
dev
,
BTN_SELECT
,
buttons
&
0x0800
);
input_report_abs
(
dev
,
ABS_GAS
,
res
[
10
]);
input_report_abs
(
dev
,
ABS_BRAKE
,
res
[
11
]);
input_report_abs
(
dev
,
ABS_X
,
res
[
12
]);
input_report_abs
(
dev
,
ABS_Y
,
res
[
13
]);
input_report_abs
(
dev
,
ABS_RX
,
res
[
14
]);
input_report_abs
(
dev
,
ABS_RY
,
res
[
15
]);
}
static
int
dc_pad_open
(
struct
input_dev
*
dev
)
{
struct
dc_pad
*
pad
=
dev
->
dev
.
platform_data
;
maple_getcond_callback
(
pad
->
mdev
,
dc_pad_callback
,
HZ
/
20
,
MAPLE_FUNC_CONTROLLER
);
return
0
;
}
static
void
dc_pad_close
(
struct
input_dev
*
dev
)
{
struct
dc_pad
*
pad
=
dev
->
dev
.
platform_data
;
maple_getcond_callback
(
pad
->
mdev
,
dc_pad_callback
,
0
,
MAPLE_FUNC_CONTROLLER
);
}
/* allow the controller to be used */
static
int
__devinit
probe_maple_controller
(
struct
device
*
dev
)
{
static
const
short
btn_bit
[
32
]
=
{
BTN_C
,
BTN_B
,
BTN_A
,
BTN_START
,
-
1
,
-
1
,
-
1
,
-
1
,
BTN_Z
,
BTN_Y
,
BTN_X
,
BTN_SELECT
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
};
static
const
short
abs_bit
[
32
]
=
{
-
1
,
-
1
,
-
1
,
-
1
,
ABS_HAT0Y
,
ABS_HAT0Y
,
ABS_HAT0X
,
ABS_HAT0X
,
-
1
,
-
1
,
-
1
,
-
1
,
ABS_HAT1Y
,
ABS_HAT1Y
,
ABS_HAT1X
,
ABS_HAT1X
,
ABS_GAS
,
ABS_BRAKE
,
ABS_X
,
ABS_Y
,
ABS_RX
,
ABS_RY
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
-
1
,
};
struct
maple_device
*
mdev
=
to_maple_dev
(
dev
);
struct
maple_driver
*
mdrv
=
to_maple_driver
(
dev
->
driver
);
int
i
,
error
;
struct
dc_pad
*
pad
;
struct
input_dev
*
idev
;
unsigned
long
data
=
be32_to_cpu
(
mdev
->
devinfo
.
function_data
[
0
]);
pad
=
kzalloc
(
sizeof
(
struct
dc_pad
),
GFP_KERNEL
);
idev
=
input_allocate_device
();
if
(
!
pad
||
!
idev
)
{
error
=
-
ENOMEM
;
goto
fail
;
}
pad
->
dev
=
idev
;
pad
->
mdev
=
mdev
;
idev
->
open
=
dc_pad_open
;
idev
->
close
=
dc_pad_close
;
for
(
i
=
0
;
i
<
32
;
i
++
)
{
if
(
data
&
(
1
<<
i
))
{
if
(
btn_bit
[
i
]
>=
0
)
__set_bit
(
btn_bit
[
i
],
idev
->
keybit
);
else
if
(
abs_bit
[
i
]
>=
0
)
__set_bit
(
abs_bit
[
i
],
idev
->
absbit
);
}
}
if
(
idev
->
keybit
[
BIT_WORD
(
BTN_JOYSTICK
)])
idev
->
evbit
[
0
]
|=
BIT_MASK
(
EV_KEY
);
if
(
idev
->
absbit
[
0
])
idev
->
evbit
[
0
]
|=
BIT_MASK
(
EV_ABS
);
for
(
i
=
ABS_X
;
i
<=
ABS_BRAKE
;
i
++
)
input_set_abs_params
(
idev
,
i
,
0
,
255
,
0
,
0
);
for
(
i
=
ABS_HAT0X
;
i
<=
ABS_HAT3Y
;
i
++
)
input_set_abs_params
(
idev
,
i
,
1
,
-
1
,
0
,
0
);
idev
->
dev
.
platform_data
=
pad
;
idev
->
dev
.
parent
=
&
mdev
->
dev
;
idev
->
name
=
mdev
->
product_name
;
idev
->
id
.
bustype
=
BUS_HOST
;
input_set_drvdata
(
idev
,
pad
);
error
=
input_register_device
(
idev
);
if
(
error
)
goto
fail
;
mdev
->
driver
=
mdrv
;
maple_set_drvdata
(
mdev
,
pad
);
return
0
;
fail:
input_free_device
(
idev
);
kfree
(
pad
);
maple_set_drvdata
(
mdev
,
NULL
);
return
error
;
}
static
int
__devexit
remove_maple_controller
(
struct
device
*
dev
)
{
struct
maple_device
*
mdev
=
to_maple_dev
(
dev
);
struct
dc_pad
*
pad
=
maple_get_drvdata
(
mdev
);
mdev
->
callback
=
NULL
;
input_unregister_device
(
pad
->
dev
);
maple_set_drvdata
(
mdev
,
NULL
);
kfree
(
pad
);
return
0
;
}
static
struct
maple_driver
dc_pad_driver
=
{
.
function
=
MAPLE_FUNC_CONTROLLER
,
.
drv
=
{
.
name
=
"Dreamcast_controller"
,
.
probe
=
probe_maple_controller
,
.
remove
=
__devexit_p
(
remove_maple_controller
),
},
};
static
int
__init
dc_pad_init
(
void
)
{
return
maple_driver_register
(
&
dc_pad_driver
);
}
static
void
__exit
dc_pad_exit
(
void
)
{
maple_driver_unregister
(
&
dc_pad_driver
);
}
module_init
(
dc_pad_init
);
module_exit
(
dc_pad_exit
);
drivers/input/joystick/walkera0701.c
0 → 100644
浏览文件 @
1dd32946
/*
* Parallel port to Walkera WK-0701 TX joystick
*
* Copyright (c) 2008 Peter Popovec
*
* More about driver: <file:Documentation/input/walkera0701.txt>
*/
/*
* 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.
*/
/* #define WK0701_DEBUG */
#define RESERVE 20000
#define SYNC_PULSE 1306000
#define BIN0_PULSE 288000
#define BIN1_PULSE 438000
#define ANALOG_MIN_PULSE 318000
#define ANALOG_MAX_PULSE 878000
#define ANALOG_DELTA 80000
#define BIN_SAMPLE ((BIN0_PULSE + BIN1_PULSE) / 2)
#define NO_SYNC 25
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/parport.h>
#include <linux/input.h>
#include <linux/hrtimer.h>
MODULE_AUTHOR
(
"Peter Popovec <popovec@fei.tuke.sk>"
);
MODULE_DESCRIPTION
(
"Walkera WK-0701 TX as joystick"
);
MODULE_LICENSE
(
"GPL"
);
static
unsigned
int
walkera0701_pp_no
;
module_param_named
(
port
,
walkera0701_pp_no
,
int
,
0
);
MODULE_PARM_DESC
(
port
,
"Parallel port adapter for Walkera WK-0701 TX (default is 0)"
);
/*
* For now, only one device is supported, if somebody need more devices, code
* can be expanded, one struct walkera_dev per device must be allocated and
* set up by walkera0701_connect (release of device by walkera0701_disconnect)
*/
struct
walkera_dev
{
unsigned
char
buf
[
25
];
u64
irq_time
,
irq_lasttime
;
int
counter
;
int
ack
;
struct
input_dev
*
input_dev
;
struct
hrtimer
timer
;
struct
parport
*
parport
;
struct
pardevice
*
pardevice
;
};
static
struct
walkera_dev
w_dev
;
static
inline
void
walkera0701_parse_frame
(
struct
walkera_dev
*
w
)
{
int
i
;
int
val1
,
val2
,
val3
,
val4
,
val5
,
val6
,
val7
,
val8
;
int
crc1
,
crc2
;
for
(
crc1
=
crc2
=
i
=
0
;
i
<
10
;
i
++
)
{
crc1
+=
w
->
buf
[
i
]
&
7
;
crc2
+=
(
w
->
buf
[
i
]
&
8
)
>>
3
;
}
if
((
w
->
buf
[
10
]
&
7
)
!=
(
crc1
&
7
))
return
;
if
(((
w
->
buf
[
10
]
&
8
)
>>
3
)
!=
(((
crc1
>>
3
)
+
crc2
)
&
1
))
return
;
for
(
crc1
=
crc2
=
0
,
i
=
11
;
i
<
23
;
i
++
)
{
crc1
+=
w
->
buf
[
i
]
&
7
;
crc2
+=
(
w
->
buf
[
i
]
&
8
)
>>
3
;
}
if
((
w
->
buf
[
23
]
&
7
)
!=
(
crc1
&
7
))
return
;
if
(((
w
->
buf
[
23
]
&
8
)
>>
3
)
!=
(((
crc1
>>
3
)
+
crc2
)
&
1
))
return
;
val1
=
((
w
->
buf
[
0
]
&
7
)
*
256
+
w
->
buf
[
1
]
*
16
+
w
->
buf
[
2
])
>>
2
;
val1
*=
((
w
->
buf
[
0
]
>>
2
)
&
2
)
-
1
;
/* sign */
val2
=
(
w
->
buf
[
2
]
&
1
)
<<
8
|
(
w
->
buf
[
3
]
<<
4
)
|
w
->
buf
[
4
];
val2
*=
(
w
->
buf
[
2
]
&
2
)
-
1
;
/* sign */
val3
=
((
w
->
buf
[
5
]
&
7
)
*
256
+
w
->
buf
[
6
]
*
16
+
w
->
buf
[
7
])
>>
2
;
val3
*=
((
w
->
buf
[
5
]
>>
2
)
&
2
)
-
1
;
/* sign */
val4
=
(
w
->
buf
[
7
]
&
1
)
<<
8
|
(
w
->
buf
[
8
]
<<
4
)
|
w
->
buf
[
9
];
val4
*=
(
w
->
buf
[
7
]
&
2
)
-
1
;
/* sign */
val5
=
((
w
->
buf
[
11
]
&
7
)
*
256
+
w
->
buf
[
12
]
*
16
+
w
->
buf
[
13
])
>>
2
;
val5
*=
((
w
->
buf
[
11
]
>>
2
)
&
2
)
-
1
;
/* sign */
val6
=
(
w
->
buf
[
13
]
&
1
)
<<
8
|
(
w
->
buf
[
14
]
<<
4
)
|
w
->
buf
[
15
];
val6
*=
(
w
->
buf
[
13
]
&
2
)
-
1
;
/* sign */
val7
=
((
w
->
buf
[
16
]
&
7
)
*
256
+
w
->
buf
[
17
]
*
16
+
w
->
buf
[
18
])
>>
2
;
val7
*=
((
w
->
buf
[
16
]
>>
2
)
&
2
)
-
1
;
/*sign */
val8
=
(
w
->
buf
[
18
]
&
1
)
<<
8
|
(
w
->
buf
[
19
]
<<
4
)
|
w
->
buf
[
20
];
val8
*=
(
w
->
buf
[
18
]
&
2
)
-
1
;
/*sign */
#ifdef WK0701_DEBUG
{
int
magic
,
magic_bit
;
magic
=
(
w
->
buf
[
21
]
<<
4
)
|
w
->
buf
[
22
];
magic_bit
=
(
w
->
buf
[
24
]
&
8
)
>>
3
;
printk
(
KERN_DEBUG
"walkera0701: %4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)
\n
"
,
val1
,
val2
,
val3
,
val4
,
val5
,
val6
,
val7
,
val8
,
magic
,
magic_bit
);
}
#endif
input_report_abs
(
w
->
input_dev
,
ABS_X
,
val2
);
input_report_abs
(
w
->
input_dev
,
ABS_Y
,
val1
);
input_report_abs
(
w
->
input_dev
,
ABS_Z
,
val6
);
input_report_abs
(
w
->
input_dev
,
ABS_THROTTLE
,
val3
);
input_report_abs
(
w
->
input_dev
,
ABS_RUDDER
,
val4
);
input_report_abs
(
w
->
input_dev
,
ABS_MISC
,
val7
);
input_report_key
(
w
->
input_dev
,
BTN_GEAR_DOWN
,
val5
>
0
);
}
static
inline
int
read_ack
(
struct
pardevice
*
p
)
{
return
parport_read_status
(
p
->
port
)
&
0x40
;
}
/* falling edge, prepare to BIN value calculation */
static
void
walkera0701_irq_handler
(
void
*
handler_data
)
{
u64
pulse_time
;
struct
walkera_dev
*
w
=
handler_data
;
w
->
irq_time
=
ktime_to_ns
(
ktime_get
());
pulse_time
=
w
->
irq_time
-
w
->
irq_lasttime
;
w
->
irq_lasttime
=
w
->
irq_time
;
/* cancel timer, if in handler or active do resync */
if
(
unlikely
(
0
!=
hrtimer_try_to_cancel
(
&
w
->
timer
)))
{
w
->
counter
=
NO_SYNC
;
return
;
}
if
(
w
->
counter
<
NO_SYNC
)
{
if
(
w
->
ack
)
{
pulse_time
-=
BIN1_PULSE
;
w
->
buf
[
w
->
counter
]
=
8
;
}
else
{
pulse_time
-=
BIN0_PULSE
;
w
->
buf
[
w
->
counter
]
=
0
;
}
if
(
w
->
counter
==
24
)
{
/* full frame */
walkera0701_parse_frame
(
w
);
w
->
counter
=
NO_SYNC
;
if
(
abs
(
pulse_time
-
SYNC_PULSE
)
<
RESERVE
)
/* new frame sync */
w
->
counter
=
0
;
}
else
{
if
((
pulse_time
>
(
ANALOG_MIN_PULSE
-
RESERVE
)
&&
(
pulse_time
<
(
ANALOG_MAX_PULSE
+
RESERVE
))))
{
pulse_time
-=
(
ANALOG_MIN_PULSE
-
RESERVE
);
pulse_time
=
(
u32
)
pulse_time
/
ANALOG_DELTA
;
/* overtiping is safe, pulsetime < s32.. */
w
->
buf
[
w
->
counter
++
]
|=
(
pulse_time
&
7
);
}
else
w
->
counter
=
NO_SYNC
;
}
}
else
if
(
abs
(
pulse_time
-
SYNC_PULSE
-
BIN0_PULSE
)
<
RESERVE
+
BIN1_PULSE
-
BIN0_PULSE
)
/* frame sync .. */
w
->
counter
=
0
;
hrtimer_start
(
&
w
->
timer
,
ktime_set
(
0
,
BIN_SAMPLE
),
HRTIMER_MODE_REL
);
}
static
enum
hrtimer_restart
timer_handler
(
struct
hrtimer
*
handle
)
{
struct
walkera_dev
*
w
;
w
=
container_of
(
handle
,
struct
walkera_dev
,
timer
);
w
->
ack
=
read_ack
(
w
->
pardevice
);
return
HRTIMER_NORESTART
;
}
static
int
walkera0701_open
(
struct
input_dev
*
dev
)
{
struct
walkera_dev
*
w
=
input_get_drvdata
(
dev
);
parport_enable_irq
(
w
->
parport
);
return
0
;
}
static
void
walkera0701_close
(
struct
input_dev
*
dev
)
{
struct
walkera_dev
*
w
=
input_get_drvdata
(
dev
);
parport_disable_irq
(
w
->
parport
);
}
static
int
walkera0701_connect
(
struct
walkera_dev
*
w
,
int
parport
)
{
int
err
=
-
ENODEV
;
w
->
parport
=
parport_find_number
(
parport
);
if
(
w
->
parport
==
NULL
)
return
-
ENODEV
;
if
(
w
->
parport
->
irq
==
-
1
)
{
printk
(
KERN_ERR
"walkera0701: parport without interrupt
\n
"
);
goto
init_err
;
}
err
=
-
EBUSY
;
w
->
pardevice
=
parport_register_device
(
w
->
parport
,
"walkera0701"
,
NULL
,
NULL
,
walkera0701_irq_handler
,
PARPORT_DEV_EXCL
,
w
);
if
(
!
w
->
pardevice
)
goto
init_err
;
if
(
parport_negotiate
(
w
->
pardevice
->
port
,
IEEE1284_MODE_COMPAT
))
goto
init_err1
;
if
(
parport_claim
(
w
->
pardevice
))
goto
init_err1
;
w
->
input_dev
=
input_allocate_device
();
if
(
!
w
->
input_dev
)
goto
init_err2
;
input_set_drvdata
(
w
->
input_dev
,
w
);
w
->
input_dev
->
name
=
"Walkera WK-0701 TX"
;
w
->
input_dev
->
phys
=
w
->
parport
->
name
;
w
->
input_dev
->
id
.
bustype
=
BUS_PARPORT
;
/* TODO what id vendor/product/version ? */
w
->
input_dev
->
id
.
vendor
=
0x0001
;
w
->
input_dev
->
id
.
product
=
0x0001
;
w
->
input_dev
->
id
.
version
=
0x0100
;
w
->
input_dev
->
open
=
walkera0701_open
;
w
->
input_dev
->
close
=
walkera0701_close
;
w
->
input_dev
->
evbit
[
0
]
=
BIT
(
EV_ABS
)
|
BIT_MASK
(
EV_KEY
);
w
->
input_dev
->
keybit
[
BIT_WORD
(
BTN_GEAR_DOWN
)]
=
BIT_MASK
(
BTN_GEAR_DOWN
);
input_set_abs_params
(
w
->
input_dev
,
ABS_X
,
-
512
,
512
,
0
,
0
);
input_set_abs_params
(
w
->
input_dev
,
ABS_Y
,
-
512
,
512
,
0
,
0
);
input_set_abs_params
(
w
->
input_dev
,
ABS_Z
,
-
512
,
512
,
0
,
0
);
input_set_abs_params
(
w
->
input_dev
,
ABS_THROTTLE
,
-
512
,
512
,
0
,
0
);
input_set_abs_params
(
w
->
input_dev
,
ABS_RUDDER
,
-
512
,
512
,
0
,
0
);
input_set_abs_params
(
w
->
input_dev
,
ABS_MISC
,
-
512
,
512
,
0
,
0
);
err
=
input_register_device
(
w
->
input_dev
);
if
(
err
)
goto
init_err3
;
hrtimer_init
(
&
w
->
timer
,
CLOCK_MONOTONIC
,
HRTIMER_MODE_REL
);
w
->
timer
.
function
=
timer_handler
;
return
0
;
init_err3:
input_free_device
(
w
->
input_dev
);
init_err2:
parport_release
(
w
->
pardevice
);
init_err1:
parport_unregister_device
(
w
->
pardevice
);
init_err:
parport_put_port
(
w
->
parport
);
return
err
;
}
static
void
walkera0701_disconnect
(
struct
walkera_dev
*
w
)
{
hrtimer_cancel
(
&
w
->
timer
);
input_unregister_device
(
w
->
input_dev
);
parport_release
(
w
->
pardevice
);
parport_unregister_device
(
w
->
pardevice
);
parport_put_port
(
w
->
parport
);
}
static
int
__init
walkera0701_init
(
void
)
{
return
walkera0701_connect
(
&
w_dev
,
walkera0701_pp_no
);
}
static
void
__exit
walkera0701_exit
(
void
)
{
walkera0701_disconnect
(
&
w_dev
);
}
module_init
(
walkera0701_init
);
module_exit
(
walkera0701_exit
);
drivers/input/keyboard/Kconfig
浏览文件 @
1dd32946
...
...
@@ -268,6 +268,15 @@ config KEYBOARD_PXA27x
To compile this driver as a module, choose M here: the
module will be called pxa27x_keypad.
config KEYBOARD_PXA930_ROTARY
tristate "PXA930/PXA935 Enhanced Rotary Controller Support"
depends on CPU_PXA930 || CPU_PXA935
help
Enable support for PXA930/PXA935 Enhanced Rotary Controller.
To compile this driver as a module, choose M here: the
module will be called pxa930_rotary.
config KEYBOARD_AAED2000
tristate "AAED-2000 keyboard"
depends on MACH_AAED2000
...
...
drivers/input/keyboard/Makefile
浏览文件 @
1dd32946
...
...
@@ -20,6 +20,7 @@ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD)
+=
hilkbd.o
obj-$(CONFIG_KEYBOARD_OMAP)
+=
omap-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x)
+=
pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)
+=
pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_AAED2000)
+=
aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO)
+=
gpio_keys.o
obj-$(CONFIG_KEYBOARD_HP6XX)
+=
jornada680_kbd.o
...
...
drivers/input/keyboard/atkbd.c
浏览文件 @
1dd32946
...
...
@@ -883,6 +883,39 @@ static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd)
atkbd
->
force_release_mask
);
}
/*
* Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release
* for its volume buttons
*/
static
void
atkbd_hp_zv6100_keymap_fixup
(
struct
atkbd
*
atkbd
)
{
const
unsigned
int
forced_release_keys
[]
=
{
0xae
,
0xb0
,
};
int
i
;
if
(
atkbd
->
set
==
2
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
forced_release_keys
);
i
++
)
__set_bit
(
forced_release_keys
[
i
],
atkbd
->
force_release_mask
);
}
/*
* Samsung NC10 with Fn+F? key release not working
*/
static
void
atkbd_samsung_keymap_fixup
(
struct
atkbd
*
atkbd
)
{
const
unsigned
int
forced_release_keys
[]
=
{
0x82
,
0x83
,
0x84
,
0x86
,
0x88
,
0x89
,
0xb3
,
0xf7
,
0xf9
,
};
int
i
;
if
(
atkbd
->
set
==
2
)
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
forced_release_keys
);
i
++
)
__set_bit
(
forced_release_keys
[
i
],
atkbd
->
force_release_mask
);
}
/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
...
...
@@ -1475,6 +1508,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_dell_laptop_keymap_fixup
,
},
{
.
ident
=
"Dell Laptop"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Dell Computer Corporation"
),
DMI_MATCH
(
DMI_CHASSIS_TYPE
,
"8"
),
/* Portable */
},
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_dell_laptop_keymap_fixup
,
},
{
.
ident
=
"HP 2133"
,
.
matches
=
{
...
...
@@ -1484,6 +1526,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_hp_keymap_fixup
,
},
{
.
ident
=
"HP Pavilion ZV6100"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"Hewlett-Packard"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"Pavilion ZV6100"
),
},
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_hp_zv6100_keymap_fixup
,
},
{
.
ident
=
"Inventec Symphony"
,
.
matches
=
{
...
...
@@ -1493,6 +1544,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_inventec_keymap_fixup
,
},
{
.
ident
=
"Samsung NC10"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"SAMSUNG ELECTRONICS CO., LTD."
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"NC10"
),
},
.
callback
=
atkbd_setup_fixup
,
.
driver_data
=
atkbd_samsung_keymap_fixup
,
},
{
}
};
...
...
drivers/input/keyboard/gpio_keys.c
浏览文件 @
1dd32946
...
...
@@ -98,6 +98,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
input
->
id
.
product
=
0x0001
;
input
->
id
.
version
=
0x0100
;
/* Enable auto repeat feature of Linux input subsystem */
if
(
pdata
->
rep
)
__set_bit
(
EV_REP
,
input
->
evbit
);
ddata
->
input
=
input
;
for
(
i
=
0
;
i
<
pdata
->
nbuttons
;
i
++
)
{
...
...
drivers/input/keyboard/hil_kbd.c
浏览文件 @
1dd32946
...
...
@@ -47,6 +47,7 @@
MODULE_AUTHOR
(
"Brian S. Julin <bri@calyx.com>"
);
MODULE_DESCRIPTION
(
HIL_GENERIC_NAME
" driver"
);
MODULE_LICENSE
(
"Dual BSD/GPL"
);
MODULE_ALIAS
(
"serio:ty03pr25id00ex*"
);
#define HIL_KBD_MAX_LENGTH 16
...
...
drivers/input/keyboard/omap-keypad.c
浏览文件 @
1dd32946
...
...
@@ -122,14 +122,10 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
/* read the keypad status */
if
(
cpu_is_omap24xx
())
{
int
i
;
for
(
i
=
0
;
i
<
omap_kp
->
rows
;
i
++
)
disable_irq
(
OMAP_GPIO_IRQ
(
row_gpios
[
i
]));
/* read the keypad status */
for
(
col
=
0
;
col
<
omap_kp
->
cols
;
col
++
)
{
set_col_gpio_val
(
omap_kp
,
~
(
1
<<
col
));
state
[
col
]
=
~
(
get_row_gpio_val
(
omap_kp
))
&
0x
3
f
;
state
[
col
]
=
~
(
get_row_gpio_val
(
omap_kp
))
&
0x
f
f
;
}
set_col_gpio_val
(
omap_kp
,
0
);
...
...
drivers/input/keyboard/pxa930_rotary.c
0 → 100644
浏览文件 @
1dd32946
/*
* Driver for the enhanced rotary controller on pxa930 and pxa935
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/pxa930_rotary.h>
#define SBCR (0x04)
#define ERCR (0x0c)
#define SBCR_ERSB (1 << 5)
struct
pxa930_rotary
{
struct
input_dev
*
input_dev
;
void
__iomem
*
mmio_base
;
int
last_ercr
;
struct
pxa930_rotary_platform_data
*
pdata
;
};
static
void
clear_sbcr
(
struct
pxa930_rotary
*
r
)
{
uint32_t
sbcr
=
__raw_readl
(
r
->
mmio_base
+
SBCR
);
__raw_writel
(
sbcr
|
SBCR_ERSB
,
r
->
mmio_base
+
SBCR
);
__raw_writel
(
sbcr
&
~
SBCR_ERSB
,
r
->
mmio_base
+
SBCR
);
}
static
irqreturn_t
rotary_irq
(
int
irq
,
void
*
dev_id
)
{
struct
pxa930_rotary
*
r
=
dev_id
;
struct
pxa930_rotary_platform_data
*
pdata
=
r
->
pdata
;
int
ercr
,
delta
,
key
;
ercr
=
__raw_readl
(
r
->
mmio_base
+
ERCR
)
&
0xf
;
clear_sbcr
(
r
);
delta
=
ercr
-
r
->
last_ercr
;
if
(
delta
==
0
)
return
IRQ_HANDLED
;
r
->
last_ercr
=
ercr
;
if
(
pdata
->
up_key
&&
pdata
->
down_key
)
{
key
=
(
delta
>
0
)
?
pdata
->
up_key
:
pdata
->
down_key
;
input_report_key
(
r
->
input_dev
,
key
,
1
);
input_sync
(
r
->
input_dev
);
input_report_key
(
r
->
input_dev
,
key
,
0
);
}
else
input_report_rel
(
r
->
input_dev
,
pdata
->
rel_code
,
delta
);
input_sync
(
r
->
input_dev
);
return
IRQ_HANDLED
;
}
static
int
pxa930_rotary_open
(
struct
input_dev
*
dev
)
{
struct
pxa930_rotary
*
r
=
input_get_drvdata
(
dev
);
clear_sbcr
(
r
);
return
0
;
}
static
void
pxa930_rotary_close
(
struct
input_dev
*
dev
)
{
struct
pxa930_rotary
*
r
=
input_get_drvdata
(
dev
);
clear_sbcr
(
r
);
}
static
int
__devinit
pxa930_rotary_probe
(
struct
platform_device
*
pdev
)
{
struct
pxa930_rotary_platform_data
*
pdata
=
pdev
->
dev
.
platform_data
;
struct
pxa930_rotary
*
r
;
struct
input_dev
*
input_dev
;
struct
resource
*
res
;
int
irq
;
int
err
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"no irq for rotary controller
\n
"
);
return
-
ENXIO
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"no I/O memory defined
\n
"
);
return
-
ENXIO
;
}
if
(
!
pdata
)
{
dev_err
(
&
pdev
->
dev
,
"no platform data defined
\n
"
);
return
-
EINVAL
;
}
r
=
kzalloc
(
sizeof
(
struct
pxa930_rotary
),
GFP_KERNEL
);
if
(
!
r
)
return
-
ENOMEM
;
r
->
mmio_base
=
ioremap_nocache
(
res
->
start
,
resource_size
(
res
));
if
(
r
->
mmio_base
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"failed to remap IO memory
\n
"
);
err
=
-
ENXIO
;
goto
failed_free
;
}
r
->
pdata
=
pdata
;
platform_set_drvdata
(
pdev
,
r
);
/* allocate and register the input device */
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
{
dev_err
(
&
pdev
->
dev
,
"failed to allocate input device
\n
"
);
err
=
-
ENOMEM
;
goto
failed_free_io
;
}
input_dev
->
name
=
pdev
->
name
;
input_dev
->
id
.
bustype
=
BUS_HOST
;
input_dev
->
open
=
pxa930_rotary_open
;
input_dev
->
close
=
pxa930_rotary_close
;
input_dev
->
dev
.
parent
=
&
pdev
->
dev
;
if
(
pdata
->
up_key
&&
pdata
->
down_key
)
{
__set_bit
(
pdata
->
up_key
,
input_dev
->
keybit
);
__set_bit
(
pdata
->
down_key
,
input_dev
->
keybit
);
__set_bit
(
EV_KEY
,
input_dev
->
evbit
);
}
else
{
__set_bit
(
pdata
->
rel_code
,
input_dev
->
relbit
);
__set_bit
(
EV_REL
,
input_dev
->
evbit
);
}
r
->
input_dev
=
input_dev
;
input_set_drvdata
(
input_dev
,
r
);
err
=
request_irq
(
irq
,
rotary_irq
,
IRQF_DISABLED
,
"enhanced rotary"
,
r
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request IRQ
\n
"
);
goto
failed_free_input
;
}
err
=
input_register_device
(
input_dev
);
if
(
err
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register input device
\n
"
);
goto
failed_free_irq
;
}
return
0
;
failed_free_irq:
free_irq
(
irq
,
r
);
failed_free_input:
input_free_device
(
input_dev
);
failed_free_io:
iounmap
(
r
->
mmio_base
);
failed_free:
kfree
(
r
);
return
err
;
}
static
int
__devexit
pxa930_rotary_remove
(
struct
platform_device
*
pdev
)
{
struct
pxa930_rotary
*
r
=
platform_get_drvdata
(
pdev
);
free_irq
(
platform_get_irq
(
pdev
,
0
),
r
);
input_unregister_device
(
r
->
input_dev
);
iounmap
(
r
->
mmio_base
);
platform_set_drvdata
(
pdev
,
NULL
);
kfree
(
r
);
return
0
;
}
static
struct
platform_driver
pxa930_rotary_driver
=
{
.
driver
=
{
.
name
=
"pxa930-rotary"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
pxa930_rotary_probe
,
.
remove
=
__devexit_p
(
pxa930_rotary_remove
),
};
static
int
__init
pxa930_rotary_init
(
void
)
{
return
platform_driver_register
(
&
pxa930_rotary_driver
);
}
module_init
(
pxa930_rotary_init
);
static
void
__exit
pxa930_rotary_exit
(
void
)
{
platform_driver_unregister
(
&
pxa930_rotary_driver
);
}
module_exit
(
pxa930_rotary_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"Driver for PXA93x Enhanced Rotary Controller"
);
MODULE_AUTHOR
(
"Yao Yong <yaoyong@marvell.com>"
);
drivers/input/misc/pcspkr.c
浏览文件 @
1dd32946
...
...
@@ -52,13 +52,13 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c
spin_lock_irqsave
(
&
i8253_lock
,
flags
);
if
(
count
)
{
/* enable counter 2 */
outb_p
(
inb_p
(
0x61
)
|
3
,
0x61
);
/* set command for counter 2, 2 byte write */
outb_p
(
0xB6
,
0x43
);
/* select desired HZ */
outb_p
(
count
&
0xff
,
0x42
);
outb
((
count
>>
8
)
&
0xff
,
0x42
);
/* enable counter 2 */
outb_p
(
inb_p
(
0x61
)
|
3
,
0x61
);
}
else
{
/* disable counter 2 */
outb
(
inb_p
(
0x61
)
&
0xFC
,
0x61
);
...
...
drivers/input/misc/uinput.c
浏览文件 @
1dd32946
...
...
@@ -37,6 +37,7 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uinput.h>
#include "../input-compat.h"
static
int
uinput_dev_event
(
struct
input_dev
*
dev
,
unsigned
int
type
,
unsigned
int
code
,
int
value
)
{
...
...
@@ -78,6 +79,7 @@ static struct uinput_request* uinput_request_find(struct uinput_device *udev, in
/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
if
(
id
>=
UINPUT_NUM_REQUESTS
||
id
<
0
)
return
NULL
;
return
udev
->
requests
[
id
];
}
...
...
@@ -127,6 +129,17 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff
struct
uinput_request
request
;
int
retval
;
/*
* uinput driver does not currently support periodic effects with
* custom waveform since it does not have a way to pass buffer of
* samples (custom_data) to userspace. If ever there is a device
* supporting custom waveforms we would need to define an additional
* ioctl (UI_UPLOAD_SAMPLES) but for now we just bail out.
*/
if
(
effect
->
type
==
FF_PERIODIC
&&
effect
->
u
.
periodic
.
waveform
==
FF_CUSTOM
)
return
-
EINVAL
;
request
.
id
=
-
1
;
init_completion
(
&
request
.
done
);
request
.
code
=
UI_FF_UPLOAD
;
...
...
@@ -353,15 +366,15 @@ static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char
{
struct
input_event
ev
;
if
(
count
!=
sizeof
(
struct
input_event
))
if
(
count
<
input_event_size
(
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
ev
,
buffer
,
sizeof
(
struct
input_event
)
))
if
(
input_event_from_user
(
buffer
,
&
ev
))
return
-
EFAULT
;
input_event
(
udev
->
dev
,
ev
.
type
,
ev
.
code
,
ev
.
value
);
return
sizeof
(
struct
input_event
);
return
input_event_size
(
);
}
static
ssize_t
uinput_write
(
struct
file
*
file
,
const
char
__user
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
...
...
@@ -407,13 +420,13 @@ static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count,
goto
out
;
}
while
(
udev
->
head
!=
udev
->
tail
&&
retval
+
sizeof
(
struct
input_event
)
<=
count
)
{
if
(
copy_to_user
(
buffer
+
retval
,
&
udev
->
buff
[
udev
->
tail
],
sizeof
(
struct
input_event
)
))
{
while
(
udev
->
head
!=
udev
->
tail
&&
retval
+
input_event_size
(
)
<=
count
)
{
if
(
input_event_to_user
(
buffer
+
retval
,
&
udev
->
buff
[
udev
->
tail
]
))
{
retval
=
-
EFAULT
;
goto
out
;
}
udev
->
tail
=
(
udev
->
tail
+
1
)
%
UINPUT_BUFFER_SIZE
;
retval
+=
sizeof
(
struct
input_event
);
retval
+=
input_event_size
(
);
}
out:
...
...
@@ -444,6 +457,93 @@ static int uinput_release(struct inode *inode, struct file *file)
return
0
;
}
#ifdef CONFIG_COMPAT
struct
uinput_ff_upload_compat
{
int
request_id
;
int
retval
;
struct
ff_effect_compat
effect
;
struct
ff_effect_compat
old
;
};
static
int
uinput_ff_upload_to_user
(
char
__user
*
buffer
,
const
struct
uinput_ff_upload
*
ff_up
)
{
if
(
INPUT_COMPAT_TEST
)
{
struct
uinput_ff_upload_compat
ff_up_compat
;
ff_up_compat
.
request_id
=
ff_up
->
request_id
;
ff_up_compat
.
retval
=
ff_up
->
retval
;
/*
* It so happens that the pointer that gives us the trouble
* is the last field in the structure. Since we don't support
* custom waveforms in uinput anyway we can just copy the whole
* thing (to the compat size) and ignore the pointer.
*/
memcpy
(
&
ff_up_compat
.
effect
,
&
ff_up
->
effect
,
sizeof
(
struct
ff_effect_compat
));
memcpy
(
&
ff_up_compat
.
old
,
&
ff_up
->
old
,
sizeof
(
struct
ff_effect_compat
));
if
(
copy_to_user
(
buffer
,
&
ff_up_compat
,
sizeof
(
struct
uinput_ff_upload_compat
)))
return
-
EFAULT
;
}
else
{
if
(
copy_to_user
(
buffer
,
ff_up
,
sizeof
(
struct
uinput_ff_upload
)))
return
-
EFAULT
;
}
return
0
;
}
static
int
uinput_ff_upload_from_user
(
const
char
__user
*
buffer
,
struct
uinput_ff_upload
*
ff_up
)
{
if
(
INPUT_COMPAT_TEST
)
{
struct
uinput_ff_upload_compat
ff_up_compat
;
if
(
copy_from_user
(
&
ff_up_compat
,
buffer
,
sizeof
(
struct
uinput_ff_upload_compat
)))
return
-
EFAULT
;
ff_up
->
request_id
=
ff_up_compat
.
request_id
;
ff_up
->
retval
=
ff_up_compat
.
retval
;
memcpy
(
&
ff_up
->
effect
,
&
ff_up_compat
.
effect
,
sizeof
(
struct
ff_effect_compat
));
memcpy
(
&
ff_up
->
old
,
&
ff_up_compat
.
old
,
sizeof
(
struct
ff_effect_compat
));
}
else
{
if
(
copy_from_user
(
ff_up
,
buffer
,
sizeof
(
struct
uinput_ff_upload
)))
return
-
EFAULT
;
}
return
0
;
}
#else
static
int
uinput_ff_upload_to_user
(
char
__user
*
buffer
,
const
struct
uinput_ff_upload
*
ff_up
)
{
if
(
copy_to_user
(
buffer
,
ff_up
,
sizeof
(
struct
uinput_ff_upload
)))
return
-
EFAULT
;
return
0
;
}
static
int
uinput_ff_upload_from_user
(
const
char
__user
*
buffer
,
struct
uinput_ff_upload
*
ff_up
)
{
if
(
copy_from_user
(
ff_up
,
buffer
,
sizeof
(
struct
uinput_ff_upload
)))
return
-
EFAULT
;
return
0
;
}
#endif
#define uinput_set_bit(_arg, _bit, _max) \
({ \
int __ret = 0; \
...
...
@@ -455,19 +555,17 @@ static int uinput_release(struct inode *inode, struct file *file)
__ret; \
})
static
long
uinput_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
long
uinput_ioctl_handler
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
,
void
__user
*
p
)
{
int
retval
;
struct
uinput_device
*
udev
;
void
__user
*
p
=
(
void
__user
*
)
arg
;
struct
uinput_device
*
udev
=
file
->
private_data
;
struct
uinput_ff_upload
ff_up
;
struct
uinput_ff_erase
ff_erase
;
struct
uinput_request
*
req
;
int
length
;
char
*
phys
;
udev
=
file
->
private_data
;
retval
=
mutex_lock_interruptible
(
&
udev
->
mutex
);
if
(
retval
)
return
retval
;
...
...
@@ -549,26 +647,24 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break
;
case
UI_BEGIN_FF_UPLOAD
:
if
(
copy_from_user
(
&
ff_up
,
p
,
sizeof
(
ff_up
)))
{
retval
=
-
EFAULT
;
retval
=
uinput_ff_upload_from_user
(
p
,
&
ff_up
);
if
(
retval
)
break
;
}
req
=
uinput_request_find
(
udev
,
ff_up
.
request_id
);
if
(
!
(
req
&&
req
->
code
==
UI_FF_UPLOAD
&&
req
->
u
.
upload
.
effect
)
)
{
if
(
!
req
||
req
->
code
!=
UI_FF_UPLOAD
||
!
req
->
u
.
upload
.
effect
)
{
retval
=
-
EINVAL
;
break
;
}
ff_up
.
retval
=
0
;
memcpy
(
&
ff_up
.
effect
,
req
->
u
.
upload
.
effect
,
sizeof
(
struct
ff_effect
))
;
ff_up
.
effect
=
*
req
->
u
.
upload
.
effect
;
if
(
req
->
u
.
upload
.
old
)
memcpy
(
&
ff_up
.
old
,
req
->
u
.
upload
.
old
,
sizeof
(
struct
ff_effect
))
;
ff_up
.
old
=
*
req
->
u
.
upload
.
old
;
else
memset
(
&
ff_up
.
old
,
0
,
sizeof
(
struct
ff_effect
));
if
(
copy_to_user
(
p
,
&
ff_up
,
sizeof
(
ff_up
)))
{
retval
=
-
EFAULT
;
break
;
}
retval
=
uinput_ff_upload_to_user
(
p
,
&
ff_up
);
break
;
case
UI_BEGIN_FF_ERASE
:
...
...
@@ -576,29 +672,34 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
retval
=
-
EFAULT
;
break
;
}
req
=
uinput_request_find
(
udev
,
ff_erase
.
request_id
);
if
(
!
(
req
&&
req
->
code
==
UI_FF_ERASE
)
)
{
if
(
!
req
||
req
->
code
!=
UI_FF_ERASE
)
{
retval
=
-
EINVAL
;
break
;
}
ff_erase
.
retval
=
0
;
ff_erase
.
effect_id
=
req
->
u
.
effect_id
;
if
(
copy_to_user
(
p
,
&
ff_erase
,
sizeof
(
ff_erase
)))
{
retval
=
-
EFAULT
;
break
;
}
break
;
case
UI_END_FF_UPLOAD
:
if
(
copy_from_user
(
&
ff_up
,
p
,
sizeof
(
ff_up
)))
{
retval
=
-
EFAULT
;
retval
=
uinput_ff_upload_from_user
(
p
,
&
ff_up
);
if
(
retval
)
break
;
}
req
=
uinput_request_find
(
udev
,
ff_up
.
request_id
);
if
(
!
(
req
&&
req
->
code
==
UI_FF_UPLOAD
&&
req
->
u
.
upload
.
effect
))
{
if
(
!
req
||
req
->
code
!=
UI_FF_UPLOAD
||
!
req
->
u
.
upload
.
effect
)
{
retval
=
-
EINVAL
;
break
;
}
req
->
retval
=
ff_up
.
retval
;
uinput_request_done
(
udev
,
req
);
break
;
...
...
@@ -608,11 +709,13 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
retval
=
-
EFAULT
;
break
;
}
req
=
uinput_request_find
(
udev
,
ff_erase
.
request_id
);
if
(
!
(
req
&&
req
->
code
==
UI_FF_ERASE
)
)
{
if
(
!
req
||
req
->
code
!=
UI_FF_ERASE
)
{
retval
=
-
EINVAL
;
break
;
}
req
->
retval
=
ff_erase
.
retval
;
uinput_request_done
(
udev
,
req
);
break
;
...
...
@@ -626,6 +729,18 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return
retval
;
}
static
long
uinput_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
uinput_ioctl_handler
(
file
,
cmd
,
arg
,
(
void
__user
*
)
arg
);
}
#ifdef CONFIG_COMPAT
static
long
uinput_compat_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
return
uinput_ioctl_handler
(
file
,
cmd
,
arg
,
compat_ptr
(
arg
));
}
#endif
static
const
struct
file_operations
uinput_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
uinput_open
,
...
...
@@ -634,6 +749,9 @@ static const struct file_operations uinput_fops = {
.
write
=
uinput_write
,
.
poll
=
uinput_poll
,
.
unlocked_ioctl
=
uinput_ioctl
,
#ifdef CONFIG_COMPAT
.
compat_ioctl
=
uinput_compat_ioctl
,
#endif
};
static
struct
miscdevice
uinput_misc
=
{
...
...
drivers/input/mouse/Kconfig
浏览文件 @
1dd32946
...
...
@@ -286,4 +286,10 @@ config MOUSE_GPIO
To compile this driver as a module, choose M here: the
module will be called gpio_mouse.
config MOUSE_PXA930_TRKBALL
tristate "PXA930 Trackball mouse"
depends on CPU_PXA930 || CPU_PXA935
help
Say Y here to support PXA930 Trackball mouse.
endif
drivers/input/mouse/Makefile
浏览文件 @
1dd32946
...
...
@@ -4,19 +4,20 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_MOUSE_AMIGA)
+=
amimouse.o
obj-$(CONFIG_MOUSE_APPLETOUCH)
+=
appletouch.o
obj-$(CONFIG_MOUSE_BCM5974)
+=
bcm5974.o
obj-$(CONFIG_MOUSE_ATARI)
+=
atarimouse.o
obj-$(CONFIG_MOUSE_RISCPC)
+=
rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT)
+=
inport.o
obj-$(CONFIG_MOUSE_LOGIBM)
+=
logibm.o
obj-$(CONFIG_MOUSE_PC110PAD)
+=
pc110pad.o
obj-$(CONFIG_MOUSE_PS2)
+=
psmouse.o
obj-$(CONFIG_MOUSE_SERIAL)
+=
sermouse.o
obj-$(CONFIG_MOUSE_HIL)
+=
hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA)
+=
vsxxxaa.o
obj-$(CONFIG_MOUSE_GPIO)
+=
gpio_mouse.o
obj-$(CONFIG_MOUSE_AMIGA)
+=
amimouse.o
obj-$(CONFIG_MOUSE_APPLETOUCH)
+=
appletouch.o
obj-$(CONFIG_MOUSE_BCM5974)
+=
bcm5974.o
obj-$(CONFIG_MOUSE_ATARI)
+=
atarimouse.o
obj-$(CONFIG_MOUSE_RISCPC)
+=
rpcmouse.o
obj-$(CONFIG_MOUSE_INPORT)
+=
inport.o
obj-$(CONFIG_MOUSE_LOGIBM)
+=
logibm.o
obj-$(CONFIG_MOUSE_PC110PAD)
+=
pc110pad.o
obj-$(CONFIG_MOUSE_PS2)
+=
psmouse.o
obj-$(CONFIG_MOUSE_PXA930_TRKBALL)
+=
pxa930_trkball.o
obj-$(CONFIG_MOUSE_SERIAL)
+=
sermouse.o
obj-$(CONFIG_MOUSE_HIL)
+=
hil_ptr.o
obj-$(CONFIG_MOUSE_VSXXXAA)
+=
vsxxxaa.o
obj-$(CONFIG_MOUSE_GPIO)
+=
gpio_mouse.o
psmouse-objs
:=
psmouse-base.o synaptics.o
...
...
drivers/input/mouse/appletouch.c
浏览文件 @
1dd32946
...
...
@@ -3,7 +3,7 @@
*
* Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2005-2008 Johannes Berg (johannes@sipsolutions.net)
* Copyright (C) 2005
Stelian Pop (stelian@popies.net)
* Copyright (C) 2005
-2008
Stelian Pop (stelian@popies.net)
* Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
* Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
* Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
...
...
@@ -35,16 +35,74 @@
#include <linux/module.h>
#include <linux/usb/input.h>
/* Type of touchpad */
enum
atp_touchpad_type
{
ATP_FOUNTAIN
,
ATP_GEYSER1
,
ATP_GEYSER2
,
ATP_GEYSER3
,
ATP_GEYSER4
/*
* Note: We try to keep the touchpad aspect ratio while still doing only
* simple arithmetics:
* 0 <= x <= (xsensors - 1) * xfact
* 0 <= y <= (ysensors - 1) * yfact
*/
struct
atp_info
{
int
xsensors
;
/* number of X sensors */
int
xsensors_17
;
/* 17" models have more sensors */
int
ysensors
;
/* number of Y sensors */
int
xfact
;
/* X multiplication factor */
int
yfact
;
/* Y multiplication factor */
int
datalen
;
/* size of USB transfers */
void
(
*
callback
)(
struct
urb
*
);
/* callback function */
};
static
void
atp_complete_geyser_1_2
(
struct
urb
*
urb
);
static
void
atp_complete_geyser_3_4
(
struct
urb
*
urb
);
static
const
struct
atp_info
fountain_info
=
{
.
xsensors
=
16
,
.
xsensors_17
=
26
,
.
ysensors
=
16
,
.
xfact
=
64
,
.
yfact
=
43
,
.
datalen
=
81
,
.
callback
=
atp_complete_geyser_1_2
,
};
static
const
struct
atp_info
geyser1_info
=
{
.
xsensors
=
16
,
.
xsensors_17
=
26
,
.
ysensors
=
16
,
.
xfact
=
64
,
.
yfact
=
43
,
.
datalen
=
81
,
.
callback
=
atp_complete_geyser_1_2
,
};
static
const
struct
atp_info
geyser2_info
=
{
.
xsensors
=
15
,
.
xsensors_17
=
20
,
.
ysensors
=
9
,
.
xfact
=
64
,
.
yfact
=
43
,
.
datalen
=
64
,
.
callback
=
atp_complete_geyser_1_2
,
};
static
const
struct
atp_info
geyser3_info
=
{
.
xsensors
=
20
,
.
ysensors
=
10
,
.
xfact
=
64
,
.
yfact
=
64
,
.
datalen
=
64
,
.
callback
=
atp_complete_geyser_3_4
,
};
#define ATP_DEVICE(prod, type) \
static
const
struct
atp_info
geyser4_info
=
{
.
xsensors
=
20
,
.
ysensors
=
10
,
.
xfact
=
64
,
.
yfact
=
64
,
.
datalen
=
64
,
.
callback
=
atp_complete_geyser_3_4
,
};
#define ATP_DEVICE(prod, info) \
{ \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
...
...
@@ -53,7 +111,7 @@ enum atp_touchpad_type {
.idProduct = (prod), \
.bInterfaceClass = 0x03, \
.bInterfaceProtocol = 0x02, \
.driver_info =
ATP_ ## type,
\
.driver_info =
(unsigned long) &info,
\
}
/*
...
...
@@ -62,43 +120,39 @@ enum atp_touchpad_type {
* According to Info.plist Geyser IV is the same as Geyser III.)
*/
static
struct
usb_device_id
atp_table
[]
=
{
static
struct
usb_device_id
atp_table
[]
=
{
/* PowerBooks Feb 2005, iBooks G4 */
ATP_DEVICE
(
0x020e
,
FOUNTAIN
),
/* FOUNTAIN ANSI */
ATP_DEVICE
(
0x020f
,
FOUNTAIN
),
/* FOUNTAIN ISO */
ATP_DEVICE
(
0x030a
,
FOUNTAIN
),
/* FOUNTAIN TP ONLY */
ATP_DEVICE
(
0x030b
,
GEYSER1
),
/* GEYSER 1 TP ONLY */
ATP_DEVICE
(
0x020e
,
fountain_info
),
/* FOUNTAIN ANSI */
ATP_DEVICE
(
0x020f
,
fountain_info
),
/* FOUNTAIN ISO */
ATP_DEVICE
(
0x030a
,
fountain_info
),
/* FOUNTAIN TP ONLY */
ATP_DEVICE
(
0x030b
,
geyser1_info
),
/* GEYSER 1 TP ONLY */
/* PowerBooks Oct 2005 */
ATP_DEVICE
(
0x0214
,
GEYSER2
),
/* GEYSER 2 ANSI */
ATP_DEVICE
(
0x0215
,
GEYSER2
),
/* GEYSER 2 ISO */
ATP_DEVICE
(
0x0216
,
GEYSER2
),
/* GEYSER 2 JIS */
ATP_DEVICE
(
0x0214
,
geyser2_info
),
/* GEYSER 2 ANSI */
ATP_DEVICE
(
0x0215
,
geyser2_info
),
/* GEYSER 2 ISO */
ATP_DEVICE
(
0x0216
,
geyser2_info
),
/* GEYSER 2 JIS */
/* Core Duo MacBook & MacBook Pro */
ATP_DEVICE
(
0x0217
,
GEYSER3
),
/* GEYSER 3 ANSI */
ATP_DEVICE
(
0x0218
,
GEYSER3
),
/* GEYSER 3 ISO */
ATP_DEVICE
(
0x0219
,
GEYSER3
),
/* GEYSER 3 JIS */
ATP_DEVICE
(
0x0217
,
geyser3_info
),
/* GEYSER 3 ANSI */
ATP_DEVICE
(
0x0218
,
geyser3_info
),
/* GEYSER 3 ISO */
ATP_DEVICE
(
0x0219
,
geyser3_info
),
/* GEYSER 3 JIS */
/* Core2 Duo MacBook & MacBook Pro */
ATP_DEVICE
(
0x021a
,
GEYSER4
),
/* GEYSER 4 ANSI */
ATP_DEVICE
(
0x021b
,
GEYSER4
),
/* GEYSER 4 ISO */
ATP_DEVICE
(
0x021c
,
GEYSER4
),
/* GEYSER 4 JIS */
ATP_DEVICE
(
0x021a
,
geyser4_info
),
/* GEYSER 4 ANSI */
ATP_DEVICE
(
0x021b
,
geyser4_info
),
/* GEYSER 4 ISO */
ATP_DEVICE
(
0x021c
,
geyser4_info
),
/* GEYSER 4 JIS */
/* Core2 Duo MacBook3,1 */
ATP_DEVICE
(
0x0229
,
GEYSER4
),
/* GEYSER 4 HF ANSI */
ATP_DEVICE
(
0x022a
,
GEYSER4
),
/* GEYSER 4 HF ISO */
ATP_DEVICE
(
0x022b
,
GEYSER4
),
/* GEYSER 4 HF JIS */
ATP_DEVICE
(
0x0229
,
geyser4_info
),
/* GEYSER 4 HF ANSI */
ATP_DEVICE
(
0x022a
,
geyser4_info
),
/* GEYSER 4 HF ISO */
ATP_DEVICE
(
0x022b
,
geyser4_info
),
/* GEYSER 4 HF JIS */
/* Terminating entry */
{
}
};
MODULE_DEVICE_TABLE
(
usb
,
atp_table
);
/*
* number of sensors. Note that only 16 instead of 26 X (horizontal)
* sensors exist on 12" and 15" PowerBooks. All models have 16 Y
* (vertical) sensors.
*/
/* maximum number of sensors */
#define ATP_XSENSORS 26
#define ATP_YSENSORS 16
...
...
@@ -107,21 +161,6 @@ MODULE_DEVICE_TABLE(usb, atp_table);
/* maximum pressure this driver will report */
#define ATP_PRESSURE 300
/*
* multiplication factor for the X and Y coordinates.
* We try to keep the touchpad aspect ratio while still doing only simple
* arithmetics.
* The factors below give coordinates like:
*
* 0 <= x < 960 on 12" and 15" Powerbooks
* 0 <= x < 1600 on 17" Powerbooks and 17" MacBook Pro
* 0 <= x < 1216 on MacBooks and 15" MacBook Pro
*
* 0 <= y < 646 on all Powerbooks
* 0 <= y < 774 on all MacBooks
*/
#define ATP_XFACT 64
#define ATP_YFACT 43
/*
* Threshold for the touchpad sensors. Any change less than ATP_THRESHOLD is
...
...
@@ -159,7 +198,7 @@ struct atp {
struct
urb
*
urb
;
/* usb request block */
u8
*
data
;
/* transferred data */
struct
input_dev
*
input
;
/* input dev */
enum
atp_touchpad_type
type
;
/* type of touchpad
*/
const
struct
atp_info
*
info
;
/* touchpad model
*/
bool
open
;
bool
valid
;
/* are the samples valid? */
bool
size_detect_done
;
...
...
@@ -169,7 +208,6 @@ struct atp {
signed
char
xy_cur
[
ATP_XSENSORS
+
ATP_YSENSORS
];
signed
char
xy_old
[
ATP_XSENSORS
+
ATP_YSENSORS
];
int
xy_acc
[
ATP_XSENSORS
+
ATP_YSENSORS
];
int
datalen
;
/* size of USB transfer */
int
idlecount
;
/* number of empty packets */
struct
work_struct
work
;
};
...
...
@@ -359,7 +397,7 @@ static int atp_status_check(struct urb *urb)
if
(
!
dev
->
overflow_warned
)
{
printk
(
KERN_WARNING
"appletouch: OVERFLOW with data "
"length %d, actual length is %d
\n
"
,
dev
->
datalen
,
dev
->
urb
->
actual_length
);
dev
->
info
->
datalen
,
dev
->
urb
->
actual_length
);
dev
->
overflow_warned
=
true
;
}
case
-
ECONNRESET
:
...
...
@@ -377,7 +415,7 @@ static int atp_status_check(struct urb *urb)
}
/* drop incomplete datasets */
if
(
dev
->
urb
->
actual_length
!=
dev
->
datalen
)
{
if
(
dev
->
urb
->
actual_length
!=
dev
->
info
->
datalen
)
{
dprintk
(
"appletouch: incomplete data package"
" (first byte: %d, length: %d).
\n
"
,
dev
->
data
[
0
],
dev
->
urb
->
actual_length
);
...
...
@@ -387,6 +425,25 @@ static int atp_status_check(struct urb *urb)
return
ATP_URB_STATUS_SUCCESS
;
}
static
void
atp_detect_size
(
struct
atp
*
dev
)
{
int
i
;
/* 17" Powerbooks have extra X sensors */
for
(
i
=
dev
->
info
->
xsensors
;
i
<
ATP_XSENSORS
;
i
++
)
{
if
(
dev
->
xy_cur
[
i
])
{
printk
(
KERN_INFO
"appletouch: 17
\"
model detected.
\n
"
);
input_set_abs_params
(
dev
->
input
,
ABS_X
,
0
,
(
dev
->
info
->
xsensors_17
-
1
)
*
dev
->
info
->
xfact
-
1
,
ATP_FUZZ
,
0
);
break
;
}
}
}
/*
* USB interrupt callback functions
*/
...
...
@@ -407,7 +464,7 @@ static void atp_complete_geyser_1_2(struct urb *urb)
goto
exit
;
/* reorder the sensors values */
if
(
dev
->
type
==
ATP_GEYSER2
)
{
if
(
dev
->
info
==
&
geyser2_info
)
{
memset
(
dev
->
xy_cur
,
0
,
sizeof
(
dev
->
xy_cur
));
/*
...
...
@@ -437,8 +494,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
dev
->
xy_cur
[
i
+
24
]
=
dev
->
data
[
5
*
i
+
44
];
/* Y values */
dev
->
xy_cur
[
i
+
26
]
=
dev
->
data
[
5
*
i
+
1
];
dev
->
xy_cur
[
i
+
34
]
=
dev
->
data
[
5
*
i
+
3
];
dev
->
xy_cur
[
ATP_XSENSORS
+
i
]
=
dev
->
data
[
5
*
i
+
1
];
dev
->
xy_cur
[
ATP_XSENSORS
+
i
+
8
]
=
dev
->
data
[
5
*
i
+
3
];
}
}
...
...
@@ -453,32 +510,8 @@ static void atp_complete_geyser_1_2(struct urb *urb)
memcpy
(
dev
->
xy_old
,
dev
->
xy_cur
,
sizeof
(
dev
->
xy_old
));
/* 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
;
}
if
(
unlikely
(
!
dev
->
size_detect_done
))
{
atp_detect_size
(
dev
);
dev
->
size_detect_done
=
1
;
goto
exit
;
}
...
...
@@ -499,10 +532,10 @@ static void atp_complete_geyser_1_2(struct urb *urb)
dbg_dump
(
"accumulator"
,
dev
->
xy_acc
);
x
=
atp_calculate_abs
(
dev
->
xy_acc
,
ATP_XSENSORS
,
ATP_XFACT
,
&
x_z
,
&
x_f
);
dev
->
info
->
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
;
dev
->
info
->
yfact
,
&
y_z
,
&
y_f
);
key
=
dev
->
data
[
dev
->
info
->
datalen
-
1
]
&
ATP_STATUS_BUTTON
;
if
(
x
&&
y
)
{
if
(
dev
->
x_old
!=
-
1
)
{
...
...
@@ -583,7 +616,7 @@ static void atp_complete_geyser_3_4(struct urb *urb)
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
)
{
if
(
dev
->
data
[
dev
->
info
->
datalen
-
1
]
&
ATP_STATUS_BASE_UPDATE
)
{
dprintk
(
KERN_DEBUG
"appletouch: updated base values
\n
"
);
...
...
@@ -610,10 +643,10 @@ static void atp_complete_geyser_3_4(struct urb *urb)
dbg_dump
(
"accumulator"
,
dev
->
xy_acc
);
x
=
atp_calculate_abs
(
dev
->
xy_acc
,
ATP_XSENSORS
,
ATP_XFACT
,
&
x_z
,
&
x_f
);
dev
->
info
->
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
;
dev
->
info
->
yfact
,
&
y_z
,
&
y_f
);
key
=
dev
->
data
[
dev
->
info
->
datalen
-
1
]
&
ATP_STATUS_BUTTON
;
if
(
x
&&
y
)
{
if
(
dev
->
x_old
!=
-
1
)
{
...
...
@@ -705,7 +738,7 @@ static int atp_handle_geyser(struct atp *dev)
{
struct
usb_device
*
udev
=
dev
->
udev
;
if
(
dev
->
type
!=
ATP_FOUNTAIN
)
{
if
(
dev
->
info
!=
&
fountain_info
)
{
/* switch to raw sensor mode */
if
(
atp_geyser_init
(
udev
))
return
-
EIO
;
...
...
@@ -726,6 +759,7 @@ static int atp_probe(struct usb_interface *iface,
struct
usb_endpoint_descriptor
*
endpoint
;
int
int_in_endpointAddr
=
0
;
int
i
,
error
=
-
ENOMEM
;
const
struct
atp_info
*
info
=
(
const
struct
atp_info
*
)
id
->
driver_info
;
/* set up the endpoint information */
/* use only the first interrupt-in endpoint */
...
...
@@ -753,35 +787,22 @@ static int atp_probe(struct usb_interface *iface,
dev
->
udev
=
udev
;
dev
->
input
=
input_dev
;
dev
->
type
=
id
->
driver_
info
;
dev
->
info
=
info
;
dev
->
overflow_warned
=
false
;
if
(
dev
->
type
==
ATP_FOUNTAIN
||
dev
->
type
==
ATP_GEYSER1
)
dev
->
datalen
=
81
;
else
dev
->
datalen
=
64
;
dev
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
dev
->
urb
)
goto
err_free_devs
;
dev
->
data
=
usb_buffer_alloc
(
dev
->
udev
,
dev
->
datalen
,
GFP_KERNEL
,
dev
->
data
=
usb_buffer_alloc
(
dev
->
udev
,
dev
->
info
->
datalen
,
GFP_KERNEL
,
&
dev
->
urb
->
transfer_dma
);
if
(
!
dev
->
data
)
goto
err_free_urb
;
/* 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
);
usb_fill_int_urb
(
dev
->
urb
,
udev
,
usb_rcvintpipe
(
udev
,
int_in_endpointAddr
),
dev
->
data
,
dev
->
info
->
datalen
,
dev
->
info
->
callback
,
dev
,
1
);
error
=
atp_handle_geyser
(
dev
);
if
(
error
)
...
...
@@ -802,35 +823,12 @@ static int atp_probe(struct usb_interface *iface,
set_bit
(
EV_ABS
,
input_dev
->
evbit
);
if
(
dev
->
type
==
ATP_GEYSER3
||
dev
->
type
==
ATP_GEYSER4
)
{
/*
* MacBook have 20 X sensors, 10 Y sensors
*/
input_set_abs_params
(
input_dev
,
ABS_X
,
0
,
((
20
-
1
)
*
ATP_XFACT
)
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
input_dev
,
ABS_Y
,
0
,
((
10
-
1
)
*
ATP_YFACT
)
-
1
,
ATP_FUZZ
,
0
);
}
else
if
(
dev
->
type
==
ATP_GEYSER2
)
{
/*
* Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
* later.
*/
input_set_abs_params
(
input_dev
,
ABS_X
,
0
,
((
15
-
1
)
*
ATP_XFACT
)
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
input_dev
,
ABS_Y
,
0
,
((
9
-
1
)
*
ATP_YFACT
)
-
1
,
ATP_FUZZ
,
0
);
}
else
{
/*
* 12" and 15" Powerbooks only have 16 x sensors,
* 17" models are detected later.
*/
input_set_abs_params
(
input_dev
,
ABS_X
,
0
,
(
16
-
1
)
*
ATP_XFACT
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
input_dev
,
ABS_Y
,
0
,
(
ATP_YSENSORS
-
1
)
*
ATP_YFACT
-
1
,
ATP_FUZZ
,
0
);
}
input_set_abs_params
(
input_dev
,
ABS_X
,
0
,
(
dev
->
info
->
xsensors
-
1
)
*
dev
->
info
->
xfact
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
input_dev
,
ABS_Y
,
0
,
(
dev
->
info
->
ysensors
-
1
)
*
dev
->
info
->
yfact
-
1
,
ATP_FUZZ
,
0
);
input_set_abs_params
(
input_dev
,
ABS_PRESSURE
,
0
,
ATP_PRESSURE
,
0
,
0
);
set_bit
(
EV_KEY
,
input_dev
->
evbit
);
...
...
@@ -852,7 +850,7 @@ static int atp_probe(struct usb_interface *iface,
return
0
;
err_free_buffer:
usb_buffer_free
(
dev
->
udev
,
dev
->
datalen
,
usb_buffer_free
(
dev
->
udev
,
dev
->
info
->
datalen
,
dev
->
data
,
dev
->
urb
->
transfer_dma
);
err_free_urb:
usb_free_urb
(
dev
->
urb
);
...
...
@@ -871,7 +869,7 @@ static void atp_disconnect(struct usb_interface *iface)
if
(
dev
)
{
usb_kill_urb
(
dev
->
urb
);
input_unregister_device
(
dev
->
input
);
usb_buffer_free
(
dev
->
udev
,
dev
->
datalen
,
usb_buffer_free
(
dev
->
udev
,
dev
->
info
->
datalen
,
dev
->
data
,
dev
->
urb
->
transfer_dma
);
usb_free_urb
(
dev
->
urb
);
kfree
(
dev
);
...
...
drivers/input/mouse/gpio_mouse.c
浏览文件 @
1dd32946
...
...
@@ -173,7 +173,7 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS
(
"platform:gpio_mouse"
);
struct
platform_driver
gpio_mouse_device_driver
=
{
st
atic
st
ruct
platform_driver
gpio_mouse_device_driver
=
{
.
remove
=
__devexit_p
(
gpio_mouse_remove
),
.
driver
=
{
.
name
=
"gpio_mouse"
,
...
...
drivers/input/mouse/hgpk.c
浏览文件 @
1dd32946
...
...
@@ -48,6 +48,30 @@ module_param(recalib_delta, int, 0644);
MODULE_PARM_DESC
(
recalib_delta
,
"packets containing a delta this large will cause a recalibration."
);
static
int
jumpy_delay
=
1000
;
module_param
(
jumpy_delay
,
int
,
0644
);
MODULE_PARM_DESC
(
jumpy_delay
,
"delay (ms) before recal after jumpiness detected"
);
static
int
spew_delay
=
1000
;
module_param
(
spew_delay
,
int
,
0644
);
MODULE_PARM_DESC
(
spew_delay
,
"delay (ms) before recal after packet spew detected"
);
static
int
recal_guard_time
=
2000
;
module_param
(
recal_guard_time
,
int
,
0644
);
MODULE_PARM_DESC
(
recal_guard_time
,
"interval (ms) during which recal will be restarted if packet received"
);
static
int
post_interrupt_delay
=
1000
;
module_param
(
post_interrupt_delay
,
int
,
0644
);
MODULE_PARM_DESC
(
post_interrupt_delay
,
"delay (ms) before recal after recal interrupt detected"
);
static
int
autorecal
=
1
;
module_param
(
autorecal
,
int
,
0644
);
MODULE_PARM_DESC
(
autorecal
,
"enable recalibration in the driver"
);
/*
* 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
...
...
@@ -66,7 +90,7 @@ static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int 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
));
msecs_to_jiffies
(
jumpy_delay
));
}
}
...
...
@@ -103,7 +127,7 @@ static void hgpk_spewing_hack(struct psmouse *psmouse,
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
));
msecs_to_jiffies
(
spew_delay
));
}
/* reset every 100 packets */
priv
->
count
=
0
;
...
...
@@ -181,7 +205,7 @@ static psmouse_ret_t hgpk_process_byte(struct psmouse *psmouse)
"packet inside calibration window, "
"queueing another recalibration
\n
"
);
psmouse_queue_work
(
psmouse
,
&
priv
->
recalib_wq
,
msecs_to_jiffies
(
1000
));
msecs_to_jiffies
(
post_interrupt_delay
));
}
priv
->
recalib_window
=
0
;
}
...
...
@@ -231,7 +255,7 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse)
* 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
);
priv
->
recalib_window
=
jiffies
+
msecs_to_jiffies
(
recal_guard_time
);
return
0
;
}
...
...
drivers/input/mouse/hil_ptr.c
浏览文件 @
1dd32946
...
...
@@ -46,7 +46,7 @@
MODULE_AUTHOR
(
"Brian S. Julin <bri@calyx.com>"
);
MODULE_DESCRIPTION
(
HIL_GENERIC_NAME
" driver"
);
MODULE_LICENSE
(
"Dual BSD/GPL"
);
MODULE_ALIAS
(
"serio:ty03pr25id0Fex*"
);
#define TABLET_SIMULATES_MOUSE
/* allow tablet to be used as mouse */
#undef TABLET_AUTOADJUST
/* auto-adjust valid tablet ranges */
...
...
drivers/input/mouse/pxa930_trkball.c
0 → 100644
浏览文件 @
1dd32946
/*
* PXA930 track ball mouse driver
*
* Copyright (C) 2007 Marvell International Ltd.
* 2008-02-28: Yong Yao <yaoyong@marvell.com>
* initial version
*
* 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.
*/
#include <linux/init.h>
#include <linux/input.h>
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/pxa930_trkball.h>
/* Trackball Controller Register Definitions */
#define TBCR (0x000C)
#define TBCNTR (0x0010)
#define TBSBC (0x0014)
#define TBCR_TBRST (1 << 1)
#define TBCR_TBSB (1 << 10)
#define TBCR_Y_FLT(n) (((n) & 0xf) << 6)
#define TBCR_X_FLT(n) (((n) & 0xf) << 2)
#define TBCNTR_YM(n) (((n) >> 24) & 0xff)
#define TBCNTR_YP(n) (((n) >> 16) & 0xff)
#define TBCNTR_XM(n) (((n) >> 8) & 0xff)
#define TBCNTR_XP(n) ((n) & 0xff)
#define TBSBC_TBSBC (0x1)
struct
pxa930_trkball
{
struct
pxa930_trkball_platform_data
*
pdata
;
/* Memory Mapped Register */
struct
resource
*
mem
;
void
__iomem
*
mmio_base
;
struct
input_dev
*
input
;
};
static
irqreturn_t
pxa930_trkball_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
pxa930_trkball
*
trkball
=
dev_id
;
struct
input_dev
*
input
=
trkball
->
input
;
int
tbcntr
,
x
,
y
;
/* According to the spec software must read TBCNTR twice:
* if the read value is the same, the reading is valid
*/
tbcntr
=
__raw_readl
(
trkball
->
mmio_base
+
TBCNTR
);
if
(
tbcntr
==
__raw_readl
(
trkball
->
mmio_base
+
TBCNTR
))
{
x
=
(
TBCNTR_XP
(
tbcntr
)
-
TBCNTR_XM
(
tbcntr
))
/
2
;
y
=
(
TBCNTR_YP
(
tbcntr
)
-
TBCNTR_YM
(
tbcntr
))
/
2
;
input_report_rel
(
input
,
REL_X
,
x
);
input_report_rel
(
input
,
REL_Y
,
y
);
input_sync
(
input
);
}
__raw_writel
(
TBSBC_TBSBC
,
trkball
->
mmio_base
+
TBSBC
);
__raw_writel
(
0
,
trkball
->
mmio_base
+
TBSBC
);
return
IRQ_HANDLED
;
}
/* For TBCR, we need to wait for a while to make sure it has been modified. */
static
int
write_tbcr
(
struct
pxa930_trkball
*
trkball
,
int
v
)
{
int
i
=
100
;
__raw_writel
(
v
,
trkball
->
mmio_base
+
TBCR
);
while
(
i
--
)
{
if
(
__raw_readl
(
trkball
->
mmio_base
+
TBCR
)
==
v
)
break
;
msleep
(
1
);
}
if
(
i
==
0
)
{
pr_err
(
"%s: timed out writing TBCR(%x)!
\n
"
,
__func__
,
v
);
return
-
ETIMEDOUT
;
}
return
0
;
}
static
void
pxa930_trkball_config
(
struct
pxa930_trkball
*
trkball
)
{
uint32_t
tbcr
;
/* According to spec, need to write the filters of x,y to 0xf first! */
tbcr
=
__raw_readl
(
trkball
->
mmio_base
+
TBCR
);
write_tbcr
(
trkball
,
tbcr
|
TBCR_X_FLT
(
0xf
)
|
TBCR_Y_FLT
(
0xf
));
write_tbcr
(
trkball
,
TBCR_X_FLT
(
trkball
->
pdata
->
x_filter
)
|
TBCR_Y_FLT
(
trkball
->
pdata
->
y_filter
));
/* According to spec, set TBCR_TBRST first, before clearing it! */
tbcr
=
__raw_readl
(
trkball
->
mmio_base
+
TBCR
);
write_tbcr
(
trkball
,
tbcr
|
TBCR_TBRST
);
write_tbcr
(
trkball
,
tbcr
&
~
TBCR_TBRST
);
__raw_writel
(
TBSBC_TBSBC
,
trkball
->
mmio_base
+
TBSBC
);
__raw_writel
(
0
,
trkball
->
mmio_base
+
TBSBC
);
pr_debug
(
"%s: final TBCR=%x!
\n
"
,
__func__
,
__raw_readl
(
trkball
->
mmio_base
+
TBCR
));
}
static
int
pxa930_trkball_open
(
struct
input_dev
*
dev
)
{
struct
pxa930_trkball
*
trkball
=
input_get_drvdata
(
dev
);
pxa930_trkball_config
(
trkball
);
return
0
;
}
static
void
pxa930_trkball_disable
(
struct
pxa930_trkball
*
trkball
)
{
uint32_t
tbcr
=
__raw_readl
(
trkball
->
mmio_base
+
TBCR
);
/* Held in reset, gate the 32-KHz input clock off */
write_tbcr
(
trkball
,
tbcr
|
TBCR_TBRST
);
}
static
void
pxa930_trkball_close
(
struct
input_dev
*
dev
)
{
struct
pxa930_trkball
*
trkball
=
input_get_drvdata
(
dev
);
pxa930_trkball_disable
(
trkball
);
}
static
int
__devinit
pxa930_trkball_probe
(
struct
platform_device
*
pdev
)
{
struct
pxa930_trkball
*
trkball
;
struct
input_dev
*
input
;
struct
resource
*
res
;
int
irq
,
error
;
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
irq
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"failed to get trkball irq
\n
"
);
return
-
ENXIO
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"failed to get register memory
\n
"
);
return
-
ENXIO
;
}
trkball
=
kzalloc
(
sizeof
(
struct
pxa930_trkball
),
GFP_KERNEL
);
if
(
!
trkball
)
return
-
ENOMEM
;
trkball
->
pdata
=
pdev
->
dev
.
platform_data
;
if
(
!
trkball
->
pdata
)
{
dev_err
(
&
pdev
->
dev
,
"no platform data defined
\n
"
);
error
=
-
EINVAL
;
goto
failed
;
}
trkball
->
mmio_base
=
ioremap_nocache
(
res
->
start
,
resource_size
(
res
));
if
(
!
trkball
->
mmio_base
)
{
dev_err
(
&
pdev
->
dev
,
"failed to ioremap registers
\n
"
);
error
=
-
ENXIO
;
goto
failed
;
}
/* held the module in reset, will be enabled in open() */
pxa930_trkball_disable
(
trkball
);
error
=
request_irq
(
irq
,
pxa930_trkball_interrupt
,
IRQF_DISABLED
,
pdev
->
name
,
trkball
);
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"failed to request irq: %d
\n
"
,
ret
);
goto
failed_free_io
;
}
platform_set_drvdata
(
pdev
,
trkball
);
input
=
input_allocate_device
();
if
(
!
input
)
{
dev_err
(
&
pdev
->
dev
,
"failed to allocate input device
\n
"
);
error
=
-
ENOMEM
;
goto
failed_free_irq
;
}
input
->
name
=
pdev
->
name
;
input
->
id
.
bustype
=
BUS_HOST
;
input
->
open
=
pxa930_trkball_open
;
input
->
close
=
pxa930_trkball_close
;
input
->
dev
.
parent
=
&
pdev
->
dev
;
input_set_drvdata
(
input
,
trkball
);
trkball
->
input
=
input
;
input_set_capability
(
input
,
EV_REL
,
REL_X
);
input_set_capability
(
input
,
EV_REL
,
REL_Y
);
error
=
input_register_device
(
input
);
if
(
error
)
{
dev_err
(
&
pdev
->
dev
,
"unable to register input device
\n
"
);
goto
failed_free_input
;
}
return
0
;
failed_free_input:
input_free_device
(
input
);
failed_free_irq:
free_irq
(
irq
,
trkball
);
failed_free_io:
iounmap
(
trkball
->
mmio_base
);
failed:
kfree
(
trkball
);
return
ret
;
}
static
int
__devexit
pxa930_trkball_remove
(
struct
platform_device
*
pdev
)
{
struct
pxa930_trkball
*
trkball
=
platform_get_drvdata
(
pdev
);
int
irq
=
platform_get_irq
(
pdev
,
0
);
input_unregister_device
(
trkball
->
input
);
free_irq
(
irq
,
trkball
);
iounmap
(
trkball
->
mmio_base
);
kfree
(
trkball
);
return
0
;
}
static
struct
platform_driver
pxa930_trkball_driver
=
{
.
driver
=
{
.
name
=
"pxa930-trkball"
,
},
.
probe
=
pxa930_trkball_probe
,
.
remove
=
__devexit_p
(
pxa930_trkball_remove
),
};
static
int
__init
pxa930_trkball_init
(
void
)
{
return
platform_driver_register
(
&
pxa930_trkball_driver
);
}
static
void
__exit
pxa930_trkball_exit
(
void
)
{
platform_driver_unregister
(
&
pxa930_trkball_driver
);
}
module_init
(
pxa930_trkball_init
);
module_exit
(
pxa930_trkball_exit
);
MODULE_AUTHOR
(
"Yong Yao <yaoyong@marvell.com>"
);
MODULE_DESCRIPTION
(
"PXA930 Trackball Mouse Driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/mouse/synaptics.c
浏览文件 @
1dd32946
...
...
@@ -445,12 +445,14 @@ static void synaptics_process_packet(struct psmouse *psmouse)
input_report_abs
(
dev
,
ABS_TOOL_WIDTH
,
finger_width
);
input_report_key
(
dev
,
BTN_TOOL_FINGER
,
num_fingers
==
1
);
input_report_key
(
dev
,
BTN_TOOL_DOUBLETAP
,
num_fingers
==
2
);
input_report_key
(
dev
,
BTN_TOOL_TRIPLETAP
,
num_fingers
==
3
);
input_report_key
(
dev
,
BTN_LEFT
,
hw
.
left
);
input_report_key
(
dev
,
BTN_RIGHT
,
hw
.
right
);
if
(
SYN_CAP_MULTIFINGER
(
priv
->
capabilities
))
{
input_report_key
(
dev
,
BTN_TOOL_DOUBLETAP
,
num_fingers
==
2
);
input_report_key
(
dev
,
BTN_TOOL_TRIPLETAP
,
num_fingers
==
3
);
}
if
(
SYN_CAP_MIDDLE_BUTTON
(
priv
->
capabilities
))
input_report_key
(
dev
,
BTN_MIDDLE
,
hw
.
middle
);
...
...
@@ -543,12 +545,14 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
set_bit
(
EV_KEY
,
dev
->
evbit
);
set_bit
(
BTN_TOUCH
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_FINGER
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_DOUBLETAP
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_TRIPLETAP
,
dev
->
keybit
);
set_bit
(
BTN_LEFT
,
dev
->
keybit
);
set_bit
(
BTN_RIGHT
,
dev
->
keybit
);
if
(
SYN_CAP_MULTIFINGER
(
priv
->
capabilities
))
{
set_bit
(
BTN_TOOL_DOUBLETAP
,
dev
->
keybit
);
set_bit
(
BTN_TOOL_TRIPLETAP
,
dev
->
keybit
);
}
if
(
SYN_CAP_MIDDLE_BUTTON
(
priv
->
capabilities
))
set_bit
(
BTN_MIDDLE
,
dev
->
keybit
);
...
...
drivers/input/mousedev.c
浏览文件 @
1dd32946
...
...
@@ -878,8 +878,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
mousedev
->
handle
.
handler
=
handler
;
mousedev
->
handle
.
private
=
mousedev
;
strlcpy
(
mousedev
->
dev
.
bus_id
,
mousedev
->
name
,
sizeof
(
mousedev
->
dev
.
bus_id
));
dev_set_name
(
&
mousedev
->
dev
,
mousedev
->
name
);
mousedev
->
dev
.
class
=
&
input_class
;
if
(
dev
)
mousedev
->
dev
.
parent
=
&
dev
->
dev
;
...
...
drivers/input/serio/hil_mlc.c
浏览文件 @
1dd32946
...
...
@@ -934,6 +934,7 @@ int hil_mlc_register(hil_mlc *mlc)
snprintf
(
mlc_serio
->
name
,
sizeof
(
mlc_serio
->
name
)
-
1
,
"HIL_SERIO%d"
,
i
);
snprintf
(
mlc_serio
->
phys
,
sizeof
(
mlc_serio
->
phys
)
-
1
,
"HIL%d"
,
i
);
mlc_serio
->
id
=
hil_mlc_serio_id
;
mlc_serio
->
id
.
id
=
i
;
/* HIL port no. */
mlc_serio
->
write
=
hil_mlc_serio_write
;
mlc_serio
->
open
=
hil_mlc_serio_open
;
mlc_serio
->
close
=
hil_mlc_serio_close
;
...
...
drivers/input/serio/i8042-x86ia64io.h
浏览文件 @
1dd32946
...
...
@@ -143,6 +143,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
DMI_MATCH
(
DMI_PRODUCT_VERSION
,
"M606"
),
},
},
{
.
ident
=
"Gigabyte M912"
,
.
matches
=
{
DMI_MATCH
(
DMI_SYS_VENDOR
,
"GIGABYTE"
),
DMI_MATCH
(
DMI_PRODUCT_NAME
,
"M912"
),
DMI_MATCH
(
DMI_PRODUCT_VERSION
,
"01"
),
},
},
{
}
};
...
...
drivers/input/serio/libps2.c
浏览文件 @
1dd32946
...
...
@@ -262,9 +262,17 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
break
;
case
PS2_RET_NAK
:
ps2dev
->
nak
=
1
;
ps2dev
->
flags
|=
PS2_FLAG_NAK
;
ps2dev
->
nak
=
PS2_RET_NAK
;
break
;
case
PS2_RET_ERR
:
if
(
ps2dev
->
flags
&
PS2_FLAG_NAK
)
{
ps2dev
->
flags
&=
~
PS2_FLAG_NAK
;
ps2dev
->
nak
=
PS2_RET_ERR
;
break
;
}
/*
* Workaround for mice which don't ACK the Get ID command.
* These are valid mouse IDs that we recognize.
...
...
@@ -282,8 +290,11 @@ int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data)
}
if
(
!
ps2dev
->
nak
&&
ps2dev
->
cmdcnt
)
ps2dev
->
flags
|=
PS2_FLAG_CMD
|
PS2_FLAG_CMD1
;
if
(
!
ps2dev
->
nak
)
{
ps2dev
->
flags
&=
~
PS2_FLAG_NAK
;
if
(
ps2dev
->
cmdcnt
)
ps2dev
->
flags
|=
PS2_FLAG_CMD
|
PS2_FLAG_CMD1
;
}
ps2dev
->
flags
&=
~
PS2_FLAG_ACK
;
wake_up
(
&
ps2dev
->
wait
);
...
...
@@ -329,6 +340,7 @@ void ps2_cmd_aborted(struct ps2dev *ps2dev)
if
(
ps2dev
->
flags
&
(
PS2_FLAG_ACK
|
PS2_FLAG_CMD
))
wake_up
(
&
ps2dev
->
wait
);
ps2dev
->
flags
=
0
;
/* reset all flags except last nack */
ps2dev
->
flags
&=
PS2_FLAG_NAK
;
}
EXPORT_SYMBOL
(
ps2_cmd_aborted
);
drivers/input/serio/pcips2.c
浏览文件 @
1dd32946
...
...
@@ -153,7 +153,7 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i
serio
->
open
=
pcips2_open
;
serio
->
close
=
pcips2_close
;
strlcpy
(
serio
->
name
,
pci_name
(
dev
),
sizeof
(
serio
->
name
));
strlcpy
(
serio
->
phys
,
dev
->
dev
.
bus_id
,
sizeof
(
serio
->
phys
));
strlcpy
(
serio
->
phys
,
dev
_name
(
&
dev
->
dev
)
,
sizeof
(
serio
->
phys
));
serio
->
port_data
=
ps2if
;
serio
->
dev
.
parent
=
&
dev
->
dev
;
ps2if
->
io
=
serio
;
...
...
drivers/input/serio/serio.c
浏览文件 @
1dd32946
...
...
@@ -546,8 +546,8 @@ static void serio_init_port(struct serio *serio)
spin_lock_init
(
&
serio
->
lock
);
mutex_init
(
&
serio
->
drv_mutex
);
device_initialize
(
&
serio
->
dev
);
snprintf
(
serio
->
dev
.
bus_id
,
sizeof
(
serio
->
dev
.
bus_id
)
,
"serio%ld"
,
(
long
)
atomic_inc_return
(
&
serio_no
)
-
1
);
dev_set_name
(
&
serio
->
dev
,
"serio%ld"
,
(
long
)
atomic_inc_return
(
&
serio_no
)
-
1
);
serio
->
dev
.
bus
=
&
serio_bus
;
serio
->
dev
.
release
=
serio_release_port
;
if
(
serio
->
parent
)
{
...
...
drivers/input/serio/xilinx_ps2.c
浏览文件 @
1dd32946
...
...
@@ -58,23 +58,20 @@
/* Mask for all the Receive Interrupts */
#define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \
XPS2_IPIXR_RX_FULL)
XPS2_IPIXR_RX_FULL)
/* Mask for all the Interrupts */
#define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \
XPS2_IPIXR_WDT_TOUT)
XPS2_IPIXR_WDT_TOUT)
/* Global Interrupt Enable mask */
#define XPS2_GIER_GIE_MASK 0x80000000
struct
xps2data
{
int
irq
;
u32
phys_addr
;
u32
remap_size
;
spinlock_t
lock
;
u8
rxb
;
/* Rx buffer */
void
__iomem
*
base_address
;
/* virt. address of control registers */
unsigned
int
dfl
;
unsigned
int
flags
;
struct
serio
serio
;
/* serio */
};
...
...
@@ -82,8 +79,13 @@ struct xps2data {
/* XPS PS/2 data transmission calls */
/************************************/
/*
* xps2_recv() will attempt to receive a byte of data from the PS/2 port.
/**
* xps2_recv() - attempts to receive a byte from the PS/2 port.
* @drvdata: pointer to ps2 device private data structure
* @byte: address where the read data will be copied
*
* If there is any data available in the PS/2 receiver, this functions reads
* the data, otherwise it returns error.
*/
static
int
xps2_recv
(
struct
xps2data
*
drvdata
,
u8
*
byte
)
{
...
...
@@ -116,33 +118,27 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
/* Check which interrupt is active */
if
(
intr_sr
&
XPS2_IPIXR_RX_OVF
)
printk
(
KERN_WARNING
"%s: receive overrun error
\n
"
,
drvdata
->
serio
.
name
);
dev_warn
(
drvdata
->
serio
.
dev
.
parent
,
"receive overrun error
\n
"
);
if
(
intr_sr
&
XPS2_IPIXR_RX_ERR
)
drvdata
->
dfl
|=
SERIO_PARITY
;
drvdata
->
flags
|=
SERIO_PARITY
;
if
(
intr_sr
&
(
XPS2_IPIXR_TX_NOACK
|
XPS2_IPIXR_WDT_TOUT
))
drvdata
->
dfl
|=
SERIO_TIMEOUT
;
drvdata
->
flags
|=
SERIO_TIMEOUT
;
if
(
intr_sr
&
XPS2_IPIXR_RX_FULL
)
{
status
=
xps2_recv
(
drvdata
,
&
drvdata
->
rxb
);
status
=
xps2_recv
(
drvdata
,
&
c
);
/* Error, if a byte is not received */
if
(
status
)
{
printk
(
KERN_ERR
"%s: wrong rcvd byte count (%d)
\n
"
,
drvdata
->
serio
.
name
,
status
);
dev_err
(
drvdata
->
serio
.
dev
.
parent
,
"wrong rcvd byte count (%d)
\n
"
,
status
);
}
else
{
c
=
drvdata
->
rxb
;
serio_interrupt
(
&
drvdata
->
serio
,
c
,
drvdata
->
dfl
);
drvdata
->
dfl
=
0
;
serio_interrupt
(
&
drvdata
->
serio
,
c
,
drvdata
->
flags
);
drvdata
->
flags
=
0
;
}
}
if
(
intr_sr
&
XPS2_IPIXR_TX_ACK
)
drvdata
->
dfl
=
0
;
return
IRQ_HANDLED
;
}
...
...
@@ -150,8 +146,15 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id)
/* serio callbacks */
/*******************/
/*
* sxps2_write() sends a byte out through the PS/2 interface.
/**
* sxps2_write() - sends a byte out through the PS/2 port.
* @pserio: pointer to the serio structure of the PS/2 port
* @c: data that needs to be written to the PS/2 port
*
* This function checks if the PS/2 transmitter is empty and sends a byte.
* Otherwise it returns error. Transmission fails only when nothing is connected
* to the PS/2 port. Thats why, we do not try to resend the data in case of a
* failure.
*/
static
int
sxps2_write
(
struct
serio
*
pserio
,
unsigned
char
c
)
{
...
...
@@ -174,33 +177,39 @@ static int sxps2_write(struct serio *pserio, unsigned char c)
return
status
;
}
/*
* sxps2_open() is called when a port is open by the higher layer.
/**
* sxps2_open() - called when a port is opened by the higher layer.
* @pserio: pointer to the serio structure of the PS/2 device
*
* This function requests irq and enables interrupts for the PS/2 device.
*/
static
int
sxps2_open
(
struct
serio
*
pserio
)
{
struct
xps2data
*
drvdata
=
pserio
->
port_data
;
int
retval
;
int
error
;
u8
c
;
retval
=
request_irq
(
drvdata
->
irq
,
&
xps2_interrupt
,
0
,
error
=
request_irq
(
drvdata
->
irq
,
&
xps2_interrupt
,
0
,
DRIVER_NAME
,
drvdata
);
if
(
retval
)
{
printk
(
KERN_ERR
"%s: Couldn't allocate interrupt %d
\n
"
,
drvdata
->
serio
.
name
,
drvdata
->
irq
);
return
retval
;
if
(
error
)
{
dev_err
(
drvdata
->
serio
.
dev
.
parent
,
"Couldn't allocate interrupt %d
\n
"
,
drvdata
->
irq
);
return
error
;
}
/* start reception by enabling the interrupts */
out_be32
(
drvdata
->
base_address
+
XPS2_GIER_OFFSET
,
XPS2_GIER_GIE_MASK
);
out_be32
(
drvdata
->
base_address
+
XPS2_IPIER_OFFSET
,
XPS2_IPIXR_RX_ALL
);
(
void
)
xps2_recv
(
drvdata
,
&
drvdata
->
rxb
);
(
void
)
xps2_recv
(
drvdata
,
&
c
);
return
0
;
/* success */
}
/*
* sxps2_close() frees the interrupt.
/**
* sxps2_close() - frees the interrupt.
* @pserio: pointer to the serio structure of the PS/2 device
*
* This function frees the irq and disables interrupts for the PS/2 device.
*/
static
void
sxps2_close
(
struct
serio
*
pserio
)
{
...
...
@@ -212,24 +221,41 @@ static void sxps2_close(struct serio *pserio)
free_irq
(
drvdata
->
irq
,
drvdata
);
}
/*********************/
/* Device setup code */
/*********************/
static
int
xps2_setup
(
struct
device
*
dev
,
struct
resource
*
regs_res
,
struct
resource
*
irq_res
)
/**
* xps2_of_probe - probe method for the PS/2 device.
* @of_dev: pointer to OF device structure
* @match: pointer to the stucture used for matching a device
*
* This function probes the PS/2 device in the device tree.
* It initializes the driver data structure and the hardware.
* It returns 0, if the driver is bound to the PS/2 device, or a negative
* value if there is an error.
*/
static
int
__devinit
xps2_of_probe
(
struct
of_device
*
ofdev
,
const
struct
of_device_id
*
match
)
{
struct
resource
r_irq
;
/* Interrupt resources */
struct
resource
r_mem
;
/* IO mem resources */
struct
xps2data
*
drvdata
;
struct
serio
*
serio
;
unsigned
long
remap_size
;
int
retval
;
struct
device
*
dev
=
&
ofdev
->
dev
;
resource_size_t
remap_size
,
phys_addr
;
int
error
;
dev_info
(
dev
,
"Device Tree Probing
\'
%s
\'\n
"
,
ofdev
->
node
->
name
);
if
(
!
dev
)
return
-
EINVAL
;
/* Get iospace for the device */
error
=
of_address_to_resource
(
ofdev
->
node
,
0
,
&
r_mem
);
if
(
error
)
{
dev_err
(
dev
,
"invalid address
\n
"
);
return
error
;
}
if
(
!
regs_res
||
!
irq_res
)
{
dev_err
(
dev
,
"IO resource(s) not found
\n
"
);
return
-
EINVAL
;
/* Get IRQ for the device */
if
(
of_irq_to_resource
(
ofdev
->
node
,
0
,
&
r_irq
)
==
NO_IRQ
)
{
dev_err
(
dev
,
"no IRQ found
\n
"
);
return
-
ENODEV
;
}
drvdata
=
kzalloc
(
sizeof
(
struct
xps2data
),
GFP_KERNEL
);
...
...
@@ -241,24 +267,23 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
dev_set_drvdata
(
dev
,
drvdata
);
spin_lock_init
(
&
drvdata
->
lock
);
drvdata
->
irq
=
irq_res
->
start
;
remap_size
=
regs_res
->
end
-
regs_res
->
start
+
1
;
if
(
!
request_mem_region
(
regs_res
->
start
,
remap_size
,
DRIVER_NAME
))
{
dev_err
(
dev
,
"Couldn't lock memory region at 0x%08X
\n
"
,
(
unsigned
int
)
regs_res
->
start
);
retval
=
-
EBUSY
;
drvdata
->
irq
=
r_irq
.
start
;
phys_addr
=
r_mem
.
start
;
remap_size
=
r_mem
.
end
-
r_mem
.
start
+
1
;
if
(
!
request_mem_region
(
phys_addr
,
remap_size
,
DRIVER_NAME
))
{
dev_err
(
dev
,
"Couldn't lock memory region at 0x%08llX
\n
"
,
(
unsigned
long
long
)
phys_addr
);
error
=
-
EBUSY
;
goto
failed1
;
}
/* Fill in configuration data and add them to the list */
drvdata
->
phys_addr
=
regs_res
->
start
;
drvdata
->
remap_size
=
remap_size
;
drvdata
->
base_address
=
ioremap
(
regs_res
->
start
,
remap_size
);
drvdata
->
base_address
=
ioremap
(
phys_addr
,
remap_size
);
if
(
drvdata
->
base_address
==
NULL
)
{
dev_err
(
dev
,
"Couldn't ioremap memory at 0x%08X
\n
"
,
(
unsigned
int
)
regs_res
->
start
);
retval
=
-
EFAULT
;
dev_err
(
dev
,
"Couldn't ioremap memory at 0x%08
ll
X
\n
"
,
(
unsigned
long
long
)
phys_addr
);
error
=
-
EFAULT
;
goto
failed2
;
}
...
...
@@ -269,8 +294,9 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
* we have the PS2 in a good state */
out_be32
(
drvdata
->
base_address
+
XPS2_SRST_OFFSET
,
XPS2_SRST_RESET
);
dev_info
(
dev
,
"Xilinx PS2 at 0x%08X mapped to 0x%p, irq=%d
\n
"
,
drvdata
->
phys_addr
,
drvdata
->
base_address
,
drvdata
->
irq
);
dev_info
(
dev
,
"Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d
\n
"
,
(
unsigned
long
long
)
phys_addr
,
drvdata
->
base_address
,
drvdata
->
irq
);
serio
=
&
drvdata
->
serio
;
serio
->
id
.
type
=
SERIO_8042
;
...
...
@@ -280,71 +306,51 @@ static int xps2_setup(struct device *dev, struct resource *regs_res,
serio
->
port_data
=
drvdata
;
serio
->
dev
.
parent
=
dev
;
snprintf
(
serio
->
name
,
sizeof
(
serio
->
name
),
"Xilinx XPS PS/2 at %08
X"
,
drvdata
->
phys_addr
);
"Xilinx XPS PS/2 at %08
llX"
,
(
unsigned
long
long
)
phys_addr
);
snprintf
(
serio
->
phys
,
sizeof
(
serio
->
phys
),
"xilinxps2/serio at %08X"
,
drvdata
->
phys_addr
);
"xilinxps2/serio at %08llX"
,
(
unsigned
long
long
)
phys_addr
);
serio_register_port
(
serio
);
return
0
;
/* success */
failed2:
release_mem_region
(
regs_res
->
start
,
remap_size
);
release_mem_region
(
phys_addr
,
remap_size
);
failed1:
kfree
(
drvdata
);
dev_set_drvdata
(
dev
,
NULL
);
return
retval
;
}
/***************************/
/* OF Platform Bus Support */
/***************************/
static
int
__devinit
xps2_of_probe
(
struct
of_device
*
ofdev
,
const
struct
of_device_id
*
match
)
{
struct
resource
r_irq
;
/* Interrupt resources */
struct
resource
r_mem
;
/* IO mem resources */
int
rc
=
0
;
printk
(
KERN_INFO
"Device Tree Probing
\'
%s
\'\n
"
,
ofdev
->
node
->
name
);
/* Get iospace for the device */
rc
=
of_address_to_resource
(
ofdev
->
node
,
0
,
&
r_mem
);
if
(
rc
)
{
dev_err
(
&
ofdev
->
dev
,
"invalid address
\n
"
);
return
rc
;
}
/* Get IRQ for the device */
rc
=
of_irq_to_resource
(
ofdev
->
node
,
0
,
&
r_irq
);
if
(
rc
==
NO_IRQ
)
{
dev_err
(
&
ofdev
->
dev
,
"no IRQ found
\n
"
);
return
rc
;
}
return
xps2_setup
(
&
ofdev
->
dev
,
&
r_mem
,
&
r_irq
);
return
error
;
}
/**
* xps2_of_remove - unbinds the driver from the PS/2 device.
* @of_dev: pointer to OF device structure
*
* This function is called if a device is physically removed from the system or
* if the driver module is being unloaded. It frees any resources allocated to
* the device.
*/
static
int
__devexit
xps2_of_remove
(
struct
of_device
*
of_dev
)
{
struct
device
*
dev
=
&
of_dev
->
dev
;
struct
xps2data
*
drvdata
;
if
(
!
dev
)
return
-
EINVAL
;
drvdata
=
dev_get_drvdata
(
dev
);
struct
xps2data
*
drvdata
=
dev_get_drvdata
(
dev
);
struct
resource
r_mem
;
/* IO mem resources */
serio_unregister_port
(
&
drvdata
->
serio
);
iounmap
(
drvdata
->
base_address
);
release_mem_region
(
drvdata
->
phys_addr
,
drvdata
->
remap_size
);
/* Get iospace of the device */
if
(
of_address_to_resource
(
of_dev
->
node
,
0
,
&
r_mem
))
dev_err
(
dev
,
"invalid address
\n
"
);
else
release_mem_region
(
r_mem
.
start
,
r_mem
.
end
-
r_mem
.
start
+
1
);
kfree
(
drvdata
);
dev_set_drvdata
(
dev
,
NULL
);
return
0
;
/* success */
return
0
;
}
/* Match table for of_platform binding */
...
...
drivers/input/tablet/gtco.c
浏览文件 @
1dd32946
...
...
@@ -877,7 +877,7 @@ static int gtco_probe(struct usb_interface *usbinterface,
dbg
(
"num endpoints: %d"
,
usbinterface
->
cur_altsetting
->
desc
.
bNumEndpoints
);
dbg
(
"interface class: %d"
,
usbinterface
->
cur_altsetting
->
desc
.
bInterfaceClass
);
dbg
(
"endpoint: attribute:0x%x type:0x%x"
,
endpoint
->
bmAttributes
,
endpoint
->
bDescriptorType
);
if
(
(
endpoint
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_INT
)
if
(
usb_endpoint_xfer_int
(
endpoint
)
)
dbg
(
"endpoint: we have interrupt endpoint
\n
"
);
dbg
(
"endpoint extra len:%d "
,
usbinterface
->
altsetting
[
0
].
extralen
);
...
...
drivers/input/tablet/wacom_wac.c
浏览文件 @
1dd32946
...
...
@@ -535,7 +535,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
return
1
;
}
int
wacom_tpc_irq
(
struct
wacom_wac
*
wacom
,
void
*
wcombo
)
static
int
wacom_tpc_irq
(
struct
wacom_wac
*
wacom
,
void
*
wcombo
)
{
char
*
data
=
wacom
->
data
;
int
prox
=
0
,
pressure
;
...
...
drivers/input/touchscreen/Kconfig
浏览文件 @
1dd32946
...
...
@@ -58,6 +58,14 @@ config TOUCHSCREEN_CORGI
NOTE: this driver is deprecated, try enable SPI and generic
ADS7846-based touchscreen driver.
config TOUCHSCREEN_DA9034
tristate "Touchscreen support for Dialog Semiconductor DA9034"
depends on PMIC_DA903X
default y
help
Say Y here to enable the support for the touchscreen found
on Dialog Semiconductor DA9034 PMIC.
config TOUCHSCREEN_FUJITSU
tristate "Fujitsu serial touchscreen"
select SERIO
...
...
@@ -95,6 +103,19 @@ config TOUCHSCREEN_ELO
To compile this driver as a module, choose M here: the
module will be called elo.
config TOUCHSCREEN_WACOM_W8001
tristate "Wacom W8001 penabled serial touchscreen"
select SERIO
help
Say Y here if you have an Wacom W8001 penabled serial touchscreen
connected to your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called wacom_w8001.
config TOUCHSCREEN_MTOUCH
tristate "MicroTouch serial touchscreens"
select SERIO
...
...
@@ -376,4 +397,15 @@ config TOUCHSCREEN_TOUCHIT213
To compile this driver as a module, choose M here: the
module will be called touchit213.
config TOUCHSCREEN_TSC2007
tristate "TSC2007 based touchscreens"
depends on I2C
help
Say Y here if you have a TSC2007 based touchscreen.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called tsc2007.
endif
drivers/input/touchscreen/Makefile
浏览文件 @
1dd32946
...
...
@@ -25,8 +25,11 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)
+=
touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)
+=
touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)
+=
touchwin.o
obj-$(CONFIG_TOUCHSCREEN_TSC2007)
+=
tsc2007.o
obj-$(CONFIG_TOUCHSCREEN_UCB1400)
+=
ucb1400_ts.o
obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)
+=
wacom_w8001.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX)
+=
wm97xx-ts.o
obj-$(CONFIG_TOUCHSCREEN_DA9034)
+=
da9034-ts.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)
+=
wm9705.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)
+=
wm9712.o
wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713)
+=
wm9713.o
...
...
drivers/input/touchscreen/ads7846.c
浏览文件 @
1dd32946
...
...
@@ -472,7 +472,7 @@ static ssize_t ads7846_disable_store(struct device *dev,
const
char
*
buf
,
size_t
count
)
{
struct
ads7846
*
ts
=
dev_get_drvdata
(
dev
);
long
i
;
unsigned
long
i
;
if
(
strict_strtoul
(
buf
,
10
,
&
i
))
return
-
EINVAL
;
...
...
@@ -559,7 +559,7 @@ static void ads7846_rx(void *ads)
if
(
packet
->
tc
.
ignore
||
Rt
>
ts
->
pressure_max
)
{
#ifdef VERBOSE
pr_debug
(
"%s: ignored %d pressure %d
\n
"
,
ts
->
spi
->
dev
.
bus_id
,
packet
->
tc
.
ignore
,
Rt
);
dev_name
(
&
ts
->
spi
->
dev
)
,
packet
->
tc
.
ignore
,
Rt
);
#endif
hrtimer_start
(
&
ts
->
timer
,
ktime_set
(
0
,
TS_POLL_PERIOD
),
HRTIMER_MODE_REL
);
...
...
@@ -947,7 +947,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts
->
penirq_recheck_delay_usecs
=
pdata
->
penirq_recheck_delay_usecs
;
snprintf
(
ts
->
phys
,
sizeof
(
ts
->
phys
),
"%s/input0"
,
spi
->
dev
.
bus_id
);
snprintf
(
ts
->
phys
,
sizeof
(
ts
->
phys
),
"%s/input0"
,
dev_name
(
&
spi
->
dev
)
);
input_dev
->
name
=
"ADS784x Touchscreen"
;
input_dev
->
phys
=
ts
->
phys
;
...
...
drivers/input/touchscreen/da9034-ts.c
0 → 100644
浏览文件 @
1dd32946
/*
* Touchscreen driver for Dialog Semiconductor DA9034
*
* Copyright (C) 2006-2008 Marvell International Ltd.
* Fengwei Yin <fengwei.yin@marvell.com>
* Eric Miao <eric.miao@marvell.com>
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/mfd/da903x.h>
#define DA9034_MANUAL_CTRL 0x50
#define DA9034_LDO_ADC_EN (1 << 4)
#define DA9034_AUTO_CTRL1 0x51
#define DA9034_AUTO_CTRL2 0x52
#define DA9034_AUTO_TSI_EN (1 << 3)
#define DA9034_PEN_DETECT (1 << 4)
#define DA9034_TSI_CTRL1 0x53
#define DA9034_TSI_CTRL2 0x54
#define DA9034_TSI_X_MSB 0x6c
#define DA9034_TSI_Y_MSB 0x6d
#define DA9034_TSI_XY_LSB 0x6e
enum
{
STATE_IDLE
,
/* wait for pendown */
STATE_BUSY
,
/* TSI busy sampling */
STATE_STOP
,
/* sample available */
STATE_WAIT
,
/* Wait to start next sample */
};
enum
{
EVENT_PEN_DOWN
,
EVENT_PEN_UP
,
EVENT_TSI_READY
,
EVENT_TIMEDOUT
,
};
struct
da9034_touch
{
struct
device
*
da9034_dev
;
struct
input_dev
*
input_dev
;
struct
delayed_work
tsi_work
;
struct
notifier_block
notifier
;
int
state
;
int
interval_ms
;
int
x_inverted
;
int
y_inverted
;
int
last_x
;
int
last_y
;
};
static
inline
int
is_pen_down
(
struct
da9034_touch
*
touch
)
{
return
da903x_query_status
(
touch
->
da9034_dev
,
DA9034_STATUS_PEN_DOWN
);
}
static
inline
int
detect_pen_down
(
struct
da9034_touch
*
touch
,
int
on
)
{
if
(
on
)
return
da903x_set_bits
(
touch
->
da9034_dev
,
DA9034_AUTO_CTRL2
,
DA9034_PEN_DETECT
);
else
return
da903x_clr_bits
(
touch
->
da9034_dev
,
DA9034_AUTO_CTRL2
,
DA9034_PEN_DETECT
);
}
static
int
read_tsi
(
struct
da9034_touch
*
touch
)
{
uint8_t
_x
,
_y
,
_v
;
int
ret
;
ret
=
da903x_read
(
touch
->
da9034_dev
,
DA9034_TSI_X_MSB
,
&
_x
);
if
(
ret
)
return
ret
;
ret
=
da903x_read
(
touch
->
da9034_dev
,
DA9034_TSI_Y_MSB
,
&
_y
);
if
(
ret
)
return
ret
;
ret
=
da903x_read
(
touch
->
da9034_dev
,
DA9034_TSI_XY_LSB
,
&
_v
);
if
(
ret
)
return
ret
;
touch
->
last_x
=
((
_x
<<
2
)
&
0x3fc
)
|
(
_v
&
0x3
);
touch
->
last_y
=
((
_y
<<
2
)
&
0x3fc
)
|
((
_v
&
0xc
)
>>
2
);
return
0
;
}
static
inline
int
start_tsi
(
struct
da9034_touch
*
touch
)
{
return
da903x_set_bits
(
touch
->
da9034_dev
,
DA9034_AUTO_CTRL2
,
DA9034_AUTO_TSI_EN
);
}
static
inline
int
stop_tsi
(
struct
da9034_touch
*
touch
)
{
return
da903x_clr_bits
(
touch
->
da9034_dev
,
DA9034_AUTO_CTRL2
,
DA9034_AUTO_TSI_EN
);
}
static
inline
void
report_pen_down
(
struct
da9034_touch
*
touch
)
{
int
x
=
touch
->
last_x
;
int
y
=
touch
->
last_y
;
x
&=
0xfff
;
if
(
touch
->
x_inverted
)
x
=
1024
-
x
;
y
&=
0xfff
;
if
(
touch
->
y_inverted
)
y
=
1024
-
y
;
input_report_abs
(
touch
->
input_dev
,
ABS_X
,
x
);
input_report_abs
(
touch
->
input_dev
,
ABS_Y
,
y
);
input_report_key
(
touch
->
input_dev
,
BTN_TOUCH
,
1
);
input_sync
(
touch
->
input_dev
);
}
static
inline
void
report_pen_up
(
struct
da9034_touch
*
touch
)
{
input_report_key
(
touch
->
input_dev
,
BTN_TOUCH
,
0
);
input_sync
(
touch
->
input_dev
);
}
static
void
da9034_event_handler
(
struct
da9034_touch
*
touch
,
int
event
)
{
int
err
;
switch
(
touch
->
state
)
{
case
STATE_IDLE
:
if
(
event
!=
EVENT_PEN_DOWN
)
break
;
/* Enable auto measurement of the TSI, this will
* automatically disable pen down detection
*/
err
=
start_tsi
(
touch
);
if
(
err
)
goto
err_reset
;
touch
->
state
=
STATE_BUSY
;
break
;
case
STATE_BUSY
:
if
(
event
!=
EVENT_TSI_READY
)
break
;
err
=
read_tsi
(
touch
);
if
(
err
)
goto
err_reset
;
/* Disable auto measurement of the TSI, so that
* pen down status will be available
*/
err
=
stop_tsi
(
touch
);
if
(
err
)
goto
err_reset
;
touch
->
state
=
STATE_STOP
;
break
;
case
STATE_STOP
:
if
(
event
==
EVENT_PEN_DOWN
)
{
report_pen_down
(
touch
);
schedule_delayed_work
(
&
touch
->
tsi_work
,
msecs_to_jiffies
(
touch
->
interval_ms
));
touch
->
state
=
STATE_WAIT
;
}
if
(
event
==
EVENT_PEN_UP
)
{
report_pen_up
(
touch
);
touch
->
state
=
STATE_IDLE
;
}
input_sync
(
touch
->
input_dev
);
break
;
case
STATE_WAIT
:
if
(
event
!=
EVENT_TIMEDOUT
)
break
;
if
(
is_pen_down
(
touch
))
{
start_tsi
(
touch
);
touch
->
state
=
STATE_BUSY
;
}
else
touch
->
state
=
STATE_IDLE
;
break
;
}
return
;
err_reset:
touch
->
state
=
STATE_IDLE
;
stop_tsi
(
touch
);
detect_pen_down
(
touch
,
1
);
}
static
void
da9034_tsi_work
(
struct
work_struct
*
work
)
{
struct
da9034_touch
*
touch
=
container_of
(
work
,
struct
da9034_touch
,
tsi_work
.
work
);
da9034_event_handler
(
touch
,
EVENT_TIMEDOUT
);
}
static
int
da9034_touch_notifier
(
struct
notifier_block
*
nb
,
unsigned
long
event
,
void
*
data
)
{
struct
da9034_touch
*
touch
=
container_of
(
nb
,
struct
da9034_touch
,
notifier
);
if
(
event
&
DA9034_EVENT_PEN_DOWN
)
{
if
(
is_pen_down
(
touch
))
da9034_event_handler
(
touch
,
EVENT_PEN_DOWN
);
else
da9034_event_handler
(
touch
,
EVENT_PEN_UP
);
}
if
(
event
&
DA9034_EVENT_TSI_READY
)
da9034_event_handler
(
touch
,
EVENT_TSI_READY
);
return
0
;
}
static
int
da9034_touch_open
(
struct
input_dev
*
dev
)
{
struct
da9034_touch
*
touch
=
input_get_drvdata
(
dev
);
int
ret
;
ret
=
da903x_register_notifier
(
touch
->
da9034_dev
,
&
touch
->
notifier
,
DA9034_EVENT_PEN_DOWN
|
DA9034_EVENT_TSI_READY
);
if
(
ret
)
return
-
EBUSY
;
/* Enable ADC LDO */
ret
=
da903x_set_bits
(
touch
->
da9034_dev
,
DA9034_MANUAL_CTRL
,
DA9034_LDO_ADC_EN
);
if
(
ret
)
return
ret
;
/* TSI_DELAY: 3 slots, TSI_SKIP: 3 slots */
ret
=
da903x_write
(
touch
->
da9034_dev
,
DA9034_TSI_CTRL1
,
0x1b
);
if
(
ret
)
return
ret
;
ret
=
da903x_write
(
touch
->
da9034_dev
,
DA9034_TSI_CTRL2
,
0x00
);
if
(
ret
)
return
ret
;
touch
->
state
=
STATE_IDLE
;
detect_pen_down
(
touch
,
1
);
return
0
;
}
static
void
da9034_touch_close
(
struct
input_dev
*
dev
)
{
struct
da9034_touch
*
touch
=
input_get_drvdata
(
dev
);
da903x_unregister_notifier
(
touch
->
da9034_dev
,
&
touch
->
notifier
,
DA9034_EVENT_PEN_DOWN
|
DA9034_EVENT_TSI_READY
);
cancel_delayed_work_sync
(
&
touch
->
tsi_work
);
touch
->
state
=
STATE_IDLE
;
stop_tsi
(
touch
);
detect_pen_down
(
touch
,
0
);
/* Disable ADC LDO */
da903x_clr_bits
(
touch
->
da9034_dev
,
DA9034_MANUAL_CTRL
,
DA9034_LDO_ADC_EN
);
}
static
int
__devinit
da9034_touch_probe
(
struct
platform_device
*
pdev
)
{
struct
da9034_touch_pdata
*
pdata
=
pdev
->
dev
.
platform_data
;
struct
da9034_touch
*
touch
;
struct
input_dev
*
input_dev
;
int
ret
;
touch
=
kzalloc
(
sizeof
(
struct
da9034_touch
),
GFP_KERNEL
);
if
(
touch
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"failed to allocate driver data
\n
"
);
return
-
ENOMEM
;
}
touch
->
da9034_dev
=
pdev
->
dev
.
parent
;
if
(
pdata
)
{
touch
->
interval_ms
=
pdata
->
interval_ms
;
touch
->
x_inverted
=
pdata
->
x_inverted
;
touch
->
y_inverted
=
pdata
->
y_inverted
;
}
else
/* fallback into default */
touch
->
interval_ms
=
10
;
INIT_DELAYED_WORK
(
&
touch
->
tsi_work
,
da9034_tsi_work
);
touch
->
notifier
.
notifier_call
=
da9034_touch_notifier
;
input_dev
=
input_allocate_device
();
if
(
!
input_dev
)
{
dev_err
(
&
pdev
->
dev
,
"failed to allocate input device
\n
"
);
ret
=
-
ENOMEM
;
goto
err_free_touch
;
}
input_dev
->
name
=
pdev
->
name
;
input_dev
->
open
=
da9034_touch_open
;
input_dev
->
close
=
da9034_touch_close
;
input_dev
->
dev
.
parent
=
&
pdev
->
dev
;
__set_bit
(
EV_ABS
,
input_dev
->
evbit
);
__set_bit
(
ABS_X
,
input_dev
->
absbit
);
__set_bit
(
ABS_Y
,
input_dev
->
absbit
);
input_set_abs_params
(
input_dev
,
ABS_X
,
0
,
1023
,
0
,
0
);
input_set_abs_params
(
input_dev
,
ABS_Y
,
0
,
1023
,
0
,
0
);
__set_bit
(
EV_KEY
,
input_dev
->
evbit
);
__set_bit
(
BTN_TOUCH
,
input_dev
->
keybit
);
touch
->
input_dev
=
input_dev
;
input_set_drvdata
(
input_dev
,
touch
);
ret
=
input_register_device
(
input_dev
);
if
(
ret
)
goto
err_free_input
;
platform_set_drvdata
(
pdev
,
touch
);
return
0
;
err_free_input:
input_free_device
(
input_dev
);
err_free_touch:
kfree
(
touch
);
return
ret
;
}
static
int
__devexit
da9034_touch_remove
(
struct
platform_device
*
pdev
)
{
struct
da9034_touch
*
touch
=
platform_get_drvdata
(
pdev
);
input_unregister_device
(
touch
->
input_dev
);
kfree
(
touch
);
return
0
;
}
static
struct
platform_driver
da9034_touch_driver
=
{
.
driver
=
{
.
name
=
"da9034-touch"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
da9034_touch_probe
,
.
remove
=
__devexit_p
(
da9034_touch_remove
),
};
static
int
__init
da9034_touch_init
(
void
)
{
return
platform_driver_register
(
&
da9034_touch_driver
);
}
module_init
(
da9034_touch_init
);
static
void
__exit
da9034_touch_exit
(
void
)
{
platform_driver_unregister
(
&
da9034_touch_driver
);
}
module_exit
(
da9034_touch_exit
);
MODULE_DESCRIPTION
(
"Touchscreen driver for Dialog Semiconductor DA9034"
);
MODULE_AUTHOR
(
"Eric Miao <eric.miao@marvell.com>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_ALIAS
(
"platform:da9034-touch"
);
drivers/input/touchscreen/tsc2007.c
0 → 100644
浏览文件 @
1dd32946
/*
* drivers/input/touchscreen/tsc2007.c
*
* Copyright (c) 2008 MtekVision Co., Ltd.
* Kwangwoo Lee <kwlee@mtekvision.com>
*
* Using code from:
* - ads7846.c
* Copyright (c) 2005 David Brownell
* Copyright (c) 2006 Nokia Corporation
* - corgi_ts.c
* Copyright (C) 2004-2005 Richard Purdie
* - omap_ts.[hc], ads7846.h, ts_osk.c
* Copyright (C) 2002 MontaVista Software
* Copyright (C) 2004 Texas Instruments
* Copyright (C) 2005 Dirk Behme
*
* 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.
*/
#include <linux/module.h>
#include <linux/hrtimer.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/i2c/tsc2007.h>
#define TS_POLL_DELAY (10 * 1000)
/* ns delay before the first sample */
#define TS_POLL_PERIOD (5 * 1000)
/* ns delay between samples */
#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
#define TSC2007_MEASURE_AUX (0x2 << 4)
#define TSC2007_MEASURE_TEMP1 (0x4 << 4)
#define TSC2007_ACTIVATE_XN (0x8 << 4)
#define TSC2007_ACTIVATE_YN (0x9 << 4)
#define TSC2007_ACTIVATE_YP_XN (0xa << 4)
#define TSC2007_SETUP (0xb << 4)
#define TSC2007_MEASURE_X (0xc << 4)
#define TSC2007_MEASURE_Y (0xd << 4)
#define TSC2007_MEASURE_Z1 (0xe << 4)
#define TSC2007_MEASURE_Z2 (0xf << 4)
#define TSC2007_POWER_OFF_IRQ_EN (0x0 << 2)
#define TSC2007_ADC_ON_IRQ_DIS0 (0x1 << 2)
#define TSC2007_ADC_OFF_IRQ_EN (0x2 << 2)
#define TSC2007_ADC_ON_IRQ_DIS1 (0x3 << 2)
#define TSC2007_12BIT (0x0 << 1)
#define TSC2007_8BIT (0x1 << 1)
#define MAX_12BIT ((1 << 12) - 1)
#define ADC_ON_12BIT (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0)
#define READ_Y (ADC_ON_12BIT | TSC2007_MEASURE_Y)
#define READ_Z1 (ADC_ON_12BIT | TSC2007_MEASURE_Z1)
#define READ_Z2 (ADC_ON_12BIT | TSC2007_MEASURE_Z2)
#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X)
#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN)
struct
ts_event
{
u16
x
;
u16
y
;
u16
z1
,
z2
;
};
struct
tsc2007
{
struct
input_dev
*
input
;
char
phys
[
32
];
struct
hrtimer
timer
;
struct
ts_event
tc
;
struct
i2c_client
*
client
;
spinlock_t
lock
;
u16
model
;
u16
x_plate_ohms
;
unsigned
pendown
;
int
irq
;
int
(
*
get_pendown_state
)(
void
);
void
(
*
clear_penirq
)(
void
);
};
static
inline
int
tsc2007_xfer
(
struct
tsc2007
*
tsc
,
u8
cmd
)
{
s32
data
;
u16
val
;
data
=
i2c_smbus_read_word_data
(
tsc
->
client
,
cmd
);
if
(
data
<
0
)
{
dev_err
(
&
tsc
->
client
->
dev
,
"i2c io error: %d
\n
"
,
data
);
return
data
;
}
/* The protocol and raw data format from i2c interface:
* S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
* Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
*/
val
=
swab16
(
data
)
>>
4
;
dev_dbg
(
&
tsc
->
client
->
dev
,
"data: 0x%x, val: 0x%x
\n
"
,
data
,
val
);
return
val
;
}
static
void
tsc2007_send_event
(
void
*
tsc
)
{
struct
tsc2007
*
ts
=
tsc
;
u32
rt
;
u16
x
,
y
,
z1
,
z2
;
x
=
ts
->
tc
.
x
;
y
=
ts
->
tc
.
y
;
z1
=
ts
->
tc
.
z1
;
z2
=
ts
->
tc
.
z2
;
/* range filtering */
if
(
x
==
MAX_12BIT
)
x
=
0
;
if
(
likely
(
x
&&
z1
))
{
/* compute touch pressure resistance using equation #1 */
rt
=
z2
;
rt
-=
z1
;
rt
*=
x
;
rt
*=
ts
->
x_plate_ohms
;
rt
/=
z1
;
rt
=
(
rt
+
2047
)
>>
12
;
}
else
rt
=
0
;
/* Sample found inconsistent by debouncing or pressure is beyond
* the maximum. Don't report it to user space, repeat at least
* once more the measurement
*/
if
(
rt
>
MAX_12BIT
)
{
dev_dbg
(
&
ts
->
client
->
dev
,
"ignored pressure %d
\n
"
,
rt
);
hrtimer_start
(
&
ts
->
timer
,
ktime_set
(
0
,
TS_POLL_PERIOD
),
HRTIMER_MODE_REL
);
return
;
}
/* NOTE: We can't rely on the pressure to determine the pen down
* state, even this controller has a pressure sensor. The pressure
* value can fluctuate for quite a while after lifting the pen and
* in some cases may not even settle at the expected value.
*
* The only safe way to check for the pen up condition is in the
* timer by reading the pen signal state (it's a GPIO _and_ IRQ).
*/
if
(
rt
)
{
struct
input_dev
*
input
=
ts
->
input
;
if
(
!
ts
->
pendown
)
{
dev_dbg
(
&
ts
->
client
->
dev
,
"DOWN
\n
"
);
input_report_key
(
input
,
BTN_TOUCH
,
1
);
ts
->
pendown
=
1
;
}
input_report_abs
(
input
,
ABS_X
,
x
);
input_report_abs
(
input
,
ABS_Y
,
y
);
input_report_abs
(
input
,
ABS_PRESSURE
,
rt
);
input_sync
(
input
);
dev_dbg
(
&
ts
->
client
->
dev
,
"point(%4d,%4d), pressure (%4u)
\n
"
,
x
,
y
,
rt
);
}
hrtimer_start
(
&
ts
->
timer
,
ktime_set
(
0
,
TS_POLL_PERIOD
),
HRTIMER_MODE_REL
);
}
static
int
tsc2007_read_values
(
struct
tsc2007
*
tsc
)
{
/* y- still on; turn on only y+ (and ADC) */
tsc
->
tc
.
y
=
tsc2007_xfer
(
tsc
,
READ_Y
);
/* turn y- off, x+ on, then leave in lowpower */
tsc
->
tc
.
x
=
tsc2007_xfer
(
tsc
,
READ_X
);
/* turn y+ off, x- on; we'll use formula #1 */
tsc
->
tc
.
z1
=
tsc2007_xfer
(
tsc
,
READ_Z1
);
tsc
->
tc
.
z2
=
tsc2007_xfer
(
tsc
,
READ_Z2
);
/* power down */
tsc2007_xfer
(
tsc
,
PWRDOWN
);
return
0
;
}
static
enum
hrtimer_restart
tsc2007_timer
(
struct
hrtimer
*
handle
)
{
struct
tsc2007
*
ts
=
container_of
(
handle
,
struct
tsc2007
,
timer
);
spin_lock_irq
(
&
ts
->
lock
);
if
(
unlikely
(
!
ts
->
get_pendown_state
()
&&
ts
->
pendown
))
{
struct
input_dev
*
input
=
ts
->
input
;
dev_dbg
(
&
ts
->
client
->
dev
,
"UP
\n
"
);
input_report_key
(
input
,
BTN_TOUCH
,
0
);
input_report_abs
(
input
,
ABS_PRESSURE
,
0
);
input_sync
(
input
);
ts
->
pendown
=
0
;
enable_irq
(
ts
->
irq
);
}
else
{
/* pen is still down, continue with the measurement */
dev_dbg
(
&
ts
->
client
->
dev
,
"pen is still down
\n
"
);
tsc2007_read_values
(
ts
);
tsc2007_send_event
(
ts
);
}
spin_unlock_irq
(
&
ts
->
lock
);
return
HRTIMER_NORESTART
;
}
static
irqreturn_t
tsc2007_irq
(
int
irq
,
void
*
handle
)
{
struct
tsc2007
*
ts
=
handle
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
ts
->
lock
,
flags
);
if
(
likely
(
ts
->
get_pendown_state
()))
{
disable_irq
(
ts
->
irq
);
hrtimer_start
(
&
ts
->
timer
,
ktime_set
(
0
,
TS_POLL_DELAY
),
HRTIMER_MODE_REL
);
}
if
(
ts
->
clear_penirq
)
ts
->
clear_penirq
();
spin_unlock_irqrestore
(
&
ts
->
lock
,
flags
);
return
IRQ_HANDLED
;
}
static
int
tsc2007_probe
(
struct
i2c_client
*
client
,
const
struct
i2c_device_id
*
id
)
{
struct
tsc2007
*
ts
;
struct
tsc2007_platform_data
*
pdata
=
pdata
=
client
->
dev
.
platform_data
;
struct
input_dev
*
input_dev
;
int
err
;
if
(
!
pdata
)
{
dev_err
(
&
client
->
dev
,
"platform data is required!
\n
"
);
return
-
EINVAL
;
}
if
(
!
i2c_check_functionality
(
client
->
adapter
,
I2C_FUNC_SMBUS_READ_WORD_DATA
))
return
-
EIO
;
ts
=
kzalloc
(
sizeof
(
struct
tsc2007
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
ts
||
!
input_dev
)
{
err
=
-
ENOMEM
;
goto
err_free_mem
;
}
ts
->
client
=
client
;
i2c_set_clientdata
(
client
,
ts
);
ts
->
input
=
input_dev
;
hrtimer_init
(
&
ts
->
timer
,
CLOCK_MONOTONIC
,
HRTIMER_MODE_REL
);
ts
->
timer
.
function
=
tsc2007_timer
;
spin_lock_init
(
&
ts
->
lock
);
ts
->
model
=
pdata
->
model
;
ts
->
x_plate_ohms
=
pdata
->
x_plate_ohms
;
ts
->
get_pendown_state
=
pdata
->
get_pendown_state
;
ts
->
clear_penirq
=
pdata
->
clear_penirq
;
pdata
->
init_platform_hw
();
snprintf
(
ts
->
phys
,
sizeof
(
ts
->
phys
),
"%s/input0"
,
client
->
dev
.
bus_id
);
input_dev
->
name
=
"TSC2007 Touchscreen"
;
input_dev
->
phys
=
ts
->
phys
;
input_dev
->
id
.
bustype
=
BUS_I2C
;
input_dev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
)
|
BIT_MASK
(
EV_ABS
);
input_dev
->
keybit
[
BIT_WORD
(
BTN_TOUCH
)]
=
BIT_MASK
(
BTN_TOUCH
);
input_set_abs_params
(
input_dev
,
ABS_X
,
0
,
MAX_12BIT
,
0
,
0
);
input_set_abs_params
(
input_dev
,
ABS_Y
,
0
,
MAX_12BIT
,
0
,
0
);
input_set_abs_params
(
input_dev
,
ABS_PRESSURE
,
0
,
MAX_12BIT
,
0
,
0
);
tsc2007_read_values
(
ts
);
ts
->
irq
=
client
->
irq
;
err
=
request_irq
(
ts
->
irq
,
tsc2007_irq
,
0
,
client
->
dev
.
driver
->
name
,
ts
);
if
(
err
<
0
)
{
dev_err
(
&
client
->
dev
,
"irq %d busy?
\n
"
,
ts
->
irq
);
goto
err_free_mem
;
}
err
=
input_register_device
(
input_dev
);
if
(
err
)
goto
err_free_irq
;
dev_info
(
&
client
->
dev
,
"registered with irq (%d)
\n
"
,
ts
->
irq
);
return
0
;
err_free_irq:
free_irq
(
ts
->
irq
,
ts
);
hrtimer_cancel
(
&
ts
->
timer
);
err_free_mem:
input_free_device
(
input_dev
);
kfree
(
ts
);
return
err
;
}
static
int
tsc2007_remove
(
struct
i2c_client
*
client
)
{
struct
tsc2007
*
ts
=
i2c_get_clientdata
(
client
);
struct
tsc2007_platform_data
*
pdata
;
pdata
=
client
->
dev
.
platform_data
;
pdata
->
exit_platform_hw
();
free_irq
(
ts
->
irq
,
ts
);
hrtimer_cancel
(
&
ts
->
timer
);
input_unregister_device
(
ts
->
input
);
kfree
(
ts
);
return
0
;
}
static
struct
i2c_device_id
tsc2007_idtable
[]
=
{
{
"tsc2007"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
tsc2007_idtable
);
static
struct
i2c_driver
tsc2007_driver
=
{
.
driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"tsc2007"
},
.
id_table
=
tsc2007_idtable
,
.
probe
=
tsc2007_probe
,
.
remove
=
tsc2007_remove
,
};
static
int
__init
tsc2007_init
(
void
)
{
return
i2c_add_driver
(
&
tsc2007_driver
);
}
static
void
__exit
tsc2007_exit
(
void
)
{
i2c_del_driver
(
&
tsc2007_driver
);
}
module_init
(
tsc2007_init
);
module_exit
(
tsc2007_exit
);
MODULE_AUTHOR
(
"Kwangwoo Lee <kwlee@mtekvision.com>"
);
MODULE_DESCRIPTION
(
"TSC2007 TouchScreen Driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/input/touchscreen/usbtouchscreen.c
浏览文件 @
1dd32946
...
...
@@ -424,7 +424,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
0
,
0
,
buf
,
2
,
USB_CTRL_SET_TIMEOUT
);
if
(
ret
<
0
)
goto
err_out
;
if
(
buf
[
0
]
!=
0x06
||
buf
[
1
]
!=
0x00
)
{
if
(
buf
[
0
]
!=
0x06
)
{
ret
=
-
ENODEV
;
goto
err_out
;
}
...
...
@@ -437,8 +437,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
TSC10_RATE_150
,
0
,
buf
,
2
,
USB_CTRL_SET_TIMEOUT
);
if
(
ret
<
0
)
goto
err_out
;
if
((
buf
[
0
]
!=
0x06
||
buf
[
1
]
!=
0x00
)
&&
(
buf
[
0
]
!=
0x15
||
buf
[
1
]
!=
0x01
))
{
if
((
buf
[
0
]
!=
0x06
)
&&
(
buf
[
0
]
!=
0x15
||
buf
[
1
]
!=
0x01
))
{
ret
=
-
ENODEV
;
goto
err_out
;
}
...
...
drivers/input/touchscreen/wacom_w8001.c
0 → 100644
浏览文件 @
1dd32946
/*
* Wacom W8001 penabled serial touchscreen driver
*
* Copyright (c) 2008 Jaya Kumar
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
* Layout based on Elo serial touchscreen driver by Vojtech Pavlik
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/ctype.h>
#define DRIVER_DESC "Wacom W8001 serial touchscreen driver"
MODULE_AUTHOR
(
"Jaya Kumar <jayakumar.lkml@gmail.com>"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
/*
* Definitions & global arrays.
*/
#define W8001_MAX_LENGTH 11
#define W8001_PACKET_LEN 11
#define W8001_LEAD_MASK 0x80
#define W8001_LEAD_BYTE 0x80
#define W8001_TAB_MASK 0x40
#define W8001_TAB_BYTE 0x40
#define W8001_QUERY_PACKET 0x20
struct
w8001_coord
{
u8
rdy
;
u8
tsw
;
u8
f1
;
u8
f2
;
u16
x
;
u16
y
;
u16
pen_pressure
;
u8
tilt_x
;
u8
tilt_y
;
};
/*
* Per-touchscreen data.
*/
struct
w8001
{
struct
input_dev
*
dev
;
struct
serio
*
serio
;
struct
mutex
cmd_mutex
;
struct
completion
cmd_done
;
int
id
;
int
idx
;
unsigned
char
expected_packet
;
unsigned
char
data
[
W8001_MAX_LENGTH
];
unsigned
char
response
[
W8001_PACKET_LEN
];
char
phys
[
32
];
};
static
int
parse_data
(
u8
*
data
,
struct
w8001_coord
*
coord
)
{
coord
->
rdy
=
data
[
0
]
&
0x20
;
coord
->
tsw
=
data
[
0
]
&
0x01
;
coord
->
f1
=
data
[
0
]
&
0x02
;
coord
->
f2
=
data
[
0
]
&
0x04
;
coord
->
x
=
(
data
[
1
]
&
0x7F
)
<<
9
;
coord
->
x
|=
(
data
[
2
]
&
0x7F
)
<<
2
;
coord
->
x
|=
(
data
[
6
]
&
0x60
)
>>
5
;
coord
->
y
=
(
data
[
3
]
&
0x7F
)
<<
9
;
coord
->
y
|=
(
data
[
4
]
&
0x7F
)
<<
2
;
coord
->
y
|=
(
data
[
6
]
&
0x18
)
>>
3
;
coord
->
pen_pressure
=
data
[
5
]
&
0x7F
;
coord
->
pen_pressure
|=
(
data
[
6
]
&
0x07
)
<<
7
;
coord
->
tilt_x
=
data
[
7
]
&
0x7F
;
coord
->
tilt_y
=
data
[
8
]
&
0x7F
;
return
0
;
}
static
void
w8001_process_data
(
struct
w8001
*
w8001
,
unsigned
char
data
)
{
struct
input_dev
*
dev
=
w8001
->
dev
;
u8
tmp
;
struct
w8001_coord
coord
;
w8001
->
data
[
w8001
->
idx
]
=
data
;
switch
(
w8001
->
idx
++
)
{
case
0
:
if
((
data
&
W8001_LEAD_MASK
)
!=
W8001_LEAD_BYTE
)
{
pr_debug
(
"w8001: unsynchronized data: 0x%02x
\n
"
,
data
);
w8001
->
idx
=
0
;
}
break
;
case
8
:
tmp
=
w8001
->
data
[
0
]
&
W8001_TAB_MASK
;
if
(
unlikely
(
tmp
==
W8001_TAB_BYTE
))
break
;
w8001
->
idx
=
0
;
memset
(
&
coord
,
0
,
sizeof
(
coord
));
parse_data
(
w8001
->
data
,
&
coord
);
input_report_abs
(
dev
,
ABS_X
,
coord
.
x
);
input_report_abs
(
dev
,
ABS_Y
,
coord
.
y
);
input_report_abs
(
dev
,
ABS_PRESSURE
,
coord
.
pen_pressure
);
input_report_key
(
dev
,
BTN_TOUCH
,
coord
.
tsw
);
input_sync
(
dev
);
break
;
case
10
:
w8001
->
idx
=
0
;
memcpy
(
w8001
->
response
,
&
w8001
->
data
,
W8001_PACKET_LEN
);
w8001
->
expected_packet
=
W8001_QUERY_PACKET
;
complete
(
&
w8001
->
cmd_done
);
break
;
}
}
static
irqreturn_t
w8001_interrupt
(
struct
serio
*
serio
,
unsigned
char
data
,
unsigned
int
flags
)
{
struct
w8001
*
w8001
=
serio_get_drvdata
(
serio
);
w8001_process_data
(
w8001
,
data
);
return
IRQ_HANDLED
;
}
static
int
w8001_async_command
(
struct
w8001
*
w8001
,
unsigned
char
*
packet
,
int
len
)
{
int
rc
=
-
1
;
int
i
;
mutex_lock
(
&
w8001
->
cmd_mutex
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
serio_write
(
w8001
->
serio
,
packet
[
i
]))
goto
out
;
}
rc
=
0
;
out:
mutex_unlock
(
&
w8001
->
cmd_mutex
);
return
rc
;
}
static
int
w8001_command
(
struct
w8001
*
w8001
,
unsigned
char
*
packet
,
int
len
)
{
int
rc
=
-
1
;
int
i
;
mutex_lock
(
&
w8001
->
cmd_mutex
);
serio_pause_rx
(
w8001
->
serio
);
init_completion
(
&
w8001
->
cmd_done
);
serio_continue_rx
(
w8001
->
serio
);
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
serio_write
(
w8001
->
serio
,
packet
[
i
]))
goto
out
;
}
wait_for_completion_timeout
(
&
w8001
->
cmd_done
,
HZ
);
if
(
w8001
->
expected_packet
==
W8001_QUERY_PACKET
)
{
/* We are back in reporting mode, the query was ACKed */
memcpy
(
packet
,
w8001
->
response
,
W8001_PACKET_LEN
);
rc
=
0
;
}
out:
mutex_unlock
(
&
w8001
->
cmd_mutex
);
return
rc
;
}
static
int
w8001_setup
(
struct
w8001
*
w8001
)
{
struct
w8001_coord
coord
;
struct
input_dev
*
dev
=
w8001
->
dev
;
unsigned
char
start
[
1
]
=
{
'1'
};
unsigned
char
query
[
11
]
=
{
'*'
};
if
(
w8001_command
(
w8001
,
query
,
1
))
return
-
1
;
memset
(
&
coord
,
0
,
sizeof
(
coord
));
parse_data
(
query
,
&
coord
);
input_set_abs_params
(
dev
,
ABS_X
,
0
,
coord
.
x
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_Y
,
0
,
coord
.
y
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_PRESSURE
,
0
,
coord
.
pen_pressure
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_TILT_X
,
0
,
coord
.
tilt_x
,
0
,
0
);
input_set_abs_params
(
dev
,
ABS_TILT_Y
,
0
,
coord
.
tilt_y
,
0
,
0
);
if
(
w8001_async_command
(
w8001
,
start
,
1
))
return
-
1
;
return
0
;
}
/*
* w8001_disconnect() is the opposite of w8001_connect()
*/
static
void
w8001_disconnect
(
struct
serio
*
serio
)
{
struct
w8001
*
w8001
=
serio_get_drvdata
(
serio
);
input_get_device
(
w8001
->
dev
);
input_unregister_device
(
w8001
->
dev
);
serio_close
(
serio
);
serio_set_drvdata
(
serio
,
NULL
);
input_put_device
(
w8001
->
dev
);
kfree
(
w8001
);
}
/*
* w8001_connect() is the routine that is called when someone adds a
* new serio device that supports the w8001 protocol and registers it as
* an input device.
*/
static
int
w8001_connect
(
struct
serio
*
serio
,
struct
serio_driver
*
drv
)
{
struct
w8001
*
w8001
;
struct
input_dev
*
input_dev
;
int
err
;
w8001
=
kzalloc
(
sizeof
(
struct
w8001
),
GFP_KERNEL
);
input_dev
=
input_allocate_device
();
if
(
!
w8001
||
!
input_dev
)
{
err
=
-
ENOMEM
;
goto
fail1
;
}
w8001
->
serio
=
serio
;
w8001
->
id
=
serio
->
id
.
id
;
w8001
->
dev
=
input_dev
;
mutex_init
(
&
w8001
->
cmd_mutex
);
init_completion
(
&
w8001
->
cmd_done
);
snprintf
(
w8001
->
phys
,
sizeof
(
w8001
->
phys
),
"%s/input0"
,
serio
->
phys
);
input_dev
->
name
=
"Wacom W8001 Penabled Serial TouchScreen"
;
input_dev
->
phys
=
w8001
->
phys
;
input_dev
->
id
.
bustype
=
BUS_RS232
;
input_dev
->
id
.
vendor
=
SERIO_W8001
;
input_dev
->
id
.
product
=
w8001
->
id
;
input_dev
->
id
.
version
=
0x0100
;
input_dev
->
dev
.
parent
=
&
serio
->
dev
;
input_dev
->
evbit
[
0
]
=
BIT_MASK
(
EV_KEY
)
|
BIT_MASK
(
EV_ABS
);
input_dev
->
keybit
[
BIT_WORD
(
BTN_TOUCH
)]
=
BIT_MASK
(
BTN_TOUCH
);
serio_set_drvdata
(
serio
,
w8001
);
err
=
serio_open
(
serio
,
drv
);
if
(
err
)
goto
fail2
;
if
(
w8001_setup
(
w8001
))
goto
fail3
;
err
=
input_register_device
(
w8001
->
dev
);
if
(
err
)
goto
fail3
;
return
0
;
fail3:
serio_close
(
serio
);
fail2:
serio_set_drvdata
(
serio
,
NULL
);
fail1:
input_free_device
(
input_dev
);
kfree
(
w8001
);
return
err
;
}
static
struct
serio_device_id
w8001_serio_ids
[]
=
{
{
.
type
=
SERIO_RS232
,
.
proto
=
SERIO_W8001
,
.
id
=
SERIO_ANY
,
.
extra
=
SERIO_ANY
,
},
{
0
}
};
MODULE_DEVICE_TABLE
(
serio
,
w8001_serio_ids
);
static
struct
serio_driver
w8001_drv
=
{
.
driver
=
{
.
name
=
"w8001"
,
},
.
description
=
DRIVER_DESC
,
.
id_table
=
w8001_serio_ids
,
.
interrupt
=
w8001_interrupt
,
.
connect
=
w8001_connect
,
.
disconnect
=
w8001_disconnect
,
};
static
int
__init
w8001_init
(
void
)
{
return
serio_register_driver
(
&
w8001_drv
);
}
static
void
__exit
w8001_exit
(
void
)
{
serio_unregister_driver
(
&
w8001_drv
);
}
module_init
(
w8001_init
);
module_exit
(
w8001_exit
);
include/linux/gpio_keys.h
浏览文件 @
1dd32946
...
...
@@ -15,6 +15,7 @@ struct gpio_keys_button {
struct
gpio_keys_platform_data
{
struct
gpio_keys_button
*
buttons
;
int
nbuttons
;
unsigned
int
rep
:
1
;
/* enable input subsystem auto repeat */
};
#endif
include/linux/i2c/tsc2007.h
0 → 100644
浏览文件 @
1dd32946
#ifndef __LINUX_I2C_TSC2007_H
#define __LINUX_I2C_TSC2007_H
/* linux/i2c/tsc2007.h */
struct
tsc2007_platform_data
{
u16
model
;
/* 2007. */
u16
x_plate_ohms
;
int
(
*
get_pendown_state
)(
void
);
void
(
*
clear_penirq
)(
void
);
/* If needed, clear 2nd level
interrupt source */
int
(
*
init_platform_hw
)(
void
);
void
(
*
exit_platform_hw
)(
void
);
};
#endif
include/linux/libps2.h
浏览文件 @
1dd32946
...
...
@@ -18,11 +18,13 @@
#define PS2_RET_ID 0x00
#define PS2_RET_ACK 0xfa
#define PS2_RET_NAK 0xfe
#define PS2_RET_ERR 0xfc
#define PS2_FLAG_ACK 1
/* Waiting for ACK/NAK */
#define PS2_FLAG_CMD 2
/* Waiting for command to finish */
#define PS2_FLAG_CMD1 4
/* Waiting for the first byte of command response */
#define PS2_FLAG_WAITID 8
/* Command execiting is GET ID */
#define PS2_FLAG_NAK 16
/* Last transmission was NAKed */
struct
ps2dev
{
struct
serio
*
serio
;
...
...
include/linux/map_to_7segment.h
浏览文件 @
1dd32946
...
...
@@ -75,7 +75,7 @@ struct seg7_conversion_map {
unsigned
char
table
[
128
];
};
static
inline
int
map_to_seg7
(
struct
seg7_conversion_map
*
map
,
int
c
)
static
__inline__
int
map_to_seg7
(
struct
seg7_conversion_map
*
map
,
int
c
)
{
return
c
>=
0
&&
c
<
sizeof
(
map
->
table
)
?
map
->
table
[
c
]
:
-
EINVAL
;
}
...
...
include/linux/serio.h
浏览文件 @
1dd32946
...
...
@@ -213,5 +213,6 @@ static inline void serio_unpin_driver(struct serio *serio)
#define SERIO_ZHENHUA 0x36
#define SERIO_INEXIO 0x37
#define SERIO_TOUCHIT213 0x37
#define SERIO_W8001 0x39
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录