5 maneras de desconectar y conectar un dispositivo USB sin retirar las manos del teclado

En multitud de ocasiones, cuando estamos utilizando nuestro ordenador desconectamos un dispositivo USB (de forma segura, como tiene que ser) y, acto seguido, nos damos cuenta de que se nos olvidó copiar un archivo o que teníamos que asegurarnos de que un dato estaba en nuestra unidad. Para estos casos suele ser muy útil desconectar virtualmente los discos USB cuando trabajamos en remoto.

Al haber expulsado el dispositivo, ya no lo vemos en nuestra lista de dispositivos, pero el disco duro o pendrive sigue conectado por el puerto USB, y en muchas distribuciones hoy en día, al haber expulsado la unidad con seguridad, tampoco vemos el dispositivo y no podemos hacer mount desde nuestro terminal. La solución más rápida es desconectar el cable y volverlo a conectar, en algunos casos, ya sea por pereza de tener que levantarnos o porque estamos accediendo a un equipo que no tenemos delante y no hay nadie cerca, no podemos hacerlo.

Información sobre dispositivos USB

Antes de empezar, vamos a ver cómo obtener información acerca de dispositivos USB conectados al sistema. Para ello, podemos utilizar lsusb, que listará los dispositivos conectados ahora mismo. Pongo ejemplos de lo que obtengo en mi equipo ahora mismo, pero tal vez sea muy diferente de lo que obtengas tú:

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 8087:0a2a Intel Corp. 
Bus 001 Device 007: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 005: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 001 Device 010: ID 125f:c93a A-DATA Technology Co., Ltd. 4GB Pen Drive
Bus 001 Device 003: ID 04f2:b424 Chicony Electronics Co., Ltd 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Si queremos más información, podemos utilizar el modificador -t que nos mostrará una salida en forma de árbol con información sobre los módulos:

$ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/8p, 5000M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/16p, 480M
    |__ Port 4: Dev 3, If 0, Class=Video, Driver=uvcvideo, 480M
    |__ Port 4: Dev 3, If 1, Class=Video, Driver=uvcvideo, 480M
    |__ Port 5: Dev 10, If 0, Class=Mass Storage, Driver=usb-storage, 480M
    |__ Port 6: Dev 5, If 0, Class=Hub, Driver=hub/4p, 12M
        |__ Port 4: Dev 7, If 0, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 4: Dev 7, If 1, Class=Human Interface Device, Driver=usbhid, 12M
        |__ Port 4: Dev 7, If 2, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 9: Dev 6, If 0, Class=Wireless, Driver=btusb, 12M
    |__ Port 9: Dev 6, If 1, Class=Wireless, Driver=btusb, 12M

Si queremos mucha más información, podemos utilizar lsusb -v (la salida es muy grande), además podríamos, por ejemplo, saber la máxima potencia que se entrega al dispositivo, de la siguiente forma:

$ lsusb -v 2>/dev/null |egrep "^Bus|MaxPower"
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
    MaxPower                0mA
Bus 001 Device 006: ID 8087:0a2a Intel Corp. 
    MaxPower              100mA
Bus 001 Device 007: ID 046d:c52b Logitech, Inc. Unifying Receiver
    MaxPower               98mA
Bus 001 Device 005: ID 1a40:0101 Terminus Technology Inc. Hub
    MaxPower              100mA
Bus 001 Device 010: ID 125f:c93a A-DATA Technology Co., Ltd. 4GB Pen Drive
    MaxPower              480mA
Bus 001 Device 003: ID 04f2:b424 Chicony Electronics Co., Ltd 
    MaxPower              500mA
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
    MaxPower                0mA

Otros comandos muy útiles son usb-devices, hwinfo, o, por ejemplo, si tenemos la ruta de un dispositivo (dentro de /dev/), podemos pedirle al sistema toda la información posible sobre el mismo y los subsistemas por los que tiene que pasar. Por ejemplo, si conectamos un disco duro USB, para nosotros poder ver utilizar el dispositivo, necesitamos un driver SCSI (por ser /dev/sdX), necesitamos también un driver de almacenamiento USB, que funciona a través del puerto USB, que pertenece a un hub, que está enchufado a un puerto PCI, entre otros sistemas intermedios. Todo eso podríamos verlo con

$ udevadm info --query=path --name=/dev/sdX --attribute-walk

o

$ udevadm info -a -n /dev/sdX

Si queremos aventurarnos, también podemos entrar en /sys/bus/usb y mirar todo lo que hay, veremos mucha información, pero afortunadamente los comandos anteriores clasifican toda esta información.

Privilegios y dispositivos

