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 ff53d5ef..3acc5619 100644 --- a/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt +++ b/app/wfbngrtl8812/src/main/cpp/CMakeLists.txt @@ -69,6 +69,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 @@ -89,12 +103,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 2e374a7b..c4723163 100644 --- a/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp +++ b/app/wfbngrtl8812/src/main/cpp/WfbngLink.cpp @@ -34,6 +34,54 @@ #undef TAG #define TAG "pixelpilot" +namespace { + +// Finds the vendor-specific Wi-Fi interface before libusb claims it. +// RTL8812BU / RTL8822BU 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; @@ -104,12 +152,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 @@ -136,7 +190,7 @@ int WfbngLink::run(JNIEnv *env, jobject context, jint wifiChannel, jint bw, jint if (stop_requested(fd)) { __android_log_print(ANDROID_LOG_WARN, TAG, "stop requested for fd=%d before bring-up, aborting", fd); rtl_devices.erase(fd); - libusb_release_interface(dev_handle, 0); + libusb_release_interface(dev_handle, wifi_interface); libusb_exit(ctx); return -1; } @@ -158,12 +212,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, @@ -178,7 +243,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, @@ -189,7 +254,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, @@ -265,7 +330,7 @@ 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); libusb_exit(ctx); return -1; } @@ -283,7 +348,7 @@ 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); libusb_exit(ctx); return 0; @@ -609,4 +674,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 +}