diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index aee7c6c04b..0696481efa 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -211,11 +211,11 @@ private: // GT5 Wheels&co - #ifdef HAVE_SDL3 +#ifdef HAVE_SDL3 {0x046D, 0xC283, 0xC29B, "lgFF_c283_c29b", &usb_device_logitech_g27::get_num_emu_devices, &usb_device_logitech_g27::make_instance}, - #else +#else {0x046D, 0xC283, 0xC29B, "lgFF_c283_c29b", nullptr, nullptr}, - #endif +#endif {0x044F, 0xB653, 0xB653, "Thrustmaster RGT FFB Pro", nullptr, nullptr}, {0x044F, 0xB65A, 0xB65A, "Thrustmaster F430", nullptr, nullptr}, {0x044F, 0xB65D, 0xB65D, "Thrustmaster FFB", nullptr, nullptr}, diff --git a/rpcs3/Emu/Io/LogitechG27.cpp b/rpcs3/Emu/Io/LogitechG27.cpp index 7f050088fe..5017ba9a1e 100644 --- a/rpcs3/Emu/Io/LogitechG27.cpp +++ b/rpcs3/Emu/Io/LogitechG27.cpp @@ -7,7 +7,6 @@ // shifter input ref // https://github.com/sonik-br/lgff_wheel_adapter/blob/d97f7823154818e1b3edff6d51498a122c302728/pico_lgff_wheel_adapter/reports.h#L265-L310 - #include "stdafx.h" #ifdef HAVE_SDL3 @@ -23,11 +22,11 @@ LOG_CHANNEL(logitech_g27_log, "LOGIG27"); -static int SDLCALL refresh_thread(void *arg) +static int SDLCALL refresh_thread(void* arg) { - auto ctx = reinterpret_cast(arg); + auto ctx = reinterpret_cast(arg); - while(true) + while (true) { ctx->thread_control_mutex.lock(); if (ctx->stop_thread) @@ -50,15 +49,15 @@ usb_device_logitech_g27::usb_device_logitech_g27(u32 controller_index, const std // parse the raw response like with passthrough device static const uint8_t raw_config[] = {0x9, 0x2, 0x29, 0x0, 0x1, 0x1, 0x4, 0x80, 0x31, 0x9, 0x4, 0x0, 0x0, 0x2, 0x3, 0x0, 0x0, 0x0, 0x9, 0x21, 0x11, 0x1, 0x21, 0x1, 0x22, 0x85, 0x0, 0x7, 0x5, 0x81, 0x3, 0x10, 0x0, 0x2, 0x7, 0x5, 0x1, 0x3, 0x10, 0x0, 0x2}; - auto &conf = device.add_node(UsbDescriptorNode(raw_config[0], raw_config[1], &raw_config[2])); - for (unsigned int index = raw_config[0];index < sizeof(raw_config);) + auto& conf = device.add_node(UsbDescriptorNode(raw_config[0], raw_config[1], &raw_config[2])); + for (unsigned int index = raw_config[0]; index < sizeof(raw_config);) { conf.add_node(UsbDescriptorNode(raw_config[index], raw_config[index + 1], &raw_config[index + 2])); index += raw_config[index]; } // Initialize effect slots - for (int i = 0;i < 4;i++) + for (int i = 0; i < 4; i++) { effect_slots[i].state = G27_FFB_INACTIVE; effect_slots[i].effect_id = -1; @@ -66,13 +65,12 @@ usb_device_logitech_g27::usb_device_logitech_g27(u32 controller_index, const std SDL_HapticDirection direction = { .type = SDL_HAPTIC_POLAR, - .dir = {27000, 0} - }; + .dir = {27000, 0}}; default_spring_effect.type = SDL_HAPTIC_SPRING; default_spring_effect.condition.direction = direction; default_spring_effect.condition.length = SDL_HAPTIC_INFINITY; - //for (int i = 0;i < 3;i++) - for (int i = 0;i < 1;i++) + // for (int i = 0;i < 3;i++) + for (int i = 0; i < 1; i++) { default_spring_effect.condition.right_sat[i] = 0x7FFF; default_spring_effect.condition.left_sat[i] = 0x7FFF; @@ -101,15 +99,16 @@ usb_device_logitech_g27::usb_device_logitech_g27(u32 controller_index, const std } } -bool usb_device_logitech_g27::open_device(){ +bool usb_device_logitech_g27::open_device() +{ return enabled; } -static void clear_sdl_joysticks(std::map> &joysticks) +static void clear_sdl_joysticks(std::map>& joysticks) { - for (auto joystick_type = joysticks.begin();joystick_type != joysticks.end();joystick_type++) + for (auto joystick_type = joysticks.begin(); joystick_type != joysticks.end(); joystick_type++) { - for (auto joystick = joystick_type->second.begin(); joystick != joystick_type->second.end();joystick++) + for (auto joystick = joystick_type->second.begin(); joystick != joystick_type->second.end(); joystick++) { SDL_CloseJoystick(*joystick); } @@ -151,7 +150,7 @@ u16 usb_device_logitech_g27::get_num_emu_devices() void usb_device_logitech_g27::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) { transfer->fake = true; - transfer->expected_count = buf_size; + transfer->expected_count = buf_size; transfer->expected_result = HC_CC_NOERR; transfer->expected_time = get_timestamp() + 100; @@ -159,13 +158,13 @@ void usb_device_logitech_g27::control_transfer(u8 bmRequestType, u8 bRequest, u1 usb_device_emulated::control_transfer(bmRequestType, bRequest, wValue, wIndex, wLength, buf_size, buf, transfer); } -static bool sdl_joysticks_equal(std::map> &left, std::map> &right) +static bool sdl_joysticks_equal(std::map>& left, std::map>& right) { if (left.size() != right.size()) { return false; } - for (auto left_joysticks_of_type = left.begin();left_joysticks_of_type != left.end();left_joysticks_of_type++) + for (auto left_joysticks_of_type = left.begin(); left_joysticks_of_type != left.end(); left_joysticks_of_type++) { auto right_joysticks_of_type = right.find(left_joysticks_of_type->first); if (right_joysticks_of_type == right.end()) @@ -176,10 +175,10 @@ static bool sdl_joysticks_equal(std::map> { return false; } - for (auto left_joystick = left_joysticks_of_type->second.begin();left_joystick != left_joysticks_of_type->second.end(); left_joystick++) + for (auto left_joystick = left_joysticks_of_type->second.begin(); left_joystick != left_joysticks_of_type->second.end(); left_joystick++) { bool found = false; - for (auto right_joystick = right_joysticks_of_type->second.begin();right_joystick != right_joysticks_of_type->second.end();right_joystick++) + for (auto right_joystick = right_joysticks_of_type->second.begin(); right_joystick != right_joysticks_of_type->second.end(); right_joystick++) { if (*left_joystick == *right_joystick) { @@ -200,14 +199,14 @@ static inline logitech_g27_sdl_mapping get_runtime_mapping() { logitech_g27_sdl_mapping mapping; - #define CONVERT_MAPPING(name) \ - { \ - mapping.name.device_type_id = g_cfg_logitech_g27.name##_device_type_id.get(); \ +#define CONVERT_MAPPING(name) \ + { \ + mapping.name.device_type_id = g_cfg_logitech_g27.name##_device_type_id.get(); \ mapping.name.type = static_cast(g_cfg_logitech_g27.name##_type.get()); \ - mapping.name.id = static_cast(g_cfg_logitech_g27.name##_id.get()); \ - mapping.name.hat = static_cast(g_cfg_logitech_g27.name##_hat.get()); \ - mapping.name.reverse = g_cfg_logitech_g27.name##_reverse.get(); \ - mapping.name.positive_axis = false; \ + mapping.name.id = static_cast(g_cfg_logitech_g27.name##_id.get()); \ + mapping.name.hat = static_cast(g_cfg_logitech_g27.name##_hat.get()); \ + mapping.name.reverse = g_cfg_logitech_g27.name##_reverse.get(); \ + mapping.name.positive_axis = false; \ } CONVERT_MAPPING(steering); @@ -249,7 +248,7 @@ static inline logitech_g27_sdl_mapping get_runtime_mapping() CONVERT_MAPPING(shifter_6); CONVERT_MAPPING(shifter_r); - #undef CONVERT_MAPPING +#undef CONVERT_MAPPING return mapping; } @@ -268,18 +267,17 @@ void usb_device_logitech_g27::sdl_refresh() uint32_t led_product_id = g_cfg_logitech_g27.led_device_type_id.get() & 0xFFFF; g_cfg_logitech_g27.m_mutex.unlock(); - - SDL_Joystick *new_led_joystick_handle = nullptr; - SDL_Haptic *new_haptic_handle = nullptr; - std::map> new_joysticks; + SDL_Joystick* new_led_joystick_handle = nullptr; + SDL_Haptic* new_haptic_handle = nullptr; + std::map> new_joysticks; int joystick_count; - SDL_JoystickID *joystick_ids = SDL_GetJoysticks(&joystick_count); + SDL_JoystickID* joystick_ids = SDL_GetJoysticks(&joystick_count); if (joystick_ids != nullptr) { - for (int i = 0;i < joystick_count;i++) + for (int i = 0; i < joystick_count; i++) { - SDL_Joystick *cur_joystick = SDL_OpenJoystick(joystick_ids[i]); + SDL_Joystick* cur_joystick = SDL_OpenJoystick(joystick_ids[i]); if (cur_joystick == nullptr) { logitech_g27_log.error("Failed opening joystick %d, %s", joystick_ids[i], SDL_GetError()); @@ -301,7 +299,7 @@ void usb_device_logitech_g27::sdl_refresh() if (cur_vendor_id == ffb_vendor_id && cur_product_id == ffb_product_id && new_haptic_handle == nullptr) { - SDL_Haptic *cur_haptic = SDL_OpenHapticFromJoystick(cur_joystick); + SDL_Haptic* cur_haptic = SDL_OpenHapticFromJoystick(cur_joystick); if (cur_haptic == nullptr) { logitech_g27_log.error("Failed opening haptic device from selected ffb device %04x:%04x", cur_vendor_id, cur_product_id); @@ -341,7 +339,7 @@ void usb_device_logitech_g27::sdl_refresh() if (haptic_changed) { SDL_CloseHaptic(haptic_handle); - for (int i = 0;i < 4;i++) + for (int i = 0; i < 4; i++) { effect_slots[i].effect_id = -1; } @@ -464,26 +462,26 @@ extern bool is_input_allowed(); static uint8_t sdl_hat_to_logitech_g27_hat(uint8_t sdl_hat) { - switch(sdl_hat) + switch (sdl_hat) { - case SDL_HAT_CENTERED: - return 8; - case SDL_HAT_UP: - return 0; - case SDL_HAT_RIGHTUP: - return 1; - case SDL_HAT_RIGHT: - return 2; - case SDL_HAT_RIGHTDOWN: - return 3; - case SDL_HAT_DOWN: - return 4; - case SDL_HAT_LEFTDOWN: - return 5; - case SDL_HAT_LEFT: - return 6; - case SDL_HAT_LEFTUP: - return 7; + case SDL_HAT_CENTERED: + return 8; + case SDL_HAT_UP: + return 0; + case SDL_HAT_RIGHTUP: + return 1; + case SDL_HAT_RIGHT: + return 2; + case SDL_HAT_RIGHTDOWN: + return 3; + case SDL_HAT_DOWN: + return 4; + case SDL_HAT_LEFTDOWN: + return 5; + case SDL_HAT_LEFT: + return 6; + case SDL_HAT_LEFTUP: + return 7; } return 0; } @@ -502,120 +500,120 @@ static uint8_t hat_components_to_logitech_g27_hat(bool up, bool down, bool left, return sdl_hat_to_logitech_g27_hat(sdl_hat); } -static bool fetch_sdl_as_button(SDL_Joystick *joystick, const sdl_mapping &mapping) +static bool fetch_sdl_as_button(SDL_Joystick* joystick, const sdl_mapping& mapping) { - switch(mapping.type) + switch (mapping.type) { - case MAPPING_BUTTON: + case MAPPING_BUTTON: + { + bool pressed = SDL_GetJoystickButton(joystick, mapping.id); + return mapping.reverse ? !pressed : pressed; + } + case MAPPING_HAT: + { + uint8_t hat_value = SDL_GetJoystickHat(joystick, mapping.id); + bool pressed = false; + switch (mapping.hat) { - bool pressed = SDL_GetJoystickButton(joystick, mapping.id); - return mapping.reverse ? !pressed : pressed; + case HAT_UP: + pressed = (hat_value & SDL_HAT_UP) ? true : false; + break; + case HAT_DOWN: + pressed = (hat_value & SDL_HAT_DOWN) ? true : false; + break; + case HAT_LEFT: + pressed = (hat_value & SDL_HAT_LEFT) ? true : false; + break; + case HAT_RIGHT: + pressed = (hat_value & SDL_HAT_RIGHT) ? true : false; + break; + case HAT_NONE: + break; } - case MAPPING_HAT: + return mapping.reverse ? !pressed : pressed; + } + case MAPPING_AXIS: + { + int32_t axis_value = SDL_GetJoystickAxis(joystick, mapping.id); + bool pressed = false; + if (mapping.positive_axis) { - uint8_t hat_value = SDL_GetJoystickHat(joystick, mapping.id); - bool pressed = false; - switch (mapping.hat) - { - case HAT_UP: - pressed = (hat_value & SDL_HAT_UP) ? true : false; - break; - case HAT_DOWN: - pressed = (hat_value & SDL_HAT_DOWN) ? true : false; - break; - case HAT_LEFT: - pressed = (hat_value & SDL_HAT_LEFT) ? true : false; - break; - case HAT_RIGHT: - pressed = (hat_value & SDL_HAT_RIGHT) ? true : false; - break; - case HAT_NONE: - break; - } - return mapping.reverse ? !pressed : pressed; + pressed = axis_value > (0x7FFF / 2); } - case MAPPING_AXIS: + else { - int32_t axis_value = SDL_GetJoystickAxis(joystick, mapping.id); - bool pressed = false; - if (mapping.positive_axis) - { - pressed = axis_value > (0x7FFF / 2); - } - else - { - pressed = axis_value < (0x7FFF / (-2)); - } - return mapping.reverse ? !pressed : pressed; + pressed = axis_value < (0x7FFF / (-2)); } + return mapping.reverse ? !pressed : pressed; + } } return false; } -static int16_t fetch_sdl_as_axis(SDL_Joystick *joystick, const sdl_mapping &mapping) +static int16_t fetch_sdl_as_axis(SDL_Joystick* joystick, const sdl_mapping& mapping) { const static int16_t MAX = 0x7FFF; const static int16_t MIN = -0x8000; const static int16_t MID = 0; - switch(mapping.type) + switch (mapping.type) { - case MAPPING_BUTTON: + case MAPPING_BUTTON: + { + bool pressed = SDL_GetJoystickButton(joystick, mapping.id); + if (mapping.reverse) { - bool pressed = SDL_GetJoystickButton(joystick, mapping.id); - if (mapping.reverse) - { - pressed = !pressed; - } - int16_t pressed_value = mapping.positive_axis ? MAX : MIN; - return pressed ? pressed_value : MID; + pressed = !pressed; } - case MAPPING_HAT: + int16_t pressed_value = mapping.positive_axis ? MAX : MIN; + return pressed ? pressed_value : MID; + } + case MAPPING_HAT: + { + uint8_t hat_value = SDL_GetJoystickHat(joystick, mapping.id); + bool pressed = false; + switch (mapping.hat) { - uint8_t hat_value = SDL_GetJoystickHat(joystick, mapping.id); - bool pressed = false; - switch (mapping.hat) - { - case HAT_UP: - pressed = (hat_value & SDL_HAT_UP) ? true : false; - break; - case HAT_DOWN: - pressed = (hat_value & SDL_HAT_DOWN) ? true : false; - break; - case HAT_LEFT: - pressed = (hat_value & SDL_HAT_LEFT) ? true : false; - break; - case HAT_RIGHT: - pressed = (hat_value & SDL_HAT_RIGHT) ? true : false; - break; - case HAT_NONE: - break; - } - if (mapping.reverse) - { - pressed = !pressed; - } - int16_t pressed_value = mapping.positive_axis ? MAX : MIN; - return pressed ? pressed_value : MID; + case HAT_UP: + pressed = (hat_value & SDL_HAT_UP) ? true : false; + break; + case HAT_DOWN: + pressed = (hat_value & SDL_HAT_DOWN) ? true : false; + break; + case HAT_LEFT: + pressed = (hat_value & SDL_HAT_LEFT) ? true : false; + break; + case HAT_RIGHT: + pressed = (hat_value & SDL_HAT_RIGHT) ? true : false; + break; + case HAT_NONE: + break; } - case MAPPING_AXIS: + if (mapping.reverse) { - int32_t axis_value = SDL_GetJoystickAxis(joystick, mapping.id); - if (mapping.reverse) - axis_value = axis_value * (-1); - if (axis_value > MAX) - axis_value = MAX; - if (axis_value < MIN) - axis_value = MIN; - if (axis_value == (MIN + 1)) - axis_value = MIN; - return axis_value; + pressed = !pressed; } + int16_t pressed_value = mapping.positive_axis ? MAX : MIN; + return pressed ? pressed_value : MID; + } + case MAPPING_AXIS: + { + int32_t axis_value = SDL_GetJoystickAxis(joystick, mapping.id); + if (mapping.reverse) + axis_value = axis_value * (-1); + if (axis_value > MAX) + axis_value = MAX; + if (axis_value < MIN) + axis_value = MIN; + if (axis_value == (MIN + 1)) + axis_value = MIN; + return axis_value; + } } return 0; } -static int16_t fetch_sdl_axis_avg(std::map> &joysticks, const sdl_mapping &mapping) +static int16_t fetch_sdl_axis_avg(std::map>& joysticks, const sdl_mapping& mapping) { const static int16_t MAX = 0x7FFF; const static int16_t MIN = -0x8000; @@ -633,7 +631,7 @@ static int16_t fetch_sdl_axis_avg(std::map // TODO account for deadzone and only pick up active devices int32_t sdl_joysticks_total_value = 0; - for (auto joystick = joysticks_of_type->second.begin();joystick != joysticks_of_type->second.end();joystick++) + for (auto joystick = joysticks_of_type->second.begin(); joystick != joysticks_of_type->second.end(); joystick++) { sdl_joysticks_total_value += fetch_sdl_as_axis(*joystick, mapping); } @@ -641,7 +639,7 @@ static int16_t fetch_sdl_axis_avg(std::map return sdl_joysticks_total_value / joysticks_of_type->second.size(); } -static bool sdl_to_logitech_g27_button(std::map> &joysticks, const sdl_mapping &mapping) +static bool sdl_to_logitech_g27_button(std::map>& joysticks, const sdl_mapping& mapping) { auto joysticks_of_type = joysticks.find(mapping.device_type_id); if (joysticks_of_type == joysticks.end()) @@ -655,28 +653,28 @@ static bool sdl_to_logitech_g27_button(std::mapsecond.begin();joystick != joysticks_of_type->second.end();joystick++) + for (auto joystick = joysticks_of_type->second.begin(); joystick != joysticks_of_type->second.end(); joystick++) { pressed = pressed || fetch_sdl_as_button(*joystick, mapping); } return pressed; } -static uint16_t sdl_to_logitech_g27_steering(std::map> &joysticks, const sdl_mapping &mapping) +static uint16_t sdl_to_logitech_g27_steering(std::map>& joysticks, const sdl_mapping& mapping) { int16_t avg = fetch_sdl_axis_avg(joysticks, mapping); uint16_t unsigned_avg = avg + 0x8000; return unsigned_avg * (0xFFFF >> 2) / 0xFFFF; } -static uint8_t sdl_to_logitech_g27_pedal(std::map> &joysticks, const sdl_mapping &mapping) +static uint8_t sdl_to_logitech_g27_pedal(std::map>& joysticks, const sdl_mapping& mapping) { int16_t avg = fetch_sdl_axis_avg(joysticks, mapping); uint16_t unsigned_avg = avg + 0x8000; return unsigned_avg * 0xFF / 0xFFFF; } -static inline void set_bit(uint8_t *buf, int bit_num, bool set) +static inline void set_bit(uint8_t* buf, int bit_num, bool set) { int byte_num = bit_num / 8; bit_num = bit_num % 8; @@ -799,7 +797,7 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp buf[9] = 0x80; // shifter y buf[10] = buf[10] | (wheel_range > 360 ? 0x90 : 0x10); - //logitech_g27_log.error("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10]); + // logitech_g27_log.error("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10]); return; } @@ -808,14 +806,14 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp // Sending data to wheel if (buf_size < 7) { - char *hex_buf = reinterpret_cast(malloc(buf_size * 3 + 1)); + char* hex_buf = reinterpret_cast(malloc(buf_size * 3 + 1)); if (hex_buf == nullptr) { logitech_g27_log.error("Unhandled wheel command with size %u != 16", buf_size); return; } int offset = 0; - for (uint32_t i = 0;i < buf_size;i++) + for (uint32_t i = 0; i < buf_size; i++) { offset += sprintf(&hex_buf[offset], "%02x ", buf[i]); } @@ -833,8 +831,7 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp SDL_HapticDirection direction = { .type = SDL_HAPTIC_POLAR, - .dir = {27000, 0} - }; + .dir = {27000, 0}}; if (reverse_effects) { direction.dir[0] = 9000; @@ -845,82 +842,82 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp // Process effects if (buf[0] == 0xf8) { - switch(buf[1]) + switch (buf[1]) { - case 0x01: + case 0x01: + { + // Change to DFP + logitech_g27_log.error("Drive Force Pro mode switch command ignored"); + break; + } + case 0x02: + { + // Change wheel range to 200 degrees + logitech_g27_log.error("Change wheel range to 200 degrees command not forwarded"); + wheel_range = 200; + break; + } + case 0x03: + { + // Change wheel range to 900 degrees + logitech_g27_log.error("Change wheel range to 900 degrees command not forwarded"); + wheel_range = 900; + break; + } + case 0x09: + { + // Change device mode + logitech_g27_log.error("Change device mode to %d %s detaching command ignored", buf[2], buf[3] ? "with" : "without"); + break; + } + case 0x0a: + { + // Revert indentity + logitech_g27_log.error("Revert device identity after reset %s command ignored", buf[2] ? "enable" : "disable"); + break; + } + case 0x10: + { + // Switch to G25 with detach + logitech_g27_log.error("Switch to G25 with detach command ignored"); + break; + } + case 0x11: + { + // Switch to G25 without detach + logitech_g27_log.error("Switch to G25 without detach command ignored"); + break; + } + case 0x12: + { + // Incoming data is a 5 bit mask, for each individual bulb + if (led_joystick_handle == nullptr) { - // Change to DFP - logitech_g27_log.error("Drive Force Pro mode switch command ignored"); break; } - case 0x02: + // Mux into total amount of bulbs on, since sdl only takes intensity + uint8_t new_led_level = 0; + for (int i = 0; i < 5; i++) { - // Change wheel range to 200 degrees - logitech_g27_log.error("Change wheel range to 200 degrees command not forwarded"); - wheel_range = 200; - break; + new_led_level += (buf[2] & (1 << i)) ? 1 : 0; } - case 0x03: - { - // Change wheel range to 900 degrees - logitech_g27_log.error("Change wheel range to 900 degrees command not forwarded"); - wheel_range = 900; - break; - } - case 0x09: - { - // Change device mode - logitech_g27_log.error("Change device mode to %d %s detaching command ignored", buf[2], buf[3] ? "with" : "without"); - break; - } - case 0x0a: - { - // Revert indentity - logitech_g27_log.error("Revert device identity after reset %s command ignored", buf[2] ? "enable" : "disable"); - break; - } - case 0x10: - { - // Switch to G25 with detach - logitech_g27_log.error("Switch to G25 with detach command ignored"); - break; - } - case 0x11: - { - // Switch to G25 without detach - logitech_g27_log.error("Switch to G25 without detach command ignored"); - break; - } - case 0x12: - { - // Incoming data is a 5 bit mask, for each individual bulb - if (led_joystick_handle == nullptr) - { - break; - } - // Mux into total amount of bulbs on, since sdl only takes intensity - uint8_t new_led_level = 0; - for (int i = 0;i < 5;i++) - { - new_led_level += (buf[2] & (1 << i)) ? 1 : 0; - } - uint8_t intensity = new_led_level * 255 / 5; - SDL_SetJoystickLED(led_joystick_handle, intensity, intensity, intensity); - break; - } - case 0x81: - { - // Wheel range change - wheel_range = (buf[3] << 8) | buf[2]; - logitech_g27_log.error("Wheel range change to %u command not forwarded", wheel_range); - break; - } - default: - { - logitech_g27_log.error("Unknown extended command %02x %02x %02x %02x %02x %02x %02x ignored", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); - break; - } + uint8_t intensity = new_led_level * 255 / 5; + SDL_SetJoystickLED(led_joystick_handle, intensity, intensity, intensity); + break; + } + case 0x81: + { + // Wheel range change + wheel_range = (buf[3] << 8) | buf[2]; + logitech_g27_log.error("Wheel range change to %u command not forwarded", wheel_range); + break; + } + default: + { + logitech_g27_log.error("Unknown extended command %02x %02x %02x %02x %02x %02x %02x ignored", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + break; + } } } else @@ -929,633 +926,635 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp uint8_t slot_mask = buf[0] >> 4; switch (cmd) { - case 0x00: - case 0x01: - case 0x0c: + case 0x00: + case 0x01: + case 0x0c: + { + // Download/Download play/Refresh + for (int i = 0; i < 4; i++) { - // Download/Download play/Refresh - for (int i = 0;i < 4;i++){ - SDL_HapticEffect new_effect = {0}; - // hack: need to reduce Download play spams for some drivers - bool update_hack = false; - if (!(slot_mask & (1 << i))) + SDL_HapticEffect new_effect = {0}; + // hack: need to reduce Download play spams for some drivers + bool update_hack = false; + if (!(slot_mask & (1 << i))) + { + continue; + } + bool unknown_effect = false; + switch (buf[1]) + { + case 0x00: + { + // Constant force + new_effect.type = SDL_HAPTIC_CONSTANT; + new_effect.constant.direction = direction; + new_effect.constant.length = SDL_HAPTIC_INFINITY; + new_effect.constant.level = logitech_g27_force_to_level(buf[2 + i]); + break; + } + case 0x01: + case 0x0b: + { + // Spring/High resolution spring + new_effect.type = SDL_HAPTIC_SPRING; + new_effect.condition.direction = direction; + new_effect.condition.length = SDL_HAPTIC_INFINITY; + uint8_t s1 = buf[5] & 1; + uint8_t s2 = (buf[5] >> 4) & 1; + // TODO direction cfg + uint16_t saturation = logitech_g27_clip_to_saturation(buf[6]); + int16_t center = 0; + uint16_t deadband = 0; + int16_t left_coeff = 0; + int16_t right_coeff = 0; + if (buf[1] == 0x01) + { + uint8_t d1 = buf[2]; + uint8_t d2 = buf[3]; + uint8_t k1 = buf[4] & (0xf >> 1); + uint8_t k2 = (buf[4] >> 4) & (0xf >> 1); + center = logitech_g27_position_to_center(d1, d2); + deadband = logitech_g27_position_to_width(d1, d2); + left_coeff = logitech_g27_coeff_to_coeff(k1, s1); + right_coeff = logitech_g27_coeff_to_coeff(k2, s2); + } + else + { + uint16_t d1 = (buf[2] << 3) | ((buf[5] >> 1) & (0xf >> 1)); + uint16_t d2 = (buf[3] << 3) | (buf[5] >> 5); + uint8_t k1 = buf[4] & 0xf; + uint8_t k2 = buf[4] >> 4; + center = logitech_g27_high_resolution_position_to_center(d1, d2); + deadband = logitech_g27_high_resolution_position_to_width(d1, d2); + left_coeff = logitech_g27_high_resolution_coeff_to_coeff(k1, s1); + right_coeff = logitech_g27_high_resolution_coeff_to_coeff(k2, s2); + } + if (reverse_effects) + { + int16_t coeff = right_coeff; + right_coeff = left_coeff; + left_coeff = coeff; + } + // for(int j = 0;j < 3;j++) + for (int j = 0; j < 1; j++) + { + new_effect.condition.right_sat[j] = saturation; + new_effect.condition.left_sat[j] = saturation; + new_effect.condition.right_coeff[j] = right_coeff; + new_effect.condition.left_coeff[j] = left_coeff; + new_effect.condition.deadband[j] = deadband; + new_effect.condition.center[j] = center; + } + break; + } + case 0x02: + case 0x0c: + { + // Damper/High resolution damper + new_effect.type = SDL_HAPTIC_DAMPER; + new_effect.condition.direction = direction; + new_effect.condition.length = SDL_HAPTIC_INFINITY; + uint8_t s1 = buf[3] & 1; + uint8_t s2 = buf[5] & 1; + // TODO direction cfg + uint16_t saturation = 0x7FFF; + int16_t left_coeff = 0; + int16_t right_coeff = 0; + if (buf[1] == 0x02) + { + uint8_t k1 = buf[2] & (0xf >> 1); + uint8_t k2 = buf[4] & (0xf >> 1); + left_coeff = logitech_g27_coeff_to_coeff(k1, s1); + right_coeff = logitech_g27_coeff_to_coeff(k2, s2); + } + else + { + uint8_t k1 = buf[2] & 0xf; + uint8_t k2 = buf[4] & 0xf; + left_coeff = logitech_g27_high_resolution_coeff_to_coeff(k1, s1); + right_coeff = logitech_g27_high_resolution_coeff_to_coeff(k2, s2); + saturation = logitech_g27_clip_to_saturation(buf[6]); + } + if (reverse_effects) + { + int16_t coeff = right_coeff; + right_coeff = left_coeff; + left_coeff = coeff; + } + // for(int j = 0;j < 3;j++) + for (int j = 0; j < 1; j++) + { + new_effect.condition.right_sat[j] = saturation; + new_effect.condition.left_sat[j] = saturation; + new_effect.condition.right_coeff[j] = right_coeff; + new_effect.condition.left_coeff[j] = left_coeff; + } + break; + } + case 0x0e: + { + // Friction + new_effect.type = SDL_HAPTIC_FRICTION; + new_effect.condition.direction = direction; + new_effect.condition.length = SDL_HAPTIC_INFINITY; + uint8_t k1 = buf[2]; + uint8_t k2 = buf[3]; + uint8_t s1 = buf[5] & 1; + uint8_t s2 = (buf[5] >> 4) & 1; + // TODO direction cfg + int16_t left_coeff = logitech_g27_friction_coeff_to_coeff(k1, s1); + int16_t right_coeff = logitech_g27_friction_coeff_to_coeff(k2, s2); + int16_t saturation = logitech_g27_clip_to_saturation(buf[4]); + if (reverse_effects) + { + int16_t coeff = right_coeff; + right_coeff = left_coeff; + left_coeff = coeff; + } + // for(int j = 0;j < 3;j++) + for (int j = 0; j < 1; j++) + { + new_effect.condition.right_sat[j] = saturation; + new_effect.condition.left_sat[j] = saturation; + new_effect.condition.right_coeff[j] = right_coeff; + new_effect.condition.left_coeff[j] = left_coeff; + } + break; + } + case 0x03: + case 0x0d: + { + // Auto center spring/High resolution auto center spring + new_effect.type = SDL_HAPTIC_SPRING; + new_effect.condition.direction = direction; + new_effect.condition.length = SDL_HAPTIC_INFINITY; + // TODO direction cfg + uint16_t saturation = logitech_g27_clip_to_saturation(buf[4]); + uint16_t deadband = 2 * 0xFFFF / 255; + int16_t center = 0; + int16_t left_coeff = 0; + int16_t right_coeff = 0; + if (buf[1] == 0x03) + { + uint8_t k1 = buf[2] & (0xf >> 1); + uint8_t k2 = buf[3] & (0xf >> 1); + left_coeff = logitech_g27_coeff_to_coeff(k1, 0); + right_coeff = logitech_g27_coeff_to_coeff(k2, 0); + } + else + { + uint8_t k1 = buf[2] & 0xf; + uint8_t k2 = buf[3] & 0xf; + left_coeff = logitech_g27_high_resolution_coeff_to_coeff(k1, 0); + right_coeff = logitech_g27_high_resolution_coeff_to_coeff(k2, 0); + } + if (reverse_effects) + { + int16_t coeff = right_coeff; + right_coeff = left_coeff; + left_coeff = coeff; + } + // for(int j = 0;j < 3;j++) + for (int j = 0; j < 1; j++) + { + new_effect.condition.right_sat[j] = saturation; + new_effect.condition.left_sat[j] = saturation; + new_effect.condition.right_coeff[j] = right_coeff; + new_effect.condition.left_coeff[j] = left_coeff; + new_effect.condition.deadband[j] = deadband; + new_effect.condition.center[j] = center; + } + break; + } + case 0x04: + case 0x05: + { + // Sawtooth up/Sawtooth down + new_effect.type = buf[1] == 0x04 ? SDL_HAPTIC_SAWTOOTHUP : SDL_HAPTIC_SAWTOOTHDOWN; + new_effect.periodic.direction = direction; + new_effect.periodic.length = SDL_HAPTIC_INFINITY; + uint8_t l1 = buf[2]; + uint8_t l2 = buf[3]; + uint8_t l0 = buf[4]; + uint8_t t3 = buf[6] >> 4; + uint8_t inc = buf[6] & 0xf; + if (inc != 0) + new_effect.periodic.period = ((l1 - l2) * logitech_g27_loops_to_ms(t3, !fixed_loop)) / inc; + else + { + logitech_g27_log.error("cannot evaluate slope for saw tooth effect, loops per step %u level per step %u", t3, inc); + new_effect.periodic.period = 1000; + } + new_effect.periodic.offset = logitech_g27_force_to_level((l1 + l2) / 2); + new_effect.periodic.magnitude = logitech_g27_force_to_level(l1) - new_effect.periodic.offset; + new_effect.periodic.phase = buf[1] == 0x04 ? 36000 * (l1 - l0) / (l1 - l2) : 36000 * (l0 - l2) / (l1 - l2); + break; + } + case 0x06: + { + // Trapezoid, convert to SDL_HAPTIC_SQUARE or SDL_HAPTIC_TRIANGLE + new_effect.periodic.direction = direction; + new_effect.periodic.length = SDL_HAPTIC_INFINITY; + uint8_t l1 = buf[2]; + uint8_t l2 = buf[3]; + uint8_t t1 = buf[4]; + uint8_t t2 = buf[5]; + uint8_t t3 = buf[6] >> 4; + uint8_t s = buf[6] & 0xf; + uint16_t total_flat_time = logitech_g27_loops_to_ms(t1 + t2, !fixed_loop); + uint16_t total_slope_time = (((l1 - l2) * logitech_g27_loops_to_ms(t3, !fixed_loop)) / s) * 2; + if (total_flat_time > total_slope_time) + { + new_effect.type = SDL_HAPTIC_SQUARE; + } + else + { + new_effect.type = SDL_HAPTIC_TRIANGLE; + } + new_effect.periodic.period = total_slope_time + total_flat_time; + new_effect.periodic.offset = logitech_g27_force_to_level((l1 + l2) / 2); + new_effect.periodic.magnitude = logitech_g27_force_to_level(l1) - new_effect.periodic.offset; + break; + } + case 0x07: + { + // Rectangle, convert to SDL_HAPTIC_SQUARE + new_effect.type = SDL_HAPTIC_SQUARE; + new_effect.periodic.direction = direction; + new_effect.periodic.length = SDL_HAPTIC_INFINITY; + uint8_t l1 = buf[2]; + uint8_t l2 = buf[3]; + uint8_t t1 = buf[4]; + uint8_t t2 = buf[5]; + uint8_t p = buf[6]; + new_effect.periodic.period = logitech_g27_loops_to_ms(t1, !fixed_loop) + logitech_g27_loops_to_ms(t2, !fixed_loop); + new_effect.periodic.offset = logitech_g27_force_to_level((l1 + l2) / 2); + new_effect.periodic.magnitude = logitech_g27_force_to_level(l1) - new_effect.periodic.offset; + if (new_effect.periodic.period != 0) + new_effect.periodic.phase = 36000 * logitech_g27_loops_to_ms(p, !fixed_loop) / new_effect.periodic.period; + else + { + logitech_g27_log.error("cannot evaluate phase for square effect"); + new_effect.periodic.phase = 0; + } + break; + } + case 0x08: + case 0x09: + { + // Variable/Ramp, convert to SDL_HAPTIC_CONSTANT + if (i % 2 != 0) { continue; } - bool unknown_effect = false; - switch (buf[1]) + new_effect.type = SDL_HAPTIC_CONSTANT; + new_effect.constant.direction = direction; + uint8_t l1 = buf[2]; + uint8_t l2 = buf[3]; + uint8_t t1 = buf[4] >> 4; + uint8_t s1 = buf[4] & 0xf; + uint8_t t2 = buf[5] >> 4; + uint8_t s2 = buf[5] & 0xf; + uint8_t d1 = buf[6] & 1; + uint8_t d2 = (buf[6] >> 4) & 1; + if (buf[1] == 0x08) { - case 0x00: + uint8_t t = i == 0 ? t1 : t2; + uint8_t s = i == 0 ? s1 : s2; + uint8_t d = i == 0 ? d1 : d2; + uint8_t l = i == 0 ? l1 : l2; + new_effect.constant.length = SDL_HAPTIC_INFINITY; + if (s == 0 || t == 0) { - // Constant force - new_effect.type = SDL_HAPTIC_CONSTANT; - new_effect.constant.direction = direction; - new_effect.constant.length = SDL_HAPTIC_INFINITY; - new_effect.constant.level = logitech_g27_force_to_level(buf[2 + i]); - break; - } - case 0x01: - case 0x0b: - { - // Spring/High resolution spring - new_effect.type = SDL_HAPTIC_SPRING; - new_effect.condition.direction = direction; - new_effect.condition.length = SDL_HAPTIC_INFINITY; - uint8_t s1 = buf[5] & 1; - uint8_t s2 = (buf[5] >> 4) & 1; - // TODO direction cfg - uint16_t saturation = logitech_g27_clip_to_saturation(buf[6]); - int16_t center = 0; - uint16_t deadband = 0; - int16_t left_coeff = 0; - int16_t right_coeff = 0; - if (buf[1] == 0x01) - { - uint8_t d1 = buf[2]; - uint8_t d2 = buf[3]; - uint8_t k1 = buf[4] & (0xf >> 1); - uint8_t k2 = (buf[4] >> 4) & (0xf >> 1); - center = logitech_g27_position_to_center(d1, d2); - deadband = logitech_g27_position_to_width(d1, d2); - left_coeff = logitech_g27_coeff_to_coeff(k1, s1); - right_coeff = logitech_g27_coeff_to_coeff(k2, s2); - } - else - { - uint16_t d1 = (buf[2] << 3) | ((buf[5] >> 1) & (0xf >> 1)); - uint16_t d2 = (buf[3] << 3) | (buf[5] >> 5); - uint8_t k1 = buf[4] & 0xf; - uint8_t k2 = buf[4] >> 4; - center = logitech_g27_high_resolution_position_to_center(d1, d2); - deadband = logitech_g27_high_resolution_position_to_width(d1, d2); - left_coeff = logitech_g27_high_resolution_coeff_to_coeff(k1, s1); - right_coeff = logitech_g27_high_resolution_coeff_to_coeff(k2, s2); - } - if (reverse_effects) - { - int16_t coeff = right_coeff; - right_coeff = left_coeff; - left_coeff = coeff; - } - //for(int j = 0;j < 3;j++) - for(int j = 0;j < 1;j++) - { - new_effect.condition.right_sat[j] = saturation; - new_effect.condition.left_sat[j] = saturation; - new_effect.condition.right_coeff[j] = right_coeff; - new_effect.condition.left_coeff[j] = left_coeff; - new_effect.condition.deadband[j] = deadband; - new_effect.condition.center[j] = center; - } - break; - } - case 0x02: - case 0x0c: - { - // Damper/High resolution damper - new_effect.type = SDL_HAPTIC_DAMPER; - new_effect.condition.direction = direction; - new_effect.condition.length = SDL_HAPTIC_INFINITY; - uint8_t s1 = buf[3] & 1; - uint8_t s2 = buf[5] & 1; - // TODO direction cfg - uint16_t saturation = 0x7FFF; - int16_t left_coeff = 0; - int16_t right_coeff = 0; - if (buf[1] == 0x02) - { - uint8_t k1 = buf[2] & (0xf >> 1); - uint8_t k2 = buf[4] & (0xf >> 1); - left_coeff = logitech_g27_coeff_to_coeff(k1, s1); - right_coeff = logitech_g27_coeff_to_coeff(k2, s2); - } - else - { - uint8_t k1 = buf[2] & 0xf; - uint8_t k2 = buf[4] & 0xf; - left_coeff = logitech_g27_high_resolution_coeff_to_coeff(k1, s1); - right_coeff = logitech_g27_high_resolution_coeff_to_coeff(k2, s2); - saturation = logitech_g27_clip_to_saturation(buf[6]); - } - if (reverse_effects) - { - int16_t coeff = right_coeff; - right_coeff = left_coeff; - left_coeff = coeff; - } - //for(int j = 0;j < 3;j++) - for(int j = 0;j < 1;j++) - { - new_effect.condition.right_sat[j] = saturation; - new_effect.condition.left_sat[j] = saturation; - new_effect.condition.right_coeff[j] = right_coeff; - new_effect.condition.left_coeff[j] = left_coeff; - } - break; - } - case 0x0e: - { - // Friction - new_effect.type = SDL_HAPTIC_FRICTION; - new_effect.condition.direction = direction; - new_effect.condition.length = SDL_HAPTIC_INFINITY; - uint8_t k1 = buf[2]; - uint8_t k2 = buf[3]; - uint8_t s1 = buf[5] & 1; - uint8_t s2 = (buf[5] >> 4) & 1; - // TODO direction cfg - int16_t left_coeff = logitech_g27_friction_coeff_to_coeff(k1, s1); - int16_t right_coeff = logitech_g27_friction_coeff_to_coeff(k2, s2); - int16_t saturation = logitech_g27_clip_to_saturation(buf[4]); - if (reverse_effects) - { - int16_t coeff = right_coeff; - right_coeff = left_coeff; - left_coeff = coeff; - } - //for(int j = 0;j < 3;j++) - for(int j = 0;j < 1;j++) - { - new_effect.condition.right_sat[j] = saturation; - new_effect.condition.left_sat[j] = saturation; - new_effect.condition.right_coeff[j] = right_coeff; - new_effect.condition.left_coeff[j] = left_coeff; - } - break; - } - case 0x03: - case 0x0d: - { - // Auto center spring/High resolution auto center spring - new_effect.type = SDL_HAPTIC_SPRING; - new_effect.condition.direction = direction; - new_effect.condition.length = SDL_HAPTIC_INFINITY; - // TODO direction cfg - uint16_t saturation = logitech_g27_clip_to_saturation(buf[4]); - uint16_t deadband = 2 * 0xFFFF / 255; - int16_t center = 0; - int16_t left_coeff = 0; - int16_t right_coeff = 0; - if (buf[1] == 0x03) - { - uint8_t k1 = buf[2] & (0xf >> 1); - uint8_t k2 = buf[3] & (0xf >> 1); - left_coeff = logitech_g27_coeff_to_coeff(k1, 0); - right_coeff = logitech_g27_coeff_to_coeff(k2, 0); - } - else - { - uint8_t k1 = buf[2] & 0xf; - uint8_t k2 = buf[3] & 0xf; - left_coeff = logitech_g27_high_resolution_coeff_to_coeff(k1, 0); - right_coeff = logitech_g27_high_resolution_coeff_to_coeff(k2, 0); - } - if (reverse_effects) - { - int16_t coeff = right_coeff; - right_coeff = left_coeff; - left_coeff = coeff; - } - //for(int j = 0;j < 3;j++) - for(int j = 0;j < 1;j++) - { - new_effect.condition.right_sat[j] = saturation; - new_effect.condition.left_sat[j] = saturation; - new_effect.condition.right_coeff[j] = right_coeff; - new_effect.condition.left_coeff[j] = left_coeff; - new_effect.condition.deadband[j] = deadband; - new_effect.condition.center[j] = center; - } - break; - } - case 0x04: - case 0x05: - { - // Sawtooth up/Sawtooth down - new_effect.type = buf[1] == 0x04 ? SDL_HAPTIC_SAWTOOTHUP : SDL_HAPTIC_SAWTOOTHDOWN; - new_effect.periodic.direction = direction; - new_effect.periodic.length = SDL_HAPTIC_INFINITY; - uint8_t l1 = buf[2]; - uint8_t l2 = buf[3]; - uint8_t l0 = buf[4]; - uint8_t t3 = buf[6] >> 4; - uint8_t inc = buf[6] & 0xf; - if (inc != 0) - new_effect.periodic.period = ((l1 - l2) * logitech_g27_loops_to_ms(t3, !fixed_loop)) / inc; - else - { - logitech_g27_log.error("cannot evaluate slope for saw tooth effect, loops per step %u level per step %u", t3, inc); - new_effect.periodic.period = 1000; - } - new_effect.periodic.offset = logitech_g27_force_to_level((l1 + l2) / 2); - new_effect.periodic.magnitude = logitech_g27_force_to_level(l1) - new_effect.periodic.offset; - new_effect.periodic.phase = buf[1] == 0x04 ? 36000 * (l1 - l0) / (l1 - l2) : 36000 * (l0 - l2) / (l1 - l2); - break; - } - case 0x06: - { - // Trapezoid, convert to SDL_HAPTIC_SQUARE or SDL_HAPTIC_TRIANGLE - new_effect.periodic.direction = direction; - new_effect.periodic.length = SDL_HAPTIC_INFINITY; - uint8_t l1 = buf[2]; - uint8_t l2 = buf[3]; - uint8_t t1 = buf[4]; - uint8_t t2 = buf[5]; - uint8_t t3 = buf[6] >> 4; - uint8_t s = buf[6] & 0xf; - uint16_t total_flat_time = logitech_g27_loops_to_ms(t1 + t2, !fixed_loop); - uint16_t total_slope_time = (((l1 - l2) * logitech_g27_loops_to_ms(t3, !fixed_loop)) / s) * 2; - if (total_flat_time > total_slope_time) - { - new_effect.type = SDL_HAPTIC_SQUARE; - } - else - { - new_effect.type = SDL_HAPTIC_TRIANGLE; - } - new_effect.periodic.period = total_slope_time + total_flat_time; - new_effect.periodic.offset = logitech_g27_force_to_level((l1 + l2) / 2); - new_effect.periodic.magnitude = logitech_g27_force_to_level(l1) - new_effect.periodic.offset; - break; - } - case 0x07: - { - // Rectangle, convert to SDL_HAPTIC_SQUARE - new_effect.type = SDL_HAPTIC_SQUARE; - new_effect.periodic.direction = direction; - new_effect.periodic.length = SDL_HAPTIC_INFINITY; - uint8_t l1 = buf[2]; - uint8_t l2 = buf[3]; - uint8_t t1 = buf[4]; - uint8_t t2 = buf[5]; - uint8_t p = buf[6]; - new_effect.periodic.period = logitech_g27_loops_to_ms(t1, !fixed_loop) + logitech_g27_loops_to_ms(t2, !fixed_loop); - new_effect.periodic.offset = logitech_g27_force_to_level((l1 + l2) / 2); - new_effect.periodic.magnitude = logitech_g27_force_to_level(l1) - new_effect.periodic.offset; - if (new_effect.periodic.period != 0) - new_effect.periodic.phase = 36000 * logitech_g27_loops_to_ms(p, !fixed_loop) / new_effect.periodic.period; - else - { - logitech_g27_log.error("cannot evaluate phase for square effect"); - new_effect.periodic.phase = 0; - } - break; - } - case 0x08: - case 0x09: - { - // Variable/Ramp, convert to SDL_HAPTIC_CONSTANT - if (i % 2 != 0) - { - continue; - } - new_effect.type = SDL_HAPTIC_CONSTANT; - new_effect.constant.direction = direction; - uint8_t l1 = buf[2]; - uint8_t l2 = buf[3]; - uint8_t t1 = buf[4] >> 4; - uint8_t s1 = buf[4] & 0xf; - uint8_t t2 = buf[5] >> 4; - uint8_t s2 = buf[5] & 0xf; - uint8_t d1 = buf[6] & 1; - uint8_t d2 = (buf[6] >> 4) & 1; - if (buf[1] == 0x08) - { - uint8_t t = i == 0 ? t1 : t2; - uint8_t s = i == 0 ? s1 : s2; - uint8_t d = i == 0 ? d1 : d2; - uint8_t l = i == 0 ? l1 : l2; - new_effect.constant.length = SDL_HAPTIC_INFINITY; - if (s == 0 || t == 0) - { - // gran turismo 6 does this, gives a variable force with no step so it just behaves as constant force - new_effect.constant.level = logitech_g27_force_to_level(l); - // hack: gran turismo 6 spams download and play - update_hack = true; - } - else - { - new_effect.constant.attack_level = logitech_g27_force_to_level(l); - if (d) - { - new_effect.constant.level = 0; - new_effect.constant.attack_length = l * logitech_g27_loops_to_ms(t, !fixed_loop) / s; - } - else - { - new_effect.constant.level = 0x7FFF; - new_effect.constant.attack_length = (255 - l) * logitech_g27_loops_to_ms(t, !fixed_loop) / s; - } - } - } - else - { - if (s2 == 0 || t2 == 0) - { - logitech_g27_log.error("cannot evaluate slope for ramp effect, loops per step %u level per step %u", t2, s2); - } - else - { - new_effect.constant.length = (l1 - l2) * logitech_g27_loops_to_ms(t2, !fixed_loop) / s2 ; - new_effect.constant.attack_length = new_effect.constant.length; - new_effect.constant.attack_level = d1 ? logitech_g27_force_to_level(l1) : logitech_g27_force_to_level(l2); - } - new_effect.constant.level = d1 ? logitech_g27_force_to_level(l2) : logitech_g27_force_to_level(l1); - } - break; - } - case 0x0a: - { - // Square - new_effect.type = SDL_HAPTIC_SQUARE; - new_effect.periodic.direction = direction; - uint8_t a = buf[2]; - uint8_t tl = buf[3]; - uint8_t th = buf[4]; - uint8_t n = buf[5]; - uint16_t t = (th << 8) | tl; - new_effect.periodic.period = logitech_g27_loops_to_ms(t * 2, !fixed_loop); - new_effect.periodic.magnitude = logitech_g27_amplitude_to_magnitude(a); - if (n == 0) - new_effect.periodic.length = new_effect.periodic.period * 256; - else - new_effect.periodic.length = new_effect.periodic.period * n; - break; - } - default: - { - unknown_effect = true; - } - } - - if (unknown_effect) - { - logitech_g27_log.error("Command %02x %02x %02x %02x %02x %02x %02x with unknown effect ignored", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); - continue; - } - - bool play_effect = (cmd == 0x01 || (cmd == 0x0c && effect_slots[i].effect_id == -1)); - - if (update_hack) - { - if (effect_slots[i].effect_id == -1) - update_hack = false; - if (effect_slots[i].last_effect.type != new_effect.type) - update_hack = false; - } - - if (cmd == 0x00 || play_effect) - { - if (effect_slots[i].effect_id != -1 && haptic_handle != nullptr && !update_hack) - { - SDL_DestroyHapticEffect(haptic_handle, effect_slots[i].effect_id); - effect_slots[i].effect_id = -1; - } - if (haptic_handle != nullptr && effect_slots[i].effect_id == -1) - { - effect_slots[i].effect_id = SDL_CreateHapticEffect(haptic_handle, &new_effect); - } - if (update_hack) - { - if (!SDL_UpdateHapticEffect(haptic_handle, effect_slots[i].effect_id, &new_effect)) - logitech_g27_log.error("Failed refreshing slot %d sdl effect %d, %s", i, new_effect.type, SDL_GetError()); - } - effect_slots[i].state = G27_FFB_DOWNLOADED; - effect_slots[i].last_effect = new_effect; - effect_slots[i].last_update = SDL_GetTicks(); - if (effect_slots[i].effect_id == -1 && haptic_handle != nullptr) - { - logitech_g27_log.error("Failed uploading effect %02x %02x %02x %02x %02x %02x %02x to slot %i, %s", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], i, SDL_GetError()); - } - } - if (play_effect && haptic_handle != nullptr) - { - if (effect_slots[i].effect_id != -1) - { - if (!SDL_RunHapticEffect(haptic_handle, effect_slots[i].effect_id, 1)) - { - logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s\n", effect_slots[i].last_effect.type, i, SDL_GetError()); - } + // gran turismo 6 does this, gives a variable force with no step so it just behaves as constant force + new_effect.constant.level = logitech_g27_force_to_level(l); + // hack: gran turismo 6 spams download and play + update_hack = true; } else { - logitech_g27_log.error("Tried to play effect slot %d with sdl effect %d, but upload failed previously", i, effect_slots[i].last_effect.type); - } - effect_slots[i].state = G27_FFB_PLAYING; - } - if (cmd == 0xc && !play_effect && haptic_handle != nullptr) - { - if (!SDL_UpdateHapticEffect(haptic_handle, effect_slots[i].effect_id, &new_effect)) - { - logitech_g27_log.error("Failed refreshing slot %d sdl effect %d, %s", i, new_effect.type, SDL_GetError()); - } - } - } - break; - } - case 0x02: - case 0x03: - { - for (int i = 0;i < 4;i++) - { - // Play/Stop - if (!(slot_mask & (1 << i))) - { - continue; - } - if (effect_slots[i].state == G27_FFB_PLAYING || effect_slots[i].state == G27_FFB_DOWNLOADED) - { - effect_slots[i].state = cmd == 0x02 ? G27_FFB_PLAYING : G27_FFB_DOWNLOADED; - if (haptic_handle != nullptr) - { - if (effect_slots[i].effect_id == -1) + new_effect.constant.attack_level = logitech_g27_force_to_level(l); + if (d) { - effect_slots[i].effect_id = SDL_CreateHapticEffect(haptic_handle, &effect_slots[i].last_effect); - } - if (effect_slots[i].effect_id != -1) - { - if (cmd == 0x02) - { - if (!SDL_RunHapticEffect(haptic_handle, effect_slots[i].effect_id, 1)) - { - logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s\n", effect_slots[i].last_effect.type, i, SDL_GetError()); - } - } - else - { - if (!SDL_StopHapticEffect(haptic_handle, effect_slots[i].effect_id)) - { - logitech_g27_log.error("Failed stopping sdl effect %d on slot %d, %s\n", effect_slots[i].last_effect.type, i, SDL_GetError()); - } - } + new_effect.constant.level = 0; + new_effect.constant.attack_length = l * logitech_g27_loops_to_ms(t, !fixed_loop) / s; } else { - if (cmd == 0x02) - { - logitech_g27_log.error("Tried to play effect slot %d with sdl effect %d, but upload failed previously", i, effect_slots[i].last_effect.type); - } - else - { - logitech_g27_log.error("Tried to stop effect slot %d with sdl effect %d, but upload failed previously", i, effect_slots[i].last_effect.type); - } + new_effect.constant.level = 0x7FFF; + new_effect.constant.attack_length = (255 - l) * logitech_g27_loops_to_ms(t, !fixed_loop) / s; } } } else { - if (cmd == 0x02) + if (s2 == 0 || t2 == 0) { - logitech_g27_log.error("Tried to play effect slot %d but it was never uploaded\n", i); + logitech_g27_log.error("cannot evaluate slope for ramp effect, loops per step %u level per step %u", t2, s2); } else { - logitech_g27_log.error("Tried to stop effect slot %d but it was never uploaded\n", i); + new_effect.constant.length = (l1 - l2) * logitech_g27_loops_to_ms(t2, !fixed_loop) / s2; + new_effect.constant.attack_length = new_effect.constant.length; + new_effect.constant.attack_level = d1 ? logitech_g27_force_to_level(l1) : logitech_g27_force_to_level(l2); } + new_effect.constant.level = d1 ? logitech_g27_force_to_level(l2) : logitech_g27_force_to_level(l1); } - } - break; - } - case 0x0e: - { - // Set Default Spring - uint8_t k1 = buf[2] & (0xf >> 1); - uint8_t k2 = buf[3] & (0xf >> 1); - uint16_t saturation = logitech_g27_clip_to_saturation(buf[4]); - int16_t left_coeff = logitech_g27_coeff_to_coeff(k1, 0); - int16_t right_coeff = logitech_g27_coeff_to_coeff(k2, 0); - uint16_t deadband = 2 * 0xFFFF / 255; - int16_t center = 0; - if (reverse_effects) - { - int16_t coeff = right_coeff; - right_coeff = left_coeff; - left_coeff = coeff; - } - //for (int i = 0;i < 3;i++){ - for (int i = 0;i < 1;i++){ - // TODO direction cfg - default_spring_effect.condition.right_sat[i] = saturation; - default_spring_effect.condition.left_sat[i] = saturation; - default_spring_effect.condition.right_coeff[i] = right_coeff; - default_spring_effect.condition.left_coeff[i] = left_coeff; - default_spring_effect.condition.deadband[i] = deadband; - default_spring_effect.condition.center[i] = center; - } - - if (haptic_handle == nullptr) - { break; } - - if (default_spring_effect_id == -1) + case 0x0a: { - default_spring_effect_id = SDL_CreateHapticEffect(haptic_handle, &default_spring_effect); - if (default_spring_effect_id == -1) + // Square + new_effect.type = SDL_HAPTIC_SQUARE; + new_effect.periodic.direction = direction; + uint8_t a = buf[2]; + uint8_t tl = buf[3]; + uint8_t th = buf[4]; + uint8_t n = buf[5]; + uint16_t t = (th << 8) | tl; + new_effect.periodic.period = logitech_g27_loops_to_ms(t * 2, !fixed_loop); + new_effect.periodic.magnitude = logitech_g27_amplitude_to_magnitude(a); + if (n == 0) + new_effect.periodic.length = new_effect.periodic.period * 256; + else + new_effect.periodic.length = new_effect.periodic.period * n; + break; + } + default: + { + unknown_effect = true; + } + } + + if (unknown_effect) + { + logitech_g27_log.error("Command %02x %02x %02x %02x %02x %02x %02x with unknown effect ignored", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + continue; + } + + bool play_effect = (cmd == 0x01 || (cmd == 0x0c && effect_slots[i].effect_id == -1)); + + if (update_hack) + { + if (effect_slots[i].effect_id == -1) + update_hack = false; + if (effect_slots[i].last_effect.type != new_effect.type) + update_hack = false; + } + + if (cmd == 0x00 || play_effect) + { + if (effect_slots[i].effect_id != -1 && haptic_handle != nullptr && !update_hack) { - logitech_g27_log.error("Failed creating default spring effect, %s", SDL_GetError()); + SDL_DestroyHapticEffect(haptic_handle, effect_slots[i].effect_id); + effect_slots[i].effect_id = -1; + } + if (haptic_handle != nullptr && effect_slots[i].effect_id == -1) + { + effect_slots[i].effect_id = SDL_CreateHapticEffect(haptic_handle, &new_effect); + } + if (update_hack) + { + if (!SDL_UpdateHapticEffect(haptic_handle, effect_slots[i].effect_id, &new_effect)) + logitech_g27_log.error("Failed refreshing slot %d sdl effect %d, %s", i, new_effect.type, SDL_GetError()); + } + effect_slots[i].state = G27_FFB_DOWNLOADED; + effect_slots[i].last_effect = new_effect; + effect_slots[i].last_update = SDL_GetTicks(); + if (effect_slots[i].effect_id == -1 && haptic_handle != nullptr) + { + logitech_g27_log.error("Failed uploading effect %02x %02x %02x %02x %02x %02x %02x to slot %i, %s", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], i, SDL_GetError()); + } + } + if (play_effect && haptic_handle != nullptr) + { + if (effect_slots[i].effect_id != -1) + { + if (!SDL_RunHapticEffect(haptic_handle, effect_slots[i].effect_id, 1)) + { + logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s\n", effect_slots[i].last_effect.type, i, SDL_GetError()); + } + } + else + { + logitech_g27_log.error("Tried to play effect slot %d with sdl effect %d, but upload failed previously", i, effect_slots[i].last_effect.type); + } + effect_slots[i].state = G27_FFB_PLAYING; + } + if (cmd == 0xc && !play_effect && haptic_handle != nullptr) + { + if (!SDL_UpdateHapticEffect(haptic_handle, effect_slots[i].effect_id, &new_effect)) + { + logitech_g27_log.error("Failed refreshing slot %d sdl effect %d, %s", i, new_effect.type, SDL_GetError()); + } + } + } + break; + } + case 0x02: + case 0x03: + { + for (int i = 0; i < 4; i++) + { + // Play/Stop + if (!(slot_mask & (1 << i))) + { + continue; + } + if (effect_slots[i].state == G27_FFB_PLAYING || effect_slots[i].state == G27_FFB_DOWNLOADED) + { + effect_slots[i].state = cmd == 0x02 ? G27_FFB_PLAYING : G27_FFB_DOWNLOADED; + if (haptic_handle != nullptr) + { + if (effect_slots[i].effect_id == -1) + { + effect_slots[i].effect_id = SDL_CreateHapticEffect(haptic_handle, &effect_slots[i].last_effect); + } + if (effect_slots[i].effect_id != -1) + { + if (cmd == 0x02) + { + if (!SDL_RunHapticEffect(haptic_handle, effect_slots[i].effect_id, 1)) + { + logitech_g27_log.error("Failed playing sdl effect %d on slot %d, %s\n", effect_slots[i].last_effect.type, i, SDL_GetError()); + } + } + else + { + if (!SDL_StopHapticEffect(haptic_handle, effect_slots[i].effect_id)) + { + logitech_g27_log.error("Failed stopping sdl effect %d on slot %d, %s\n", effect_slots[i].last_effect.type, i, SDL_GetError()); + } + } + } + else + { + if (cmd == 0x02) + { + logitech_g27_log.error("Tried to play effect slot %d with sdl effect %d, but upload failed previously", i, effect_slots[i].last_effect.type); + } + else + { + logitech_g27_log.error("Tried to stop effect slot %d with sdl effect %d, but upload failed previously", i, effect_slots[i].last_effect.type); + } + } } } else { - if (!SDL_UpdateHapticEffect(haptic_handle, default_spring_effect_id, &default_spring_effect)) + if (cmd == 0x02) { - logitech_g27_log.error("Failed updating default spring effect, %s", SDL_GetError()); - } - } - break; - } - case 0x04: - case 0x05: - { - // Default spring on/Default spring off - if (haptic_handle == nullptr) - { - break; - } - - if (default_spring_effect_id == -1) - { - default_spring_effect_id = SDL_CreateHapticEffect(haptic_handle, &default_spring_effect); - if (default_spring_effect_id == -1) - { - logitech_g27_log.error("Failed creating default spring effect, %s", SDL_GetError()); - } - } - if (default_spring_effect_id != -1) - { - if (cmd == 0x04) - { - if (!SDL_RunHapticEffect(haptic_handle, default_spring_effect_id, 1)) - { - logitech_g27_log.error("Failed playing default spring effect, %s", SDL_GetError()); - } + logitech_g27_log.error("Tried to play effect slot %d but it was never uploaded\n", i); } else { - if (!SDL_StopHapticEffect(haptic_handle, default_spring_effect_id)) - { - logitech_g27_log.error("Failed stopping default spring effect, %s", SDL_GetError()); - } + logitech_g27_log.error("Tried to stop effect slot %d but it was never uploaded\n", i); } } - break; } - case 0x08: + break; + } + case 0x0e: + { + // Set Default Spring + uint8_t k1 = buf[2] & (0xf >> 1); + uint8_t k2 = buf[3] & (0xf >> 1); + uint16_t saturation = logitech_g27_clip_to_saturation(buf[4]); + int16_t left_coeff = logitech_g27_coeff_to_coeff(k1, 0); + int16_t right_coeff = logitech_g27_coeff_to_coeff(k2, 0); + uint16_t deadband = 2 * 0xFFFF / 255; + int16_t center = 0; + if (reverse_effects) { - // Normal Mode / Extended - logitech_g27_log.error("Normal mode restore command ignored"); - break; + int16_t coeff = right_coeff; + right_coeff = left_coeff; + left_coeff = coeff; } - case 0x09: + // for (int i = 0;i < 3;i++){ + for (int i = 0; i < 1; i++) { - // Set LED - if (led_joystick_handle == nullptr) - { - break; - } + // TODO direction cfg + default_spring_effect.condition.right_sat[i] = saturation; + default_spring_effect.condition.left_sat[i] = saturation; + default_spring_effect.condition.right_coeff[i] = right_coeff; + default_spring_effect.condition.left_coeff[i] = left_coeff; + default_spring_effect.condition.deadband[i] = deadband; + default_spring_effect.condition.center[i] = center; + } - uint8_t new_led_level = 0; - for (int i = 0;i < 8;i++) + if (haptic_handle == nullptr) + { + break; + } + + if (default_spring_effect_id == -1) + { + default_spring_effect_id = SDL_CreateHapticEffect(haptic_handle, &default_spring_effect); + if (default_spring_effect_id == -1) { - new_led_level += (buf[1] & (1 << i)) ? 1 : 0; + logitech_g27_log.error("Failed creating default spring effect, %s", SDL_GetError()); } - uint8_t intensity = new_led_level * 255 / 7; - SDL_SetJoystickLED(led_joystick_handle, intensity, intensity, intensity); - break; } - case 0x0a: + else { - // Set watchdog - logitech_g27_log.error("Watchdog command with duration of %u loops ignored", buf[1]); - break; - } - case 0x0b: - { - // Raw mode - logitech_g27_log.error("Raw mode command ignored"); - break; - } - case 0x0d: - { - // Fixed time loop toggle - fixed_loop = buf[1] ? true : false; - if (!fixed_loop) + if (!SDL_UpdateHapticEffect(haptic_handle, default_spring_effect_id, &default_spring_effect)) { - logitech_g27_log.error("as fast as possible mode requested, effect durations might be inaccurate"); + logitech_g27_log.error("Failed updating default spring effect, %s", SDL_GetError()); } + } + break; + } + case 0x04: + case 0x05: + { + // Default spring on/Default spring off + if (haptic_handle == nullptr) + { break; } - case 0x0f: + + if (default_spring_effect_id == -1) + { + default_spring_effect_id = SDL_CreateHapticEffect(haptic_handle, &default_spring_effect); + if (default_spring_effect_id == -1) + { + logitech_g27_log.error("Failed creating default spring effect, %s", SDL_GetError()); + } + } + if (default_spring_effect_id != -1) + { + if (cmd == 0x04) + { + if (!SDL_RunHapticEffect(haptic_handle, default_spring_effect_id, 1)) + { + logitech_g27_log.error("Failed playing default spring effect, %s", SDL_GetError()); + } + } + else + { + if (!SDL_StopHapticEffect(haptic_handle, default_spring_effect_id)) + { + logitech_g27_log.error("Failed stopping default spring effect, %s", SDL_GetError()); + } + } + } + break; + } + case 0x08: + { + // Normal Mode / Extended + logitech_g27_log.error("Normal mode restore command ignored"); + break; + } + case 0x09: + { + // Set LED + if (led_joystick_handle == nullptr) { - // Set dead band - logitech_g27_log.error("Set dead band command ignored"); break; } - default: + + uint8_t new_led_level = 0; + for (int i = 0; i < 8; i++) { - logitech_g27_log.error("Unknown command %02x %02x %02x %02x %02x %02x %02x ignored", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + new_led_level += (buf[1] & (1 << i)) ? 1 : 0; } + uint8_t intensity = new_led_level * 255 / 7; + SDL_SetJoystickLED(led_joystick_handle, intensity, intensity, intensity); + break; + } + case 0x0a: + { + // Set watchdog + logitech_g27_log.error("Watchdog command with duration of %u loops ignored", buf[1]); + break; + } + case 0x0b: + { + // Raw mode + logitech_g27_log.error("Raw mode command ignored"); + break; + } + case 0x0d: + { + // Fixed time loop toggle + fixed_loop = buf[1] ? true : false; + if (!fixed_loop) + { + logitech_g27_log.error("as fast as possible mode requested, effect durations might be inaccurate"); + } + break; + } + case 0x0f: + { + // Set dead band + logitech_g27_log.error("Set dead band command ignored"); + break; + } + default: + { + logitech_g27_log.error("Unknown command %02x %02x %02x %02x %02x %02x %02x ignored", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); + } } } sdl_handles_mutex.unlock(); diff --git a/rpcs3/Emu/Io/LogitechG27.h b/rpcs3/Emu/Io/LogitechG27.h index 0dafa68f4f..d1c5f294bd 100644 --- a/rpcs3/Emu/Io/LogitechG27.h +++ b/rpcs3/Emu/Io/LogitechG27.h @@ -116,8 +116,9 @@ public: std::mutex thread_control_mutex; bool stop_thread; char thread_name[64]; - SDL_Thread *thread = nullptr; + SDL_Thread* thread = nullptr; void sdl_refresh(); + private: u32 m_controller_index; @@ -125,9 +126,9 @@ private: bool reverse_effects; std::mutex sdl_handles_mutex; - SDL_Joystick *led_joystick_handle = nullptr; - SDL_Haptic *haptic_handle = nullptr; - std::map> joysticks; + SDL_Joystick* led_joystick_handle = nullptr; + SDL_Haptic* haptic_handle = nullptr; + std::map> joysticks; bool fixed_loop = false; uint16_t wheel_range = 200; logitech_g27_ffb_slot effect_slots[4]; diff --git a/rpcs3/Emu/Io/LogitechG27Config.cpp b/rpcs3/Emu/Io/LogitechG27Config.cpp index 78563f373b..5934847faf 100644 --- a/rpcs3/Emu/Io/LogitechG27Config.cpp +++ b/rpcs3/Emu/Io/LogitechG27Config.cpp @@ -10,17 +10,18 @@ emulated_logitech_g27_config g_cfg_logitech_g27; LOG_CHANNEL(cfg_log, "CFG"); -void emulated_logitech_g27_config::fill_defaults(){ +void emulated_logitech_g27_config::fill_defaults() +{ // a shifter-less g29 with a xbox 360 controller shifter place holder... m_mutex.lock(); - #define INIT_AXIS_MAPPING(name, device_type_id, id, reverse) \ - { \ - name##_device_type_id.set(device_type_id); \ - name##_type.set(MAPPING_AXIS); \ - name##_id.set(id); \ - name##_hat.set(HAT_NONE); \ - name##_reverse.set(reverse); \ +#define INIT_AXIS_MAPPING(name, device_type_id, id, reverse) \ + { \ + name##_device_type_id.set(device_type_id); \ + name##_type.set(MAPPING_AXIS); \ + name##_id.set(id); \ + name##_hat.set(HAT_NONE); \ + name##_reverse.set(reverse); \ } INIT_AXIS_MAPPING(steering, 0x046dc24f, 0, false); @@ -28,15 +29,15 @@ void emulated_logitech_g27_config::fill_defaults(){ INIT_AXIS_MAPPING(brake, 0x046dc24f, 3, false); INIT_AXIS_MAPPING(clutch, 0x046dc24f, 1, false); - #undef INIT_AXIS_MAPPING +#undef INIT_AXIS_MAPPING - #define INIT_BUTTON_MAPPING(name, device_type_id, id, reverse) \ - { \ - name##_device_type_id.set(device_type_id); \ - name##_type.set(MAPPING_BUTTON); \ - name##_id.set(id); \ - name##_hat.set(HAT_NONE); \ - name##_reverse.set(reverse); \ +#define INIT_BUTTON_MAPPING(name, device_type_id, id, reverse) \ + { \ + name##_device_type_id.set(device_type_id); \ + name##_type.set(MAPPING_BUTTON); \ + name##_id.set(id); \ + name##_hat.set(HAT_NONE); \ + name##_reverse.set(reverse); \ } INIT_BUTTON_MAPPING(shift_up, 0x046dc24f, 4, false); @@ -66,15 +67,15 @@ void emulated_logitech_g27_config::fill_defaults(){ INIT_BUTTON_MAPPING(shifter_3, 0x045e028e, 2, false); INIT_BUTTON_MAPPING(shifter_4, 0x045e028e, 1, false); - #undef INIT_BUTTON_MAPPING +#undef INIT_BUTTON_MAPPING - #define INIT_HAT_MAPPING(name, device_type_id, id, hat, reverse) \ - { \ - name##_device_type_id.set(device_type_id); \ - name##_type.set(MAPPING_HAT); \ - name##_id.set(id); \ - name##_hat.set(hat); \ - name##_reverse.set(reverse); \ +#define INIT_HAT_MAPPING(name, device_type_id, id, hat, reverse) \ + { \ + name##_device_type_id.set(device_type_id); \ + name##_type.set(MAPPING_HAT); \ + name##_id.set(id); \ + name##_hat.set(hat); \ + name##_reverse.set(reverse); \ } INIT_HAT_MAPPING(up, 0x046dc24f, 0, HAT_UP, false); @@ -86,7 +87,7 @@ void emulated_logitech_g27_config::fill_defaults(){ INIT_HAT_MAPPING(shifter_6, 0x045e028e, 0, HAT_DOWN, false); INIT_HAT_MAPPING(shifter_r, 0x045e028e, 0, HAT_LEFT, false); - #undef INIT_HAT_MAPPING +#undef INIT_HAT_MAPPING reverse_effects.set(true); ffb_device_type_id.set(0x046dc24f); @@ -97,7 +98,8 @@ void emulated_logitech_g27_config::fill_defaults(){ m_mutex.unlock(); } -void emulated_logitech_g27_config::save(){ +void emulated_logitech_g27_config::save() +{ m_mutex.lock(); const std::string cfg_name = fmt::format("%s%s.yml", fs::get_config_dir(true), "LogitechG27"); cfg_log.notice("Saving LogitechG27 config: %s", cfg_name); @@ -112,7 +114,6 @@ void emulated_logitech_g27_config::save(){ cfg_log.error("Failed to save LogitechG27 config to '%s' (error=%s)", cfg_name, fs::g_tls_error); } m_mutex.unlock(); - } bool emulated_logitech_g27_config::load() @@ -125,7 +126,7 @@ bool emulated_logitech_g27_config::load() m_mutex.lock(); - if (fs::file cfg_file{ cfg_name, fs::read }) + if (fs::file cfg_file{cfg_name, fs::read}) { if (const std::string content = cfg_file.to_string(); !content.empty()) { diff --git a/rpcs3/Emu/Io/LogitechG27Config.h b/rpcs3/Emu/Io/LogitechG27Config.h index 7e93e62ba2..b727cc9d68 100644 --- a/rpcs3/Emu/Io/LogitechG27Config.h +++ b/rpcs3/Emu/Io/LogitechG27Config.h @@ -4,19 +4,20 @@ #include -struct emulated_logitech_g27_config : cfg::node { +struct emulated_logitech_g27_config : cfg::node +{ std::mutex m_mutex; bool load(); void save(); void fill_defaults(); - #define STR(s) #s - #define MAPPING_ENTRY(name) \ - cfg::uint<0, 0xFFFFFFFF> name##_device_type_id{this, STR(name##_device_type_id)}; \ - cfg::uint<0, 0xFFFFFFFF> name##_type{this, STR(name##_type)}; \ - cfg::uint<0, 0xFFFFFFFFFFFFFFFF> name##_id{this, STR(name##_id)}; \ - cfg::uint<0, 0xFFFFFFFF> name##_hat{this, STR(name##_hat)}; \ - cfg::_bool name##_reverse{this, STR(name##_reverse)}; +#define STR(s) #s +#define MAPPING_ENTRY(name) \ + cfg::uint<0, 0xFFFFFFFF> name##_device_type_id{this, STR(name##_device_type_id)}; \ + cfg::uint<0, 0xFFFFFFFF> name##_type{this, STR(name##_type)}; \ + cfg::uint<0, 0xFFFFFFFFFFFFFFFF> name##_id{this, STR(name##_id)}; \ + cfg::uint<0, 0xFFFFFFFF> name##_hat{this, STR(name##_hat)}; \ + cfg::_bool name##_reverse{this, STR(name##_reverse)}; MAPPING_ENTRY(steering); MAPPING_ENTRY(throttle); @@ -57,8 +58,8 @@ struct emulated_logitech_g27_config : cfg::node { MAPPING_ENTRY(shifter_6); MAPPING_ENTRY(shifter_r); - #undef MAPPING_ENTRY - #undef STR +#undef MAPPING_ENTRY +#undef STR cfg::_bool reverse_effects{this, "reverse_effects"}; cfg::uint<0, 0xFFFFFFFF> ffb_device_type_id{this, "ffb_device_type_id"}; diff --git a/rpcs3/Input/sdl_instance.cpp b/rpcs3/Input/sdl_instance.cpp index 92f91d3195..1491d0a472 100644 --- a/rpcs3/Input/sdl_instance.cpp +++ b/rpcs3/Input/sdl_instance.cpp @@ -22,7 +22,7 @@ sdl_instance::~sdl_instance() sdl_instance& sdl_instance::get_instance() { - static sdl_instance instance {}; + static sdl_instance instance{}; return instance; } @@ -61,64 +61,65 @@ bool sdl_instance::initialize() SDL_SetLogPriorities(SDL_LOG_PRIORITY_VERBOSE); SDL_SetLogOutputFunction([](void*, int category, SDL_LogPriority priority, const char* message) - { - std::string category_name; - switch (category) { - case SDL_LOG_CATEGORY_APPLICATION: - category_name = "app"; - break; - case SDL_LOG_CATEGORY_ERROR: - category_name = "error"; - break; - case SDL_LOG_CATEGORY_ASSERT: - category_name = "assert"; - break; - case SDL_LOG_CATEGORY_SYSTEM: - category_name = "system"; - break; - case SDL_LOG_CATEGORY_AUDIO: - category_name = "audio"; - break; - case SDL_LOG_CATEGORY_VIDEO: - category_name = "video"; - break; - case SDL_LOG_CATEGORY_RENDER: - category_name = "render"; - break; - case SDL_LOG_CATEGORY_INPUT: - category_name = "input"; - break; - case SDL_LOG_CATEGORY_TEST: - category_name = "test"; - break; - default: - category_name = fmt::format("unknown(%d)", category); - break; - } + std::string category_name; + switch (category) + { + case SDL_LOG_CATEGORY_APPLICATION: + category_name = "app"; + break; + case SDL_LOG_CATEGORY_ERROR: + category_name = "error"; + break; + case SDL_LOG_CATEGORY_ASSERT: + category_name = "assert"; + break; + case SDL_LOG_CATEGORY_SYSTEM: + category_name = "system"; + break; + case SDL_LOG_CATEGORY_AUDIO: + category_name = "audio"; + break; + case SDL_LOG_CATEGORY_VIDEO: + category_name = "video"; + break; + case SDL_LOG_CATEGORY_RENDER: + category_name = "render"; + break; + case SDL_LOG_CATEGORY_INPUT: + category_name = "input"; + break; + case SDL_LOG_CATEGORY_TEST: + category_name = "test"; + break; + default: + category_name = fmt::format("unknown(%d)", category); + break; + } - switch (priority) - { - case SDL_LOG_PRIORITY_VERBOSE: - case SDL_LOG_PRIORITY_DEBUG: - sdl_log.trace("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_INFO: - sdl_log.notice("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_WARN: - sdl_log.warning("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_ERROR: - sdl_log.error("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_CRITICAL: - sdl_log.error("%s: %s", category_name, message); - break; - default: - break; - } - }, nullptr); + switch (priority) + { + case SDL_LOG_PRIORITY_VERBOSE: + case SDL_LOG_PRIORITY_DEBUG: + sdl_log.trace("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_INFO: + sdl_log.notice("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_WARN: + sdl_log.warning("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_ERROR: + sdl_log.error("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_CRITICAL: + sdl_log.error("%s: %s", category_name, message); + break; + default: + break; + } + }, + nullptr); m_initialized = true; instance_mutex.unlock(); diff --git a/rpcs3/Input/sdl_instance.h b/rpcs3/Input/sdl_instance.h index d74d872745..788e9e3858 100644 --- a/rpcs3/Input/sdl_instance.h +++ b/rpcs3/Input/sdl_instance.h @@ -12,6 +12,7 @@ public: bool initialize(); void pump_events(); + private: bool m_initialized = false; std::mutex instance_mutex; diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt index f6ba8c608f..c49daf0346 100644 --- a/rpcs3/rpcs3qt/CMakeLists.txt +++ b/rpcs3/rpcs3qt/CMakeLists.txt @@ -22,7 +22,7 @@ add_library(rpcs3_ui STATIC emu_settings.cpp elf_memory_dumping_dialog.cpp emulated_pad_settings_dialog.cpp - emulated_logitech_g27_settings_dialog.cpp + emulated_logitech_g27_settings_dialog.cpp fatal_error_dialog.cpp find_dialog.cpp flow_layout.cpp diff --git a/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.cpp b/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.cpp index 543dc961b1..2cad2b0f18 100644 --- a/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.cpp @@ -20,7 +20,8 @@ LOG_CHANNEL(logitech_g27_cfg_log, "LOGIG27"); #define DEFAULT_STATUS " " -struct joystick_state { +struct joystick_state +{ std::vector axes; std::vector buttons; std::vector hats; @@ -30,14 +31,14 @@ class DeviceChoice : public QWidget { public: - DeviceChoice(QWidget *parent, uint32_t device_type_id, const char *name) + DeviceChoice(QWidget* parent, uint32_t device_type_id, const char* name) : QWidget(parent) { this->device_type_id = device_type_id; auto layout = new QHBoxLayout(this); - QLabel *label = new QLabel(this); + QLabel* label = new QLabel(this); label->setText(QString(name)); layout->addWidget(label); @@ -64,8 +65,9 @@ public: private: uint32_t device_type_id; - QLabel *display_box; - void update_display(){ + QLabel* display_box; + void update_display() + { char text_buf[32]; sprintf(text_buf, "%04x:%04x", device_type_id >> 16, device_type_id & 0xFFFF); display_box->setText(QString(text_buf)); @@ -76,7 +78,7 @@ class Mapping : public QGroupBox { public: - Mapping(QWidget *parent, emulated_logitech_g27_settings_dialog *dialog, DeviceChoice *ffb_device, DeviceChoice *led_device, sdl_mapping mapping, bool is_axis, const char *name, bool flip_axis_display) + Mapping(QWidget* parent, emulated_logitech_g27_settings_dialog* dialog, DeviceChoice* ffb_device, DeviceChoice* led_device, sdl_mapping mapping, bool is_axis, const char* name, bool flip_axis_display) : QGroupBox(parent) { this->setting_dialog = dialog; @@ -88,16 +90,16 @@ public: this->mapping_in_progress = false; this->flip_axis_display = flip_axis_display; - QVBoxLayout *layout = new QVBoxLayout(this); + QVBoxLayout* layout = new QVBoxLayout(this); setLayout(layout); - QWidget *horizontal_container = new QWidget(this); - QHBoxLayout *horizontal_layout = new QHBoxLayout(horizontal_container); + QWidget* horizontal_container = new QWidget(this); + QHBoxLayout* horizontal_layout = new QHBoxLayout(horizontal_container); horizontal_container->setLayout(horizontal_layout); layout->addWidget(horizontal_container); - QLabel *label = new QLabel(horizontal_container); + QLabel* label = new QLabel(horizontal_container); label->setText(QString(name)); display_box = new QLabel(horizontal_container); @@ -144,131 +146,134 @@ public: layout->addWidget(axis_status); connect(ffb_set_button, &QPushButton::clicked, this, [this]() - { - this->ffb_device->set_device_type_id(this->mapping.device_type_id); - }); + { + this->ffb_device->set_device_type_id(this->mapping.device_type_id); + }); connect(led_set_button, &QPushButton::clicked, this, [this]() - { - this->led_device->set_device_type_id(this->mapping.device_type_id); - }); + { + this->led_device->set_device_type_id(this->mapping.device_type_id); + }); - connect(map_button, &QPushButton::clicked, this, [this](){ - this->mapping_in_progress = true; - this->timeout_msec = 5500; - this->setting_dialog->disable(); - this->last_joystick_states = this->setting_dialog->get_joystick_states(); - }); + connect(map_button, &QPushButton::clicked, this, [this]() + { + this->mapping_in_progress = true; + this->timeout_msec = 5500; + this->setting_dialog->disable(); + this->last_joystick_states = this->setting_dialog->get_joystick_states(); + }); - connect(unmap_button, &QPushButton::clicked, this, [this](){ - this->mapping.device_type_id = 0; - update_display(); - }); + connect(unmap_button, &QPushButton::clicked, this, [this]() + { + this->mapping.device_type_id = 0; + update_display(); + }); - connect(reverse_checkbox, &QCheckBox::clicked, this, [this](){ - this->mapping.reverse = this->reverse_checkbox->isChecked(); - }); + connect(reverse_checkbox, &QCheckBox::clicked, this, [this]() + { + this->mapping.reverse = this->reverse_checkbox->isChecked(); + }); tick_timer = new QTimer(this); connect(tick_timer, &QTimer::timeout, this, [this]() - { - if (this->mapping_in_progress) { - char text_buf[128]; - - int timeout_sec = this->timeout_msec / 1000; - - const std::map &new_joystick_states = this->setting_dialog->get_joystick_states(); - - sprintf(text_buf, "Input %s for %s, timeout in %d %s", this->is_axis ? "axis" : "button/hat", this->name.c_str(), timeout_sec, timeout_sec >= 2 ? "seconds" : "second"); - this->setting_dialog->set_state_text(text_buf); - - for (auto new_joystick_state = new_joystick_states.begin();new_joystick_state != new_joystick_states.end();new_joystick_state++) + if (this->mapping_in_progress) { - auto last_joystick_state = this->last_joystick_states.find(new_joystick_state->first); - if (last_joystick_state == this->last_joystick_states.end()) + char text_buf[128]; + + int timeout_sec = this->timeout_msec / 1000; + + const std::map& new_joystick_states = this->setting_dialog->get_joystick_states(); + + sprintf(text_buf, "Input %s for %s, timeout in %d %s", this->is_axis ? "axis" : "button/hat", this->name.c_str(), timeout_sec, timeout_sec >= 2 ? "seconds" : "second"); + this->setting_dialog->set_state_text(text_buf); + + for (auto new_joystick_state = new_joystick_states.begin(); new_joystick_state != new_joystick_states.end(); new_joystick_state++) { - continue; + auto last_joystick_state = this->last_joystick_states.find(new_joystick_state->first); + if (last_joystick_state == this->last_joystick_states.end()) + { + continue; + } + + if (this->is_axis) + { + const static int16_t axis_change_threshold = 0x7FFF / 5; + if (last_joystick_state->second.axes.size() != new_joystick_state->second.axes.size()) + { + logitech_g27_cfg_log.error("during input state change diff, number of axes on %04x:%04x changed", new_joystick_state->first >> 16, new_joystick_state->first & 0xFFFF); + continue; + } + for (std::vector::size_type i = 0; i < new_joystick_state->second.axes.size(); i++) + { + int32_t diff = std::abs(last_joystick_state->second.axes[i] - new_joystick_state->second.axes[i]); + if (diff > axis_change_threshold) + { + this->mapping_in_progress = false; + this->setting_dialog->set_state_text(DEFAULT_STATUS); + this->setting_dialog->enable(); + this->mapping.device_type_id = new_joystick_state->first; + this->mapping.type = MAPPING_AXIS; + this->mapping.id = i; + this->mapping.hat = HAT_NONE; + break; + } + } + } + else + { + if (last_joystick_state->second.buttons.size() != new_joystick_state->second.buttons.size()) + { + logitech_g27_cfg_log.error("during input state change diff, number of buttons on %04x:%04x changed", new_joystick_state->first >> 16, new_joystick_state->first & 0xFFFF); + continue; + } + if (last_joystick_state->second.hats.size() != new_joystick_state->second.hats.size()) + { + logitech_g27_cfg_log.error("during input state change diff, number of hats on %04x:%04x changed", new_joystick_state->first >> 16, new_joystick_state->first & 0xFFFF); + continue; + } + for (std::vector::size_type i = 0; i < new_joystick_state->second.buttons.size(); i++) + { + if (last_joystick_state->second.buttons[i] != new_joystick_state->second.buttons[i]) + { + this->mapping_in_progress = false; + this->setting_dialog->set_state_text(DEFAULT_STATUS); + this->setting_dialog->enable(); + this->mapping.device_type_id = new_joystick_state->first; + this->mapping.type = MAPPING_BUTTON; + this->mapping.id = i; + this->mapping.hat = HAT_NONE; + break; + } + } + for (std::vector::size_type i = 0; i < new_joystick_state->second.hats.size(); i++) + { + if (last_joystick_state->second.hats[i] != new_joystick_state->second.hats[i] && new_joystick_state->second.hats[i] != HAT_NONE) + { + this->mapping_in_progress = false; + this->setting_dialog->set_state_text(DEFAULT_STATUS); + this->setting_dialog->enable(); + this->mapping.device_type_id = new_joystick_state->first; + this->mapping.type = MAPPING_HAT; + this->mapping.id = i; + this->mapping.hat = new_joystick_state->second.hats[i]; + break; + } + } + } } - if (this->is_axis) + this->timeout_msec = this->timeout_msec - 25; + if (this->timeout_msec <= 0) { - const static int16_t axis_change_threshold = 0x7FFF / 5; - if (last_joystick_state->second.axes.size() != new_joystick_state->second.axes.size()) - { - logitech_g27_cfg_log.error("during input state change diff, number of axes on %04x:%04x changed", new_joystick_state->first >> 16, new_joystick_state->first & 0xFFFF); - continue; - } - for (std::vector::size_type i = 0;i < new_joystick_state->second.axes.size();i++) - { - int32_t diff = std::abs(last_joystick_state->second.axes[i] - new_joystick_state->second.axes[i]); - if (diff > axis_change_threshold) - { - this->mapping_in_progress = false; - this->setting_dialog->set_state_text(DEFAULT_STATUS); - this->setting_dialog->enable(); - this->mapping.device_type_id = new_joystick_state->first; - this->mapping.type = MAPPING_AXIS; - this->mapping.id = i; - this->mapping.hat = HAT_NONE; - break; - } - } - } - else - { - if (last_joystick_state->second.buttons.size() != new_joystick_state->second.buttons.size()) - { - logitech_g27_cfg_log.error("during input state change diff, number of buttons on %04x:%04x changed", new_joystick_state->first >> 16, new_joystick_state->first & 0xFFFF); - continue; - } - if (last_joystick_state->second.hats.size() != new_joystick_state->second.hats.size()) - { - logitech_g27_cfg_log.error("during input state change diff, number of hats on %04x:%04x changed", new_joystick_state->first >> 16, new_joystick_state->first & 0xFFFF); - continue; - } - for (std::vector::size_type i = 0;i < new_joystick_state->second.buttons.size();i++) - { - if (last_joystick_state->second.buttons[i] != new_joystick_state->second.buttons[i]) - { - this->mapping_in_progress = false; - this->setting_dialog->set_state_text(DEFAULT_STATUS); - this->setting_dialog->enable(); - this->mapping.device_type_id = new_joystick_state->first; - this->mapping.type = MAPPING_BUTTON; - this->mapping.id = i; - this->mapping.hat = HAT_NONE; - break; - } - } - for (std::vector::size_type i = 0;i < new_joystick_state->second.hats.size();i++) - { - if (last_joystick_state->second.hats[i] != new_joystick_state->second.hats[i] && new_joystick_state->second.hats[i] != HAT_NONE) - { - this->mapping_in_progress = false; - this->setting_dialog->set_state_text(DEFAULT_STATUS); - this->setting_dialog->enable(); - this->mapping.device_type_id = new_joystick_state->first; - this->mapping.type = MAPPING_HAT; - this->mapping.id = i; - this->mapping.hat = new_joystick_state->second.hats[i]; - break; - } - } + this->mapping_in_progress = false; + this->setting_dialog->set_state_text(DEFAULT_STATUS); + this->setting_dialog->enable(); } } - this->timeout_msec = this->timeout_msec - 25; - if (this->timeout_msec <= 0) - { - this->mapping_in_progress = false; - this->setting_dialog->set_state_text(DEFAULT_STATUS); - this->setting_dialog->enable(); - } - } - - update_display(); - }); + update_display(); + }); tick_timer->start(25); } @@ -290,13 +295,13 @@ public: reverse_checkbox->setEnabled(true); } - void set_mapping(const sdl_mapping &mapping) + void set_mapping(const sdl_mapping& mapping) { this->mapping = mapping; update_display(); } - const sdl_mapping &get_mapping() + const sdl_mapping& get_mapping() { return mapping; } @@ -306,59 +311,60 @@ private: bool is_axis; std::string name; - DeviceChoice *ffb_device; - DeviceChoice *led_device; - QLabel *display_box; - QPushButton *ffb_set_button; - QPushButton *led_set_button; - QPushButton *map_button; - QPushButton *unmap_button; - QCheckBox *reverse_checkbox; + DeviceChoice* ffb_device; + DeviceChoice* led_device; + QLabel* display_box; + QPushButton* ffb_set_button; + QPushButton* led_set_button; + QPushButton* map_button; + QPushButton* unmap_button; + QCheckBox* reverse_checkbox; bool mapping_in_progress; int timeout_msec = 5000; - QTimer *tick_timer; + QTimer* tick_timer; std::map last_joystick_states; - QCheckBox *button_status; - QSlider *axis_status; + QCheckBox* button_status; + QSlider* axis_status; bool flip_axis_display; - emulated_logitech_g27_settings_dialog *setting_dialog; + emulated_logitech_g27_settings_dialog* setting_dialog; - void update_display(){ + void update_display() + { char text_buf[64]; - const char *type_string = nullptr; - switch(mapping.type) + const char* type_string = nullptr; + switch (mapping.type) { - case MAPPING_BUTTON: - type_string = "button"; - break; - case MAPPING_HAT: - type_string = "hat"; - break; - case MAPPING_AXIS: - type_string = "axis"; - break; + case MAPPING_BUTTON: + type_string = "button"; + break; + case MAPPING_HAT: + type_string = "hat"; + break; + case MAPPING_AXIS: + type_string = "axis"; + break; } - const char *hat_string = nullptr; - switch(mapping.hat) + const char* hat_string = nullptr; + switch (mapping.hat) { - case HAT_UP: - hat_string = "up"; - break; - case HAT_DOWN: - hat_string = "down"; - break; - case HAT_LEFT: - hat_string = "left"; - break; - case HAT_RIGHT: - hat_string = "right"; - break; - case HAT_NONE: - hat_string = ""; - break; + case HAT_UP: + hat_string = "up"; + break; + case HAT_DOWN: + hat_string = "down"; + break; + case HAT_LEFT: + hat_string = "left"; + break; + case HAT_RIGHT: + hat_string = "right"; + break; + case HAT_NONE: + hat_string = ""; + break; } sprintf(text_buf, "%04x:%04x, %s %u %s", mapping.device_type_id >> 16, mapping.device_type_id & 0xFFFF, type_string, mapping.id, hat_string); display_box->setText(QString(text_buf)); @@ -382,49 +388,49 @@ private: axis_status->setValue(axis_value); } - const std::map &joystick_states = setting_dialog->get_joystick_states(); + const std::map& joystick_states = setting_dialog->get_joystick_states(); auto joystick_state = joystick_states.find(mapping.device_type_id); if (joystick_state != joystick_states.end()) { - switch(mapping.type) + switch (mapping.type) { - case MAPPING_BUTTON: - { - if (joystick_state->second.buttons.size() <= mapping.id) - break; - bool value = joystick_state->second.buttons[mapping.id]; - if (mapping.reverse) - value = !value; - button_status->setChecked(value); + case MAPPING_BUTTON: + { + if (joystick_state->second.buttons.size() <= mapping.id) break; - } - case MAPPING_HAT: - { - if (joystick_state->second.hats.size() <= mapping.id) - break; - bool value = joystick_state->second.hats[mapping.id] == mapping.hat; - if (mapping.reverse) - value = !value; - button_status->setChecked(value); + bool value = joystick_state->second.buttons[mapping.id]; + if (mapping.reverse) + value = !value; + button_status->setChecked(value); + break; + } + case MAPPING_HAT: + { + if (joystick_state->second.hats.size() <= mapping.id) break; - } - case MAPPING_AXIS: - { - if (joystick_state->second.axes.size() <= mapping.id) - break; - int32_t value = joystick_state->second.axes[mapping.id]; - if (mapping.reverse) - value = value * (-1); - if (flip_axis_display) - value = value * (-1); - if (value > 0x7FFF) - value = 0x7FFF; - else if (value < (-0x8000)) - value = (-0x8000); - axis_status->setValue(value); + bool value = joystick_state->second.hats[mapping.id] == mapping.hat; + if (mapping.reverse) + value = !value; + button_status->setChecked(value); + break; + } + case MAPPING_AXIS: + { + if (joystick_state->second.axes.size() <= mapping.id) break; - } + int32_t value = joystick_state->second.axes[mapping.id]; + if (mapping.reverse) + value = value * (-1); + if (flip_axis_display) + value = value * (-1); + if (value > 0x7FFF) + value = 0x7FFF; + else if (value < (-0x8000)) + value = (-0x8000); + axis_status->setValue(value); + break; + } } } } @@ -432,14 +438,14 @@ private: void emulated_logitech_g27_settings_dialog::save_ui_state_to_config() { - #define SAVE_MAPPING(name) \ - { \ - const sdl_mapping &m = name->get_mapping(); \ +#define SAVE_MAPPING(name) \ + { \ + const sdl_mapping& m = name->get_mapping(); \ g_cfg_logitech_g27.name##_device_type_id.set(m.device_type_id); \ - g_cfg_logitech_g27.name##_type.set(m.type); \ - g_cfg_logitech_g27.name##_id.set(m.id); \ - g_cfg_logitech_g27.name##_hat.set(m.hat); \ - g_cfg_logitech_g27.name##_reverse.set(m.reverse); \ + g_cfg_logitech_g27.name##_type.set(m.type); \ + g_cfg_logitech_g27.name##_id.set(m.id); \ + g_cfg_logitech_g27.name##_hat.set(m.hat); \ + g_cfg_logitech_g27.name##_reverse.set(m.reverse); \ } SAVE_MAPPING(steering); @@ -481,7 +487,7 @@ void emulated_logitech_g27_settings_dialog::save_ui_state_to_config() SAVE_MAPPING(shifter_6); SAVE_MAPPING(shifter_r); - #undef SAVE_MAPPING +#undef SAVE_MAPPING g_cfg_logitech_g27.ffb_device_type_id.set(ffb_device->get_device_type_id()); g_cfg_logitech_g27.led_device_type_id.set(led_device->get_device_type_id()); @@ -492,17 +498,16 @@ void emulated_logitech_g27_settings_dialog::save_ui_state_to_config() void emulated_logitech_g27_settings_dialog::load_ui_state_from_config() { - #define LOAD_MAPPING(name) \ - { \ - sdl_mapping m = { \ +#define LOAD_MAPPING(name) \ + { \ + sdl_mapping m = { \ .device_type_id = static_cast(g_cfg_logitech_g27.name##_device_type_id.get()), \ - .type = static_cast(g_cfg_logitech_g27.name##_type.get()), \ - .id = static_cast(g_cfg_logitech_g27.name##_id.get()), \ - .hat = static_cast(g_cfg_logitech_g27.name##_hat.get()), \ - .reverse = g_cfg_logitech_g27.name##_reverse.get(), \ - .positive_axis = false \ - }; \ - name->set_mapping(m); \ + .type = static_cast(g_cfg_logitech_g27.name##_type.get()), \ + .id = static_cast(g_cfg_logitech_g27.name##_id.get()), \ + .hat = static_cast(g_cfg_logitech_g27.name##_hat.get()), \ + .reverse = g_cfg_logitech_g27.name##_reverse.get(), \ + .positive_axis = false}; \ + name->set_mapping(m); \ } LOAD_MAPPING(steering); @@ -544,7 +549,7 @@ void emulated_logitech_g27_settings_dialog::load_ui_state_from_config() LOAD_MAPPING(shifter_6); LOAD_MAPPING(shifter_r); - #undef LOAD_MAPPING +#undef LOAD_MAPPING ffb_device->set_device_type_id(static_cast(g_cfg_logitech_g27.ffb_device_type_id.get())); led_device->set_device_type_id(static_cast(g_cfg_logitech_g27.led_device_type_id.get())); @@ -570,34 +575,34 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi g_cfg_logitech_g27.load(); connect(buttons, &QDialogButtonBox::clicked, this, [this, buttons](QAbstractButton* button) - { - if (button == buttons->button(QDialogButtonBox::Apply)) { - save_ui_state_to_config(); - g_cfg_logitech_g27.save(); - load_ui_state_from_config(); - } - else if (button == buttons->button(QDialogButtonBox::Save)) - { - save_ui_state_to_config(); - g_cfg_logitech_g27.save(); - accept(); - } - else if (button == buttons->button(QDialogButtonBox::RestoreDefaults)) - { - if (QMessageBox::question(this, tr("Confirm Reset"), tr("Reset all?")) != QMessageBox::Yes) - return; - g_cfg_logitech_g27.fill_defaults(); - load_ui_state_from_config(); - g_cfg_logitech_g27.save(); - } - else if (button == buttons->button(QDialogButtonBox::Cancel)) - { - reject(); - } - }); + if (button == buttons->button(QDialogButtonBox::Apply)) + { + save_ui_state_to_config(); + g_cfg_logitech_g27.save(); + load_ui_state_from_config(); + } + else if (button == buttons->button(QDialogButtonBox::Save)) + { + save_ui_state_to_config(); + g_cfg_logitech_g27.save(); + accept(); + } + else if (button == buttons->button(QDialogButtonBox::RestoreDefaults)) + { + if (QMessageBox::question(this, tr("Confirm Reset"), tr("Reset all?")) != QMessageBox::Yes) + return; + g_cfg_logitech_g27.fill_defaults(); + load_ui_state_from_config(); + g_cfg_logitech_g27.save(); + } + else if (button == buttons->button(QDialogButtonBox::Cancel)) + { + reject(); + } + }); - QLabel *warning = new QLabel(QString("Warning: Force feedback output were meant for Logitech G27, on stronger wheels please adjust force strength accordingly in your wheel software."), this); + QLabel* warning = new QLabel(QString("Warning: Force feedback output were meant for Logitech G27, on stronger wheels please adjust force strength accordingly in your wheel software."), this); warning->setStyleSheet("color: red;"); v_layout->addWidget(warning); @@ -616,7 +621,7 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi led_device = new DeviceChoice(this, g_cfg_logitech_g27.led_device_type_id.get(), "LED Device"); mapping_scroll_area = new QScrollArea(this); - QWidget *mapping_widget = new QWidget(mapping_scroll_area); + QWidget* mapping_widget = new QWidget(mapping_scroll_area); QVBoxLayout* mapping_layout = new QVBoxLayout(mapping_widget); mapping_widget->setLayout(mapping_layout); mapping_scroll_area->setWidget(mapping_widget); @@ -627,21 +632,20 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi v_layout->addWidget(mapping_scroll_area); - #define ADD_MAPPING_SETTING(name, is_axis, display_name, flip_axis_display) \ - { \ - sdl_mapping m = { \ - .device_type_id = static_cast(g_cfg_logitech_g27.name##_device_type_id.get()), \ - .type = static_cast(g_cfg_logitech_g27.name##_type.get()), \ - .id = static_cast(g_cfg_logitech_g27.name##_id.get()), \ - .hat = static_cast(g_cfg_logitech_g27.name##_hat.get()), \ - .reverse = g_cfg_logitech_g27.name##_reverse.get(), \ - .positive_axis = false \ - }; \ +#define ADD_MAPPING_SETTING(name, is_axis, display_name, flip_axis_display) \ + { \ + sdl_mapping m = { \ + .device_type_id = static_cast(g_cfg_logitech_g27.name##_device_type_id.get()), \ + .type = static_cast(g_cfg_logitech_g27.name##_type.get()), \ + .id = static_cast(g_cfg_logitech_g27.name##_id.get()), \ + .hat = static_cast(g_cfg_logitech_g27.name##_hat.get()), \ + .reverse = g_cfg_logitech_g27.name##_reverse.get(), \ + .positive_axis = false}; \ name = new Mapping(mapping_widget, this, ffb_device, led_device, m, is_axis, display_name, flip_axis_display); \ - mapping_layout->addWidget(name); \ + mapping_layout->addWidget(name); \ } - QLabel *axis_label = new QLabel(QString("Axes:"), mapping_widget); + QLabel* axis_label = new QLabel(QString("Axes:"), mapping_widget); mapping_layout->addWidget(axis_label); ADD_MAPPING_SETTING(steering, true, "Steering", false); @@ -649,7 +653,7 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi ADD_MAPPING_SETTING(brake, true, "Brake", true); ADD_MAPPING_SETTING(clutch, true, "Clutch", true); - QLabel *button_label = new QLabel(QString("Buttons:"), mapping_widget); + QLabel* button_label = new QLabel(QString("Buttons:"), mapping_widget); mapping_layout->addWidget(button_label); ADD_MAPPING_SETTING(shift_up, false, "Shift up", false); @@ -687,7 +691,7 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi ADD_MAPPING_SETTING(shifter_6, false, "Gear 6", false); ADD_MAPPING_SETTING(shifter_r, false, "Gear R", false); - #undef ADD_MAPPING_SETTING +#undef ADD_MAPPING_SETTING v_layout->addWidget(ffb_device); v_layout->addWidget(led_device); @@ -703,7 +707,7 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi emulated_logitech_g27_settings_dialog::~emulated_logitech_g27_settings_dialog() { - for (auto joystick_handle = joystick_handles.begin();joystick_handle != joystick_handles.end();joystick_handle++) + for (auto joystick_handle = joystick_handles.begin(); joystick_handle != joystick_handles.end(); joystick_handle++) { SDL_CloseJoystick(*joystick_handle); } @@ -734,7 +738,7 @@ static inline hat_component get_sdl_hat_component(uint8_t sdl_hat) return HAT_NONE; } -const std::map &emulated_logitech_g27_settings_dialog::get_joystick_states() +const std::map& emulated_logitech_g27_settings_dialog::get_joystick_states() { if (!sdl_initialized) { @@ -755,15 +759,15 @@ const std::map &emulated_logitech_g27_settings_dialog: sdl_instance::get_instance().pump_events(); int joystick_count; - SDL_JoystickID *joystick_ids = SDL_GetJoysticks(&joystick_count); + SDL_JoystickID* joystick_ids = SDL_GetJoysticks(&joystick_count); - std::vector new_joystick_handles; + std::vector new_joystick_handles; if (joystick_ids != nullptr) { - for (int i = 0;i < joystick_count;i++) + for (int i = 0; i < joystick_count; i++) { - SDL_Joystick *cur_joystick = SDL_OpenJoystick(joystick_ids[i]); + SDL_Joystick* cur_joystick = SDL_OpenJoystick(joystick_ids[i]); if (cur_joystick == nullptr) { continue; @@ -779,15 +783,15 @@ const std::map &emulated_logitech_g27_settings_dialog: int num_axes = SDL_GetNumJoystickAxes(cur_joystick); int num_buttons = SDL_GetNumJoystickButtons(cur_joystick); int num_hats = SDL_GetNumJoystickHats(cur_joystick); - for (int j = 0;j < num_axes;j++) + for (int j = 0; j < num_axes; j++) { s.axes.push_back(SDL_GetJoystickAxis(cur_joystick, j)); } - for (int j = 0;j < num_buttons;j++) + for (int j = 0; j < num_buttons; j++) { s.buttons.push_back(SDL_GetJoystickButton(cur_joystick, j)); } - for (int j = 0;j < num_hats;j++) + for (int j = 0; j < num_hats; j++) { uint8_t sdl_hat = SDL_GetJoystickHat(cur_joystick, j); s.hats.push_back(get_sdl_hat_component(sdl_hat)); @@ -796,15 +800,15 @@ const std::map &emulated_logitech_g27_settings_dialog: } else { - for (std::vector::size_type j = 0;j < cur_state->second.axes.size();j++) + for (std::vector::size_type j = 0; j < cur_state->second.axes.size(); j++) { cur_state->second.axes[j] = (cur_state->second.axes[j] + SDL_GetJoystickAxis(cur_joystick, j)) / 2; } - for (std::vector::size_type j = 0;j < cur_state->second.buttons.size();j++) + for (std::vector::size_type j = 0; j < cur_state->second.buttons.size(); j++) { cur_state->second.buttons[j] = cur_state->second.buttons[j] || SDL_GetJoystickButton(cur_joystick, j); } - for (std::vector::size_type j = 0;j < cur_state->second.hats.size();j++) + for (std::vector::size_type j = 0; j < cur_state->second.hats.size(); j++) { if (cur_state->second.hats[j] != HAT_NONE) continue; @@ -815,7 +819,7 @@ const std::map &emulated_logitech_g27_settings_dialog: } } - for (auto joystick_handle = joystick_handles.begin(); joystick_handle != joystick_handles.end();joystick_handle++) + for (auto joystick_handle = joystick_handles.begin(); joystick_handle != joystick_handles.end(); joystick_handle++) { SDL_CloseJoystick(*joystick_handle); } @@ -826,7 +830,7 @@ const std::map &emulated_logitech_g27_settings_dialog: return last_joystick_states; } -void emulated_logitech_g27_settings_dialog::set_state_text(const char *text) +void emulated_logitech_g27_settings_dialog::set_state_text(const char* text) { state_text->setText(QString(text)); } @@ -836,11 +840,11 @@ void emulated_logitech_g27_settings_dialog::toggle_state(bool enable) int slider_position = mapping_scroll_area->verticalScrollBar()->sliderPosition(); - #define TOGGLE_STATE(name) \ - { \ - if (enable) \ - name->enable(); \ - else \ +#define TOGGLE_STATE(name) \ + { \ + if (enable) \ + name->enable(); \ + else \ name->disable(); \ } TOGGLE_STATE(steering); @@ -882,7 +886,7 @@ void emulated_logitech_g27_settings_dialog::toggle_state(bool enable) TOGGLE_STATE(shifter_6); TOGGLE_STATE(shifter_r); - #undef TOGGLE_STATE +#undef TOGGLE_STATE enabled->setEnabled(enable); reverse_effects->setEnabled(enable); @@ -891,11 +895,13 @@ void emulated_logitech_g27_settings_dialog::toggle_state(bool enable) mapping_scroll_area->verticalScrollBar()->setSliderPosition(slider_position); } -void emulated_logitech_g27_settings_dialog::enable(){ +void emulated_logitech_g27_settings_dialog::enable() +{ toggle_state(true); } -void emulated_logitech_g27_settings_dialog::disable(){ +void emulated_logitech_g27_settings_dialog::disable() +{ toggle_state(false); } diff --git a/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.h b/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.h index fdca83d72d..dbbadbf8b6 100644 --- a/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.h +++ b/rpcs3/rpcs3qt/emulated_logitech_g27_settings_dialog.h @@ -30,65 +30,66 @@ public: ~emulated_logitech_g27_settings_dialog(); void disable(); void enable(); - void set_state_text(const char *); - const std::map &get_joystick_states(); + void set_state_text(const char*); + const std::map& get_joystick_states(); + private: void toggle_state(bool enable); void load_ui_state_from_config(); void save_ui_state_to_config(); std::map last_joystick_states; - std::vector joystick_handles; + std::vector joystick_handles; uint64_t last_joystick_states_update = 0; bool sdl_initialized = false; // ui elements - QLabel *state_text; + QLabel* state_text; - QCheckBox *enabled; - QCheckBox *reverse_effects; + QCheckBox* enabled; + QCheckBox* reverse_effects; - Mapping *steering; - Mapping *throttle; - Mapping *brake; - Mapping *clutch; - Mapping *shift_up; - Mapping *shift_down; + Mapping* steering; + Mapping* throttle; + Mapping* brake; + Mapping* clutch; + Mapping* shift_up; + Mapping* shift_down; - Mapping *up; - Mapping *down; - Mapping *left; - Mapping *right; + Mapping* up; + Mapping* down; + Mapping* left; + Mapping* right; - Mapping *triangle; - Mapping *cross; - Mapping *square; - Mapping *circle; + Mapping* triangle; + Mapping* cross; + Mapping* square; + Mapping* circle; - Mapping *l2; - Mapping *l3; - Mapping *r2; - Mapping *r3; + Mapping* l2; + Mapping* l3; + Mapping* r2; + Mapping* r3; - Mapping *plus; - Mapping *minus; + Mapping* plus; + Mapping* minus; - Mapping *dial_clockwise; - Mapping *dial_anticlockwise; + Mapping* dial_clockwise; + Mapping* dial_anticlockwise; - Mapping *select; - Mapping *pause; + Mapping* select; + Mapping* pause; - Mapping *shifter_1; - Mapping *shifter_2; - Mapping *shifter_3; - Mapping *shifter_4; - Mapping *shifter_5; - Mapping *shifter_6; - Mapping *shifter_r; + Mapping* shifter_1; + Mapping* shifter_2; + Mapping* shifter_3; + Mapping* shifter_4; + Mapping* shifter_5; + Mapping* shifter_6; + Mapping* shifter_r; - DeviceChoice *ffb_device; - DeviceChoice *led_device; + DeviceChoice* ffb_device; + DeviceChoice* led_device; - QScrollArea *mapping_scroll_area; + QScrollArea* mapping_scroll_area; };