博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
amlogic t972红外遥控功能器及飞鼠模式(附上RK和全志飞鼠模式)
阅读量:4165 次
发布时间:2019-05-26

本文共 19806 字,大约阅读时间需要 66 分钟。

驱动:

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
(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
(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 modevoid 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 modevoid 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处理。

转载地址:http://qmoxi.baihongyu.com/

你可能感兴趣的文章
进程间通信之:socket
查看>>
本地socket与网络socket实现
查看>>
linux中的find命令——查找文件名
查看>>
linux系统下 CP命令(备注:替换正在运行的进程,用FTP工具是从本地传是不行的,需要用cp -rf ../update/zb_terminal ./zb_terminal)
查看>>
linux进程运行的相关shell命令 fg、bg、jobs、&、ctrl + z(后台、前台等等)
查看>>
linux ls命令ls /dev | grep sda 什么意思(以及grep连接符|怎么用)
查看>>
system()、popen()
查看>>
linux mount (挂载命令)、umount (卸载命令)详解
查看>>
chmod命令详解使用格式和方法
查看>>
linux中的access函数
查看>>
chdir改变当前目录以及理解守护进程为何fork()两次?
查看>>
创建守护进程以及为什么fork两次
查看>>
open/close函数的使用
查看>>
C语言中lseek()函数和fseek()函数的使用详解
查看>>
linux 中 open和fopen的区别
查看>>
LINUX共享内存使用常见陷阱与分析
查看>>
Linux编程gcc编译器禁止所有警告和显示所有警告
查看>>
共享内存理解:shmget()函数、shmat()、IPC_CREAT | IPC_EXCL
查看>>
ctime函数--把日期和时间转换为字符串(打印时间时常用-LINUX系统)
查看>>
查看linux内核命令 ls /etc/rc.d -l
查看>>