Driving a Google Coral USB Accelerator (Edge TPU) from a non-rooted Android phone via Termux — no /dev/bus/usb access, no root, no libusb device-open. Everything goes through the file descriptor that termux-usb -e hands us and the kernel USBDEVFS_CONTROL ioctl (allowed on that fd).
A userspace DFU flash driver and compilation patchset to drive the Google Coral USB Accelerator on non-rooted Android/Termux hosts. Version: 0.1.0.
The Coral USB Accelerator ships uninitialized (1a6e:089a, a DFU 1.1 device), must be DFU-flashed with Google's apex firmware, and then re-enumerates as 18d1:9302. On a rooted Linux host, the stock libedgetpu runtime handles this. On a non-rooted Android/Termux host, standard libusb cannot scan or open the device. This repository implements a Userspace DFU driver over a termux-usb file descriptor, and provides a patch for libedgetpu to inject that file descriptor via the CORAL_USB_FD environment variable.
This project was split out of adb-android-control (which is a separate, ADB-only toolkit). The Coral USB VID/PIDs that briefly lived on that repo's feat/usb-coral-edge-tpu branch are carried here in get_usb.py.
| Path | What it is |
|---|---|
coral_dfu.py |
Userspace DFU driver: reads the device descriptor, issues DFU_GETSTATUS/DFU_GETSTATE, and optionally DFU-downloads a firmware blob in wTransferSize chunks. |
coral_dfu_wrap.sh |
termux-usb -e wrapper for coral_dfu.py (fd arrives as an arg). |
coral_flash_wrap.sh |
Wrapper that DFU-flashes the apex firmware (defaults to the blob inside libedgetpu_src/driver/usb/; override with $2). |
get_usb.py |
Reads a USB device descriptor from the termux-usb fd and prints vendor / product / known-device name. Includes the Coral IDs. |
usb_deep.py, usb_raw.py |
Lower-level USB descriptor probes used during bring-up. |
usb_deep_wrap.sh |
termux-usb -e wrapper for usb_deep.py. |
libedgetpu-research/ |
Tracked backup of the fd-patch research: LIBEDGETPU_FD_PATCH.md, PATCH_NOTES.md, BUILD_FEASIBILITY.md, build_termux.sh, and libedgetpu-local-changes.patch (the local diff against upstream libedgetpu). |
libedgetpu_src/ |
Not tracked (see .gitignore). A working clone of github.com/google-coral/libedgetpu with local modifications (driver/usb/local_usb_device.cc, makefile_build/Makefile) — those changes are captured as the patch in libedgetpu-research/. |
The apex_latest_single_ep.bin / apex_latest_multi_ep.bin blobs live in libedgetpu_src/driver/usb/. coral_flash_wrap.sh points there by default.
# identify the attached device
termux-usb -l
termux-usb -r -e ./coral_dfu_wrap.sh /dev/bus/usb/001/002 # status/probe
termux-usb -r -e ./coral_flash_wrap.sh /dev/bus/usb/001/002 # DFU-flash firmwaregraph TD
A[Attached USB Coral 1a6e:089a] --> B[termux-usb CLI Wrapper]
B -->|Grants Permission| C[File Descriptor fd Passed]
C --> D[coral_dfu.py Userspace Driver]
D -->|USBDEVFS_CONTROL ioctls| E{DFU Flash State Machine}
E -->|Download Firmware blocks| F[DFU Flash apex firmware]
F -->|Re-enumeration| G[Attached Edge TPU 18d1:9302]
| Status / Error | Root Cause | Mitigation |
|---|---|---|
Permission Denied / popup fails |
User clicked "Cancel" on the Android USB permission prompt or failed to call termux-usb -r. |
Re-run with -r flag to force prompt, and explicitly approve on Android popup. |
ioctl(USBDEVFS_CONTROL) fails |
The file descriptor has been closed by Termux or the device was unplugged. | Verify the USB cable connection. Check that the python script is receiving a valid, open file descriptor. |
DFU_GETSTATUS returns DFU_ERROR |
The Edge TPU is wedged in an invalid DFU state (often due to aborted downloads). | Unplug and replug the Coral Accelerator. Ensure you wait for DFU state transitions before writing new chunks. |
apex_latest_single_ep.bin missing |
The firmware binary blob is missing from path libedgetpu_src/driver/usb/. |
Run build_termux.sh to fetch TensorFlow resources, or place the .bin firmware file manually. |
- Golden Rule 1: No direct device node opens. Non-rooted Termux cannot open
/dev/bus/usb/...nodes directly. You must always pass the file descriptor generated bytermux-usbto the driver script. - Golden Rule 2: Explicit DFU Status Verification. Never write blocks of firmware back-to-back without querying
DFU_GETSTATUS. You must wait for the DFU state to transition todfuDNLOAD-IDLEbefore issuing the next block download. - Golden Rule 3: Re-enumeration awareness. When DFU flashing succeeds, the device automatically resets and changes its USB VID:PID from
1a6e:089ato18d1:9302. Any script monitoring the DFU process must terminate, as the old file descriptor becomes invalid. - Golden Rule 4: C++ Library Integration. To run Tensorflow Lite models on the Coral,
CORAL_USB_FDmust be exported with the new file descriptor value before loadinglibedgetpu.soin python.
Потребителски (userspace) DFU флаш драйвер и набор от пачове за компилация, предназначени за стартиране на Google Coral USB Accelerator на нерутнати Android/Termux хостове. Версия: 0.1.0.
Коралът се доставя неинициализиран (1a6e:089a, DFU 1.1 устройство), трябва да се флашне с DFU фърмуер (apex firmware) на Google и след това се преинициализира като 18d1:9302. На рутнати машини стандартната библиотека libedgetpu се справя с това автоматично. На нерутнат телефон през Termux стандартната библиотека не може да сканира или отвори устройството. Това хранилище имплементира DFU драйвер на потребителско ниво над файлов дескриптор от termux-usb и предоставя пач за libedgetpu за инжектиране на този файлов дескриптор чрез променливата CORAL_USB_FD.
Този проект е отделен от adb-android-control. Идентификационните USB VID/PID за Coral, които за кратко бяха в клон feat/usb-coral-edge-tpu на това хранилище, сега се съдържат тук в get_usb.py.
| Път | Описание |
|---|---|
coral_dfu.py |
Userspace DFU драйвер: чете дескриптора на устройството, изпраща DFU_GETSTATUS/DFU_GETSTATE и по желание изтегля фърмуерния блок в чанкове с размер wTransferSize. |
coral_dfu_wrap.sh |
Обвивка на termux-usb -e за coral_dfu.py (файловият дескриптор се подава като аргумент). |
coral_flash_wrap.sh |
Обвивка за DFU флашване на apex фърмуера (сочи към файла в libedgetpu_src/driver/usb/ по подразбиране). |
get_usb.py |
Чете USB дескриптор от файловия дескриптор на termux-usb и извежда производител / продукт / разпознато име. Включва и идентификаторите за Coral. |
usb_deep.py, usb_raw.py |
Ниско ниво сонди за USB дескриптори, използвани по време на разработването. |
usb_deep_wrap.sh |
Обвивка на termux-usb -e за usb_deep.py. |
libedgetpu-research/ |
Проследявана папка с проучвания: LIBEDGETPU_FD_PATCH.md, PATCH_NOTES.md, BUILD_FEASIBILITY.md, build_termux.sh и libedgetpu-local-changes.patch (разликите спрямо оригиналния libedgetpu). |
libedgetpu_src/ |
Непроследявана (виж .gitignore). Клонинг на github.com/google-coral/libedgetpu с локални промени — промените са записани като пач в libedgetpu-research/. |
Фърмуерните файлове apex_latest_single_ep.bin / apex_latest_multi_ep.bin се намират в libedgetpu_src/driver/usb/. coral_flash_wrap.sh сочи към тях по подразбиране.
# Идентифициране на свързаното устройство
termux-usb -l
termux-usb -r -e ./coral_dfu_wrap.sh /dev/bus/usb/001/002 # статус / сонда
termux-usb -r -e ./coral_flash_wrap.sh /dev/bus/usb/001/002 # DFU флашване на фърмуерgraph TD
A[Свързан USB Coral 1a6e:089a] --> B[termux-usb CLI Обвивка]
B -->|Оторизация от потребител| C[Подаване на файлов дескриптор fd]
C --> D[coral_dfu.py Userspace Драйвер]
D -->|USBDEVFS_CONTROL ioctls| E{DFU Флаш Краен автомат}
E -->|Инжектиране на фърмуер блокове| F[DFU Флаш на apex firmware]
F -->|Ре-инициализация| G[Свързан Edge TPU 18d1:9302]
| Статус / Грешка | Причина | Решение |
|---|---|---|
Permission Denied / грешка в попапа |
Потребителят е отказал достъп на попапа за Android USB или не е извикал termux-usb -r. |
Стартирайте отново с флаг -r за принудителен попап и изрично одобрете достъпа. |
Грешка в ioctl(USBDEVFS_CONTROL) |
Файловият дескриптор е затворен от Termux или устройството е изключено. | Проверете USB връзката. Уверете се, че python скриптът получава валиден, отворен файлов дескриптор. |
DFU_GETSTATUS връща DFU_ERROR |
Устройството е блокирало в невалидно DFU състояние (обикновено поради прекъснато флашване). | Изключете и включете отново Coral ускорителя. Уверете се, че чакате прехода на DFU състоянията пред писане на нови блокове. |
Липсващ apex_latest_single_ep.bin |
Фърмуерният двоичен файл липсва в пътя libedgetpu_src/driver/usb/. |
Изпълнете build_termux.sh за извличане на TensorFlow ресурси, или поставете фърмуерния файл ръчно. |
- Златно правило 1: Без директно отваряне на системния файл. Нерутнатите Termux конзоли нямат достъп до
/dev/bus/usb/.... Винаги подавайте файловия дескриптор, генериран отtermux-usb. - Златно правило 2: Изрично изчакване на DFU статус. Никога не изпращайте фърмуерни блокове един след друг без проверка на
DFU_GETSTATUS. Трябва да изчакате прехода на DFU състоянието къмdfuDNLOAD-IDLEпреди следващия блок. - Златно правило 3: Внимание при ре-инициализация. При успешно DFU флашване устройството се рестартира автоматично и променя своя USB VID:PID от
1a6e:089aна18d1:9302. Мониторингът трябва да се прекрати, тъй като старият файлов дескриптор става невалиден. - Златно правило 4: Интеграция с C++ Библиотеката. За стартиране на Tensorflow Lite модели на Coral, променливата
CORAL_USB_FDтрябва да бъде експортирана с новия дескриптор преди зареждането наlibedgetpu.soв python.