Категория > Новости > Bluetooth для андроида. Портируем с Linux на Android драйвер USB-адаптера - «Новости»

Bluetooth для андроида. Портируем с Linux на Android драйвер USB-адаптера - «Новости»


5-01-2022, 00:01. Автор: Becker
точ­ки зре­ния прог­раммис­та, цен­траль­ный ком­понент под­систе­мы Bluetooth в Android — сис­темная служ­ба Bluetooth (пред­став­ляющая собой при­ложе­ние для Android), которая через Binder IPC дает при­ложе­ниям дос­туп к услу­гам Bluetooth-про­филей, а сама исполь­зует при этом JNI-интерфей­сы, реали­зован­ные на уров­не HAL и ведущие к ком­понен­там сте­ка Bluetooth и рас­ширени­ям пос­тавщи­ка (в дво­ичных биб­лиоте­ках).
Ар­хитек­тура под­систе­мы Bluetooth в Android 7

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


Ниж­ний уро­вень под­систе­мы Bluetooth в Android

Ос­талось выяс­нить, на каком имен­но уров­не у нас проб­лема, которая меша­ет адап­теру взять и зарабо­тать.


Опе­раци­онная сис­тема 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 '.conf'

До­бавив эти ком­понен­ты на схе­му, я получил сле­дующую кар­тину.


Вза­имос­вязь ком­понен­тов под­систе­мы Bluetooth в опе­раци­онной сис­теме иссле­дуемой ТВ‑прис­тавки

Соб­ранной информа­ции дос­таточ­но, что­бы пред­положить, что драй­веры на ТВ‑прис­тавке не под­держи­вают Bluetooth-адап­теры на кон­трол­лерах CSR. Пос­коль­ку ядро име­ет под­дер­жку модулей, мож­но попытать­ся испра­вить дело, соб­рав соот­ветс­тву­ющий модуль с необ­ходимым драй­вером.


 

Модуль ядра с драйвером USB-адаптера


В качес­тве плат­формы для сбор­ки я исполь­зовал 64-бит­ную ОС Bodhi Linux 6.0.0 (осно­ван­ную на Ubuntu 20.04 LTS). У нее есть минима­лис­тичный уста­новоч­ный образ, в который вхо­дят инс­тру­мен­ты метапа­кета build essential. Для наших работ дос­таточ­но вир­туаль­ной машины с опе­ратив­ной памятью 1 Гбайт и накопи­телем 20 Гбайт. Пос­ле уста­нов­ки сис­темы и син­хро­низа­ции с репози­тори­ем надо уста­новить допол­нитель­ные пакеты unzip, python2 и libncurses5 и соз­дать сим­воличес­кую ссыл­ку на интер­пре­татор:


Соз­дадим каталог для работы:


Что­бы соб­рать модуль драй­вера, нуж­ны исходни­ки ядра Linux той вер­сии, которая исполь­зует­ся в опе­раци­онной сис­теме ТВ‑прис­тавки, в дан­ном слу­чае 3.10.104. К счастью, на GitHub быс­тро нашел­ся репози­торий с ядра­ми Linux, адап­тирован­ными для устрой­ств на плат­форме Rockchip. Забира­ем исходни­ки из него:


Те­перь надо рас­паковать получен­ный архив в рабочий каталог и про­верить, соот­ветс­тву­ет ли вер­сия ядра ожи­дани­ям:



$ 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/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 как модуля ядра. Пос­ле это­го выпол­ним коман­ду


Ис­ходные тек­сты ядра скон­фигури­рова­ны и готовы к сбор­ке модуля. Собирать будем с помощью инс­тру­мен­тов Linaro. Их нуж­но извлечь из архи­ва gcc-linaro-4.9.4-2017.01-x86_64_arm-eabi.tar.xz в каталог tvbox, пос­ле чего из под­катало­га kernel-release-3.10 выпол­няем коман­ду


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 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 года и содер­жит единс­твен­ный ком­мит — форк какого‑то дав­но исчезнув­шего источни­ка.



Перейти обратно к новости