XInput_Scp/BTConnection.cpp (269 lines of code) (raw):

#include "StdAfx.h" CBTConnection::CBTConnection(void) { WSADATA wsaData; CollectionSize = 0; m_bInited = false; sockaddr_in Control, Report; Control.sin_family = AF_INET; Control.sin_addr.s_addr = inet_addr("127.0.0.1"); Control.sin_port = htons(ControlPort); Report.sin_family = AF_INET; Report.sin_addr.s_addr = inet_addr("127.0.0.1"); Report.sin_port = htons(ReportPort); for (int Index = 0; Index < 4; Index++) { memset(&(m_padState [Index]), 0, sizeof(XINPUT_STATE)); memset(&(m_padVibration[Index]), 0, sizeof(XINPUT_VIBRATION)); memset(&(m_Extended [Index]), 0, sizeof(SCP_EXTN)); } if (WSAStartup(MAKEWORD(2, 2), &wsaData) == NO_ERROR) { if ((m_Control = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { WSACleanup(); return; } if (connect(m_Control, (SOCKADDR*) &Control, sizeof(Control)) == SOCKET_ERROR) { closesocket(m_Control); WSACleanup(); return; } if ((m_Report = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { closesocket(m_Control); WSACleanup(); return; } if (bind(m_Report, (SOCKADDR*) &Report, sizeof(Report)) == SOCKET_ERROR) { closesocket(m_Control); closesocket(m_Report); WSACleanup(); return; } } m_bInited = true; } BOOL CBTConnection::Open() { UCHAR Buffer[6]; Buffer[0] = 0; Buffer[1] = 0; if (m_bInited) { CollectionSize = 0; if (send(m_Control, (CHAR*) Buffer, 6, 0) != SOCKET_ERROR) { if (recv(m_Control, (CHAR*) Buffer, 6, 0) > 0) { for (int Index = 2; Index < 6; Index++) { if (Buffer[Index] > 0) CollectionSize++; } } } } if (CollectionSize > 0) { m_bConnected = m_xConnected = true; _beginthread(ReadThread, 0, this); } return CollectionSize > 0; } BOOL CBTConnection::Close() { if (m_bInited) { m_bInited = m_bConnected = m_xConnected = false; try { closesocket(m_Control); closesocket(m_Report); WSACleanup(); } catch (...) { } } return !m_bConnected; } void CBTConnection::Report(DWORD dwUserIndex) { UCHAR Buffer[4]; Buffer[0] = (UCHAR) dwUserIndex; Buffer[1] = 0x01; Buffer[2] = m_padVibration[dwUserIndex].wLeftMotorSpeed >> 8; Buffer[3] = m_padVibration[dwUserIndex].wRightMotorSpeed >> 8; if (m_bConnected) { send(m_Control, (CHAR*) Buffer, 4, 0); } } BOOL CBTConnection::Read(UCHAR* Buffer) { int bRead = 0; if (m_bConnected) { bRead = recv(m_Report, (CHAR*) Buffer, 96, 0); } return bRead > 0; } void CBTConnection::ReadThread(void *lpController) { CBTConnection* Pad = (CBTConnection *) lpController; UCHAR Buffer[96]; while (Pad->m_bConnected) { if (Pad->Read(Buffer)) { if (Buffer[1] == 2) { Pad->XInputMapState(Buffer[0], &Buffer[8], Buffer[89]); } else { memset(&(Pad->m_padState [Buffer[0]]), 0, sizeof(XINPUT_STATE)); memset(&(Pad->m_padVibration[Buffer[0]]), 0, sizeof(XINPUT_VIBRATION)); memset(&(Pad->m_Extended [Buffer[0]]), 0, sizeof(SCP_EXTN)); } } else { Pad->m_bConnected = false; } } _endthread(); } void CBTConnection::XInputMapState(DWORD Pad, UCHAR* Report, UCHAR Model) { m_padState[Pad].Gamepad.wButtons = 0; if (Model == 1) // DS3 { DWORD Buttons = Report[2] << 0 | Report[3] << 8 | Report[4] << 16 | Report[5] << 24; if (Buttons & (0x1 << 0)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; if (Buttons & (0x1 << 1)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; if (Buttons & (0x1 << 2)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; if (Buttons & (0x1 << 3)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_START; if (Buttons & (0x1 << 4)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; if (Buttons & (0x1 << 5)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; if (Buttons & (0x1 << 6)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; if (Buttons & (0x1 << 7)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; if (Buttons & (0x1 << 10)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; if (Buttons & (0x1 << 11)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; if (Buttons & (0x1 << 12)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_Y; if (Buttons & (0x1 << 13)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_B; if (Buttons & (0x1 << 14)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_A; if (Buttons & (0x1 << 15)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_X; if (Buttons & (0x1 << 16)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; m_padState[Pad].Gamepad.sThumbRY = -Scale((SHORT) Report[9]); m_padState[Pad].Gamepad.sThumbRX = Scale((SHORT) Report[8]); m_padState[Pad].Gamepad.sThumbLY = -Scale((SHORT) Report[7]); m_padState[Pad].Gamepad.sThumbLX = Scale((SHORT) Report[6]); // Remap for Triggers - Not Unpacked as Axis by UnpackReport m_padState[Pad].Gamepad.bLeftTrigger = Report[18]; m_padState[Pad].Gamepad.bRightTrigger = Report[19]; // Convert for Extension m_Extended[Pad].SCP_UP = ToPressure(Report[14]); m_Extended[Pad].SCP_RIGHT = ToPressure(Report[15]); m_Extended[Pad].SCP_DOWN = ToPressure(Report[16]); m_Extended[Pad].SCP_LEFT = ToPressure(Report[17]); m_Extended[Pad].SCP_LX = ToAxis(m_padState[Pad].Gamepad.sThumbLX); m_Extended[Pad].SCP_LY = ToAxis(m_padState[Pad].Gamepad.sThumbLY); m_Extended[Pad].SCP_L1 = ToPressure(Report[20]); m_Extended[Pad].SCP_L2 = ToPressure(Report[18]); m_Extended[Pad].SCP_L3 = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? 1.0f : 0.0f; m_Extended[Pad].SCP_RX = ToAxis(m_padState[Pad].Gamepad.sThumbRX); m_Extended[Pad].SCP_RY = ToAxis(m_padState[Pad].Gamepad.sThumbRY); m_Extended[Pad].SCP_R1 = ToPressure(Report[21]); m_Extended[Pad].SCP_R2 = ToPressure(Report[19]); m_Extended[Pad].SCP_R3 = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? 1.0f : 0.0f; m_Extended[Pad].SCP_T = ToPressure(Report[22]); m_Extended[Pad].SCP_C = ToPressure(Report[23]); m_Extended[Pad].SCP_X = ToPressure(Report[24]); m_Extended[Pad].SCP_S = ToPressure(Report[25]); m_Extended[Pad].SCP_SELECT = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? 1.0f : 0.0f; m_Extended[Pad].SCP_START = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_START ? 1.0f : 0.0f; m_Extended[Pad].SCP_PS = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE ? 1.0f : 0.0f; } if (Model == 2) // DS4 { DWORD Buttons = Report[5] << 0 | Report[6] << 8 | Report[7] << 16; if (Buttons & (0x1 << 12)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; if (Buttons & (0x1 << 14)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; if (Buttons & (0x1 << 15)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; if (Buttons & (0x1 << 13)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_START; if (Buttons & (0x1 << 0)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP; if (Buttons & (0x1 << 1)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT; if (Buttons & (0x1 << 2)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN; if (Buttons & (0x1 << 3)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; if (Buttons & (0x1 << 8)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; if (Buttons & (0x1 << 9)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; if (Buttons & (0x1 << 7)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_Y; if (Buttons & (0x1 << 6)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_B; if (Buttons & (0x1 << 5)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_A; if (Buttons & (0x1 << 4)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_X; if (Buttons & (0x1 << 16)) m_padState[Pad].Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; m_padState[Pad].Gamepad.sThumbRY = -Scale((SHORT) Report[4]); m_padState[Pad].Gamepad.sThumbRX = Scale((SHORT) Report[3]); m_padState[Pad].Gamepad.sThumbLY = -Scale((SHORT) Report[2]); m_padState[Pad].Gamepad.sThumbLX = Scale((SHORT) Report[1]); // Remap for Triggers m_padState[Pad].Gamepad.bLeftTrigger = Report[8]; m_padState[Pad].Gamepad.bRightTrigger = Report[9]; // Convert for Extension m_Extended[Pad].SCP_UP = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? 1.0f : 0.0f; m_Extended[Pad].SCP_RIGHT = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT ? 1.0f : 0.0f; m_Extended[Pad].SCP_DOWN = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ? 1.0f : 0.0f; m_Extended[Pad].SCP_LEFT = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ? 1.0f : 0.0f; m_Extended[Pad].SCP_LX = ToAxis(m_padState[Pad].Gamepad.sThumbLX); m_Extended[Pad].SCP_LY = ToAxis(m_padState[Pad].Gamepad.sThumbLY); m_Extended[Pad].SCP_L1 = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER ? 1.0f : 0.0f; m_Extended[Pad].SCP_L2 = ToPressure(Report[8]); m_Extended[Pad].SCP_L3 = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB ? 1.0f : 0.0f; m_Extended[Pad].SCP_RX = ToAxis(m_padState[Pad].Gamepad.sThumbRX); m_Extended[Pad].SCP_RY = ToAxis(m_padState[Pad].Gamepad.sThumbRY); m_Extended[Pad].SCP_R1 = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER ? 1.0f : 0.0f; m_Extended[Pad].SCP_R2 = ToPressure(Report[9]); m_Extended[Pad].SCP_R3 = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB ? 1.0f : 0.0f; m_Extended[Pad].SCP_T = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_Y ? 1.0f : 0.0f; m_Extended[Pad].SCP_C = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_B ? 1.0f : 0.0f; m_Extended[Pad].SCP_X = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_A ? 1.0f : 0.0f; m_Extended[Pad].SCP_S = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_X ? 1.0f : 0.0f; m_Extended[Pad].SCP_SELECT = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_BACK ? 1.0f : 0.0f; m_Extended[Pad].SCP_START = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_START ? 1.0f : 0.0f; m_Extended[Pad].SCP_PS = m_padState[Pad].Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE ? 1.0f : 0.0f; } } DWORD CBTConnection::GetState(DWORD dwUserIndex, XINPUT_STATE* pState) { if (m_bConnected) { m_padState[dwUserIndex].dwPacketNumber++; memcpy(pState, &(m_padState[dwUserIndex]), sizeof(XINPUT_STATE)); } return m_bConnected ? ERROR_SUCCESS : ERROR_DEVICE_NOT_CONNECTED; } DWORD CBTConnection::SetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration) { if (m_bConnected) { if ((pVibration->wLeftMotorSpeed != m_padVibration[dwUserIndex].wLeftMotorSpeed) || (pVibration->wRightMotorSpeed != m_padVibration[dwUserIndex].wRightMotorSpeed)) { m_padVibration[dwUserIndex].wRightMotorSpeed = pVibration->wRightMotorSpeed; m_padVibration[dwUserIndex].wLeftMotorSpeed = pVibration->wLeftMotorSpeed; Report(dwUserIndex); } } return m_bConnected ? ERROR_SUCCESS : ERROR_DEVICE_NOT_CONNECTED; } DWORD CBTConnection::GetExtended(DWORD dwUserIndex, SCP_EXTN* pPressure) { if (m_bConnected) { memcpy(pPressure, &m_Extended[dwUserIndex], sizeof(SCP_EXTN)); } return m_bConnected ? ERROR_SUCCESS : ERROR_DEVICE_NOT_CONNECTED;; } // UNDOCUMENTED DWORD CBTConnection::GetStateEx(DWORD dwUserIndex, XINPUT_STATE *pState) { return GetState(dwUserIndex, pState); }