Skip to content

Commit

Permalink
Merge pull request #8150 from lioncash/kbd
Browse files Browse the repository at this point in the history
IOS/USB_KBD: Minor cleanup
  • Loading branch information
leoetlino authored Jun 14, 2019
2 parents 3b7a7ae + c8b950e commit 59155b4
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 172 deletions.
293 changes: 139 additions & 154 deletions Source/Core/Core/IOS/USB/USB_KBD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "Core/IOS/USB/USB_KBD.h"

#include <cstring>
#include <array>
#include <queue>

#include "Common/FileUtil.h"
Expand All @@ -22,156 +22,11 @@

namespace IOS::HLE::Device
{
USB_KBD::SMessageData::SMessageData(u32 type, u8 modifiers, u8* pressed_keys)
namespace
{
MsgType = Common::swap32(type);
Unk1 = 0; // swapped
Modifiers = modifiers;
Unk2 = 0;

if (pressed_keys) // Doesn't need to be in a specific order
memcpy(PressedKeys, pressed_keys, sizeof(PressedKeys));
else
memset(PressedKeys, 0, sizeof(PressedKeys));
}

// TODO: support in netplay/movies.

USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

IPCCommandResult USB_KBD::Open(const OpenRequest& request)
{
INFO_LOG(IOS, "USB_KBD: Open");
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_KeyboardLayout, KBD_LAYOUT_QWERTY);

m_MessageQueue = std::queue<SMessageData>();
for (bool& pressed : m_OldKeyBuffer)
{
pressed = false;
}

m_OldModifiers = 0x00;

// m_MessageQueue.push(SMessageData(MSG_KBD_CONNECT, 0, nullptr));
return Device::Open(request);
}

IPCCommandResult USB_KBD::Write(const ReadWriteRequest& request)
{
// Stubbed.
return GetDefaultReply(IPC_SUCCESS);
}

IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request)
{
if (SConfig::GetInstance().m_WiiKeyboard && !Core::WantsDeterminism() &&
ControlReference::InputGateOn() && !m_MessageQueue.empty())
{
Memory::CopyToEmu(request.buffer_out, &m_MessageQueue.front(), sizeof(SMessageData));
m_MessageQueue.pop();
}
return GetDefaultReply(IPC_SUCCESS);
}

bool USB_KBD::IsKeyPressed(int _Key)
{
#ifdef _WIN32
if (GetAsyncKeyState(_Key) & 0x8000)
return true;
else
return false;
#else
// TODO: do it for non-Windows platforms
return false;
#endif
}

