06.输入系统:第10课第22节_输入系统_多点触摸驱动程序_idc配置文件

通过前面的章节,我们已经已经知道怎么编写触摸屏的驱动程序,但是编写之后我们并不能直接使用,在最初移植的时候,编写完程序之后,在安卓的应用层,把上报的数据当做鼠标来处理了,特别的不方便。所以我们需要为我们的触摸屏驱动增加配置文件。

通过前面的小节我们可以知道,android中的输入系统会监测/dev/input目录,当有输入设备接入时,该目录下会生成设备节点,然后输入系统_Reader线程会根据设备节点的name找到对应的配置文件,分别为*idc,*kcm,*kl文件,该些内容在前面都有讲解过。其查找顺序如下:
在这里插入图片描述
在我们的android系统中,使用的是第三个,即system/usr/idc/。我们首先在源码编写SDK/device/rockchip/rk3399/qytech_azalea/gslx680.idc文件,内容如下:

touch.deviceType = touchScreen
touch.orientationAware = 1

告诉android系统,该为一个触摸屏设备。除此之外我们还要修改evice/rockchip/rk3399/qytech_azalea.mk文件,做以下修改(增加+好所表示的代码):

PRODUCT_COPY_FILES += \
    device/rockchip/rk3399/rk3399_all/ddr_config.xml:system/etc/ddr_config.xml \
    device/rockchip/rk3399/rk3399_all/video_status:system/etc/video_status \
+   device/rockchip/rk3399/qytech_azalea/gslx680.idc:system/usr/idc/gslx680.idc \
    device/rockchip/common/resolution_white.xml:/system/usr/share/resolution_white.xml

然后重新编译烧写即可。

那么为什么非要添加这个配置文件呢?有没有办法不添加这个配置文件?
touch.deviceType可以设置为多种类型:
touch.deviceType = touchScreen | touchPad | pointer | default

touchScreen : 触摸屏, 覆盖在显示器上, 可以直接操作各种图标
touchPad    : 触摸板, 不是覆盖在显示器上, 需要在LCD上显示一个光标以便定位
pointer     : 跟touchPad类似, 多一些手势功能("Indirect Multi-touch Pointer Gestures")
default     : 由系统自己确定

我们根据touch.deviceType 这个线索,在源码中查看一下,看看看他在什么地方被引用,在InputReader.cpp文件中,可以看到如下:

	/*从品质文件之中尝试一下,看是否能够获得touch.deviceType这个属性*/
    if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
            deviceTypeString)) {
        /*如果获取的属性为"touchScreen"*/
        if (deviceTypeString == "touchScreen") {
            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
        } else if (deviceTypeString == "touchPad") { /*如果获取的属性为"touchPad"*/
            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
        } else if (deviceTypeString == "touchNavigation") {
            mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
        } else if (deviceTypeString == "pointer") {
            mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
        } else if (deviceTypeString != "default") {
            ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
        }
    }

我们可以看到,从配置文件获得"touch.deviceType"属性之后,其会赋值给mParameters.deviceType,那么除了在该处mParameters.deviceType被赋值为Parameters::DEVICE_TYPE_TOUCH_SCREEN,其他的地方有赋值吗?我们在源码中搜索DEVICE_TYPE_TOUCH_SCREEN,可以在该文件中找到:

    if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
        // The device is a touch screen.
        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;

他会查看输入设备有没有一些属性,如果这个属性为INPUT_PROP_DIRECT,他就会执行:

		mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;

在EventHub.cpp中,我们可以找到hasInputProperty()函数的定义:

bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
    if (property >= 0 && property <= INPUT_PROP_MAX) {
        AutoMutex _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device) {
            return test_bit(property, device->propBitmask);
        }
    }
    return false;
}

可以看到,他是device->propBitmask中,看下有没有property属性,我们搜索propBitmask:

    ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);

可以看到通过ioctl,传递给内核一个EVIOCGPROP的指令,我们在内核源码中搜索EVIOCGPROP,他内核接收到怎么指令之后,会做出什么处理。在内核evdev.c文件中,我们可以看到:

	case EVIOCGPROP(0):
		return bits_to_user(dev->propbit, INPUT_PROP_MAX,size, p, compat_mode);

我们需要设置dev->propbit,其可选择设置如下:

#define INPUT_PROP_POINTER		0x00	/* needs a pointer */
#define INPUT_PROP_DIRECT		0x01	/* direct input devices 直接操作图标*/
#define INPUT_PROP_BUTTONPAD		0x02	/* has button(s) under pad */
#define INPUT_PROP_SEMI_MT		0x03	/* touch rectangle only */

#define INPUT_PROP_MAX			0x1f
#define INPUT_PROP_CNT			(INPUT_PROP_MAX + 1)

我们需去设置INPUT_PROP_DIRECT,在内核中搜索INPUT_PROP_DIRECT,可以找到很多文件对他的应用,看内核中是如何使用,其实在我们的触摸屏源码也存在:

//	__set_bit(INPUT_PROP_DIRECT, input_device->propbit);

只是被注释掉了,只需要取消注释,重新编译源码,即使没有那个配置文件,我们也能正常的操作屏幕了。

现在我们回过头看看,andriod系统中是如何使用INPUT_PROP_DIRECT,在andriod源码的EventHub.cpp文件中,回到:

	 ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);

当有输入设备接入时,android系统的Reader线程,会调用一系列的ioctrl,获取设备相关的信息,如果存在EVIOCGPROP属性,他被读取到device->propBitmask中,在InputReader.cpp文件中:

if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
        // The device is a touch screen.
        mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;

就会设置mParameters.deviceType,如果没有找个这个配置文件,会设置默认值:

    } else {
        // The device is a touch pad of unknown purpose.
        mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
    }

可以理解为我们使用的鼠标。这样该小节就讲解完成了

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/88695907