Хакер - Bluetooth для андроида. Портируем с Linux на Android драйвер USB-адаптера
hacker_frei
Игорь Орещенков
Содержание статьи
- Архитектура подсистемы Bluetooth в Android
- Рекогносцировка
- Модуль ядра с драйвером USB-адаптера
- Библиотека взаимодействия с драйвером
- Доработки
- Выводы
- Использованное ПО
- Использованная документация
Не все USB-устройства начинают работать на Android сразу после подключения. В этой статье я покажу, как решить проблему, на примере широко распространенного Bluetooth-адаптера CSR 4.0. Нам понадобится собрать из исходников ядро Linux и покопаться в интерфейсной библиотеке Android.
Современное железо редко предполагает что‑то доделывать руками или допиливать в прошивках. Однако есть целый класс устройств «ноунейм», которые просто‑таки взывают к умелым рукам и пытливым умам. Немного смекалки, и можно заставить их работать не хуже именитых аналогов.
Вот, например, ничем не примечательная ТВ‑приставка в виде черной квадратной пластиковой коробки с надписью «MXQ Pro 4K» на крышке и бюджетной начинкой: SOC RK3229, 1 Гбайт RAM и 8 Гбайт NAND. У меня она уже около года почти бесперебойно транслировала на телевизор YouTube и каналы интернет‑телевидения, музицировала и сообщала свежие новости.
В самом начале ее мультимедийной жизни характер у приставки был строптивый, и при каждом удобном случае она норовила зависнуть или перезагрузиться. Эту проблему удалось решить, установив сглаживающий фильтр в цепи питания и заменив комплектный блок питания более качественным.
В какой‑то момент я подумал, не использовать ли мне эту приставку еще и для игр. Беспроводной контроллер подошел бы для этого как нельзя лучше.
В целом контроллеры можно разделить на две категории: RF (Radio Frequency, радиочастотные) и BT (Bluetooth), оба в итоге работают по радиоканалу. Вариант с RF требует использовать проприетарный донгл (и занимать им порт USB), а Bluetooth должен поддерживаться на стороне приставки.
Зато Bluetooth универсален и, помимо подключения устройств ввода, может быть использован для вывода звука на беспроводные колонки, файлового обмена со смартфоном и так далее. Мой выбор был предопределен тем, что в ближайшем магазине нашелся лишь BT-контроллер VR-PARK. Не образец изящного дизайна, но не любоваться же на него!
К сожалению, на плате ТВ‑приставки отсутствует аппаратный BT-модуль, однако в настройках ее операционной системы Android 7.1.2 я видел пункт включения Bluetooth, что вроде бы позволяло надеяться на поддержку стека протоколов. Возможно, после подключения модуля Bluetooth в USB сработает магия и сразу представится возможность насладиться игрой?
С этими мыслями я прикупил USB-адаптер Bluetooth с лаконичной надписью «CSR 4.0» на корпусе. Вернувшись домой, я вставил его в порт приставки, и тот весело замигал светодиодом. А после включения Bluetooth в настройках... ничего не произошло. То есть почти ничего, если не считать возникновения задачи, решению которой посвящена эта статья: настроить ТВ‑приставку на использование адаптера USB Bluetooth.
Когда возникает проблема, исследователь первым делом идет в интернет, чтобы собрать сведения о ней. На удивление, материалов оказалось немного. То ли никто не подключал USB-адаптер к приставке, то ли у всех он работал из коробки, но последние содержательные обсуждения датировались 2013 годом и относились к автомобильной системе мультимедиа.
Результат бессистемных попыток отыскать работающие настройки не порадовал: я только потерял несколько часов и осознал, что придется искать собственный путь. А для этого необходимо понимать, как подсистема Bluetooth встроена в Android.
АРХИТЕКТУРА ПОДСИСТЕМЫ BLUETOOTH В ANDROID
С точки зрения программиста, центральный компонент подсистемы Bluetooth в Android — системная служба Bluetooth (представляющая собой приложение для Android), которая через Binder IPC дает приложениям доступ к услугам Bluetooth-профилей, а сама использует при этом JNI-интерфейсы, реализованные на уровне HAL и ведущие к компонентам стека Bluetooth и расширениям поставщика (в двоичных библиотеках).

