{"id":3032,"date":"2022-02-08T20:47:11","date_gmt":"2022-02-08T20:47:11","guid":{"rendered":"https:\/\/blog.rastersoft.com\/?p=3032"},"modified":"2022-02-20T18:18:09","modified_gmt":"2022-02-20T18:18:09","slug":"haciendo-que-mi-tableta-de-dibujo-funcione-en-linux","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=3032","title":{"rendered":"Haciendo que mi tableta de dibujo funcione en Linux"},"content":{"rendered":"\n<p>Hace tiempo me compr\u00e9 una tableta de dibujo de estas para \u00abpintar con l\u00e1piz\u00bb, pero por desgracia nunca la pude usar porque no funcionaba correctamente en Linux: al mover el l\u00e1piz, el cursor del rat\u00f3n se mov\u00eda correctamente, pero no hac\u00eda nada cuando tocaba sobre la superficie ni cuando pulsaba los botones del l\u00e1piz. Sin embargo, como estos d\u00edas ten\u00eda algo de tiempo libre, decid\u00ed ponerme con ella a ver qu\u00e9 pod\u00eda descubrir, y si consegu\u00eda resolver el problema.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet.jpg\" rel=\"lightbox-0\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"814\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet-1024x814.jpg\" alt=\"\" class=\"wp-image-3033\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet-1024x814.jpg 1024w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet-300x238.jpg 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet-768x611.jpg 768w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet-1536x1221.jpg 1536w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/tablet.jpg 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>La tableta de dibujo<\/figcaption><\/figure>\n\n\n\n<p>Lo primero que hice fue echar un vistazo a la informaci\u00f3n de <em>lsusb<\/em>. Ah\u00ed puede ver el c\u00f3digo del fabricante y el del dispositivo:<\/p>\n\n\n\n<p class=\"has-text-align-center mycode\">Bus 002 Device 006: ID 2179:0004 UGTABLET TABLET WP5540<\/p>\n\n\n\n<p>Una b\u00fasqueda r\u00e1pida en <a rel=\"noreferrer noopener\" href=\"https:\/\/the-sz.com\/products\/usbid\/index.php\" target=\"_blank\">una de las muchas bases de datos de USB<\/a> me mostr\u00f3 que el chip controlador pertenece a la empresa <a rel=\"noreferrer noopener\" href=\"http:\/\/www.ugtizer.com.tw\/\" target=\"_blank\">UGtizer Corp<\/a>, pero en su web no encontr\u00e9 ning\u00fan driver adecuado. Una b\u00fasqueda en la <a href=\"http:\/\/www.linux-usb.org\/usb-ids.html\" target=\"_blank\" rel=\"noreferrer noopener\">p\u00e1gina de USB Linux<\/a> tampoco me dio informaci\u00f3n \u00fatil.<\/p>\n\n\n\n<p>Decid\u00ed entonces que podr\u00eda probarla en Windows, a ver si era un problema de la tableta en s\u00ed. Para ello instal\u00e9 uno en una m\u00e1quina virtual y configur\u00e9 un filtro USB para que redirigiese la tableta a \u00e9ste tan pronto se enchufase, y evitar as\u00ed interferencias desde Linux.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-07-19-49-29.png\" rel=\"lightbox-1\"><img loading=\"lazy\" decoding=\"async\" width=\"840\" height=\"558\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-07-19-49-29.png\" alt=\"\" class=\"wp-image-3036\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-07-19-49-29.png 840w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-07-19-49-29-300x199.png 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-07-19-49-29-768x510.png 768w\" sizes=\"auto, (max-width: 840px) 100vw, 840px\" \/><\/a><\/figure>\n\n\n\n<p>Y funcion\u00f3 perfectamente: si mov\u00eda el l\u00e1piz a unos mil\u00edmetros de la superficie, el cursor se mov\u00eda igual que en Linux, pero si lo apoyaba, Windows identificaba una pulsaci\u00f3n de bot\u00f3n de rat\u00f3n y pod\u00eda seleccionar iconos, cosa que en Linux no ocurr\u00eda. Los dos botones del l\u00e1piz tambi\u00e9n funcionaban como el bot\u00f3n derecho y central del rat\u00f3n.<\/p>\n\n\n\n<p>Por supuesto, dado que la tablet <em>medio<\/em> funcionaba en Linux, yo supuse que deb\u00eda seguir el <a rel=\"noreferrer noopener\" href=\"https:\/\/en.wikipedia.org\/wiki\/Human_interface_device\" target=\"_blank\">est\u00e1ndar USB HID<\/a>, pero que habr\u00eda <em>algo<\/em> que se sal\u00eda de \u00e9l y Linux no era capaz de identificar correctamente. O bien podr\u00eda ser que hubiese que configurar primero de alguna manera la tableta, y que Windows lo estuviese haciendo bien y Linux no.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esnifando-paquetes-usb\">Esnifando paquetes USB<\/h2>\n\n\n\n<p>Decid\u00ed comprobar primero la segunda posibilidad. Para ello desenchuf\u00e9 primero la tableta y cargu\u00e9 el m\u00f3dulo <em>usbmon<\/em> con:<\/p>\n\n\n\n<p class=\"mycode\">sudo modprobe usbmon<\/p>\n\n\n\n<p>Luego lanc\u00e9 Wireshark, empec\u00e9 a capturar desde el puerto 2 de USB (pues, si vemos la salida de <em>lsusb<\/em>, es en \u00e9l en donde est\u00e1 el puerto que us\u00e9), conect\u00e9 la tableta, e hice algunos movimientos con el l\u00e1piz sin apoyar y apoyado en la superficie.<\/p>\n\n\n\n<p>Hecho esto, detuve la captura, desconect\u00e9 la tableta, apagu\u00e9 la m\u00e1quina virtual, e hice una nueva captura, para ver qu\u00e9 hac\u00eda Linux. Luego abr\u00ed ambas capturas, cada una en una ventana diferente, y filtr\u00e9 los paquetes de la tableta con:<\/p>\n\n\n\n<p class=\"mycode\">usb.bus_id == X&amp;&amp; usb.device_address == YY<\/p>\n\n\n\n<p>Siendo <strong>X<\/strong> el bus en el que estaba conectada la tableta, e <strong>YY<\/strong> el identificador que se le asign\u00f3 en cada momento.<\/p>\n\n\n\n<p>El resultado no fue nada conclusivo, pues en ambas capturas sal\u00eda m\u00e1s o menos lo mismo: primero se piden los datos b\u00e1sicos del dispositivo, luego la configuraci\u00f3n completa (donde pone que es un dispositivo HID), algunas cosas m\u00e1s sin importancia, y finalmente lee el HID Report, donde vienen los datos HID para configurar el dispositivo. Tanto en Windows como en Linux eran exactamente iguales, por lo que no parec\u00edan ir por ah\u00ed los tiros. Una vez hecho todo esto, el resto de datos se enviaban s\u00f3lo desde la tableta hacia el ordenador en forma de interrupciones USB, y parec\u00edan bastante similares entre ambos sistemas operativos.<\/p>\n\n\n\n<p>Llegados a este punto no pod\u00eda hacer mucho m\u00e1s, porque no sab\u00eda nada sobre el est\u00e1ndar HID ni sobre el significado de cada byte que se estaba enviando sobre el cable, as\u00ed que decid\u00ed hacer un alto y leerme la <a href=\"https:\/\/www.usb.org\/sites\/default\/files\/hid1_11.pdf\" target=\"_blank\" rel=\"noreferrer noopener\">documentaci\u00f3n oficial de HID<\/a> (una lectura amena y tremendamente divertida, como cualquier documentaci\u00f3n oficial &#x1f61d; ).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"el-estandar-hid\">El est\u00e1ndar HID<\/h2>\n\n\n\n<p>La idea detr\u00e1s de HID es crear un protocolo que permita definir absolutamente cualquier dispositivo de interfaz humana, tanto actual como futuro, y hacerlo adem\u00e1s de una manera que permita que cada fabricante lo implemente casi de la manera que quiera. Para ello, un dispositivo HID simplemente tiene que definir un <strong>HID Report<\/strong>, que no es m\u00e1s que una tabla donde se definen qu\u00e9 tipos de entrada tiene, y poco m\u00e1s. Dicha tabla puede estar definida directamente en ROM, lo que simplifica mucho el dise\u00f1o.<\/p>\n\n\n\n<p>\u00bfY qu\u00e9 contiene dicha tabla? Pues b\u00e1sicamente una serie de entradas en las que se define, para cada posible sensor o actuador del dispositivo:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Tipo (por ejemplo: Eje X relativo, Tecla <em>Y<\/em>, presi\u00f3n&#8230;)<\/li><li>N\u00famero de bits que ocupa el dato (el bit inicial se deduce de la propia lista)<\/li><li>Rango f\u00edsico y l\u00f3gico<\/li><\/ul>\n\n\n\n<p>Y algunas cosas m\u00e1s. Adem\u00e1s, las entradas se pueden agrupar por <em>tipo de dispositivo<\/em>, de manera que no es lo mismo un bot\u00f3n de rat\u00f3n que un bot\u00f3n de teclado, y asignarle un identificador a cada grupo.<\/p>\n\n\n\n<p>En el caso de mi tableta, la tabla HID es as\u00ed:<\/p>\n\n\n\n<ul class=\"mycode wp-block-list\"><li>Uso <em>digitizer<\/em> (id: 0x07)<ul><li>Punta de l\u00e1piz: 1 bit<\/li><li>Bot\u00f3n de l\u00e1piz: 1 bit<\/li><li>Goma de borrar de l\u00e1piz: 1 bit<\/li><li>No usados: 2 bits<\/li><li>L\u00e1piz dentro de rango: 1 bit<\/li><li>No usados: 2 bits<\/li><li>Eje X: 16 bits<ul><li>rango f\u00edsico: 0, 5500<\/li><li>rango l\u00f3gico: 0, 22000<\/li><\/ul><\/li><li>Eje Y: 16 bits<ul><li>rango f\u00edsico: 0, 4000<\/li><li>rango l\u00f3gico: 0, 16000<\/li><\/ul><\/li><\/ul><\/li><li>Uso <em>mouse<\/em> (id: 0x08)<ul><li>Bot\u00f3n 1: 1 bit<\/li><li>Bot\u00f3n 2: 1 bit<\/li><li>Bot\u00f3n 3: 1 bit<\/li><li>No usados: 5 bits<\/li><li>Eje X relativo: 8 bits<ul><li>rango l\u00f3gico: -127, 127<\/li><\/ul><\/li><li>Eje Y relativo: 8 bits<ul><li>rango l\u00f3gico: -127, 127<\/li><\/ul><\/li><li>Rueda de rat\u00f3n: 8 bits<ul><li>rango l\u00f3gico: -127, 127<\/li><\/ul><\/li><li>No usados: 8 bits<\/li><\/ul><\/li><li>Uso <em>mouse <\/em>(id: 0x09)<ul><li>Bot\u00f3n 1: 1 bit<\/li><\/ul><ul><li>Bot\u00f3n 2: 1 bit<\/li><li>Bot\u00f3n 3: 1 bit<\/li><li>No usados: 5 bits<\/li><li>Eje X absoluto: 16 bits<ul><li>rango l\u00f3gico: 0, 32767<\/li><\/ul><\/li><li>Eje Y absoluto: 16 bits<ul><li>rango l\u00f3gico: 0, 32767<\/li><\/ul><\/li><li>Presi\u00f3n del l\u00e1piz: 16 bits<ul><li>rango l\u00f3gico: 0, 1023<\/li><\/ul><\/li><\/ul><\/li><\/ul>\n\n\n\n<p>Con esta tabla a mano, si nos llega un bloque de interrupci\u00f3n con los siguientes valores:<\/p>\n\n\n\n<p class=\"mycode\">09 00 5d 49 05 56 00 00<\/p>\n\n\n\n<p>Podemos deducir f\u00e1cilmente su significado: el primer byte es el <em>uso<\/em>, por lo que, al ser 9, tenemos que fijarnos en el \u00faltimo de los tres bloque de la tabla. El primer byte contiene el estado de tres botones de tipo <em>rat\u00f3n<\/em>, pero como los bits correspondientes son 0, significa que no est\u00e1n pulsados. Los dos siguientes bytes son la posici\u00f3n del l\u00e1piz en el eje X, los dos siguientes la posici\u00f3n en el eje Y, y los dos \u00faltimos la presi\u00f3n. F\u00e1cil.<\/p>\n\n\n\n<p>La cuesti\u00f3n es que tanto en Windows como en Linux los datos que se enviaban eran exactamente iguales: si tocaba con el l\u00e1piz en la superficie se activaba el bit 0 del primer byte y aparec\u00eda un valor en los dos \u00faltimos bytes, que aumentaba con la presi\u00f3n que ejerc\u00eda. Si pulsaba alguno de los dos botones en el l\u00e1piz se activaban los bits 1 o 2 del primer byte&#8230; todo era correcto, salvo por el detalle de que Linux no hac\u00eda caso. Incluso escrib\u00ed un peque\u00f1o programa en <em>python<\/em> para leer e interpretar los datos en tiempo real desde la interfaz <em>usbmon<\/em>, y todo era correcto: los datos se enviaban correctamente, y siempre era con bloques de tipo 9.<\/p>\n\n\n\n<p>De hecho, no pod\u00eda evitar preguntarme<em> por qu\u00e9 hab\u00eda dos entradas de tipo rat\u00f3n<\/em>, y sobre todo <em>por qu\u00e9 una de ellas ten\u00eda ejes relativos<\/em>. La respuesta se me ocurri\u00f3 de casualidad: este chip sirve para tabletas h\u00edbridas, donde se puede usar un l\u00e1piz o un rat\u00f3n:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/1f062c6269ff458122a76e26d1af18bf.jpg\" rel=\"lightbox-2\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"800\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/1f062c6269ff458122a76e26d1af18bf.jpg\" alt=\"\" class=\"wp-image-3048\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/1f062c6269ff458122a76e26d1af18bf.jpg 800w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/1f062c6269ff458122a76e26d1af18bf-300x300.jpg 300w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/1f062c6269ff458122a76e26d1af18bf-150x150.jpg 150w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/1f062c6269ff458122a76e26d1af18bf-768x768.jpg 768w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><figcaption>Ejemplo de tableta con l\u00e1piz y rat\u00f3n<\/figcaption><\/figure>\n\n\n\n<p>Eso explicaba los dos tipos: si se usaba el rat\u00f3n, se emitir\u00edan interrupciones con el tipo 0x08, y si se usa el l\u00e1piz entonces ser\u00edan de tipo 0x09. Y el tipo 0x07 supongo que ser\u00eda para alg\u00fan tipo de l\u00e1piz diferente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"vamos-al-kernel\">Vamos al kernel<\/h2>\n\n\n\n<p>Llegados a este punto comprend\u00ed que el problema ten\u00eda que estar, necesariamente, en el driver <em>HID<\/em> de Linux, as\u00ed que descargu\u00e9 las fuentes del kernel, las compil\u00e9 y las instal\u00e9 en mi Debian con:<\/p>\n\n\n\n<p class=\"mycode\">make localmodconfig # copia la configuraci\u00f3n del kernel actual<br>make -j5<br>make deb-pkg -j5 # crea paquetes .deb<\/p>\n\n\n\n<p>Y con ello, me fui al fichero <em>hid-input.c<\/em>. En \u00e9l encontr\u00e9 el punto en el que procesa la tabla HID y descubr\u00ed un detalle interesante hacia el final de la funci\u00f3n:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-08-21-12-32.png\" rel=\"lightbox-3\"><img loading=\"lazy\" decoding=\"async\" width=\"626\" height=\"491\" src=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-08-21-12-32.png\" alt=\"\" class=\"wp-image-3050\" srcset=\"https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-08-21-12-32.png 626w, https:\/\/blog.rastersoft.com\/wp-content\/uploads\/2022\/02\/Captura-de-pantalla-de-2022-02-08-21-12-32-300x235.png 300w\" sizes=\"auto, (max-width: 626px) 100vw, 626px\" \/><\/a><\/figure>\n\n\n\n<p>\u00a1Si un evento estaba duplicado, parec\u00eda ignorarlo a menos que se activase HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE! Esto ten\u00eda buena pinta, porque, efectivamente, los eventos de pulsaci\u00f3n de rat\u00f3n est\u00e1n duplicados en el bloque 8 y en el 9. Prob\u00e9 a a\u00f1adir el Quirk para mi tableta en el fichero <em>hid-quirks.c<\/em>, compil\u00e9, desmont\u00e9 los m\u00f3dulos de HID y volv\u00ed a montarlos, y&#8230;<\/p>\n\n\n\n<p>\u00a1CASI! Me hab\u00eda asignado al l\u00e1piz las siguientes tres acciones del rat\u00f3n: siguiente p\u00e1gina, anterior p\u00e1gina y no-se-cual-m\u00e1s. Claramente iba por buen camino.<\/p>\n\n\n\n<p>Se me ocurri\u00f3 entonces modificar el c\u00f3digo para invertir el orden en el que se procesaban las entradas de la tabla HID, de manera que primero se a\u00f1adiesen las del bloque 9 y luego las del 8, y el resultado fue que&#8230; \u00a1\u00a1\u00a1FUNCION\u00d3!!! Parec\u00eda que lo hab\u00eda resuelto, as\u00ed que cre\u00e9 un parche para poder configurarlo como un Quirk m\u00e1s, a\u00f1ad\u00ed mi tableta a la lista de dispositivos con Quirks, y envi\u00e9 un parche a la gente del kernel. En respuesta, amablemente me indicaron que mi soluci\u00f3n se ve\u00eda demasiado alambicada, y que quiz\u00e1s deber\u00eda probar con HID_QUIRK_MULTI_INPUT, que crear\u00eda un dispositivo diferente para cada tipo de bloque. Lo prob\u00e9, y efectivamente, esa era la soluci\u00f3n, as\u00ed que cre\u00e9 un nuevo parche, mucho m\u00e1s sencillo, lo envi\u00e9, y fue aceptado. \u00a1\u00a1Hurra!!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"anadiendo-un-quirk-a-un-dispositivo-en-el-driver-hid\">A\u00f1adiendo un QUIRK a un dispositivo en el driver HID<\/h2>\n\n\n\n<p>Vamos a ver este detalle con m\u00e1s calma porque es importante, y puede serle \u00fatil a m\u00e1s gente. Lo primero que tenemos que hacer es bajarnos las fuentes del kernel actual desde el repositorio GIT oficial:<\/p>\n\n\n\n<p class=\"mycode\">git:\/\/git.kernel.org\/pub\/scm\/linux\/kernel\/git\/torvalds\/linux.git<\/p>\n\n\n\n<p>Una vez que lo tenemos, nos hacemos un <em>branch<\/em> para nuestro parche y abrimos el fichero <em>drivers\/hid\/hid-ids.h<\/em>. En \u00e9l buscamos si el fabricante de nuestro dispositivo ya est\u00e1 a\u00f1adido o no (lo m\u00e1s probable es que s\u00ed), mediante el identificador que obtuvimos con <em>lsusb<\/em>. En mi caso, el identificador 0x2179 ya estaba a\u00f1adido a nombre de UGTizer con:<\/p>\n\n\n\n<p class=\"mycode\">#define USB_VENDOR_ID_UGTIZER 0x2179<\/p>\n\n\n\n<p>pero dentro de \u00e9l no estaba mi tableta, por lo que a\u00f1ad\u00ed una l\u00ednea con su definici\u00f3n:<\/p>\n\n\n\n<p class=\"mycode\">#define USB_DEVICE_ID_UGTIZER_TABLET_WP5540 0x0004<\/p>\n\n\n\n<p>Una vez hecho esto s\u00f3lo tuve que abrir el fichero <em>drivers\/hid\/hid-quirks.c<\/em> y a\u00f1adir una entrada con mi <em>vendor<\/em>, mi<em> device<\/em> y los <em>quirks<\/em> que quer\u00eda a\u00f1adir para \u00e9l:<\/p>\n\n\n\n<p class=\"mycode\">{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT },<\/p>\n\n\n\n<p>Y con esto estuvo listo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"y-mientras-espero-a-que-mi-distro-anada-el-parche\">\u00bfY mientras espero a que mi distro a\u00f1ada el parche?<\/h2>\n\n\n\n<p>Obviamente no quer\u00eda estar con el kernel de desarrollo en mi sistema, sino que quer\u00eda tener el oficial. \u00bfSignifica eso que no podr\u00e9 usar mi tableta hasta que Debian haga un backport del parche? Pues afortunadamente no, porque el m\u00f3dulo HID permite pasarle manualmente un grupo de <em>quirks<\/em> a a\u00f1adir a un grupo de dispositivos. Para ello basta con editar el fichero <em>\/etc\/default\/grub<\/em> y, en la l\u00ednea donde se definen los par\u00e1metros de arranque del kernel (que, en general, ser\u00e1 la de <em>GRUB_CMDLINE_LINUX_DEFAULT<\/em>) a\u00f1adir lo siguiente:<\/p>\n\n\n\n<p class=\"mycode\">usbhid.quirks=0x2179:0x0004:0x0040<\/p>\n\n\n\n<p>El primer n\u00famero hexadecimal es el identificador USB del fabricante, el segundo es el identificador de dispositivo, y el tercero es un mapa de bits con los <em>quirks<\/em> a activar. La lista est\u00e1 definida en el fichero <em>drivers\/hid\/hid.h<\/em>, y en el momento de escribir este art\u00edculo es:<\/p>\n\n\n\n<p class=\"mycode\">#define HID_QUIRK_INVERT BIT(0)<br>#define HID_QUIRK_NOTOUCH BIT(1)<br>#define HID_QUIRK_IGNORE BIT(2)<br>#define HID_QUIRK_NOGET BIT(3)<br>#define HID_QUIRK_HIDDEV_FORCE BIT(4)<br>#define HID_QUIRK_BADPAD BIT(5)<br>#define HID_QUIRK_MULTI_INPUT BIT(6)<br>#define HID_QUIRK_HIDINPUT_FORCE BIT(7)<br>\/* BIT(8) reserved for backward compatibility, was HID_QUIRK_NO_EMPTY_INPUT *\/<br>\/* BIT(9) reserved for backward compatibility, was NO_INIT_INPUT_REPORTS *\/<br>#define HID_QUIRK_ALWAYS_POLL BIT(10)<br>#define HID_QUIRK_INPUT_PER_APP BIT(11)<br>#define HID_QUIRK_X_INVERT BIT(12)<br>#define HID_QUIRK_Y_INVERT BIT(13)<br>#define HID_QUIRK_SKIP_OUTPUT_REPORTS BIT(16)<br>#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID BIT(17)<br>#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP BIT(18)<br>#define HID_QUIRK_HAVE_SPECIAL_DRIVER BIT(19)<br>#define HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE BIT(20)<br>#define HID_QUIRK_FULLSPEED_INTERVAL BIT(28)<br>#define HID_QUIRK_NO_INIT_REPORTS BIT(29)<br>#define HID_QUIRK_NO_IGNORE BIT(30)<br>#define HID_QUIRK_NO_INPUT_SYNC BIT(31)<\/p>\n\n\n\n<p>Algunos son obvios, pero otros, la verdad, es que no se para qu\u00e9 pueden servir, as\u00ed que si alg\u00fan d\u00eda me encuentro con un dispositivo HID que no va, ir\u00e9 probando de uno en uno a ver.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hace tiempo me compr\u00e9 una tableta de dibujo de estas para \u00abpintar con l\u00e1piz\u00bb, pero por desgracia nunca la pude usar porque no funcionaba correctamente en Linux: al mover el l\u00e1piz, el cursor del rat\u00f3n se mov\u00eda correctamente, pero no hac\u00eda nada cuando tocaba sobre la superficie ni cuando pulsaba los botones del l\u00e1piz. Sin &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=3032\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Haciendo que mi tableta de dibujo funcione en Linux<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,7],"tags":[],"class_list":["post-3032","post","type-post","status-publish","format-standard","hentry","category-programacion","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/3032","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3032"}],"version-history":[{"count":10,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/3032\/revisions"}],"predecessor-version":[{"id":3055,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/3032\/revisions\/3055"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3032"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3032"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3032"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}