Android 添加键值并上报从驱动到上层

平台 :RK3288

OS:Android7.1

kernel部分添加键值:

1.在dts中(kernel/arch/arm/boot/dts/rk3288-android.dtsi)添加键值属性,可以仿照power按键配置

wake-key {
			gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
			linux,code = <117>;
			pinctrl-names = "default";
			pinctrl-0 = <&pmic_int>;
			label = "wake";
			gpio-key,wakeup;
};

因我们使用的键值操作是通过gpio触发的,则配置成gpio-key。
linux,code 键码可以查看内核自定义键码来选择。定义在kernel/include/uapi/linux/input-event-codes.h下。

/*
 * Event types
 */
 
#define EV_SYN			0x00
#define EV_KEY			0x01
#define EV_REL			0x02
#define EV_ABS			0x03
#define EV_MSC			0x04
#define EV_SW			0x05
#define EV_LED			0x11
#define EV_SND			0x12
#define EV_REP			0x14
#define EV_FF			0x15
#define EV_PWR			0x16
#define EV_FF_STATUS		0x17
#define EV_MAX			0x1f
#define EV_CNT			(EV_MAX+1)

/*
 * Keys and buttons
 *
 * Most of the keys/buttons are modeled after USB HUT 1.12
 * (see http://www.usb.org/developers/hidpage).
 * Abbreviations in the comments:
 * AC - Application Control
 * AL - Application Launch Button
 * SC - System Control
 */
#define KEY_RIGHTALT		100
#define KEY_LINEFEED		101
#define KEY_HOME		102
#define KEY_UP			103
#define KEY_PAGEUP		104
#define KEY_LEFT		105
#define KEY_RIGHT		106
#define KEY_END			107
#define KEY_DOWN		108
#define KEY_PAGEDOWN		109
#define KEY_INSERT		110
#define KEY_DELETE		111
#define KEY_MACRO		112
#define KEY_MUTE		113
#define KEY_VOLUMEDOWN		114
#define KEY_VOLUMEUP		115
#define KEY_POWER		116	/* SC System Power Down */
#define KEY_KPEQUAL		117
#define KEY_KPPLUSMINUS		118
#define KEY_PAUSE		119
#define KEY_SCALE		120	/* AL Compiz Scale (Expose) */

#define KEY_KPCOMMA		121
#define KEY_HANGEUL		122
#define KEY_HANGUEL		KEY_HANGEUL
#define KEY_HANJA		123
#define KEY_YEN			124
#define KEY_LEFTMETA		125
#define KEY_RIGHTMETA		126
#define KEY_COMPOSE		127

#define KEY_STOP		128	/* AC Stop */
#define KEY_AGAIN		129
#define KEY_PROPS		130	/* AC Properties */
#define KEY_UNDO		131	/* AC Undo */
#define KEY_FRONT		132
#define KEY_COPY		133	/* AC Copy */
#define KEY_OPEN		134	/* AC Open */
#define KEY_PASTE		135	/* AC Paste */
#define KEY_FIND		136	/* AC Search */
#define KEY_CUT			137	/* AC Cut */
#define KEY_HELP		138	/* AL Integrated Help Center */
#define KEY_MENU		139	/* Menu (show menu) */
#define KEY_CALC		140	/* AL Calculator */
#define KEY_SETUP		141
#define KEY_SLEEP		142	/* SC System Sleep */
#define KEY_WAKEUP		143	/* System Wake Up */
#define KEY_FILE		144	/* AL Local Machine Browser */
#define KEY_SENDFILE		145
#define KEY_DELETEFILE		146
#define KEY_XFER		147
#define KEY_PROG1		148
#define KEY_PROG2		149
#define KEY_WWW			150	/* AL Internet Browser */
#define KEY_MSDOS		151
#define KEY_COFFEE		152	/* AL Terminal Lock/Screensaver */
#define KEY_SCREENLOCK		KEY_COFFEE
#define KEY_ROTATE_DISPLAY	153	/* Display orientation for e.g. tablets */
#define KEY_DIRECTION		KEY_ROTATE_DISPLAY
#define KEY_CYCLEWINDOWS	154
#define KEY_MAIL		155
#define KEY_BOOKMARKS		156	/* AC Bookmarks */
#define KEY_COMPUTER		157
#define KEY_BACK		158	/* AC Back */
#define KEY_FORWARD		159	/* AC Forward */
#define KEY_CLOSECD		160
#define KEY_EJECTCD		161
#define KEY_EJECTCLOSECD	162
#define KEY_NEXTSONG		163
#define KEY_PLAYPAUSE		164
#define KEY_PREVIOUSSONG	165
#define KEY_STOPCD		166
#define KEY_RECORD		167
#define KEY_REWIND		168
#define KEY_PHONE		169	/* Media Select Telephone */
#define KEY_ISO			170
#define KEY_CONFIG		171	/* AL Consumer Control Configuration */
#define KEY_HOMEPAGE		172	/* AC Home */
#define KEY_REFRESH		173	/* AC Refresh */
#define KEY_EXIT		174	/* AC Exit */

因键值较多,就只列一部分出来,在定义键码的时候,注意不要与现正在使用的键码重复。如不确认哪些键码是已经使用的,可以在该文件中添加自定义键码。
在dts中添加键值属性后,需要在驱动(我的是在/kernel/drivers/input/keyboard/rk_reys.c)里,做dts解析:

	/* parse info from dt */
	ddata->nbuttons = key_num;
	error = rk_keys_parse_dt(ddata, pdev);
	if (error)
		goto fail0;

如该按键需要以中断的方式触发,则可以为这个按键申请中断:

