Nous écrivons un pilote pour un ordinateur portable pour le plaisir et le profit, ou comment s'engager dans le noyau même si vous êtes un imbécile

Comment tout a commencé


Commençons par poser le problème. Éléments fournis: un ordinateur portable. Nouvel ordinateur portable, jeux. Avec rétro-éclairage RVB. Voici un ordinateur portable comme celui-ci:

image
Image prise à partir de lenovo.com

Il existe également un programme pour cet ordinateur portable. Le programme contrôle simplement ce rétro-éclairage.

Le seul problème est le programme pour Windows, mais je veux que tout fonctionne dans votre Linux préféré. Et les ampoules pour briller, et pour que de belles couleurs scintillent. Oui, c'est juste comment faire, de sorte que sans ingénierie inverse et sans écrire vos pilotes? La réponse simple est venue rapidement - aucun moyen. Eh bien, allons écrire un pilote.

Étape 1 - Plonger dans le code


Nous avons trois endroits à partir desquels vous pouvez voir comment le rétro-éclairage clignote. Par ordre de difficulté croissante:

1. Un grand programme de jeu gonflé Lenovo Nerve Center - dans lequel il y a une fonction pour configurer tout ce rétro-éclairage.

2. La combinaison des raccourcis clavier Fn + Space est possible. il est traité par le même programme.

3. BIOS. Pendant le chargement de l'ordinateur portable, le rétroéclairage scintille également - mais uniquement en rouge et seulement pendant une seconde.

Pour l'avenir, je dirai que je devais essayer les trois, mais je n'ai progressé avec un certain succès que le premier. Nous allons parler d'elle.

Eh bien, ouvrez le dossier du programme:

dossier

Nous remarquons immédiatement qu'il existe une DLL avec un nom intéressant - LedSettingsPlugin.dll. La nôtre est-elle ...? Ouvrons dans IDA Pro et jetons un œil.

moitié droite

Faites attention à la moitié droite de l'écran. Il y a beaucoup d'informations laissées par les programmeurs - nous les utiliserons. Nous voyons que pour une raison quelconque, il existe de nombreuses lignes similaires aux noms de méthode. Pourquoi?

nom-de-fonction

Et ce sont les noms des méthodes. Comme c'est pratique! Disons ce que nous pouvons avec nos propres noms, et regardons à nouveau la liste des fonctions. Pour nommer dans l'IDA, vous pouvez utiliser le raccourci clavier N, ou simplement cliquer avec le bouton droit sur ce que nous voulons appeler.

setledstatusex

Nous regardons les fonctions ... Y720LedSetHelper :: SetLEDStatusEx. On dirait que nous devons! Nous remarquons que quelque chose comme une chaîne est formée ici, puis passée à un certain CHidDevHelper :: HidRequestsByPath. Plus précisément intéressé par var_38, toutes les métamorphoses dont l'IDA nous a gentiment désigné.

Var_34 nous intéresse également. Il va juste après var_38 - dans la tradition d'assemblage, les variables sont stockées dans l'ordre inverse sous RSP. Var_34 n'est ici que le nom de la constante - -34h.

Nous obtenons qu'à partir de var_38 le programme met zéro, puis le style, la couleur, le numéro trois et le bloc sont la partie du clavier à laquelle cette couleur s'appliquera. (Pour l'avenir, je dirai que trois est la valeur de luminosité ici. Après l'avoir rendu gérable, nous obtenons le pilote encore plus cool que l'original!)

Entrons dans HidRequestsByPath et découvrons enfin comment cela se passe.

devhelper

Nous voyons deux fonctions, HidD_GetFeature et HidD_SetFeature. Les deux dans le fichier ne sont pas tracés ... Mais ils sont très bien tracés dans la documentation officielle de Microsoft - ici et ici .

Vous pouvez vous en féliciter - nous y sommes arrivés. C'est le fond, pas besoin de creuser plus profondément. Sous Linux, il existe de telles fonctions - il suffit de les appeler avec les mêmes arguments, et tout devrait fonctionner ... est-ce vrai?

Étape 2 - lancer le prototype ...?


Pas vraiment. Commençons simplement et exécutons lsusb. Nous trouvons donc le clavier et lui envoyons quelque chose.

lsusb

Integrated Technology Express, Inc. semble le plus intéressant ici. Nous utiliserons le fameux outil / dev / hidraw. Nous trouvons le bon ... Cela se fait par une simple recherche dans les fichiers / sys / class / hidraw / hidraw * / device / uevent.

cacher

En voici un. Les chiffres sont les mêmes - cela signifie que cet appareil est hidraw0. Mais nous essayons d'envoyer des données, et rien ne se passe! Une sorte de non-sens. À ce stade, les mains commencent à tomber ... Peut-être, pas pour les simples mortels, est-ce cette ingénierie inverse?

Mais continuons. Nous allons essayer. Si l'auteur comprenait tout cela, il inverserait la recherche de notre chauffeur du même centre nerveux ... Mais nous n'avons pas de cerveau. Revenons à Windows, il y a une idée.

Il y a une telle chose dans Windows - Gestionnaire de périphériques. Cela vous permet de faire beaucoup de choses - nous sommes intéressés par le fait qu'il vous permet de couper des appareils. Simple et sans compromis.

Coupons les appareils un par un jusqu'à ce que l'état des ampoules cesse de changer.

désactiver l'appareil

Celui-ci a été coupé. Donc, si vous regardez l'ID du matériel, nous verrons quel est son nom et avec quoi il mange.

notre-appareil

Nous regardons - c'est lui.

dmesg

Un appareil que j'inonde depuis plusieurs années à Dmesg.

[Pourquoi n'est-il pas apparu dans lsusb? Et pas du tout USB. Il utilise le protocole I2C HID, qui vous permet de cacher les appareils des mains curieuses des artisans pour installer des gadgets HID sur le bus de l'ordinateur lui-même.]

Digression lyrique - engageons-nous


À la recherche du bon appareil, j'ai repris mon installation presque jusqu'au noyau. De plus, je n'aimais pas vraiment ce que j'ai montré cette feuille de dmesg avant chaque verrou. Puisque je suis ici, pourquoi ne pas écrire un court commit? Les mains me démangent quand même.

Ce que nous devons voir, c'est où se trouvent les appareils sur I2C HID, et où écrire les bizarreries qui leur sont inhérentes. Ici. Sans plus tarder, écoutons l'erreur - longueur d'entrée incorrecte. Rendons-le correct.

mauvaise taille d'entrée

Ajoutez une nouvelle bizarrerie, appelons-la I2C_HID_QUIRK_BAD_INPUT_SIZE. Par analogie avec celles existantes.

bizarrerie

Ajoutez notre appareil à la liste des quirkut. Ce que nous avons fait jusqu'à présent:

1. Recherchez sur Internet «i2c hid linux kernel». Cliquez sur la quatrième réponse à DuckDuckGo.

2. A écrit trois (!) Mots en anglais - BAD_INPUT_SIZE

3. Ajout d'un au BIT (4). Il s'est avéré BIT (5).

4. Nous avons ajouté un numéro dans hid-ids.h - l'ID de notre appareil (non indiqué dans l'illustration, mais il est également approximatif).

