[packages] usb-modeswitch: add hotplug handler to invoke usb_modeswitch when a flip...
authorJo-Philipp Wich <jow@openwrt.org>
Sun, 4 Jul 2010 18:19:03 +0000 (18:19 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sun, 4 Jul 2010 18:19:03 +0000 (18:19 +0000)
SVN-Revision: 22062

utils/usb-modeswitch/Makefile
utils/usb-modeswitch/files/modeswitch.hotplug [new file with mode: 0644]

index 24f0d00bcf665d96bdf2d9a31b23dc4c7c8dc8ea..0aa202189e6e7955f9d19802d8b01e51ccf8fe5f 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=usb-modeswitch
 PKG_VERSION:=1.1.2
 
 PKG_NAME:=usb-modeswitch
 PKG_VERSION:=1.1.2
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://www.draisberghof.de/usb_modeswitch
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://www.draisberghof.de/usb_modeswitch
@@ -40,6 +40,8 @@ endef
 define Package/usb-modeswitch/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/usb_modeswitch-OpenWrt $(1)/usr/bin/usb_modeswitch
 define Package/usb-modeswitch/install
        $(INSTALL_DIR) $(1)/usr/bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/usb_modeswitch-OpenWrt $(1)/usr/bin/usb_modeswitch
+       $(INSTALL_DIR) $(1)/etc/hotplug.d/usb
+       $(INSTALL_DATA) ./files/modeswitch.hotplug $(1)/etc/hotplug.d/usb/20-modeswitch
 endef
 
 $(eval $(call BuildPackage,usb-modeswitch))
 endef
 
 $(eval $(call BuildPackage,usb-modeswitch))
diff --git a/utils/usb-modeswitch/files/modeswitch.hotplug b/utils/usb-modeswitch/files/modeswitch.hotplug
new file mode 100644 (file)
index 0000000..eebaf13
--- /dev/null
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+local uVid uPid uMa uPr uSe
+local sVe sMo sRe
+
+local modeswitch="/usr/bin/usb_modeswitch"
+
+
+log() {
+       logger -t "usb-modeswitch" "$@"
+}
+
+sanitize() {
+       sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@"
+}
+
+find_scsi_attrs() {
+       [ -n "$DEVPATH" ] && [ -d /sys/$DEVPATH/host* ] && {
+               log "$DEVICENAME is a SCSI device, waiting for it to settle..."
+               local timeout=20
+               while [ $((--timeout)) -ge 0 ]; do
+                       [ -d /sys/$DEVPATH/host*/target* ] && {
+                               local scsi_dir
+                               for scsi_dir in /sys/$DEVPATH/host*/target*/*; do
+                                       [ -d "$scsi_dir" ] || break
+                                       case "$scsi_dir" in
+                                               */host*/target*/*:*:*:*)
+                                                       sVe=$(sanitize "$scsi_dir/vendor")
+                                                       sMo=$(sanitize "$scsi_dir/model")
+                                                       sRe=$(sanitize "$scsi_dir/rev")
+
+                                                       log "$DEVICENAME: Vendor=${sVe:-?} Model=${sMo:-?} Revision=${sRe:-?}"
+                                                       return 0
+                                               ;;
+                                       esac
+                               done
+                       } || {
+                               sleep 1
+                       }
+               done
+               log "$DEVICENAME: Failed to get SCSI attributes!"
+       }
+
+       return 1
+}
+
+find_usb_attrs() {
+       local usb_dir="/sys/$DEVPATH"
+       [ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}"
+
+       uVid=$(cat "$usb_dir/idVendor")
+       uPid=$(cat "$usb_dir/idProduct")
+       uMa=$(sanitize "$usb_dir/manufacturer")
+       uPr=$(sanitize "$usb_dir/product")
+       uSe=$(sanitize "$usb_dir/serial")
+
+       log "$DEVICENAME: Manufacturer=${uMa:-?} Product=${uPr:-?} Serial=${uSe:-?}"
+}
+
+match_config_tag() {
+       local conf="$1"
+       local tag="$2"
+
+       case "${conf##*/}" in
+               *:*$tag=*)
+                       local cmp; eval "cmp=\$$tag"
+                       local pat="${conf#*:$tag=}"; pat="${pat%%:*}"
+                       case "$cmp" in
+                               *$pat*) return 0 ;;
+                               *) return 1 ;;
+                       esac
+               ;;
+       esac
+
+       return 0
+}
+
+match_config() {
+       local conf="$1"
+       local tag
+
+       for tag in uMa uPr uSe sVe sMo sRe; do
+               match_config_tag "$conf" "$tag" || return 1
+       done
+
+       return 0
+}
+
+
+
+if [ "$ACTION" = add ]; then
+       [ -d "/etc/usb_modeswitch.d" ] && [ -x "$modeswitch" ] && {
+               case "$DEVICENAME" in
+                       *-*:*.*) : ;;
+                       *) log "Not handling $DEVICENAME"; exit 0 ;;
+               esac
+
+               find_usb_attrs
+
+               local candidates=0
+               local conf configs
+               for conf in /etc/usb_modeswitch.d/$uVid:$uPid*; do
+                       [ -f "$conf" ] || break
+                       configs="${configs:+$configs }$conf"
+                       $((candidates++))
+               done
+
+               # Found more than one candidate, read SCSI attributes and find the best match
+               [ $candidates -gt 1 ] && {
+                       find_scsi_attrs
+                       for conf in $configs; do
+                               match_config "$conf" && {
+                                       configs="$conf"
+                                       candidates=1
+                                       break
+                               }
+                       done
+               }
+
+               # If a candidate is remaining, start usb-modeswitch
+               [ -n "$configs" ] && {
+                       log "$DEVICENAME: Selecting ${configs%% *} for mode switching"
+                       $modeswitch -c "${configs%% *}"
+               } || {
+                       log "$DEVICENAME: Device does not seem to need mode switching"
+               }
+       }
+fi