#!/bin/sh
# tlp - handle added usb devices
#
# Copyright (c) 2013 Thomas Koch <linrunner at gmx.net>
# This software is licensed under the GPL v2 or later.

# --- Constants
readonly LOGGER=logger

readonly USBD=/sys/bus/usb/devices
readonly USB_TIMEOUT=2
readonly USB_TIMEOUT_MS=2000

readonly RUNDIR=/var/run/tlp
readonly USB_DONE=usb_done

readonly CONFFILE=/etc/default/tlp

# --- Subroutines
patinstr () { # $1: pattern, $2: target -- test if pattern matches part of target
    [ -n "$1" -a -n "$2" -a -z "${2##*$1*}" ]
    return $?
}

echo_debug () { # $1: tag; $2: msg; echo debug msg if tag matches 
    if patinstr "$1" "$TLP_DEBUG"; then
        $LOGGER -p debug -t "tlp[$$,$PPID]" "$2"
    fi
}

# --- MAIN

# Get args
usbdevp=/sys$1
hid=''

# Read config
[ -f $CONFFILE ] || exit 0
. $CONFFILE

# Exit if TLP or autosuspend disabled
[ "$TLP_ENABLE" = "1" ] && [ "$USB_AUTOSUSPEND" = "1" ] || exit 0

# USB autosuspend has two principal operation modes:
#
# Mode 1 (optional):
# - System startup is handled by tlp-functions:set_usb_suspend()
# - Startup completion is signaled by "flag file" $USB_DONE
# - Newly added devices are handled by this udev script
# - Mode 1 is enabled by the private config variable X_TLP_USB_MODE=1
#
# Mode 2 (default):
# - Everything - including system startup, but not shutdown - is handled by this udev script


# Do exit if mode 1 and no startup completion flag
[ "$X_TLP_USB_MODE" = "1" ] && [ ! -f $RUNDIR/$USB_DONE ] && exit 0

# Check for hid subdevices
for subdevp in $usbdevp/*:*; do
    if [ -d $subdevp ] && [ "$(cat $subdevp/bInterfaceClass)" = "03" ]; then
        hid="_hid"
        break
    fi
done

# Handle device
if [ -f $usbdevp/power/autosuspend ] || [ -f $usbdevp/power/autosuspend_delay_ms ]; then
    # wait for sysfs to settle
    sleep 0.5

    # device is autosuspendable
    ctrlf="control"
    autof="autosuspend_delay_ms"
    usbid="$(cat $usbdevp/idVendor):$(cat $usbdevp/idProduct)"
    busdev="Bus $(cat $usbdevp/busnum) Dev $(cat $usbdevp/devnum)"
            
    control="auto"
    if [ "$hid" = "_hid" ]; then
        # hid devices
        control="on"
    elif patinstr "$usbid" "$USB_BLACKLIST"; then
        # blacklisted device
        control="on"
    fi
        
    if [ -f $usbdevp/power/control ]; then
        echo "$control" > $usbdevp/power/control
    else
        # level is deprecated
        echo "$control" > $usbdevp/power/level
        ctrlf="level"
    fi
    
    if [ -f $usbdevp/power/autosuspend_delay_ms ]; then
        echo $USB_TIMEOUT_MS > $usbdevp/power/autosuspend_delay_ms 2> /dev/null
        if [ $? != 0 ]; then
            # openSUSE 11.4/2.6.37: writing to autosuspend_delay_ms fails -> fallback to autosuspend
            echo_debug "usb" "udev_usb.autosuspend_delay_ms_not_writable: $busdev ID $usbid $usbdevp"
            echo $USB_TIMEOUT > $usbdevp/power/autosuspend
            autof="autosuspend"
        fi
    else
        # autosuspend is deprecated
        echo $USB_TIMEOUT > $usbdevp/power/autosuspend
        autof="autosuspend"
    fi
    
    echo_debug "usb" "udev_usb.$control$hid: $busdev ID $usbid $usbdevp [$ctrlf $autof]"
fi

exit 0