error =devm_request_irq(dev, irq,  keys_isr1,
						IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,
							button->desc ? button->desc:"wake",button);
键值上报:

1.注册input事件:
通过input_register_device()函数来向内核注册input事件。
2.input事件上报:
input事件上报是通过input_event()input_report_key()函数上报。

input_event()函数简介:
函数原型:

void input_event(struct input_dev *dev,
		 unsigned int type, unsigned int code, int value)
{ 
		unsigned long flags; 
		if (is_event_supported(type, dev->evbit, EV_MAX)) 
		{
			spin_lock_irqsave(&dev->event_lock, flags); 
			add_input_randomness(type, code, value); 
			input_handle_event(dev, type, code, value);
			spin_unlock_irqrestore(&dev->event_lock, flags); 
		} 
} 
EXPORT_SYMBOL(input_event);		 

参数介绍:
struct input_dev *dev:需要上报的事件
unsigned int type:上报的事件类型(在前面的input-event-codes.h文件中有定义)
unsigned int code:上报的键码
int value :上报的键值

使用实例:

static irqreturn_t keys_isr1(int irq, void *dev_id)
{
        struct rk_keys_button *button = (struct rk_keys_button *)dev_id;
        struct rk_keys_drvdata *pdata = dev_get_drvdata(button->dev);
        struct input_dev *input = pdata->input;
        int irq_status = gpio_get_value(14);

        if (0==irq_status){     //插入就触发中断,,拔出来也触发中断。
                input_event(input, EV_KEY, 118, 1);
                input_sync(input);
                udelay(50);
                input_event(input, EV_KEY, 118, 0);
                input_sync(input);
        }
        else if (1==irq_status){
                input_event(input, EV_KEY, 117, 1);
                input_sync(input);
                udelay(50);
                input_event(input, EV_KEY, 117, 0);
                input_sync(input);
        }

        return IRQ_HANDLED;
}

注意:input_event()上报按键事件必须先上报1(意为按下),再上报0(意为弹起),不能单独上报1,或者上报0。

kernel部分添加完成后,可通过getevent命令来确认事件有无上报成功。

内核部分确认调试成功后,需要将键值上报至上层:
1.修改按键布局映射文件,都是以.kl结尾的文件,可通过
cat /proc/bus/input/devices 命令来查看我们系统中的input device信息,系统通过vendor id product id 或者device name 来匹配布局文件,也可通过dumpsys input去获取目前正在使用的布局文件。
我使用的是/device/rockchip/common/rk29-keypad.kl布局文件

key 59    MENU
key 102   HOME
key 114   VOLUME_DOWN
key 115   VOLUME_UP
key 116   POWER
key 143   NOTIFICATION
key 158   BACK
key 212   CAMERA
key 217   SEARCH

在这后面添加key 117 F1 则表示内核上报的117键值映射到系统的键值为F1
系统的键值定义在frameworks/base/core/java/android/view/KeyEvent.java下。

添加完成后可以在frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java里添加打印信息,查看键值是否上报成功。

public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
        final boolean keyguardOn = keyguardOn();
        final int keyCode = event.getKeyCode();
        final int repeatCount = event.getRepeatCount();
        final int metaState = event.getMetaState();
        final int flags = event.getFlags();
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final boolean canceled = event.isCanceled();

        if (DEBUG_INPUT) {
            Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
                    + " canceled=" + canceled);
        }

上层APK可通过调用frameworks/base/core/java/android/view/KeyEvent.java中的接口去拦截键值

public interface Callback {
        boolean onKeyDown(int keyCode, KeyEvent event);

        boolean onKeyLongPress(int keyCode, KeyEvent event);

        boolean onKeyUp(int keyCode, KeyEvent event);
        
        boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
}
  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
这个问题比较复杂,需要分步骤来回答。下面是大致的流程和代码: 1. 添加键值Android 系统添加键值需要修改内核代码。在内核找到 keyboard.h 文件,添加一个键值,例如: ``` #define KEY_F1 59 ``` 2. 修改驱动 修改键盘驱动程序来处理新添加键值。在驱动程序找到处理键盘输入的函数,通常是 input_event 函数。在该函数添加对新键值的处理,例如: ``` static void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { if (code == KEY_F1) { // 处理 F1 按键 } // 处理其他按键 } ``` 3. 上报按键事件到用户空间 在驱动程序上报键值的按键事件到用户空间。在 input_event 函数,使用 input_report_key 函数上报按键事件: ``` static void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { if (code == KEY_F1) { input_report_key(dev, code, value); input_sync(dev); } // 处理其他按键 } ``` 4. 注册输入设备 在驱动程序注册输入设备。在驱动程序的 probe 函数注册输入设备,例如: ``` static int keyboard_probe(struct platform_device *pdev) { struct input_dev *input_dev; int err; input_dev = input_allocate_device(); if (!input_dev) { dev_err(&pdev->dev, "input_allocate_device failed\n"); return -ENOMEM; } input_dev->name = "My Keyboard"; input_dev->phys = "mykeyboard/input0"; input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; set_bit(EV_KEY, input_dev->evbit); set_bit(KEY_F1, input_dev->keybit); err = input_register_device(input_dev); if (err) { dev_err(&pdev->dev, "input_register_device failed\n"); input_free_device(input_dev); return err; } platform_set_drvdata(pdev, input_dev); return 0; } ``` 5. 编译内核并安装 编译内核并安装到 Android 系统。 6. 测试 使用 Android 系统的输入法或其他应用程序测试新添加键值是否能够被识别。例如,在文本编辑器按下 F1 按键,应该能够输入字符或执行相应的操作。 以上是大致的流程和代码示例,具体实现可能需要根据具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值