Эту схему можно продолжить вниз по системной иерархии, и тогда станет видно, что библиотеки HAL используют интерфейс hci0 для доступа к HCI-сокетам ядра операционной системы, которые через драйвер позволяют взаимодействовать с аппаратным Bluetooth-модулем, подключенным к системной плате шиной SDIO, UART или USB.

Осталось выяснить, на каком именно уровне у нас проблема, которая мешает адаптеру взять и заработать.
Операционная система Android — это ядро Linux, поверх которого работает гипервизор виртуальных машин Dalvik. Начинать анализ разумно с нижнего уровня, последовательно убеждаясь в том, что есть физическое подключение, операционная система и драйвер видят адаптер, он доступен на уровне HAL и так далее — до момента, когда он должен работать.
Чтобы исследовать ОС и вносить в нее изменения, нужен доступ к командной оболочке с правами суперпользователя. Об основах использования консоли Android можно прочитать в статье «Консольный Android».
WARNING
Вмешательство в операционную систему с правами суперпользователя может нарушить работоспособность устройства и вывести его из строя. Принимая решение выполнить описанные в статье рекомендации, исследователь берет на себя полную ответственность за возможные негативные последствия своих действий.
РЕКОГНОСЦИРОВКА
В системных сообщениях dmesg упоминания о Bluetooth встречаются в следующих контекстах:
[1] Bluetooth: Core ver 2.16
[2] NET: Registered protocol family 31
[3] Bluetooth: HCI device and connection manager initialized
[4] Bluetooth: HCI socket layer initialized
[5] Bluetooth: L2CAP socket layer initialized
[6] Bluetooth: SCO socket layer initialized
. . .
[7] Bluetooth: HCI UART driver ver 2.2
[8] Bluetooth: HCI H4 protocol initialized
[9] Bluetooth: HCILL protocol initialized
[10] rtk_btusb: RTKBT_RELEASE_NAME: 20170109_TV_ANDROID_6.x
[11] rtk_btusb: Realtek Bluetooth USB driver module init, version 4.1.2
[12] rtk_btusb: Register usb char device interface for BT driver
[13] usbcore: registered new interface driver rtk_btusb
. . .
[14] Bluetooth: RFCOMM TTY layer initialized
[15] Bluetooth: RFCOMM socket layer initialized
[16] Bluetooth: RFCOMM ver 1.11
[17] Bluetooth: BNEP (Ethernet Emulation) ver 1.3
[18] Bluetooth: BNEP filters: protocol multicast
[19] Bluetooth: BNEP socket layer initialized
[20] Bluetooth: HIDP (Human Interface Emulation) ver 1.2
[21] Bluetooth: HIDP socket layer initialized
. . .
[23] usb 5-1: New USB device found, idVendor=0a12, idProduct=0001
[24] usb 5-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[25] usb 5-1: Product: CSR8510 A10
Строка 1 говорит о том, что ядро Linux собрано с поддержкой стека Bluetooth, строка 2 сообщает о регистрации в ядре семейства протоколов Bluetooth. Сразу после этого инициализируются слои сокетов HCI, L2CAP и SCO (3–6).
Затем активируются драйверы, предназначенные для взаимодействия с адаптерами Bluetooth, подключаемыми по шинам UART и USB (7–13). К сожалению, последний «понимает» только контроллеры Realtek, а наш адаптер CSR этим драйвером не поддерживается.
Последний блок сообщений (14–21) информирует об инициализации высокоуровневых протоколов RFCOMM, BNEP и HIDP стека Bluetooth. Строки 23–25 соответствуют реакции операционной системы на подключение USB-адаптера и говорят о том, что на физическом уровне он опознается шиной USB.
Интересно, где же находится драйвер адаптера? Команда lsmod выдала список из двух модулей, среди которых rtk_btusb не оказалось. Значит, он интегрирован в ядро Linux. Но список непустой, а значит, ядро собрано с поддержкой модулей. Запомним это на будущее.
Я изучил файловую систему ТВ‑приставки и нашел следующие компоненты, имеющие отношение к подсистеме Bluetooth:
/app/Bluetooth/Bluetooth.apk
/system/lib/libbluetooth_jni.so
/system/lib/hw/audio.a2dp.default.so
/system/lib/hw/bluetooth.default.so
/system/lib/hw/bluetooth_rtk.default.so
/system/lib/libbt-vendor_uart.so
/system/lib/libbt-vendor_usb.so
/system/lib/rtkbt/...
/system/vendor/libbt-vendor.so
/system/etc/bluetooth/bt_did.conf
/system/etc/bluetooth/bt_stack.conf
/system/etc/bluetooth/bt_vendor.conf
/system/etc/bluetooth/rtkbt.conf
/system/etc/bluetooth/rtkbt_plugins.conf
Следующие команды, последовательно примененные к файлам библиотек, помогут нам понять их зависимость друг от друга:
$ strings /system/lib/hw/название-библиотеки.so | grep '.so'
$ strings /system/lib/hw/название-библиотеки.so | grep '.conf'
Добавив эти компоненты на схему, я получил следующую картину.

