mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Logitech G27 Expand SDL device identification, add mapping note
Fanatec windows drivers doesn't mux a single device into a single software device. Instead they have two identical devices in terms of vendor and product id. Add a mostly stable way to tell between the two. Currently working wheels should not be affected, Fanatec users please map the wheel again.
This commit is contained in:
parent
b1b02e0425
commit
1d99968ffe
5 changed files with 232 additions and 78 deletions
|
@ -73,7 +73,7 @@ bool usb_device_logitech_g27::open_device()
|
|||
return m_enabled;
|
||||
}
|
||||
|
||||
static void clear_sdl_joysticks(std::map<u32, std::vector<SDL_Joystick*>>& joystick_map)
|
||||
static void clear_sdl_joysticks(std::map<u64, std::vector<SDL_Joystick*>>& joystick_map)
|
||||
{
|
||||
for (auto& [type, joysticks] : joystick_map)
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ 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<u32, std::vector<SDL_Joystick*>>& left, std::map<u32, std::vector<SDL_Joystick*>>& right)
|
||||
static bool sdl_joysticks_equal(std::map<u64, std::vector<SDL_Joystick*>>& left, std::map<u64, std::vector<SDL_Joystick*>>& right)
|
||||
{
|
||||
if (left.size() != right.size())
|
||||
{
|
||||
|
@ -159,6 +159,20 @@ static bool sdl_joysticks_equal(std::map<u32, std::vector<SDL_Joystick*>>& left,
|
|||
return true;
|
||||
}
|
||||
|
||||
static std::map<u64, std::vector<SDL_Joystick*>> get_sdl_joysticks_v1(std::map<u64, std::vector<SDL_Joystick*>>& v2)
|
||||
{
|
||||
std::map<u64, std::vector<SDL_Joystick*>> v1;
|
||||
|
||||
for (const auto& [v2_key, joysticks] : v2)
|
||||
{
|
||||
const u64 v1_key = v2_key & 0xFFFFFFFF;
|
||||
// this only works with wheels that worked with v1, and that's okay, Fanatec users need to re-map anyway
|
||||
v1[v1_key] = joysticks;
|
||||
}
|
||||
|
||||
return v1;
|
||||
}
|
||||
|
||||
static inline logitech_g27_sdl_mapping get_runtime_mapping()
|
||||
{
|
||||
logitech_g27_sdl_mapping mapping {};
|
||||
|
@ -225,17 +239,14 @@ void usb_device_logitech_g27::sdl_refresh()
|
|||
|
||||
m_reverse_effects = g_cfg_logitech_g27.reverse_effects.get();
|
||||
|
||||
const u32 ffb_vendor_id = g_cfg_logitech_g27.ffb_device_type_id.get() >> 16;
|
||||
const u32 ffb_product_id = g_cfg_logitech_g27.ffb_device_type_id.get() & 0xFFFF;
|
||||
|
||||
const u32 led_vendor_id = g_cfg_logitech_g27.led_device_type_id.get() >> 16;
|
||||
const u32 led_product_id = g_cfg_logitech_g27.led_device_type_id.get() & 0xFFFF;
|
||||
const u64 ffb_device_type_id = g_cfg_logitech_g27.ffb_device_type_id.get();
|
||||
const u64 led_device_type_id = g_cfg_logitech_g27.led_device_type_id.get();
|
||||
|
||||
lock.unlock();
|
||||
|
||||
SDL_Joystick* new_led_joystick_handle = nullptr;
|
||||
SDL_Haptic* new_haptic_handle = nullptr;
|
||||
std::map<u32, std::vector<SDL_Joystick*>> new_joysticks;
|
||||
std::map<u64, std::vector<SDL_Joystick*>> new_joysticks;
|
||||
|
||||
int joystick_count = 0;
|
||||
if (SDL_JoystickID* joystick_ids = SDL_GetJoysticks(&joystick_count))
|
||||
|
@ -250,7 +261,15 @@ void usb_device_logitech_g27::sdl_refresh()
|
|||
}
|
||||
const u16 cur_vendor_id = SDL_GetJoystickVendor(cur_joystick);
|
||||
const u16 cur_product_id = SDL_GetJoystickProduct(cur_joystick);
|
||||
const u32 joystick_type_id = (cur_vendor_id << 16) | cur_product_id;
|
||||
const emulated_g27_device_type_id joystick_type_id_struct =
|
||||
{
|
||||
.product_id = static_cast<u64>(cur_product_id),
|
||||
.vendor_id = static_cast<u64>(cur_vendor_id),
|
||||
.num_axes = static_cast<u64>(SDL_GetNumJoystickAxes(cur_joystick)),
|
||||
.num_hats = static_cast<u64>(SDL_GetNumJoystickHats(cur_joystick)),
|
||||
.num_buttons = static_cast<u64>(SDL_GetNumJoystickButtons(cur_joystick))
|
||||
};
|
||||
const u64 joystick_type_id = joystick_type_id_struct.as_u64();
|
||||
auto joysticks_of_type = new_joysticks.find(joystick_type_id);
|
||||
if (joysticks_of_type == new_joysticks.end())
|
||||
{
|
||||
|
@ -261,7 +280,11 @@ void usb_device_logitech_g27::sdl_refresh()
|
|||
joysticks_of_type->second.push_back(cur_joystick);
|
||||
}
|
||||
|
||||
if (cur_vendor_id == ffb_vendor_id && cur_product_id == ffb_product_id && new_haptic_handle == nullptr)
|
||||
u64 joystick_type_id_for_ffb = joystick_type_id;
|
||||
if (emulated_g27_device_type_id::is_v1(ffb_device_type_id))
|
||||
joystick_type_id_for_ffb = joystick_type_id & 0xFFFFFFFF;
|
||||
|
||||
if (joystick_type_id_for_ffb == ffb_device_type_id && new_haptic_handle == nullptr)
|
||||
{
|
||||
SDL_Haptic* cur_haptic = SDL_OpenHapticFromJoystick(cur_joystick);
|
||||
if (cur_haptic == nullptr)
|
||||
|
@ -274,7 +297,11 @@ void usb_device_logitech_g27::sdl_refresh()
|
|||
}
|
||||
}
|
||||
|
||||
if (cur_vendor_id == led_vendor_id && cur_product_id == led_product_id && new_led_joystick_handle == nullptr)
|
||||
u64 joystick_type_id_for_led = joystick_type_id;
|
||||
if (emulated_g27_device_type_id::is_v1(led_device_type_id))
|
||||
joystick_type_id_for_led = joystick_type_id & 0xFFFFFFFF;
|
||||
|
||||
if (joystick_type_id_for_led == led_device_type_id && new_led_joystick_handle == nullptr)
|
||||
{
|
||||
new_led_joystick_handle = cur_joystick;
|
||||
}
|
||||
|
@ -319,6 +346,7 @@ void usb_device_logitech_g27::sdl_refresh()
|
|||
// finally clear out previous joystick handles
|
||||
clear_sdl_joysticks(m_joysticks);
|
||||
m_joysticks = new_joysticks;
|
||||
m_joysticks_v1 = get_sdl_joysticks_v1(new_joysticks);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -576,7 +604,7 @@ static s16 fetch_sdl_as_axis(SDL_Joystick* joystick, const sdl_mapping& mapping)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static s16 fetch_sdl_axis_avg(std::map<u32, std::vector<SDL_Joystick*>>& joysticks, const sdl_mapping& mapping)
|
||||
static s16 fetch_sdl_axis_avg(std::map<u64, std::vector<SDL_Joystick*>>& joysticks, std::map<u64, std::vector<SDL_Joystick*>>& joysticks_v1, const sdl_mapping& mapping)
|
||||
{
|
||||
constexpr s16 MAX = 0x7FFF;
|
||||
constexpr s16 MIN = -0x8000;
|
||||
|
@ -584,7 +612,9 @@ static s16 fetch_sdl_axis_avg(std::map<u32, std::vector<SDL_Joystick*>>& joystic
|
|||
auto joysticks_of_type = joysticks.find(mapping.device_type_id);
|
||||
if (joysticks_of_type == joysticks.end())
|
||||
{
|
||||
return mapping.reverse ? MAX : MIN;
|
||||
joysticks_of_type = joysticks_v1.find(mapping.device_type_id);
|
||||
if (joysticks_of_type == joysticks_v1.end())
|
||||
return mapping.reverse ? MAX : MIN;
|
||||
}
|
||||
|
||||
if (joysticks_of_type->second.empty())
|
||||
|
@ -602,12 +632,14 @@ static s16 fetch_sdl_axis_avg(std::map<u32, std::vector<SDL_Joystick*>>& joystic
|
|||
return std::clamp<s16>(sdl_joysticks_total_value / static_cast<s32>(joysticks_of_type->second.size()), MIN, MAX);
|
||||
}
|
||||
|
||||
static bool sdl_to_logitech_g27_button(std::map<u32, std::vector<SDL_Joystick*>>& joysticks, const sdl_mapping& mapping)
|
||||
static bool sdl_to_logitech_g27_button(std::map<u64, std::vector<SDL_Joystick*>>& joysticks, std::map<u64, std::vector<SDL_Joystick*>>& joysticks_v1, const sdl_mapping& mapping)
|
||||
{
|
||||
auto joysticks_of_type = joysticks.find(mapping.device_type_id);
|
||||
if (joysticks_of_type == joysticks.end())
|
||||
{
|
||||
return mapping.reverse;
|
||||
joysticks_of_type = joysticks_v1.find(mapping.device_type_id);
|
||||
if (joysticks_of_type == joysticks_v1.end())
|
||||
return mapping.reverse;
|
||||
}
|
||||
|
||||
if (joysticks_of_type->second.empty())
|
||||
|
@ -623,16 +655,16 @@ static bool sdl_to_logitech_g27_button(std::map<u32, std::vector<SDL_Joystick*>>
|
|||
return pressed;
|
||||
}
|
||||
|
||||
static u16 sdl_to_logitech_g27_steering(std::map<u32, std::vector<SDL_Joystick*>>& joysticks, const sdl_mapping& mapping)
|
||||
static u16 sdl_to_logitech_g27_steering(std::map<u64, std::vector<SDL_Joystick*>>& joysticks, std::map<u64, std::vector<SDL_Joystick*>>& joysticks_v1, const sdl_mapping& mapping)
|
||||
{
|
||||
const s16 avg = fetch_sdl_axis_avg(joysticks, mapping);
|
||||
const s16 avg = fetch_sdl_axis_avg(joysticks, joysticks_v1, mapping);
|
||||
const u16 unsigned_avg = avg + 0x8000;
|
||||
return unsigned_avg * (0xFFFF >> 2) / 0xFFFF;
|
||||
}
|
||||
|
||||
static u8 sdl_to_logitech_g27_pedal(std::map<u32, std::vector<SDL_Joystick*>>& joysticks, const sdl_mapping& mapping)
|
||||
static u8 sdl_to_logitech_g27_pedal(std::map<u64, std::vector<SDL_Joystick*>>& joysticks, std::map<u64, std::vector<SDL_Joystick*>>& joysticks_v1, const sdl_mapping& mapping)
|
||||
{
|
||||
const s16 avg = fetch_sdl_axis_avg(joysticks, mapping);
|
||||
const s16 avg = fetch_sdl_axis_avg(joysticks, joysticks_v1, mapping);
|
||||
const u16 unsigned_avg = avg + 0x8000;
|
||||
return unsigned_avg * 0xFF / 0xFFFF;
|
||||
}
|
||||
|
@ -672,44 +704,44 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp
|
|||
|
||||
// Fetch input states from SDL
|
||||
m_sdl_handles_mutex.lock();
|
||||
const u16 steering = sdl_to_logitech_g27_steering(m_joysticks, m_mapping.steering);
|
||||
const u8 throttle = sdl_to_logitech_g27_pedal(m_joysticks, m_mapping.throttle);
|
||||
const u8 brake = sdl_to_logitech_g27_pedal(m_joysticks, m_mapping.brake);
|
||||
const u8 clutch = sdl_to_logitech_g27_pedal(m_joysticks, m_mapping.clutch);
|
||||
const bool shift_up = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shift_up);
|
||||
const bool shift_down = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shift_down);
|
||||
const u16 steering = sdl_to_logitech_g27_steering(m_joysticks, m_joysticks_v1, m_mapping.steering);
|
||||
const u8 throttle = sdl_to_logitech_g27_pedal(m_joysticks, m_joysticks_v1, m_mapping.throttle);
|
||||
const u8 brake = sdl_to_logitech_g27_pedal(m_joysticks, m_joysticks_v1, m_mapping.brake);
|
||||
const u8 clutch = sdl_to_logitech_g27_pedal(m_joysticks, m_joysticks_v1, m_mapping.clutch);
|
||||
const bool shift_up = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shift_up);
|
||||
const bool shift_down = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shift_down);
|
||||
|
||||
const bool up = sdl_to_logitech_g27_button(m_joysticks, m_mapping.up);
|
||||
const bool down = sdl_to_logitech_g27_button(m_joysticks, m_mapping.down);
|
||||
const bool left = sdl_to_logitech_g27_button(m_joysticks, m_mapping.left);
|
||||
const bool right = sdl_to_logitech_g27_button(m_joysticks, m_mapping.right);
|
||||
const bool up = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.up);
|
||||
const bool down = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.down);
|
||||
const bool left = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.left);
|
||||
const bool right = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.right);
|
||||
|
||||
const bool triangle = sdl_to_logitech_g27_button(m_joysticks, m_mapping.triangle);
|
||||
const bool cross = sdl_to_logitech_g27_button(m_joysticks, m_mapping.cross);
|
||||
const bool square = sdl_to_logitech_g27_button(m_joysticks, m_mapping.square);
|
||||
const bool circle = sdl_to_logitech_g27_button(m_joysticks, m_mapping.circle);
|
||||
const bool triangle = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.triangle);
|
||||
const bool cross = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.cross);
|
||||
const bool square = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.square);
|
||||
const bool circle = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.circle);
|
||||
|
||||
const bool l2 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.l2);
|
||||
const bool l3 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.l3);
|
||||
const bool r2 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.r2);
|
||||
const bool r3 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.r3);
|
||||
const bool l2 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.l2);
|
||||
const bool l3 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.l3);
|
||||
const bool r2 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.r2);
|
||||
const bool r3 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.r3);
|
||||
|
||||
const bool plus = sdl_to_logitech_g27_button(m_joysticks, m_mapping.plus);
|
||||
const bool minus = sdl_to_logitech_g27_button(m_joysticks, m_mapping.minus);
|
||||
const bool plus = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.plus);
|
||||
const bool minus = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.minus);
|
||||
|
||||
const bool dial_clockwise = sdl_to_logitech_g27_button(m_joysticks, m_mapping.dial_clockwise);
|
||||
const bool dial_anticlockwise = sdl_to_logitech_g27_button(m_joysticks, m_mapping.dial_anticlockwise);
|
||||
const bool dial_clockwise = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.dial_clockwise);
|
||||
const bool dial_anticlockwise = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.dial_anticlockwise);
|
||||
|
||||
const bool select = sdl_to_logitech_g27_button(m_joysticks, m_mapping.select);
|
||||
const bool pause = sdl_to_logitech_g27_button(m_joysticks, m_mapping.pause);
|
||||
const bool select = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.select);
|
||||
const bool pause = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.pause);
|
||||
|
||||
const bool shifter_1 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_1);
|
||||
const bool shifter_2 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_2);
|
||||
const bool shifter_3 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_3);
|
||||
const bool shifter_4 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_4);
|
||||
const bool shifter_5 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_5);
|
||||
const bool shifter_6 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_6);
|
||||
const bool shifter_r = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_r);
|
||||
const bool shifter_1 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_1);
|
||||
const bool shifter_2 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_2);
|
||||
const bool shifter_3 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_3);
|
||||
const bool shifter_4 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_4);
|
||||
const bool shifter_5 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_5);
|
||||
const bool shifter_6 = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_6);
|
||||
const bool shifter_r = sdl_to_logitech_g27_button(m_joysticks, m_joysticks_v1, m_mapping.shifter_r);
|
||||
m_sdl_handles_mutex.unlock();
|
||||
|
||||
// populate buffer
|
||||
|
|
|
@ -36,7 +36,16 @@ struct logitech_g27_ffb_slot
|
|||
|
||||
struct sdl_mapping
|
||||
{
|
||||
u32 device_type_id = 0; // (vendor_id << 16) | product_id
|
||||
/*
|
||||
* orginally 32bit, just vendor product match
|
||||
* v1: (vendor_id << 16) | product_id
|
||||
*
|
||||
* now 64bit, matching more to handle Fanatec's shenanigans, should be good until Fanatec desides that it's funny to register > 1023 axes/hats/buttons, then have two hid devices with the exact same numbers with one single wheel base
|
||||
* serial/version/firmware/guid is not used for now because those are still unreliable in SDL in the context of config
|
||||
* not migrating to string yet, don't want to make joystick look up heavy
|
||||
* v2: (num_buttons:10 << 52) | (num_hats:10 << 42) | (num_axes:10 << 32) | (vendor_id:16 << 16) | product_id:16
|
||||
*/
|
||||
u64 device_type_id = 0;
|
||||
sdl_mapping_type type = sdl_mapping_type::button;
|
||||
u64 id = 0;
|
||||
hat_component hat = hat_component::none;
|
||||
|
@ -111,7 +120,8 @@ private:
|
|||
std::mutex m_sdl_handles_mutex;
|
||||
SDL_Joystick* m_led_joystick_handle = nullptr;
|
||||
SDL_Haptic* m_haptic_handle = nullptr;
|
||||
std::map<u32, std::vector<SDL_Joystick*>> m_joysticks;
|
||||
std::map<u64, std::vector<SDL_Joystick*>> m_joysticks;
|
||||
std::map<u64, std::vector<SDL_Joystick*>> m_joysticks_v1;
|
||||
bool m_fixed_loop = false;
|
||||
u16 m_wheel_range = 200;
|
||||
std::array<logitech_g27_ffb_slot, 4> m_effect_slots {};
|
||||
|
|
|
@ -20,15 +20,61 @@ enum class hat_component
|
|||
right
|
||||
};
|
||||
|
||||
// this was a bitfield, but juggling at least 3 compilers and OSes means no bitfield
|
||||
// num_buttons:10 << 52 | num_hats:10 << 42 | num_axes:10 << 32 | vendor_id:16 << 16 | product_id:16
|
||||
struct emulated_g27_device_type_id
|
||||
{
|
||||
// big types to keep 64bit bit shift operations sane
|
||||
u64 product_id;
|
||||
u64 vendor_id;
|
||||
u64 num_axes;
|
||||
u64 num_hats;
|
||||
u64 num_buttons;
|
||||
|
||||
u64 as_u64() const
|
||||
{
|
||||
u64 value = product_id;
|
||||
value |= vendor_id << 16;
|
||||
value |= (num_axes & ((1 << 10) - 1)) << 32;
|
||||
value |= (num_hats & ((1 << 10) - 1)) << 42;
|
||||
value |= (num_buttons & ((1 << 10) - 1)) << 52;
|
||||
return value;
|
||||
}
|
||||
|
||||
bool is_v1()
|
||||
{
|
||||
return !num_axes && !num_hats && !num_buttons;
|
||||
}
|
||||
|
||||
static emulated_g27_device_type_id from_u64(u64 data)
|
||||
{
|
||||
const emulated_g27_device_type_id id =
|
||||
{
|
||||
.product_id = static_cast<u64>(data & 0xFFFF),
|
||||
.vendor_id = static_cast<u64>((data >> 16) & 0xFFFF),
|
||||
.num_axes = static_cast<u64>((data >> 32) & ((1 << 10) - 1)),
|
||||
.num_hats = static_cast<u64>((data >> 42) & ((1 << 10) - 1)),
|
||||
.num_buttons = static_cast<u64>((data >> 52) & ((1 << 10) - 1))
|
||||
};
|
||||
return id;
|
||||
}
|
||||
|
||||
static bool is_v1(u64 data)
|
||||
{
|
||||
emulated_g27_device_type_id id = from_u64(data);
|
||||
return id.is_v1();
|
||||
}
|
||||
};
|
||||
|
||||
struct emulated_logitech_g27_mapping : cfg::node
|
||||
{
|
||||
cfg::uint<0, 0xFFFFFFFF> device_type_id;
|
||||
cfg::uint<0, 0xFFFFFFFFFFFFFFFF> device_type_id;
|
||||
cfg::_enum<sdl_mapping_type> type;
|
||||
cfg::uint<0, 0xFFFFFFFFFFFFFFFF> id;
|
||||
cfg::_enum<hat_component> hat;
|
||||
cfg::_bool reverse;
|
||||
|
||||
emulated_logitech_g27_mapping(cfg::node* owner, std::string name, u32 device_type_id_def, sdl_mapping_type type_def, uint64_t id_def, hat_component hat_def, bool reverse_def)
|
||||
emulated_logitech_g27_mapping(cfg::node* owner, std::string name, u64 device_type_id_def, sdl_mapping_type type_def, u64 id_def, hat_component hat_def, bool reverse_def)
|
||||
: cfg::node(owner, std::move(name)),
|
||||
device_type_id(this, "device_type_id", device_type_id_def),
|
||||
type(this, "type", type_def),
|
||||
|
@ -45,6 +91,7 @@ public:
|
|||
std::mutex m_mutex;
|
||||
|
||||
// TODO these defaults are for a shifter-less G29 + a xbox controller for shifter testing, perhaps find a new default
|
||||
// TODO, when a new default is found, use the new device type id style
|
||||
|
||||
emulated_logitech_g27_mapping steering{this, "steering", 0x046dc24f, sdl_mapping_type::axis, 0, hat_component::none, false};
|
||||
emulated_logitech_g27_mapping throttle{this, "throttle", 0x046dc24f, sdl_mapping_type::axis, 2, hat_component::none, false};
|
||||
|
@ -86,8 +133,8 @@ public:
|
|||
emulated_logitech_g27_mapping shifter_r{this, "shifter_r", 0x045e028e, sdl_mapping_type::hat, 0, hat_component::left, false};
|
||||
|
||||
cfg::_bool reverse_effects{this, "reverse_effects", true};
|
||||
cfg::uint<0, 0xFFFFFFFF> ffb_device_type_id{this, "ffb_device_type_id", 0x046dc24f};
|
||||
cfg::uint<0, 0xFFFFFFFF> led_device_type_id{this, "led_device_type_id", 0x046dc24f};
|
||||
cfg::uint<0, 0xFFFFFFFFFFFFFFFF> ffb_device_type_id{this, "ffb_device_type_id", 0x046dc24f};
|
||||
cfg::uint<0, 0xFFFFFFFFFFFFFFFF> led_device_type_id{this, "led_device_type_id", 0x046dc24f};
|
||||
|
||||
cfg::_bool enabled{this, "enabled", false};
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ public:
|
|||
m_display_box->setTextFormat(Qt::RichText);
|
||||
m_display_box->setWordWrap(true);
|
||||
m_display_box->setFrameStyle(QFrame::Box);
|
||||
m_display_box->setMinimumWidth(150);
|
||||
m_display_box->setMinimumWidth(225);
|
||||
|
||||
m_map_button = new QPushButton(tr("MAP"), horizontal_container);
|
||||
m_unmap_button = new QPushButton(tr("UNMAP"), horizontal_container);
|
||||
|
@ -253,7 +253,7 @@ public:
|
|||
if (m_mapping_in_progress)
|
||||
{
|
||||
const int timeout_sec = m_timeout_msec / 1000;
|
||||
const std::map<u32, joystick_state>& new_joystick_states = m_setting_dialog->get_joystick_states();
|
||||
const std::map<u64, joystick_state>& new_joystick_states = m_setting_dialog->get_joystick_states();
|
||||
|
||||
m_setting_dialog->set_state_text(tr("Input %0 for %1, timeout in %2 %3").arg(m_is_axis ? tr("axis") : tr("button/hat")).arg(m_name).arg(timeout_sec).arg(timeout_sec >= 2 ? tr("seconds") : tr("second")));
|
||||
|
||||
|
@ -270,7 +270,7 @@ public:
|
|||
constexpr s16 axis_change_threshold = 0x7FFF / 5;
|
||||
if (last_joystick_state->second.axes.size() != new_joystick_state.axes.size())
|
||||
{
|
||||
logitech_g27_cfg_log.error("During input state change diff, number of axes on %04x:%04x changed", device_type_id >> 16, device_type_id & 0xFFFF);
|
||||
logitech_g27_cfg_log.error("During input state change diff, number of axes on %04x:%04x changed", (device_type_id >> 16) & 0xFFFF, device_type_id & 0xFFFF);
|
||||
continue;
|
||||
}
|
||||
for (usz i = 0; i < new_joystick_state.axes.size(); i++)
|
||||
|
@ -293,12 +293,12 @@ public:
|
|||
{
|
||||
if (last_joystick_state->second.buttons.size() != new_joystick_state.buttons.size())
|
||||
{
|
||||
logitech_g27_cfg_log.error("during input state change diff, number of buttons on %04x:%04x changed", device_type_id >> 16, device_type_id & 0xFFFF);
|
||||
logitech_g27_cfg_log.error("during input state change diff, number of buttons on %04x:%04x changed", (device_type_id >> 16) & 0xFFFF, device_type_id & 0xFFFF);
|
||||
continue;
|
||||
}
|
||||
if (last_joystick_state->second.hats.size() != new_joystick_state.hats.size())
|
||||
{
|
||||
logitech_g27_cfg_log.error("during input state change diff, number of hats on %04x:%04x changed", device_type_id >> 16, device_type_id & 0xFFFF);
|
||||
logitech_g27_cfg_log.error("during input state change diff, number of hats on %04x:%04x changed", (device_type_id >> 16) & 0xFFFF, device_type_id & 0xFFFF);
|
||||
continue;
|
||||
}
|
||||
for (usz i = 0; i < new_joystick_state.buttons.size(); i++)
|
||||
|
@ -381,14 +381,14 @@ private:
|
|||
bool m_mapping_in_progress = false;
|
||||
int m_timeout_msec = 5500;
|
||||
QTimer* m_tick_timer = nullptr;
|
||||
std::map<u32, joystick_state> m_last_joystick_states;
|
||||
std::map<u64, joystick_state> m_last_joystick_states;
|
||||
|
||||
QCheckBox* m_button_status = nullptr;
|
||||
QSlider* m_axis_status = nullptr;
|
||||
|
||||
void update_display()
|
||||
{
|
||||
const std::string text = fmt::format("%04x:%04x, %s %u %s", m_mapping.device_type_id >> 16, m_mapping.device_type_id & 0xFFFF, m_mapping.type, m_mapping.id, m_mapping.hat);
|
||||
const std::string text = fmt::format("%04x:%04x (0x%08x), %s %u %s", (m_mapping.device_type_id >> 16) & 0xFFFF, m_mapping.device_type_id & 0xFFFF, m_mapping.device_type_id >> 32, m_mapping.type, m_mapping.id, m_mapping.hat);
|
||||
m_display_box->setText(QString::fromStdString(text));
|
||||
|
||||
m_reverse_checkbox->setChecked(m_mapping.reverse);
|
||||
|
@ -406,7 +406,7 @@ private:
|
|||
m_axis_status->setValue(std::clamp(axis_value, -0x8000, 0x7FFF));
|
||||
}
|
||||
|
||||
const std::map<u32, joystick_state>& joystick_states = m_setting_dialog->get_joystick_states();
|
||||
const std::map<u64, joystick_state>& joystick_states = m_setting_dialog->get_joystick_states();
|
||||
auto joystick_state = joystick_states.find(m_mapping.device_type_id);
|
||||
|
||||
if (joystick_state != joystick_states.end())
|
||||
|
@ -525,11 +525,51 @@ void emulated_logitech_g27_settings_dialog::save_ui_state_to_config()
|
|||
}
|
||||
}
|
||||
|
||||
static void migrate_device_type_id(emulated_g27_device_type_id& device_type_id_struct)
|
||||
{
|
||||
if (!device_type_id_struct.is_v1())
|
||||
return;
|
||||
|
||||
sdl_instance::get_instance().pump_events();
|
||||
int joystick_count = 0;
|
||||
SDL_JoystickID* joystick_ids = SDL_GetJoysticks(&joystick_count);
|
||||
|
||||
if (!joystick_ids)
|
||||
return;
|
||||
|
||||
for (int i = 0;i < joystick_count;i++)
|
||||
{
|
||||
SDL_Joystick* cur_joystick = SDL_OpenJoystick(joystick_ids[i]);
|
||||
if (!cur_joystick)
|
||||
continue;
|
||||
|
||||
const u16 vendor_id = SDL_GetJoystickVendor(cur_joystick);
|
||||
const u16 product_id = SDL_GetJoystickProduct(cur_joystick);
|
||||
if (vendor_id == device_type_id_struct.vendor_id && product_id == device_type_id_struct.product_id)
|
||||
{
|
||||
device_type_id_struct.num_axes = SDL_GetNumJoystickAxes(cur_joystick);
|
||||
device_type_id_struct.num_hats = SDL_GetNumJoystickHats(cur_joystick);
|
||||
device_type_id_struct.num_buttons = SDL_GetNumJoystickButtons(cur_joystick);
|
||||
SDL_CloseJoystick(cur_joystick);
|
||||
break;
|
||||
}
|
||||
SDL_CloseJoystick(cur_joystick);
|
||||
}
|
||||
SDL_free(joystick_ids);
|
||||
}
|
||||
|
||||
static u64 migrate_device_type_id(u64 old_id)
|
||||
{
|
||||
emulated_g27_device_type_id old_id_struct = emulated_g27_device_type_id::from_u64(old_id);
|
||||
migrate_device_type_id(old_id_struct);
|
||||
return old_id_struct.as_u64();
|
||||
}
|
||||
|
||||
void emulated_logitech_g27_settings_dialog::load_ui_state_from_config()
|
||||
{
|
||||
const auto load_mapping = [this](const emulated_logitech_g27_mapping& mapping, Mapping* ui_mapping, mapping_device_choice device_choice)
|
||||
{
|
||||
const sdl_mapping m =
|
||||
sdl_mapping m =
|
||||
{
|
||||
.device_type_id = mapping.device_type_id.get(),
|
||||
.type = mapping.type.get(),
|
||||
|
@ -538,12 +578,25 @@ void emulated_logitech_g27_settings_dialog::load_ui_state_from_config()
|
|||
.reverse = mapping.reverse.get(),
|
||||
.positive_axis = false
|
||||
};
|
||||
|
||||
if (m_sdl_initialized)
|
||||
m.device_type_id = migrate_device_type_id(m.device_type_id);
|
||||
|
||||
ui_mapping->set_mapping(m);
|
||||
if (g_cfg_logitech_g27.ffb_device_type_id.get() == m.device_type_id && m_ffb_device->get_device_choice() == mapping_device_choice::NONE)
|
||||
|
||||
u64 ffb_device_type_id = g_cfg_logitech_g27.ffb_device_type_id.get();
|
||||
u64 led_device_type_id = g_cfg_logitech_g27.led_device_type_id.get();
|
||||
if (m_sdl_initialized)
|
||||
{
|
||||
ffb_device_type_id = migrate_device_type_id(ffb_device_type_id);
|
||||
led_device_type_id = migrate_device_type_id(led_device_type_id);
|
||||
}
|
||||
|
||||
if (ffb_device_type_id == m.device_type_id && m_ffb_device->get_device_choice() == mapping_device_choice::NONE)
|
||||
{
|
||||
m_ffb_device->set_device_choice(device_choice);
|
||||
}
|
||||
if (g_cfg_logitech_g27.led_device_type_id.get() == m.device_type_id && m_led_device->get_device_choice() == mapping_device_choice::NONE)
|
||||
if (led_device_type_id == m.device_type_id && m_led_device->get_device_choice() == mapping_device_choice::NONE)
|
||||
{
|
||||
m_led_device->set_device_choice(device_choice);
|
||||
}
|
||||
|
@ -629,8 +682,8 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi
|
|||
if (QMessageBox::question(this, tr("Confirm Reset"), tr("Reset all?")) != QMessageBox::Yes)
|
||||
return;
|
||||
g_cfg_logitech_g27.reset();
|
||||
load_ui_state_from_config();
|
||||
g_cfg_logitech_g27.save();
|
||||
load_ui_state_from_config();
|
||||
}
|
||||
else if (button == buttons->button(QDialogButtonBox::Cancel))
|
||||
{
|
||||
|
@ -643,6 +696,10 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi
|
|||
warning->setWordWrap(true);
|
||||
v_layout->addWidget(warning);
|
||||
|
||||
QLabel* mapping_note = new QLabel(tr("Note: Please DO NOT map your wheel onto gamepads, only map it here. If your wheel was mapped onto gamepads, go to gamepad settings and unmap it. If you used vJoy to map your wheel onto a gamepad before for rpcs3, undo that."), this);
|
||||
mapping_note->setWordWrap(true);
|
||||
v_layout->addWidget(mapping_note);
|
||||
|
||||
m_enabled = new QCheckBox(tr("Enabled (requires game restart)"), this);
|
||||
v_layout->addWidget(m_enabled);
|
||||
|
||||
|
@ -727,10 +784,10 @@ emulated_logitech_g27_settings_dialog::emulated_logitech_g27_settings_dialog(QWi
|
|||
v_layout->addWidget(buttons);
|
||||
setLayout(v_layout);
|
||||
|
||||
load_ui_state_from_config();
|
||||
|
||||
m_sdl_initialized = sdl_instance::get_instance().initialize();
|
||||
|
||||
load_ui_state_from_config();
|
||||
|
||||
if (m_sdl_initialized)
|
||||
get_joystick_states();
|
||||
}
|
||||
|
@ -769,7 +826,7 @@ static inline hat_component get_sdl_hat_component(u8 sdl_hat)
|
|||
return hat_component::none;
|
||||
}
|
||||
|
||||
const std::map<u32, joystick_state>& emulated_logitech_g27_settings_dialog::get_joystick_states()
|
||||
const std::map<u64, joystick_state>& emulated_logitech_g27_settings_dialog::get_joystick_states()
|
||||
{
|
||||
if (!m_sdl_initialized)
|
||||
{
|
||||
|
@ -785,7 +842,7 @@ const std::map<u32, joystick_state>& emulated_logitech_g27_settings_dialog::get_
|
|||
|
||||
m_last_joystick_states_update = now;
|
||||
|
||||
std::map<u32, joystick_state> new_joystick_states;
|
||||
std::map<u64, joystick_state> new_joystick_states;
|
||||
std::vector<SDL_Joystick*> new_joystick_handles;
|
||||
|
||||
sdl_instance::get_instance().pump_events();
|
||||
|
@ -802,15 +859,23 @@ const std::map<u32, joystick_state>& emulated_logitech_g27_settings_dialog::get_
|
|||
}
|
||||
new_joystick_handles.push_back(cur_joystick);
|
||||
|
||||
const u32 device_type_id = (SDL_GetJoystickVendor(cur_joystick) << 16) | SDL_GetJoystickProduct(cur_joystick);
|
||||
const int num_axes = SDL_GetNumJoystickAxes(cur_joystick);
|
||||
const int num_buttons = SDL_GetNumJoystickButtons(cur_joystick);
|
||||
const int num_hats = SDL_GetNumJoystickHats(cur_joystick);
|
||||
const emulated_g27_device_type_id device_type_id_struct =
|
||||
{
|
||||
.product_id = static_cast<u64>(SDL_GetJoystickProduct(cur_joystick)),
|
||||
.vendor_id = static_cast<u64>(SDL_GetJoystickVendor(cur_joystick)),
|
||||
.num_axes = static_cast<u64>(num_axes),
|
||||
.num_hats = static_cast<u64>(num_hats),
|
||||
.num_buttons = static_cast<u64>(num_buttons)
|
||||
};
|
||||
const u64 device_type_id = device_type_id_struct.as_u64();
|
||||
|
||||
auto cur_state = new_joystick_states.find(device_type_id);
|
||||
if (cur_state == new_joystick_states.end())
|
||||
{
|
||||
joystick_state s {};
|
||||
const int num_axes = SDL_GetNumJoystickAxes(cur_joystick);
|
||||
const int num_buttons = SDL_GetNumJoystickButtons(cur_joystick);
|
||||
const int num_hats = SDL_GetNumJoystickHats(cur_joystick);
|
||||
for (int j = 0; j < num_axes; j++)
|
||||
{
|
||||
s.axes.push_back(SDL_GetJoystickAxis(cur_joystick, j));
|
||||
|
|
|
@ -38,14 +38,14 @@ public:
|
|||
emulated_logitech_g27_settings_dialog(QWidget* parent = nullptr);
|
||||
virtual ~emulated_logitech_g27_settings_dialog();
|
||||
void set_state_text(const QString& text);
|
||||
const std::map<u32, joystick_state>& get_joystick_states();
|
||||
const std::map<u64, joystick_state>& get_joystick_states();
|
||||
void set_enable(bool enable);
|
||||
|
||||
private:
|
||||
void load_ui_state_from_config();
|
||||
void save_ui_state_to_config();
|
||||
|
||||
std::map<u32, joystick_state> m_last_joystick_states;
|
||||
std::map<u64, joystick_state> m_last_joystick_states;
|
||||
std::vector<SDL_Joystick*> m_joystick_handles;
|
||||
uint64_t m_last_joystick_states_update = 0;
|
||||
bool m_sdl_initialized = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue