amlogic t972红外遥控功能器及飞鼠模式(附上RK和全志飞鼠模式)

驱动:
common/drivers/amlogic/input/remote
remote_core.c:遥控器核心层,向input子系统注册、上报键值。
remote_cdev.c:/dev/amremote设备节点及相关的ioctl操作
remote_decoder_xmp.c:XMP红外协议解码器
remote_meson.c:红外遥控器配置相关。
remote_raw.c:使用软件方式来获取红外扫描值。
remote_regmap.c:寄存器操作相关的代码
sysfs.c:为应用程序提供sys文件节点及操作。

驱动代码的入口在remote_meson.c:
在这里插入图片描述

遥控器初始化

在这里插入图片描述
直接看remote_probe()

static int remote_probe(struct platform_device *pdev)
{
    
    
	struct remote_dev *dev;
	int ret;
	struct remote_chip *chip;

	//结构体remote_chip包含整个红外相关的信息
	chip = kzalloc(sizeof(struct remote_chip), GFP_KERNEL);
	//结构体remote_dev代表一个红外设备
	dev = remote_allocate_device();

	chip->r_dev = dev;
	chip->dev = &pdev->dev;

	chip->r_dev->dev = &pdev->dev;
	chip->r_dev->platform_data = (void *)chip;
	chip->r_dev->getkeycode    = getkeycode;
	chip->r_dev->ir_report_rel = ir_report_rel;
	chip->r_dev->set_custom_code = set_custom_code;
	chip->r_dev->is_valid_custom = is_valid_custom;
	chip->r_dev->is_next_repeat  = is_next_repeat;
	chip->r_dev->max_learned_pulse = MAX_LEARNED_PULSE;
	chip->set_register_config = ir_register_default_config;
	platform_set_drvdata(pdev, chip);
	//初始化input_dev,设置为input0,可用getevent | grep event0来获取按键事件
	ir_input_device_init(dev->input_device, &pdev->dev, "aml_keypad");
	//红外初始化,这里初始化硬件相关的,比如寄存器,中断、led灯还有红外协议类型。
	ret = ir_hardware_init(pdev);1//创建/dev/amremote设备节点
	ret = ir_cdev_init(chip);

	dev->rc_type = chip->protocol;	//dts里面配置为REMOTE_TYPE_NEC
	//向remote_core注册红外设备
	ret = remote_register_device(dev);2//使能红外唤醒系统功能
	device_init_wakeup(&pdev->dev, 1);
	dev_pm_set_wake_irq(&pdev->dev, chip->irqno);
	//led控制相关,检测到遥控按键时闪一下led灯
	led_trigger_register_simple("rc_feedback", &dev->led_feedback);
	//下面与红外学习有关
	setup_timer(&dev->learning_done, ir_learning_done, (unsigned long)dev);
	if (dev->demod_enable)
		demod_init(chip);
	INIT_DELAYED_WORK(&chip->ir_workqueue, learning_done_workqueue);
	INIT_WORK(&chip->fifo_work, get_fifo_data_work);
	return 0;
}

(1)、ir_hardware_init()

ir_hardware_init()
|–>ir_get_devtree_pdata():从dts里面获取寄存器,中断、led灯还有红外协议类型。
| |–>get_custom_tables():从dts里面获取按键键值表
|–>set_register_config(),也就是调用ir_register_default_config()
| |–>ir_contr_init()
|–>ir_interrupt() 注册中断处理函数
|–>tasklet_enable(&tasklet); 使能一个任务tasklet

在这里插入图片描述
从remote_reg_proto找到对应协议的寄存器信息,比如dts里面设置协议为REMOTE_TYPE_NEC:
在这里插入图片描述
ir_contr_init()接下来的查代码则根据reg_nec来初始化寄存器。

(2)、remote_register_device

int remote_register_device(struct remote_dev *dev)
{
    
    
	int i;
	int ret;

	__set_bit(EV_KEY, dev->input_device->evbit);
	for (i = KEY_RESERVED; i < BTN_MISC; i++)
		__set_bit(i, dev->input_device->keybit);
	for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; i++)
		__set_bit(i, dev->input_device->keybit);

	__set_bit(BTN_MOUSE, dev->input_device->keybit);
	__set_bit(BTN_LEFT, dev->input_device->keybit);
	__set_bit(BTN_RIGHT, dev->input_device->keybit);
	__set_bit(BTN_MIDDLE, dev->input_device->keybit);

	__set_bit(EV_REL, dev->input_device->evbit);
	__set_bit(REL_X, dev->input_device->relbit);
	__set_bit(REL_Y, dev->input_device->relbit);
	__set_bit(REL_WHEEL, dev->input_device->relbit);

	dev->input_device->keycodesize = sizeof(unsigned short);
	dev->input_device->keycodemax = 0x1ff;
//注册input设备
	ret = input_register_device(dev->input_device);
//下面用于调试,这里分配了4kb,调试时调用
	dev->debug_current     = 0;
	dev->debug_buffer_size = 4096;
	dev->debug_buffer = kzalloc(dev->debug_buffer_size, GFP_KERNEL);
	if (!dev->debug_buffer) {
    
    
		dev_err(dev->dev, "kzalloc debug_buffer error!\n");
		ret = -ENOMEM;
	}

	return ret;
}

中断处理函数ir_interrupt

上面只是初始化过程,其中注册了中断函数ir_interrupt(),并使能中断。当操作红外遥控器时,中断被触发并调用ir_interrupt()处理(裁剪后的):

static irqreturn_t ir_interrupt(int irq, void *dev_id)
{
    
    

	remote_reg_read(rc, MULTI_IR_ID, REG_REG1, &val);
	val = (val & 0x1FFF0000) >> 16;
	sprintf(buf, "duration:%d\n", val);
	debug_log_printk(rc->r_dev, buf);

	if (MULTI_IR_SOFTWARE_DECODE(rc->protocol)) {
    
    
。。。。。。
	} else {
    
    
		for (cnt = 0; cnt < (ENABLE_LEGACY_IR(rc->protocol)
				? 2:1); cnt++) {
    
    
			remote_reg_read(rc, cnt, REG_STATUS, &contr_status);
			if (IR_DATA_IS_VALID(contr_status)) {
    
    
				rc->ir_work = cnt;
				break;
			}
		}

		if (cnt == IR_ID_MAX) {
    
    
			dev_err(rc->dev, "invalid interrupt.\n");
			return IRQ_HANDLED;
		}

		tasklet_schedule(&tasklet);
	}
	return IRQ_HANDLED;
}

tasklet是个全局变量,这是Linux中断机制里面“下半部”的一种实现方式——tasklet,其静态注册如下:
在这里插入图片描述
在前面ir_hardware_init()函数最后,设置了amlremote_tasklet参数为remote_chip。这里的中断处理函数ir_interrupt()主动调度tasklet,即异步调用amlremote_tasklet:
在这里插入图片描述
remote_keydown()函数
在这里插入图片描述

  1. ir_report_rel
    鼠标模式下的按键处理,发送“相对坐标”事件,后面再分析。
  2. getkeycode
    根据dts配置信息,获取对应遥控器scancode对应的keycode
  3. ir_do_keydown
    发送按键事件。

这里解析getkeycode(),去掉无关代码后:
在这里插入图片描述
在这里插入图片描述
ir_lookup_by_scancode()使用二分法从已经排序的键值表获得scancode对应的keycode序号。然后getkeycode()返回序号对应的keycode。

遥控器鼠标模式

遥控器模拟鼠标功能:单击鼠标按键可切换到鼠标模式,此时在android视图上绘制鼠标的箭头. 单击上,下,左和右时,鼠标箭头可以上,下,左和右移动。
打上amlogic原厂的补丁,使能遥控功能器鼠标模式,不过代码只能适配一种遥控器。
在解析dts、获得键值表最后添加以下代码:
在这里插入图片描述
这里设置鼠标模式切换的按键及4个反向键和OK键,总共6个按键的扫描码。当用户操作遥控器fn_key_scancode建时,在getkeycode()进行模式切换:
在这里插入图片描述
此后,上下左右这4个方向键会被ir_report_rel()处理:

static int ir_report_rel(struct remote_dev *dev, u32 scancode, int status)
{
    
    
。。。。。。
	/*nothing need to do in normal mode*/
	//当前不是鼠标模式,则直接返回
	if (!ct || (ct->ir_dev_mode != MOUSE_MODE))
		return -EINVAL;

	//repeat_count用于设置移动步数,长按时间越长,移动步数越大(直到最大值)
	if (status == REMOTE_REPEAT) {
    
    
		valid_scancode = dev->last_scancode;
		repeat_count++;
		if (repeat_count > ARRAY_SIZE(move_accelerate) - 1)
			repeat_count = ARRAY_SIZE(move_accelerate) - 1;
	} else {
    
    
		valid_scancode = scancode;
		dev->last_scancode = scancode;
		repeat_count = 0;
	}
	//分别处理四个方向键,计算步数
	if (valid_scancode == ct->tab.cursor_code.cursor_left_scancode) {
    
    
		cursor_value = -(1 + move_accelerate[repeat_count]);
		mouse_code = REL_X;
	} else if (valid_scancode ==
			ct->tab.cursor_code.cursor_right_scancode) {
    
    
		cursor_value = 1 + move_accelerate[repeat_count];
		mouse_code = REL_X;
	} else if (valid_scancode ==
			ct->tab.cursor_code.cursor_up_scancode) {
    
    
		cursor_value = -(1 + move_accelerate[repeat_count]);
		mouse_code = REL_Y;
	} else if (valid_scancode ==
			ct->tab.cursor_code.cursor_down_scancode) {
    
    
		cursor_value = 1 + move_accelerate[repeat_count];
		mouse_code = REL_Y;
	} else {
    
    
		return -EINVAL;
	}
	//发送“相对坐标”的event事件
	input_event(chip->r_dev->input_device, EV_REL,
			mouse_code, cursor_value);
	input_sync(chip->r_dev->input_device);

	return 0;
}

那OK键或Enter键如何处理呢?
在这里插入图片描述
BTN_LEFT是鼠标的左键。

问题1、按遥控器鼠标键,UI界面不能出现鼠标图标

因在get_custom_tables()只设置了鼠标键扫描值,没有设置keycode,所以使用了默认值0,即KEY_RESERVED。而在ir_do_keydown()判断keycode为KEY_RESERVED时不发送event事件。所以按遥控鼠标键仅仅是驱动里面对鼠标模式进行切换,UI界面不会有响应。
在这里插入图片描述

问题2、兼容多个遥控器

虽然上面实现了遥控器的鼠标功能,但是只能适配一种遥控器的扫描码,如果换一个遥控器怎么办?如果系统支持多个遥控器又怎么办?这些扫描码需要从dts获取:

/*return scancode*/
static __u16 ir_lookup_by_keycode(struct ir_map_tab *ir_map,
		unsigned int keycode)
{
    
    
	int i = 0;
	int len = ir_map->map_size - 1;

	for(;i <= len; i++){
    
    
		if(ir_map->codemap[i].keycode == keycode)
			return (__u16)(0xff - ir_map->codemap[i].scancode);
	}

	return (__u16)0xff;
}
static int get_custom_tables(struct device_node *node,
	struct remote_chip *chip)
{
    
    
	。。。。。。
		memset(&ptable->tab.cursor_code, 0xff,
					sizeof(struct cursor_codemap));
		ptable->tab.cursor_code.fn_key_scancode = ir_lookup_by_keycode(&ptable->tab, CURSOR_FN_KEYCODE);
		ptable->tab.cursor_code.cursor_left_scancode = ir_lookup_by_keycode(&ptable->tab, CURSOR_LEFT_KEYCODE);
		ptable->tab.cursor_code.cursor_right_scancode = ir_lookup_by_keycode(&ptable->tab, CURSOR_RIGHT_KEYCODE);
		ptable->tab.cursor_code.cursor_up_scancode = ir_lookup_by_keycode(&ptable->tab, CURSOR_UP_KEYCODE);
		ptable->tab.cursor_code.cursor_down_scancode = ir_lookup_by_keycode(&ptable->tab, CURSOR_DOWN_KEYCODE);
		ptable->tab.cursor_code.cursor_ok_scancode = ir_lookup_by_keycode(&ptable->tab, CURSOR_OK_KEYCODE);;
		printk("cursor_code:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
			ptable->tab.cursor_code.fn_key_scancode,
			ptable->tab.cursor_code.cursor_left_scancode,
			ptable->tab.cursor_code.cursor_right_scancode,
			ptable->tab.cursor_code.cursor_up_scancode,
			ptable->tab.cursor_code.cursor_down_scancode,
			ptable->tab.cursor_code.cursor_ok_scancode);

		ir_scancode_sort(&ptable->tab);
}

但是,发现dts里面的键值表,KEY_F5可能有多个扫描码(可能是历史原因,不同生产批次的遥控器上某个按键可能被设置了不同的扫描码),同理其他Keycode也可能有多个扫描码。

static bool is_contain_scancode_keycode(struct ir_map_tab *ir_map,
		unsigned int scancode, unsigned int keycode)
{
    
    
	int index = ir_lookup_by_scancode(ir_map, scancode);
	if (index < 0) {
    
    
		printk("scancode %d undefined\n", scancode);
		return false;
	}

	if( (ir_map->codemap[index].keycode == keycode) )
		return true;

	return false;
}

