/
nickel-usbms.sh
executable file
·294 lines (257 loc) · 8.09 KB
/
nickel-usbms.sh
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#!/bin/sh
# A few constants for stuff that should pretty much be set in stone
ONBOARD_BLOCKDEV="/dev/mmcblk0p3"
SDCARD_BLOCKDEV="/dev/mmcblk1p1"
# Logging facilities
logmsg() {
# Set terminal color escape sequences
END="\033[0m"
RED="\033[31;1m"
YELLOW="\033[33;1m"
GREEN="\033[32;1m"
# Set the requested loglevel, default to notice, like logger
LOG_LEVEL="notice"
PRINT_COLOR="${GREEN}"
case "${1}" in
"C" )
LOG_LEVEL="crit"
PRINT_COLOR="${RED}"
;;
"E" )
LOG_LEVEL="err"
PRINT_COLOR="${RED}"
;;
"W" )
LOG_LEVEL="warning"
PRINT_COLOR="${YELLOW}"
;;
"N" )
LOG_LEVEL="notice"
PRINT_COLOR="${YELLOW}"
;;
"I" )
LOG_LEVEL="info"
PRINT_COLOR="${GREEN}"
;;
"D" )
LOG_LEVEL="debug"
PRINT_COLOR="${YELLOW}"
;;
esac
# Actual message ;)
LOG_MSG="${2}"
# Send to syslog
logger -t "UNCaGED" -p daemon.${LOG_LEVEL} "${LOG_MSG}"
# Print to console
printf "%b%s%b\n" "${PRINT_COLOR}" "${LOG_MSG}" "${END}"
# Print to screen
PRINT_ROW=4
# Keep notices visible by printing them one row higher
if [ "${LOG_LEVEL}" = "notice" ]; then
PRINT_ROW=3
fi
# Keep verbose debugging off-screen, though...
if [ "${LOG_LEVEL}" != "debug" ] ; then
./fbink -q -y ${PRINT_ROW} -mp "${LOG_MSG}"
fi
}
# Get the needed environment variables from the running Nickel process.
# Needed by the Wifi enable/disable functions
get_nickel_env() {
eval "$(xargs -n 1 -0 <"/proc/$(pidof nickel)/environ" | grep -e DBUS_SESSION_BUS_ADDRESS -e NICKEL_HOME -e WIFI_MODULE -e LANG -e WIFI_MODULE_PATH -e INTERFACE 2>/dev/null)"
}
insert_usb() {
sync
echo "usb plug add" >> /tmp/nickel-hardware-status
}
remove_usb() {
sync
echo "usb plug remove" >> /tmp/nickel-hardware-status
}
# The contents of the following functions were adapted from KOreader
release_ip() {
get_nickel_env
# Release IP and shutdown udhcpc.
pkill -9 -f '/bin/sh /etc/udhcpc.d/default.script'
ifconfig "${INTERFACE}" 0.0.0.0
}
obtain_ip() {
get_nickel_env
# Make sure we start from scratch
release_ip
# Use udhcpc to obtain IP.
env -u LD_LIBRARY_PATH udhcpc -S -i "${INTERFACE}" -s /etc/udhcpc.d/default.script -t15 -T10 -A3 -b -q
}
wifi_is_forced() {
if grep -qs " /mnt/onboard" "/proc/mounts"; then
KOBO_CONF_FILE="/mnt/onboard/.kobo/Kobo/Kobo eReader.conf"
elif grep -qs " /mnt/newonboard" "/proc/mounts"; then
KOBO_CONF_FILE="/mnt/newonboard/.kobo/Kobo/Kobo eReader.conf"
else
return 2
fi
grep -qs "ForceWifiOn=true" "$KOBO_CONF_FILE"
return $?
}
enable_wifi() {
if wifi_is_forced; then
return 0
fi
get_nickel_env
WIFI_TIMEOUT=0
while lsmod | grep -q sdio_wifi_pwr; do
# If the Wifi hasn't been killed by Nickel within 5 seconds, assume it's not going to...
if [ ${WIFI_TIMEOUT} -ge 20 ]; then
return 0
fi
# Nickel hasn't killed Wifi yet. We sleep for a bit (250ms), then try again
usleep 250000
WIFI_TIMEOUT=$(( WIFI_TIMEOUT + 1 ))
done
# Load wifi modules and enable wifi.
lsmod | grep -q sdio_wifi_pwr || insmod "/drivers/${PLATFORM}/wifi/sdio_wifi_pwr.ko"
# Moar sleep!
usleep 250000
# WIFI_MODULE_PATH = /drivers/$PLATFORM/wifi/$WIFI_MODULE.ko
lsmod | grep -q "${WIFI_MODULE}" || insmod "${WIFI_MODULE_PATH}"
# Race-y as hell, don't try to optimize this!
sleep 1
ifconfig "${INTERFACE}" up
[ "$WIFI_MODULE" != "8189fs" ] && [ "${WIFI_MODULE}" != "8192es" ] && wlarm_le -i "${INTERFACE}" up
pidof wpa_supplicant >/dev/null \
|| env -u LD_LIBRARY_PATH \
wpa_supplicant -D wext -s -i "${INTERFACE}" -O /var/run/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -B
# Before obtaining an IP address via DHCP, we should determine whether wpa_supplicant connects successfully or not.
# We use the wpa_cli application to do this, checking 'wpa_state' for 'COMPLETED'. Some other states I've seen
# are DISCONNECTED, SCANNING and ASSOCIATING. There are probably others.
WIFI_TIMEOUT=0
while ! wpa_cli status | grep -q "wpa_state=COMPLETED"; do
# If wpa_supplicant hasn't connected within 5 seconds, we couldn't connect to the Wifi network
if [ ${WIFI_TIMEOUT} -ge 20 ]; then
logmsg "E" "wpa_supplicant failed to connect"
# Disable the Wifi stuff we have enabled before exiting...
disable_wifi
return 1
fi
usleep 250000
WIFI_TIMEOUT=$(( WIFI_TIMEOUT + 1 ))
done
# Obtain an IP address
logmsg "I" "Acquiring IP"
obtain_ip
}
disable_wifi() {
if wifi_is_forced; then
return 0
fi
# Before we continue, better release our IP
release_ip
get_nickel_env
# Disable wifi, and remove all modules.
killall udhcpc default.script wpa_supplicant 2>/dev/null
[ "${WIFI_MODULE}" != "8189fs" ] && [ "${WIFI_MODULE}" != "8192es" ] && wlarm_le -i "${INTERFACE}" down
ifconfig "${INTERFACE}" down
# Some sleep in between may avoid system getting hung
# (we test if a module is actually loaded to avoid unneeded sleeps)
if lsmod | grep -q "${WIFI_MODULE}"; then
usleep 250000
rmmod "${WIFI_MODULE}"
fi
if lsmod | grep -q sdio_wifi_pwr; then
usleep 250000
rmmod sdio_wifi_pwr
fi
}
# Call example: mount_fs "$ONBOARD_BLOCKDEV" "/mnt/newonboard"
mount_fs() {
# Set variables
BLK_DEV="$1"
MNT_NEW="$2"
# Make sure to create the new mountpoint directory, if it doesn't already exist
mkdir -p "$MNT_NEW"
# First check to make device isn't already mounted, if so, we keep trying for up to 5 seconds
# before aborting
MOUNT_TIMEOUT=0
while grep -qs "^${BLK_DEV}" "/proc/mounts"; do
# If the partition is still mounted after 5 seconds, we abort
if [ ${MOUNT_TIMEOUT} -ge 20 ]; then
return 254
fi
# Nickel hasn't unmounted device yet. We sleep for a bit (250ms), then try again
usleep 250000
MOUNT_TIMEOUT=$(( MOUNT_TIMEOUT + 1 ))
done
# If we got this far, we are ready to mount
sleep 1
msg="$(mount -o noatime,nodiratime,shortname=mixed,utf8 -t vfat "$BLK_DEV" "$MNT_NEW" 2>&1)"
ret=$?
if [ ${ret} -ne 0 ]; then
logmsg "D" "Failed to mount ${BLK_DEV}! (${ret}: ${msg})"
fi
return ${ret}
}
# Call exampe: unmount_fs "/mnt/newonboard"
unmount_fs() {
MNT_NEW="$1"
# next, make sure we are still mounted where we expect to be
if ! grep -qs " ${MNT_NEW}" "/proc/mounts"; then
return 253
fi
# If mounted, we now try to unmount
sync
sleep 1
msg="$(umount "$MNT_NEW" 2>&1)"
ret=$?
if [ ${ret} -ne 0 ]; then
logmsg "D" "Failed to unmount ${MNT_NEW}! (${ret}: ${msg})"
fi
return ${ret}
}
# Note, no SD card is not considered an error. Always check whether
# MNT_SD_NEW exists before attempting to use the SD card
mount_sd() {
# Check if SD card is present
if [ ! -b "$SDCARD_BLOCKDEV" ]; then
ret=0
else
MNT_SD_NEW="/mnt/newsd"
mount_fs "$SDCARD_BLOCKDEV" "$MNT_SD_NEW"
ret=$?
if [ ${ret} -ne 0 ]; then
unset MNT_SD_NEW
fi
fi
return ${ret}
}
mount_onboard() {
MNT_ONBOARD_NEW="/mnt/newonboard"
mount_fs "$ONBOARD_BLOCKDEV" "$MNT_ONBOARD_NEW"
ret=$?
if [ ${ret} -ne 0 ]; then
unset MNT_ONBOARD_NEW
fi
return ${ret}
}
unmount_sd() {
if [ ! -b "$SDCARD_BLOCKDEV" ]; then
ret=0
elif [ -z "$MNT_SD_NEW" ]; then
ret=254
else
unmount_fs "$MNT_SD_NEW"
ret=$?
unset MNT_SD_NEW
fi
return ${ret}
}
unmount_onboard() {
# First, we check if mount_onboard has previously been invoked
if [ -z "$MNT_ONBOARD_NEW" ]; then
ret=254
else
unmount_fs "$MNT_ONBOARD_NEW"
ret=$?
unset MNT_ONBOARD_NEW
fi
return ${ret}
}