8042451373b57bd13a714923fd17243127460ecd
[openwrt/svn-archive/archive.git] / utils / usb-modeswitch / files / modeswitch.hotplug
1 #!/bin/sh
2
3 local uVid uPid uMa uPr uSe
4 local sVe sMo sRe
5
6 local modeswitch="/usr/bin/usb_modeswitch"
7
8
9 log() {
10 logger -t "usb-modeswitch" "$@"
11 }
12
13 sanitize() {
14 sed -e 's/[[:space:]]\+$//; s/[[:space:]]\+/_/g' "$@"
15 }
16
17 find_scsi_attrs() {
18 [ -n "$DEVPATH" ] && [ -d /sys/$DEVPATH/host* ] && {
19 log "$DEVICENAME is a SCSI device, waiting for it to settle..."
20 local timeout=20
21 while [ $((--timeout)) -ge 0 ]; do
22 [ -d /sys/$DEVPATH/host*/target* ] && {
23 local scsi_dir
24 for scsi_dir in /sys/$DEVPATH/host*/target*/*; do
25 [ -d "$scsi_dir" ] || break
26 case "$scsi_dir" in
27 */host*/target*/*:*:*:*)
28 sVe=$(sanitize "$scsi_dir/vendor")
29 sMo=$(sanitize "$scsi_dir/model")
30 sRe=$(sanitize "$scsi_dir/rev")
31
32 log "$DEVICENAME: Vendor=${sVe:-?} Model=${sMo:-?} Revision=${sRe:-?}"
33 return 0
34 ;;
35 esac
36 done
37 } || {
38 sleep 1
39 }
40 done
41 log "$DEVICENAME: Failed to get SCSI attributes!"
42 }
43
44 return 1
45 }
46
47 find_usb_attrs() {
48 local usb_dir="/sys/$DEVPATH"
49 [ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}"
50
51 uVid=$(cat "$usb_dir/idVendor")
52 uPid=$(cat "$usb_dir/idProduct")
53 uMa=$(sanitize "$usb_dir/manufacturer")
54 uPr=$(sanitize "$usb_dir/product")
55 uSe=$(sanitize "$usb_dir/serial")
56
57 log "$DEVICENAME: Manufacturer=${uMa:-?} Product=${uPr:-?} Serial=${uSe:-?}"
58 }
59
60 match_config_tag() {
61 local conf="$1"
62 local tag="$2"
63
64 case "${conf##*/}" in
65 *:*$tag=*)
66 local cmp; eval "cmp=\$$tag"
67 local pat="${conf#*:$tag=}"; pat="${pat%%:*}"
68 case "$cmp" in
69 *$pat*) return 0 ;;
70 *) return 1 ;;
71 esac
72 ;;
73 esac
74
75 return 0
76 }
77
78 match_config() {
79 local conf="$1"
80 local tag
81
82 for tag in uMa uPr uSe sVe sMo sRe; do
83 match_config_tag "$conf" "$tag" || return 1
84 done
85
86 return 0
87 }
88
89
90
91 if [ "$ACTION" = add ]; then
92 [ -d "/etc/usb_modeswitch.d" ] && [ -x "$modeswitch" ] && {
93 case "$DEVICENAME" in
94 *-*:*.*) : ;;
95 *) exit 0 ;;
96 esac
97
98 find_usb_attrs
99
100 local candidates=0
101 local conf configs
102 for conf in /etc/usb_modeswitch.d/$uVid:$uPid*; do
103 [ -f "$conf" ] || break
104 configs="${configs:+$configs }$conf"
105 $((candidates++))
106 done
107
108 # Found more than one candidate, read SCSI attributes and find the best match
109 [ $candidates -gt 1 ] && {
110 find_scsi_attrs
111 for conf in $configs; do
112 match_config "$conf" && {
113 configs="$conf"
114 candidates=1
115 break
116 }
117 done
118 }
119
120 # If a candidate is remaining, start usb-modeswitch
121 [ -n "$configs" ] && {
122 log "$DEVICENAME: Selecting ${configs%% *} for mode switching"
123 # ugly workaround, but working for all hw we got for testing
124 switching_done=0
125 switching_tries=0
126 local usb_dir="/sys/$DEVPATH"
127 [ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}"
128 while [ $switching_done -lt 1 -a $switching_tries -le 6 ]; do
129 $modeswitch -I -D -n -s 30 -c "${configs%% *}"
130 if [ $(sanitize "$usb_dir/idProduct") = $uPid ]; then
131 log "switching seemingly failed"
132 else
133 switching_done=1
134 fi
135 switching_tries=$(( $switching_tries + 1 ))
136 done
137 }
138 }
139 fi