From d961247b9a6098d3921c06b4dd61e566eb5d381a Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Sun, 27 Oct 2024 03:42:16 +0100 Subject: [PATCH] Add more information about permission errors --- .../CaptureDeviceSpecific/3dscapture_ftd3.hpp | 3 +- .../ISNitro/usb_is_nitro_acquisition.hpp | 3 +- .../CaptureDeviceSpecific/dscapture_ftd2.hpp | 3 +- .../usb_ds_3ds_capture.hpp | 3 +- include/CaptureDeviceSpecific/usb_generic.hpp | 1 + include/capture_structs.hpp | 3 +- include/devicecapture.hpp | 9 +++++ include/utils.hpp | 1 + .../CaptureDeviceSpecific/3dscapture_ftd3.cpp | 17 +++++++++- .../ISNitro/usb_is_nitro_acquisition.cpp | 11 ++++-- .../CaptureDeviceSpecific/dscapture_ftd2.cpp | 2 +- .../usb_ds_3ds_capture.cpp | 6 +++- source/CaptureDeviceSpecific/usb_generic.cpp | 34 +++++++++++++++++++ source/cc3dsfs.cpp | 2 +- source/devicecapture.cpp | 30 ++++++++++++---- source/utils.cpp | 13 +++++++ 16 files changed, 123 insertions(+), 18 deletions(-) diff --git a/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp b/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp index d079026..a2da5d2 100644 --- a/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp +++ b/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp @@ -6,8 +6,9 @@ #include "hw_defs.hpp" #include "capture_structs.hpp" #include "display_structs.hpp" +#include "devicecapture.hpp" -void list_devices_ftd3(std::vector &devices_list); +void list_devices_ftd3(std::vector &devices_list, std::vector &no_access_list); bool connect_ftd3(bool print_failed, CaptureData* capture_data, CaptureDevice* device); void ftd3_capture_main_loop(CaptureData* capture_data); void ftd3_capture_cleanup(CaptureData* capture_data); diff --git a/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.hpp b/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.hpp index 9bbecb8..dfc1709 100644 --- a/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.hpp +++ b/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.hpp @@ -6,8 +6,9 @@ #include "hw_defs.hpp" #include "capture_structs.hpp" #include "display_structs.hpp" +#include "devicecapture.hpp" -void list_devices_is_nitro(std::vector &devices_list); +void list_devices_is_nitro(std::vector &devices_list, std::vector &no_access_list); bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device); void is_nitro_acquisition_main_loop(CaptureData* capture_data); void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data); diff --git a/include/CaptureDeviceSpecific/dscapture_ftd2.hpp b/include/CaptureDeviceSpecific/dscapture_ftd2.hpp index c809c70..55a487f 100644 --- a/include/CaptureDeviceSpecific/dscapture_ftd2.hpp +++ b/include/CaptureDeviceSpecific/dscapture_ftd2.hpp @@ -6,8 +6,9 @@ #include "hw_defs.hpp" #include "capture_structs.hpp" #include "display_structs.hpp" +#include "devicecapture.hpp" -void list_devices_ftd2(std::vector &devices_list); +void list_devices_ftd2(std::vector &devices_list, std::vector &no_access_list); bool connect_ftd2(bool print_failed, CaptureData* capture_data, CaptureDevice* device); void ftd2_capture_main_loop(CaptureData* capture_data); void ftd2_capture_cleanup(CaptureData* capture_data); diff --git a/include/CaptureDeviceSpecific/usb_ds_3ds_capture.hpp b/include/CaptureDeviceSpecific/usb_ds_3ds_capture.hpp index cf026dd..532ac6c 100644 --- a/include/CaptureDeviceSpecific/usb_ds_3ds_capture.hpp +++ b/include/CaptureDeviceSpecific/usb_ds_3ds_capture.hpp @@ -6,8 +6,9 @@ #include "hw_defs.hpp" #include "capture_structs.hpp" #include "display_structs.hpp" +#include "devicecapture.hpp" -void list_devices_usb_ds_3ds(std::vector &devices_list); +void list_devices_usb_ds_3ds(std::vector &devices_list, std::vector &no_access_list); bool connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device); void usb_capture_main_loop(CaptureData* capture_data); void usb_capture_cleanup(CaptureData* capture_data); diff --git a/include/CaptureDeviceSpecific/usb_generic.hpp b/include/CaptureDeviceSpecific/usb_generic.hpp index 04c4ce0..cfc47c3 100644 --- a/include/CaptureDeviceSpecific/usb_generic.hpp +++ b/include/CaptureDeviceSpecific/usb_generic.hpp @@ -7,5 +7,6 @@ void usb_init(); void usb_close(); bool usb_is_initialized(); libusb_context* get_usb_ctx(); +int get_usb_total_filtered_devices(const uint16_t valid_vids[], size_t num_vids, const uint16_t valid_pids[], size_t num_pids); #endif diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index 24c4bf8..54860c1 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -126,7 +126,8 @@ struct CaptureDevice { struct CaptureStatus { CaptureDevice device; - std::string error_text; + std::string graphical_error_text; + std::string detailed_error_text; bool new_error_text; volatile int curr_in = 0; volatile int cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM; diff --git a/include/devicecapture.hpp b/include/devicecapture.hpp index 374416e..4a3bb67 100755 --- a/include/devicecapture.hpp +++ b/include/devicecapture.hpp @@ -6,12 +6,21 @@ #include "capture_structs.hpp" #include "frontend.hpp" +struct no_access_recap_data { + no_access_recap_data(std::string name) : name(name), vid(-1), pid(-1) {} + no_access_recap_data(uint16_t vid, uint16_t pid) : name(""), vid(vid), pid(pid) {} + std::string name; + int vid; + int pid; +}; + void capture_init(); void capture_close(); bool connect(bool print_failed, CaptureData* capture_data, FrontendData* frontend_data); void captureCall(CaptureData* capture_data); void capture_error_print(bool print_failed, CaptureData* capture_data, std::string error_string); +void capture_error_print(bool print_failed, CaptureData* capture_data, std::string graphical_string, std::string detailed_string); uint64_t get_audio_n_samples(CaptureData* capture_data, uint64_t read); uint64_t get_video_in_size(CaptureData* capture_data); std::string get_name_of_device(CaptureStatus* capture_status); diff --git a/include/utils.hpp b/include/utils.hpp index c228a45..a0c881d 100755 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -37,6 +37,7 @@ uint32_t from_le(uint32_t value); uint32_t from_be(uint32_t value); uint16_t from_le(uint16_t value); uint16_t from_be(uint16_t value); +std::string to_hex(uint16_t value); std::string get_float_str_decimals(float value, int decimals); void init_threads(void); diff --git a/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp b/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp index ad977b2..097ceb0 100644 --- a/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp +++ b/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp @@ -8,6 +8,9 @@ #define FT_ASYNC_CALL FT_ReadPipeAsync #endif #include +#if defined(USE_IS_NITRO_USB) || defined(USE_DS_3DS_USB) +#include "usb_generic.hpp" +#endif #include #include @@ -23,9 +26,14 @@ #define FIFO_CHANNEL 0 #endif +#define FTD3XX_VID 0x0403 + #define REAL_SERIAL_NUMBER_SIZE 16 #define SERIAL_NUMBER_SIZE (REAL_SERIAL_NUMBER_SIZE+1) +const uint16_t ftd3xx_valid_vids[] = {FTD3XX_VID}; +const uint16_t ftd3xx_valid_pids[] = {0x601e, 0x601f, 0x602a, 0x602b, 0x602c, 0x602d, 0x602f}; + static bool get_is_bad_ftd3xx(); static bool get_skip_initial_pipe_abort(); @@ -75,11 +83,12 @@ static bool get_skip_initial_pipe_abort() { return skip_initial_pipe_abort; } -void list_devices_ftd3(std::vector &devices_list) { +void list_devices_ftd3(std::vector &devices_list, std::vector &no_access_list) { FT_STATUS ftStatus; DWORD numDevs = 0; std::string valid_descriptions[] = {"N3DSXL", "N3DSXL.2"}; ftStatus = FT_CreateDeviceInfoList(&numDevs); + size_t num_inserted = 0; if (!FT_FAILED(ftStatus) && numDevs > 0) { const int debug_multiplier = 1; @@ -105,6 +114,12 @@ void list_devices_ftd3(std::vector &devices_list) { } } } + if(num_inserted == 0) { + #if defined(USE_IS_NITRO_USB) || defined(USE_DS_3DS_USB) + if(get_usb_total_filtered_devices(ftd3xx_valid_vids, sizeof(ftd3xx_valid_vids) / sizeof(ftd3xx_valid_vids[0]), ftd3xx_valid_pids, sizeof(ftd3xx_valid_pids) / sizeof(ftd3xx_valid_pids[0])) != numDevs) + no_access_list.emplace_back("FTD3XX"); + #endif + } } uint64_t ftd3_get_video_in_size(CaptureData* capture_data) { diff --git a/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp b/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp index 2f4d3a9..d56aac0 100644 --- a/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp +++ b/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp @@ -77,7 +77,7 @@ static is_nitro_device_handlers* usb_find_by_serial_number(const is_nitro_usb_de return final_handlers; } -void list_devices_is_nitro(std::vector &devices_list) { +void list_devices_is_nitro(std::vector &devices_list, std::vector &no_access_list) { const size_t num_is_nitro_desc = GetNumISNitroDesc(); int* curr_serial_extra_id_is_nitro = new int[num_is_nitro_desc]; bool* no_access_elems = new bool[num_is_nitro_desc]; @@ -90,9 +90,14 @@ void list_devices_is_nitro(std::vector &devices_list) { is_nitro_libusb_list_devices(devices_list, no_access_elems, not_supported_elems, curr_serial_extra_id_is_nitro, num_is_nitro_desc); bool any_not_supported = false; - for (int i = 0; i < num_is_nitro_desc; i++) + for(int i = 0; i < num_is_nitro_desc; i++) any_not_supported |= not_supported_elems[i]; - if (any_not_supported) + for(int i = 0; i < num_is_nitro_desc; i++) + if(no_access_elems[i]) { + const is_nitro_usb_device* usb_device = GetISNitroDesc(i); + no_access_list.emplace_back(usb_device->vid, usb_device->pid); + } + if(any_not_supported) is_driver_list_devices(devices_list, not_supported_elems, curr_serial_extra_id_is_nitro, num_is_nitro_desc); delete[] curr_serial_extra_id_is_nitro; diff --git a/source/CaptureDeviceSpecific/dscapture_ftd2.cpp b/source/CaptureDeviceSpecific/dscapture_ftd2.cpp index 2d0fff8..f30b657 100644 --- a/source/CaptureDeviceSpecific/dscapture_ftd2.cpp +++ b/source/CaptureDeviceSpecific/dscapture_ftd2.cpp @@ -9,7 +9,7 @@ #include #include -void list_devices_ftd2(std::vector &devices_list) { +void list_devices_ftd2(std::vector &devices_list, std::vector &no_access_list) { } uint64_t ftd2_get_video_in_size(CaptureData* capture_data) { diff --git a/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp b/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp index 7c8b31f..1bbdb2e 100644 --- a/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp +++ b/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp @@ -308,7 +308,7 @@ static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutput memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3); } -void list_devices_usb_ds_3ds(std::vector &devices_list) { +void list_devices_usb_ds_3ds(std::vector &devices_list, std::vector &no_access_list) { if(!usb_is_initialized()) return; libusb_device **usb_devices; @@ -336,6 +336,10 @@ void list_devices_usb_ds_3ds(std::vector &devices_list) { if(num_devices >= 0) libusb_free_device_list(usb_devices, 1); + + for(int i = 0; i < num_usb_desc; i++) + if(no_access_elems[i]) + no_access_list.emplace_back(usb_devices_desc_list[i]->vid, usb_devices_desc_list[i]->pid); } bool connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device) { diff --git a/source/CaptureDeviceSpecific/usb_generic.cpp b/source/CaptureDeviceSpecific/usb_generic.cpp index 675f866..3619d30 100644 --- a/source/CaptureDeviceSpecific/usb_generic.cpp +++ b/source/CaptureDeviceSpecific/usb_generic.cpp @@ -31,3 +31,37 @@ bool usb_is_initialized() { libusb_context* get_usb_ctx() { return usb_ctx; } + +int get_usb_total_filtered_devices(const uint16_t valid_vids[], size_t num_vids, const uint16_t valid_pids[], size_t num_pids) { + if(!usb_is_initialized()) + return 0; + libusb_device **usb_devices; + int num_devices = libusb_get_device_list(get_usb_ctx(), &usb_devices); + libusb_device_descriptor usb_descriptor{}; + int num_devices_found = 0; + + for(int i = 0; i < num_devices; i++) { + int result = libusb_get_device_descriptor(usb_devices[i], &usb_descriptor); + if(result < 0) + continue; + bool found_vid = false; + for(int j = 0; j < num_vids; j++) + if(usb_descriptor.idVendor == valid_vids[j]) { + found_vid = true; + break; + } + if(!found_vid) + continue; + for(int j = 0; j < num_pids; j++) { + if(usb_descriptor.idProduct == valid_pids[j]) { + num_devices_found += 1; + break; + } + } + } + + if(num_devices >= 0) + libusb_free_device_list(usb_devices, 1); + + return num_devices_found; +} diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 33469f0..5539410 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -433,7 +433,7 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data, } if(capture_data->status.new_error_text) { - UpdateOutText(out_text_data, capture_data->status.error_text, capture_data->status.error_text, TEXT_KIND_ERROR); + UpdateOutText(out_text_data, capture_data->status.detailed_error_text, capture_data->status.graphical_error_text, TEXT_KIND_ERROR); capture_data->status.new_error_text = false; } diff --git a/source/devicecapture.cpp b/source/devicecapture.cpp index 261faec..bf8a30e 100755 --- a/source/devicecapture.cpp +++ b/source/devicecapture.cpp @@ -50,8 +50,13 @@ static int choose_device(std::vector *devices_list, FrontendData* } void capture_error_print(bool print_failed, CaptureData* capture_data, std::string error_string) { + capture_error_print(print_failed, capture_data, error_string, error_string); +} + +void capture_error_print(bool print_failed, CaptureData* capture_data, std::string graphical_string, std::string detailed_string) { if(print_failed) { - capture_data->status.error_text = error_string; + capture_data->status.graphical_error_text = graphical_string; + capture_data->status.detailed_error_text = detailed_string; capture_data->status.new_error_text = true; } } @@ -70,21 +75,34 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten // Device Listing std::vector devices_list; + std::vector no_access_list; #ifdef USE_FTD3 - list_devices_ftd3(devices_list); + list_devices_ftd3(devices_list, no_access_list); #endif #ifdef USE_FTD2 - list_devices_ftd2(devices_list); + list_devices_ftd2(devices_list, no_access_list); #endif #ifdef USE_DS_3DS_USB - list_devices_usb_ds_3ds(devices_list); + list_devices_usb_ds_3ds(devices_list, no_access_list); #endif #ifdef USE_IS_NITRO_USB - list_devices_is_nitro(devices_list); + list_devices_is_nitro(devices_list, no_access_list); #endif if(devices_list.size() <= 0) { - capture_error_print(print_failed, capture_data, "No device was found"); + if(no_access_list.size() <= 0) + capture_error_print(print_failed, capture_data, "No device was found"); + else { + std::string full_error_part = ""; + for(int i = 0; i < no_access_list.size(); i++) { + full_error_part += " - "; + if(no_access_list[i].vid == -1) + full_error_part += no_access_list[i].name; + else + full_error_part += "VID: " + to_hex(no_access_list[i].vid) + ", PID: " + to_hex(no_access_list[i].pid); + } + capture_error_print(print_failed, capture_data, "No device was found\nPossible permission error", "No device was found - Possible permission error" + full_error_part); + } return false; } diff --git a/source/utils.cpp b/source/utils.cpp index f84d4da..776cc57 100755 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -96,6 +96,19 @@ uint16_t from_be(uint16_t value) { return value; } +std::string to_hex(uint16_t value) { + const int num_digits = sizeof(value) * 2; + char digits[num_digits]; + for(int i = 0; i < num_digits; i++) { + uint8_t subvalue = (value >> (4 * (num_digits - 1 - i))) & 0xF; + char digit = '0' + subvalue; + if(subvalue >= 0xA) + digit = 'A' + (subvalue - 0xA); + digits[i] = digit; + } + return static_cast(digits); +} + void init_threads(void) { #if defined(__linux__) && defined(XLIB_BASED) XInitThreads();