diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj
index a157cf6729..7e8c63a4ba 100644
--- a/Source/Core/Core/Core.vcproj
+++ b/Source/Core/Core/Core.vcproj
@@ -2179,6 +2179,10 @@
 				RelativePath=".\Src\IPC_HLE\WII_IPC_HLE_Device_usb.h"
 				>
 			</File>
+			<File
+				RelativePath=".\Src\IPC_HLE\WII_IPC_HLE_Usb_Kbd.cpp"
+				>
+			</File>
 			<File
 				RelativePath=".\Src\IPC_HLE\WII_IPC_HLE_WiiMote.cpp"
 				>
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
index 0032537221..f439bbf35b 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
@@ -1993,356 +1993,3 @@ bool CWII_IPC_HLE_Device_usb_oh0::IOCtlV(u32 _CommandAddress)
 }
 
 
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// CWII_IPC_HLE_Device_usb_kbd
-//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
-#ifdef _WIN32
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2A, // Backspace
-	0x2B, // Tab
-	0x00, 0x00, 
-	0x00, // Clear
-	0x28, // Return
-	0x00, 0x00,
-	0x00, // Shift
-	0x00, // Control
-	0x00, // ALT
-	0x48, // Pause
-	0x39, // Capital
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x29, // Escape
-	0x00, 0x00, 0x00, 0x00,
-	0x2C, // Space
-	0x4B, // Prior
-	0x4E, // Next
-	0x4D, // End
-	0x4A, // Home
-	0x50, // Left
-	0x52, // Up
-	0x4F, // Right
-	0x51, // Down
-	0x00, 0x00, 0x00, 
-	0x46, // Print screen
-	0x49, // Insert
-	0x4C, // Delete
-	0x00,
-	// 0 -> 9
-	0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 
-	0x25, 0x26,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	// A -> Z
-	0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 
-	0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
-	0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
-	0x1C, 0x1D,
-	0x00, 0x00, 0x00, 0x00,
-	0x00,
-	// Numpad 0 -> 9
-	0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
-	0x60, 0x61,
-	0x55, // Multiply
-	0x57, // Add
-	0x00, // Separator
-	0x56, // Substract
-	0x63, // Decimal
-	0x54, // Divide
-	// F1 -> F12
-	0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
-	0x42, 0x43, 0x44, 0x45, 
-	// F13 -> F24
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x53, // Numlock
-	0x47, // Scroll lock
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	// Modifier keys
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	0x33, // ';'
-	0x2E, // Plus
-	0x36, // Comma
-	0x2D, // Minus
-	0x37, // Period
-	0x38, // '/'
-	0x35, // '~'
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00,
-	0x2F, // '['
-	0x32, // '\'
-	0x30, // ']'
-	0x34, // '''
-	0x00, //
-	0x00, // Nothing interesting past this point.
-#else
-	// TODO: do it for non-Windows platforms
-	0
-#endif
-};
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
-#ifdef _WIN32
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x2A, // Backspace
-	0x2B, // Tab
-	0x00, 0x00, 
-	0x00, // Clear
-	0x28, // Return
-	0x00, 0x00,
-	0x00, // Shift
-	0x00, // Control
-	0x00, // ALT
-	0x48, // Pause
-	0x39, // Capital
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x29, // Escape
-	0x00, 0x00, 0x00, 0x00,
-	0x2C, // Space
-	0x4B, // Prior
-	0x4E, // Next
-	0x4D, // End
-	0x4A, // Home
-	0x50, // Left
-	0x52, // Up
-	0x4F, // Right
-	0x51, // Down
-	0x00, 0x00, 0x00, 
-	0x46, // Print screen
-	0x49, // Insert
-	0x4C, // Delete
-	0x00,
-	// 0 -> 9
-	0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 
-	0x25, 0x26,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	// A -> Z
-	0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 
-	0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
-	0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
-	0x1C, 0x1A,
-	0x00, 0x00, 0x00, 0x00,
-	0x00,
-	// Numpad 0 -> 9
-	0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
-	0x60, 0x61,
-	0x55, // Multiply
-	0x57, // Add
-	0x00, // Separator
-	0x56, // Substract
-	0x63, // Decimal
-	0x54, // Divide
-	// F1 -> F12
-	0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
-	0x42, 0x43, 0x44, 0x45, 
-	// F13 -> F24
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x53, // Numlock
-	0x47, // Scroll lock
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	// Modifier keys
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	0x30, // '$'
-	0x2E, // Plus
-	0x10, // Comma
-	0x00, // Minus
-	0x36, // Period
-	0x37, // '/'
-	0x34, // '�'
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00,
-	0x2D, // ')'
-	0x32, // '\'
-	0x2F, // '^'
-	0x00, // '�'
-	0x38, // '!'
-	0x00, // Nothing interesting past this point.
-#else
-	// TODO: do it for non-Windows platforms
-	0
-#endif
-};
-
-CWII_IPC_HLE_Device_usb_kbd::CWII_IPC_HLE_Device_usb_kbd(u32 _DeviceID, const std::string& _rDeviceName)
-: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
-{
-}
-
-CWII_IPC_HLE_Device_usb_kbd::~CWII_IPC_HLE_Device_usb_kbd()
-{}
-
-bool CWII_IPC_HLE_Device_usb_kbd::Open(u32 _CommandAddress, u32 _Mode)
-{
-    Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
-
-	IniFile ini;
-	ini.Load(CONFIG_FILE);
-	ini.Get("USB Keyboard", "Layout", &m_KeyboardLayout, KBD_LAYOUT_QWERTY);
-
-	for(int i = 0; i < 256; i++)
-		m_OldKeyBuffer[i] = false;
-	m_OldModifiers = 0x00;
-
-	PushMessage(MSG_KBD_CONNECT, 0x00, NULL);
-
-    return true;
-}
-
-bool CWII_IPC_HLE_Device_usb_kbd::IOCtl(u32 _CommandAddress)
-{
-    u32 Parameter = Memory::Read_U32(_CommandAddress +0x0C);
-    u32 BufferIn =  Memory::Read_U32(_CommandAddress + 0x10);
-    u32 BufferInSize =  Memory::Read_U32(_CommandAddress + 0x14);
-    u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
-    u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
-
-	if (!m_MessageQueue.empty())
-	{
-		WriteMessage(BufferOut, m_MessageQueue.front());
-		m_MessageQueue.pop();
-	}
-
-    Memory::Write_U32(0, _CommandAddress + 0x4);
-    return true;
-}
-
-bool CWII_IPC_HLE_Device_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
-}
-
-u32 CWII_IPC_HLE_Device_usb_kbd::Update()
-{
-	u8 Modifiers = 0x00;
-	u8 PressedKeys[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-	bool GotEvent = false;
-	int i, j;
-
-	j = 0;
-	for (i = 0; i < 256; i++)
-	{
-		bool KeyPressedNow = IsKeyPressed(i);
-		bool KeyPressedBefore = m_OldKeyBuffer[i];
-		u8 KeyCode;
-
-		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[j] = KeyCode;
-
-				j++;
-				if(j == 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)
-		PushMessage(MSG_EVENT, Modifiers, PressedKeys);
-
-	return 0;
-}
-
-void CWII_IPC_HLE_Device_usb_kbd::PushMessage(u32 _Message, u8 _Modifiers, u8 * _PressedKeys)
-{
-	SMessageData MsgData;
-
-	MsgData.dwMessage = _Message;
-	MsgData.dwUnk1 = 0;
-	MsgData.bModifiers = _Modifiers;
-	MsgData.bUnk2 = 0;
-
-	if (_PressedKeys)
-		memcpy(MsgData.bPressedKeys, _PressedKeys, sizeof(MsgData.bPressedKeys));
-	else
-		memset(MsgData.bPressedKeys, 0, sizeof(MsgData.bPressedKeys));
-
-	m_MessageQueue.push(MsgData);
-}
-
-void CWII_IPC_HLE_Device_usb_kbd::WriteMessage(u32 _Address, SMessageData _Message)
-{
-	// TODO: the MessageData struct could be written directly in memory,
-	// instead of writing each member separately
-	Memory::Write_U32(_Message.dwMessage, _Address);
-	Memory::Write_U32(_Message.dwUnk1, _Address + 0x4);
-	Memory::Write_U8(_Message.bModifiers, _Address + 0x8);
-	Memory::Write_U8(_Message.bUnk2, _Address + 0x9);
-	Memory::Write_U8(_Message.bPressedKeys[0], _Address + 0xA);
-	Memory::Write_U8(_Message.bPressedKeys[1], _Address + 0xB);
-	Memory::Write_U8(_Message.bPressedKeys[2], _Address + 0xC);
-	Memory::Write_U8(_Message.bPressedKeys[3], _Address + 0xD);
-	Memory::Write_U8(_Message.bPressedKeys[4], _Address + 0xE);
-	Memory::Write_U8(_Message.bPressedKeys[5], _Address + 0xF);
-}
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
index 79e5a1e722..4baca9a399 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
@@ -293,10 +293,3 @@ private:
 
 #endif
 
-
-
-
-
-
-
-
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Usb_Kbd.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Usb_Kbd.cpp
new file mode 100644
index 0000000000..c6efe4750e
--- /dev/null
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Usb_Kbd.cpp
@@ -0,0 +1,367 @@
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "../Core.h" // Local core functions
+#include "WII_IPC_HLE_Device_usb.h"
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
+#ifdef _WIN32
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x2A, // Backspace
+	0x2B, // Tab
+	0x00, 0x00, 
+	0x00, // Clear
+	0x28, // Return
+	0x00, 0x00,
+	0x00, // Shift
+	0x00, // Control
+	0x00, // ALT
+	0x48, // Pause
+	0x39, // Capital
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x29, // Escape
+	0x00, 0x00, 0x00, 0x00,
+	0x2C, // Space
+	0x4B, // Prior
+	0x4E, // Next
+	0x4D, // End
+	0x4A, // Home
+	0x50, // Left
+	0x52, // Up
+	0x4F, // Right
+	0x51, // Down
+	0x00, 0x00, 0x00, 
+	0x46, // Print screen
+	0x49, // Insert
+	0x4C, // Delete
+	0x00,
+	// 0 -> 9
+	0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 
+	0x25, 0x26,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00,
+	// A -> Z
+	0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 
+	0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+	0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+	0x1C, 0x1D,
+	0x00, 0x00, 0x00, 0x00,
+	0x00,
+	// Numpad 0 -> 9
+	0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+	0x60, 0x61,
+	0x55, // Multiply
+	0x57, // Add
+	0x00, // Separator
+	0x56, // Substract
+	0x63, // Decimal
+	0x54, // Divide
+	// F1 -> F12
+	0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
+	0x42, 0x43, 0x44, 0x45, 
+	// F13 -> F24
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x53, // Numlock
+	0x47, // Scroll lock
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	// Modifier keys
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x33, // ';'
+	0x2E, // Plus
+	0x36, // Comma
+	0x2D, // Minus
+	0x37, // Period
+	0x38, // '/'
+	0x35, // '~'
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00,
+	0x2F, // '['
+	0x32, // '\'
+	0x30, // ']'
+	0x34, // '''
+	0x00, //
+	0x00, // Nothing interesting past this point.
+#else
+	// TODO: do it for non-Windows platforms
+	0
+#endif
+};
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
+#ifdef _WIN32
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x2A, // Backspace
+	0x2B, // Tab
+	0x00, 0x00, 
+	0x00, // Clear
+	0x28, // Return
+	0x00, 0x00,
+	0x00, // Shift
+	0x00, // Control
+	0x00, // ALT
+	0x48, // Pause
+	0x39, // Capital
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x29, // Escape
+	0x00, 0x00, 0x00, 0x00,
+	0x2C, // Space
+	0x4B, // Prior
+	0x4E, // Next
+	0x4D, // End
+	0x4A, // Home
+	0x50, // Left
+	0x52, // Up
+	0x4F, // Right
+	0x51, // Down
+	0x00, 0x00, 0x00, 
+	0x46, // Print screen
+	0x49, // Insert
+	0x4C, // Delete
+	0x00,
+	// 0 -> 9
+	0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 
+	0x25, 0x26,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00,
+	// A -> Z
+	0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 
+	0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
+	0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
+	0x1C, 0x1A,
+	0x00, 0x00, 0x00, 0x00,
+	0x00,
+	// Numpad 0 -> 9
+	0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+	0x60, 0x61,
+	0x55, // Multiply
+	0x57, // Add
+	0x00, // Separator
+	0x56, // Substract
+	0x63, // Decimal
+	0x54, // Divide
+	// F1 -> F12
+	0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
+	0x42, 0x43, 0x44, 0x45, 
+	// F13 -> F24
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x53, // Numlock
+	0x47, // Scroll lock
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	// Modifier keys
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x30, // '$'
+	0x2E, // Plus
+	0x10, // Comma
+	0x00, // Minus
+	0x36, // Period
+	0x37, // '/'
+	0x34, // '�'
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00,
+	0x2D, // ')'
+	0x32, // '\'
+	0x2F, // '^'
+	0x00, // '�'
+	0x38, // '!'
+	0x00, // Nothing interesting past this point.
+#else
+	// TODO: do it for non-Windows platforms
+	0
+#endif
+};
+
+CWII_IPC_HLE_Device_usb_kbd::CWII_IPC_HLE_Device_usb_kbd(u32 _DeviceID, const std::string& _rDeviceName)
+: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
+{
+}
+
+CWII_IPC_HLE_Device_usb_kbd::~CWII_IPC_HLE_Device_usb_kbd()
+{}
+
+bool CWII_IPC_HLE_Device_usb_kbd::Open(u32 _CommandAddress, u32 _Mode)
+{
+    Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
+
+	IniFile ini;
+	ini.Load(CONFIG_FILE);
+	ini.Get("USB Keyboard", "Layout", &m_KeyboardLayout, KBD_LAYOUT_QWERTY);
+
+	for(int i = 0; i < 256; i++)
+		m_OldKeyBuffer[i] = false;
+	m_OldModifiers = 0x00;
+
+	PushMessage(MSG_KBD_CONNECT, 0x00, NULL);
+
+    return true;
+}
+
+bool CWII_IPC_HLE_Device_usb_kbd::IOCtl(u32 _CommandAddress)
+{
+    u32 Parameter = Memory::Read_U32(_CommandAddress +0x0C);
+    u32 BufferIn =  Memory::Read_U32(_CommandAddress + 0x10);
+    u32 BufferInSize =  Memory::Read_U32(_CommandAddress + 0x14);
+    u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
+    u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
+
+	if (!m_MessageQueue.empty())
+	{
+		WriteMessage(BufferOut, m_MessageQueue.front());
+		m_MessageQueue.pop();
+	}
+
+    Memory::Write_U32(0, _CommandAddress + 0x4);
+    return true;
+}
+
+bool CWII_IPC_HLE_Device_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
+}
+
+u32 CWII_IPC_HLE_Device_usb_kbd::Update()
+{
+	u8 Modifiers = 0x00;
+	u8 PressedKeys[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	bool GotEvent = false;
+	int i, j;
+
+	j = 0;
+	for (i = 0; i < 256; i++)
+	{
+		bool KeyPressedNow = IsKeyPressed(i);
+		bool KeyPressedBefore = m_OldKeyBuffer[i];
+		u8 KeyCode;
+
+		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[j] = KeyCode;
+
+				j++;
+				if(j == 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)
+		PushMessage(MSG_EVENT, Modifiers, PressedKeys);
+
+	return 0;
+}
+
+void CWII_IPC_HLE_Device_usb_kbd::PushMessage(u32 _Message, u8 _Modifiers, u8 * _PressedKeys)
+{
+	SMessageData MsgData;
+
+	MsgData.dwMessage = _Message;
+	MsgData.dwUnk1 = 0;
+	MsgData.bModifiers = _Modifiers;
+	MsgData.bUnk2 = 0;
+
+	if (_PressedKeys)
+		memcpy(MsgData.bPressedKeys, _PressedKeys, sizeof(MsgData.bPressedKeys));
+	else
+		memset(MsgData.bPressedKeys, 0, sizeof(MsgData.bPressedKeys));
+
+	m_MessageQueue.push(MsgData);
+}
+
+void CWII_IPC_HLE_Device_usb_kbd::WriteMessage(u32 _Address, SMessageData _Message)
+{
+	// TODO: the MessageData struct could be written directly in memory,
+	// instead of writing each member separately
+	Memory::Write_U32(_Message.dwMessage, _Address);
+	Memory::Write_U32(_Message.dwUnk1, _Address + 0x4);
+	Memory::Write_U8(_Message.bModifiers, _Address + 0x8);
+	Memory::Write_U8(_Message.bUnk2, _Address + 0x9);
+	Memory::Write_U8(_Message.bPressedKeys[0], _Address + 0xA);
+	Memory::Write_U8(_Message.bPressedKeys[1], _Address + 0xB);
+	Memory::Write_U8(_Message.bPressedKeys[2], _Address + 0xC);
+	Memory::Write_U8(_Message.bPressedKeys[3], _Address + 0xD);
+	Memory::Write_U8(_Message.bPressedKeys[4], _Address + 0xE);
+	Memory::Write_U8(_Message.bPressedKeys[5], _Address + 0xF);
+}
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
index f06593b12f..1d0916e5e3 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
@@ -28,109 +28,6 @@
 #include "l2cap.h" // Local
 #include "WiiMote_HID_Attr.h"
 
-#pragma pack(push, 1)
-
-#define SDP_CHANNEL						0x01
-#define HIDP_CONTROL_CHANNEL			0x11
-#define HID_INTERRUPT_CHANNEL			0x13
-
-
-struct SL2CAP_Header
-{
-	u16 Length;
-	u16 CID;
-};
-
-/* L2CAP command codes */
-#define L2CAP_COMMAND_REJ 0x01
-#define L2CAP_CONN_REQ    0x02
-#define L2CAP_CONN_RSP    0x03
-#define L2CAP_CONF_REQ    0x04
-#define L2CAP_CONF_RSP    0x05
-#define L2CAP_DISCONN_REQ 0x06
-#define L2CAP_DISCONN_RSP 0x07
-#define L2CAP_ECHO_REQ    0x08
-#define L2CAP_ECHO_RSP    0x09
-#define L2CAP_INFO_REQ    0x0a
-#define L2CAP_INFO_RSP    0x0b
-
-/* connect result */
-#define L2CAP_CR_SUCCESS    0x0000
-#define L2CAP_CR_PEND       0x0001
-#define L2CAP_CR_BAD_PSM    0x0002
-#define L2CAP_CR_SEC_BLOCK  0x0003
-#define L2CAP_CR_NO_MEM     0x0004
-
-/* connect status */
-#define L2CAP_CS_NO_INFO      0x0000
-#define L2CAP_CS_AUTHEN_PEND  0x0001
-#define L2CAP_CS_AUTHOR_PEND  0x0002
-
-
-struct SL2CAP_Command
-{
-	u8 code;
-	u8 ident;
-	u16 len;
-};
-
-struct SL2CAP_CommandConnectionReq // 0x02
-{
-	u16 psm;
-	u16 scid;
-};
-
-struct SL2CAP_ConnectionResponse // 0x03
-{
-	u16 dcid;
-	u16 scid;
-	u16 result;
-	u16 status;
-};
-
-struct SL2CAP_Options
-{
-	u8 type;
-	u8 length;
-};
-
-struct SL2CAP_OptionsMTU
-{
-	u16 MTU;
-};
-
-struct SL2CAP_OptionsFlushTimeOut
-{
-	u16 TimeOut;
-};
-
-struct SL2CAP_CommandConfigurationReq // 0x04
-{
-	u16 dcid;
-	u16 flags;
-};
-
-struct SL2CAP_CommandConfigurationResponse // 0x05
-{
-	u16 scid;
-	u16 flags;
-	u16 result;
-};
-
-struct SL2CAP_CommandDisconnectionReq // 0x06
-{
-	u16 dcid;
-	u16 scid;
-};
-
-struct SL2CAP_CommandDisconnectionResponse // 0x07
-{
-	u16 dcid;
-	u16 scid;
-};
-
-#pragma pack(pop)
-
 static CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb;
 
 
@@ -143,8 +40,8 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
 	, m_HIDInterruptChannel_Connected(false)
 	, m_HIDInterruptChannel_ConnectedWait(false)
 	, m_HIDInterruptChannel_Config(false)
-	, m_HIDInterruptChannel_ConfigWait(false)          
-        , m_Name("Nintendo RVL-CNT-01")
+	, m_HIDInterruptChannel_ConfigWait(false)
+	, m_Name("Nintendo RVL-CNT-01")
 	, m_pHost(_pHost)
 
 
@@ -1050,3 +947,4 @@ namespace Core
 		DEBUG_LOG(WII_IPC_WIIMOTE, "=========================================================");
 	}
 }