Собранной информации достаточно, чтобы предположить, что драйверы на ТВ‑приставке не поддерживают Bluetooth-адаптеры на контроллерах CSR. Поскольку ядро имеет поддержку модулей, можно попытаться исправить дело, собрав соответствующий модуль с необходимым драйвером.
МОДУЛЬ ЯДРА С ДРАЙВЕРОМ USB-АДАПТЕРА
В качестве платформы для сборки я использовал 64-битную ОС Bodhi Linux 6.0.0 (основанную на Ubuntu 20.04 LTS). У нее есть минималистичный установочный образ, в который входят инструменты метапакета build essential. Для наших работ достаточно виртуальной машины с оперативной памятью 1 Гбайт и накопителем 20 Гбайт. После установки системы и синхронизации с репозиторием надо установить дополнительные пакеты unzip, python2 и libncurses5 и создать символическую ссылку на интерпретатор:
$ sudo ln -s /usr/bin/python2.7 /usr/bin/python
Создадим каталог для работы:
$ mkdir $HOME/tvbox && cd $HOME/tvbox
Чтобы собрать модуль драйвера, нужны исходники ядра Linux той версии, которая используется в операционной системе ТВ‑приставки, в данном случае 3.10.104. К счастью, на GitHub быстро нашелся репозиторий с ядрами Linux, адаптированными для устройств на платформе Rockchip. Забираем исходники из него:
$ wget -C kernel-release-3.10.zip https://github.com/rockchip-linux/kernel/archive/refs/heads/release-3.10.zip
Теперь надо распаковать полученный архив в рабочий каталог и проверить, соответствует ли версия ядра ожиданиям:
$ cd kernel-release-3.10
$ head Makefile
VERSION = 3
PATCHLEVEL = 10
SUBLEVEL = 104
Чтобы посмотреть, какие конфигурации доступны для платформы Rockchip, выполним команду
$ make help | grep rockchip
rockchip_chromium_defconfig - Build for rockchip_chromium
rockchip_defconfig - Build for rockchip
Вариант для операционной системы Chromium OS отбрасываем, остается rockchip_defconfig. Ищем нужный конфиг:
$ find ./arch -name 'rockchip_defconfig'
./arch/arm64/configs/rockchip_defconfig
./arch/arm/configs/rockchip_defconfig
В нашей приставке стоит чип RK3229. Он 32-разрядный, поэтому нам актуален второй вариант. Для конфигурирования ядра, как написано в kernel-release-3.10/README и kernel-release-3.10/android/configs/README, надо выполнить команды
$ ARCH=arm scripts/kconfig/merge_config.sh \
arch/arm/configs/rockchip_defconfig \
android/configs/android-base.cfg \
android/configs/android-recommended.cfg
Далее в только что созданный файл .config надо добавить строку CONFIG_MODULES=y (после строки CONFIG_MODULES is not set), чтобы включить поддержку модулей ядром, а также строку CONFIG_BT_HCIBTUSB=m (после строки CONFIG_BT_HCIBTUSB is not set) — для сборки драйвера USB-адаптеров Bluetooth как модуля ядра. После этого выполним команду
$ ARCH=arm make olddefconfig
Исходные тексты ядра сконфигурированы и готовы к сборке модуля. Собирать будем с помощью инструментов Linaro. Их нужно извлечь из архива gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi.tar.xz в каталог tvbox, после чего из подкаталога kernel-release-3.10 выполняем команду
$ PATH=$HOME/tvbox/gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi/bin:$PATH \
ARCH=arm CROSS_COMPILE=arm-eabi- make modules
Через непродолжительное время модуль ядра будет сформирован в файле kernel-release-3.10/drivers/bluetooth/btusb.ko. Этот файл надо записать на ТВ‑приставку в каталог /system/lib/modules и попробовать запустить:
# insmod /system/lib/modules/btusb.ko
insmod: failed to load btusb.ko: Exec format error
Неудача: нам сообщили, что файл имеет неправильный формат. Детальное описание проблемы можно найти в сообщениях ядра:
# dmesg | tail
btusb: version magic '3.10.104 SMP preempt ARMv7 p2v8 ' should be '3.10.104 SMP preempt mod_unload ARMv7 p2v8 '
Оказывается, собранная версия не имеет атрибута mod_unload. Придется вернуться к исходным текстам и в файл .config после строки # CONFIG_MODULE_UNLOAD is not set добавить параметр CONFIG_MODULE_UNLOAD=y, а затем повторить сборку:
$ make clean
$ make olddefconfig
$ make modules
Записываем новый модуль на ТВ‑приставку и запускаем:
# insmod /system/lib/modules/btusb.ko
Проверяем результат:
# dmesg | tail
usbcore: registered new interface driver btusb
# lsmod
Module Size Used by
btusb 14685 0 [permanent]
Неужели получилось? Пока что все говорит о том, что модуль заработал. Для проверки воспользуемся командой rfkill (она становится доступной после установки BusyBox). Сначала надо выполнить команду rfkill list без подключенного модуля и запомнить ее вывод (если он не пустой). Затем подключить модуль и повторить выполнение команды:
# rfkill list
0: hci0: bluetooth
Soft blocked: no
Hard blocked: no
В выводе должны появиться строки, соответствующие подключенному адаптеру. Потом адаптер надо отключить и снова выполнить rfkill list. Теперь строки, соответствующие адаптеру, должны исчезнуть из вывода. Только такое динамичное поведение говорит о работоспособности драйвера.
Альтернативный способ проверки — наблюдение за содержимым каталога /sys/class/rfkill. При подключении адаптера Bluetooth в нем должен создаваться подкаталог rfkillN (где N — номер устройства), а при отключении — исчезать.
Из файла /init.connectivity.rc, который содержит команды, выполняемые при загрузке системы для инициализации коммуникационных устройств, можно узнать, что файлам /sys/class/rfkill/rfkillN/{type,state} надо назначить владельца bluetooth:net_bt_stack, а файлу state — еще и права доступа 0664. Сделаем это и попытаемся активировать Bluetooth в настройках Android. Увы, но бегунок элемента управления снова возвращается в положение «Выкл.».
На этом этапе возникает соблазн раздобыть утилиты hciconfig и hcitool, чтобы продолжить настраивать подсистему Bluetooth над ядром Linux, но это тупиковый путь. Наша задача — заставить работать Bluetooth в Android. А для этого надо принять, что задача обеспечить работу драйвера на уровне ядра выполнена, и обратиться к нашей схеме за следующей целью. Ей оказалась «библиотека производителя» libbt-vendor.so — именно она должна обеспечить интерфейс между драйвером ядра и подсистемой Bluetooth в Android.
WWW
Для автоматизации описанной выше работы — получения исходных текстов ядра, его настройки и сборки модуля — можешь воспользоваться моими сценариями на bash.
БИБЛИОТЕКА ВЗАИМОДЕЙСТВИЯ С ДРАЙВЕРОМ
С библиотекой libbt-vendor.so дело оказалось несколько сложнее, чем с драйвером. На сайте с исходниками Android обнаружились только материалы по библиотекам для адаптеров на чипах Realtek и Broadcom. Единственный вселяющий надежду репозиторий на GitHub с описанием «A libbt-vendor.so for usb bluetooth on Android» датирован сентябрем 2014 года и содержит единственный коммит — форк какого‑то давно исчезнувшего источника.
Выходит, задача не имеет решения? Или все‑таки попробовать? Эрнест Хемингуэй в романе «По ком звонит колокол» писал: есть только один способ убедиться в том, что приказ невыполним, — попытаться его выполнить. Такой подход не всегда рационален с прагматической точки зрения, но по крайней мере даже в случае неудачи позволит заявить: «Я сделал все, что мог. Кто может — пусть сделает лучше!» Поэтому продолжаем. В конце концов, цена нашей неудачи ничтожна в сравнении с ситуациями, в которых оказывались герои Хемингуэя.
В качестве сборочной платформы будем использовать ту же виртуальную машину, что и для сборки модуля ядра, — ее ресурсов более чем достаточно. Чтобы получить динамическую библиотеку для Android, потребуется набор инструментов Android NDK, включающий кросс‑компилятор и заголовочные файлы. Поскольку целевая система — Android 7.1.2 Nougat, я выбрал инструментарий версии r16b, соответствующий периоду расцвета этой системы. С таким же успехом можно взять r14b или r15c, но другие версии потребуют серьезной адаптации исходников.
Чтобы собрать библиотеку libbt-vendor.so, поддерживающую USB-адаптеры Bluetooth, потребуются:
- исходные коды этой библиотеки
libbt-usb-master.zip, полученные из репозиторияliangxiaoju/libbt-usb; - исходные коды частей системы Android
utils.tar.gz,cutils.tar.gzиlog.tar.gzиз ветвиnougat-release(которая соответствует седьмой версии) с android.googlesource.com; - исходные тексты подсистемы Bluedroid
bluedroid.tar.gzсамой последней версии из того же репозитория; - файл библиотеки
libcutils.soиз каталога/system/libфайловой системы телеприставки.
Эти ингредиенты надо скомпоновать в иерархическую файловую структуру проекта NDK. В дальнейшем предполагается, что дистрибутив NDK распакован в каталог $HOME/tvbox, а для проекта создан подкаталог $HOME/tvbox/libbt-usb-master, внутри которого:
jni— содержимое каталогаlibbt-usb-master, находящегося в архивеlibbt-usb-master.zip;jni/include/utils— содержимое архиваutils.tar.gz;jni/include/cutils— содержимое архиваcutils.tar.gz;jni/include/log— содержимое архиваlog.tar.gz;jni/lib/libcutils.so— двоичный файл, полученный с телеприставки;external/bluetooth/bluedroid— содержимое архиваbluedroid.tar.gz.
Помимо этого, надо создать файл tvbox/libbt-usb-master/jni/Application.mk, в котором будет задана минимальная версия Android API и архитектура целевой системы:
PP_PLATFORM := android-21
PP_ABI := armeabi-v7a
WWW
Ты можешь использовать мои скрипты для получения исходников и формирования файлового дерева проекта NDK. Скрипт vendor-prepare.sh дополнительно модифицирует исходники, без чего сборка проекта не будет успешной.
Теперь процесс сборки можно запускать из каталога tvbox/libbt-usb-master:
$ ../android-ndk-r16b/ndk-build
Во время сборки будут выданы предупреждения:
- об отсутствии обработчиков для операций
BT_VND_OP_SET_AUDIO_STATEиBT_VND_OP_EPILOGв селекторе switch (opcode) файлаjni/src/bt_vendor_hci.c; - о повторном определении константы
HCI_MAX_FRAME_SIZEв файлеjni/src/hci.h.
Второе предупреждение можно смело игнорировать, а что до первого, то пока остается надеяться, что оно касается аудиопрофилей Bluetooth и не отразится на работе джойстика.
Собранная библиотека находится по пути tvbox/libbt-usb-master/libs/armeabi-v7a/libbt-vendor.so. Ее надо записать в каталог /system/vendor/lib телеприставки, после чего можно приступать к испытаниям. Перед этим, конечно, не будет лишним проверить, что адаптер включен в USB, его драйвер загружен, а файлам в подкаталоге /sys/class/rfkill/rfkillN/ даны необходимые разрешения, как это было описано выше.
Открываем настройки Android, включаем Bluetooth — и приставка сразу выключается. Включаем приставку и повторяем процедуру — результат тот же, отрицательный. Обидно, однако это свидетельствует, что мы чего‑то достигли и Android взаимодействует с драйвером для Linux. Пусть и в такой неудачной форме.
Взглянем еще раз на схему, чтобы оценить пройденный путь. Но что это? Из схемы видно, что библиотека libbt-vendor.so использует настройки, которые записаны в файле /system/etc/bluetooth/bt_vendor.conf, а на текущий момент там указано, что адаптер Bluetooth будет подключаться к последовательному порту. Мы подключаем его к шине USB, но какими тогда должны быть параметры?
Заглядываем в исходники libbt-vendor.so и в каталоге tvbox/libbt-usb-master/jni/conf находим эталонный bt_vendor.conf. Берем его и заменяем только два параметра:
HCIDevice = N, гдеN— номер Bluetooth-адаптера, который указан в пути/sys/class/rfkill/rfkillN/;Type = hci, то есть Bluetooth-адаптер напрямую предоставляет интерфейс HCI.
Запишем исправленный конфигурационный файл на приставку вместо существующего и повторим испытание. После попытки включить Bluetooth система сообщает, что ищет устройства. Все работает!
ДОРАБОТКИ
Со временем я столкнулся с новой проблемой: приставка иногда переставала видеть контроллер, и для восстановления его работы нужно было перезагружать и его, и приставку. Это убивало всю радость!
Вскоре выяснилось, что стабильность работы этой связки сильно зависит от расстояния между приставкой и контроллером. По всей видимости, виной тому — слабая связь между миниатюрным адаптером и контроллером, который может полностью прятаться в руках. Было эмпирически установлено, что радиус нормальной работы — это 1,5–2 метра от приставки.
Спать спокойно мешали и два предупреждения об ошибках, которые я проигнорировал при сборке интерфейсной библиотеки. Давай поищем константу по файлам в каталоге libbt-usb-master:
$ grep -R 'BT_VND_OP_EPILOG' *
Я нашел упоминание в заголовочном файле external/bluetooth/bluedroid/hci/include/bt_vendor_lib.h. Он наряду с перечнем идентификаторов сообщений содержит описание правил их обработки. Оттуда можно узнать, что сообщение BT_VND_OP_SET_AUDIO_STATE отправляется, чтобы проинформировать о состоянии звукового устройства, и в нашем случае его действительно можно игнорировать. А вот сообщение BT_VND_OP_EPILOG говорит о завершении работы с устройством, и его нужно отправлять стеку Bluetooth, чтобы сообщить, что устройство можно отключать вызовом функции epilog_cb.
Дополним конструкцию множественного выбора в файле libbt-usb-master/jni/src/bt_vendor_hci.c следующими строками по аналогии с другими обработчиками:
case BT_VND_OP_SET_AUDIO_STATE:
break;
case BT_VND_OP_EPILOG:
if (bt_vendor_cbacks) {
ALOGE ("vendor lib op epilog done");
bt_vendor_cbacks -> epilog_cb (BT_VND_OP_RESULT_SUCCESS);
}
break;
После этого компиляция библиотеки не вызывает вопросов. Однако нельзя исключать, что в каких‑то случаях обработка сообщений требует более сложных действий. Каких именно? Чтобы ответить на этот вопрос, надо глубже погрузиться в принципы взаимодействия подсистемы Bluetooth с USB-адаптером. Возможно, кто‑нибудь из читателей увидит в этом свою задачу, решит ее и расскажет об этом!
ВЫВОДЫ
Итак, задача полностью решена. Давай напоследок вспомним и систематизируем проделанные шаги, чтобы в случае надобности повторить их с другим устройством. Мне потребовалось:
- собрать и установить драйвер USB-адаптера, представляющий собой модуль ядра
/system/lib/modules/btusb.ko; - адаптировать исходники динамической библиотеки интерфейса между подсистемой Bluetooth и драйвером адаптера
libbt-vendor.soк заголовочным файлам и инструментам NDK; - подготовить проект NDK, собрать и установить файл библиотеки
/system/vendor/lib/libbt-vendor.so; - актуализировать конфигурационный файл
/system/etc/bluetooth/bt_vendor.conf.
Помимо этого, для автоматизации запуска модуля ядра и установки разрешений на виртуальные файлы при загрузке ОС я сделал конфигурационный файл системы инициализации /system/etc/init/btusb.rc со следующим содержимым:
on boot
insmod /system/lib/modules/btusb.ko
chown bluetooth net_bt_stack /sys/class/rfkill/rfkill0/type
chown bluetooth net_bt_stack /sys/class/rfkill/rfkill0/state
chmod 0664 /sys/class/rfkill/rfkill0/state
В имени rfkill0 цифру 0 может потребоваться заменить другим номером, который присваивается USB-адаптеру операционной системой.
Вот и все. Это был не самый легкий путь, зато мы узнали много нового!
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei