forked from yshui/.files
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsususb
141 lines (121 loc) · 3.72 KB
/
sususb
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
141
#!/bin/bash
usage()
{
cat<<EOF
suspend-usb-device Copyright (C) 2009 Yan Li <elliot.li.tech@gmail.com>
This script is designed to properly put an USB device into suspend
mode that can then be unplugged safely. It sends a SYNCHRONIZE CACHE
command followed by a START-STOP command (if the device supports it),
unbinds the device from the driver and then suspends the USB
port. After that you can disconnect your USB device safely.
usage:
$0 [options] dev
sample:
$0 /dev/sde
options:
-l show the device and USB bus ID only
-h print this usage
-v verbose
This program comes with ABSOLUTELY NO WARRANTY. This is free
software, and you are welcome to redistribute it under certain
conditions; for details please read the licese at the beginning of the
source code file.
EOF
}
set -e -u
SHOW_DEVICE_ONLY=0
VERBOSE=1
REMOVE=0
while getopts "vlh" opt; do
case "$opt" in
h)
usage
exit 2
;;
l)
SHOW_DEVICE_ONLY=1
;;
v)
VERBOSE=1
;;
r)
REMOVE=1
;;
?)
echo
usage
exit 2
;;
esac
done
DEV_NAME=${!OPTIND:-}
if [ -z ${DEV_NAME} ]; then
usage
exit 2
fi
# mount checking
if mount | grep "^${DEV_NAME}[[:digit:]]* "; then
1>&2 echo "the above disk or partition is still mounted, can't suspend device"
1>&2 echo "umounting ${DEV_NAME}"
umount ${DEV_NAME}
fi
# mount double-checking
if mount | grep "^${DEV_NAME}[[:digit:]]* "; then
1>&2 echo "the above disk or partition is still mounted, can't suspend device"
1>&2 echo "umounting ${DEV_NAME}"
exit 1
fi
DEVICE=$(udevadm info --query=path --name=${DEV_NAME} --attribute-walk | \
egrep "looking at parent device" | head -1 | \
sed -e "s/.*looking at parent device '\(\/devices\/.*\)\/.*\/host.*/\1/g")
if [ -z $DEVICE ]; then
1>&2 echo "cannot find appropriate parent USB/Firewire device, "
1>&2 echo "perhaps ${DEV_NAME} is not an USB/Firewire device?"
exit 1
fi
# the trailing basename of ${DEVICE} is DEV_BUS_ID ("5-8" in the
# sample above)
DEV_BUS_ID=${DEVICE##*/}
[[ $VERBOSE == 1 ]] && echo "Found device $DEVICE associated to $DEV_NAME; USB bus id is $DEV_BUS_ID"
if [ ${SHOW_DEVICE_ONLY} -eq 1 ]; then
echo Device: ${DEVICE}
echo Bus ID: ${DEV_BUS_ID}
exit 0
fi
# flush all buffers
sync
# root check
if [ `id -u` -ne 0 ]; then
1>&2 echo error, must be run as root, exiting...
exit 1
fi
# send SCSI sync command, some devices don't support this so we just
# ignore errors with "|| true"
[[ $VERBOSE == 1 ]] && echo "Syncing device $DEV_NAME"
sdparm --command=sync "$DEV_NAME" >/dev/null || true
sleep 5
# send SCSI stop command
[[ $VERBOSE == 1 ]] && echo "Stopping device $DEV_NAME"
sdparm --command=stop "$DEV_NAME" >/dev/null
# unbind it; if this yields "no such device", we are trying to unbind the wrong device
[[ $VERBOSE == 1 ]] && echo "Unbinding device $DEV_BUS_ID"
if [[ "${DEV_BUS_ID}" == fw* ]]
then
echo -n "${DEV_BUS_ID}" > /sys/bus/firewire/drivers/sbp2/unbind
else
# suspend it if it's an USB device (we have no way to suspend a
# firewire device yet)
# check if CONFIG_USB_SUSPEND is enabled
[[ $VERBOSE == 1 ]] && echo "Checking whether $DEVICE can be suspended"
POWER_LEVEL_FILE=/sys${DEVICE}/power/control
POWER_SUSPEND_FILE=/sys${DEVICE}/power/autosuspend
[[ $VERBOSE == 1 ]] && echo "Suspending $DEVICE by writing to $POWER_LEVEL_FILE"
echo -n "${DEV_BUS_ID}" > /sys/bus/usb/drivers/usb/unbind
sleep 1
echo '0' > "$POWER_SUSPEND_FILE"
sleep 1
echo 'auto' > "$POWER_LEVEL_FILE"
sleep 1
[[ $REMOVE == 1 ]] && echo "Remove device"
[[ $REMOVE == 1 ]] && echo "1" > /sys${DEVICE}/remove
fi