上面判断键值表里面scancode和keycode是不是一对键值。比如判断scancode对应的keycode是不是OK键:
在这里插入图片描述
缺点是每次按按键都要进行遍历然后判断。

问题3、光标移动速度慢

在这里插入图片描述

RK遥控器鼠标模式

Rockchip的遥控器鼠标模式主要在inputflinger实现。

按键定义

鼠标移动功能需要5个按键,在framework/native/include/android/keycodes.h定义:

    AKEYCODE_TV_KEYMOUSE_LEFT = 286,
    AKEYCODE_TV_KEYMOUSE_RIGHT = 287,
    AKEYCODE_TV_KEYMOUSE_UP = 288,
    AKEYCODE_TV_KEYMOUSE_DOWN = 289,
    AKEYCODE_TV_KEYMOUSE_MODE_SWITCH = 290

其中AKEYCODE_TV_KEYMOUSE_MODE_SWITCH 用于进入/退出鼠标模式,其他4个按键是方向键。

按键处理

Framework/native/services/inputflinger/InputReader.cpp
KeyboardInputMapper::processKey()

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
        int32_t usageCode) {
    
    
	。。。。。。
	char mKeyMouseState[PROPERTY_VALUE_MAX] = "";
	property_get("sys.KeyMouse.mKeyMouseState", mKeyMouseState, "off");
	char mID[PROPERTY_VALUE_MAX] = "";
	sprintf(mID,"%d",getDeviceId());
	property_set("sys.ID.mID",mID);

	if (down) {
    
    
	   if (keyCode == AKEYCODE_TV_KEYMOUSE_MODE_SWITCH) {
    
    
		   if (strcmp(mKeyMouseState, "on")==0) {
    
    
			   property_set("sys.KeyMouse.mKeyMouseState", "off");
		   } else if (strcmp(mKeyMouseState,"off")==0) {
    
    
			   property_set("sys.KeyMouse.mKeyMouseState","on");
		   }
	   }
	   。。。。。。
	   
	if (strcmp(mKeyMouseState, "on") == 0) {
    
    
        if(keyCode == AKEYCODE_DPAD_LEFT) {
    
    
            keyCode = AKEYCODE_TV_KEYMOUSE_LEFT;
        } else if (keyCode == AKEYCODE_DPAD_RIGHT) {
    
    
            keyCode = AKEYCODE_TV_KEYMOUSE_RIGHT;
        } else if (keyCode == AKEYCODE_DPAD_UP) {
    
    
            keyCode = AKEYCODE_TV_KEYMOUSE_UP;
        } else if (keyCode == AKEYCODE_DPAD_DOWN) {
    
    
            keyCode = AKEYCODE_TV_KEYMOUSE_DOWN;
        }
    }

如果AKEYCODE_TV_KEYMOUSE_MODE_SWITCH被按下,则根据上一次保存的鼠标模式状态进行模式切换。属性sys.KeyMouse.mKeyMouseState也用来控制Framework中其他代码的流程。
当进入鼠标模式时,对四个方向键做一些键值转换。因为按遥控器的方向键是和键盘方向键上报给InputFlinger的Event事件是一样的,所以这里将键值转换为鼠标的方向键,以便Framework对其进行特殊处理。
这些转换后的方向键,会被分发到WMS处理,KeyEvent.java也新增、定义了这些按键值:

    /** Key code constant: Tv controlloer left mouse key */
    public static final int KEYCODE_TV_KEYMOUSE_LEFT = 286;
    /** Key code constant: Tv controlloer right mouse key*/
    public static final int KEYCODE_TV_KEYMOUSE_RIGHT = 287;
    /** Key code constant: Tv controlloer up mouse key*/
    public static final int KEYCODE_TV_KEYMOUSE_UP = 288;
    /** Key code constant: Tv controlloer down mouse key*/
    public static final int KEYCODE_TV_KEYMOUSE_DOWN = 289;
    /** Key code constant: Tv controlloer switch mouse key*/
    public static final int KEYCODE_TV_KEYMOUSE_MODE_SWITCH = 290;

    private static final int LAST_KEYCODE = KEYCODE_TV_KEYMOUSE_MODE_SWITCH;

PhoneWindowManager.java interceptKeyBeforeDispatching()对按键预处理:

        mstate = SystemProperties.get("sys.KeyMouse.mKeyMouseState");
        if (mstate.equals("on") && ((keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_LEFT)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_RIGHT)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_UP)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_DOWN)
                || (keyCode == KeyEvent.KEYCODE_TV_KEYMOUSE_MODE_SWITCH))) {
    
    
            keydown = down;
            mKeyMouseHandler.sendEmptyMessage(keyCode);
            //return -1;
        }

