From f1e305c303800ed16a5e794332f4af29cdc7aa22 Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Fri, 19 Sep 2025 20:58:07 +0200 Subject: [PATCH] Add ability to list connected joysticks (to fix issues with udev rules on Linux) --- include/event_structs.hpp | 1 + include/utils.hpp | 3 +- .../usb_is_device_communications.cpp | 9 ++-- source/cc3dsfs.cpp | 7 ++++ source/devicecapture.cpp | 2 +- source/frontend.cpp | 41 +++++++++++-------- source/utils.cpp | 17 ++++++-- 7 files changed, 54 insertions(+), 26 deletions(-) diff --git a/include/event_structs.hpp b/include/event_structs.hpp index 2dd8085..0fb20b4 100644 --- a/include/event_structs.hpp +++ b/include/event_structs.hpp @@ -33,6 +33,7 @@ struct SFEvent { }; void joystick_axis_poll(std::queue &events_queue); +void joystick_print_all(); JoystickDirection get_joystick_direction(uint32_t joystickId, sf::Joystick::Axis axis, float position); JoystickAction get_joystick_action(uint32_t joystickId, uint32_t joy_button); void init_extra_buttons_poll(int page_up_id, int page_down_id, int enter_id, int power_id, bool use_pud_up); diff --git a/include/utils.hpp b/include/utils.hpp index 9adccf3..6bed4bd 100755 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -87,7 +87,8 @@ uint32_t rotate_bits_left(uint32_t value); uint32_t rotate_bits_right(uint32_t value); void init_start_time(); uint32_t ms_since_start(); -std::string to_hex(uint16_t value); +std::string to_hex_u8(const uint8_t value); +std::string to_hex_u16(uint16_t value); std::string get_float_str_decimals(float value, int decimals); void init_threads(void); void complete_threads(void); diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp index 958bd8d..b3d91b7 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp @@ -359,12 +359,15 @@ static void enc_dec_table_add_usage(is_device_twl_enc_dec_table* table) { static void table_print(uint8_t* data, size_t size) { /* + std::string output = ""; for(size_t i = 0; i < size; i++) { - printf("%02x ", data[i]); + output += to_hex_u8(data[i]); if((i % 0x10) == 0xF) - printf("\n"); + output += "\n"; + else + output += " "; } - printf("\n"); + ActualConsoleOutText(output); */ } diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 4a388f4..36cb00e 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -33,6 +33,7 @@ struct override_all_data { override_win_data override_top_data; override_win_data override_bot_data; bool disable_frame_blending = false; + bool print_controller_list = false; bool no_audio = false; int volume = DEFAULT_NO_VOLUME_VALUE; bool always_prevent_mouse_showing = false; @@ -599,6 +600,9 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data, SuccessConnectionOutTextGenerator(out_text_data, capture_data); int no_data_consecutive = 0; + if(override_data.print_controller_list) + joystick_print_all(); + while(capture_data->status.running) { bool polled = false; @@ -883,6 +887,8 @@ int main(int argc, char **argv) { continue; if(parse_existence_arg(i, argv, override_data.auto_save, false, "--no_auto_save")) continue; + if(parse_existence_arg(i, argv, override_data.print_controller_list, true, "--list_joysticks")) + continue; #ifdef RASPI if(parse_int_arg(i, argc, argv, page_up_id, "--pi_select")) continue; @@ -934,6 +940,7 @@ int main(int argc, char **argv) { ActualConsoleOutText(" instead of the default one. When the program closes,"); ActualConsoleOutText(" the data is also saved to the specified profile."); ActualConsoleOutText(" --no_auto_save Disables automatic save when closing the software."); + ActualConsoleOutText(" --list_joysticks Prints a list of all the detected joysticks."); #ifdef RASPI ActualConsoleOutText(" --pi_select ID Specifies ID for the select GPIO button."); ActualConsoleOutText(" --pi_menu ID Specifies ID for the menu GPIO button."); diff --git a/source/devicecapture.cpp b/source/devicecapture.cpp index 88b4726..df4cdc7 100755 --- a/source/devicecapture.cpp +++ b/source/devicecapture.cpp @@ -118,7 +118,7 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten 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); + full_error_part += "VID: " + to_hex_u16(no_access_list[i].vid) + ", PID: " + to_hex_u16(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); } diff --git a/source/frontend.cpp b/source/frontend.cpp index 1172442..9d54f2b 100755 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -4,8 +4,6 @@ #include #include -#define DEBUG_PRINT_CONTROLLER_INFO - const CropData default_3ds_crop = { .top_width = TOP_WIDTH_3DS, .top_height = HEIGHT_3DS, .top_x = 0, .top_y = 0, @@ -923,26 +921,10 @@ std::string save_screen_info(std::string base, const ScreenInfo &info) { } void joystick_axis_poll(std::queue &events_queue) { - #ifdef DEBUG_PRINT_CONTROLLER_INFO - static bool printed_once = false; - bool has_already_printed_once = printed_once; - #endif - for(unsigned int i = 0; i < sf::Joystick::Count; i++) { if(!sf::Joystick::isConnected(i)) continue; - #ifdef DEBUG_PRINT_CONTROLLER_INFO - if(!has_already_printed_once) { - printed_once = true; - ActualConsoleOutText("Controller " + std::to_string(i + 1) + ":"); - sf::Joystick::Identification joy_details = sf::Joystick::getIdentification(i); - ActualConsoleOutText("\tName: " + joy_details.name); - ActualConsoleOutText("\tVID: " + std::to_string(joy_details.vendorId)); - ActualConsoleOutText("\tPID: " + std::to_string(joy_details.vendorId)); - } - #endif - for(unsigned int j = 0; j < sf::Joystick::AxisCount; j++) { sf::Joystick::Axis axis = sf::Joystick::Axis((unsigned int)sf::Joystick::Axis::X + j); if(sf::Joystick::hasAxis(i, axis)) @@ -951,6 +933,29 @@ void joystick_axis_poll(std::queue &events_queue) { } } +void joystick_print_all() { + int num_connected = 0; + + for(unsigned int i = 0; i < sf::Joystick::Count; i++) { + if(!sf::Joystick::isConnected(i)) + continue; + num_connected += 1; + } + + ActualConsoleOutText("Connected Joysticks: " + std::to_string(num_connected)); + + for(unsigned int i = 0; i < sf::Joystick::Count; i++) { + if(!sf::Joystick::isConnected(i)) + continue; + + ActualConsoleOutText("Joystick " + std::to_string(i + 1) + ":"); + sf::Joystick::Identification joy_details = sf::Joystick::getIdentification(i); + ActualConsoleOutText("\tName: " + joy_details.name); + ActualConsoleOutText("\tVID: " + std::to_string(joy_details.vendorId)); + ActualConsoleOutText("\tPID: " + std::to_string(joy_details.productId)); + } +} + const PARData* get_base_par() { return basic_possible_pars[0]; } diff --git a/source/utils.cpp b/source/utils.cpp index e78c7d1..7484145 100755 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -226,9 +226,7 @@ uint32_t ms_since_start() { return (uint32_t)(diff.count() * 1000); } -std::string to_hex(uint16_t value) { - const int num_digits = sizeof(value) * 2; - char digits[num_digits]; +static std::string to_hex_base(const uint64_t value, char* digits, const int num_digits) { for(int i = 0; i < num_digits; i++) { uint8_t subvalue = (value >> (4 * (num_digits - 1 - i))) & 0xF; char digit = '0' + subvalue; @@ -236,9 +234,22 @@ std::string to_hex(uint16_t value) { digit = 'A' + (subvalue - 0xA); digits[i] = digit; } + digits[num_digits] = '\0'; return static_cast(digits); } +std::string to_hex_u8(const uint8_t value) { + const int num_digits = sizeof(value) * 2; + char digits[num_digits + 1]; + return to_hex_base(value, digits, num_digits); +} + +std::string to_hex_u16(const uint16_t value) { + const int num_digits = sizeof(value) * 2; + char digits[num_digits + 1]; + return to_hex_base(value, digits, num_digits); +} + void init_threads(void) { #if defined(__linux__) && defined(XLIB_BASED) XInitThreads();