Add support for buffered DirectInput data to reduce polling load when it is supported. Only attempt setting a DirectInput device's axis mode if the device reports having axes and its axis mode is not already set to absolute. If the axis mode still can't be set to absolute, blacklist the device so that any future attempts will abort early. This should help when dealing with broken device drivers that report being game controllers and not fully supporting game controller functionality.
This commit is contained in:
parent
95c98093e9
commit
3557c46ae6
@ -80,6 +80,17 @@ namespace
|
|||||||
|
|
||||||
typedef std::vector<JoystickRecord> JoystickList;
|
typedef std::vector<JoystickRecord> JoystickList;
|
||||||
JoystickList joystickList;
|
JoystickList joystickList;
|
||||||
|
|
||||||
|
struct JoystickBlacklistEntry
|
||||||
|
{
|
||||||
|
unsigned int vendorId;
|
||||||
|
unsigned int productId;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<JoystickBlacklistEntry> JoystickBlacklist;
|
||||||
|
JoystickBlacklist joystickBlacklist;
|
||||||
|
|
||||||
|
const DWORD directInputEventBufferSize = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -330,7 +341,16 @@ Joystick::Identification JoystickImpl::getIdentification() const
|
|||||||
JoystickState JoystickImpl::update()
|
JoystickState JoystickImpl::update()
|
||||||
{
|
{
|
||||||
if (directInput)
|
if (directInput)
|
||||||
return updateDInput();
|
{
|
||||||
|
if (m_buffered)
|
||||||
|
{
|
||||||
|
return updateDInputBuffered();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return updateDInputPolled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JoystickState state;
|
JoystickState state;
|
||||||
|
|
||||||
@ -391,7 +411,7 @@ void JoystickImpl::initializeDInput()
|
|||||||
// Try to acquire a DirectInput 8.x interface
|
// Try to acquire a DirectInput 8.x interface
|
||||||
HRESULT result = directInput8Create(GetModuleHandleW(NULL), 0x0800, guids::IID_IDirectInput8W, reinterpret_cast<void**>(&directInput), NULL);
|
HRESULT result = directInput8Create(GetModuleHandleW(NULL), 0x0800, guids::IID_IDirectInput8W, reinterpret_cast<void**>(&directInput), NULL);
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
// De-initialize everything
|
// De-initialize everything
|
||||||
directInput = NULL;
|
directInput = NULL;
|
||||||
@ -460,7 +480,7 @@ void JoystickImpl::updateConnectionsDInput()
|
|||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
err() << "Failed to enumerate DirectInput devices: " << result << std::endl;
|
err() << "Failed to enumerate DirectInput devices: " << result << std::endl;
|
||||||
|
|
||||||
@ -499,6 +519,8 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
|
|
||||||
std::memset(&m_deviceCaps, 0, sizeof(DIDEVCAPS));
|
std::memset(&m_deviceCaps, 0, sizeof(DIDEVCAPS));
|
||||||
m_deviceCaps.dwSize = sizeof(DIDEVCAPS);
|
m_deviceCaps.dwSize = sizeof(DIDEVCAPS);
|
||||||
|
m_state = JoystickState();
|
||||||
|
m_buffered = false;
|
||||||
|
|
||||||
// Search for a joystick with the given index in the connected list
|
// Search for a joystick with the given index in the connected list
|
||||||
for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end(); ++i)
|
for (std::vector<JoystickRecord>::iterator i = joystickList.begin(); i != joystickList.end(); ++i)
|
||||||
@ -508,13 +530,54 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
// Create device
|
// Create device
|
||||||
HRESULT result = directInput->CreateDevice(i->guid, &m_device, NULL);
|
HRESULT result = directInput->CreateDevice(i->guid, &m_device, NULL);
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
err() << "Failed to create DirectInput device: " << result << std::endl;
|
err() << "Failed to create DirectInput device: " << result << std::endl;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get vendor and product id of the device
|
||||||
|
DIPROPDWORD property;
|
||||||
|
std::memset(&property, 0, sizeof(property));
|
||||||
|
property.diph.dwSize = sizeof(property);
|
||||||
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
|
||||||
|
if (SUCCEEDED(m_device->GetProperty(DIPROP_VIDPID, &property.diph)))
|
||||||
|
{
|
||||||
|
m_identification.productId = HIWORD(property.dwData);
|
||||||
|
m_identification.vendorId = LOWORD(property.dwData);
|
||||||
|
|
||||||
|
// Check if device is already blacklisted
|
||||||
|
if (m_identification.productId && m_identification.vendorId)
|
||||||
|
{
|
||||||
|
for (JoystickBlacklist::const_iterator iter = joystickBlacklist.begin(); iter != joystickBlacklist.end(); ++iter)
|
||||||
|
{
|
||||||
|
if ((m_identification.productId == iter->productId) &&
|
||||||
|
(m_identification.vendorId == iter->vendorId))
|
||||||
|
{
|
||||||
|
// Device is blacklisted
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get friendly product name of the device
|
||||||
|
DIPROPSTRING stringProperty;
|
||||||
|
std::memset(&stringProperty, 0, sizeof(stringProperty));
|
||||||
|
stringProperty.diph.dwSize = sizeof(stringProperty);
|
||||||
|
stringProperty.diph.dwHeaderSize = sizeof(stringProperty.diph);
|
||||||
|
stringProperty.diph.dwHow = DIPH_DEVICE;
|
||||||
|
stringProperty.diph.dwObj = 0;
|
||||||
|
|
||||||
|
if (SUCCEEDED(m_device->GetProperty(DIPROP_PRODUCTNAME, &stringProperty.diph)))
|
||||||
|
m_identification.name = stringProperty.wsz;
|
||||||
|
|
||||||
static bool formatInitialized = false;
|
static bool formatInitialized = false;
|
||||||
static DIDATAFORMAT format;
|
static DIDATAFORMAT format;
|
||||||
|
|
||||||
@ -524,59 +587,80 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
const DWORD povType = DIDFT_POV | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
const DWORD povType = DIDFT_POV | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
||||||
const DWORD buttonType = DIDFT_BUTTON | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
const DWORD buttonType = DIDFT_BUTTON | DIDFT_OPTIONAL | DIDFT_ANYINSTANCE;
|
||||||
|
|
||||||
static DIOBJECTDATAFORMAT data[8 + 4 + sf::Joystick::ButtonCount];
|
static DIOBJECTDATAFORMAT data[8 * 4 + 4 + sf::Joystick::ButtonCount];
|
||||||
|
|
||||||
data[0].pguid = &guids::GUID_XAxis;
|
for (int i = 0; i < 4; ++i)
|
||||||
data[0].dwOfs = DIJOFS_X;
|
{
|
||||||
|
data[8 * i + 0].pguid = &guids::GUID_XAxis;
|
||||||
|
data[8 * i + 1].pguid = &guids::GUID_YAxis;
|
||||||
|
data[8 * i + 2].pguid = &guids::GUID_ZAxis;
|
||||||
|
data[8 * i + 3].pguid = &guids::GUID_RxAxis;
|
||||||
|
data[8 * i + 4].pguid = &guids::GUID_RyAxis;
|
||||||
|
data[8 * i + 5].pguid = &guids::GUID_RzAxis;
|
||||||
|
data[8 * i + 6].pguid = &guids::GUID_Slider;
|
||||||
|
data[8 * i + 7].pguid = &guids::GUID_Slider;
|
||||||
|
}
|
||||||
|
|
||||||
data[1].pguid = &guids::GUID_YAxis;
|
data[ 0].dwOfs = DIJOFS_X;
|
||||||
data[1].dwOfs = DIJOFS_Y;
|
data[ 1].dwOfs = DIJOFS_Y;
|
||||||
|
data[ 2].dwOfs = DIJOFS_Z;
|
||||||
|
data[ 3].dwOfs = DIJOFS_RX;
|
||||||
|
data[ 4].dwOfs = DIJOFS_RY;
|
||||||
|
data[ 5].dwOfs = DIJOFS_RZ;
|
||||||
|
data[ 6].dwOfs = DIJOFS_SLIDER(0);
|
||||||
|
data[ 7].dwOfs = DIJOFS_SLIDER(1);
|
||||||
|
data[ 8].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lVX);
|
||||||
|
data[ 9].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lVY);
|
||||||
|
data[10].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lVZ);
|
||||||
|
data[11].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lVRx);
|
||||||
|
data[12].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lVRy);
|
||||||
|
data[13].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lVRz);
|
||||||
|
data[14].dwOfs = FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]);
|
||||||
|
data[15].dwOfs = FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]);
|
||||||
|
data[16].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lAX);
|
||||||
|
data[17].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lAY);
|
||||||
|
data[18].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lAZ);
|
||||||
|
data[19].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lARx);
|
||||||
|
data[20].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lARy);
|
||||||
|
data[21].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lARz);
|
||||||
|
data[22].dwOfs = FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]);
|
||||||
|
data[23].dwOfs = FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]);
|
||||||
|
data[24].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lFX);
|
||||||
|
data[25].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lFY);
|
||||||
|
data[26].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lFZ);
|
||||||
|
data[27].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lFRx);
|
||||||
|
data[28].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lFRy);
|
||||||
|
data[29].dwOfs = FIELD_OFFSET(DIJOYSTATE2, lFRz);
|
||||||
|
data[30].dwOfs = FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]);
|
||||||
|
data[31].dwOfs = FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]);
|
||||||
|
|
||||||
data[2].pguid = &guids::GUID_ZAxis;
|
for (int i = 0; i < 8 * 4; ++i)
|
||||||
data[2].dwOfs = DIJOFS_Z;
|
|
||||||
|
|
||||||
data[3].pguid = &guids::GUID_RxAxis;
|
|
||||||
data[3].dwOfs = DIJOFS_RX;
|
|
||||||
|
|
||||||
data[4].pguid = &guids::GUID_RyAxis;
|
|
||||||
data[4].dwOfs = DIJOFS_RY;
|
|
||||||
|
|
||||||
data[5].pguid = &guids::GUID_RzAxis;
|
|
||||||
data[5].dwOfs = DIJOFS_RZ;
|
|
||||||
|
|
||||||
data[6].pguid = &guids::GUID_Slider;
|
|
||||||
data[6].dwOfs = DIJOFS_SLIDER(0);
|
|
||||||
|
|
||||||
data[7].pguid = &guids::GUID_Slider;
|
|
||||||
data[7].dwOfs = DIJOFS_SLIDER(1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
|
||||||
{
|
{
|
||||||
data[i].dwType = axisType;
|
data[i].dwType = axisType;
|
||||||
data[i].dwFlags = DIDOI_ASPECTPOSITION;
|
data[i].dwFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
data[8 + i].pguid = &guids::GUID_POV;
|
data[8 * 4 + i].pguid = &guids::GUID_POV;
|
||||||
data[8 + i].dwOfs = static_cast<DWORD>(DIJOFS_POV(i));
|
data[8 * 4 + i].dwOfs = static_cast<DWORD>(DIJOFS_POV(i));
|
||||||
data[8 + i].dwType = povType;
|
data[8 * 4 + i].dwType = povType;
|
||||||
data[8 + i].dwFlags = 0;
|
data[8 * 4 + i].dwFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sf::Joystick::ButtonCount; ++i)
|
for (int i = 0; i < sf::Joystick::ButtonCount; ++i)
|
||||||
{
|
{
|
||||||
data[8 + 4 + i].pguid = NULL;
|
data[8 * 4 + 4 + i].pguid = NULL;
|
||||||
data[8 + 4 + i].dwOfs = static_cast<DWORD>(DIJOFS_BUTTON(i));
|
data[8 * 4 + 4 + i].dwOfs = static_cast<DWORD>(DIJOFS_BUTTON(i));
|
||||||
data[8 + 4 + i].dwType = buttonType;
|
data[8 * 4 + 4 + i].dwType = buttonType;
|
||||||
data[8 + 4 + i].dwFlags = 0;
|
data[8 * 4 + 4 + i].dwFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
format.dwSize = sizeof(DIDATAFORMAT);
|
format.dwSize = sizeof(DIDATAFORMAT);
|
||||||
format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
|
format.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
|
||||||
format.dwFlags = DIDFT_ABSAXIS;
|
format.dwFlags = DIDFT_ABSAXIS;
|
||||||
format.dwDataSize = sizeof(DIJOYSTATE);
|
format.dwDataSize = sizeof(DIJOYSTATE2);
|
||||||
format.dwNumObjs = 8 + 4 + sf::Joystick::ButtonCount;
|
format.dwNumObjs = 8 * 4 + 4 + sf::Joystick::ButtonCount;
|
||||||
format.rgodf = data;
|
format.rgodf = data;
|
||||||
|
|
||||||
formatInitialized = true;
|
formatInitialized = true;
|
||||||
@ -585,7 +669,7 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
// Set device data format
|
// Set device data format
|
||||||
result = m_device->SetDataFormat(&format);
|
result = m_device->SetDataFormat(&format);
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
err() << "Failed to set DirectInput device data format: " << result << std::endl;
|
err() << "Failed to set DirectInput device data format: " << result << std::endl;
|
||||||
|
|
||||||
@ -598,7 +682,7 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
// Get device capabilities
|
// Get device capabilities
|
||||||
result = m_device->GetCapabilities(&m_deviceCaps);
|
result = m_device->GetCapabilities(&m_deviceCaps);
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
err() << "Failed to get DirectInput device capabilities: " << result << std::endl;
|
err() << "Failed to get DirectInput device capabilities: " << result << std::endl;
|
||||||
|
|
||||||
@ -608,30 +692,10 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set axis mode to absolute
|
|
||||||
DIPROPDWORD property;
|
|
||||||
std::memset(&property, 0, sizeof(property));
|
|
||||||
property.diph.dwSize = sizeof(property);
|
|
||||||
property.diph.dwHeaderSize = sizeof(property.diph);
|
|
||||||
property.diph.dwHow = DIPH_DEVICE;
|
|
||||||
property.dwData = DIPROPAXISMODE_ABS;
|
|
||||||
|
|
||||||
result = m_device->SetProperty(DIPROP_AXISMODE, &property.diph);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
err() << "Failed to set DirectInput device axis mode: " << result << std::endl;
|
|
||||||
|
|
||||||
m_device->Release();
|
|
||||||
m_device = NULL;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enumerate device objects (axes/povs/buttons)
|
// Enumerate device objects (axes/povs/buttons)
|
||||||
result = m_device->EnumObjects(&JoystickImpl::deviceObjectEnumerationCallback, this, DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
result = m_device->EnumObjects(&JoystickImpl::deviceObjectEnumerationCallback, this, DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
err() << "Failed to enumerate DirectInput device objects: " << result << std::endl;
|
err() << "Failed to enumerate DirectInput device objects: " << result << std::endl;
|
||||||
|
|
||||||
@ -641,29 +705,116 @@ bool JoystickImpl::openDInput(unsigned int index)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get friendly product name of the device
|
// Set device's axis mode to absolute if the device reports having at least one axis
|
||||||
DIPROPSTRING stringProperty;
|
for (int i = 0; i < Joystick::AxisCount; ++i)
|
||||||
std::memset(&stringProperty, 0, sizeof(stringProperty));
|
|
||||||
stringProperty.diph.dwSize = sizeof(stringProperty);
|
|
||||||
stringProperty.diph.dwHeaderSize = sizeof(stringProperty.diph);
|
|
||||||
stringProperty.diph.dwHow = DIPH_DEVICE;
|
|
||||||
stringProperty.diph.dwObj = 0;
|
|
||||||
|
|
||||||
if (!m_device->GetProperty(DIPROP_PRODUCTNAME, &stringProperty.diph))
|
|
||||||
{
|
{
|
||||||
m_identification.name = stringProperty.wsz;
|
if (m_axes[i] != -1)
|
||||||
|
{
|
||||||
|
std::memset(&property, 0, sizeof(property));
|
||||||
|
property.diph.dwSize = sizeof(property);
|
||||||
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
property.diph.dwObj = 0;
|
||||||
|
|
||||||
|
result = m_device->GetProperty(DIPROP_AXISMODE, &property.diph);
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
err() << "Failed to get DirectInput device axis mode for device \""
|
||||||
|
<< m_identification.name.toAnsiString() << "\": " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the axis mode is already set to absolute we don't need to set it again ourselves
|
||||||
|
if (property.dwData == DIPROPAXISMODE_ABS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::memset(&property, 0, sizeof(property));
|
||||||
|
property.diph.dwSize = sizeof(property);
|
||||||
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
property.dwData = DIPROPAXISMODE_ABS;
|
||||||
|
|
||||||
|
m_device->SetProperty(DIPROP_AXISMODE, &property.diph);
|
||||||
|
|
||||||
|
// Check if the axis mode has been set to absolute
|
||||||
|
std::memset(&property, 0, sizeof(property));
|
||||||
|
property.diph.dwSize = sizeof(property);
|
||||||
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
property.diph.dwObj = 0;
|
||||||
|
|
||||||
|
result = m_device->GetProperty(DIPROP_AXISMODE, &property.diph);
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
err() << "Failed to verify DirectInput device axis mode for device \""
|
||||||
|
<< m_identification.name.toAnsiString() << "\": " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the axis mode hasn't been set to absolute fail here and blacklist the device
|
||||||
|
if (property.dwData != DIPROPAXISMODE_ABS)
|
||||||
|
{
|
||||||
|
if (m_identification.vendorId && m_identification.productId)
|
||||||
|
{
|
||||||
|
JoystickBlacklistEntry entry;
|
||||||
|
|
||||||
|
entry.vendorId = m_identification.vendorId;
|
||||||
|
entry.productId = m_identification.productId;
|
||||||
|
|
||||||
|
joystickBlacklist.push_back(entry);
|
||||||
|
|
||||||
|
// Pre-C++11 shrink_to_fit()
|
||||||
|
JoystickBlacklist(joystickBlacklist.begin(), joystickBlacklist.end()).swap(joystickBlacklist);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get vendor and produce id of the device
|
// Try to enable buffering by setting the buffer size
|
||||||
std::memset(&property, 0, sizeof(property));
|
std::memset(&property, 0, sizeof(property));
|
||||||
property.diph.dwSize = sizeof(property);
|
property.diph.dwSize = sizeof(property);
|
||||||
property.diph.dwHeaderSize = sizeof(property.diph);
|
property.diph.dwHeaderSize = sizeof(property.diph);
|
||||||
property.diph.dwHow = DIPH_DEVICE;
|
property.diph.dwHow = DIPH_DEVICE;
|
||||||
|
property.dwData = directInputEventBufferSize;
|
||||||
|
|
||||||
if (!m_device->GetProperty(DIPROP_VIDPID, &property.diph))
|
result = m_device->SetProperty(DIPROP_BUFFERSIZE, &property.diph);
|
||||||
|
|
||||||
|
if (result == DI_OK)
|
||||||
{
|
{
|
||||||
m_identification.productId = HIWORD(property.dwData);
|
// Buffering supported
|
||||||
m_identification.vendorId = LOWORD(property.dwData);
|
m_buffered = true;
|
||||||
|
}
|
||||||
|
else if (result == DI_POLLEDDEVICE)
|
||||||
|
{
|
||||||
|
// Only polling supported
|
||||||
|
m_buffered = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err() << "Failed to set DirectInput device buffer size for device \""
|
||||||
|
<< m_identification.name.toAnsiString() << "\": " << result << std::endl;
|
||||||
|
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -709,7 +860,113 @@ JoystickCaps JoystickImpl::getCapabilitiesDInput() const
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
JoystickState JoystickImpl::updateDInput()
|
JoystickState JoystickImpl::updateDInputBuffered()
|
||||||
|
{
|
||||||
|
// If we don't make it to the end of this function, mark the device as disconnected
|
||||||
|
m_state.connected = false;
|
||||||
|
|
||||||
|
if (!m_device)
|
||||||
|
return m_state;
|
||||||
|
|
||||||
|
DIDEVICEOBJECTDATA events[directInputEventBufferSize];
|
||||||
|
DWORD eventCount = directInputEventBufferSize;
|
||||||
|
|
||||||
|
// Try to get the device data
|
||||||
|
HRESULT result = m_device->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), events, &eventCount, 0);
|
||||||
|
|
||||||
|
// If we have not acquired or have lost the device, attempt to (re-)acquire it and get the device data again
|
||||||
|
if ((result == DIERR_NOTACQUIRED) || (result == DIERR_INPUTLOST))
|
||||||
|
{
|
||||||
|
m_device->Acquire();
|
||||||
|
result = m_device->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), events, &eventCount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still can't get the device data, assume it has been disconnected
|
||||||
|
if ((result == DIERR_NOTACQUIRED) || (result == DIERR_INPUTLOST))
|
||||||
|
{
|
||||||
|
m_device->Release();
|
||||||
|
m_device = NULL;
|
||||||
|
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(result))
|
||||||
|
{
|
||||||
|
err() << "Failed to get DirectInput device data: " << result << std::endl;
|
||||||
|
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate through all buffered events
|
||||||
|
for (DWORD i = 0; i < eventCount; ++i)
|
||||||
|
{
|
||||||
|
bool eventHandled = false;
|
||||||
|
|
||||||
|
// Get the current state of each axis
|
||||||
|
for (int j = 0; j < Joystick::AxisCount; ++j)
|
||||||
|
{
|
||||||
|
if (m_axes[j] == events[i].dwOfs)
|
||||||
|
{
|
||||||
|
if (j == Joystick::PovX)
|
||||||
|
{
|
||||||
|
unsigned short value = LOWORD(events[i].dwData);
|
||||||
|
|
||||||
|
if (value != 0xFFFF)
|
||||||
|
{
|
||||||
|
float angle = (static_cast<float>(value)) * 3.141592654f / DI_DEGREES / 180.f;
|
||||||
|
|
||||||
|
m_state.axes[j] = std::sin(angle) * 100.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_state.axes[j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (j == Joystick::PovY)
|
||||||
|
{
|
||||||
|
unsigned short value = LOWORD(events[i].dwData);
|
||||||
|
|
||||||
|
if (value != 0xFFFF)
|
||||||
|
{
|
||||||
|
float angle = (static_cast<float>(value)) * 3.141592654f / DI_DEGREES / 180.f;
|
||||||
|
|
||||||
|
m_state.axes[j] = std::cos(angle) * 100.f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_state.axes[j] = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_state.axes[j] = (static_cast<float>(static_cast<short>(events[i].dwData)) + 0.5f) * 100.f / 32767.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
eventHandled = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventHandled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get the current state of each button
|
||||||
|
for (int j = 0; j < Joystick::ButtonCount; ++j)
|
||||||
|
{
|
||||||
|
if (m_buttons[j] == events[i].dwOfs)
|
||||||
|
m_state.buttons[j] = (events[i].dwData != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_state.connected = true;
|
||||||
|
|
||||||
|
return m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
JoystickState JoystickImpl::updateDInputPolled()
|
||||||
{
|
{
|
||||||
JoystickState state;
|
JoystickState state;
|
||||||
|
|
||||||
@ -718,7 +975,7 @@ JoystickState JoystickImpl::updateDInput()
|
|||||||
// Poll the device
|
// Poll the device
|
||||||
m_device->Poll();
|
m_device->Poll();
|
||||||
|
|
||||||
DIJOYSTATE joystate;
|
DIJOYSTATE2 joystate;
|
||||||
|
|
||||||
// Try to get the device state
|
// Try to get the device state
|
||||||
HRESULT result = m_device->GetDeviceState(sizeof(joystate), &joystate);
|
HRESULT result = m_device->GetDeviceState(sizeof(joystate), &joystate);
|
||||||
@ -740,7 +997,7 @@ JoystickState JoystickImpl::updateDInput()
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
err() << "Failed to get DirectInput device state: " << result << std::endl;
|
err() << "Failed to get DirectInput device state: " << result << std::endl;
|
||||||
|
|
||||||
@ -878,7 +1135,7 @@ BOOL CALLBACK JoystickImpl::deviceObjectEnumerationCallback(const DIDEVICEOBJECT
|
|||||||
|
|
||||||
HRESULT result = joystick.m_device->SetProperty(DIPROP_RANGE, &propertyRange.diph);
|
HRESULT result = joystick.m_device->SetProperty(DIPROP_RANGE, &propertyRange.diph);
|
||||||
|
|
||||||
if (result)
|
if (result != DI_OK)
|
||||||
err() << "Failed to set DirectInput device axis property range: " << result << std::endl;
|
err() << "Failed to set DirectInput device axis property range: " << result << std::endl;
|
||||||
|
|
||||||
return DIENUM_CONTINUE;
|
return DIENUM_CONTINUE;
|
||||||
|
@ -186,12 +186,20 @@ public:
|
|||||||
JoystickCaps getCapabilitiesDInput() const;
|
JoystickCaps getCapabilitiesDInput() const;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Update the joystick and get its new state (DInput)
|
/// \brief Update the joystick and get its new state (DInput, Buffered)
|
||||||
///
|
///
|
||||||
/// \return Joystick state
|
/// \return Joystick state
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
JoystickState updateDInput();
|
JoystickState updateDInputBuffered();
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
/// \brief Update the joystick and get its new state (DInput, Polled)
|
||||||
|
///
|
||||||
|
/// \return Joystick state
|
||||||
|
///
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
JoystickState updateDInputPolled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -227,6 +235,8 @@ private:
|
|||||||
int m_axes[Joystick::AxisCount]; //!< Offsets to the bytes containing the axes states, -1 if not available
|
int m_axes[Joystick::AxisCount]; //!< Offsets to the bytes containing the axes states, -1 if not available
|
||||||
int m_buttons[Joystick::ButtonCount]; //!< Offsets to the bytes containing the button states, -1 if not available
|
int m_buttons[Joystick::ButtonCount]; //!< Offsets to the bytes containing the button states, -1 if not available
|
||||||
Joystick::Identification m_identification; //!< Joystick identification
|
Joystick::Identification m_identification; //!< Joystick identification
|
||||||
|
JoystickState m_state; //!< Buffered joystick state
|
||||||
|
bool m_buffered; //!< true if the device uses buffering, false if the device uses polling
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
Loading…
Reference in New Issue
Block a user