发送消息给mKeyMouseHandler处理:

    private int screenWidth;
    private int screenHeight;
    private String mstate = null;
    private float mdeltax, mdeltay;
    boolean keydown;

    public Handler mKeyMouseHandler = new Handler() {
    
    
        public void handleMessage(Message msg) {
    
    
            switch(msg.what){
    
    
            case KeyEvent.KEYCODE_TV_KEYMOUSE_LEFT:
                mdeltax = -1.0f;
                mdeltay = 0;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_RIGHT:
                mdeltax = 1.0f;
                mdeltay = 0;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_UP:
                mdeltax = 0;
                mdeltay = -1.0f;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_DOWN:
                mdeltax = 0;
                mdeltay = 1.0f;
                break;
            case KeyEvent.KEYCODE_TV_KEYMOUSE_MODE_SWITCH:
                mdeltax = 0;
                mdeltay = 0;
                break;
            default:
                break;
            }

            try {
    
    
				//移动鼠标光标位置
                mWindowManager.dispatchMouse(mdeltax,mdeltay,screenWidth,screenHeight);
            } catch (Exception e){
    
    
                e.printStackTrace();
            }

            if (keydown) {
    
    //如果按键没有弹起,则继续发送消息(模拟长按事件)
                mKeyMouseHandler.sendEmptyMessageDelayed(msg.what,30);
            }
        }
    };

mWindowManager.dispatchMouse()–>WindowManagerService::dispatchMouse()–>InputManagerService::dispatchMouse()–>android_server_InputManager_nativedispatchMouse()

static void android_server_InputManager_nativedispatchMouse(JNIEnv* env,
		jclass clazz,jfloat x,jfloat y,jint w,jint h,jlong ptr) {
    
    
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    int mID;
    float mx, my;
    float screenWidth,screenHeight;
    char *mgetID=new char[PROPERTY_VALUE_MAX];
    const char *mkeyMouseState;
    screenWidth=(float)w;
    screenHeight=(float)h;

    property_get("sys.ID.mID",mgetID,0);
    mID=atoi(mgetID);

    mPointerController=im->obtainPointerController(mID);

    //start to dispatchMouse
    mPointerController->setPresentation(
                    PointerControllerInterface::PRESENTATION_POINTER);
    mPointerController->move(x,y);
    mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
    mPointerController->getPosition(&mx, &my);

    //if((mx<=0)||((mx>=(screenWidth-10.0f))||(my<=0)||(my>=(screenHeight-10.0f)))
    //	x=0;y=0;

    if (mx == 0) {
    
    
	    mkeyMouseState="left";
    } else if (mx>=(screenWidth-5.0f)) {
    
    
	    mkeyMouseState="right";
    } else if (my == 0) {
    
    
	    mkeyMouseState="up";
    } else if (my >= (screenHeight-5.0f)) {
    
    
	    mkeyMouseState="down";
    } else {
    
    
	    mkeyMouseState="Non-boundary";
    }

    property_set("sys.keymouselimitstate",mkeyMouseState);
}

这里调用PointerController用来保存、控制光标的位置信息。

显示光标:

static void android_server_InputManager_nativedispatchMouseByCd(JNIEnv* env,
jclass clazz,jfloat x,jfloat y,jlong ptr) {
    
    
   NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
   int mID;
   char *mgetID=new char[PROPERTY_VALUE_MAX];

   property_get("sys.ID.mID",mgetID,0);
   mID=atoi(mgetID);

   mPointerController=im->obtainPointerController(mID);

   //start to dispatchMouse
    mPointerController->setPresentation(
                    PointerControllerInterface::PRESENTATION_POINTER);
    mPointerController->setPosition(x,y);
    mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
	//mPointerController->fade(PointerControllerInterface::TRANSITION_IMMEDIATE);
}

如果要隐藏光标,则调用PointerController::fade()。默认情况下,在鼠标无操作几秒后光标会自动消失。

全志遥控器鼠标模式