Para llevar a cabo esta tarea necesitaremos conocer qué dispositivo vamos a reconectar. Para ello, podemos ejecutar:

$ dmesg | tail
[jue nov 24 19:50:04 2016] sd 7:0:0:0: Attached scsi generic sg3 type 0
[798339.431677] sd 7:0:0:0: [sdc] 15806464 512-byte logical blocks: (8.09 GB/7.54 GiB)
[798339.431840] sd 7:0:0:0: [sdc] Write Protect is off
[798339.431848] sd 7:0:0:0: [sdc] Mode Sense: 00 00 00 00
[798339.431988] sd 7:0:0:0: [sdc] Asking for cache data failed
[798339.431996] sd 7:0:0:0: [sdc] Assuming drive cache: write through
[798339.434157]  sdc: sdc1 sdc2
[798339.446812] sd 7:0:0:0: [sdc] Attached SCSI removable disk
[798360.808588] ISO 9660 Extensions: Microsoft Joliet Level 3
[798360.809353] ISO 9660 Extensions: RRIP_1991A

En esta salida, veremos que el dispositivo con el que trabajamos es sdc (sdc1 y sdc2 serían particiones dentro de ese disco). Para los ejemplos utilizaré este dispositivo, en tu caso tendrás que visualizar con cuál cuentas.

En los ejemplos que se detallan a continuación utilizaré sudo para ejecutar los comandos con privilegios de root. Aunque bastaría con tener un usuario con permiso suficiente. Si queremos ver los privilegios necesarios, basta con hacer ls al dispositivo:

$ ls -latr /dev/sdc
brw-rw---- 1 root disk 8, 32 nov 24 19:50 /dev/sdc

Ahí vemos que el dueño es root y el grupo disk. Bastaría con tener un usuario perteneciente al grupo disk.

Método 1. Tratarlo como si fuera un CD/DVD

Es el más sencillo de todos. Seguro que si llevas años en GNU/Linux, cuando trabajabas con CD-ROM o DVD utilizabas el comando eject. Bien, eject servía para abrir el CDROM y eject -t sirve para cerrar la bandeja. Pues bien, si hacemos esto ante el dispositivo USB:

$ sudo eject -t /dev/sdc

El dispositivo debería aparecer como si lo hubiéramos conectado de nuevo.

Método 2. Desenchufado y enchufado virtual

En algunos sistemas (siempre y cuando el hardware lo soporte), cuando retiras el dispositivo USB con seguridad, se deja de alimentar el dispositivo y éste ya no aparece. Es lo mismo que cuando se hace:

udisksctl power-off -b /dev/sdc

En este caso, /dev/sdc es mi dispositivo, y con este comando simuló una desconexión energética virtual.

El problema es que ahora /dev/sdc no existe, es más, si miramos dmesg, obtendremos algo así:

$ dmesg | tail
[281954.693298] usb 1-5: USB disconnect, device number 3

Entonces si probamos con el método de eject no funcionará. Nota: He destacado usb 1-5 y en breve veremos por qué.

Si trabajas en remoto, esto puede ser una buena idea. Imagina que tienes discos USB conectados para hacer copias de seguridad. Cuando estás realizando las copias sí que viene bien que el sistema sepa que hay discos conectados pero, cuando no estamos utilizándolos por un lado debemos ahorrar energía y evitar el desgaste de los discos, por lo que es mejor cortar la corriente, por otro lado, no queremos que aplicaciones maliciosas vean que existen estos discos para que no se infecten. (Sí, en GNU/Linux hay virus).

¿Cómo conectamos ahora la corriente?

Debemos hacer una llamada al puerto USB, para ello hay un proyecto llamado hubpower (enlazo a un fork del proyecto original porque aquí se arregla un bug que puede quitarle la corriente a más dispositivos y no sólo al que queremos). Hay más proyectos (como uhubctl), pero este no tiene dependencias para cuando vayamos a compilar, además es sólo un archivo hubpower.c.
Primero, lo compilamos,

$ gcc -o hubpower hubpower.c

Ahora, ¿recordáis los números en negrita del dmesg?, pues los vamos a utilizar, tendremos que desconectar el dispositivo y volver a conectarlo, así:

$ sudo ./hubpower 1:1 power 5 off
Port  5 status: 0000  Power-Off
$ sudo ./hubpower 1:1 power 5 on
Port  5 status: 0100  Power-On

Si no nos detecta el dispositivo, podemos probar hacer:

$ sudo ./hubpower 1:1 bind
Bind-driver request sent to the kernel

De esta manera, volveremos a ver nuestro dispositivo USB conectado.

Si no queremos un programa en C… lo tengo en perl

