martes, 10 de diciembre de 2013

Trucos Ubuntu: Recuperar de la suspensión con dispositivos USB


Con este vídeo creo que puedo dar por solucionado el "peculiar" funcionamiento de la suspensión en nuestros sistemas Ubuntu, que conforme ha ido pasando el tiempo ha ido perdiendo funcionalidades por el camino. El arreglo de este capítulo sirve para poder recuperar a nuestros sistemas con pulsaciones de nuestros periféricos conectados a un USB. Lo bueno es que los scripts que os voy a proporcionar son configurables, así que se pueden hacer cosas bastante chulas con ellos.

Como no se puede hacer mucha literatura con este asunto, os voy a ahorrar palabrería y paso directamente al código que tendréis que copiar y pegar en el terminal para conseguir que funcione este procedimiento. Pero antes de ello, menciono las fuentes: toda la información la he extraído del blog de la familia Bernaerts, que contiene unos cuantos tutoriales de interés y cuya lectura os recomiendo. Dicho esto, pasamos al código, paso a paso.

1. Instalamos el software necesario:
sudo apt-get install zenity

2.  Actualizamos la información de los controladores USB:
sudo update-usbids

3. Creamos el primer script...
sudo gedit /usr/local/sbin/enable-wakeup
4. ...copiamos el siguiente código en el archivo que hemos creado (le damos a guardar al finalizar)...

#!/bin/bash
#
# Script to enable a USB devices to be used to resume computer from sleep
#
# Depends on udevadm package
# 09/05/2012 - V1.0 by Nicolas Bernaerts
# if device has been removed, exit
[ "$ACTION" = "remove" ] && exit 0
# set PATH as it is not set for udev scripts
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
# set device SYSFS path
DEVICE_SYSFS="/sys$1"
CURRENT_SYSFS=$DEVICE_SYSFS
# get device product and vendor name from parent SYSFS
DEVICE_VENDOR=`udevadm info --query=all -p "$CURRENT_SYSFS/../" | grep "ID_VENDOR_ID=" | cut -d "=" -f 2`
DEVICE_PRODUCT=`udevadm info --query=all -p "$CURRENT_SYSFS/../" | grep "ID_MODEL_ID=" | cut -d "=" -f 2`
DEVICE_LABEL=`lsusb | grep "${DEVICE_VENDOR}:${DEVICE_PRODUCT}" | sed 's/^.*[0-9a-f]\:[0-9a-f]* \(.*\)$/\1/g'`
# loop thru the SYSFS path, up to PCI bus
CARRY_ON=1
while [ $CARRY_ON -eq 1 ]
do
  # get the first three letters of current SYSFS folder
  FIRST_LETTERS=`basename $CURRENT_SYSFS | sed 's/^\(...\).*$/\1/g'`
  # if current SYSFS is PCI bus, stop the loop
  if [ "$FIRST_LETTERS" = "pci" ] || [ "$FIRST_LETTERS" = "/" ] ; then
    CARRY_ON=0
  # else,
  else
    # if possible, enable wakeup for current SYSFS
    WAKEUP_FILE="${CURRENT_SYSFS}/power/wakeup"
    if [ -f $WAKEUP_FILE ]; then
      echo "enabled" > $WAKEUP_FILE
    fi
    # go to father directory of current SYSFS
    CURRENT_SYSFS=`dirname $CURRENT_SYSFS`
  fi
done
# log the action
LOG_HEADER="USB device ${DEVICE_VENDOR}:${DEVICE_PRODUCT}"
logger "${LOG_HEADER} - Description : ${DEVICE_LABEL}"
logger "${LOG_HEADER} - SysFS path  : ${DEVICE_SYSFS}"
logger "${LOG_HEADER} - Device is enabled to handle suspend/resume"

5. ...y le damos permisos de ejecución:
sudo chmod +x /usr/local/sbin/enable-wakeup

6. Creamos el segundo script...
sudo gedit /usr/local/sbin/select-resume-devices

7. ...copiamos el código...
 #!/bin/bash
