Ubuntu, impresoras idénticas, udev

Hace un tiempo, en la empresa de mi viejo, compramos dos impresoras Samsung ML-1665. Son impresoras láser y se están utilizando para imprimir facturas. La máquina de la caja, a la cual están conectadas, tiene Ubuntu 10.04. Después de seguir un excelente howto para instalarlas, la primera fue detectada correctamente y comenzó a funcionar a la perfección.

Al conectar la segunda impresora, exactamente igual que la primera, la detección fue también satifactoria. Aunque surgió un pequeño gran problema: al imprimir sobre ésta última, la impresión se realizaba sobre la primera. Observando la configuración de ambas, me percaté de que tenían exactamente el mismo Device URI.

La solución fue bastante rápida: editar el archivo /etc/cups/printers.conf, y cambiar el device URI, que era algo así como “usb:/Samsung…” por “file:/dev/usblp0”, y la otra impresora por “file:/dev/usblp1”. Con esto el problema fue resuelto y todo comenzó a funcionar como uno esperaba. Aunque no tardó en surgir otro inconveniente.


Después de un tiempo de estar funcionando todo de mil maravillas, la cajera me comenta un día que, para sorpresa de ella, las facturas A se imprimían en la impresora para las facturas B, y viceversa. Me había comentado que no fue mucho problema, ya que simplemente cambió las hojas y tema resuelto. Pero desde ese mismo instante no me quedé muy tranquilo.

Después de un tiempo recibo una nueva llamada: las impresoras estaban enloquecidas. Todos los días, al encender la PC, los puertos se cambiaban. Lo que en el principio era una pequeña molestia, ahora se estaba transformando en una situación bastante irritante. No estaba seguro cómo solucionarlo, así que por lo tanto intenté una actualización del sistema, lo que en apariencias lo había solucionado. Duró uno o dos meses más hasta que el problema reapareció.

Entonces esa vez me puse a buscar un poco más, a preguntar, y me encontré con udev. Este componente del kernel Linux, encargado de gestionar dispositivos, permite, entre muchas cosas, crear reglas para: nombrarlos de una forma distinta (cambiar “sda1” por “mi_disco”), agregar links simbólicos cuando se cumplan ciertas condiciones, ejecutar comandos ante ciertos eventos, y mil cosas más.

Lo que tuve que hacer, entonces, es buscar algún tipo de información en los atributos de cada impresora, que sea único para la misma. Para esto utilicé el comando udevadm:

$ udevadm info -a -p  $(udevadm info -q path -n /dev/usblp0)

[...]

  looking at parent device '/devices/pci0000:00/0000:00:1d.3/usb5/5-2':
    KERNELS=="5-2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="1368"
    ATTRS{idVendor}=="04e8"
    ATTRS{idProduct}=="3301"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="16"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="5"
    ATTRS{devnum}=="2"
    ATTRS{version}==" 1.10"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Samsung Electronics Co., Ltd."
    ATTRS{product}=="ML-1660 Series"
    ATTRS{serial}=="Z526BKDZ800022B."

El atributo serial es el que difiere en cada impresora, por lo tanto utilicé éste para crear un archivo /etc/udev/rules.d/impresoras.rules con las siguientes reglas:

SUBSYSTEMS=="usb", ATTRS{product}=="ML-1660 Series", ATTRS{serial}=="Z526BKAZ301606A.", SYMLINK+="impr_fa"
SUBSYSTEMS=="usb", ATTRS{product}=="ML-1660 Series", ATTRS{serial}=="Z526BKDZ800022B.", SYMLINK+="impr_fb"

Una vez guardado el archivo, hacen un “service udev reload”, desenchufan y vuelven a enchufar las impresoras, y verán que aparecen los dispositivos “impr_fa” e “impr_fb”. Ahora estos serán siempre fijos y aputarán siempre al mismo dispositivo físico (en teoría, les cuento en unos meses). Tal cual lo que estaba buscando. Si hacemos un “ls” vemos:

$ ls -l /dev/impr*
lrwxrwxrwx 1 root root 7 2011-02-22 07:34 /dev/impr_fa -> usb/lp1
lrwxrwxrwx 1 root root 7 2011-02-22 10:25 /dev/impr_fb -> usb/lp0

Pueden encontrar más información sobre cómo escribir reglas udev en este link. A mí me vino muy bien para las impresoras, pero se podrían hacer cosas interesantes con pendrives y otros dispositivos.

Cuando les mostré esto a César y a Nacho, nos preguntábamos si en Windows será posible hacer algo similar. Una de las respuestas fue: “estas cosas [impresoras enloquecidas] no pasan en Windows” 🙂 y “seguramente debe tener alguna forma de configurarlo”. Solo por curiosidad: ¿alguien tiene alguna información al respecto?