キーワード
dtsi、gpio、キー、入力サブシステム、イベント分析、長押しキー検出
gpio_keysの説明
キーは組み込み開発で一般的に使用されるものであり、成熟したメカニズムがLinuxカーネルで作成されています。
Linuxカーネルの下のdrivers / input / keyboard / gpio_keys.cは、アーキテクチャに依存しないGPIOキードライバーを実装します。このキードライバーを使用するには、対応するデバイスツリーで関連データを定義するだけです。ドライブの実装は非常に単純ですが、独立したキードライブの実装により適しています。
gpio-keysは、入力アーキテクチャに基づく汎用GPIOキードライバーです。ドライバーは、Linuxデバイスドライバーモデルのアイデアに沿って、ドライバーとデバイスの分離を実現するplatform_driverアーキテクチャに基づいています。プロジェクトのキードライバーは通常、gpio-keysに基づいて記述されているため、gpio_keysを分析する必要があります。
ここでは、長押し検出をサポートするためにアプリケーション層で処理しました(私のプログラムは長押し6S印刷に設定されています)。ドライバー層でデバウンス時間を変更しようとしたところ、効果が非常に悪かったため、あきらめました。
dtsiデバイスツリーの実装
- デバイスツリーの実装はほとんど同じですが、必要なパラメーターを入力するだけです。
gpio_keys {
compatible = "gpio-keys";
label = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&key_recovery_default>;
recovery {
label = "recovery";
gpios = <&tlmm 23 GPIO_ACTIVE_HIGH>;
linux,input-type = <1>;
linux,code = <115>;
/*这三项根据需求添加*/
gpio-key,wakeup;
debounce-interval = <15>;
linux,can-disable;
};
};
1.ノード名は「gpio-keys」です。
2. gpio-keysノードの互換属性値を「gpio-keys」に設定する必要があります。
3.すべてのKEYはgpio-keysの子ノードであり、各子ノードは次の属性で自身を記述することができます。
gpios:KEYで接続されたGPIO情報。
割り込み:KEYで使用されるGPIO割り込み情報は必要ありません。書き込むことはできません。
ラベル:キー名
Linux、コード:シミュレートするKEYキー
gpio-key、wakeup:ウェイクアップできます
debounce-interval:デバウンス時間
- その他の分野
1.ボタンがダブルクリックをサポートする必要がある場合は、オートリピートを追加します
シンプルなドライバー分析
これは標準のプラットフォームドライバーフレームワークです。デバイスツリーを使用してKEYデバイス情報を記述する場合は、デバイスノードの互換性のある属性値を「gpio-keys」に設定する必要があります。デバイスとドライバーが一致すると、gpio_keys_probe関数が実行されます
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.driver = {
.name = "gpio-keys",
.pm = &gpio_keys_pm_ops,
.of_match_table = gpio_keys_of_match,
}
};
デバイスツリー分析、デバイスツリーからKEYに関連するデバイスノード情報を取得
static int gpio_keys_probe(struct platform_device *pdev)
{
if (!pdata) {
pdata = gpio_keys_get_devtree_pdata(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
}
}
読み取りイベントを表示
- イベントを表示
ls -l / dev / input
- ファイルの内容を表示する
hexdump / dev / input / event0
アプリケーション層の解析キー値
#define RECOVERY_KEY "/dev/input/event2"
#define RECOVERY_KEY_CODE 115
#define RECOVERY_KEY_PRESS 0
void recovery_key_press_timer(int sig)
{
if(SIGALRM == sig)
{
printf("alarm 6s.\n");
}
return;
}
static void read_recovery_key_event()
{
int fd = -1, ret = -1;
struct input_event ev;
fd = open(RECOVERY_KEY, O_RDONLY);
if (fd < 0)
{
printf("open RECOVERY_KEY event failed.\n");
return;
}
memset(&ev, 0, sizeof(struct input_event));
ret = read(fd, &ev, sizeof(struct input_event));
if (ret != sizeof(struct input_event))
{
printf("read RECOVERY_KEY event failed.\n");
close(fd);
}
if( (RECOVERY_KEY_CODE == ev.code) && (RECOVERY_KEY_PRESS == ev.value) )
{
printf("recovery-key press.\n");
alarm(6);
}
else
{
printf("recovery-key release.\n");
alarm(0);
}
close(fd);
}
int main(int argc, char **argv)
{
int rc = 0;
signal(SIGALRM, recovery_key_press_timer);
while(1)
{
read_recovery_key_event();
}
return 0;
}