临沂建设局网站官网,做网站的书籍,温州网站优化搜索,wordpress cnrk3588s: 旋转编码器input输入事件适配
基于Android 12 kernel-5.10版本
参考文档#xff1a; https://blog.csdn.net/szembed/article/details/131551950 Linux 输入设备调试详解#xff08;零基础开发#xff09;Rotary_Encoder旋转编码器驱动 通用GPIO为例 挂载input输…rk3588s: 旋转编码器input输入事件适配
基于Android 12 kernel-5.10版本
参考文档 https://blog.csdn.net/szembed/article/details/131551950 Linux 输入设备调试详解零基础开发Rotary_Encoder旋转编码器驱动 通用GPIO为例 挂载input输入子系统
https://source.android.google.cn/docs/core/interaction/input?hlzh-cn https://developer.android.google.cn/reference/android/support/wearable/input/RotaryEncoder https://developer.android.google.cn/training/wearables/user-input/rotary-input?hlzh-cn 旋转输入 某些 Wear OS 设备包含实体侧面旋钮。当用户旋转此类旋钮时应用的当前视图会向上或向下滚动。此类输入称为“旋转输入”。
1驱动层配置 配置设备树使用已有的rotary_encoder.c驱动代码。
linux驱动设备树配置参考
https://elixir.bootlin.com/linux/latest/source/drivers/input/misc/rotary_encoder.c
https://elixir.bootlin.com/linux/latest/source/arch/arm64/boot/dts/freescale/imx8mn-dimonoff-gateway-evk.dtsrotary: rotary-encoder {compatible rotary-encoder;pinctrl-names default;pinctrl-0 pinctrl_rotary;gpios gpio5 12 GPIO_ACTIVE_LOW, /* A */gpio5 13 GPIO_ACTIVE_LOW; /* B */linux,axis 0; /* REL_X */rotary-encoder,relative-axis;};pinctrl_rotary: rotarygrp {fsl,pins MX8MN_IOMUXC_ECSPI2_MISO_GPIO5_IO12 0x00000156MX8MN_IOMUXC_ECSPI2_SS0_GPIO5_IO13 0x00000156;};2framework层适配 上面驱动层配置好设备树后通过getevent能看到rotary encoder事件。 但是应用App层却收不到。 旋转编码器input输入事件和鼠标滚轮类似设备上鼠标滚轮事件是正常的。 于是先看鼠标滚轮事件。
鼠标滚轮
$ adb shell getevent -lpi
add device 2: /dev/input/event2bus: 0003vendor 093aproduct 2533version 0111name: Gaming Mouselocation: usb-fc840000.usb-1/input0id: version: 1.0.1events:KEY (0001): BTN_MOUSE BTN_RIGHT BTN_MIDDLE BTN_SIDE BTN_EXTRA REL (0002): REL_X REL_Y REL_WHEEL REL_WHEEL_HI_RES MSC (0004): MSC_SCAN input props:noneadb shell dumpsys input2: Gaming MouseClasses: CURSOR | EXTERNALPath: /dev/input/event2Enabled: trueDescriptor: 922b2be403d5734c3dacd1c480566209f0f39e80Location: usb-fc840000.usb-1/input0ControllerNumber: 0UniqueId: Identifier: bus0x0003, vendor0x093a, product0x2533, version0x0111KeyLayoutFile: KeyCharacterMapFile: ConfigurationFile: VideoDevice: none01-11 03:13:33.710 569 663 I EventHub: New device: id6, fd181, path/dev/input/event2, nameGaming Mouse, classesCURSOR | EXTERNAL, configuration, keyLayout, keyCharacterMap, builtinKeyboardfalse,
01-11 03:13:33.714 569 663 I InputReader: Device added: id5, eventHubId6, nameGaming Mouse, descriptor922b2be403d5734c3dacd1c480566209f0f39e80,sources0x00002002
rotary encoder事件信息
rotary encoder事件信息
$ adb shell getevent -lpi
add device 2: /dev/input/event0bus: 0019vendor 0000product 0000version 0000name: rotary // 设备名是rotarylocation: id: version: 1.0.1events:REL (0002): REL_X input props:none添加rotary.idc文件用于framework层识别rotary encoder设备
framework层代码流程分析
frameworks/native/services/inputflinger/reader/EventHub.cpp// Load the configuration file for the device.device-loadConfigurationLocked();// 要想rotary encoder旋转编码器被framework层识别到需要的条件要有configuration文件且device.type为rotaryEncoder// See if this is a rotary encoder type device.String8 deviceType String8();if (device-configuration device-configuration-tryGetProperty(String8(device.type), deviceType)) {if (!deviceType.compare(String8(rotaryEncoder))) {device-classes | InputDeviceClass::ROTARY_ENCODER;}}// 根据设备名找configuration配置文件adb shell getevent -lpi 查看到设备名是name: rotary// Try device name.return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName(), type); 先在android源代码device目录grep -r rotaryEncoder搜索看看是否有类似配置。
搜索到virtio_input_rotary.idc所以执行如下操作验证framework层就能识别到旋转编码器设备了
cp device/generic/goldfish/input/virtio_input_rotary.idc rotary.idc
adb push rotary.idc /system/usr/idc/添加rotary.idc文件虽然framework层识别到了rotary encoder设备但是事件还是报不到App层。继续分析。原因是rotary encoder报的事件是 EV_REL REL_X而RotaryEncoderInputMapper没有解析REL_X事件。因此需要适配解析REL_X事件
打开DEBUG_INBOUND_EVENT_DETAILS log开关后验证旋转编码器的input事件
能看到log时说明App层就能收到事件如果打印不出该log则App层收不到事件。
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILSALOGD(notifyMotion - id% PRIx32 eventTime% PRId64 , deviceId%d, source0x%x, displayId% PRId32 , policyFlags0x%x, action0x%x, actionButton0x%x, flags0x%x, metaState0x%x, buttonState0x%x, edgeFlags0x%x, xPrecision%f, yPrecision%f, xCursorPosition%f, yCursorPosition%f, downTime% PRId64,args-id, args-eventTime, args-deviceId, args-source, args-displayId,args-policyFlags, args-action, args-actionButton, args-flags, args-metaState,args-buttonState, args-edgeFlags, args-xPrecision, args-yPrecision,args-xCursorPosition, args-yCursorPosition, args-downTime);for (uint32_t i 0; i args-pointerCount; i) {ALOGD( Pointer %d: id%d, toolType%d, x%f, y%f, pressure%f, size%f, touchMajor%f, touchMinor%f, toolMajor%f, toolMinor%f, orientation%f,i, args-pointerProperties[i].id, args-pointerProperties[i].toolType,args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),args-pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));}
#endifRotaryEncoderInputMapper解析旋转编码器的input事件数据
RotaryEncoderInputMapper::sync() 函数解析旋转编码器的input事件
$ adb shell getevent -l
add device 1: /dev/input/event0name: rotary/dev/input/event0: EV_REL REL_X 00000001
/dev/input/event0: EV_SYN SYN_REPORT 00000000 /dev/input/event0: EV_REL REL_X ffffffff
/dev/input/event0: EV_SYN SYN_REPORT 0000000086 void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
87 mRotaryEncoderScrollAccumulator.process(rawEvent);
88
89 if (rawEvent-type EV_SYN rawEvent-code SYN_REPORT) {
90 sync(rawEvent-when, rawEvent-readTime);
91 }
92 }
93
94 void RotaryEncoderInputMapper::sync(nsecs_t when, nsecs_t readTime) {
95 PointerCoords pointerCoords;
96 pointerCoords.clear();
97
98 PointerProperties pointerProperties;
99 pointerProperties.clear();
100 pointerProperties.id 0;
101 pointerProperties.toolType AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
102 ALOGI(RotaryEncoderInputMapper::sync);// scroll 返回的是0导致下面notifyMotion走不到。需要在getRelativeVWheel函数里适配
103 float scroll mRotaryEncoderScrollAccumulator.getRelativeVWheel();
104 bool scrolled scroll ! 0;
105
106 // This is not a pointer, so its not associated with a display.
107 int32_t displayId ADISPLAY_ID_NONE;
108
109 // Moving the rotary encoder should wake the device (if specified).
110 uint32_t policyFlags 0;
111 if (scrolled getDeviceContext().isExternal()) {
112 policyFlags | POLICY_FLAG_WAKE;
113 }
114
115 if (mOrientation DISPLAY_ORIENTATION_180) {
116 scroll -scroll;
117 }
118
119 // Send motion event.
120 if (scrolled) {
121 int32_t metaState getContext()-getGlobalMetaState();
122 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);// 添加x的值否则无论正向旋转还是反向旋转x值都是0导致应用App无法识别方向pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, scroll);
123
124 NotifyMotionArgs scrollArgs(getContext()-getNextId(), when, readTime, getDeviceId(),
125 mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0,
126 0, metaState, /* buttonState */ 0, MotionClassification::NONE,
127 AMOTION_EVENT_EDGE_FLAG_NONE, 1, pointerProperties,
128 pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
129 AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
130 getListener()-notifyMotion(scrollArgs);ALOGI(RotaryEncoderInputMapper::sync notifyMotion);
131 }
132
133 mRotaryEncoderScrollAccumulator.finishSync();
134 }42 void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
43 if (rawEvent-type EV_REL) {
44 switch (rawEvent-code) {
45 case REL_WHEEL:
46 mRelWheel rawEvent-value;
47 break;
48 case REL_HWHEEL:
49 mRelHWheel rawEvent-value;
50 break;case REL_X: // 由于自己的旋转编码器报的事件是REL_X所以需要添加该类型解析mRelWheel rawEvent-value;break;
51 }
52 }
53 }log: 旋转编码器正向旋转x1.000000 SOURCE_ROTARY_ENCODER 0x00400000 source0x400000
04-07 05:47:32.041 575 667 D InputDispatcher: notifyMotion - idb0eb158 eventTime1947954629000, deviceId4, source0x400000, displayId-1, policyFlags0x0, action0x8, actionButton0x0, flags0x0, metaState0x0, buttonState0x0, edgeFlags0x0, xPrecision0.000000, yPrecision0.000000, xCursorPositionnan, yCursorPositionnan, downTime0
04-07 05:47:32.041 575 667 D InputDispatcher: Pointer 0: id0, toolType0, x1.000000, y0.000000, pressure0.000000, size0.000000, touchMajor0.000000, touchMinor0.000000, toolMajor0.000000, toolMinor0.000000, orientation0.000000
04-07 05:47:32.041 575 666 D InputDispatcher: dispatchMotion - eventTime1947954629000, deviceId4, source0x400000, displayId-1, policyFlags0x62000000, action0x8, actionButton0x0, flags0x0, metaState0x0, buttonState0x0,edgeFlags0x0, xPrecision0.000000, yPrecision0.000000, downTime0
04-07 05:47:32.041 575 666 D InputDispatcher: Pointer 0: id0, toolType0, x1.000000, y0.000000, pressure0.000000, size0.000000, touchMajor0.000000, touchMinor0.000000, toolMajor0.000000, toolMinor0.000000, orientation0.000000旋转编码器反向旋转x-1.000000 SOURCE_ROTARY_ENCODER 0x00400000 source0x400000
04-07 05:47:35.923 575 667 I InputReader: lqy111 RotaryEncoderInputMapper::sync
04-07 05:47:35.923 575 667 I InputReader: lqy111 RotaryEncoderInputMapper::sync: scroll:-1.000000
04-07 05:47:35.923 575 667 I InputReader: lqy111 RotaryEncoderInputMapper::sync notifyMotion
04-07 05:47:35.923 575 667 D InputDispatcher: notifyMotion - id45c55f eventTime1951836828000, deviceId4, source0x400000, displayId-1, policyFlags0x0, action0x8, actionButton0x0, flags0x0, metaState0x0, buttonState0x0, edgeFlags0x0, xPrecision0.000000, yPrecision0.000000, xCursorPositionnan, yCursorPositionnan, downTime0
04-07 05:47:35.923 575 667 D InputDispatcher: Pointer 0: id0, toolType0, x-1.000000, y0.000000, pressure0.000000, size0.000000, touchMajor0.000000, touchMinor0.000000, toolMajor0.000000, toolMinor0.000000, orientation0.000000
04-07 05:47:35.923 575 666 D InputDispatcher: dispatchMotion - eventTime1951836828000, deviceId4, source0x400000, displayId-1, policyFlags0x62000000, action0x8, actionButton0x0, flags0x0, metaState0x0, buttonState0x0,edgeFlags0x0, xPrecision0.000000, yPrecision0.000000, downTime0
04-07 05:47:35.923 575 666 D InputDispatcher: Pointer 0: id0, toolType0, x-1.000000, y0.000000, pressure0.000000, size0.000000, touchMajor0.000000, touchMinor0.000000, toolMajor0.000000, toolMinor0.000000, orientation0.000000core/java/android/view/InputDevice.java: public static final int SOURCE_ROTARY_ENCODER 0x00400000 | SOURCE_CLASS_NONE; source0x400000App层监听旋转输入事件
App层监听旋转输入事件
developer.android.google.cn/training/wearables/user-input/rotary-input
myView.setOnGenericMotionListener
onGenercMotion
或者 在Activity也可以。framework层监听旋转输入事件
在NativeInputManager::interceptMotionBeforeQueueing()添加适配代码。
com_android_server_input_InputManagerService.cpp
void NativeInputManager::interceptMotionBeforeQueueing(const int32_t displayId, nsecs_t when,uint32_t policyFlags) {调试总结
make libinputreader -j3
make libinputflinger -j3 make libinputflinger_base -j3while true; do echo ######$(date)######;adb logcat -b all | grep -i -E EventHub|InputDispatcher|InputReader|WindowManager; doneadb shell getevent
adb shell getevent -l
adb shell getevent -lip
adb shell dumpsys input