Connected LLE USB implementation with the rest of the emulator (untested)
This commit is contained in:
parent
4e7d4a7eda
commit
c18e2f6a38
|
@ -35,8 +35,13 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
||||||
#include "InputConfig.h"
|
#include "InputConfig.h"
|
||||||
|
#include "..\devices\usb\XidGamepad.h"
|
||||||
|
#include "..\..\CxbxKrnl\EmuKrnl.h" // For EmuWarning
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
|
InputDeviceManager* g_InputDeviceManager = nullptr;
|
||||||
|
|
||||||
InputDeviceManager::InputDeviceManager()
|
InputDeviceManager::InputDeviceManager()
|
||||||
{
|
{
|
||||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
|
||||||
|
@ -53,6 +58,7 @@ InputDeviceManager::~InputDeviceManager()
|
||||||
int InputDeviceManager::EnumSdl2Devices()
|
int InputDeviceManager::EnumSdl2Devices()
|
||||||
{
|
{
|
||||||
int NumOfJoysticks;
|
int NumOfJoysticks;
|
||||||
|
int NumInvalidJoysticks;
|
||||||
SDL2Devices* pDev;
|
SDL2Devices* pDev;
|
||||||
SDL_GameController* pController;
|
SDL_GameController* pController;
|
||||||
std::vector<SDL2Devices*>::iterator it;
|
std::vector<SDL2Devices*>::iterator it;
|
||||||
|
@ -60,16 +66,19 @@ int InputDeviceManager::EnumSdl2Devices()
|
||||||
NumOfJoysticks = SDL_NumJoysticks();
|
NumOfJoysticks = SDL_NumJoysticks();
|
||||||
if (NumOfJoysticks < 0) {
|
if (NumOfJoysticks < 0) {
|
||||||
EmuWarning("Failed to enumerate joysticks. The error was: %s", SDL_GetError());
|
EmuWarning("Failed to enumerate joysticks. The error was: %s", SDL_GetError());
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
SDL_GameControllerButtonBind;
|
|
||||||
|
NumInvalidJoysticks = 0;
|
||||||
|
|
||||||
for (int i = 0; i < NumOfJoysticks; i++) {
|
for (int i = 0; i < NumOfJoysticks; i++) {
|
||||||
if (SDL_IsGameController(i)) {
|
if (SDL_IsGameController(i)) {
|
||||||
pDev = new SDL2Devices();
|
pDev = new SDL2Devices();
|
||||||
pDev->m_Index = i;
|
pDev->m_Index = i;
|
||||||
m_Sdl2Devices.push_back(pDev);
|
m_Sdl2Devices.push_back(pDev);
|
||||||
}
|
}
|
||||||
// this joystick not supported at the moment
|
// this joystick is not supported at the moment
|
||||||
|
NumInvalidJoysticks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (it = m_Sdl2Devices.begin(); it != m_Sdl2Devices.end();) {
|
for (it = m_Sdl2Devices.begin(); it != m_Sdl2Devices.end();) {
|
||||||
|
@ -78,14 +87,154 @@ int InputDeviceManager::EnumSdl2Devices()
|
||||||
EmuWarning("Failed to open game controller %s. The error was %s\n", SDL_GameControllerNameForIndex((*it)->m_Index), SDL_GetError());
|
EmuWarning("Failed to open game controller %s. The error was %s\n", SDL_GameControllerNameForIndex((*it)->m_Index), SDL_GetError());
|
||||||
delete (*it);
|
delete (*it);
|
||||||
it = m_Sdl2Devices.erase(it);
|
it = m_Sdl2Devices.erase(it);
|
||||||
|
NumInvalidJoysticks++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf("Found game controller %s\n", SDL_GameControllerName(pController));
|
printf("Found game controller %s\n", SDL_GameControllerName(pController));
|
||||||
(*it)->m_Gamepad = pController;
|
(*it)->m_Gamepad = pController;
|
||||||
(*it)->m_jyID = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(pController));
|
(*it)->m_jyID = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(pController));
|
||||||
|
(*it)->m_Attached = 1;
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NumOfJoysticks - NumInvalidJoysticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputDeviceManager::ConnectDeviceToXbox(int port, int type)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
std::vector<SDL2Devices*>::iterator it;
|
||||||
|
|
||||||
|
if (port > 4 || port < 1) { return ret; };
|
||||||
|
|
||||||
|
for (it = m_Sdl2Devices.begin(); it != m_Sdl2Devices.end(); ++it) {
|
||||||
|
if ((*it)->m_Index == (port - 1)) {
|
||||||
|
--port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == m_Sdl2Devices.end()) {
|
||||||
|
EmuWarning("Attempted to connect a device not yet enumerated.\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MS_CONTROLLER_DUKE: {
|
||||||
|
if (g_HubObjArray[port] == nullptr) {
|
||||||
|
g_HubObjArray[port] = new Hub;
|
||||||
|
ret = g_HubObjArray[port]->Init(port);
|
||||||
|
if (ret) {
|
||||||
|
delete g_HubObjArray[port];
|
||||||
|
g_HubObjArray[port] = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (g_XidControllerObjArray[port] == nullptr) {
|
||||||
|
g_XidControllerObjArray[port] = new XidGamepad;
|
||||||
|
ret = g_XidControllerObjArray[port]->Init(port);
|
||||||
|
if (ret) {
|
||||||
|
g_HubObjArray[port]->HubDestroy();
|
||||||
|
delete g_HubObjArray[port];
|
||||||
|
g_HubObjArray[port] = nullptr;
|
||||||
|
delete g_XidControllerObjArray[port];
|
||||||
|
g_XidControllerObjArray[port] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -1;
|
||||||
|
g_HubObjArray[port]->HubDestroy();
|
||||||
|
delete g_HubObjArray[port];
|
||||||
|
g_HubObjArray[port] = nullptr;
|
||||||
|
EmuWarning("Xid controller already present at port %d.2\n", port + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EmuWarning("Hub already present at port %d\n", port + 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MS_CONTROLLER_S:
|
||||||
|
case LIGHT_GUN:
|
||||||
|
case STEERING_WHEEL:
|
||||||
|
case MEMORY_UNIT:
|
||||||
|
case IR_DONGLE:
|
||||||
|
case STEEL_BATTALION_CONTROLLER: {
|
||||||
|
printf("This device type is not yet supported\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
EmuWarning("Attempted to attach an unknown device type\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
(*it)->m_Type = type;
|
||||||
|
(*it)->m_Attached = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputDeviceManager::DisconnectDeviceFromXbox(int port)
|
||||||
|
{
|
||||||
|
std::vector<SDL2Devices*>::iterator it;
|
||||||
|
|
||||||
|
if (port < 1) { return; }
|
||||||
|
|
||||||
|
for (it = m_Sdl2Devices.begin(); it != m_Sdl2Devices.end(); ++it) {
|
||||||
|
if ((*it)->m_Index == (port - 1)) {
|
||||||
|
--port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == m_Sdl2Devices.end()) {
|
||||||
|
// Not necessarily a bug. This could also be triggered by detaching an unsupported joystick
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port + 1 > 4) {
|
||||||
|
delete (*it);
|
||||||
|
m_Sdl2Devices.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((*it)->m_Type)
|
||||||
|
{
|
||||||
|
case MS_CONTROLLER_DUKE: {
|
||||||
|
if (g_HubObjArray[port] != nullptr && g_XidControllerObjArray[port] != nullptr) {
|
||||||
|
g_HubObjArray[port]->HubDestroy();
|
||||||
|
delete g_HubObjArray[port];
|
||||||
|
g_HubObjArray[port] = nullptr;
|
||||||
|
delete g_XidControllerObjArray[port];
|
||||||
|
g_XidControllerObjArray[port] = nullptr;
|
||||||
|
delete (*it);
|
||||||
|
m_Sdl2Devices.erase(it);
|
||||||
|
// Here, we could also see if there are detached devices that have a matching type and bound buttons, so that it can immediately
|
||||||
|
// be used instead of remaining inactive (example: 5 controllers and 1st is detached -> 5th can be used if it has bindings)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EmuWarning("Attempted to disconnect a device not attached to the Xbox.\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MS_CONTROLLER_S:
|
||||||
|
case LIGHT_GUN:
|
||||||
|
case STEERING_WHEEL:
|
||||||
|
case MEMORY_UNIT:
|
||||||
|
case IR_DONGLE:
|
||||||
|
case STEEL_BATTALION_CONTROLLER: {
|
||||||
|
printf("This device type is not yet supported\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
EmuWarning("Attempted to detach an unknown device type\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputDeviceManager::StartInputThread()
|
void InputDeviceManager::StartInputThread()
|
||||||
|
@ -128,6 +277,29 @@ void InputDeviceManager::InputThread(InputDeviceManager* pVoid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SDL_JOYDEVICEADDED: {
|
||||||
|
bool found = false;
|
||||||
|
for (auto dev : pVoid->m_Sdl2Devices) {
|
||||||
|
if (dev->m_Index == event.jdevice.which) {
|
||||||
|
// already enumerated, skipping
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
// for now we only support a single controller at port 1, more will be added later
|
||||||
|
if (!pVoid->IsValidController(event.jdevice.which) && event.jdevice.which == 0) {
|
||||||
|
pVoid->ConnectDeviceToXbox(1, MS_CONTROLLER_DUKE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_JOYDEVICEREMOVED: {
|
||||||
|
pVoid->DisconnectDeviceFromXbox(event.jdevice.which + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case SDL_CONTROLLERBUTTONUP:
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
case SDL_CONTROLLERBUTTONDOWN: {
|
case SDL_CONTROLLERBUTTONDOWN: {
|
||||||
pVoid->UpdateButtonState(event.cbutton.which, event.cbutton.button, event.cbutton.state);
|
pVoid->UpdateButtonState(event.cbutton.which, event.cbutton.button, event.cbutton.state);
|
||||||
|
@ -139,6 +311,13 @@ void InputDeviceManager::InputThread(InputDeviceManager* pVoid)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SDL_CONTROLLERDEVICEADDED: {
|
||||||
|
|
||||||
|
}
|
||||||
|
case SDL_CONTROLLERDEVICEREMOVED: {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
case SDL_QUIT: {
|
case SDL_QUIT: {
|
||||||
bContinue = false;
|
bContinue = false;
|
||||||
break;
|
break;
|
||||||
|
@ -250,3 +429,51 @@ void InputDeviceManager::UpdateAxisState(SDL_JoystickID id, uint8_t axis_index,
|
||||||
|
|
||||||
ControllerObj->UpdateAxisState(xbox_button, state);
|
ControllerObj->UpdateAxisState(xbox_button, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int InputDeviceManager::IsValidController(int index)
|
||||||
|
{
|
||||||
|
SDL2Devices* pDev;
|
||||||
|
SDL_GameController* pController;
|
||||||
|
|
||||||
|
if (SDL_IsGameController(index)) {
|
||||||
|
pDev = new SDL2Devices();
|
||||||
|
pDev->m_Index = index;
|
||||||
|
m_Sdl2Devices.push_back(pDev);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this joystick is not supported at the moment
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pController = SDL_GameControllerOpen(pDev->m_Index);
|
||||||
|
if (pController == nullptr) {
|
||||||
|
EmuWarning("Failed to open game controller %s. The error was %s\n", SDL_GameControllerNameForIndex(pDev->m_Index), SDL_GetError());
|
||||||
|
delete pDev;
|
||||||
|
m_Sdl2Devices.erase(m_Sdl2Devices.begin() + index);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (pDev->m_Index > 3) {
|
||||||
|
printf("More than 4 controllers detected. Putting game controller %s in detached state\n",
|
||||||
|
SDL_GameControllerName(pController));
|
||||||
|
pDev->m_Attached = 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Found game controller %s\n", SDL_GameControllerName(pController));
|
||||||
|
pDev->m_Gamepad = pController;
|
||||||
|
pDev->m_jyID = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(pController));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL2Devices* InputDeviceManager::FindDeviceFromXboxPort(int port)
|
||||||
|
{
|
||||||
|
if (port > 4 || port < 1) { return nullptr; };
|
||||||
|
|
||||||
|
for (auto it = m_Sdl2Devices.begin(); it != m_Sdl2Devices.end(); ++it) {
|
||||||
|
if ((*it)->m_Index == (port - 1)) {
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
|
@ -39,8 +39,6 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <thread>
|
|
||||||
#include "..\..\CxbxKrnl\EmuKrnl.h" // For EmuWarning
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
#define GAMEPAD_A 0
|
#define GAMEPAD_A 0
|
||||||
|
@ -75,13 +73,35 @@
|
||||||
#include "SDL2_Device.h"
|
#include "SDL2_Device.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* enum indicating the device type to attach to the virtual xbox */
|
||||||
|
typedef enum {
|
||||||
|
DEVICE_INVALID = 0,
|
||||||
|
MS_CONTROLLER_DUKE,
|
||||||
|
MS_CONTROLLER_S,
|
||||||
|
LIGHT_GUN,
|
||||||
|
STEERING_WHEEL,
|
||||||
|
MEMORY_UNIT,
|
||||||
|
IR_DONGLE,
|
||||||
|
STEEL_BATTALION_CONTROLLER,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class InputDeviceManager
|
class InputDeviceManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputDeviceManager();
|
InputDeviceManager();
|
||||||
~InputDeviceManager();
|
~InputDeviceManager();
|
||||||
|
|
||||||
|
// enumerate all available sdl2 controllers
|
||||||
int EnumSdl2Devices();
|
int EnumSdl2Devices();
|
||||||
|
// start input event processing thread
|
||||||
|
void StartInputThread();
|
||||||
|
// connect the enumerated device to the virtual xbox
|
||||||
|
int ConnectDeviceToXbox(int port, int type);
|
||||||
|
// disconnect a device from the emulated xbox
|
||||||
|
void DisconnectDeviceFromXbox(int port);
|
||||||
|
// find the device attached to the supplied xbox port
|
||||||
|
SDL2Devices* FindDeviceFromXboxPort(int port);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -90,8 +110,6 @@ class InputDeviceManager
|
||||||
|
|
||||||
// assign the button binding to the devices
|
// assign the button binding to the devices
|
||||||
//void AssignBindings();
|
//void AssignBindings();
|
||||||
// start input event processing thread
|
|
||||||
void StartInputThread();
|
|
||||||
// input thread
|
// input thread
|
||||||
static void InputThread(InputDeviceManager* pVoid);
|
static void InputThread(InputDeviceManager* pVoid);
|
||||||
// updates the button state of a joystick
|
// updates the button state of a joystick
|
||||||
|
@ -100,6 +118,10 @@ class InputDeviceManager
|
||||||
void UpdateHatState(SDL_JoystickID id, uint8_t hat_index, uint8_t state);
|
void UpdateHatState(SDL_JoystickID id, uint8_t hat_index, uint8_t state);
|
||||||
// updates the axis state of a joystick
|
// updates the axis state of a joystick
|
||||||
void UpdateAxisState(SDL_JoystickID id, uint8_t axis_index, int16_t state);
|
void UpdateAxisState(SDL_JoystickID id, uint8_t axis_index, int16_t state);
|
||||||
|
// checks if the controller attached can be used by sdl
|
||||||
|
int IsValidController(int index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern InputDeviceManager* g_InputDeviceManager;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
||||||
#include "SDL2_Device.h"
|
#include "SDL2_Device.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
int SDL2Devices::GetBoundButton(int sdl_key)
|
int SDL2Devices::GetBoundButton(int sdl_key)
|
||||||
|
@ -197,3 +198,19 @@ void SDL2Devices::UpdateAxisState(uint8_t xbox_button, int16_t state)
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDL2Devices::ReadButtonState(uint16_t* wButtons, uint8_t* bAnalogButtons, int16_t* sThumbLX,
|
||||||
|
int16_t* sThumbLY, int16_t* sThumbRX, int16_t* sThumbRY)
|
||||||
|
{
|
||||||
|
if (bStateDirty) {
|
||||||
|
*wButtons = m_State.wButtons.load();
|
||||||
|
*sThumbLX = m_State.sThumbLX.load();
|
||||||
|
*sThumbLY = m_State.sThumbLY.load();
|
||||||
|
*sThumbRX = m_State.sThumbRX.load();
|
||||||
|
*sThumbRY = m_State.sThumbRY.load();
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
bAnalogButtons[i] = m_State.bAnalogButtons[i].load();
|
||||||
|
}
|
||||||
|
bStateDirty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,10 @@ class SDL2Devices
|
||||||
SDL_GameController* m_Gamepad;
|
SDL_GameController* m_Gamepad;
|
||||||
// id of this controller
|
// id of this controller
|
||||||
SDL_JoystickID m_jyID;
|
SDL_JoystickID m_jyID;
|
||||||
|
// attach/detach state of this controller
|
||||||
|
int m_Attached;
|
||||||
|
// indicates the xbox device emulated by this controller
|
||||||
|
int m_Type = DEVICE_INVALID;
|
||||||
|
|
||||||
// update analog button state
|
// update analog button state
|
||||||
void UpdateAnalogButtonState(uint8_t xbox_button, uint8_t state);
|
void UpdateAnalogButtonState(uint8_t xbox_button, uint8_t state);
|
||||||
|
@ -73,10 +77,13 @@ class SDL2Devices
|
||||||
int GetBoundButton(int sdl_key);
|
int GetBoundButton(int sdl_key);
|
||||||
// update bBindingsChanged flag
|
// update bBindingsChanged flag
|
||||||
void SetChangedBinding(bool bFlag) { m_bBindingsChanged = bFlag; }
|
void SetChangedBinding(bool bFlag) { m_bBindingsChanged = bFlag; }
|
||||||
|
// read the current button state of a device
|
||||||
|
void ReadButtonState(uint16_t* wButtons, uint8_t* bAnalogButtons, int16_t* sThumbLX,
|
||||||
|
int16_t* sThumbLY, int16_t* sThumbRX, int16_t* sThumbRY);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// default bindings
|
// default bindings (hardcoded for now)
|
||||||
const int m_ButtonMap_Analog[8][2] = {
|
const int m_ButtonMap_Analog[8][2] = {
|
||||||
{ GAMEPAD_A, SDL_CONTROLLER_BUTTON_A },
|
{ GAMEPAD_A, SDL_CONTROLLER_BUTTON_A },
|
||||||
{ GAMEPAD_B, SDL_CONTROLLER_BUTTON_B },
|
{ GAMEPAD_B, SDL_CONTROLLER_BUTTON_B },
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace xboxkrnl
|
||||||
#include "devices\LED.h" // For LED::Sequence
|
#include "devices\LED.h" // For LED::Sequence
|
||||||
#include "EmuSha.h" // For the SHA1 functions
|
#include "EmuSha.h" // For the SHA1 functions
|
||||||
#include "Timer.h" // For Timer_Init
|
#include "Timer.h" // For Timer_Init
|
||||||
|
#include "..\Common\Input\InputConfig.h" // For the InputDeviceManager
|
||||||
|
|
||||||
/*! thread local storage */
|
/*! thread local storage */
|
||||||
Xbe::TLS *CxbxKrnl_TLS = NULL;
|
Xbe::TLS *CxbxKrnl_TLS = NULL;
|
||||||
|
@ -1454,10 +1455,23 @@ __declspec(noreturn) void CxbxKrnlInit
|
||||||
|
|
||||||
EmuHLEIntercept(pXbeHeader);
|
EmuHLEIntercept(pXbeHeader);
|
||||||
|
|
||||||
|
if (!bLLE_USB) {
|
||||||
SetupXboxDeviceTypes();
|
SetupXboxDeviceTypes();
|
||||||
|
}
|
||||||
|
|
||||||
InitXboxHardware(HardwareModel::Revision1_5); // TODO : Make configurable
|
InitXboxHardware(HardwareModel::Revision1_5); // TODO : Make configurable
|
||||||
|
|
||||||
|
if (bLLE_USB) {
|
||||||
|
int ret;
|
||||||
|
g_InputDeviceManager = new InputDeviceManager;
|
||||||
|
ret = g_InputDeviceManager->EnumSdl2Devices();
|
||||||
|
g_InputDeviceManager->StartInputThread();
|
||||||
|
if (ret > 0) {
|
||||||
|
// Temporary: the device type and bindings should be read from emushared, for now always assume one xbox controller
|
||||||
|
g_InputDeviceManager->ConnectDeviceToXbox(1, MS_CONTROLLER_DUKE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now the hardware devices exist, couple the EEPROM buffer to it's device
|
// Now the hardware devices exist, couple the EEPROM buffer to it's device
|
||||||
g_EEPROM->SetEEPROM((uint8_t*)EEPROM);
|
g_EEPROM->SetEEPROM((uint8_t*)EEPROM);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,9 @@
|
||||||
// *
|
// *
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
@ -107,6 +109,10 @@ void ClockThread(TimerObject* Timer)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Timer->Callback(Timer->Opaque);
|
Timer->Callback(Timer->Opaque);
|
||||||
|
if (Timer->Exit.load()) {
|
||||||
|
Timer_Destroy(Timer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
NewExpireTime = GetNextExpireTime(Timer);
|
NewExpireTime = GetNextExpireTime(Timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
||||||
#include "Xbox.h" // For HardwareModel
|
#include "Xbox.h" // For HardwareModel
|
||||||
|
#include "..\CxbxKrnl\HLEIntercept.h"
|
||||||
|
|
||||||
PCIBus* g_PCIBus;
|
PCIBus* g_PCIBus;
|
||||||
SMBus* g_SMBus;
|
SMBus* g_SMBus;
|
||||||
|
@ -130,8 +131,10 @@ void InitXboxHardware(HardwareModel hardwareModel)
|
||||||
g_NVNet = new NVNetDevice();
|
g_NVNet = new NVNetDevice();
|
||||||
g_NV2A = new NV2ADevice();
|
g_NV2A = new NV2ADevice();
|
||||||
g_ADM1032 = new ADM1032Device();
|
g_ADM1032 = new ADM1032Device();
|
||||||
|
if (bLLE_USB) {
|
||||||
g_USB0 = new USBDevice();
|
g_USB0 = new USBDevice();
|
||||||
g_USB1 = new USBDevice();
|
g_USB1 = new USBDevice();
|
||||||
|
}
|
||||||
|
|
||||||
// Connect devices to SM bus
|
// Connect devices to SM bus
|
||||||
g_SMBus->ConnectDevice(SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER, g_SMC); // W 0x20 R 0x21
|
g_SMBus->ConnectDevice(SMBUS_ADDRESS_SYSTEM_MICRO_CONTROLLER, g_SMC); // W 0x20 R 0x21
|
||||||
|
@ -160,8 +163,10 @@ void InitXboxHardware(HardwareModel hardwareModel)
|
||||||
//g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(5, 0)), g_NVAPU);
|
//g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(5, 0)), g_NVAPU);
|
||||||
//g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(6, 0)), g_AC97);
|
//g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(6, 0)), g_AC97);
|
||||||
g_PCIBus->ConnectDevice(PCI_DEVID(1, PCI_DEVFN(0, 0)), g_NV2A, NV2A_ADDR);
|
g_PCIBus->ConnectDevice(PCI_DEVID(1, PCI_DEVFN(0, 0)), g_NV2A, NV2A_ADDR);
|
||||||
|
if (bLLE_USB) {
|
||||||
g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(2, 0)), g_USB0, USB0_BASE);
|
g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(2, 0)), g_USB0, USB0_BASE);
|
||||||
g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(3, 0)), g_USB1, USB1_BASE);
|
g_PCIBus->ConnectDevice(PCI_DEVID(0, PCI_DEVFN(3, 0)), g_USB1, USB1_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO : Handle other SMBUS Addresses, like PIC_ADDRESS, XCALIBUR_ADDRESS
|
// TODO : Handle other SMBUS Addresses, like PIC_ADDRESS, XCALIBUR_ADDRESS
|
||||||
// Resources : http://pablot.com/misc/fancontroller.cpp
|
// Resources : http://pablot.com/misc/fancontroller.cpp
|
||||||
|
|
|
@ -81,6 +81,8 @@
|
||||||
extern USBDevice* g_USB0;
|
extern USBDevice* g_USB0;
|
||||||
extern USBDevice* g_USB1;
|
extern USBDevice* g_USB1;
|
||||||
|
|
||||||
|
Hub* g_HubObjArray[4] = { nullptr };
|
||||||
|
|
||||||
|
|
||||||
struct USBHubPort {
|
struct USBHubPort {
|
||||||
USBPort port; // downstream port status
|
USBPort port; // downstream port status
|
||||||
|
@ -689,3 +691,11 @@ void Hub::HubCleanUp()
|
||||||
m_pPeripheralFuncStruct = nullptr;
|
m_pPeripheralFuncStruct = nullptr;
|
||||||
m_HubState = nullptr;
|
m_HubState = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Hub::HubDestroy()
|
||||||
|
{
|
||||||
|
while (m_UsbDev->m_HostController->m_bFrameTime) {}
|
||||||
|
m_UsbDev->m_HostController->m_bFrameTime = true;
|
||||||
|
m_pPeripheralFuncStruct->handle_destroy();
|
||||||
|
m_UsbDev->m_HostController->m_bFrameTime = false;
|
||||||
|
}
|
||||||
|
|
|
@ -50,10 +50,10 @@ class Hub
|
||||||
// usb device this hub is attached to
|
// usb device this hub is attached to
|
||||||
USBDevice* m_UsbDev = nullptr;
|
USBDevice* m_UsbDev = nullptr;
|
||||||
|
|
||||||
// initialize this peripheral
|
// initialize this hub
|
||||||
int Init(int port);
|
int Init(int port);
|
||||||
// destroy hub resources
|
// start hub destruction
|
||||||
void HubCleanUp();
|
void HubDestroy();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -84,6 +84,8 @@ class Hub
|
||||||
void UsbHubReleasePort(XboxDeviceState* dev);
|
void UsbHubReleasePort(XboxDeviceState* dev);
|
||||||
// retieve the name of the feature of the usb request
|
// retieve the name of the feature of the usb request
|
||||||
std::string GetFeatureName(int feature);
|
std::string GetFeatureName(int feature);
|
||||||
|
// destroy hub resources
|
||||||
|
void HubCleanUp();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Hub* g_HubObjArray[4];
|
extern Hub* g_HubObjArray[4];
|
||||||
|
|
|
@ -195,6 +195,7 @@ OHCI::OHCI(int Irq, USBDevice* UsbObj)
|
||||||
|
|
||||||
m_IrqNum = Irq;
|
m_IrqNum = Irq;
|
||||||
m_UsbDevice = UsbObj;
|
m_UsbDevice = UsbObj;
|
||||||
|
m_bFrameTime = false;
|
||||||
ops = new USBPortOps();
|
ops = new USBPortOps();
|
||||||
{
|
{
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
@ -231,9 +232,13 @@ void OHCI::OHCI_FrameBoundaryWorker()
|
||||||
{
|
{
|
||||||
OHCI_HCCA hcca;
|
OHCI_HCCA hcca;
|
||||||
|
|
||||||
|
while (m_bFrameTime) {}
|
||||||
|
m_bFrameTime = true;
|
||||||
|
|
||||||
if (OHCI_ReadHCCA(m_Registers.HcHCCA, &hcca)) {
|
if (OHCI_ReadHCCA(m_Registers.HcHCCA, &hcca)) {
|
||||||
EmuWarning("%s: HCCA read error at physical address 0x%X", m_Registers.HcHCCA, LOG_STR_OHCI);
|
EmuWarning("%s: HCCA read error at physical address 0x%X", m_Registers.HcHCCA, LOG_STR_OHCI);
|
||||||
OHCI_FatalError();
|
OHCI_FatalError();
|
||||||
|
m_bFrameTime = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +263,7 @@ void OHCI::OHCI_FrameBoundaryWorker()
|
||||||
|
|
||||||
// Stop if UnrecoverableError happened or OHCI_SOF will crash
|
// Stop if UnrecoverableError happened or OHCI_SOF will crash
|
||||||
if (m_Registers.HcInterruptStatus & OHCI_INTR_UE) {
|
if (m_Registers.HcInterruptStatus & OHCI_INTR_UE) {
|
||||||
|
m_bFrameTime = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +309,7 @@ void OHCI::OHCI_FrameBoundaryWorker()
|
||||||
EmuWarning("%s: HCCA write error at physical address 0x%X", LOG_STR_OHCI, m_Registers.HcHCCA);
|
EmuWarning("%s: HCCA write error at physical address 0x%X", LOG_STR_OHCI, m_Registers.HcHCCA);
|
||||||
OHCI_FatalError();
|
OHCI_FatalError();
|
||||||
}
|
}
|
||||||
|
m_bFrameTime = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OHCI::OHCI_FatalError()
|
void OHCI::OHCI_FatalError()
|
||||||
|
|
|
@ -140,6 +140,10 @@ struct OHCI_Registers
|
||||||
class OHCI
|
class OHCI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Indicates that the timer thread is accessing the OHCI object. Necessary because the input thread from the
|
||||||
|
// InputDeviceManager will access us when it needs to destroy a device
|
||||||
|
std::atomic_bool m_bFrameTime;
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
OHCI(int Irqn, USBDevice* UsbObj);
|
OHCI(int Irqn, USBDevice* UsbObj);
|
||||||
// destructor
|
// destructor
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
#include "XidGamepad.h"
|
#include "XidGamepad.h"
|
||||||
#include "USBDevice.h"
|
#include "USBDevice.h"
|
||||||
|
#include "Common/Input/InputConfig.h"
|
||||||
|
|
||||||
#define LOG_STR_GAMEPAD "Gamepad:"
|
#define LOG_STR_GAMEPAD "Gamepad:"
|
||||||
|
|
||||||
|
@ -47,6 +48,8 @@
|
||||||
#define XID_GET_CAPABILITIES 0x01
|
#define XID_GET_CAPABILITIES 0x01
|
||||||
|
|
||||||
|
|
||||||
|
XidGamepad* g_XidControllerObjArray[4];
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
/* Class-specific xid descriptor */
|
/* Class-specific xid descriptor */
|
||||||
|
@ -239,9 +242,10 @@ int XidGamepad::UsbXidClaimPort(XboxDeviceState* dev, int port)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_UsbDev == nullptr) {
|
if (m_UsbDev == nullptr) {
|
||||||
EmuWarning("Port requested %d.%d not found (in use?)", port, 2);
|
EmuWarning("Port requested %d.2 not found (in use?)", port);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
m_Port = port;
|
||||||
it = m_UsbDev->m_FreePorts.begin() + i;
|
it = m_UsbDev->m_FreePorts.begin() + i;
|
||||||
dev->Port = *it;
|
dev->Port = *it;
|
||||||
(*it)->Dev = dev;
|
(*it)->Dev = dev;
|
||||||
|
@ -316,6 +320,12 @@ void XidGamepad::UsbXid_HandleControl(XboxDeviceState* dev, USBPacket* p,
|
||||||
if (value == 0x100) {
|
if (value == 0x100) {
|
||||||
assert(m_XidState->in_state.bLength <= length);
|
assert(m_XidState->in_state.bLength <= length);
|
||||||
// m_XidState->in_state.bReportId++; /* FIXME: I'm not sure if bReportId is just a counter */
|
// m_XidState->in_state.bReportId++; /* FIXME: I'm not sure if bReportId is just a counter */
|
||||||
|
SDL2Devices* controller = g_InputDeviceManager->FindDeviceFromXboxPort(m_Port);
|
||||||
|
if (controller != nullptr) {
|
||||||
|
controller->ReadButtonState(&m_XidState->in_state.wButtons, m_XidState->in_state.bAnalogButtons,
|
||||||
|
&m_XidState->in_state.sThumbLX, &m_XidState->in_state.sThumbLY, &m_XidState->in_state.sThumbRX,
|
||||||
|
&m_XidState->in_state.sThumbRY);
|
||||||
|
}
|
||||||
std::memcpy(data, &m_XidState->in_state, m_XidState->in_state.bLength);
|
std::memcpy(data, &m_XidState->in_state, m_XidState->in_state.bLength);
|
||||||
p->ActualLength = m_XidState->in_state.bLength;
|
p->ActualLength = m_XidState->in_state.bLength;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
|
|
||||||
struct USBXIDState; // forward declare
|
struct USBXIDState; // forward declare
|
||||||
|
|
||||||
|
|
||||||
/* Class which implements an xbox gamepad */
|
/* Class which implements an xbox gamepad */
|
||||||
class XidGamepad
|
class XidGamepad
|
||||||
{
|
{
|
||||||
|
@ -60,6 +59,8 @@ class XidGamepad
|
||||||
USBXIDState* m_XidState = nullptr;
|
USBXIDState* m_XidState = nullptr;
|
||||||
// gamepad class functions
|
// gamepad class functions
|
||||||
USBDeviceClass* m_pPeripheralFuncStruct = nullptr;
|
USBDeviceClass* m_pPeripheralFuncStruct = nullptr;
|
||||||
|
// xbox port this gamepad is attached to
|
||||||
|
int m_Port = 0;
|
||||||
|
|
||||||
// initialize various member variables/functions
|
// initialize various member variables/functions
|
||||||
XboxDeviceState* ClassInitFn();
|
XboxDeviceState* ClassInitFn();
|
||||||
|
@ -77,4 +78,6 @@ class XidGamepad
|
||||||
void UsbXid_HandleData(XboxDeviceState* dev, USBPacket* p);
|
void UsbXid_HandleData(XboxDeviceState* dev, USBPacket* p);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern XidGamepad* g_XidControllerObjArray[4];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue