blob: eb71b3056a5801a15290ec85e2dfed7b1338a18b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
#!/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
*-*:*.*) : ;;
*) 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"
# ugly workaround, but working for all hw we got for testing
switching_done=0
switching_tries=0
local usb_dir="/sys/$DEVPATH"
[ -f "$usb_dir/idVendor" ] || usb_dir="${usb_dir%/*}"
while [ $switching_done -lt 1 -a $switching_tries -le 6 ]; do
$modeswitch -v $uVid -p $uPid -I -D -n -s 30 -c "${configs%% *}"
if [ $(sanitize "$usb_dir/idProduct") = $uPid ]; then
log "$DEVICENAME: Switching seemingly failed"
sleep 1
else
switching_done=1
fi
switching_tries=$(( $switching_tries + 1 ))
done
}
}
fi
|