[Beijing Xunwei] Expérimentation du sous-système i.MX6ULL Terminator Linux INPUT Linux est livré avec un pilote de bouton

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:
Insérez la description de l'image ici

Graphique 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:
Insérez la description de l'image ici

Graphique 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:
Insérez la description de l'image ici

Graphique 2.2

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.

Insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/BeiJingXunWei/article/details/112258428
conseillé
Classement