Programmons maintenant.

Nous voyons la ligne - `ret_size = ihid-> inbuf [0] | ihid-> inbuf [1] << 8; `

Et puis il se plaint que ret_size n'est pas égal à ce qu'il veut.

Que si le queer est impliqué, faites la même chose, bien au contraire.

si-condition

Nous envoyons le patch à la newsletter, sans oublier de tester ... (pour être honnête, il a juste fallu plus pour l'ajouter à la newsletter du cerveau. Ce n'est pas facile.)

appliqué

Et c'est tout.

Étape 3 - le conducteur!


Ensuite, je me suis souvenu - oh oui, vous devez encore écrire un pilote. J'ai décidé de ne pas encore le confier au noyau (des questions ont commencé à y être posées, j'ai vraiment dû réfléchir. Si l'un des citoyens de Habrovsk peut m'aider à me conseiller, écrivez-moi - je serai heureux!)

Ouvrez le python. (Au début, bash l'était, mais j'ai changé d'avis très rapidement.) Nous allons utiliser le fameux outil / dev / hidraw.

/ dev / hidraw0, / dev / hidraw1 - comment fonctionnent ces fichiers? Pour les E / S simples, ils peuvent être utilisés comme n'importe quel fichier normal et cela fonctionnera. Mais GetFeature et SetFeature doivent bricoler avec ...

StackOverflow (ou quelqu'un d'autre, je ne me souviens pas déjà) a suggéré qu'il avait besoin d'un peu d'ioctl. Il s'agit d'une méthode spéciale pour travailler avec des fichiers inhabituels tels que des périphériques HID, des terminaux, etc.

Ioctl fonctionne comme ça. Vous lui donnez un descripteur de fichier ouvert (qui s'intéresse à ce que c'est, il y a un lien vers Wikipedia ), un certain nombre et un tampon - après quoi il fait quelque chose avec ce tampon et le renvoie. Je n'exagère pas, il y a beaucoup de choses qui dépendent de l'implémentation. Permettez-moi de vous donner un exemple: 0xC0114806, ou déjà familier pour nous SetFeature. C'est

(6 << 29) | (ord('H') << 8) | (0x06 << 0) | (0x11 << 16).

Les 6 premiers ici signifient que le fichier sera ouvert pour l'écriture et la lecture. Pourquoi la lecture n'est pas très claire - mais il est écrit pour le faire, probablement. Ord ('H') ici - HID abrégé. Peut-être que d'autres choses signifient, selon le fichier. Dans ce cas, le HID.
0x06 - l'équipe elle-même. La sixième équipe avec HID est SetFeature. La dernière partie est la longueur du tampon.

Il ne reste plus qu'à appeler ioctl avec ces valeurs - et la sortie est le pilote. Il travaille .

Postface


J'espère que c'était intéressant à lire. Peut-être même utile. Certains ont été omis ou abrégés - le lecteur clairvoyant, peut-être, découvrira la lecture de l'état dans le pilote, et un deuxième SetFeature, qui n'était pas du tout mentionné dans le texte. Le développement des pilotes et du noyau Linux sont de grandes choses, et ils ne peuvent pas être complètement maîtrisés en un seul vélo. L'article n'est probablement pas à ce sujet, mais sur le fait que faire quelque chose de petit et agréable, open-source ou pour vous-même, n'est pas du tout difficile. Il suffit de trouver une semaine de soirées avec du thé et une envie de se plonger dans le code.

Source: https://habr.com/ru/post/fr484564/


All Articles