From 7f805492ec488139b51c2cf8a175c472bc107305 Mon Sep 17 00:00:00 2001 From: Roman Lut <11955117+RomanLut@users.noreply.github.com> Date: Mon, 25 May 2026 18:40:40 +0200 Subject: [PATCH 1/3] updated to latest devourer with rtl8821au support --- .../openipc/pixelpilot/UsbDeviceFilter.java | 4 +- app/src/main/res/xml/usb_device_filter.xml | 129 +++++++++++++++--- app/wfbngrtl8812/src/main/cpp/CMakeLists.txt | 22 ++- app/wfbngrtl8812/src/main/cpp/TxFrame.cpp | 8 +- app/wfbngrtl8812/src/main/cpp/TxFrame.h | 10 +- app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp | 6 +- app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp | 2 +- app/wfbngrtl8812/src/main/cpp/devourer | 2 +- 8 files changed, 143 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java b/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java index f59ecfd9..8ef029bd 100644 --- a/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java +++ b/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java @@ -31,8 +31,8 @@ public static List parseXml(Context context, int resourceId) String vendorIdString = parser.getAttributeValue(null, "vendor-id"); String productIdString = parser.getAttributeValue(null, "product-id"); - int vendorId = Integer.parseInt(vendorIdString, 16); - int productId = Integer.parseInt(productIdString, 16); + int vendorId = Integer.decode(vendorIdString); + int productId = Integer.decode(productIdString); UsbDeviceFilter device = new UsbDeviceFilter(vendorId, productId); devices.add(device); diff --git a/app/src/main/res/xml/usb_device_filter.xml b/app/src/main/res/xml/usb_device_filter.xml index f230ca27..bf76bd92 100644 --- a/app/src/main/res/xml/usb_device_filter.xml +++ b/app/src/main/res/xml/usb_device_filter.xml @@ -1,36 +1,121 @@ + product-id="0x8812" + vendor-id="0x0BDA" /> + product-id="0x881A" + vendor-id="0x0BDA" /> + product-id="0x881B" + vendor-id="0x0BDA" /> + product-id="0x0101" + vendor-id="0x2357" /> + product-id="0x0103" + vendor-id="0x2357" /> + product-id="0x010D" + vendor-id="0x2357" /> + product-id="0x010E" + vendor-id="0x2357" /> + product-id="0x17D2" + vendor-id="0x0B05" /> + product-id="0x0012" + vendor-id="0x2604" /> + product-id="0x0408" + vendor-id="0x0409" /> + product-id="0x3426" + vendor-id="0x0586" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt b/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt index 42811e99..d55a34f7 100644 --- a/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt +++ b/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt @@ -30,9 +30,23 @@ add_library(devourer STATIC ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8812PhyReg.h ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8812PwrSeq.c ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8812PwrSeq.h + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8814PhyCfg.h + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8814PhyReg.h + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8814PwrSeq.c + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8814PwrSeq.h + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8814_PostFwdlReplay.h + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8821APwrSeq.c + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8821APwrSeq.h + ${CMAKE_SOURCE_DIR}/devourer/hal/Hal8821PhyReg.h ${CMAKE_SOURCE_DIR}/devourer/hal/basic_types.h ${CMAKE_SOURCE_DIR}/devourer/hal/hal8812a_fw.c ${CMAKE_SOURCE_DIR}/devourer/hal/hal8812a_fw.h + ${CMAKE_SOURCE_DIR}/devourer/hal/hal8814a_fw.c + ${CMAKE_SOURCE_DIR}/devourer/hal/hal8814a_fw.h + ${CMAKE_SOURCE_DIR}/devourer/hal/hal8821a_fw.c + ${CMAKE_SOURCE_DIR}/devourer/hal/hal8821a_fw.h + ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8814a/Hal8814_PhyTables.c + ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8814a/Hal8814_PhyTables.h ${CMAKE_SOURCE_DIR}/devourer/hal/hal_com_reg.h ${CMAKE_SOURCE_DIR}/devourer/hal/rtl8812a_hal.h ${CMAKE_SOURCE_DIR}/devourer/hal/rtl8812a_recv.h @@ -52,10 +66,12 @@ add_library(devourer STATIC ${CMAKE_SOURCE_DIR}/devourer/src/HalModule.cpp ${CMAKE_SOURCE_DIR}/devourer/src/HalModule.h ${CMAKE_SOURCE_DIR}/devourer/src/ParsedRadioPacket.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/PhyTableLoader.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/PhyTableLoader.h ${CMAKE_SOURCE_DIR}/devourer/src/RadioManagementModule.cpp ${CMAKE_SOURCE_DIR}/devourer/src/RadioManagementModule.h - ${CMAKE_SOURCE_DIR}/devourer/src/Rtl8812aDevice.cpp - ${CMAKE_SOURCE_DIR}/devourer/src/Rtl8812aDevice.h + ${CMAKE_SOURCE_DIR}/devourer/src/RtlJaguarDevice.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/RtlJaguarDevice.h ${CMAKE_SOURCE_DIR}/devourer/src/RtlUsbAdapter.cpp ${CMAKE_SOURCE_DIR}/devourer/src/RtlUsbAdapter.h ${CMAKE_SOURCE_DIR}/devourer/src/SelectedChannel.h @@ -67,6 +83,8 @@ set_target_properties(devourer PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_ target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer) target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal) +target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal/phydm) +target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8814a) set_property(TARGET devourer PROPERTY CXX_STANDARD 20) # WFB-NG RTL8812 library diff --git a/app/wfbngrtl8812/src/main/cpp/TxFrame.cpp b/app/wfbngrtl8812/src/main/cpp/TxFrame.cpp index 1107e7f5..0536371b 100644 --- a/app/wfbngrtl8812/src/main/cpp/TxFrame.cpp +++ b/app/wfbngrtl8812/src/main/cpp/TxFrame.cpp @@ -3,7 +3,7 @@ #include "sodium/crypto_aead_chacha20poly1305.h" #include "sodium/crypto_box.h" #include "sodium/randombytes.h" -#include "src/Rtl8812aDevice.h" +#include "src/RtlJaguarDevice.h" #include "src/wifibroadcast.hpp" #include "src/zfex.h" @@ -422,7 +422,7 @@ UsbTransmitter::UsbTransmitter(int k, uint8_t *radiotapHeader, size_t radiotapHeaderLen, uint8_t frameType, - Rtl8812aDevice *device) + RtlJaguarDevice *device) : Transmitter(k, n, keypair, epoch, channelId), channelId_(channelId), currentOutput_(0), ieee80211Sequence_(0), radiotapHeader_(radiotapHeader), radiotapHeaderLen_(radiotapHeaderLen), frameType_(frameType), rtlDevice_(device) { @@ -795,7 +795,7 @@ void TxFrame::dataSource( } } -void TxFrame::run(Rtl8812aDevice *rtlDevice, TxArgs *arg) { +void TxFrame::run(RtlJaguarDevice *rtlDevice, TxArgs *arg) { // Decide if using VHT if (arg->bandwidth >= 80) { arg->vht_mode = true; @@ -964,4 +964,4 @@ void TxFrame::run(Rtl8812aDevice *rtlDevice, TxArgs *arg) { std::fprintf(stderr, "Error in TxFrame::run: %s\n", ex.what()); #endif } -} \ No newline at end of file +} diff --git a/app/wfbngrtl8812/src/main/cpp/TxFrame.h b/app/wfbngrtl8812/src/main/cpp/TxFrame.h index 72d37375..9453f4b9 100644 --- a/app/wfbngrtl8812/src/main/cpp/TxFrame.h +++ b/app/wfbngrtl8812/src/main/cpp/TxFrame.h @@ -6,7 +6,7 @@ extern "C" { #include "wfb-ng/src/zfex.h" // FEC library } -#include "devourer/src/Rtl8812aDevice.h" // Rtl8812aDevice definition +#include "devourer/src/RtlJaguarDevice.h" // RtlJaguarDevice definition #include "wfb-ng/src/wifibroadcast.hpp" // Wifibroadcast definitions // -- System / C++ Includes -- @@ -294,7 +294,7 @@ class UsbTransmitter : public Transmitter { uint8_t *radiotapHeader, size_t radiotapHeaderLen, uint8_t frameType, - Rtl8812aDevice *device); + RtlJaguarDevice *device); ~UsbTransmitter() override = default; @@ -314,7 +314,7 @@ class UsbTransmitter : public Transmitter { uint8_t *radiotapHeader_; size_t radiotapHeaderLen_; uint8_t frameType_; - Rtl8812aDevice *rtlDevice_; + RtlJaguarDevice *rtlDevice_; }; //------------------------------------------------------------- @@ -379,10 +379,10 @@ class TxFrame { /** * @brief Configures and runs the transmitter with the given arguments. - * @param rtlDevice The Rtl8812aDevice pointer (if using USB). + * @param rtlDevice The RtlJaguarDevice pointer (if using USB). * @param arg TxArgs structure with user parameters. */ - void run(Rtl8812aDevice *rtlDevice, TxArgs *arg); + void run(RtlJaguarDevice *rtlDevice, TxArgs *arg); /** * @brief Signals that the main loop should stop. diff --git a/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp b/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp index c7a364c7..8a2b4815 100644 --- a/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp +++ b/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp @@ -56,7 +56,7 @@ std::string generate_random_string(size_t length) { WfbngLink::WfbngLink(JNIEnv *env, jobject context) : current_fd(-1), adaptive_link_enabled(true), adaptive_tx_power(30) { initAgg(); - Logger_t log; + log = std::make_shared(); wifi_driver = std::make_unique(log); } @@ -218,7 +218,7 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint __android_log_print( ANDROID_LOG_ERROR, TAG, "radio link ID %d, radio PORT %d", args->link_id, args->radio_port); - Rtl8812aDevice *current_device = rtl_devices.at(fd).get(); + RtlJaguarDevice *current_device = rtl_devices.at(fd).get(); if (!usb_tx_thread) { init_thread(usb_tx_thread, [&]() { return std::make_unique([this, current_device, args] { @@ -588,4 +588,4 @@ extern "C" JNIEXPORT void JNICALL Java_com_openipc_wfbngrtl8812_WfbNgLink_native link->fec_recovered_to_3 = recTo3; link->fec_recovered_to_2 = recTo2; link->fec_recovered_to_1 = recTo1; -} \ No newline at end of file +} diff --git a/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp b/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp index 195cce6e..a917b96e 100644 --- a/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp +++ b/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp @@ -54,7 +54,7 @@ class WfbngLink { bool ldpc_enabled{true}; bool stbc_enabled{true}; - std::map> rtl_devices; + std::map> rtl_devices; std::unique_ptr link_quality_thread{nullptr}; bool should_clear_stats{false}; FecChangeController fec; diff --git a/app/wfbngrtl8812/src/main/cpp/devourer b/app/wfbngrtl8812/src/main/cpp/devourer index bbc7385b..01cad755 160000 --- a/app/wfbngrtl8812/src/main/cpp/devourer +++ b/app/wfbngrtl8812/src/main/cpp/devourer @@ -1 +1 @@ -Subproject commit bbc7385b9bce2098eab62ae37913a8879b994ef7 +Subproject commit 01cad7554a68ddd038e9cdf115562fa06202ff82 From 6dce96787b59b5cc16534db8b2a974817a48aa2c Mon Sep 17 00:00:00 2001 From: Roman Lut <11955117+RomanLut@users.noreply.github.com> Date: Tue, 14 Jul 2026 07:03:53 +0200 Subject: [PATCH 2/3] fixed merge conflings --- .../openipc/pixelpilot/UsbDeviceFilter.java | 12 +- .../openipc/pixelpilot/WfbLinkManager.java | 4 +- app/src/main/res/xml/usb_device_filter.xml | 110 +++++++++--------- 3 files changed, 67 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java b/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java index 8ef029bd..ebcd1b6f 100644 --- a/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java +++ b/app/src/main/java/com/openipc/pixelpilot/UsbDeviceFilter.java @@ -31,8 +31,8 @@ public static List parseXml(Context context, int resourceId) String vendorIdString = parser.getAttributeValue(null, "vendor-id"); String productIdString = parser.getAttributeValue(null, "product-id"); - int vendorId = Integer.decode(vendorIdString); - int productId = Integer.decode(productIdString); + int vendorId = parseHexId(vendorIdString); + int productId = parseHexId(productIdString); UsbDeviceFilter device = new UsbDeviceFilter(vendorId, productId); devices.add(device); @@ -42,4 +42,12 @@ public static List parseXml(Context context, int resourceId) } return devices; } + + private static int parseHexId(String value) { + if (value == null) { + throw new IllegalArgumentException("USB ID is missing"); + } + String normalized = value.trim().replaceFirst("^0[xX]", ""); + return Integer.parseInt(normalized, 16); + } } diff --git a/app/src/main/java/com/openipc/pixelpilot/WfbLinkManager.java b/app/src/main/java/com/openipc/pixelpilot/WfbLinkManager.java index 8580be69..f8175fd8 100644 --- a/app/src/main/java/com/openipc/pixelpilot/WfbLinkManager.java +++ b/app/src/main/java/com/openipc/pixelpilot/WfbLinkManager.java @@ -97,8 +97,8 @@ public Map getAttachedAdapters() { try { filters = UsbDeviceFilter.parseXml(context, R.xml.usb_device_filter); } catch (Exception e) { - e.printStackTrace(); - return null; + Log.e(TAG, "Unable to parse USB device filter", e); + return new HashMap<>(); } Map res = new HashMap<>(); diff --git a/app/src/main/res/xml/usb_device_filter.xml b/app/src/main/res/xml/usb_device_filter.xml index b0541d16..1774817c 100644 --- a/app/src/main/res/xml/usb_device_filter.xml +++ b/app/src/main/res/xml/usb_device_filter.xml @@ -1,73 +1,73 @@ + product-id="0x8812" + vendor-id="0x0BDA" /> + product-id="0x881A" + vendor-id="0x0BDA" /> + product-id="0x881B" + vendor-id="0x0BDA" /> + product-id="0x0101" + vendor-id="0x2357" /> + product-id="0x0103" + vendor-id="0x2357" /> + product-id="0x010D" + vendor-id="0x2357" /> + product-id="0x010E" + vendor-id="0x2357" /> + product-id="0x17D2" + vendor-id="0x0B05" /> + product-id="0x0012" + vendor-id="0x2604" /> + product-id="0x0408" + vendor-id="0x0409" /> + product-id="0x3426" + vendor-id="0x0586" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + product-id="0xA81A" + vendor-id="0x0BDA" /> + product-id="0xA82A" + vendor-id="0x0BDA" /> + product-id="0xE822" + vendor-id="0x0BDA" /> From f81226e9b429aacd3b6eebd6a9e5f986b660502e Mon Sep 17 00:00:00 2001 From: Roman Lut <11955117+RomanLut@users.noreply.github.com> Date: Tue, 14 Jul 2026 09:52:41 +0200 Subject: [PATCH 3/3] added rtl8822bu support --- app/src/main/res/xml/usb_device_filter.xml | 3 + app/wfbngrtl8812/src/main/cpp/CMakeLists.txt | 21 +++ app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp | 134 +++++++++++++++++-- app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp | 3 + app/wfbngrtl8812/src/main/cpp/devourer | 2 +- 5 files changed, 150 insertions(+), 13 deletions(-) diff --git a/app/src/main/res/xml/usb_device_filter.xml b/app/src/main/res/xml/usb_device_filter.xml index 1774817c..f28c0ecc 100644 --- a/app/src/main/res/xml/usb_device_filter.xml +++ b/app/src/main/res/xml/usb_device_filter.xml @@ -70,4 +70,7 @@ + diff --git a/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt b/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt index a7320129..87c1dc0b 100644 --- a/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt +++ b/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt @@ -44,6 +44,7 @@ add_library(devourer STATIC ${CMAKE_SOURCE_DIR}/devourer/src/TxMode.cpp ${CMAKE_SOURCE_DIR}/devourer/src/TxPower.cpp ${CMAKE_SOURCE_DIR}/devourer/src/LinkHealth.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/LaCapture.cpp ${CMAKE_SOURCE_DIR}/devourer/src/SignalStop.cpp ${CMAKE_SOURCE_DIR}/devourer/src/WiFiDriver.cpp ${CMAKE_SOURCE_DIR}/devourer/src/PhyTableLoader.cpp @@ -65,6 +66,20 @@ add_library(devourer STATIC ${CMAKE_SOURCE_DIR}/devourer/src/jaguar1/FrameParser.cpp ${CMAKE_SOURCE_DIR}/devourer/src/jaguar1/BbDbgportReader.cpp + # --- Jaguar2 (RTL8822BU / RTL8812BU) --- + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/RtlJaguar2Device.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/HalJaguar2.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/HalmacJaguar2Fw.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/HalmacJaguar2MacInit.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/Phy8822bTables.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/Halrf8822b.cpp + ${CMAKE_SOURCE_DIR}/devourer/hal/hal8822b_fw.c + ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8822b/Hal8822b_PhyTables.c + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/Phy8821cTables.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar2/Halrf8821c.cpp + ${CMAKE_SOURCE_DIR}/devourer/hal/hal8821c_fw.c + ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8821c/Hal8821c_PhyTables.c + # --- Jaguar3 shared (dispatchers compiled for any Jaguar3 variant) --- ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/RtlJaguar3Device.cpp ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/HalJaguar3.cpp @@ -72,6 +87,7 @@ add_library(devourer STATIC ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/HalmacJaguar3MacInit.cpp ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/RadioManagementJaguar3.cpp ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/PhyTableLoaderJaguar3.cpp + ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/PhydmRuntimeJaguar3.cpp ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/Phy8822cTables.cpp ${CMAKE_SOURCE_DIR}/devourer/src/jaguar3/Halrf8822c.cpp @@ -84,12 +100,17 @@ set_target_properties(devourer PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_ target_compile_definitions(devourer PUBLIC DEVOURER_HAVE_JAGUAR1=1 + DEVOURER_HAVE_JAGUAR2=1 + DEVOURER_HAVE_JAGUAR2_8822B=1 + DEVOURER_HAVE_JAGUAR2_8821C=1 DEVOURER_HAVE_JAGUAR3=1 DEVOURER_HAVE_JAGUAR3_8822E=1) target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer) target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/src) target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal) +target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8822b) +target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8821c) target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8822c) target_include_directories(devourer PUBLIC ${CMAKE_SOURCE_DIR}/devourer/hal/phydm/rtl8822e) target_link_libraries(devourer PUBLIC log) diff --git a/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp b/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp index 217a9214..4cfb39c3 100644 --- a/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp +++ b/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp @@ -40,6 +40,54 @@ *i = 42; \ } while (0) +namespace { + +// Finds the vendor-specific Wi-Fi interface before libusb claims it. +// RTL8812BU / RTL8812BU is a composite USB device: interfaces 0 and 1 belong to +// Bluetooth, while its Wi-Fi bulk endpoints are on interface 2. Assuming +// interface 0 works for RTL8812AU but claims the wrong function on that BU +// layout, so select the interface that actually provides bulk IN and OUT. +int findRtlWifiInterface(libusb_device_handle *dev_handle) { + if (dev_handle == nullptr) { + return 0; + } + + libusb_config_descriptor *config = nullptr; + if (libusb_get_active_config_descriptor(libusb_get_device(dev_handle), &config) != LIBUSB_SUCCESS) { + return 0; + } + + for (uint8_t interface_index = 0; interface_index < config->bNumInterfaces; interface_index++) { + const libusb_interface &interface = config->interface[interface_index]; + for (int alt_index = 0; alt_index < interface.num_altsetting; alt_index++) { + const libusb_interface_descriptor &descriptor = interface.altsetting[alt_index]; + bool has_bulk_in = false; + bool has_bulk_out = false; + for (uint8_t endpoint_index = 0; endpoint_index < descriptor.bNumEndpoints; endpoint_index++) { + const libusb_endpoint_descriptor &endpoint = descriptor.endpoint[endpoint_index]; + if ((endpoint.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK) { + continue; + } + if (endpoint.bEndpointAddress & LIBUSB_ENDPOINT_IN) { + has_bulk_in = true; + } else { + has_bulk_out = true; + } + } + if (descriptor.bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && has_bulk_in && has_bulk_out) { + const int interface_number = descriptor.bInterfaceNumber; + libusb_free_config_descriptor(config); + return interface_number; + } + } + } + + libusb_free_config_descriptor(config); + return 0; +} + +} + std::string generate_random_string(size_t length) { const std::string characters = "abcdefghijklmnopqrstuvwxyz"; std::random_device rd; @@ -94,6 +142,11 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint libusb_context *ctx = NULL; txFrame = std::make_shared(); + { + std::lock_guard lock(stop_request_mutex); + stop_requested_fds.erase(fd); + } + r = libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY); r = libusb_init(&ctx); if (r < 0) { @@ -109,12 +162,18 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint return r; } - if (libusb_kernel_driver_active(dev_handle, 0)) { - r = libusb_detach_kernel_driver(dev_handle, 0); + const int wifi_interface = findRtlWifiInterface(dev_handle); + if (libusb_kernel_driver_active(dev_handle, wifi_interface)) { + r = libusb_detach_kernel_driver(dev_handle, wifi_interface); __android_log_print(ANDROID_LOG_DEBUG, TAG, "libusb_detach_kernel_driver: %d", r); } - r = libusb_claim_interface(dev_handle, 0); - __android_log_print(ANDROID_LOG_DEBUG, TAG, "Creating driver and device for fd=%d", fd); + r = libusb_claim_interface(dev_handle, wifi_interface); + if (r != LIBUSB_SUCCESS) { + __android_log_print(ANDROID_LOG_ERROR, TAG, "libusb_claim_interface(%d) failed: %d", wifi_interface, r); + libusb_exit(ctx); + return r; + } + __android_log_print(ANDROID_LOG_DEBUG, TAG, "Creating driver and device for fd=%d interface=%d", fd, wifi_interface); devourer::DeviceConfig cfg; // TX+RX on the one claimed handle. Jaguar3 (RTL8812EU/8822EU) must know @@ -127,11 +186,24 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint rtl_devices[fd] = wifi_driver->CreateRtlDevice(dev_handle, ctx, nullptr, cfg); if (!rtl_devices.at(fd)) { + rtl_devices.erase(fd); libusb_exit(ctx); __android_log_print(ANDROID_LOG_ERROR, TAG, "CreateRtlDevice error"); return -1; } + { + std::lock_guard lock(stop_request_mutex); + if (stop_requested_fds.erase(fd) != 0) { + __android_log_print(ANDROID_LOG_INFO, TAG, "RTL device fd %d was stopped during startup", fd); + rtl_devices.at(fd)->Stop(); + libusb_release_interface(dev_handle, wifi_interface); + rtl_devices.erase(fd); + libusb_exit(ctx); + return 0; + } + } + uint8_t *video_channel_id_be8 = reinterpret_cast(&video_channel_id_be); uint8_t *udp_channel_id_be8 = reinterpret_cast(&udp_channel_id_be); uint8_t *mavlink_channel_id_be8 = reinterpret_cast(&mavlink_channel_id_be); @@ -149,12 +221,23 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint uint8_t antenna[4] = {1, 1, 1, 1}; std::lock_guard lock(agg_mutex); + // Every device parser returns the complete 802.11 frame, + // including its four-byte FCS. wfb-ng authenticates only the + // payload, after both the MAC header and FCS are removed. + constexpr size_t fcs_length = 4; + if (packet.Data.size() < sizeof(ieee80211_header) + fcs_length) { + return; + } + + const size_t wfb_packet_length = + packet.Data.size() - sizeof(ieee80211_header) - fcs_length; + if (frame.MatchesChannelID(video_channel_id_be8)) { SignalQualityCalculator::get_instance().add_rssi(packet.RxAtrib.rssi[0], packet.RxAtrib.rssi[1]); SignalQualityCalculator::get_instance().add_snr(packet.RxAtrib.snr[0], packet.RxAtrib.snr[1]); video_aggregator->process_packet(packet.Data.data() + sizeof(ieee80211_header), - packet.Data.size() - sizeof(ieee80211_header) - 4, + wfb_packet_length, 0, antenna, rssi, @@ -169,7 +252,7 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint } } else if (frame.MatchesChannelID(mavlink_channel_id_be8)) { mavlink_aggregator->process_packet(packet.Data.data() + sizeof(ieee80211_header), - packet.Data.size() - sizeof(ieee80211_header) - 4, + wfb_packet_length, 0, antenna, rssi, @@ -180,7 +263,7 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint NULL); } else if (frame.MatchesChannelID(udp_channel_id_be8)) { udp_aggregator->process_packet(packet.Data.data() + sizeof(ieee80211_header), - packet.Data.size() - sizeof(ieee80211_header) - 4, + wfb_packet_length, 0, antenna, rssi, @@ -240,6 +323,20 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint // Blocking RX loop on this thread; devourer pumps the libusb events // itself. Returns once StopRxLoop() is called. + { + std::lock_guard lock(stop_request_mutex); + if (stop_requested_fds.erase(fd) != 0) { + __android_log_print(ANDROID_LOG_INFO, TAG, "RTL device fd %d stopped before RX loop", fd); + current_device->Stop(); + libusb_release_interface(dev_handle, wifi_interface); + rtl_devices.erase(fd); + if (current_fd == fd) { + current_fd = -1; + } + libusb_exit(ctx); + return 0; + } + } current_device->StartRxLoop(packetProcessor); } catch (const std::runtime_error &error) { __android_log_print(ANDROID_LOG_ERROR, TAG, "runtime_error: %s", error.what()); @@ -251,7 +348,11 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint if (dev) { dev->Stop(); } - libusb_release_interface(dev_handle, 0); + libusb_release_interface(dev_handle, wifi_interface); + rtl_devices.erase(fd); + if (current_fd == fd) { + current_fd = -1; + } libusb_exit(ctx); return -1; } @@ -269,16 +370,25 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint dev->Stop(); } - r = libusb_release_interface(dev_handle, 0); + r = libusb_release_interface(dev_handle, wifi_interface); __android_log_print(ANDROID_LOG_DEBUG, TAG, "libusb_release_interface: %d", r); + rtl_devices.erase(fd); + if (current_fd == fd) { + current_fd = -1; + } libusb_exit(ctx); return 0; } void WfbngLink::stop(JNIEnv *env, jobject context, jint fd) { + { + std::lock_guard lock(stop_request_mutex); + stop_requested_fds.insert(fd); + } if (rtl_devices.find(fd) == rtl_devices.end()) { - __android_log_print(ANDROID_LOG_ERROR, TAG, "rtl_devices.find(%d) == rtl_devices.end()", fd); - CRASH(); + // run() may already have removed a driver that failed to initialise. + // Stop is also called during the Java-side teardown in that case. + __android_log_print(ANDROID_LOG_WARN, TAG, "No active RTL device for fd %d", fd); return; } auto dev = rtl_devices.at(fd).get(); @@ -591,4 +701,4 @@ extern "C" JNIEXPORT void JNICALL Java_com_openipc_wfbngrtl8812_WfbNgLink_native link->fec_recovered_to_3 = recTo3; link->fec_recovered_to_2 = recTo2; link->fec_recovered_to_1 = recTo1; -} \ No newline at end of file +} diff --git a/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp b/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp index 24f74c5b..a38a586e 100644 --- a/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp +++ b/app/wfbngrtl8812/src/main/cpp/WfbngLink.hpp @@ -18,6 +18,7 @@ extern "C" { #include #include #include +#include #include #include // Added for std::vector @@ -97,6 +98,8 @@ class WfbngLink { const char *keyPath = "/data/user/0/com.openipc.pixelpilot/files/gs.key"; std::recursive_mutex thread_mutex; + std::mutex stop_request_mutex; + std::set stop_requested_fds; std::unique_ptr wifi_driver; std::shared_ptr txFrame; uint32_t video_channel_id_be; diff --git a/app/wfbngrtl8812/src/main/cpp/devourer b/app/wfbngrtl8812/src/main/cpp/devourer index 73f1cb4b..1511c8ef 160000 --- a/app/wfbngrtl8812/src/main/cpp/devourer +++ b/app/wfbngrtl8812/src/main/cpp/devourer @@ -1 +1 @@ -Subproject commit 73f1cb4bcc6d1cfd6c5560f6637ce34aeaa94803 +Subproject commit 1511c8ef78430bc171c8dab83dd154cc2daf2caa