Chinaunix首页 | 论坛 | 博客
  • 博客访问: 181259
  • 博文数量: 13
  • 博客积分: 265
  • 博客等级: 二等列兵
  • 技术积分: 402
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-16 17:19
文章分类

全部博文(13)

文章存档

2014年(2)

2013年(2)

2012年(9)

我的朋友

分类: LINUX

2012-09-07 17:02:55

    Assumed that you Linux kernel & Android system can start successfully, and adb can work.
    Below context just list what I do when I debug touch screen feature in A10 pro of Allwinner.

    1, At first, check if you driver module is loaded or not in you adb shell or by minicom in serial port.
  1. # lsmod
    if not, please check your init.rc or insert manually(driver ko file usually in path /system/vendor/modules/, depending on makefile of your devices)

    2, check if hardware(touch screen) is connected and mounted.
  1.  # getevent
    show info below:
  1. add device 1: /dev/input/event3
      name:     "bma250"
    could not get driver version for /dev/input/js0, Invalid argument
    add device 2: /dev/input/event2
      name:     "ft5x_ts"
    add device 3: /dev/input/event0
      name:     "sun4i-keyboard"
    could not get driver version for /dev/input/mice, Not a typewriter
    add device 4: /dev/input/event1
      name:     "axp20-supplyer"
    Fortunately I have not hardware problem, it mount as device /dev/input/event2 successfully.
    If failed, please check step 1, then make sure if you hardware is not broken and power supply correct.
This part debug is a little complicated because it is relative with your Linux kernel driver code. Let's instruct touch screen driver simply.
    At first, it defines a ctp(configurable touch panel) relative operations, read some hardware configure from special file(defined by manufactory or yourself), initial and wakeup to detect touch panel.
    Then defines some aw_i2c_ts_fops(struct file_operations), at least implement open, unlocked_ioctl and release function here. It implemented by comunication with i2c modules and usually this part is mature enough, just copy from Internet.
    At last a struct i2c_driver should be add to i2c drivers(by function i2c_add_driver), here, probe, the most important function should be implemented. In probe, register some input event for device, allocate a input device struct and register it, and initial a irq for handle input request in bottom half.
    When Irq coming, it read data from i2c and post to android frame work, that all the process in short.
    I will instruct input kernel driver details in some other post later.

    3, Check raw events from kernel when you click your touch panel.
    You can get event by command getevent and compare with log in EventHub(framework/base/services/input/EventHub.cpp, InputReader get raw events in a thread by invoking EventHub::getEvents).
    As a click event, raw events should be(just list some important parameters):
    Down Events group:
  1. (EV_ABS, ABS_MT_TRACKING_ID, touchId)
  2. (EV_ABS, ABS_MT_TOUCH_MAJOR, pressValue)
  3. (EV_ABS, ABS_MT_POSITION_X, x)
  4. (EV_ABS, ABS_MT_POSITION_Y, y)
  5. (EV_ABS, ABS_MT_WIDTH_MAJOR, 1)
  6. (EV_SYN, SYN_MT_REPORT, 0)
  7. (EV_SYN, SYN_REPORT, 0)
    touchId is from 0 to increase, max is 16, to identify your touch pointer; pressValue is a nonzero value.
    You can refer to android document: http://source.android.com/tech/input/touch-devices.html. You can add or remove some optional events yourself in your kernel driver.
    Upper raw events group will be send to input reader several times until you move your finger up from touch panel. then raw event should be:
    Up Events group:
  1. (EV_ABS, ABS_MT_TOUCH_MAJOR, releaseValue)
  2. (EV_SYN, SYN_REPORT, 0)
    releaseValue usually is 0.
    If you event is very different, please check you kernel driver code of irq handle part. In my case, raw events is all right. so I have to continue to check android input dispatch process.

    4, Generate various action in InputReader and dispatch them in InputDispatch.
    When first down events group is captured by input reader, it should be dispatch as event  AMOTION_EVENT_ACTION_DOWN at TouchInputMapper::dispatchTouches. In my case it is defined as a AMOTION_EVENT_ACTION_HOVER_ENTER, it is wrong! So I investigate why it is regarded as a hover event:
  1. while (!downIdBits.isEmpty())
It always empty.
  1. BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
and:
  1. BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
  2. BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
    I check mCurrentCookedPointerData.touchingIdBits, it is 0 all the time, but mCurrentCookedPointerData.hoveringIdBits change; Obviously process is using hoveringIdBits to respond some events rather than using touchingIdBits. Why?
    In MultiTouchInputMapper::syncTouch:
  1. bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
  2.                   && ( mTouchButtonAccumulator.isHovering()
  3.                         || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
  4. outPointer.isHovering = isHovering;
  5. ...
  6. ...
  7. mCurrentRawPointerData.markIdBit(id, isHovering);
    I track and find that isHovering is always true, THAT'S THE REASON. Let's check how mTouchButtonAccumulator.isHovering works:
  1. bool TouchButtonAccumulator::isHovering() const {
  2.      return mHaveBtnTouch && !mBtnTouch;
  3. }
while:
  1. mHaveBtnTouch = device->hasKey(BTN_TOUCH);
    LOL, seems root cause is found. As a muti-touch screen, this event should not be register, but for a single touch screen this must be register. Check kernel driver if BTN_TOUCH event is register in probe function :

  1. #ifdef FOR_TSLIB_TEST
  2. set_bit(BTN_TOUCH, input_dev->keybit);
  3. #endif
    undefine it and AMOTION_EVENT_ACTION_DOWN is generated.

    5, Trouble is continuing...
    When up event group is capture, My broad does not generate AMOTION_EVENT_ACTION_UP, it continue with AMOTION_EVENT_ACTION_MOVE. WTF. Look the logcat log, in TouchInputMapper::sync:
  1. syncTouch(when, &havePointerIds);

  2. #if DEBUG_RAW_EVENTS
  3. if (!havePointerIds) {
  4. ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
  5. mLastRawPointerData.pointerCount,
  6. mCurrentRawPointerData.pointerCount);
  7. }
    havePointerIds return a false here, and log show "syncTouch: pointerCount 1 -> 1". and 1 -> 0. Check MultiTouchInputMapper::syncTouch again:
  1. if (*outHavePointerIds) {
  2.      if (id < 0 && !mPointerIdBits.isFull()) {
  3.      id = mPointerIdBits.markFirstUnmarkedBit();
  4.      mPointerTrackingIdMap[id] = trackingId;
  5.      }
  6.     ....
  7.     ....
  8. }
  9. if (id < 0) {
  10.      *outHavePointerIds = false;
  11.      ....
  12. }
    mPointerIdBits is always full and id can not get a positive value. Add codes in this function to drop some invalid pointer:
  1. if (!inSlot->isInUse()) {
  2.      continue;
  3. }
  4. // this is new added to filter invalid pointer
  5. if((inSlot->getX() == 0) && (inSlot->getY() == 0)) {
  6.      continue;
  7. }
    Compile, flash to board, OK!
阅读(2857) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~