+
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h
index b996188f10..23c6ddb113 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.h
@@ -23,6 +23,109 @@
 
 class CWII_IPC_HLE_Device_usb_oh1_57e_305;
 
+enum
+{
+	SDP_CHANNEL			 = 0x01,
+	HIDP_CONTROL_CHANNEL = 0x11,
+	HID_INTERRUPT_CHANNEL= 0x13,
+
+	// L2CAP command codes
+	L2CAP_COMMAND_REJ    = 0x01,
+	L2CAP_CONN_REQ       = 0x02,
+	L2CAP_CONN_RSP       = 0x03,
+	L2CAP_CONF_REQ       = 0x04,
+	L2CAP_CONF_RSP       = 0x05,
+	L2CAP_DISCONN_REQ    = 0x06,
+	L2CAP_DISCONN_RSP    = 0x07,
+	L2CAP_ECHO_REQ       = 0x08,
+	L2CAP_ECHO_RSP       = 0x09,
+	L2CAP_INFO_REQ       = 0x0a,
+	L2CAP_INFO_RSP       = 0x0b,
+
+	// connect result
+	L2CAP_CR_SUCCESS     = 0x0000,
+	L2CAP_CR_PEND        = 0x0001,
+	L2CAP_CR_BAD_PSM     = 0x0002,
+	L2CAP_CR_SEC_BLOCK   = 0x0003,
+	L2CAP_CR_NO_MEM      = 0x0004,
+
+	//connect status
+	L2CAP_CS_NO_INFO     = 0x0000,
+	L2CAP_CS_AUTHEN_PEND = 0x0001,
+	L2CAP_CS_AUTHOR_PEND = 0x0002,
+};
+
+#pragma pack(push, 1)
+
+struct SL2CAP_Header
+{
+	u16 Length;
+	u16 CID;
+};
+
+struct SL2CAP_Command
+{
+	u8 code;
+	u8 ident;
+	u16 len;
+};
+
+struct SL2CAP_CommandConnectionReq // 0x02
+{
+	u16 psm;
+	u16 scid;
+};
+
+struct SL2CAP_ConnectionResponse // 0x03
+{
+	u16 dcid;
+	u16 scid;
+	u16 result;
+	u16 status;
+};
+
+struct SL2CAP_Options
+{
+	u8 type;
+	u8 length;
+};
+
+struct SL2CAP_OptionsMTU
+{
+	u16 MTU;
+};
+
+struct SL2CAP_OptionsFlushTimeOut
+{
+	u16 TimeOut;
+};
+
+struct SL2CAP_CommandConfigurationReq // 0x04
+{
+	u16 dcid;
+	u16 flags;
+};
+
+struct SL2CAP_CommandConfigurationResponse // 0x05
+{
+	u16 scid;
+	u16 flags;
+	u16 result;
+};
+
+struct SL2CAP_CommandDisconnectionReq // 0x06
+{
+	u16 dcid;
+	u16 scid;
+};
+
+struct SL2CAP_CommandDisconnectionResponse // 0x07
+{
+	u16 dcid;
+	u16 scid;
+};
+
+#pragma pack(pop)
 
 class CBigEndianBuffer
 {
diff --git a/Source/Core/Core/Src/SConscript b/Source/Core/Core/Src/SConscript
index 97a2bf7d5c..705e17e7c0 100644
--- a/Source/Core/Core/Src/SConscript
+++ b/Source/Core/Core/Src/SConscript
@@ -69,6 +69,7 @@ files = ["ActionReplay.cpp",
          "IPC_HLE/WII_IPC_HLE_Device_net.cpp",
          "IPC_HLE/WII_IPC_HLE_WiiMote.cpp",
          "IPC_HLE/WII_IPC_HLE_Device_usb.cpp",
+         "IPC_HLE/WII_IPC_HLE_Usb_Kbd.cpp",
          "IPC_HLE/WiiMote_HID_Attr.cpp",
          "PowerPC/PowerPC.cpp",
          "PowerPC/PPCAnalyst.cpp",