Skip to content

Commit

Permalink
SI: GCAdapter reorganisation
Browse files Browse the repository at this point in the history
Reorganise GCAdapter, try to cater for calibration.
  • Loading branch information
booto committed Aug 17, 2019
1 parent da6289b commit 16d12f5
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 108 deletions.
6 changes: 0 additions & 6 deletions Source/Core/Core/HW/SI/SI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,6 @@ static void RunSIBuffer(u64 user_data, s64 cycles_late)
if (s_com_csr.TSTART)
{
u32 request_length = ConvertSILengthField(s_com_csr.OUTLNGTH);
u32 expected_response_length = ConvertSILengthField(s_com_csr.INLNGTH);
std::vector<u8> request_copy(s_si_buffer.data(), s_si_buffer.data() + request_length);

std::unique_ptr<ISIDevice>& device = s_channel[s_com_csr.CHANNEL].device;
Expand All @@ -671,9 +670,6 @@ static void RunSIBuffer(u64 user_data, s64 cycles_late)
EstimateTicksForXfer(1, SI_MICROSECONDS_PER_STOP_BIT) - cycles_late,
s_get_response_event[s_com_csr.CHANNEL], SiGetMaskForChannel(s_com_csr.CHANNEL));

INFO_LOG(SERIALINTERFACE,
"RunSIBuffer chan: %d request_length: %u expected_response_length: %u",
s_com_csr.CHANNEL, request_length, expected_response_length);
// TODO:
// Wait a reasonable amount of time for the result to be available:
// request is N bytes, ends with a stop bit
Expand Down Expand Up @@ -1054,8 +1050,6 @@ void TriggerPoll(s64 cycles_late)
EstimateTicksForXfer(1, SI_MICROSECONDS_PER_STOP_BIT) -
cycles_late,
s_poll_get_response_event, user_data);

INFO_LOG(SERIALINTERFACE, "TriggerPoll: user_data: %x", user_data);
}

// Polling finished
Expand Down
24 changes: 24 additions & 0 deletions Source/Core/Core/HW/SI/SI_DeviceGCAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,30 @@ int CSIDevice_GCAdapter::RunBuffer(u8* buffer, int request_length)
return 0;
}
}
// Read the command
EBufferCommands command = static_cast<EBufferCommands>(buffer[0]);
switch (command)
{
case CMD_ORIGIN:
case CMD_RECALIBRATE:
{
SOrigin origin = {};
GCAdapter::origin_data od;
GCAdapter::GetOrigin(m_device_number, &od);
origin.origin_stick_x = od.stickX;
origin.origin_stick_y = od.stickY;
origin.substick_x = od.substickX;
origin.substick_y = od.substickY;
origin.trigger_left = od.triggerL;
origin.trigger_right = od.triggerR;
u8* calibration = reinterpret_cast<u8*>(&origin);
for (int i = 0; i < (int)sizeof(SOrigin); i++)
{
buffer[i] = *calibration++;
}
return sizeof(SOrigin);
}
}
return CSIDevice_GCController::RunBuffer(buffer, request_length);
}

Expand Down
2 changes: 0 additions & 2 deletions Source/Core/Core/HW/SI/SI_DeviceGCController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,6 @@ int CSIDevice_GCController::RunBuffer(u8* buffer, int request_length)

void CSIDevice_GCController::HandleMoviePadStatus(GCPadStatus* pad_status)
{
INFO_LOG(SERIALINTERFACE, "HandleMoviePadStatus input timestamp: %llu device_number: %d",
Common::Timer::GetTimeUs(), m_device_number);
Movie::CallGCInputManip(pad_status, m_device_number);

Movie::SetPolledDevice();
Expand Down
220 changes: 120 additions & 100 deletions Source/Core/InputCommon/GCAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,22 @@ static u8 s_controller_type[SerialInterface::MAX_SI_CHANNELS] = {
ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE};
static u8 s_controller_rumble[4];

static std::mutex s_mutex;
static u8 s_controller_payload[37];
struct poll_data
{
u8 status;
u8 buttons1;
u8 buttons2;
u8 stickX;
u8 stickY;
u8 substickX;
u8 substickY;
u8 triggerL;
u8 triggerR;
};

static std::mutex s_poll_mutex;
static std::array<poll_data, SerialInterface::MAX_SI_CHANNELS> s_controller_payload;
static std::array<origin_data, SerialInterface::MAX_SI_CHANNELS> s_controller_origin;
static u8 s_controller_payload_swap[37];

static std::atomic<int> s_controller_payload_size = {0};
Expand Down Expand Up @@ -82,15 +96,21 @@ static void Read()
int payload_size = 0;
while (s_adapter_thread_running.IsSet())
{
libusb_interrupt_transfer(s_handle, s_endpoint_in, s_controller_payload_swap,
sizeof(s_controller_payload_swap), &payload_size, 16);

std::array<u8, 37> transfer_buffer;
libusb_interrupt_transfer(s_handle, s_endpoint_in, &transfer_buffer[0], sizeof(transfer_buffer),
&payload_size, 16);
if ((payload_size == 37) && (transfer_buffer[0] == 0x21))
{
{
std::lock_guard<std::mutex> lk(s_poll_mutex);
std::copy_n(&transfer_buffer[1], sizeof(s_controller_payload),
reinterpret_cast<u8*>(&s_controller_payload));
}
}
else
{
std::lock_guard<std::mutex> lk(s_mutex);
std::swap(s_controller_payload_swap, s_controller_payload);
s_controller_payload_size.store(payload_size);
memset(reinterpret_cast<u8*>(&s_controller_payload), 0, sizeof(s_controller_payload));
}

Common::YieldCPU();
}
}
Expand Down Expand Up @@ -338,7 +358,7 @@ static void AddGCAdapter(libusb_device* device)
for (u8 e = 0; e < interface->bNumEndpoints; e++)
{
const libusb_endpoint_descriptor* endpoint = &interface->endpoint[e];
if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN)
if ((endpoint->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
s_endpoint_in = endpoint->bEndpointAddress;
else
s_endpoint_out = endpoint->bEndpointAddress;
Expand Down Expand Up @@ -405,121 +425,116 @@ static void Reset()

GCPadStatus Input(int chan)
{
GCPadStatus pad = {};
if (!UseAdapter())
return {};
return pad;

if (s_handle == nullptr || s_status != ADAPTER_DETECTED)
return {};
{
return pad;
}

int payload_size = 0;
u8 controller_payload_copy[37];
if (s_controller_type[chan] == ControllerTypes::CONTROLLER_NONE)
{
return pad;
}

poll_data pd;
{
std::lock_guard<std::mutex> lk(s_mutex);
std::copy(std::begin(s_controller_payload), std::end(s_controller_payload),
std::begin(controller_payload_copy));
payload_size = s_controller_payload_size.load();
std::lock_guard<std::mutex> lk(s_poll_mutex);
pd = s_controller_payload[chan];
}

GCPadStatus pad = {};
if (payload_size != sizeof(controller_payload_copy) ||
controller_payload_copy[0] != LIBUSB_DT_HID)
u8 type = pd.status >> 4;
if (type == ControllerTypes::CONTROLLER_NONE)
{
ERROR_LOG(SERIALINTERFACE, "error reading payload (size: %d, type: %02x)", payload_size,
controller_payload_copy[0]);
Reset();
NOTICE_LOG(SERIALINTERFACE, "Device disconnected from Port %d", chan + 1);
s_controller_type[chan] = ControllerTypes::CONTROLLER_NONE;
return pad;
}
else
/*
if (type != ControllerTypes::CONTROLLER_NONE &&
s_controller_type[chan] == ControllerTypes::CONTROLLER_NONE)
{
bool get_origin = false;
u8 type = controller_payload_copy[1 + (9 * chan)] >> 4;
if (type != ControllerTypes::CONTROLLER_NONE &&
s_controller_type[chan] == ControllerTypes::CONTROLLER_NONE)
{
NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1,
controller_payload_copy[1 + (9 * chan)]);
get_origin = true;
}

s_controller_type[chan] = type;

if (s_controller_type[chan] != ControllerTypes::CONTROLLER_NONE)
{
u8 b1 = controller_payload_copy[1 + (9 * chan) + 1];
u8 b2 = controller_payload_copy[1 + (9 * chan) + 2];

if (b1 & (1 << 0))
pad.button |= PAD_BUTTON_A;
if (b1 & (1 << 1))
pad.button |= PAD_BUTTON_B;
if (b1 & (1 << 2))
pad.button |= PAD_BUTTON_X;
if (b1 & (1 << 3))
pad.button |= PAD_BUTTON_Y;

if (b1 & (1 << 4))
pad.button |= PAD_BUTTON_LEFT;
if (b1 & (1 << 5))
pad.button |= PAD_BUTTON_RIGHT;
if (b1 & (1 << 6))
pad.button |= PAD_BUTTON_DOWN;
if (b1 & (1 << 7))
pad.button |= PAD_BUTTON_UP;

if (b2 & (1 << 0))
pad.button |= PAD_BUTTON_START;
if (b2 & (1 << 1))
pad.button |= PAD_TRIGGER_Z;
if (b2 & (1 << 2))
pad.button |= PAD_TRIGGER_R;
if (b2 & (1 << 3))
pad.button |= PAD_TRIGGER_L;

if (get_origin)
pad.button |= PAD_GET_ORIGIN;

pad.stickX = controller_payload_copy[1 + (9 * chan) + 3];
pad.stickY = controller_payload_copy[1 + (9 * chan) + 4];
pad.substickX = controller_payload_copy[1 + (9 * chan) + 5];
pad.substickY = controller_payload_copy[1 + (9 * chan) + 6];
pad.triggerLeft = controller_payload_copy[1 + (9 * chan) + 7];
pad.triggerRight = controller_payload_copy[1 + (9 * chan) + 8];
}
else if (!Core::WantsDeterminism())
{
// This is a hack to prevent a desync due to SI devices
// being different and returning different values.
// The corresponding code in DeviceGCAdapter has the same check
pad.button = PAD_ERR_STATUS;
}
NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1,
pd.status);
get_origin = true;
}
*/

u8 b1 = pd.buttons1;
u8 b2 = pd.buttons2;

if (b1 & (1 << 0))
pad.button |= PAD_BUTTON_A;
if (b1 & (1 << 1))
pad.button |= PAD_BUTTON_B;
if (b1 & (1 << 2))
pad.button |= PAD_BUTTON_X;
if (b1 & (1 << 3))
pad.button |= PAD_BUTTON_Y;

if (b1 & (1 << 4))
pad.button |= PAD_BUTTON_LEFT;
if (b1 & (1 << 5))
pad.button |= PAD_BUTTON_RIGHT;
if (b1 & (1 << 6))
pad.button |= PAD_BUTTON_DOWN;
if (b1 & (1 << 7))
pad.button |= PAD_BUTTON_UP;

if (b2 & (1 << 0))
pad.button |= PAD_BUTTON_START;
if (b2 & (1 << 1))
pad.button |= PAD_TRIGGER_Z;
if (b2 & (1 << 2))
pad.button |= PAD_TRIGGER_R;
if (b2 & (1 << 3))
pad.button |= PAD_TRIGGER_L;

pad.stickX = pd.stickX;
pad.stickY = pd.stickY;
pad.substickX = pd.substickX;
pad.substickY = pd.substickY;
pad.triggerLeft = pd.triggerL;
pad.triggerRight = pd.triggerR;

return pad;
}

bool DeviceConnected(int chan)
{
int payload_size = 0;
u8 controller_payload_copy[37];

poll_data pd;
{
std::lock_guard<std::mutex> lk(s_mutex);
std::copy(std::begin(s_controller_payload), std::end(s_controller_payload),
std::begin(controller_payload_copy));
payload_size = s_controller_payload_size.load();
std::lock_guard<std::mutex> lk(s_poll_mutex);
pd = s_controller_payload[chan];
}

if (payload_size != sizeof(controller_payload_copy) ||
controller_payload_copy[0] != LIBUSB_DT_HID)
u8 type = pd.status >> 4;
if (type == ControllerTypes::CONTROLLER_NONE)
{
ERROR_LOG(SERIALINTERFACE, "error reading payload (size: %d, type: %02x)", payload_size,
controller_payload_copy[0]);
Reset();
if (s_controller_type[chan] != ControllerTypes::CONTROLLER_NONE)
{
NOTICE_LOG(SERIALINTERFACE, "Device disconnected from Port %d", chan + 1);
s_controller_type[chan] = ControllerTypes::CONTROLLER_NONE;
}
return false;
}

u8 type = controller_payload_copy[1 + (9 * chan)] >> 4;
if (s_controller_type[chan] == ControllerTypes::CONTROLLER_NONE)
{
NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1,
pd.status);
s_controller_origin[chan].stickX = pd.stickX;
s_controller_origin[chan].stickY = pd.stickY;
s_controller_origin[chan].substickX = pd.substickX;
s_controller_origin[chan].substickY = pd.substickY;
s_controller_origin[chan].triggerL = pd.triggerL;
s_controller_origin[chan].triggerR = pd.triggerR;
s_controller_type[chan] = type;
}

return type != ControllerTypes::CONTROLLER_NONE;
return true;
}

void ResetDeviceType(int chan)
Expand Down Expand Up @@ -594,4 +609,9 @@ bool IsDetected(const char** error_message)
return false;
}

void GetOrigin(int chan, origin_data* origin)
{
*origin = s_controller_origin[chan];
}

} // end of namespace GCAdapter
11 changes: 11 additions & 0 deletions Source/Core/InputCommon/GCAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ enum ControllerTypes
CONTROLLER_WIRED = 1,
CONTROLLER_WIRELESS = 2
};
struct origin_data
{
u8 stickX;
u8 stickY;
u8 substickX;
u8 substickY;
u8 triggerL;
u8 triggerR;
};

void Init();
void ResetRumble();
void Shutdown();
Expand All @@ -30,5 +40,6 @@ bool IsDetected(const char** error_message);
bool DeviceConnected(int chan);
void ResetDeviceType(int chan);
bool UseAdapter();
void GetOrigin(int chan, origin_data* origin);

} // end of namespace GCAdapter

0 comments on commit 16d12f5

Please sign in to comment.