• 移植 android, touch screen 不能正常工作的问题


    http://blog.csdn.net/yrj/archive/2009/12/28/5085008.aspx 

    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 0x1f
    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-2.6.25/drivers/input/touchscreen/bbk_lifeng_ts.c 
    需要修改的配置文件
    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/bf0102f934ebcd5c252df2b3.html
    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集成了音频处理和触摸屏处理两部分功能。
    WM9713支持AC97标准,通过64个寄存器对它进行控制,这个在WM9713的datasheet里有详细的描述。
    WM9713与PXA300之间通过同步串号SSP通信。PXA300在硬件上对AC97有支持,它提供了FIFO,所以音频数据可以通过DMA方式读写。
    它旁边是WM9713音频芯片,主要功能是A/D转换和D/A转换,播放时把数字信号转换成模拟信号,录音时把模拟信号转换成数字信号。因为触摸屏也用到了A/D转换,为了重用这个功能,所以WM9713集成了音频处理和触摸屏处理两部分功能;
    三星智能机i900 音频和触摸使用的是 wolfson WM9713
    9713触摸问题
    我现在用9713采样触摸屏的点,用的是polling的模式,一次采样5个点!但是发现如果触摸笔不离开屏(不停的采样),会降低系统的性能!所以想改 用DMA的模式(Continuous mode),尝试了几次没有成功(点击第一次之后就没反应了),请问有没有使用过9713 DMA模式采样的兄弟们,给点提示!谢谢!环境是:wince6,pxa310, wm9713和4-wire触摸屏。bsp是Mavell的.
    文档说,dma模式可以节约cpu干预而损失的时间,比polling方式少大概一半时间(我的实验结果),其他都是一样的 
    Audio:1个AC97,采用wolf公司的WM9713,1个II2S,采用wolf公司的WM8580A;

    WM8580 介绍
    http://www.wolfsonmicro.cn/products/WM8580/
    WM8580是一款带有S/PDIF收发器的多路音频编码解码器(CODEC),特别适用于DVD以及需要有环绕立体声处理的家用高保真音响、汽车和其它视听设备等应用。 
    该器件集成了一个内置的立体声24位多比特模数转换器(ADC),支持16~32位字长的数字音频输出及8kHz~192kHz的采样率。
    此外,该器件还包含三个立体声24位多比特数模转换器,每个都带有各自的超采样数字内插滤波器,并支持16~32位字长的数字音频输入及8kHz~192kHz的采样率。每路DAC通道都有独立的数字音量和静音控制。
    两个独立的音频数据接口支持I2S、左对齐、右对齐及DSP数字音频格式。每个音频接口都可以工作在主时钟模式或从时钟模式。
    S/PDIF收发器可与IEC-60958-3兼容,支持32k/s~192k/s的帧频。它带有四个多路复用输入端及一个输出端。它还有内置的状态和错误监控功能,其结果可以通过串行接口或者GPO接脚进行传输。同时,还提供S/PDIF通道块配置功能。 
    该器件带有两个锁相环(PLL),可以对它们进行单独配置,以生成两个系统时钟作为内部或外部使用。 
    对该器件的控制和设置是通过一个两线制或三线制(可与SPI兼容)的串行接口来实现的。串行接口为所有功能的应用提供了渠道,这些功能包括通道选择、音量 控制、静音、去/加重、S/PDIF控制/状态,以及电源管理工具。另外,该器件的硬件管理模式还可以通过选择管脚来激活或禁止器件的功能。 
    WM8580是采用48引脚TQFP封装,现可供货。
    WM9713 
    http://www.wolfsonmicro.cn/products/WM9713
    带有触摸屏控制器的声音和音频编码解码器
    WM9713L是一款高度集成的输入/输出器件,专为移动计算和通信而设计。
    该芯片采用了双编解码器运行的架构,通过AC连接接口支持高保真(Hi-Fi)立体声编解码器功能,同时还通过一个PCM型同步串行端口(SSP)额外支 持声音编码解码器功能。该芯片还提供了一个第三辅助数字模拟转换器,用于采用与主编码解码器不同的采样率,支持产生监控音调(supervisory tones)或铃声等。
    该器件能够直接连接到一个4线或5线触摸屏、单声道或立体声麦克风、立体声耳机以及立体声扬声器,从而降低了系统元器件总数。与耳机、扬声器以及听筒的无 电容连接,可节省成本和印刷电路板面积。另外,还提供了多个模拟输入和输出引脚,与无线通讯设备模拟连接无缝集成在一起。
    通过一个符合AC-97标准的单独的AC-Link接口,可以连接和控制所有的芯片功能。可以直接输入24.576MHz的主时钟,或者由板上的锁相环从一个13MHz (或其他频率)时钟从内部产生,该锁相环支持从2.048Mhz 到78.6Mhz的大范围输入时钟。
    WM9713L运行的电源电压范围为1.8V-3.6V;芯片上的任何部分都可以通过软件控制实现关断来降低功耗。该器件采用了小型的无引线7×7mm封装,是掌上和便携系统应用的理想方案。

    以下为转载:

    按键触摸屏流程分析:
    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 0x1f
    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-2.6.25/drivers/input/touchscreen/bbk_lifeng_ts.c 
    需要修改的配置文件
    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/bf0102f934ebcd5c252df2b3.html
    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集成了音频处理和触摸屏处理两部分功能。
    WM9713支持AC97标准,通过64个寄存器对它进行控制,这个在WM9713的datasheet里有详细的描述。
    WM9713与PXA300之间通过同步串号SSP通信。PXA300在硬件上对AC97有支持,它提供了FIFO,所以音频数据可以通过DMA方式读写。
    它旁边是WM9713音频芯片,主要功能是A/D转换和D/A转换,播放时把数字信号转换成模拟信号,录音时把模拟信号转换成数字信号。因为触摸屏也用到了A/D转换,为了重用这个功能,所以WM9713集成了音频处理和触摸屏处理两部分功能;
    三星智能机i900 音频和触摸使用的是 wolfson WM9713
    9713触摸问题
    我现在用9713采样触摸屏的点,用的是polling的模式,一次采样5个点!但是发现如果触摸笔不离开屏(不停的采样),会降低系统的性能!所以想改 用DMA的模式(Continuous mode),尝试了几次没有成功(点击第一次之后就没反应了),请问有没有使用过9713 DMA模式采样的兄弟们,给点提示!谢谢!环境是:wince6,pxa310, wm9713和4-wire触摸屏。bsp是Mavell的.
    文档说,dma模式可以节约cpu干预而损失的时间,比polling方式少大概一半时间(我的实验结果),其他都是一样的 
    Audio:1个AC97,采用wolf公司的WM9713,1个II2S,采用wolf公司的WM8580A;

    WM8580 介绍
    http://www.wolfsonmicro.cn/products/WM8580/
    WM8580是一款带有S/PDIF收发器的多路音频编码解码器(CODEC),特别适用于DVD以及需要有环绕立体声处理的家用高保真音响、汽车和其它视听设备等应用。 
    该器件集成了一个内置的立体声24位多比特模数转换器(ADC),支持16~32位字长的数字音频输出及8kHz~192kHz的采样率。
    此外,该器件还包含三个立体声24位多比特数模转换器,每个都带有各自的超采样数字内插滤波器,并支持16~32位字长的数字音频输入及8kHz~192kHz的采样率。每路DAC通道都有独立的数字音量和静音控制。
    两个独立的音频数据接口支持I2S、左对齐、右对齐及DSP数字音频格式。每个音频接口都可以工作在主时钟模式或从时钟模式。
    S/PDIF收发器可与IEC-60958-3兼容,支持32k/s~192k/s的帧频。它带有四个多路复用输入端及一个输出端。它还有内置的状态和错误监控功能,其结果可以通过串行接口或者GPO接脚进行传输。同时,还提供S/PDIF通道块配置功能。 
    该器件带有两个锁相环(PLL),可以对它们进行单独配置,以生成两个系统时钟作为内部或外部使用。 
    对该器件的控制和设置是通过一个两线制或三线制(可与SPI兼容)的串行接口来实现的。串行接口为所有功能的应用提供了渠道,这些功能包括通道选择、音量 控制、静音、去/加重、S/PDIF控制/状态,以及电源管理工具。另外,该器件的硬件管理模式还可以通过选择管脚来激活或禁止器件的功能。 
    WM8580是采用48引脚TQFP封装,现可供货。
    WM9713 
    http://www.wolfsonmicro.cn/products/WM9713
    带有触摸屏控制器的声音和音频编码解码器
    WM9713L是一款高度集成的输入/输出器件,专为移动计算和通信而设计。
    该芯片采用了双编解码器运行的架构,通过AC连接接口支持高保真(Hi-Fi)立体声编解码器功能,同时还通过一个PCM型同步串行端口(SSP)额外支 持声音编码解码器功能。该芯片还提供了一个第三辅助数字模拟转换器,用于采用与主编码解码器不同的采样率,支持产生监控音调(supervisory tones)或铃声等。
    该器件能够直接连接到一个4线或5线触摸屏、单声道或立体声麦克风、立体声耳机以及立体声扬声器,从而降低了系统元器件总数。与耳机、扬声器以及听筒的无 电容连接,可节省成本和印刷电路板面积。另外,还提供了多个模拟输入和输出引脚,与无线通讯设备模拟连接无缝集成在一起。
    通过一个符合AC-97标准的单独的AC-Link接口,可以连接和控制所有的芯片功能。可以直接输入24.576MHz的主时钟,或者由板上的锁相环从一个13MHz (或其他频率)时钟从内部产生,该锁相环支持从2.048Mhz 到78.6Mhz的大范围输入时钟。
    WM9713L运行的电源电压范围为1.8V-3.6V;芯片上的任何部分都可以通过软件控制实现关断来降低功耗。该器件采用了小型的无引线7×7mm封装,是掌上和便携系统应用的理想方案。

  • 相关阅读:
    洛谷P1208 [USACO1.3]混合牛奶 Mixing Milk 题解 结构体排序
    信息学竞赛中C语言的输入输出
    Python 关键字参数和可变参数
    大白话讲解神经网络算法,原理如此简单!
    idea debug flink1.12 sqlClient 源码
    Flink SQL如何保证分topic有序
    Flink 1.12.0 SQL Connector支持 Oracle
    Flink实战之Flink SQL connector支持并行度配置
    java程序中执行脚本时具有的是那个用户的权限呢?
    clickhouse日期等函数的使用
  • 原文地址:https://www.cnblogs.com/leaven/p/1658891.html
Copyright © 2020-2023  润新知