按鼠标模式键时,调用了TVWindowManager.java interceptKeyBeforeDispatching():

                if(mKeyEnterMouseMode) {
    
    
                    try{
    
    
                        mWindowManager.keyExitMouseMode();
                        mKeyEnterMouseMode = false;
                    }
                } else {
    
    
                    try {
    
    
                        mWindowManager.keyEnterMouseMode();
                        mWindowManager.keySetMouseDistance(Settings.System.getInt(mContext.getContentResolver(), Settings.System.MOUSE_ADVANCE, 30));
                        mWindowManager.keySetMouseBtnCode(mLeftBtn, mMidBtn, mRightBtn);
                        mWindowManager.keySetMouseMoveCode(mLeft, mRight, mTop, mBottom);

                        mKeyEnterMouseMode = true;
                    }
                }

进入鼠标模式会调用keyEnterMouseMode等函数,而退出鼠标模式则调用keyExitMouseMode()。keyEnterMouseMode最终调用到Native层:

//support mouse mode
void InputReader::keyEnterMouseMode(){
    
    
    ALOGD("Enter mouse mode!");
    mKeyInMouseMode = true;
    ssize_t deviceIndex = mDevices.indexOfKey(mMouseDeviceId);
    if (deviceIndex < 0){
    
    
        ALOGW("Discarding event for unknown deviceId %d.", mMouseDeviceId);
        return;
    }
    InputDevice* device = mDevices.valueAt(deviceIndex);
    if (device->isIgnored()){
    
    
        return;
    }
}

接下来如果按遥控器方向键,则在InputReader::processEventsLocked()–>convertEvent()转换为鼠标按键:



//support mouse mode
void InputReader::convertEvent(const RawEvent* rawEvents,size_t count) {
    
    
    RawEvent *tmpRawEvent = mConvertEventBuffer;

    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++,tmpRawEvent++){
    
    
        tmpRawEvent->deviceId   = rawEvent->deviceId;
        tmpRawEvent->code       = rawEvent->code;
        tmpRawEvent->type       = rawEvent->type;
        tmpRawEvent->value      = rawEvent->value;
        tmpRawEvent->when       = rawEvent->when;

        if(mKeyInMouseMode){
    
    
            if(true){
    
    //tmpRawEvent->deviceId == mKeyDeviceId
                if(rawEvent->type == EV_KEY) {
    
    
                    if(rawEvent->code == mLeft && rawEvent->value != 0) {
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;
                        tmpRawEvent->type      = EV_REL;
                        tmpRawEvent->code      = REL_X;
                        tmpRawEvent->value     = -mDistance;

                        mKeySynced             = false;
                    }else if(rawEvent->code == mRight && rawEvent->value != 0){
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;
                        tmpRawEvent->type      = EV_REL;
                        tmpRawEvent->code      = REL_X;
                        tmpRawEvent->value     = mDistance;

                        mKeySynced             = false;
                    }else if(rawEvent->code == mTop && rawEvent->value != 0){
    
    
                        tmpRawEvent->deviceId   = mMouseDeviceId;
                        tmpRawEvent->type      = EV_REL;
                        tmpRawEvent->code      = REL_Y;
                        tmpRawEvent->value     = -mDistance;

                        mKeySynced             = false;
                    } else if(rawEvent->code == mBottom && rawEvent->value != 0){
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;
                        tmpRawEvent->type      = EV_REL;
                        tmpRawEvent->code  = REL_Y;
                        tmpRawEvent->value     = mDistance;

                        mKeySynced             = false;
                    } else if(rawEvent->code == mLeftBtn){
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;
                        tmpRawEvent->type      = EV_KEY;
                        tmpRawEvent->code  = BTN_LEFT;

                        mKeySynced             = false;
                    } else if(rawEvent->code == mMidBtn){
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;
                        tmpRawEvent->type      = EV_KEY;
                        tmpRawEvent->code  = BTN_MIDDLE;

                        mKeySynced             = false;
                    } else if(rawEvent->code == mRightBtn){
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;
                        tmpRawEvent->type      = EV_KEY;
                        tmpRawEvent->code  = BTN_RIGHT;

                        mKeySynced             = false;
                    }
                } else if(rawEvent->type == EV_SYN){
    
    
                    if(mKeySynced == false){
    
    
                        tmpRawEvent->deviceId  = mMouseDeviceId;

                        mKeySynced = true;
                    }
                }
            }
        }
    }
}

如上重新封装一个RawEvent,其中DeviceId设置为Mouse,之后RawEvent将被CursorInputMapper处理。

猜你喜欢

转载自blog.csdn.net/suwen8100/article/details/117040096
今日推荐