分类: LINUX
2010-06-18 23:33:56
touchscreen已经在驱动中校正了,通过驱动报上来的点的坐标都是正确的。但是android没有反应,这是因为battery的问题造成的。
移植用的开发板没有电池的驱动,因此 android无法获得正确的电池状态,默认为LCD off的状态,android在LCD off状态下,
输入的任何touch的点都当作(0,0)处理,因此需要修改相关的代码。
修改的方法:
文件frameworks/base/services/jni/com_android_service_BatteryService.cpp
函数android_server_BatteryService_update
在最后加入:
env->SetBooleanField(obj, gFieldIds.mAcOnline, true);
env->SetIntField(obj, gFieldIds.mBatteryStatus, gConstants.statusUnknown);
env->SetIntField(obj, gFieldIds.mBatteryHealth, gConstants.healthUnknown);
还需要在驱动中加入
按下时:input_report_key(input, BTN_TOUCH,1);
释放时:input_report_key(input, BTN_TOUCH,0);
还需要在驱动probe的时候加入以下4句:
set_bit(EV_KEY,input_dev->evbit);
set_bit(EV_ABS,input_dev->evbit);
set_bit(BTN_TOUCH,input_dev->keybit);
set_bit(EV_SYN,input_dev->evbit);
android2.0里面还是不能正常工作,这是因为android把单点的touchscreen当成多点的来处理来。
权宜的解决方法,过滤掉多点的设备类型:
文件
frameworks/base/services/java/com/android/server/KeyInputQueue.java
在mThread线程代码中修改,classes值如下:
final int classes = di.classes &(~(RawInputEvent.CLASS_TOUCHSCREEN_MT));
以下为转载:
按键触摸屏流程分析:
WindowManagerService类的构造函数
WindowManagerService()
mQueue = new KeyQ();
因为 WindowManagerService.java (frameworks\base\services\java\com\android\server)中有:
private class KeyQ extends KeyInputQueue
KeyQ 是抽象类 KeyInputQueue 的实现,所以 new KeyQ类的时候实际上在 KeyInputQueue 类中创建了
一个线程 InputDeviceReader 专门用来冲设备读取按键事件,代码:
Thread mThread = new Thread("InputDeviceReader") {
public void run()
{
在循环中调用:readEvent(ev);
...
send = preprocessEvent(di, ev);
实际调用的是 KeyQ 类的 preprocessEvent 函数
...
int keycode = rotateKeyCodeLocked(ev.keycode);
int[] map = mKeyRotationMap;
for (int i=0; igetEvent(&deviceId, &type, &scancode, &keycode,&flags, &value, &when);
调用的是 EventHub.cpp (frameworks\base\libs\ui)中的:
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
int32_t* outValue, nsecs_t* outWhen)
在函数中调用了读设备操作:res = read(mFDs.fd, &iev, sizeof(iev));
在构造函数 WindowManagerService()调用 new KeyQ() 以后接着调用了:
mInputThread = new InputDispatcherThread();
...
mInputThread.start();
来启动一个线程 InputDispatcherThread
run()
process();
QueuedEvent ev = mQueue.getEvent(...)
因为WindowManagerService类中: final KeyQ mQueue;
所以实际上 InputDispatcherThread 线程实际上从 KeyQ 的事件队列中读取按键事件。
switch (ev.classType)
case RawInputEvent.CLASS_KEYBOARD:
...
dispatchKey((KeyEvent)ev.event, 0, 0);
mQueue.recycleEvent(ev);
break;
case RawInputEvent.CLASS_TOUCHSCREEN:
//Log.i(TAG, "Read next event " ev);
dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
break;
setRotationUnchecked
littonton 触摸屏幕驱动修改记录
修改
内核代码/drivers/input/touchscreen/wm9713_touch.c
static int codec_ts_evt_add(codec_ts_t *ts, u16 pressure, u16 x, u16 y)
{
...
input_report_abs(ts->idev, ABS_PRESSURE, pressure & 0xfff);
//针对android加上的
input_report_key(ts->idev, BTN_TOUCH,1);
return 0;
}
static void codec_ts_evt_release(codec_ts_t *ts)
{
input_report_abs(ts->idev, ABS_PRESSURE, 0);
//针对android加上的
input_report_abs(ts->idev,BTN_TOUCH,0);
wm9713_event_ack(EVENT_TYPE_PDN);
}
static int ts_init(struct platform_device *pdev)
{
...
//针对android加上的
__set_bit(EV_KEY, codec_ts_input->evbit);
__set_bit(BTN_TOUCH, codec_ts_input->keybit);
__set_bit(EV_SYN,codec_ts_input->evbit);
//针对android加上的 end
...
}
input_report_key() 报按键
input_report_abs() 报绝对坐标 函数分析:
Input.h (kernel\include\linux):
static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value)
input_event(dev, EV_ABS, code, value)
调用的是 Input.c (kernel\drivers\input)中的函数
void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
{
unsigned long flags;
检测是否为支持的事件
if (is_event_supported(type, dev->evbit, EV_MAX)) {
//锁中断
spin_lock_irqsave(&dev->event_lock, flags);
add_input_randomness(type, code, value);
input_handle_event(dev, type, code, value);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
is_event_supported() 函数检测当前事件类型,输入子系统支持的事件类型在文件
kernel/include/linux/input.h 中定义:
#define EV_SYN 0x00
#define EV_KEY 0x01
#define EV_REL 0x02
#define EV_ABS 0x03
#define EV_MSC 0x04
#define EV_SW 0x05
#define EV_LED 0x11
#define EV_SND 0x12
#define EV_REP 0x14
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x
static void input_handle_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
{
int disposition = INPUT_IGNORE_EVENT;
...
switch (type) {
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX)) {
value = input_defuzz_abs_event(value,
dev->abs[code], dev->absfuzz[code]);
if (dev->abs[code] != value) {
dev->abs[code] = value;
disposition = INPUT_PASS_TO_HANDLERS;
}
}
break;
...
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
dev->sync = 0;
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
if (disposition & INPUT_PASS_TO_HANDLERS)
input_pass_event(dev, type, code, value);
}
函数的code是
ABS_PRESSURE
BTN_TOUCH
static void input_pass_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
rcu_read_lock();
handle = rcu_dereference(dev->grab);
if (handle)
handle->handler->event(handle, type, code, value);
else
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle,
type, code, value);
rcu_read_unlock();
}
Apm-power.c (kernel\drivers\input): error = input_register_handle(handle);
Evbug.c (kernel\drivers\input): error = input_register_handle(handle);
Evdev.c (kernel\drivers\input): error = input_register_handle(&evdev->handle);
Input.c (kernel\drivers\input): * input_register_handle - register a new input handle
Input.c (kernel\drivers\input):int input_register_handle(struct input_handle *handle)
Input.c (kernel\drivers\input):EXPORT_SYMBOL(input_register_handle);
Input.h (kernel\include\linux):int input_register_handle(struct input_handle *);
Joydev.c (kernel\drivers\input): error = input_register_handle(&joydev->handle);
Keyboard.c (kernel\drivers\char): error = input_register_handle(handle);
Keychord.c (kernel\drivers\input\misc): ret = input_register_handle(handle);
Keyreset.c (kernel\drivers\input): ret = input_register_handle(handle);
Mousedev.c (kernel\drivers\input): error = input_register_handle(&mousedev->handle);
Rfkill-input.c (kernel\net\rfkill): error = input_register_handle(handle);
==================================================================
Littleton 开发板相关驱动:
Littleton.c (kernel\arch\arm\mach-pxa)
static void __init littleton_init(void)
{
/* initialize MFP configurations */
pxa3xx_mfp_config(ARRAY_AND_SIZE(littleton_mfp_cfg));
/*
* Note: we depend bootloader set the correct
* value to MSC register for SMC91x.
*/
platform_device_register(&smc91x_device);
littleton_init_lcd();
littleton_init_keypad();
littleton_init_nand();
}
Littleton.c (kernel\arch\arm\mach-pxa)
键盘初始化
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
static unsigned int littleton_matrix_key_map[] = {
/* KEY(row, col, key_code) */
KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7),
KEY(1, 2, KEY_8), KEY(2, 2, KEY_9),
KEY(0, 3, KEY_KPASTERISK), /* * */
KEY(2, 3, KEY_KPDOT), /* # */
KEY(5, 4, KEY_ENTER),
KEY(5, 0, KEY_UP),
KEY(5, 1, KEY_DOWN),
KEY(5, 2, KEY_LEFT),
KEY(5, 3, KEY_RIGHT),
KEY(3, 2, KEY_HOME),
KEY(4, 1, KEY_END),
KEY(3, 3, KEY_BACK),
KEY(4, 0, KEY_SEND),
KEY(4, 2, KEY_VOLUMEUP),
KEY(4, 3, KEY_VOLUMEDOWN),
KEY(3, 0, KEY_F22), /* soft1 */
KEY(3, 1, KEY_F23), /* soft2 */
};
static struct pxa27x_keypad_platform_data littleton_keypad_info = {
.matrix_key_rows = 6,
.matrix_key_cols = 5,
.matrix_key_map = littleton_matrix_key_map,
.matrix_key_map_size = ARRAY_SIZE(littleton_matrix_key_map),
.enable_rotary0 = 1,
.rotary0_up_key = KEY_UP,
.rotary0_down_key = KEY_DOWN,
.debounce_interval = 30,
};
static void __init littleton_init_keypad(void)
{
pxa_set_keypad_info(&littleton_keypad_info);
}
#else
static inline void littleton_init_keypad(void) {}
#endif
=========================================
大板子添加了lifeng触摸屏驱动
linux-
需要修改的配置文件
linux-2.6.25/drivers-r8/input/touchscreen/Kconfig
在 if INPUT_TOUCHSCREEN 后面加上下面内容:
config TOUCHSCREEN_LIFENG
tristate "LIFENG based touchscreen"
depends on INPUT_EVDEV
default y
help
Say Y here if you want to enable lifeng touch driver
修改 linux-2.6.25/drivers-r8/input/touchscreen/Makefine 文件,添加:
obj-$(CONFIG_TOUCHSCREEN_LIFENG) = bbk_lifeng_ts.o
让起编译 linux-2.6.25/drivers/input/touchscreen/bbk_lifeng_ts.c 文件
文件 linux-2.6.25/arch/arm/mach-pxa/littleton.c 中需要修改的地方:
static unsigned int littleton_matrix_key_map[] = {
/* KEY(row, col, key_code) */
//KEY(1, 3, KEY_0), KEY(0, 0, KEY_1), KEY(1, 0, KEY_2), KEY(2, 0, KEY_3),
//KEY(0, 1, KEY_4), KEY(1, 1, KEY_5), KEY(2, 1, KEY_6), KEY(0, 2, KEY_7),
//KEY(1, 2, KEY_8), KEY(2, 2, KEY_9),
KEY(0, 2, KEY_1), KEY(0, 3, KEY_2), KEY(0, 4, KEY_3), KEY(1, 2, KEY_4),
KEY(1, 3, KEY_5), KEY(1, 4, KEY_6), KEY(2, 2, KEY_7), KEY(2, 3, KEY_8),
KEY(2, 4, KEY_9), KEY(0, 1, KEY_0),
KEY(0, 0, KEY_MENU), /*添加的*/
//KEY(0, 3, KEY_KPASTERISK), /* * */
//KEY(2, 3, KEY_KPDOT), /* # */
KEY(1, 0, KEY_KPASTERISK), /* * */
KEY(1, 1, KEY_KPDOT), /* # */
}
static struct pxa27x_keypad_platform_data littleton_keypad_info = {
.matrix_key_rows = 5, /* 由 6 改为 5 */
.matrix_key_cols = 4, /* 由 5 改为 4 */
...
};
//添加
static struct platform_device lifeng_ts_device = {
.name = "lifeng-ts",
.id = -1,
};
static struct platform_device *devices[] __initdata = {
&smc91x_device,
&lifeng_ts_device,//添加
&micco_ts_device,
&micco_bl_device,
&micco_kp_bl_device,
&pxa3xx_device_imm,
&micco_charger_device,
};
========================================
一篇介绍linux输入子系统非常好的文章
linux输入子系统
http://hi.baidu.com/licett/blog/item/bf
KeyEvent newKeyEvent(InputDevice device, long downTime,long eventTime, boolean down, int keycode, int repeatCount,int scancode, int flags)
mThread.start();
Thread mThread = new Thread("InputDeviceReader")
readEvent(ev);
readEvent
android_server_KeyInputQueue_readEvent
hub->getEvent(&deviceId, &type, &scancode, &keycode,
ViewRoot()
mWindow = new W(this, context);
static class W extends IWindow.Stub
public void dispatchKey(KeyEvent event)
public void dispatchKey(KeyEvent event)
Message msg = obtainMessage(DISPATCH_KEY);
sendMessageAtTime(msg, event.getEventTime());
ViewRoot.java (frameworks\base\core\java\android\view)
public void handleMessage(Message msg)
case DISPATCH_KEY:
deliverKeyEvent((KeyEvent)msg.obj, true);
如果是输入框
if (mLastWasImTarget)
{
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null && mView != null) {
int seq = enqueuePendingEvent(event, sendDone);
if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME:
AC 97 AUDIO TOUCHPANEL CODEC
WM9713 - AC 97 AUDIO TOUCHPANEL CODEC - Wolfson Microelectronics plc
WM9713,它的主要功能其实就是A/D转换和D/A转换,播放时把数字信号转换成模拟信号,录音时把模拟信号转换成数字信号。因为触摸屏也用到了A/D转换,为了重用这个功能,所以WM9713集成了音频处理和触摸屏处理两部分功能。