Como empezó todo
Comencemos planteando el problema. Dado: una computadora portátil. Nueva computadora portátil, juegos. Con retroiluminación RGB. Aquí hay una computadora portátil como esta:
Imagen tomada de lenovo.comTambién hay un programa para esta computadora portátil. El programa solo controla esta luz de fondo.
El único problema es el programa para Windows, pero quiero que todo funcione en su Linux favorito. Y bombillas para brillar, y para que los hermosos colores parpadearan. Sí, así es cómo hacerlo, de modo que sin ingeniería inversa y sin escribir sus controladores. La respuesta simple llegó rápidamente, de ninguna manera. Bueno, vamos a escribir un controlador.
Paso 1 - profundizando en el código
Tenemos tres lugares desde los cuales puede ver cómo parpadea la luz de fondo. En orden de dificultad creciente:
1. Un programa de juegos grande y dinámico Lenovo Nerve Center, en el que hay una función para configurar toda esta luz de fondo.
2. La combinación de las teclas de acceso rápido Fn + Space es posible. Es procesado por el mismo programa.
3. BIOS. Mientras se carga la computadora portátil, la luz de fondo también parpadea, pero solo en rojo y solo por un segundo.
Mirando hacia el futuro, diré que tuve que probar los tres, pero progresé con cierto éxito solo en el primero. Hablaremos de ella.
Bueno, abra la carpeta del programa:

Notamos de inmediato que hay una DLL con un nombre interesante: LedSettingsPlugin.dll. ¿Es el nuestro ...? Abramos en IDA Pro y echemos un vistazo.

Presta atención a la mitad derecha de la pantalla. Queda mucha información de los programadores, la usaremos. Vemos que por alguna razón hay muchas líneas similares a los nombres de métodos. Por qué

Y estos son los nombres de los métodos. ¡Qué conveniente! Digamos lo que podamos con nuestros propios nombres, y observemos nuevamente la lista de funciones. Para nombrar en la IDA, puede usar la tecla de acceso rápido N, o simplemente hacer clic derecho sobre lo que queremos llamar.

Nos fijamos en las funciones ... Y720LedSetHelper :: SetLEDStatusEx. ¡Parece que necesitamos hacerlo! Notamos que algo así como una cadena se forma aquí y luego se pasa a un cierto CHidDevHelper :: HidRequestsByPath. Específicamente interesado en var_38, todas las metamorfosis de las cuales la IDA nos designó amablemente.
Var_34 también es interesante para nosotros. Va justo después de var_38: en la tradición de ensamblaje, las variables se almacenan en orden inverso en RSP. Var_34 aquí es solo el nombre de la constante - -34h.
Obtenemos que a partir de var_38 el programa pone cero, luego el estilo, el color, el número tres y el bloque son la parte del teclado a la que se aplicará este color. (Mirando hacia el futuro, diré que tres es el valor de brillo aquí. Después de hacerlo manejable, ¡conseguimos que el controlador sea aún más genial que el original!)
Entremos en HidRequestsByPath y finalmente descubramos cómo va.

Vemos dos funciones, HidD_GetFeature y HidD_SetFeature. Ambos en el archivo no se rastrean ... Pero están muy bien rastreados en la documentación oficial de Microsoft,
aquí y
aquí .
Puedes felicitarte por esto: llegamos allí. Este es el fondo, no es necesario cavar más profundo. En Linux, existen tales funciones: solo necesita llamarlas con los mismos argumentos, y todo debería funcionar ... ¿es cierto?
Paso 2: ¿lanzar el prototipo ...?
En realidad no Comencemos simple y ejecute lsusb. Entonces encontramos el teclado y le enviamos algo.

Integrated Technology Express, Inc. Parece el más interesante aquí. Utilizaremos la famosa herramienta / dev / hidraw. Encontramos el correcto ... Esto se hace mediante una simple búsqueda en los archivos / sys / class / hidraw / hidraw * / device / uevent.

Aquí hay uno. Los números son los mismos, eso significa que este dispositivo es hidraw0. Pero estamos tratando de enviar datos, ¡y no pasa nada! Algún tipo de tontería. En esta etapa, las manos comienzan a caer ... Tal vez, no para simples mortales, ¿es esto ingeniería inversa?
Pero continuemos. Lo intentaremos Si el autor entendiera todo esto, revertiría la búsqueda de nuestro conductor en el mismo Nerve Center ... Pero no tenemos cerebro. Volvamos a Windows, hay una idea.
Hay tal cosa en Windows: Administrador de dispositivos. Le permite hacer mucho: nos interesa el hecho de que le permite cortar dispositivos. Simple e intransigente.
Cortemos los dispositivos uno por uno hasta que el estado de las bombillas deje de cambiar.