#
# Script to create resume udev rules for USB devices
#
# Depends on zenity
# 09/05/2012 - V1.0 by Nicolas Bernaerts
# udev file to generate
UDEV_FILE="/etc/udev/rules.d/90-hid-wakeup-enable.rules"
# set separator as CR
IFS=$'\n'
# list all USB devices, excluding root & hubs
LIST_DEVICE=(`lsusb | grep -v "0000:0000" | grep -iv "hub" | sed 's/^.*[0-9a-f]\:[0-9a-f]* \(.*\)$/\1/g'`)
# loop thru the devices array to generate zenity parameter
for DEVICE in "${LIST_DEVICE[@]}"
do
  # if needed, remove [xxx] from device name as it gives trouble with grep
  DEVICE=`echo "$DEVICE" | sed 's/\[.*\]//g'`
  # add it to the parameters list
  ARR_PARAMETER=( FALSE ${DEVICE} ${ARR_PARAMETER[@]} )
done
# display the dialog box to choose devices
TITLE="Wakeup - Enable USB devices"
TEXT="Please, select USB devices you want to use to resume your computer"
CHOICE=`zenity --list --width=600 --height=250 --text=$TEXT --title=$TITLE --checklist --column "Select" --column "Device name" "${ARR_PARAMETER[@]}"`
# slit the device choice into an array
IFS="|" read -a ARR_CHOICE <<< "$CHOICE"
# if at least one device has been selected, initialise udev rules file
[ ${#ARR_CHOICE[@]} -gt 0 ] && echo "# udev rule for USB wake-up of selected devices" > $UDEV_FILE
[ ${#ARR_CHOICE[@]} -gt 0 ] && echo "#" >> $UDEV_FILE
# loop thru the selected devices to create udev rules
for DEVICE_NAME in "${ARR_CHOICE[@]}"
do
  # get current device data
  DEVICE_DATA=`lsusb | grep "${DEVICE_NAME}" | sed 's/^.*ID \([0-9a-f]*\):\([0-9a-f]*\).*$/\1|\2/g'`
  DEVICE_VENDOR=`echo $DEVICE_DATA | cut -d"|" -f1`
  DEVICE_PRODUCT=`echo $DEVICE_DATA | cut -d"|" -f2`
  # create udev rule for current device
  DEVICE_RULE="SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"$DEVICE_VENDOR\", ATTRS{idProduct}==\"$DEVICE_PRODUCT\" RUN+=\"/usr/local/sbin/enable-wakeup \$env{DEVPATH}\" "
  # add udev rule for current device
  echo "# ${DEVICE_NAME}" >> $UDEV_FILE
  echo ${DEVICE_RULE} >> $UDEV_FILE
done
# if at least one device has been selected, display notification
TITLE="USB resume enabled"
TEXT="Your USB devices are resume enabled.\nTo finalize configuration you have to do one of these actions :\n- replug USB devices\n- reboot the computer"
[ ${#ARR_CHOICE[@]} -gt 0 ] && notify-send --icon=media-eject $TITLE $TEXT

8. ...y damos permisos de ejecución:
sudo chmod +x /usr/local/sbin/select-resume-devices

9. Ejecutamos el segundo script:
sudo /usr/local/sbin/select-resume-devices 

10. Elegimos el dispositivo (o los dispositivos) que queremos activar:


11. Reiniciamos, ¡y listo!

Como os decía antes de toda esta ristra de abracadabras, lo bueno de este método es que podemos seleccionar qué dispositivos estarán activos para poder recuperar el sistema, con lo que podemos conseguir que, por ejemplo, nuestro media center se recupere con un toque del mando distancia. No está mal, ¿eh?

NOTA IMPORTANTE: aunque lo indico en el vídeo, no está de más insistir; todo esto no funcionará si no tenemos activada en nuestra BIOS la opción WAKE ON USB. Cada BIOS tiene una forma de acceso diferente, que en general se indica durante la secuencia de arranque (generalmente alguna tecla "F" o la tecla "suprimir", depende del fabricante).  
 

Todos los contenidos de este blog se ofrecen de forma gratuita y se pueden distribuir libremente. Si piensas que lo merecemos, puedes hacer una donación para el mantenimiento de este blog (o tomarnos una caña a tu salud) haciendo clic en el siguiente botón: