laptop-mode-tools: USB autosuspend ignores user input devices

Human input devices (HIDs) like mice and keyboards cannot handle the
auto suspend properly.  This patch modifies the autosuspend script to
check for and ignore all HIDs when enabling auto suspend.

BUG=chromium-os:4534
TEST=verified that HID autosuspend files are not being written to while
non-HID autosuspend files are
Signed-off-by: Simon Que <sque@chromium.org>

Change-Id: If4a881a0efb3177697e1f4b4f15b8171c881f165

Review URL: http://codereview.chromium.org/3590005
diff --git a/laptop-mode-tools_1.52/etc/laptop-mode/conf.d/usb-autosuspend.conf b/laptop-mode-tools_1.52/etc/laptop-mode/conf.d/usb-autosuspend.conf
index 7710b0c..2ab8c4e 100644
--- a/laptop-mode-tools_1.52/etc/laptop-mode/conf.d/usb-autosuspend.conf
+++ b/laptop-mode-tools_1.52/etc/laptop-mode/conf.d/usb-autosuspend.conf
@@ -30,6 +30,11 @@
 # Example: AUTOSUSPEND_USBID_BLACKLIST="046d:c025 0123:abcd"
 AUTOSUSPEND_USBID_BLACKLIST=""
 
+# The list of USB driver types that should not use autosuspend.  The driver
+# type is given by "DRIVER=..." in a USB device's uevent file.
+# Example: AUTOSUSPEND_USBID_BLACKLIST="usbhid usb-storage"
+AUTOSUSPEND_USBTYPE_BLACKLIST="usbhid"
+
 # Trigger auto-suspension of the USB deivce under conditional circumstances
 BATT_SUSPEND_USB=1
 LM_AC_SUSPEND_USB=0
diff --git a/laptop-mode-tools_1.52/usr/share/laptop-mode-tools/modules/usb-autosuspend b/laptop-mode-tools_1.52/usr/share/laptop-mode-tools/modules/usb-autosuspend
index fdda281..c82a8ed 100755
--- a/laptop-mode-tools_1.52/usr/share/laptop-mode-tools/modules/usb-autosuspend
+++ b/laptop-mode-tools_1.52/usr/share/laptop-mode-tools/modules/usb-autosuspend
@@ -17,6 +17,28 @@
 	return 1
 }
 
+# Check whether the USB driver type is blacklisted
+blacklisted_by_type() {
+	device=$1
+	device_base=`basename $device`
+	for driver_type in $AUTOSUSPEND_USBTYPE_BLACKLIST; do
+		if grep -q DRIVER=$driver_type $device/uevent; then
+			return 0
+		fi
+		# Check child devices as well.  The actual driver type is
+		# listed in a child device, not the top-level device.
+		for subdevice in $device/$device_base*; do
+			if [ -f $subdevice/uevent ]; then
+				if grep -q DRIVER=$driver_type\
+				    $subdevice/uevent; then
+					return 0
+				fi
+			fi
+		done
+	done
+	return 1
+}
+
 if [ x$CONTROL_USB_AUTOSUSPEND = x1 ] ; then
     if [ $ON_AC -eq 1 ]; then
         if [ "$ACTIVATE" -eq 1 ]; then
@@ -40,6 +62,7 @@
 	      do
 		  usb_device=`basename $usb_device`;
 		  if ! blacklisted /sys/bus/usb/devices/$usb_device; then
+			if ! blacklisted_by_type /sys/bus/usb/devices/$usb_device; then
 			  if [ -f /sys/bus/usb/devices/$usb_device/power/autosuspend ]; then
 				  echo $AUTOSUSPEND_TIMEOUT > /sys/bus/usb/devices/$usb_device/power/autosuspend;
 				  log "VERBOSE" "Enabling auto suspend mode for usb device $usb_device."
@@ -53,6 +76,9 @@
 			  else
 				  log "VERBOSE" "Not enabling auto power level for usb device $usb_device"
 			  fi
+			else
+			  log "VERBOSE" "Device $usb_device has blacklisted driver type, skipping auto suspend."
+			fi
 		  else
 			  log "VERBOSE" "USB device $usbid is in the autosuspend blacklist."
 		  fi