Un programa en C es duro para compilar y probar si lo que vamos a hacer es muy sencillo, así que podemos probar este pequeño port en 10 líneas hecho en perl:

#!/bin/perl
require "sys/ioctl.ph";

$device="05";
open(my $usbdev, ">", "/dev/bus/usb/001/001");
$data = pack("H*", "23010800".$device."000000FFFFFF8813");
ioctl($usbdev, 0xC0185500, $data);
$data = pack("H*", "23030800".$device."000000FFFFFF8813");
ioctl($usbdev, 0xC0185500, $data);
close($usbdev);

Debemos respetar $device, el número de puerto (en mi caso era el 5), es un valor en hexadecimal, por lo tanto el 10 será A, 11 será B, 15 será F, 16 será 10… También tenemos que vigilar el dispositivo y el bus, a los que accedemos desde /dev/bus/usb/001/001, los números deben ir con ceros a la izquierda ya que estamos llamando a ese archivo.

Como vemos, la clave está en ioctl(), es una función que manipula parámetros de un dispositivo a partir de un fichero especial en el sistema de archivos. Entre los valores hexadecimales utilizados, encontramos 0xC0185500, una constante llamada USBDEVFS_CONTROL con la que enviaremos un comando de control al dispositivo USB, Los demás códigos pertenecen a la petición de desconexión y conexión (podéis encontrar más información en el programa hecho en C).

Método 3. Ocultando y mostrando el dispositivo

Otra manera de desconectar el dispositivo podría ser:

echo '1-5' |sudo tee /sys/bus/usb/drivers/usb/unbind

Y podremos recuperarlo haciendo:

echo '1-5' |sudo tee /sys/bus/usb/drivers/usb/bind

Este método, no causa una desconexión completa del dispositivo. Sólo hace que el sistema operativo no hable con él y muchos dispositivos, cuando un ordenador no quiere saber nada de ellos, se ponen en modo bajo consumo, ya que no les vamos a pedir nada.

Método 4. Autorización del dispositivo

Lo malo de este método es que en muchos sistemas se pueden desactivar temporalmente más dispositivos, que no son sólo el que necesitamos, sino que atacamos a todo un hub USB. Por ejemplo:

$ echo 0 | sudo tee /sys/bus/usb/devices/usb1/authorized
$ echo 1 | sudo tee /sys/bus/usb/devices/usb1/authorized

Que, por supuesto lo podemos ejecutar todo seguido:

$ echo 0 | sudo tee /sys/bus/usb/devices/usb1/authorized ; echo 1 | sudo tee /sys/bus/usb/devices/usb1/authorized

