关键字

rk3568、音量、按键、volume、key

rk3568中音量键设备节点:

/dev/input/event2
/sys/class/input/input2

设备树文件配置

有三处相关配置,且都生成有相关设备节点,但调节音量实际用的是adc-keys(由于内核要打很多补丁,当前展示out目录下打完补丁后的文件):

img

img

img

驱动文件

驱动文件位置(由于可能打补丁,展示的out目录下路径,如果需要源码路径按文件名搜索即可):
out/kernel/src_tmp/linux-5.10/drivers/input/keyboard/adc-keys.c

初始化:

static int adc_keys_probe(struct platform_device *pdev)
{
    // 设置输入设备input的属性等
    ... ...

    error = input_setup_polling(input, adc_keys_poll);  // 设置轮询函数
    if (error) {
        dev_err(dev, "Unable to set up polling: %d\n", error);
        return error;
    }

    if (!device_property_read_u32(dev, "poll-interval", &value)) // 设置轮询间隔 100ms, dtsi文件中有配置“poll-interval = <100>;”
        input_set_poll_interval(input, value);

    error = input_register_device(input); // 注册输入设备
    if (error) {
        dev_err(dev, "Unable to register input device: %d\n", error);
        return error;
    }

    return 0;
}

轮询函数

static void adc_keys_poll(struct input_dev *input) // 100ms循环一次
{
    struct adc_keys_state *st = input_get_drvdata(input);
    int i, value, ret;
    u32 diff, closest = 0xffffffff;
    int keycode = 0;

    ret = iio_read_channel_processed(st->channel, &value);
    if (unlikely(ret < 0)) {
        /* Forcibly release key if any was pressed */
        value = st->keyup_voltage;
    } else {
        for (i = 0; i < st->num_keys; i++) {
            diff = abs(st->map[i].voltage - value);
            if (diff < closest) {
                closest = diff;
                keycode = st->map[i].keycode;
            }
        }
    }

    if (abs(st->keyup_voltage - value) < closest)
        keycode = 0;

    if (st->last_key && st->last_key != keycode)
        input_report_key(input, st->last_key, 0); // 检测到按键事件后上报按键事件

    if (keycode)
        input_report_key(input, keycode, 1);

    input_sync(input);
    st->last_key = keycode;
}

上报按键事件后,工作流程和电源键类似,由多模接收到按键事件后,传递给订阅此事件的模块,如音频,适配模块等可以订阅此事件,然后调用音量接口调节音量

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