Sin embargo el presente articulo fue creado con el fin de experimentar un poco con libusb, udev.
Para quien es este articulo?
Esta pensando para programadores, y curiosos. No se explica como funciona Libusb, pero se da un ejemplo de vida real.
Contexto:
El teclado viene con 5 Macro Keys. Que necesitan ser inicial izadas en orden de que Linux detecte sus entradas. Desgraciadamente para ello se necesita, hacer un poco de ingeniería inversa de las entradas. El objetivo de articulo no es para aprender a hacer ingeniería inversa del tema. Pero pueden ver un vídeo muy ilustrativo aqui.
En resumen; Lo que necesitamos hacer es mandar unos bits mágicos a través de LibUSB al teclado para que empiece a usar los Macros.
La forma mas sencilla de probar todo es con evtest.
sudo evtest No device specified, trying to scan all of /dev/input/event* Available devices: #Blablabla en mi compu el input esta en el 4 /dev/input/event4: Razer Razer BlackWidow Ultimate /dev/input/event5: Razer Razer BlackWidow Ultimate /dev/input/event6: Razer Razer BlackWidow Ultimate #Blablabla Select the device event number [0-20]: 4 Input driver version is 1.0.1 Input device ID: bus 0x3 vendor 0x1532 product 0x10d version 0x111 Input device name: "Razer Razer BlackWidow Ultimate" Supported events: Event type 0 (EV_SYN) #Bla bla bla Y esta es la parte interesante... Note que el Key configura teclas F13 en adelante. Esas son las macros. Event code 183 (KEY_F13) Event code 184 (KEY_F14) Event code 185 (KEY_F15) Event code 186 (KEY_F16) Event code 187 (KEY_F17) Event code 188 (KEY_F18) Event code 189 (KEY_F19) Event code 190 (KEY_F20) Event code 191 (KEY_F21) Event code 192 (KEY_F22) Event code 193 (KEY_F23) Event code 194 (KEY_F24) Event code 240 (KEY_UNKNOWN) Event type 4 (EV_MSC) Event code 4 (MSC_SCAN) Event type 17 (EV_LED) Event code 0 (LED_NUML) Event code 1 (LED_CAPSL) Event code 2 (LED_SCROLLL) Key repeat handling: Repeat type 20 (EV_REP) Repeat code 0 (REP_DELAY) Value 250 Repeat code 1 (REP_PERIOD) Value 33 Properties: Testing ... (interrupt to exit) Event: time 1520787420.323002, type 17 (EV_LED), code 0 (LED_NUML), value 0 Event: time 1520787420.323002, -------------- EV_SYN ------------ Event: time 1520787420.376467, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028 Event: time 1520787420.376467, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0 Event: time 1520787420.376467, -------------- EV_SYN ------------ Event: time 1520787422.226497, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e0 Event: time 1520787422.226497, type 1 (EV_KEY), code 29 (KEY_LEFTCTRL), value 1 Event: time 1520787422.226497, -------------- EV_SYN ------------ Event: time 1520787422.476487, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70006 Event: time 1520787422.476487, type 1 (EV_KEY), code 46 (KEY_C), value 1 Event: time 1520787422.476487, -------------- EV_SYN ------------
Cada vez que toquen una tecla convencional, verán el input de la tecla. Pero si se presiona alguna de las macros no pasa nada. Para solucionar cree un pequeño programa en C el cual le pasa los bits mágicos al teclado.
#include#include #include using namespace std; #define VENDOR_ID 0x1532 #define PRODUCT_ID 0x10D #define USB_REQUEST_TYPE 0x21 #define USB_VALUE 0x300 #define USB_REQUEST 9 #define USB_INDEX 0 #define USB_INTERFACE 0 //La interfaz de configuracion esta en el 0 unsigned char buffer[90] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00}; //Magic bits int main(int argc, char** argv) { libusb_context *ctx = NULL; //a libusb session libusb_device_handle *dev_handle; //a device handle int result; //Result form the writting result = libusb_init(&ctx); //initialize a library session if (result < 0) { cout << "libusb_init init error " << result << endl; //there was an error return false; } dev_handle = libusb_open_device_with_vid_pid(ctx, VENDOR_ID, PRODUCT_ID); //these are vendorID and productID I found for my usb device if (dev_handle == NULL) { cout << "libusb_open_device_with_vid_pid cannot open Blackwidow keyboard" << endl; return false; } if (libusb_kernel_driver_active(dev_handle, USB_INTERFACE) == 1) { if (libusb_detach_kernel_driver(dev_handle, USB_INTERFACE) != 0) { cout << "libusb_detach_kernel_driver error" << endl; return false; } } result = libusb_claim_interface(dev_handle, USB_INTERFACE); //claim interface 0 (the first) of device (mine had jsut 1) if (result < 0) { cout << "Cannot Claim Interface" << endl; return false; } result = libusb_control_transfer(dev_handle, USB_REQUEST_TYPE, USB_REQUEST, USB_VALUE, USB_INDEX, buffer, 90, 0); if (result != 90) { return false; } result = libusb_release_interface(dev_handle, USB_INTERFACE); //release the claimed interface if (result != 0) { cout << "Cannot Release Interface" << endl; return false; } //Attached and reclain the driver libusb_attach_kernel_driver(dev_handle, USB_INTERFACE); libusb_close(dev_handle); //close the device we opened libusb_exit(ctx); //needs to be called to end the return 0; }
Ahora bien debemos compilar el programa con libusb y ejecutar este programa con sudo
# Instalar la libreria necesaria sudo apt-get install libusb-1.0-0-dev # Instalar GCC sudo apt-get install build-essential # Compilar g++ blackwidowkeyboardinit.cpp `pkg-config libusb-1.0 --libs --cflags` -o blackwidowkeyboardinit # Ejecutar el programa sudo ./blackwidowkeyboardinit #Ahora bien debemos moverlo a una ubicacion final sudo mv blackwidowkeyboardinit /usr/bin/blackwidowkeyboardinit
Y por ultimo volvemos a probar con evtest.
Ahora si veremos las entradas del teclado cuando presionemos algún MacroKey...
Lo que queda es que el programa se ejecute con permisos de super usuario, cuando se inserta el teclado. Para eso recurrimos al udev.
#Dentro de la carpeta /etc/udev/rules.d #Creamos un archivo sudo touch 40-razer_blackwidow_keyboard.rules #Con el contenido #ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="010d", RUN+="/bin/sh -c 'echo == >> /home/koza/udev-env.txt; env >> /home/koza/udev-env.txt'" #ACTION=="add", ATTR{idVendor}=="1532", ATTR{idProduct}=="010d", RUN+="/usr/bin/blackwidowkeyboardinit" #Refrescamos las reglas con udev sudo udevadm control --reload-rules #Reiniciasmos udev sudo service udev restart
Tomar en cuenta que la primera linea del archivo se puede eliminar, Pero por testing la dejo allí.
Simplemente cuando insertar el teclado en un USB en home crear un archivo con los datos del ambiente.
Si quieres experimentar con las reglas debes simplemente ejecutar el comando siguiente después de cada cambio.
udevadm control --reload-rules && udevadm trigger
Nota: Probado en Debian 8 (Jessie)