Este fue cortado. Entonces, si observa la ID de hardware, veremos cómo se llama y con qué come.

Lo miramos, es él.

Un dispositivo que he estado inundando durante varios años en dmesg.
[¿Por qué no apareció en lsusb? Y no USB en absoluto. Utiliza el protocolo I2C HID, que le permite
ocultar dispositivos de las manos curiosas de los artesanos para instalar dispositivos HID en el bus de la computadora.]
Digresión de lírica - comprometámonos
En busca del dispositivo correcto, recogí mi instalación casi en el núcleo. Además, no me gustó mucho lo que mostré esta hoja dmesg antes de cada bloqueo. Ya que estoy aquí, ¿por qué no escribir una confirmación breve? Las manos pican de todos modos.
Lo que necesitamos ver es dónde están los dispositivos en I2C HID y dónde escribir qué rarezas son inherentes a ellos.
Aquí Sin más preámbulos, escuchemos el error: longitud de entrada incorrecta. Hagámoslo correcto.

Agregue un nuevo capricho, nombremos I2C_HID_QUIRK_BAD_INPUT_SIZE. Por analogía con los existentes.

Agregue nuestro dispositivo a la lista quirkut. Lo que hemos hecho hasta ahora:
1. Busque en Internet “i2c hid linux kernel”. Hicimos clic en la cuarta respuesta a DuckDuckGo.
2. Escribió tres (!) Palabras en inglés - BAD_INPUT_SIZE
3. Se agregó uno a BIT (4). Resultó BIT (5).
4. Agregamos un número en hid-ids.h: la ID de nuestro dispositivo (no se muestra en la ilustración, pero allí también está aproximadamente).
Programemos ahora.
Vemos la línea - `ret_size = ihid-> inbuf [0] | ihid-> inbuf [1] << 8; `
Y luego se queja de que ret_size no es igual a lo que quiere.
Deje que si el extraño está involucrado, haga lo mismo, todo lo contrario.

Enviamos el parche a la lista de correo, sin olvidarnos de probar ... (para ser honesto, solo tomó más agregarlo al boletín del cerebro. No es fácil).

Y eso es todo.
Paso 3: ¡el conductor!
Entonces recordé: oh sí, todavía tienes que escribir un controlador. Decidí no comprometerlo aún con el núcleo (las preguntas comenzaron a surgir allí, realmente tuve que pensar. Si alguno de los ciudadanos de Habrovsk puede ayudarme a aconsejar, escríbame, ¡me alegraré!)
Abre la pitón. (Al principio, bash era, pero cambié de opinión muy rápidamente). Usaremos la conocida herramienta / dev / hidraw.
/ dev / hidraw0, / dev / hidraw1: ¿cómo funcionan estos archivos? Para E / S simples, se pueden usar como cualquier archivo normal, y funcionará. Pero GetFeature y SetFeature tienen que jugar con ...
StackOverflow (u otra persona, ya no lo recuerdo) sugirió que necesitaba algo de ioctl. Este es un método especial para trabajar con archivos inusuales como dispositivos HID, terminales y similares.
Ioctl funciona así. Le das un descriptor de archivo abierto (quién está interesado en lo que es,
hay un enlace a Wikipedia ), un número y un búfer, después de lo cual hace algo con este búfer y lo devuelve. No exageraré, solo muchas cosas dependen de la implementación. Déjame darte un ejemplo: 0xC0114806, o ya nos es familiar para SetFeature. Es
(6 << 29) | (ord('H') << 8) | (0x06 << 0) | (0x11 << 16).
Los primeros 6 aquí significan que el archivo estará abierto para escritura y lectura. Por qué leer no es muy claro, pero está escrito para hacerlo, probablemente debería hacerlo. Ord ('H') aquí - abreviado HID. Quizás otras cosas significan, dependiendo del archivo. En este caso, el HID.
0x06: el equipo en sí. El sexto equipo con HID es SetFeature. La última parte es la longitud del búfer.
Solo queda llamar a ioctl con estos valores, y la salida es el controlador.
El esta trabajando .
Epílogo
Espero que haya sido interesante de leer. Incluso útil, tal vez. Algunos fueron omitidos o abreviados: el lector con visión aguda, tal vez, descubrirá la lectura del estado en el controlador, y algunos segundos SetFeature, que no se mencionó en absoluto en el texto. El desarrollo de controladores y el kernel de Linux son cosas importantes, y no se pueden dominar por completo en una bicicleta. Es más probable que el artículo no sea sobre esto, sino sobre el hecho de que hacer algo pequeño y agradable, de código abierto o para usted mismo, no es en absoluto difícil. Solo necesita encontrar una semana de noches con té y un deseo de profundizar en el código.