void USB_KBD::Update()
{
if (!SConfig::GetInstance().m_WiiKeyboard || Core::WantsDeterminism() || !m_is_active)
return;

u8 Modifiers = 0x00;
u8 PressedKeys[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
bool GotEvent = false;
int num_pressed_keys = 0;
for (int i = 0; i < 256; i++)
{
bool KeyPressedNow = IsKeyPressed(i);
bool KeyPressedBefore = m_OldKeyBuffer[i];
u8 KeyCode = 0;

if (KeyPressedNow ^ KeyPressedBefore)
{
if (KeyPressedNow)
{
switch (m_KeyboardLayout)
{
case KBD_LAYOUT_QWERTY:
KeyCode = m_KeyCodesQWERTY[i];
break;

case KBD_LAYOUT_AZERTY:
KeyCode = m_KeyCodesAZERTY[i];
break;
}

if (KeyCode == 0x00)
continue;

PressedKeys[num_pressed_keys] = KeyCode;

num_pressed_keys++;
if (num_pressed_keys == 6)
break;
}

GotEvent = true;
}

m_OldKeyBuffer[i] = KeyPressedNow;
}

#ifdef _WIN32
if (GetAsyncKeyState(VK_LCONTROL) & 0x8000)
Modifiers |= 0x01;
if (GetAsyncKeyState(VK_LSHIFT) & 0x8000)
Modifiers |= 0x02;
if (GetAsyncKeyState(VK_MENU) & 0x8000)
Modifiers |= 0x04;
if (GetAsyncKeyState(VK_LWIN) & 0x8000)
Modifiers |= 0x08;
if (GetAsyncKeyState(VK_RCONTROL) & 0x8000)
Modifiers |= 0x10;
if (GetAsyncKeyState(VK_RSHIFT) & 0x8000)
Modifiers |= 0x20;
if (GetAsyncKeyState(VK_MENU) &
0x8000) // TODO: VK_MENU is for ALT, not for ALT GR (ALT GR seems to work though...)
Modifiers |= 0x40;
if (GetAsyncKeyState(VK_RWIN) & 0x8000)
Modifiers |= 0x80;
#else
// TODO: modifiers for non-Windows platforms
#endif

if (Modifiers ^ m_OldModifiers)
{
GotEvent = true;
m_OldModifiers = Modifiers;
}

if (GotEvent)
m_MessageQueue.push(SMessageData(MSG_EVENT, Modifiers, PressedKeys));
}

// Crazy ugly
#ifdef _WIN32
u8 USB_KBD::m_KeyCodesQWERTY[256] = {

constexpr std::array<u8, 256> s_key_codes_qwerty{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
Expand Down Expand Up @@ -241,11 +96,9 @@ u8 USB_KBD::m_KeyCodesQWERTY[256] = {
0x34, // '''
0x00, //
0x00, // Nothing interesting past this point.

};

u8 USB_KBD::m_KeyCodesAZERTY[256] = {

constexpr std::array<u8, 256> s_key_codes_azerty{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
Expand Down Expand Up @@ -315,11 +168,143 @@ u8 USB_KBD::m_KeyCodesAZERTY[256] = {
0x00, // ' '
0x38, // '!'
0x00, // Nothing interesting past this point.

};
#else
u8 USB_KBD::m_KeyCodesQWERTY[256] = {0};
constexpr std::array<u8, 256> s_key_codes_qwerty{};

constexpr std::array<u8, 256> s_key_codes_azerty{};
#endif
} // Anonymous namespace

USB_KBD::MessageData::MessageData(MessageType type, u8 modifiers, PressedKeyData pressed_keys)
: msg_type{Common::swap32(static_cast<u32>(type))}, modifiers{modifiers}, pressed_keys{
pressed_keys}
{
}

// TODO: support in netplay/movies.

USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

IPCCommandResult USB_KBD::Open(const OpenRequest& request)
{
INFO_LOG(IOS, "USB_KBD: Open");
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
ini.GetOrCreateSection("USB Keyboard")->Get("Layout", &m_keyboard_layout, KBD_LAYOUT_QWERTY);

m_message_queue = {};
m_old_key_buffer.fill(false);
m_old_modifiers = 0x00;

// m_message_queue.emplace(MessageType::KeyboardConnect, 0, PressedKeyData{});
return Device::Open(request);
}

IPCCommandResult USB_KBD::Write(const ReadWriteRequest& request)
{
// Stubbed.
return GetDefaultReply(IPC_SUCCESS);
}

IPCCommandResult USB_KBD::IOCtl(const IOCtlRequest& request)
{
if (SConfig::GetInstance().m_WiiKeyboard && !Core::WantsDeterminism() &&
ControlReference::InputGateOn() && !m_message_queue.empty())
{
Memory::CopyToEmu(request.buffer_out, &m_message_queue.front(), sizeof(MessageData));
m_message_queue.pop();
}
return GetDefaultReply(IPC_SUCCESS);
}

bool USB_KBD::IsKeyPressed(int key) const
{
#ifdef _WIN32
return (GetAsyncKeyState(key) & 0x8000) != 0;
#else
// TODO: do it for non-Windows platforms
return false;
#endif
}

void USB_KBD::Update()
{
if (!SConfig::GetInstance().m_WiiKeyboard || Core::WantsDeterminism() || !m_is_active)
return;

u8 USB_KBD::m_KeyCodesAZERTY[256] = {0};
u8 modifiers = 0x00;
PressedKeyData pressed_keys{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
bool got_event = false;
size_t num_pressed_keys = 0;
for (size_t i = 0; i < m_old_key_buffer.size(); i++)
{
const bool key_pressed_now = IsKeyPressed(static_cast<int>(i));
const bool key_pressed_before = m_old_key_buffer[i];
u8 key_code = 0;

if (key_pressed_now ^ key_pressed_before)
{
if (key_pressed_now)
{
switch (m_keyboard_layout)
{
case KBD_LAYOUT_QWERTY:
key_code = s_key_codes_qwerty[i];
break;

case KBD_LAYOUT_AZERTY:
key_code = s_key_codes_azerty[i];
break;
}

if (key_code == 0x00)
continue;

pressed_keys[num_pressed_keys] = key_code;

num_pressed_keys++;
if (num_pressed_keys == pressed_keys.size())
break;
}

got_event = true;
}

m_old_key_buffer[i] = key_pressed_now;
}

#ifdef _WIN32
if (GetAsyncKeyState(VK_LCONTROL) & 0x8000)
modifiers |= 0x01;
if (GetAsyncKeyState(VK_LSHIFT) & 0x8000)
modifiers |= 0x02;
if (GetAsyncKeyState(VK_MENU) & 0x8000)
modifiers |= 0x04;
if (GetAsyncKeyState(VK_LWIN) & 0x8000)
modifiers |= 0x08;
if (GetAsyncKeyState(VK_RCONTROL) & 0x8000)
modifiers |= 0x10;
if (GetAsyncKeyState(VK_RSHIFT) & 0x8000)
modifiers |= 0x20;
// TODO: VK_MENU is for ALT, not for ALT GR (ALT GR seems to work though...)
if (GetAsyncKeyState(VK_MENU) & 0x8000)
modifiers |= 0x40;
if (GetAsyncKeyState(VK_RWIN) & 0x8000)
modifiers |= 0x80;
#else
// TODO: modifiers for non-Windows platforms
#endif

if (modifiers ^ m_old_modifiers)
{
got_event = true;
m_old_modifiers = modifiers;
}

if (got_event)
m_message_queue.emplace(MessageType::Event, modifiers, pressed_keys);
}
} // namespace IOS::HLE::Device
40 changes: 22 additions & 18 deletions Source/Core/Core/IOS/USB/USB_KBD.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

#pragma once

#include <array>
#include <queue>
#include <string>
#include <type_traits>

#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
Expand All @@ -24,40 +26,42 @@ class USB_KBD : public Device
void Update() override;

private:
enum
enum class MessageType : u32
{
MSG_KBD_CONNECT = 0,
MSG_KBD_DISCONNECT = 1,
MSG_EVENT = 2
KeyboardConnect = 0,
KeyboardDisconnect = 1,
Event = 2
};

using PressedKeyData = std::array<u8, 6>;

#pragma pack(push, 1)
struct SMessageData
struct MessageData
{
u32 MsgType;
u32 Unk1;
u8 Modifiers;
u8 Unk2;
u8 PressedKeys[6];
MessageType msg_type{};
u32 unk1 = 0;
u8 modifiers = 0;
u8 unk2 = 0;
PressedKeyData pressed_keys{};

SMessageData(u32 msg_type, u8 modifiers, u8* pressed_keys);
MessageData(MessageType msg_type, u8 modifiers, PressedKeyData pressed_keys);
};
static_assert(std::is_trivially_copyable_v<MessageData>,
"MessageData must be trivially copyable, as it's copied into emulated memory.");
#pragma pack(pop)
std::queue<SMessageData> m_MessageQueue;
std::queue<MessageData> m_message_queue;

bool m_OldKeyBuffer[256];
u8 m_OldModifiers;
std::array<bool, 256> m_old_key_buffer{};
u8 m_old_modifiers = 0;

virtual bool IsKeyPressed(int _Key);
bool IsKeyPressed(int key) const;

// This stuff should probably die
enum
{
KBD_LAYOUT_QWERTY = 0,
KBD_LAYOUT_AZERTY = 1
};
int m_KeyboardLayout;
static u8 m_KeyCodesQWERTY[256];
static u8 m_KeyCodesAZERTY[256];
int m_keyboard_layout = KBD_LAYOUT_QWERTY;
};
} // namespace IOS::HLE::Device

0 comments on commit 59155b4

Please sign in to comment.