1
|
#!/bin/sh
|
2
|
# Copyright 2018-2024 Alkis Georgopoulos <github.com/alkisg>
|
3
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
4
|
|
5
|
usage() {
|
6
|
printf "Usage: %s [OPTIONS] [COMMAND]
|
7
|
|
8
|
Install the drivers for the BrosTrend AC1L/AC3L/AC5L, AX1L/AX4L/AX5L adapters.
|
9
|
The main difficulty is in detecting the appropriate kernel *headers* package.
|
10
|
|
11
|
Options:
|
12
|
-h Show this help message.
|
13
|
-p Pause on exit.
|
14
|
-t Gather troubleshoting information.
|
15
|
" "$0"
|
16
|
}
|
17
|
|
18
|
bold() {
|
19
|
if [ "$_PRINTBOLD_FIRST_TIME" != 1 ]; then
|
20
|
_PRINTBOLD_FIRST_TIME=1
|
21
|
_BOLD_FACE=$(tput bold 2>/dev/null) || true
|
22
|
_NORMAL_FACE=$(tput sgr0 2>/dev/null) || true
|
23
|
fi
|
24
|
if [ "$1" = "-n" ]; then
|
25
|
shift
|
26
|
printf "%s" "${_BOLD_FACE}$*${_NORMAL_FACE}"
|
27
|
else
|
28
|
printf "%s\n" "${_BOLD_FACE}$*${_NORMAL_FACE}"
|
29
|
fi
|
30
|
}
|
31
|
|
32
|
# For the external tools we need that are also provided by busybox,
|
33
|
# if some tool doesn't exist, create a namesake function that calls busybox.
|
34
|
# `/usr/lib/initramfs-tools/bin/busybox` shows the smallest list of tools.
|
35
|
busybox_fallbacks() {
|
36
|
local busybox tool
|
37
|
|
38
|
busybox=$(command -v busybox)
|
39
|
# Ubuntu chroots ship with a "busybox-initramfs" minimal package
|
40
|
if [ -z "$busybox" ] && [ -x /usr/lib/initramfs-tools/bin/busybox ]; then
|
41
|
busybox=/usr/lib/initramfs-tools/bin/busybox
|
42
|
fi
|
43
|
test -n "$busybox" || return 0
|
44
|
for tool in awk blockdev cat chgrp chmod chown chroot chvt cp \
|
45
|
cpio cut date df env expr find getopt grep head hostname id \
|
46
|
insmod ionice ip kill killall ln logger losetup ls lsmod \
|
47
|
mkdir mktemp modprobe mount mv nc netstat pidof ping \
|
48
|
poweroff ps pwd readlink rm rmdir rmmod sed setsid sleep sort \
|
49
|
swapoff swapon switch_root sync tee touch tr truncate umount \
|
50
|
uname wc; do
|
51
|
# Periodically, prefix a "true" to the following line and test all
|
52
|
# applets to see if we are indeed compatible with the busybox syntax
|
53
|
! is_command "$tool" || continue
|
54
|
eval "$tool() {
|
55
|
$busybox $tool \"\$@\"
|
56
|
}"
|
57
|
done
|
58
|
}
|
59
|
|
60
|
# Set $_DRIVER, based on the script filename, or the inserted adapter,
|
61
|
# or the user input. It may also be set in the environment.
|
62
|
select_driver() {
|
63
|
local fname product _dummy choice
|
64
|
|
65
|
fname=${0##*/}
|
66
|
fname=${fname%.sh}
|
67
|
case "$fname" in
|
68
|
8812au | 88x2bu | 8821cu | 8852bu) _DRIVER="rtl$fname" ;;
|
69
|
aic8800) _DRIVER=$fname ;;
|
70
|
esac
|
71
|
while [ -z "$_DRIVER" ]; do
|
72
|
while read -r product _dummy; do
|
73
|
case "$product" in
|
74
|
0bda:8812) _DRIVER=rtl8812au ;;
|
75
|
0bda:b812) _DRIVER=rtl88x2bu ;;
|
76
|
0bda:c811) _DRIVER=rtl8821cu ;;
|
77
|
0bda:1a2b)
|
78
|
_DRIVER=rtl8852bu
|
79
|
bold "Switching the adapter from storage to WLAN mode"
|
80
|
# Background it as it can take up to 30 seconds in a VM
|
81
|
rw usb_modeswitch -KQ -v 0bda -p 1a2b &
|
82
|
;;
|
83
|
0bda:b832) _DRIVER=rtl8852bu ;;
|
84
|
a69c:5721)
|
85
|
_DRIVER=aic8800
|
86
|
bold "Switching the adapter from storage to WLAN mode"
|
87
|
# Background it as it can take up to 30 seconds in a VM
|
88
|
rw usb_modeswitch -KQ -v a69c -p 5721 &
|
89
|
;;
|
90
|
368b:88df) _DRIVER=aic8800 ;;
|
91
|
esac
|
92
|
done <<EOF
|
93
|
$(lsusb_)
|
94
|
EOF
|
95
|
test -n "$_DRIVER" && break
|
96
|
bold "Could not detect the adapter!"
|
97
|
echo "Please insert the BrosTrend Wi-Fi adapter into a USB slot
|
98
|
and press [Enter] to continue.
|
99
|
If you don't have the adapter currently, you may type:
|
100
|
(a) to install the 8812au driver for the old AC1L/AC3L models before 2019, or
|
101
|
(b) to install the 88x2bu driver for the new AC1L/AC3L version 2 models, or
|
102
|
(c) to install the 8821cu driver for the AC5L model, or
|
103
|
(d) to install the 8852bu driver for the AX1L/AX4L models, or
|
104
|
(e) to install the aic8800 driver for the AX5L model,
|
105
|
(q) to quit without installing a driver"
|
106
|
bold -n "Please type your choice, or [Enter] to autodetect: "
|
107
|
read -r choice
|
108
|
case "$choice" in
|
109
|
a) _DRIVER=rtl8812au ;;
|
110
|
b) _DRIVER=rtl88x2bu ;;
|
111
|
c) _DRIVER=rtl8821cu ;;
|
112
|
d) _DRIVER=rtl8852bu ;;
|
113
|
e) _DRIVER=aic8800 ;;
|
114
|
q) die "Aborted" ;;
|
115
|
esac
|
116
|
done
|
117
|
}
|
118
|
|
119
|
detect_package_manager() {
|
120
|
for _PM in apt-get dnf eopkg pacman pkgtool ppm swupd yum xbps-install zypper unknown; do
|
121
|
if is_command "$_PM"; then
|
122
|
if [ "$_PM" = "apt-get" ] && ! is_command dpkg && is_command rpm; then
|
123
|
# ALT, PCLinuxOS, Vine: https://en.wikipedia.org/wiki/APT-RPM
|
124
|
_PM=apt-rpm
|
125
|
fi
|
126
|
break
|
127
|
fi
|
128
|
done
|
129
|
bold "Package manager is: $_PM"
|
130
|
}
|
131
|
|
132
|
# Output a message to stderr and abort execution
|
133
|
die() {
|
134
|
bold "$@" >&2
|
135
|
pause_exit 1
|
136
|
}
|
137
|
|
138
|
# Download a file from the Internet
|
139
|
download() {
|
140
|
if is_command wget; then
|
141
|
re wget --no-check-certificate -nv "$@"
|
142
|
elif is_command curl; then
|
143
|
re curl --insecure -O "$@"
|
144
|
elif is_command busybox; then
|
145
|
# busybox wget supports --no-check-certificate since 20.04, no point
|
146
|
re busybox wget -nv "$@"
|
147
|
else
|
148
|
die "Please install wget or curl and then re-run the installer"
|
149
|
fi
|
150
|
}
|
151
|
|
152
|
install_debian_prerequisites() {
|
153
|
local kernel header headers
|
154
|
|
155
|
rw apt-get update
|
156
|
# If the appropriate headers are already installed, return
|
157
|
test -d "/lib/modules/$(uname -r)/build" && return 0
|
158
|
|
159
|
# Possible image metapackage names:
|
160
|
# Ubuntu: https://packages.ubuntu.com/source/focal/linux-meta
|
161
|
# E.g. linux-image-generic, linux-image-lowlatency-hwe-18.04
|
162
|
# Debian: https://packages.debian.org/source/buster/linux-latest
|
163
|
# E.g. linux-image-686, linux-image-amd64, linux-image-armmp
|
164
|
# Proxmox: pve-kernel-5.4, pve-kernel5.15, pve-headers
|
165
|
# Raspberry Pi OS: raspberrypi-kernel
|
166
|
# OSMC: rbp2-kernel-osmc, rbp2-image-4.19.55-6-osmc, rbp2-headers-4.19.55-6-osmc
|
167
|
# ODROID-XU4: linux-odroid-5422 (Bionic, 4.14.165-172, armv7l, includes headers)
|
168
|
|
169
|
headers=""
|
170
|
# We can't use `dpkg -S .../modules.builtin` as -hwe are metapackages.
|
171
|
# So we use `dpkg -l linux-image-[^.][^.][^.]*` to avoid linux-image-5.11
|
172
|
# but include linux-image-hwe-18.04.
|
173
|
# The [hi] part is for held kernel packages, e.g. moodleaudio.org
|
174
|
for kernel in $(dpkg -l 'linux-image[^.][^.][^.]*' 'pve-kernel*[^a-z]' raspberrypi-kernel 2>/dev/null |
|
175
|
awk '/^[hi]i/ { print $2 }'); do
|
176
|
case "$kernel" in
|
177
|
pve-kernel*)
|
178
|
header=pve-headers
|
179
|
;;
|
180
|
raspberrypi-kernel)
|
181
|
header=raspberrypi-kernel-headers
|
182
|
;;
|
183
|
*)
|
184
|
header=$(echo "$kernel" | sed 's/image/headers/')
|
185
|
;;
|
186
|
esac
|
187
|
if apt-cache policy "$header" | grep -q '[0-9]'; then
|
188
|
headers="$headers $header"
|
189
|
fi
|
190
|
done
|
191
|
if [ -n "$headers" ]; then
|
192
|
bold "Installing kernel headers:$headers"
|
193
|
re apt-get install --yes $headers
|
194
|
else
|
195
|
request_info "Couldn't detect the appropriate kernel headers package!" \
|
196
|
dpkg -S "/lib/modules/$(uname -r)"
|
197
|
fi
|
198
|
}
|
199
|
|
200
|
install_driver() {
|
201
|
local module reinstall ver ikd
|
202
|
|
203
|
case "$_DRIVER" in
|
204
|
rtl*) module=${_DRIVER#rtl} ;;
|
205
|
*) module=aic8800_fdrv ;;
|
206
|
esac
|
207
|
bold "Downloading the $_DRIVER driver"
|
208
|
re cd "$(mktemp -d)"
|
209
|
# Avoid the "Download is performed unsandboxed" apt warning
|
210
|
re chmod 755 .
|
211
|
download "https://linux.brostrend.com/$_DRIVER-dkms.deb"
|
212
|
bold "Installing and compiling the driver"
|
213
|
case "$_PM" in
|
214
|
apt-get)
|
215
|
# Prefer apt, but fall back to dpkg if necessary
|
216
|
if dpkg --compare-versions "$(dpkg-query -W apt | awk '{ print $2 }')" gt 1.2; then
|
217
|
# Avoid "Internal Error, No filename for..." error on ^iF
|
218
|
if dpkg -l "$_DRIVER-dkms" | grep -q ^ii; then
|
219
|
reinstall=--reinstall
|
220
|
else
|
221
|
unset reinstall
|
222
|
fi
|
223
|
# We want --no-install-recommends here because dkms in Debian
|
224
|
# recommends a lot of kernel header packages that we may not require.
|
225
|
# Caution, linuxmint uses a wrapper that can run `apt install --yes`
|
226
|
# but it doesn't understand `apt --yes install`. Meh.
|
227
|
re apt install $reinstall --yes --no-install-recommends \
|
228
|
"./$_DRIVER-dkms.deb"
|
229
|
else
|
230
|
# The downside of using dpkg instead of apt is that dkms etc
|
231
|
# will be marked as "manually installed".
|
232
|
re apt-get install --yes --no-install-recommends \
|
233
|
bc dkms libc6-dev linux-libc-dev
|
234
|
re dpkg -i "./$_DRIVER-dkms.deb"
|
235
|
fi
|
236
|
;;
|
237
|
*)
|
238
|
re ar x "$_DRIVER-dkms.deb"
|
239
|
re tar xf data.tar.gz
|
240
|
ver=$(echo usr/src/*-*)
|
241
|
ver=${ver##*-}
|
242
|
re rm -rf "/usr/src/$_DRIVER-$ver"
|
243
|
re mv "usr/src/$_DRIVER-$ver" /usr/src/
|
244
|
re cd "/usr/src/$_DRIVER-$ver"
|
245
|
if is_command dkms; then
|
246
|
dkms remove -m "$_DRIVER" -v "$ver" --all 2>/dev/null
|
247
|
rw dkms add -m "$_DRIVER" -v "$ver"
|
248
|
re dkms build -m "$_DRIVER" -v "$ver"
|
249
|
re dkms install -m "$_DRIVER" -v "$ver"
|
250
|
else
|
251
|
bold "Compiling without dkms..."
|
252
|
re make
|
253
|
re make install
|
254
|
fi
|
255
|
# Install the conf file which blacklists the in-kernel drivers
|
256
|
if [ -L "/etc/modprobe.d/$module.conf" ]; then
|
257
|
rm -f "/etc/modprobe.d/$module.conf"
|
258
|
fi
|
259
|
link="/usr/src/$_DRIVER-$ver/$module.conf"
|
260
|
if [ -f "$link" ] &&
|
261
|
[ -d /etc/modprobe.d ] &&
|
262
|
[ ! -e "/etc/modprobe.d/$_DRIVER.conf" ]; then
|
263
|
re ln -s "$link" /etc/modprobe.d/
|
264
|
fi
|
265
|
;;
|
266
|
esac
|
267
|
# Unload the competing in-kernel drivers
|
268
|
case "$_DRIVER" in
|
269
|
rtl88x2bu) ikd=rtw88_8822bu ;;
|
270
|
rtl8821cu) ikd=rtw88_8821cu ;;
|
271
|
*) ikd= ;;
|
272
|
esac
|
273
|
if [ -n "$ikd" ] && [ -d "/sys/module/$ikd" ]; then
|
274
|
bold "Unloading the $ikd in-kernel driver"
|
275
|
if ! timeout 10 modprobe -r "$ikd"; then
|
276
|
bold "Failed to unload the $ikd in-kernel driver, PLEASE REBOOT"
|
277
|
fi
|
278
|
fi
|
279
|
re modprobe "$module"
|
280
|
}
|
281
|
|
282
|
# Install missing packages from the ones specified
|
283
|
# $1: package manager command
|
284
|
# $*: packages
|
285
|
# If "cmd:package" is passed and missing, return "package".
|
286
|
# If "headers:package" is passed, check for the running kernel headers.
|
287
|
inmp() {
|
288
|
local pmcmd
|
289
|
local var cmd package
|
290
|
local list
|
291
|
|
292
|
pmcmd=$1
|
293
|
shift
|
294
|
list=""
|
295
|
for var; do
|
296
|
IFS=":" read -r cmd package <<EOF
|
297
|
$var
|
298
|
EOF
|
299
|
package=${package:-$cmd}
|
300
|
if [ "$cmd" = headers ]; then
|
301
|
if [ ! -d "/lib/modules/$(uname -r)/build" ]; then
|
302
|
list="$list $package"
|
303
|
fi
|
304
|
elif ! is_command "$cmd"; then
|
305
|
list="$list $package"
|
306
|
fi
|
307
|
done
|
308
|
if [ -n "$list" ]; then
|
309
|
bold "Running: $pmcmd$list"
|
310
|
if [ "$pmcmd" = "unknown" ]; then
|
311
|
request_info "Unsupported distribution!
|
312
|
Install dependencies manually: ar bc gcc make tar linux-headers
|
313
|
Please see: https://linux.brostrend.com/supported-distributions" \
|
314
|
cat /etc/os-release
|
315
|
else
|
316
|
re $pmcmd $list
|
317
|
fi
|
318
|
fi
|
319
|
}
|
320
|
|
321
|
# The prerequisites are:
|
322
|
# ar:binutils bc elfutils-libelf-devel gcc make tar headers:kernel-devel
|
323
|
# elfutils-libelf-devel too for rpm dists, see https://bugs.debian.org/886474
|
324
|
# dkms satisfies all of them except for bc
|
325
|
install_prerequisites() {
|
326
|
local var
|
327
|
|
328
|
bold "Installing prerequisites"
|
329
|
case "$_PM" in
|
330
|
# TODO: see variations in https://github.com/morrownr/88x2bu-20210702
|
331
|
apt-get | apt-rpm)
|
332
|
install_debian_prerequisites
|
333
|
;;
|
334
|
dnf | yum | zypper)
|
335
|
# Examples of `rpm -qf "/boot/vmlinuz-$(uname -r)"`:
|
336
|
# CentOS Linux 8: kernel-core-4.18.0-348.7.1.el8_5.x86_64
|
337
|
# CentOS Linux 8 -lt: kernel-lt-core-5.4.240-1.el8.elrepo.x86_64
|
338
|
# fedora-37: kernel-core-6.1.18-200.fc37.x86_64
|
339
|
# fedora-38: kernel-modules-core-6.2.11-300.fc38.x86_64
|
340
|
# openSUSE Leap 15.3: kernel-default-5.3.18-150300.59.106.1.x86_64
|
341
|
# Transform them to e.g.: kernel-devel, kernel-lt-devel, -ml, -uek,
|
342
|
# kernel-default-devel
|
343
|
var=$(rpm -qf "/boot/vmlinuz-$(uname -r)") ||
|
344
|
request_info "Unknown kernel"
|
345
|
var=$(echo "$var" | grep -o 'kernel-[-[:alpha:]]*')
|
346
|
var=${var%core-}
|
347
|
var=${var%modules-}
|
348
|
var="${var}devel"
|
349
|
if [ "$_PM" = "zypper" ]; then
|
350
|
inmp "zypper install -y" bc dkms "headers:$var"
|
351
|
else
|
352
|
# RHEL-based distributions might not provide dkms
|
353
|
if "$_PM" list dkms >/dev/null 2>&1; then
|
354
|
inmp "$_PM install -y" bc dkms "headers:$var"
|
355
|
else
|
356
|
inmp "$_PM install -y" ar:binutils bc :elfutils-libelf-devel gcc make tar "headers:$var"
|
357
|
fi
|
358
|
fi
|
359
|
;;
|
360
|
eopkg)
|
361
|
re eopkg update-repo
|
362
|
inmp "eopkg install" ar:binutils bc gcc make tar headers:linux-current-headers
|
363
|
;;
|
364
|
pacman)
|
365
|
# In Manjaro, select the current kernel, not the old linux316-headers:
|
366
|
inmp "pacman -Sy" bc dkms headers:linux-headers
|
367
|
;;
|
368
|
swupd)
|
369
|
# https://docs.01.org/clearlinux/latest/guides/kernel/kernel-modules-dkms.html
|
370
|
var="$(uname -r)"
|
371
|
var=${var##*.}
|
372
|
inmp "swupd bundle-add" bc dkms:"kernel-$var-dkms"
|
373
|
;;
|
374
|
xbps-install)
|
375
|
inmp "xbps-install -S" bc dkms
|
376
|
;;
|
377
|
*)
|
378
|
inmp "unknown" bc ar bc gcc make tar headers
|
379
|
;;
|
380
|
esac
|
381
|
}
|
382
|
|
383
|
# Check if parameter is a command; `command -v` isn't allowed by POSIX
|
384
|
is_command() {
|
385
|
local fun
|
386
|
|
387
|
if [ -z "$_IS_COMMAND" ]; then
|
388
|
command -v is_command >/dev/null ||
|
389
|
die "Your shell doesn't support command -v"
|
390
|
_IS_COMMAND=1
|
391
|
fi
|
392
|
for fun in "$@"; do
|
393
|
command -v "$fun" >/dev/null || return $?
|
394
|
done
|
395
|
}
|
396
|
|
397
|
# Return true if the kernel is at least that version
|
398
|
kver() {
|
399
|
if [ -z "$_UNAME_R" ]; then
|
400
|
_UNAME_R=$(uname -r)
|
401
|
fi
|
402
|
test "$(printf "%s\n%s\n" "$_UNAME_R" "$1" | sort -rV | head -n1)" = "$_UNAME_R" ||
|
403
|
return $?
|
404
|
}
|
405
|
|
406
|
# Implement lsusb as it isn't preinstalled in some distributions
|
407
|
# Return only the Brostrend devices
|
408
|
# Typical lsusb descriptions (/var/lib/usbutils/usb.ids):
|
409
|
# AC1,3Lv1: Bus 003 Device 008: ID 0bda:8812 Realtek Semiconductor Corp.
|
410
|
# RTL8812AU 802.11a/b/g/n/ac 2T2R DB WLAN Adapter
|
411
|
# AC1,3Lv2: Bus 003 Device 007: ID 0bda:b812 Realtek Semiconductor Corp.
|
412
|
# RTL88x2bu [AC1200 Techkey]
|
413
|
# AC5L: Bus 003 Device 027: ID 0bda:c811 Realtek Semiconductor Corp.
|
414
|
# 802.11ac NIC
|
415
|
# AX1Lst: Bus 003 Device 027: ID 0bda:1a2b Realtek Semiconductor Corp.
|
416
|
# RTL8188GU 802.11n WLAN Adapter (Driver CDROM Mode)
|
417
|
# AX1,4L: Bus 003 Device 027: ID 0bda:b832 Realtek Semiconductor Corp.
|
418
|
# 802.11ac WLAN Adapter
|
419
|
# AX5Lst: Bus 001 Device 015: ID a69c:5721 aicsemi Aic MSC
|
420
|
# AX5L: Bus 001 Device 016: ID 368b:88df AICSemi AIC8800DC
|
421
|
# The manufacturer:product description is too bare. Just use our own.
|
422
|
lsusb_() {
|
423
|
local fname fdir usbid msg
|
424
|
|
425
|
for fname in /sys/bus/usb/devices/*/idVendor; do
|
426
|
fdir=${fname%/*}
|
427
|
usbid="$(cat "$fname"):$(cat "$fdir/idProduct")"
|
428
|
# Return only our own devices
|
429
|
case "$usbid" in
|
430
|
0bda:8812) msg="Brostrend AC1Lv1/AC3Lv1 Wi-Fi adapter" ;;
|
431
|
0bda:b812) msg="Brostrend AC1L/AC3L Wi-Fi adapter" ;;
|
432
|
0bda:c811) msg="Brostrend AC5L Wi-Fi adapter" ;;
|
433
|
0bda:1a2b) msg="Brostrend AX1L/AX4L Wi-Fi adapter (storage mode)" ;;
|
434
|
0bda:b832) msg="Brostrend AX1L/AX4L Wi-Fi adapter" ;;
|
435
|
a69c:5721) msg="Brostrend AX5L Wi-Fi adapter (storage mode)" ;;
|
436
|
368b:88df) msg="Brostrend AX5L Wi-Fi adapter" ;;
|
437
|
*) continue ;;
|
438
|
esac
|
439
|
# TODO: try to detect if it's a USB2 or USB3 port
|
440
|
echo "$usbid $msg"
|
441
|
done
|
442
|
}
|
443
|
|
444
|
pause_exit() {
|
445
|
local _dummy
|
446
|
|
447
|
if [ "$_PAUSE_ON_EXIT" = 1 ]; then
|
448
|
bold -n "Press [Enter] to close the current window."
|
449
|
read -r _dummy
|
450
|
fi
|
451
|
exit "${1:-0}"
|
452
|
}
|
453
|
|
454
|
re() {
|
455
|
"$@" || request_info "Aborting, command failed: $*"
|
456
|
}
|
457
|
|
458
|
request_info() {
|
459
|
if [ -n "$1" ]; then
|
460
|
echo "$1" >&2
|
461
|
shift
|
462
|
fi
|
463
|
troubleshoot >/tmp/troubleshooting.txt 2>&1
|
464
|
if [ $# -gt 0 ]; then
|
465
|
rt "$@" >>/tmp/troubleshooting.txt
|
466
|
fi
|
467
|
die "
|
468
|
===================================================
|
469
|
ERROR: The driver was NOT successfully installed!
|
470
|
===================================================
|
471
|
1) Please select ALL the text in this terminal, then right click with the
|
472
|
mouse and select Copy, and finally paste all the text in an email to:
|
473
|
support@brostrend.com
|
474
|
2) Please also attach this autogenerated log file to the email:
|
475
|
/tmp/troubleshooting.txt
|
476
|
If you want to view it, run:
|
477
|
xdg-open /tmp/troubleshooting.txt
|
478
|
3) Some common issues are documented in:
|
479
|
https://linux.brostrend.com/troubleshooting/"
|
480
|
}
|
481
|
|
482
|
rw() {
|
483
|
"$@" || echo "Warning, command failed: $*" >&2
|
484
|
}
|
485
|
|
486
|
# Echo and run a troubleshooting command, and log its output
|
487
|
rt() {
|
488
|
local fflag iflag eflag
|
489
|
|
490
|
while [ -n "$1" ]; do
|
491
|
case "$1" in
|
492
|
-f) fflag=1 ;;
|
493
|
-i) iflag=1 ;;
|
494
|
-e) eflag=1 ;;
|
495
|
*) break ;;
|
496
|
esac
|
497
|
shift
|
498
|
done
|
499
|
# Check if the binary doesn't exist, e.g. apt on Fedora
|
500
|
if [ "$fflag" = 1 ]; then
|
501
|
# And either return failure,
|
502
|
is_command "$1" || return 1
|
503
|
elif [ "$iflag" = 1 ]; then
|
504
|
# ...or ignore it and return success
|
505
|
is_command "$1" || return 0
|
506
|
fi
|
507
|
printf "\n# %s\n" "$*"
|
508
|
if [ "$eflag" = 1 ]; then
|
509
|
# Use eval, e.g. for `command 1 | command 2`
|
510
|
eval "$*" || return $?
|
511
|
else
|
512
|
"$@" || return $?
|
513
|
fi
|
514
|
}
|
515
|
|
516
|
troubleshoot() {
|
517
|
echo "Troubleshooting information collected on $(date)"
|
518
|
rt uname -a
|
519
|
rt grep PRETTY /etc/os-release
|
520
|
rt -i dpkg --print-architecture
|
521
|
rt lsusb_
|
522
|
rt -f -e lsmod "| grep -wE '88...u|aic8800.*'" ||
|
523
|
rt -e ls "/sys/module/ | grep -wE '88...u|aic8800.*'"
|
524
|
rt -i -e rfkill list
|
525
|
rt -i -e mokutil --sb-state
|
526
|
rt -f dkms status || rt -i apt policy dkms
|
527
|
rt -i -e dpkg "-l '*-dkms' | grep ^ii"
|
528
|
rt ip a
|
529
|
rt ls -d /lib/modules/*/build /usr/src/linux-headers-*
|
530
|
rt -f dpkg -S /boot /lib/modules /usr/src/ ||
|
531
|
rt -i rpm -qf /boot/vmlinu* /lib/modules/* /usr/src/*
|
532
|
# iw isn't available in vanilla Ubuntu GNOME 22.04, but iwlist is
|
533
|
rt -i iw reg get
|
534
|
rt -f nmcli dev wifi || rt -i iwlist scanning
|
535
|
# Try the faster variant, fallback to the safer ones
|
536
|
rt -f journalctl -b -n 5000 --file /[vr][au][rn]/log/journal/"$(cat /etc/machine-id)"/system.journal ||
|
537
|
rt -f journalctl -b -n 5000 ||
|
538
|
rt "dmesg | tail -n 5000"
|
539
|
}
|
540
|
|
541
|
warn() {
|
542
|
bold "$@" >&2
|
543
|
}
|
544
|
|
545
|
main() {
|
546
|
local title scriptpath
|
547
|
|
548
|
case "$1" in
|
549
|
"") ;;
|
550
|
-p) _PAUSE_ON_EXIT=1 ;;
|
551
|
-t) _TROUBLESHOOT=1 ;;
|
552
|
*)
|
553
|
usage
|
554
|
exit 0
|
555
|
;;
|
556
|
esac
|
557
|
|
558
|
# First check if we need to spawn an x-terminal-emulator.
|
559
|
# Note that after pkexec we don't have access to $DISPLAY.
|
560
|
if [ "$_PAUSE_ON_EXIT" != 1 ] && { [ ! -t 0 ] || [ ! -t 1 ]; } &&
|
561
|
xmodmap -n >/dev/null 2>&1; then
|
562
|
title=${1##*/}
|
563
|
case "$title" in
|
564
|
-s | --source) title=${2##*/} ;;
|
565
|
'') title=${0##*/} ;;
|
566
|
esac
|
567
|
_PAUSE_ON_EXIT=1 exec x-terminal-emulator -T "$title" -e sh "$0" "$@"
|
568
|
fi
|
569
|
|
570
|
# Get root access if we don't already have it
|
571
|
if [ "$(id -u)" -ne 0 ]; then
|
572
|
# Make the installer executable, in case it was downloaded from the web.
|
573
|
scriptpath="$(
|
574
|
cd "$(dirname "$0")"
|
575
|
pwd -P
|
576
|
)/$(basename "$0")"
|
577
|
test -x "$scriptpath" || chmod +x "$scriptpath"
|
578
|
test -x "$scriptpath" || die "Could not make $scriptpath executable"
|
579
|
|
580
|
bold "Root access is required"
|
581
|
# Prefer sudo when available, to avoid pkexec-over-ssh issues:
|
582
|
# https://gitlab.freedesktop.org/polkit/polkit/-/issues/17
|
583
|
if groups | grep -qwE 'sudo|wheel' && is_command sudo; then
|
584
|
exec sudo "$scriptpath" ${_PAUSE_ON_EXIT:+-p} "$@"
|
585
|
else
|
586
|
# TODO: for some reason, a delay is needed here, otherwise pkexec might not appear!
|
587
|
sleep 1
|
588
|
exec pkexec "$scriptpath" ${_PAUSE_ON_EXIT:+-p} "$@"
|
589
|
fi
|
590
|
fi
|
591
|
|
592
|
# Tolerate users using `su` instead of `su -`
|
593
|
if ! echo "$PATH" | grep -qw sbin; then
|
594
|
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
595
|
fi
|
596
|
busybox_fallbacks
|
597
|
if [ "$_TROUBLESHOOT" = "1" ]; then
|
598
|
troubleshoot >/tmp/troubleshooting.txt 2>&1
|
599
|
die "The troubleshooting information was saved in this file:
|
600
|
/tmp/troubleshooting.txt
|
601
|
If you want to view it, run:
|
602
|
xdg-open /tmp/troubleshooting.txt
|
603
|
Please attach that file in an email to:
|
604
|
support@brostrend.com"
|
605
|
fi
|
606
|
select_driver
|
607
|
detect_package_manager
|
608
|
install_prerequisites
|
609
|
install_driver
|
610
|
bold "
|
611
|
=====================================================
|
612
|
The driver was successfully installed!
|
613
|
We'd appreciate an Amazon product review:
|
614
|
https://www.amazon.com/review/create-review/listing
|
615
|
====================================================="
|
616
|
pause_exit
|
617
|
}
|
618
|
|
619
|
main "$@"
|