Tenemos que tener cuidado, si hay más discos conectados al mismo puerto USB (y casi siempre en nuestros ordenadores varios puertos USB de los que vemos están conectados internamente a un hub, por lo que hay grupos de puertos con el mismo USB padre, por decirlo de alguna manera.

Método 5. Reinciar el subsistema USB

Si queremos reiniciar el subsistema USB. Esto es, refrescar todos los dispositivos USB, como desenchufarlos y enchufarlos todos, por un lado podemos descargar y recargar el módulo USB del kernel:

$ sudo modprobe -r ehci_hcd ; sudo modprobe ehci_hcd #Para USB2
$ sudo modprobe -r xhci_hcd ; sudo modprobe xhci_hcd #Para USB3

Aunque algunas distribuciones, las últimas versiones de Ubuntu y derivadas incluidas, tienen los módulos USB integrados y no pueden ser descargados. Por otro lado, puede que el sistema no nos deje descargarlos por estar en uso a causa de otros módulos (impresoras, almacenamiento, dispositivos de interfaz, etc), y si nos ponemos a descargar módulos y romper cosas tal vez nos toque reiniciar el equipo al final. Así que, de otra forma podemos hacer:

$ echo '0000:00:14.5' | sudo tee /sys/bus/pci/drivers/xhci_hcd/unbind
$ echo '0000:00:14.5' | sudo tee /sys/bus/pci/drivers/xhci_hcd/bind

Para encontrar nuestro dispositivo, podemos hacer ls dentro de /sys/bus/pci/drivers/xhci_hcd, aparecerán varias cosas, tenemos que buscar una que se parezca a esto aaaa:bb:cc:dd.e. Puede que tu puerto USB no venga como xhci_hcd (USB3), sino que venga como ehci_hcd (USB2)


14 comentarios, deja el tuyo

Deja tu comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

*

  1. Responsable de los datos: Miguel Ángel Gatón
  2. Finalidad de los datos: Controlar el SPAM, gestión de comentarios.
  3. Legitimación: Tu consentimiento
  4. Comunicación de los datos: No se comunicarán los datos a terceros salvo por obligación legal.
  5. Almacenamiento de los datos: Base de datos alojada en Occentus Networks (UE)
  6. Derechos: En cualquier momento puedes limitar, recuperar y borrar tu información.

  1.   Cristian dijo

    ¡Excelente artículo!

    1.    gasparfm dijo

      Muchas gracias Cristian! Espero que te haya resultado útil.

  2.   Antonio Juan dijo

    En este articulo no se habla de que siempre que vas a meterlo está del lado contrario al correcto y hay que darle la vuelta… jejeje. Estupendo articulo.

    1.    gasparfm dijo

      Gracias Antonio Juan ! Pues mira, no sabes la de veces que me ha pasado eso mientras estaba probando todo lo que he puesto en el post !!! 🙂

  3.   ROMSAT dijo

    Genial. Un artículo superior. Debería titularse: «Aprende sobre el sistema Linux a través del simple hecho de desconectar y conectar tu lápiz USB.» Felicidades.
    Un saludo desde Málaga.

    1.    gasparfm dijo

      Pues sí, no sé si alguien se iniciará en esto de programar en C y el acceso a dispositivos a partir de este post!! ¡¡ También de Málaga !! Estamos en todas partes 🙂

  4.   HO2Gi dijo

    Impresionante articulo. Te as pasado con semejante material.

    1.    gasparfm dijo

      Gracias HO2Gi !! En mi blog personal ( http://totaki.com/poesiabinaria ) también hay un montón de tutoriales del estilo 🙂

  5.   Atahualpa dijo

    muchas gracias amigo. Estoy iniciándome en linux, específicamente en linux mint, y tengo el siguiente problema: en la cónsola puedo ver que mi teléfono está conectado a la maquina pero en el gestor de archivos no. Y por lo tanto no puedo usarlo como modem para conectarme a internet. Que puedo hacer?

    1.    Gaspar Fernández dijo

      Hay teléfonos que no te dejan conectar como módem, pero puedes hacer Tethering

  6.   Milazzo dijo

    Excelente documentación!
    Gracias por dedicar tu tiempo a compartir la experiencia.
    Lo estoy usando de referencia para otro tipo de problema que tengo: Desconexion de los puertos USB en ubuntu (#42~precise1-Ubuntu SMP Wed Aug 14 15:31:16 UTC 2013)
    Llega un momento en el Sistema que arroja un -110 en el dmesg y reinicia el PC, se supone que la falla es por falta de potencia en el USB donde se conecta el dispositivo (USB3.0).

    Ahora uso el lsusb -v para verificar el nivel de potencia del dispositivo pero este arroja 2mA, cosa que es totalmente absurda… solo los led consumen mas que eso…

    Conecto un modem-USB-4G huawei E8372, sin embargo el maxpower indica 2mA, cosa increible, ahora la duda cambio y surgieron otras:
    ¿el MaxPower es un atributo que viene por defecto del dispositivo o en el SO?
    ¿Es un parametro de la maxima potencia que entregara el puerto usb?
    En caso de ser un parametro
    ¿Se puede modificar este parametro y establecer al maximo otorgado por el puerto USB(900mAh- 3.0 / 500mAh- 2.0)?
    En caso de no ser un parámetro,
    ¿Es un valor de medición a tiempo real del consumo que hay por el USB (improbable)?
    Si es otra opcion por favor explicame ya que estoy con dudas de la información referencial.

    Quede con varias dudas con respecto a ese valor MaxPower si tienen alguna información adicional les estaría muy agradecido.

    lsusb -v 2>/dev/null |egrep «^Bus|MaxPower|bDeviceClass|iProduct»

    Bus 002 Device 006: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
    bDeviceClass 255 Vendor Specific Class
    iProduct 2 USB2.0-Serial
    MaxPower 96mA
    Bus 002 Device 008: ID 12d1:14db Huawei Technologies Co., Ltd.
    bDeviceClass 2 Communications
    iProduct 2 HUAWEI_MOBILE
    MaxPower 2mA

  7.   Anonimo dijo

    Se puede aplicar a windows?

  8.   Chelo dijo

    Muchas gracias. Con udisksctl power-off -b /dev/sdc sobre mi disco externo alcanzó para solucionar el dolor de cabeza. ¿No sería mejor que el unmount tenga una opción para hacer esto mismo?

  9.   Marisa dijo

    Dios, qué c*ñazo! Alguien se ha leído este testamento entero? Y encima después de la chapa seguimos sin saber cómo se apaga un DAC/interfaz de sonido USB, una impresora, una tableta gráfica… en fin, nada que no sea un pincho o un disco externo. Vaya pérdida de tiempo…