Répertoire d'articles
1 Linux est livré avec le code source du pilote de bouton
Le pilote de bouton est également intégré au noyau Linux. Si vous souhaitez l'utiliser, vous devez le configurer dans le noyau. Recherchez la configuration correspondante en suivant le chemin suivant:
Device Drivers --->
Input device support --->
[*] Keyboards --->
<*> GPIO Buttons
Sélectionnez l'option "GPIO Buttons", et le pilote sera compilé dans le noyau Linux, comme illustré dans la figure 1.1:
Après l'enregistrement et la sortie, "CONFIG_KEYBOARD_GPIO = y" apparaîtra sous le fichier .congfig.
Le chemin du pilote de bouton intégré drivers / input / keyboard / gpio_keys.c dans le noyau Linux, le pilote de bouton est basé sur le cadre de la plate-forme et utilise le sous-système d'entrée pour implémenter des fonctions.
Une partie du code du fichier gpio_keys.c est la suivante:
673 static const struct of_device_id gpio_keys_of_match[] = {
674 {
.compatible = "gpio-keys", },
675 {
},
676 };
......
842 static struct platform_driver gpio_keys_device_driver = {
843 .probe = gpio_keys_probe,
844 .remove = gpio_keys_remove,
845 .driver = {
846 .name = "gpio-keys",
847 .pm = &gpio_keys_pm_ops,
848 .of_match_table = of_match_ptr(gpio_keys_of_match),
849 }
850 };
851
852 static int __init gpio_keys_init(void)
853 {
854 return platform_driver_register(&gpio_keys_device_driver);
855 }
856
857 static void __exit gpio_keys_exit(void)
858 {
859 platform_driver_unregister(&gpio_keys_device_driver);
860 }
Comme le montre le code ci-dessus, il s'agit d'une structure de trame de plate-forme typique. Lorsque le périphérique est correctement mis en correspondance, la fonction gpio_keys_probe sera exécutée. Voyons ce qui est implémenté dans la fonction gpio_keys_probe:
689 static int gpio_keys_probe(struct platform_device *pdev)
690 {
691 struct device *dev = &pdev->dev;
692 const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
693 struct gpio_keys_drvdata *ddata;
694 struct input_dev *input;
695 size_t size;
696 int i, error;
697 int wakeup = 0;
698
699 if (!pdata) {
700 pdata = gpio_keys_get_devtree_pdata(dev);
701 if (IS_ERR(pdata))
702 return PTR_ERR(pdata);
703 }
......
713 input = devm_input_allocate_device(dev);
714 if (!input) {
715 dev_err(dev, "failed to allocate input device\n");
716 return -ENOMEM;
717 }
718
719 ddata->pdata = pdata;
720 ddata->input = input;
721 mutex_init(&ddata->disable_lock);
722
723 platform_set_drvdata(pdev, ddata);
724 input_set_drvdata(input, ddata);
725
726 input->name = pdata->name ? : pdev->name;
727 input->phys = "gpio-keys/input0";
728 input->dev.parent = &pdev->dev;
729 input->open = gpio_keys_open;
730 input->close = gpio_keys_close;
731
732 input->id.bustype = BUS_HOST;
733 input->id.vendor = 0x0001;
734 input->id.product = 0x0001;
735 input->id.version = 0x0100;
736
737 /* Enable auto repeat feature of Linux input subsystem */
738 if (pdata->rep)
739 __set_bit(EV_REP, input->evbit);
740
741 for (i = 0; i < pdata->nbuttons; i++) {
742 const struct gpio_keys_button *button = &pdata->buttons[i];
743 struct gpio_button_data *bdata = &ddata->data[i];
744
745 error = gpio_keys_setup_key(pdev, input, bdata, button);
746 if (error)
747 return error;
748
749 if (button->wakeup)
750 wakeup = 1;
751 }
......
760 error = input_register_device(input);
761 if (error) {
762 dev_err(dev, "Unable to register input device, error: %d\n",
763 error);
764 goto err_remove_group;
765 }
......
774 }
À la ligne 700, appelez la fonction gpio_keys_get_devtree_pdata pour obtenir les informations relatives au nœud de périphérique KEY à partir de l'arborescence des périphériques.
À la ligne 713, utilisez la fonction devm_input_allocate_device pour postuler à input_dev.
726 ~ 735, initialisez input_dev.
Ligne 739, définissez l'événement input_dev, voici l'événement EV_REP.
Sur la ligne 745, appelez la fonction gpio_keys_setup_key pour continuer à définir la clé. Cette fonction définira le code d'événement EV_KEY de input_dev (c'est-à-dire, quelle clé est simulée par KEY).
Sur la ligne 760, appelez la fonction input_register_device pour enregistrer input_dev avec le système Linux.
Regardons à nouveau le contenu de la fonction gpio_keys_setup_key:
437 static int gpio_keys_setup_key(struct platform_device *pdev,
438 struct input_dev *input,
439 struct gpio_button_data *bdata,
440 const struct gpio_keys_button *button)
441 {
442 const char *desc = button->desc ? button->desc : "gpio_keys";
443 struct device *dev = &pdev->dev;
444 irq_handler_t isr;
445 unsigned long irqflags;
446 int irq;
447 int error;
448
449 bdata->input = input;
450 bdata->button = button;
451 spin_lock_init(&bdata->lock);
452
453 if (gpio_is_valid(button->gpio)) {
454
455 error = devm_gpio_request_one(&pdev->dev, button->gpio,
456 GPIOF_IN, desc);
457 if (error < 0) {
458 dev_err(dev, "Failed to request GPIO %d, error %d\n",
459 button->gpio, error);
460 return error;
......
488 isr = gpio_keys_gpio_isr;
489 irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
490
491 } else {
492 if (!button->irq) {
493 dev_err(dev, "No IRQ specified\n");
494 return -EINVAL;
495 }
496 bdata->irq = button->irq;
......
506
507 isr = gpio_keys_irq_isr;
508 irqflags = 0;
509 }
510
511 input_set_capability(input, button->type ?: EV_KEY, button->code);
......
540 return 0;
541 }
À la ligne 511, appelez la fonction input_set_capability pour définir l'événement EV_KEY et le type de clé KEY, c'est-à-dire quelle clé est KEY utilisée? Nous allons définir la clé spécifiée comme quel bouton dans l'arborescence des périphériques.
Une fois que tout est prêt, il ne reste plus qu'à attendre que le bouton soit enfoncé, puis à signaler l'événement au noyau Linux. Le rapport d'événement se fait dans la fonction gpio_keys_irq_isr. Le contenu de cette fonction est le suivant:
392 static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
393 {
394 struct gpio_button_data *bdata = dev_id;
395 const struct gpio_keys_button *button = bdata->button;
396 struct input_dev *input = bdata->input;
397 unsigned long flags;
398
399 BUG_ON(irq != bdata->irq);
400
401 spin_lock_irqsave(&bdata->lock, flags);
402
403 if (!bdata->key_pressed) {
404 if (bdata->button->wakeup)
405 pm_wakeup_event(bdata->input->dev.parent, 0);
406
407 input_event(input, EV_KEY, button->code, 1);
408 input_sync(input);
409
410 if (!bdata->release_delay) {
411 input_event(input, EV_KEY, button->code, 0);
412 input_sync(input);
413 goto out;
414 }
415
416 bdata->key_pressed = true;
417 }
418
419 if (bdata->release_delay)
420 mod_timer(&bdata->release_timer,
421 jiffies + msecs_to_jiffies(bdata->release_delay));
422 out:
423 spin_unlock_irqrestore(&bdata->lock, flags);
424 return IRQ_HANDLED;
425 }
On peut voir que le fichier de pilote key_input.c que nous avons écrit avant est le même que le fichier de pilote fourni avec le noyau Linux. Ils appliquent et initialisent tous les deux la structure input_dev, définissent des événements, puis s'enregistrent auprès du noyau Linux. Enfin, l'événement et la valeur de l'événement sont signalés dans la fonction de traitement d'interruption de clé.
2 L'utilisation du pilote de bouton du noyau Linux
Il est également très simple d'utiliser le pilote de bouton intégré dans le noyau Linux. Il vous suffit d'ajouter le nœud de périphérique spécifié dans l'arborescence des périphériques. Pour plus de détails, reportez-vous à la documentation / devicetree / bindings / input / gpio-keys fichier .txt.
Il existe plusieurs exigences pour le contenu du nœud:
① Le nom du nœud est "gpio-keys".
② La valeur d'attribut compatible du nœud gpio-keys doit être définie sur "gpio-keys".
③ Toutes les KEY sont des nœuds enfants de gpio-keys, et chaque nœud enfant peut se décrire avec les attributs suivants:
gpios: informations GPIO connectées à KEY.
interruptions: informations d'interruption GPIO utilisées par KEY, elles ne sont pas nécessaires et ne peuvent pas être écrites.
label: KEY name
linux, code: KEY clés à simuler, c'est-à-dire ces clés dans l'exemple de code 58.1.2.4.
④ Ajoutez une répétition automatique si la touche prend en charge la double pression.
Ouvrez le fichier topeet_emmc_4_3.dts, conformément aux exigences ci-dessus, créez le nœud de périphérique du bouton, le contenu est le suivant:
1 gpio-keys {
2 compatible = "gpio-keys";
3 #address-cells = <1>;
4 #size-cells = <0>;
5 autorepeat;
6 key0 {
7 label = "GPIO Key Enter";
8 linux,code = <KEY_ENTER>;
9 gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
10 };
11 };
À la ligne 2, la valeur de l'attribut compatible doit être la même que le nom compatible dans le pilote.
À la ligne 5, la répétition automatique indique la prise en charge des pressions sur les touches.
Ligne 6 ~ 10, définissez les informations du bouton, définissez le nom de l'étiquette du bouton. Ligne 8, définissez la fonction du bouton, réglez le bouton sur la fonction KEY_ENTER, qui est la touche d'entrée. Enfin, la 9ème ligne définit la broche GPIO utilisée par le bouton.
Après avoir ajouté le nœud de périphérique du bouton dans l'arborescence des périphériques, recompilez le fichier de l'arborescence des périphériques, puis téléchargez à nouveau le fichier de l'arborescence des périphériques, démarrez le système Linux et vérifiez le répertoire / dev / input, comme illustré dans la Figure 2.1:
Vous pouvez voir que le fichier event1 a été généré. Ce fichier est le fichier de périphérique correspondant au bouton KEY0. Utilisez la commande hexdump pour afficher le fichier / dev / input / event1. La commande est la suivante:
hexdump /dev/input/event1
Appuyez ensuite sur le bouton KEY0 sur la carte de développement et le terminal afficheront le contenu suivant:
La sortie du terminal indique que le pilote de clé dans le noyau Linux fonctionne normalement. Si le terminal ne sort pas et qu'il n'y a pas de réponse à la pression de la touche, il peut y avoir les raisons suivantes:
① Activation ou non de la clé du noyau Linux chauffeur.
② Si le nœud gpio-keys dans l'arborescence des périphériques a été créé avec succès.
③ S'il y a d'autres périphériques dans l'arborescence des périphériques qui utilisent également le GPIO correspondant au bouton KEY, mais nous n'avons pas supprimé ces informations de périphérique.