[Orxonox-commit 945] r5668 - in code/branches/resource2/src/ois: . linux win32
rgrieder at orxonox.net
rgrieder at orxonox.net
Sat Aug 22 23:16:34 CEST 2009
Author: rgrieder
Date: 2009-08-22 23:16:34 +0200 (Sat, 22 Aug 2009)
New Revision: 5668
Modified:
code/branches/resource2/src/ois/OISEffect.cpp
code/branches/resource2/src/ois/OISEffect.h
code/branches/resource2/src/ois/OISForceFeedback.cpp
code/branches/resource2/src/ois/OISForceFeedback.h
code/branches/resource2/src/ois/OISJoyStick.h
code/branches/resource2/src/ois/OISPrereqs.h
code/branches/resource2/src/ois/linux/EventHelpers.cpp
code/branches/resource2/src/ois/linux/EventHelpers.h
code/branches/resource2/src/ois/linux/LinuxForceFeedback.cpp
code/branches/resource2/src/ois/linux/LinuxForceFeedback.h
code/branches/resource2/src/ois/linux/LinuxJoyStickEvents.cpp
code/branches/resource2/src/ois/win32/Win32ForceFeedback.cpp
code/branches/resource2/src/ois/win32/Win32ForceFeedback.h
code/branches/resource2/src/ois/win32/Win32InputManager.cpp
code/branches/resource2/src/ois/win32/Win32InputManager.h
code/branches/resource2/src/ois/win32/Win32JoyStick.cpp
code/branches/resource2/src/ois/win32/Win32JoyStick.h
code/branches/resource2/src/ois/win32/Win32KeyBoard.cpp
Log:
Updated OIS library (still 1.2, but CVS version).
There have been some little fixes and support for force feedback on Linux (but this doesn't concern us for now...)
Modified: code/branches/resource2/src/ois/OISEffect.cpp
===================================================================
--- code/branches/resource2/src/ois/OISEffect.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/OISEffect.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -30,6 +30,41 @@
//const unsigned int Effect::OIS_INFINITE = 0xFFFFFFFF;
//------------------------------------------------------------------------------//
+static const char* pszEForceString[] =
+ { "UnknownForce",
+ "ConstantForce",
+ "RampForce",
+ "PeriodicForce",
+ "ConditionalForce",
+ "CustomForce" };
+
+const char* Effect::getForceTypeName(Effect::EForce eValue)
+{
+ return (eValue >= 0 && eValue < _ForcesNumber) ? pszEForceString[eValue] : "<Bad force type>";
+}
+
+static const char* pszETypeString[] =
+ { "Unknown",
+ "Constant",
+ "Ramp",
+ "Square", "Triangle", "Sine", "SawToothUp", "SawToothDown",
+ "Friction", "Damper", "Inertia", "Spring",
+ "Custom" };
+
+const char* Effect::getEffectTypeName(Effect::EType eValue)
+{
+ return (eValue >= 0 && eValue < _TypesNumber) ? pszETypeString[eValue] : "<Bad effect type>";
+}
+
+static const char* pszEDirectionString[] =
+ { "NorthWest", "North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West"};
+
+const char* Effect::getDirectionName(Effect::EDirection eValue)
+{
+ return (eValue >= 0 && eValue < _DirectionsNumber) ? pszEDirectionString[eValue] : "<Bad direction>";
+}
+
+//------------------------------------------------------------------------------//
Effect::Effect() :
force(UnknownForce),
type(Unknown),
Modified: code/branches/resource2/src/ois/OISEffect.h
===================================================================
--- code/branches/resource2/src/ois/OISEffect.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/OISEffect.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -59,9 +59,12 @@
RampForce,
PeriodicForce,
ConditionalForce,
- CustomForce
+ CustomForce,
+ _ForcesNumber // Always keep in last position.
};
+ static const char* getForceTypeName(EForce eValue);
+
//! Type of effect
enum EType
{
@@ -78,9 +81,12 @@
Damper, //ConditionalForce
Inertia, //ConditionalForce
Spring, //ConditionalForce
- Custom //CustomForce
+ Custom, //CustomForce
+ _TypesNumber // Always keep in last position.
};
+ static const char* getEffectTypeName(EType eValue);
+
//! Direction of the Force
enum EDirection
{
@@ -91,9 +97,12 @@
SouthEast,
South,
SouthWest,
- West
+ West,
+ _DirectionsNumber // Always keep in last position.
};
+ static const char* getDirectionName(EDirection eValue);
+
/**
This constructor allows you to set the force type and effect.
*/
@@ -167,7 +176,7 @@
/**
An optional envelope to be applied to the start/end of an effect. If any of
these values are nonzero, then the envelope will be used in setting up the
- effect. Not currently utilised.. But, will be soon.
+ effect.
*/
class _OISExport Envelope : public ForceEffect
{
@@ -177,14 +186,23 @@
#pragma warning (push)
#pragma warning (disable : 4800)
#endif
- bool isUsed() { return attackLength | attackLevel | fadeLength | fadeLevel; }
+ bool isUsed() const { return attackLength | attackLevel | fadeLength | fadeLevel; }
#if defined(OIS_MSVC_COMPILER)
#pragma warning (pop)
#endif
- unsigned short attackLength;
+ // Duration of the attack (microseconds)
+ unsigned int attackLength;
+
+ // Absolute level at the beginning of the attack (0 to 10K)
+ // (automatically signed when necessary by FF core according to effect level sign)
unsigned short attackLevel;
- unsigned short fadeLength;
+
+ // Duration of fade (microseconds)
+ unsigned int fadeLength;
+
+ // Absolute level at the end of fade (0 to 10K)
+ // (automatically signed when necessary by FF core according to effect level sign)
unsigned short fadeLevel;
};
@@ -210,7 +228,7 @@
public:
RampEffect() : startLevel(0), endLevel(0) {}
- class Envelope envelope; //Optional envolope
+ class Envelope envelope; //Optional envelope
signed short startLevel; //-10K to +10k
signed short endLevel; //-10K to +10k
};
Modified: code/branches/resource2/src/ois/OISForceFeedback.cpp
===================================================================
--- code/branches/resource2/src/ois/OISForceFeedback.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/OISForceFeedback.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -26,17 +26,49 @@
using namespace OIS;
//-------------------------------------------------------------//
+ForceFeedback::ForceFeedback() : mSetGainSupport(false), mSetAutoCenterSupport(false)
+{
+}
+
+//-------------------------------------------------------------//
void ForceFeedback::_addEffectTypes( Effect::EForce force, Effect::EType type )
{
- if( force == Effect::UnknownForce || type == Effect::Unknown )
- OIS_EXCEPT( E_General, "Unknown Force||Type was added too effect list..." );
+ if( force <= Effect::UnknownForce || force >= Effect::_ForcesNumber
+ || type <= Effect::Unknown || type >= Effect::_TypesNumber )
+ OIS_EXCEPT( E_General, "Can't add unknown effect Force/Type to the supported list" );
- mSupportedEffects[force] = type;
+ mSupportedEffects.insert(std::pair<Effect::EForce, Effect::EType>(force, type));
}
//-------------------------------------------------------------//
-const ForceFeedback::SupportedEffectList&
- ForceFeedback::getSupportedEffects() const
+void ForceFeedback::_setGainSupport( bool on )
{
+ mSetGainSupport = on;
+}
+
+//-------------------------------------------------------------//
+void ForceFeedback::_setAutoCenterSupport( bool on )
+{
+ mSetAutoCenterSupport = on;
+}
+
+//-------------------------------------------------------------//
+const ForceFeedback::SupportedEffectList& ForceFeedback::getSupportedEffects() const
+{
return mSupportedEffects;
}
+
+//-------------------------------------------------------------//
+bool ForceFeedback::supportsEffect(Effect::EForce force, Effect::EType type) const
+{
+ const std::pair<SupportedEffectList::const_iterator, SupportedEffectList::const_iterator>
+ iterRange = mSupportedEffects.equal_range(force);
+ SupportedEffectList::const_iterator iter;
+ for (iter = iterRange.first; iter != iterRange.second; iter++)
+ {
+ if ((*iter).second == type)
+ return true;
+ }
+
+ return false;
+}
Modified: code/branches/resource2/src/ois/OISForceFeedback.h
===================================================================
--- code/branches/resource2/src/ois/OISForceFeedback.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/OISForceFeedback.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -35,7 +35,7 @@
class _OISExport ForceFeedback : public Interface
{
public:
- ForceFeedback() {}
+ ForceFeedback();
virtual ~ForceFeedback() {}
/**
@@ -43,6 +43,7 @@
This is like setting the master volume of an audio device.
Individual effects have gain levels; however, this affects all
effects at once.
+ Note: If the device does not support master gain setting, nothing is done
@param level
A value between 0.0 and 1.0 represent the percentage of gain. 1.0
being the highest possible force level (means no scaling).
@@ -55,6 +56,7 @@
before uploading any effects. Auto centering is the motor moving
the joystick back to center. DirectInput only has an on/off setting,
whereas linux has levels.. Though, we go with DI's on/off mode only
+ Note: If the device does not support auto-centering, nothing is done
@param auto_on
true to turn auto centering on, false to turn off.
*/
@@ -86,17 +88,33 @@
*/
virtual short getFFAxesNumber() = 0;
- typedef std::map<Effect::EForce, Effect::EType> SupportedEffectList;
/**
@remarks
+ Get the current load (%, in [0, 100] of the FF device memory
+ */
+ virtual unsigned short getFFMemoryLoad() = 0;
+
+ typedef std::multimap<Effect::EForce, Effect::EType> SupportedEffectList;
+ /**
+ @remarks
Get a list of all supported effects
*/
const SupportedEffectList& getSupportedEffects() const;
+ /**
+ @remarks
+ Tell if a given force / effect type pair is supported
+ */
+ bool supportsEffect(Effect::EForce force, Effect::EType type) const;
+
void _addEffectTypes( Effect::EForce force, Effect::EType type );
+ void _setGainSupport( bool on );
+ void _setAutoCenterSupport( bool on );
protected:
SupportedEffectList mSupportedEffects;
+ bool mSetGainSupport;
+ bool mSetAutoCenterSupport;
};
}
#endif //OIS_ForceFeedBack_H
Modified: code/branches/resource2/src/ois/OISJoyStick.h
===================================================================
--- code/branches/resource2/src/ois/OISJoyStick.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/OISJoyStick.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -31,7 +31,7 @@
#define OIS_JOYSTICK_VECTOR3_DEFAULT 2.28f
//! POV / HAT Joystick component
- class _OISExport Pov : Component
+ class _OISExport Pov : public Component
{
public:
Pov() : Component(OIS_POV), direction(0) {}
@@ -50,7 +50,7 @@
};
//! A sliding axis - only used in Win32 Right Now
- class _OISExport Slider : Component
+ class _OISExport Slider : public Component
{
public:
Slider() : Component(OIS_Slider), abX(0), abY(0) {};
Modified: code/branches/resource2/src/ois/OISPrereqs.h
===================================================================
--- code/branches/resource2/src/ois/OISPrereqs.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/OISPrereqs.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -166,8 +166,8 @@
class _OISExport Button : public Component
{
public:
- Button() {}
- Button(bool bPushed) : Component(OIS_Button), pushed(bPushed) {};
+ Button() : Component(OIS_Button), pushed(false) {}
+ Button(bool bPushed) : Component(OIS_Button), pushed(bPushed) {}
//! true if pushed, false otherwise
bool pushed;
};
Modified: code/branches/resource2/src/ois/linux/EventHelpers.cpp
===================================================================
--- code/branches/resource2/src/ois/linux/EventHelpers.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/linux/EventHelpers.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -33,43 +33,59 @@
#ifdef OIS_LINUX_JOY_DEBUG
# include <iostream>
- using namespace std;
#endif
+using namespace std;
using namespace OIS;
class DeviceComponentInfo
{
public:
- std::vector<int> buttons, relAxes, absAxes, hats;
+ vector<int> buttons, relAxes, absAxes, hats;
};
-bool inline isBitSet(unsigned long bits[], unsigned int bit)
+bool inline isBitSet(unsigned char bits[], unsigned int bit)
{
- return (bits[bit/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1;
+ return (bits[(bit)/(sizeof(unsigned char)*8)] >> ((bit)%(sizeof(unsigned char)*8))) & 1;
}
+
//-----------------------------------------------------------------------------//
DeviceComponentInfo getComponentInfo( int deviceID )
{
- unsigned long info[2][((KEY_MAX-1)/(sizeof(long)*8)) +1];
- memset( info, 0, sizeof(info) );
+ unsigned char ev_bits[1 + EV_MAX/8/sizeof(unsigned char)];
+ memset( ev_bits, 0, sizeof(ev_bits) );
+ //Read "all" (hence 0) components of the device
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getComponentInfo(" << deviceID
+ << ") : Reading device events features" << endl;
+#endif
+ if (ioctl(deviceID, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1)
+ OIS_EXCEPT( E_General, "Could not read device events features");
+
DeviceComponentInfo components;
- //Read "all" (hence 0) components of the device - read into first entry
- ioctl(deviceID, EVIOCGBIT(0, EV_MAX), info[0]);
-
for (int i = 0; i < EV_MAX; i++)
{
- if( isBitSet(info[0], i) )
+ if( isBitSet(ev_bits, i) )
{
- memset( info[1], 0, sizeof(info) / 2 );
- ioctl(deviceID, EVIOCGBIT(i, KEY_MAX), info[1]);
- for (int j = 0; j < KEY_MAX; j++)
+ // Absolute axis.
+ if(i == EV_ABS)
{
- if( isBitSet(info[1], j) )
+ unsigned char abs_bits[1 + ABS_MAX/8/sizeof(unsigned char)];
+ memset( abs_bits, 0, sizeof(abs_bits) );
+
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getComponentInfo(" << deviceID
+ << ") : Reading device absolute axis features" << endl;
+#endif
+
+ if (ioctl(deviceID, EVIOCGBIT(i, sizeof(abs_bits)), abs_bits) == -1)
+ OIS_EXCEPT( E_General, "Could not read device absolute axis features");
+
+ for (int j = 0; j < ABS_MAX; j++)
{
- if(i == EV_ABS)
+ if( isBitSet(abs_bits, j) )
{
//input_absinfo abInfo;
//ioctl( fd, EVIOCGABS(j), abInfo );
@@ -88,13 +104,47 @@
//ioctl(deviceID, EVIOCSABS(j), &absinfo);
}
}
- else if(i == EV_REL)
+ }
+ }
+ else if(i == EV_REL)
+ {
+ unsigned char rel_bits[1 + REL_MAX/8/sizeof(unsigned char)];
+ memset( rel_bits, 0, sizeof(rel_bits) );
+
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getComponentInfo(" << deviceID
+ << ") : Reading device relative axis features" << endl;
+#endif
+
+ if (ioctl(deviceID, EVIOCGBIT(i, sizeof(rel_bits)), rel_bits) == -1)
+ OIS_EXCEPT( E_General, "Could not read device relative axis features");
+
+ for (int j = 0; j < REL_MAX; j++)
+ {
+ if( isBitSet(rel_bits, j) )
{
- components.relAxes.push_back(j);
+ components.relAxes.push_back(j);
}
- else if(i == EV_KEY)
+ }
+ }
+ else if(i == EV_KEY)
+ {
+ unsigned char key_bits[1 + KEY_MAX/8/sizeof(unsigned char)];
+ memset( key_bits, 0, sizeof(key_bits) );
+
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getComponentInfo(" << deviceID
+ << ") : Reading device buttons features" << endl;
+#endif
+
+ if (ioctl(deviceID, EVIOCGBIT(i, sizeof(key_bits)), key_bits) == -1)
+ OIS_EXCEPT( E_General, "Could not read device buttons features");
+
+ for (int j = 0; j < KEY_MAX; j++)
+ {
+ if( isBitSet(key_bits, j) )
{
- components.buttons.push_back(j);
+ components.buttons.push_back(j);
}
}
}
@@ -107,7 +157,8 @@
//-----------------------------------------------------------------------------//
bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js )
{
- if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" );
+ if( deviceID == -1 )
+ OIS_EXCEPT( E_General, "Error with File Descriptor" );
DeviceComponentInfo info = getComponentInfo( deviceID );
@@ -116,20 +167,26 @@
js.button_map.clear();
#ifdef OIS_LINUX_JOY_DEBUG
- cout << "\n\nDisplaying ButtonMapping Status:";
+ cout << endl << "Displaying ButtonMapping Status:" << endl;
#endif
- for(std::vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
+ for(vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
{
//Check to ensure we find at least one joy only button
- if( (*i >= BTN_JOYSTICK && *i <= BTN_THUMBR) || (*i >= BTN_WHEEL && *i <= BTN_GEAR_UP ) )
+ if( (*i >= BTN_JOYSTICK && *i < BTN_GAMEPAD)
+ || (*i >= BTN_GAMEPAD && *i < BTN_DIGI)
+ || (*i >= BTN_WHEEL && *i < KEY_OK) )
joyButtonFound = true;
js.button_map[*i] = buttons++;
#ifdef OIS_LINUX_JOY_DEBUG
- cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1);
+ cout << "Button Mapping ID (hex): " << hex << *i
+ << " OIS Button Num: " << dec << buttons-1 << endl;
#endif
}
+ #ifdef OIS_LINUX_JOY_DEBUG
+ cout << endl;
+ #endif
//Joy Buttons found, so it must be a joystick or pad
if( joyButtonFound )
@@ -139,22 +196,34 @@
js.buttons = buttons;
js.axes = info.relAxes.size() + info.absAxes.size();
js.hats = info.hats.size();
+ #ifdef OIS_LINUX_JOY_DEBUG
+ cout << endl << "Device name:" << js.vendor << endl;
+ cout << "Device unique Id:" << getUniqueId(deviceID) << endl;
+ cout << "Device physical location:" << getPhysicalLocation(deviceID) << endl;
+ #endif
//Map the Axes
#ifdef OIS_LINUX_JOY_DEBUG
- cout << "\n\nDisplaying AxisMapping Status:";
+ cout << endl << "Displaying AxisMapping Status:" << endl;
#endif
int axes = 0;
- for(std::vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
+ for(vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
{
js.axis_map[*i] = axes;
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::isJoyStick(" << deviceID
+ << ") : Reading device absolute axis #" << *i << " features" << endl;
+#endif
+
input_absinfo absinfo;
- ioctl(deviceID, EVIOCGABS(*i), &absinfo);
+ if (ioctl(deviceID, EVIOCGABS(*i), &absinfo) == -1)
+ OIS_EXCEPT( E_General, "Could not read device absolute axis features");
js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum);
#ifdef OIS_LINUX_JOY_DEBUG
- cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes;
+ cout << "Axis Mapping ID (hex): " << hex << *i
+ << " OIS Axis Num: " << dec << axes << endl;
#endif
++axes;
@@ -165,18 +234,54 @@
}
//-----------------------------------------------------------------------------//
-std::string EventUtils::getName( int deviceID )
+string EventUtils::getName( int deviceID )
{
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getName(" << deviceID
+ << ") : Reading device name" << endl;
+#endif
+
char name[OIS_DEVICE_NAME];
- ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name);
- return std::string(name);
+ if (ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name) == -1)
+ OIS_EXCEPT( E_General, "Could not read device name");
+ return string(name);
}
//-----------------------------------------------------------------------------//
+string EventUtils::getUniqueId( int deviceID )
+{
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getUniqueId(" << deviceID
+ << ") : Reading device unique Id" << endl;
+#endif
+
+#define OIS_DEVICE_UNIQUE_ID 128
+ char uId[OIS_DEVICE_UNIQUE_ID];
+ if (ioctl(deviceID, EVIOCGUNIQ(OIS_DEVICE_UNIQUE_ID), uId) == -1)
+ OIS_EXCEPT( E_General, "Could not read device unique Id");
+ return string(uId);
+}
+
+//-----------------------------------------------------------------------------//
+string EventUtils::getPhysicalLocation( int deviceID )
+{
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::getPhysicalLocation(" << deviceID
+ << ") : Reading device physical location" << endl;
+#endif
+
+#define OIS_DEVICE_PHYSICAL_LOCATION 128
+ char physLoc[OIS_DEVICE_PHYSICAL_LOCATION];
+ if (ioctl(deviceID, EVIOCGPHYS(OIS_DEVICE_PHYSICAL_LOCATION), physLoc) == -1)
+ OIS_EXCEPT( E_General, "Could not read device physical location");
+ return string(physLoc);
+}
+
+//-----------------------------------------------------------------------------//
void EventUtils::enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff )
{
//Linux Event to OIS Event Mappings
- std::map<int, Effect::EType> typeMap;
+ map<int, Effect::EType> typeMap;
typeMap[FF_CONSTANT] = Effect::Constant;
typeMap[FF_RAMP] = Effect::Ramp;
typeMap[FF_SPRING] = Effect::Spring;
@@ -190,44 +295,74 @@
typeMap[FF_INERTIA] = Effect::Inertia;
typeMap[FF_CUSTOM] = Effect::Custom;
- std::map<int, Effect::EForce> forceMap;
+ map<int, Effect::EForce> forceMap;
forceMap[FF_CONSTANT] = Effect::ConstantForce;
- forceMap[FF_RAMP] = Effect::RampForce;
- forceMap[FF_PERIODIC] = Effect::PeriodicForce;
- forceMap[FF_CUSTOM] = Effect::CustomForce;
+ forceMap[FF_RAMP] = Effect::RampForce;
+ forceMap[FF_SPRING] = Effect::ConditionalForce;
+ forceMap[FF_FRICTION] = Effect::ConditionalForce;
+ forceMap[FF_SQUARE] = Effect::PeriodicForce;
+ forceMap[FF_TRIANGLE] = Effect::PeriodicForce;
+ forceMap[FF_SINE] = Effect::PeriodicForce;
+ forceMap[FF_SAW_UP] = Effect::PeriodicForce;
+ forceMap[FF_SAW_DOWN] = Effect::PeriodicForce;
+ forceMap[FF_DAMPER] = Effect::ConditionalForce;
+ forceMap[FF_INERTIA] = Effect::ConditionalForce;
+ forceMap[FF_CUSTOM] = Effect::CustomForce;
//Remove any previously existing memory and create fresh
removeForceFeedback( ff );
- *ff = new LinuxForceFeedback();
+ *ff = new LinuxForceFeedback(deviceID);
- unsigned long info[4] = {0,0,0,0};
- unsigned long subinfo[4]= {0,0,0,0};
+ //Read overall force feedback features
+ unsigned char ff_bits[1 + FF_MAX/8/sizeof(unsigned char)];
+ memset(ff_bits, 0, sizeof(ff_bits));
- //Read overall force feedback components of the device
- ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(long)*4), info);
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "EventUtils::enumerateForceFeedback(" << deviceID
+ << ") : Reading device force feedback features" << endl;
+#endif
+ if (ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(ff_bits)), ff_bits) == -1)
+ OIS_EXCEPT( E_General, "Could not read device force feedback features");
+
+
+ #ifdef OIS_LINUX_JOY_DEBUG
+ cout << "FF bits: " << hex;
+ for (int i = 0; i < sizeof(ff_bits); i++)
+ cout << (int)ff_bits[i];
+ cout << endl << dec;
+ #endif
+
//FF Axes
- //if( isBitSet(info, ABS_X) ) //X Axis
- //if( isBitSet(info, ABS_Y) ) //Y Axis
- //if( isBitSet(info, ABS_WHEEL) ) //Wheel
+ //if( isBitSet(ff_bits, ABS_X) ) //X Axis
+ //if( isBitSet(ff_bits, ABS_Y) ) //Y Axis
+ //if( isBitSet(ff_bits, ABS_WHEEL) ) //Wheel
//FF Effects
- for( int effect = ABS_WHEEL+1; effect < FF_MAX; effect++ )
+ for( int effect = FF_EFFECT_MIN; effect <= FF_WAVEFORM_MAX; effect++ )
{
- if(isBitSet(info, effect))
+ // The RUMBLE force type is ignored, as periodic force one is more powerfull.
+ // The PERIODIC force type is processed later, for each associated periodic effect type.
+ if (effect == FF_RUMBLE || effect == FF_PERIODIC)
+ continue;
+
+ if(isBitSet(ff_bits, effect))
{
- //std::cout << "\tEffect Type: " << effect << std::endl;
- memset(subinfo, 0, sizeof(subinfo));
- //Read any info about this supported effect
- ioctl(deviceID, EVIOCGBIT(effect, sizeof(long)*4), subinfo);
- for( int force = 0; force < FF_MAX; force++ )
- {
- if(isBitSet(subinfo, force))
- (*ff)->_addEffectTypes( forceMap[force], typeMap[effect] );
- }
+ #ifdef OIS_LINUX_JOY_DEBUG
+ cout << " Effect Type: " << Effect::getEffectTypeName(typeMap[effect]) << endl;
+ #endif
+
+ (*ff)->_addEffectTypes( forceMap[effect], typeMap[effect] );
}
}
+ //FF device properties
+ if (isBitSet(ff_bits, FF_GAIN))
+ (*ff)->_setGainSupport(true);
+
+ if (isBitSet(ff_bits, FF_AUTOCENTER))
+ (*ff)->_setAutoCenterSupport(true);
+
//Check to see if any effects were added, else destroy the pointer
const ForceFeedback::SupportedEffectList &list = (*ff)->getSupportedEffects();
if( list.size() == 0 )
Modified: code/branches/resource2/src/ois/linux/EventHelpers.h
===================================================================
--- code/branches/resource2/src/ois/linux/EventHelpers.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/linux/EventHelpers.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -42,6 +42,8 @@
static void removeForceFeedback( LinuxForceFeedback** ff );
static std::string getName( int deviceID );
+ static std::string getUniqueId( int deviceID );
+ static std::string getPhysicalLocation( int deviceID );
};
}
#endif
Modified: code/branches/resource2/src/ois/linux/LinuxForceFeedback.cpp
===================================================================
--- code/branches/resource2/src/ois/linux/LinuxForceFeedback.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/linux/LinuxForceFeedback.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -23,39 +23,537 @@
#include "linux/LinuxForceFeedback.h"
#include "OISException.h"
+#include <cstdlib>
+#include <errno.h>
+#include <memory.h>
+
using namespace OIS;
+// 0 = No trace; 1 = Important traces; 2 = Debug traces
+#define OIS_LINUX_JOYFF_DEBUG 1
+
+#ifdef OIS_LINUX_JOYFF_DEBUG
+# include <iostream>
+ using namespace std;
+#endif
+
//--------------------------------------------------------------//
-LinuxForceFeedback::LinuxForceFeedback()
+LinuxForceFeedback::LinuxForceFeedback(int deviceID) :
+ ForceFeedback(), mJoyStick(deviceID)
{
}
+
//--------------------------------------------------------------//
LinuxForceFeedback::~LinuxForceFeedback()
{
+ // Unload all effects.
+ for(EffectList::iterator i = mEffectList.begin(); i != mEffectList.end(); ++i )
+ {
+ struct ff_effect *linEffect = i->second;
+ if( linEffect )
+ _unload(linEffect->id);
+ }
+
+ mEffectList.clear();
}
//--------------------------------------------------------------//
-void LinuxForceFeedback::setMasterGain(float)
+unsigned short LinuxForceFeedback::getFFMemoryLoad()
{
+ int nEffects = -1;
+ if (ioctl(mJoyStick, EVIOCGEFFECTS, &nEffects) == -1)
+ OIS_EXCEPT(E_General, "Unknown error reading max number of uploaded effects.");
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << "LinuxForceFeedback("<< mJoyStick
+ << ") : Read device max number of uploaded effects : " << nEffects << endl;
+#endif
+
+ return (unsigned short int)(nEffects > 0 ? 100.0*mEffectList.size()/nEffects : 100);
}
//--------------------------------------------------------------//
-void LinuxForceFeedback::setAutoCenterMode(bool)
+void LinuxForceFeedback::setMasterGain(float value)
{
+ if (!mSetGainSupport)
+ {
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+ cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain "
+ << "is not supported by the device" << endl;
+#endif
+ return;
+ }
+
+ struct input_event event;
+
+ memset(&event, 0, sizeof(event));
+ event.type = EV_FF;
+ event.code = FF_GAIN;
+ if (value < 0.0)
+ value = 0.0;
+ else if (value > 1.0)
+ value = 1.0;
+ event.value = (__s32)(value * 0xFFFFUL);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+ cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain to "
+ << value << " => " << event.value << endl;
+#endif
+
+ if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
+ OIS_EXCEPT(E_General, "Unknown error changing master gain.");
+ }
}
//--------------------------------------------------------------//
-void LinuxForceFeedback::upload( const Effect* /*effect*/ )
+void LinuxForceFeedback::setAutoCenterMode(bool enabled)
{
+ if (!mSetAutoCenterSupport)
+ {
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+ cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting auto-center mode "
+ << "is not supported by the device" << endl;
+#endif
+ return;
+ }
+
+ struct input_event event;
+
+ memset(&event, 0, sizeof(event));
+ event.type = EV_FF;
+ event.code = FF_AUTOCENTER;
+ event.value = (__s32)(enabled*0xFFFFFFFFUL);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+ cout << "LinuxForceFeedback("<< mJoyStick << ") : Toggling auto-center to "
+ << enabled << " => 0x" << hex << event.value << dec << endl;
+#endif
+
+ if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
+ OIS_EXCEPT(E_General, "Unknown error toggling auto-center.");
+ }
}
//--------------------------------------------------------------//
-void LinuxForceFeedback::modify( const Effect* /*effect*/ )
+void LinuxForceFeedback::upload( const Effect* effect )
{
+ switch( effect->force )
+ {
+ case OIS::Effect::ConstantForce:
+ _updateConstantEffect(effect);
+ break;
+ case OIS::Effect::ConditionalForce:
+ _updateConditionalEffect(effect);
+ break;
+ case OIS::Effect::PeriodicForce:
+ _updatePeriodicEffect(effect);
+ break;
+ case OIS::Effect::RampForce:
+ _updateRampEffect(effect);
+ break;
+ case OIS::Effect::CustomForce:
+ //_updateCustomEffect(effect);
+ //break;
+ default:
+ OIS_EXCEPT(E_NotImplemented, "Requested force not implemented yet, sorry!");
+ break;
+ }
}
//--------------------------------------------------------------//
-void LinuxForceFeedback::remove( const Effect* /*effect*/ )
+void LinuxForceFeedback::modify( const Effect* effect )
{
+ upload(effect);
}
+//--------------------------------------------------------------//
+void LinuxForceFeedback::remove( const Effect* effect )
+{
+ //Get the effect - if it exists
+ EffectList::iterator i = mEffectList.find(effect->_handle);
+ if( i != mEffectList.end() )
+ {
+ struct ff_effect *linEffect = i->second;
+ if( linEffect )
+ {
+ _stop(effect->_handle);
+
+ _unload(effect->_handle);
+
+ free(linEffect);
+
+ mEffectList.erase(i);
+ }
+ else
+ mEffectList.erase(i);
+ }
+}
+
+//--------------------------------------------------------------//
+// To Signed16/Unsigned15 safe conversions
+#define MaxUnsigned15Value 0x7FFF
+#define toUnsigned15(value) \
+ (__u16)((value) < 0 ? 0 : ((value) > MaxUnsigned15Value ? MaxUnsigned15Value : (value)))
+
+#define MaxSigned16Value 0x7FFF
+#define MinSigned16Value -0x7FFF
+#define toSigned16(value) \
+ (__s16)((value) < MinSigned16Value ? MinSigned16Value : ((value) > MaxSigned16Value ? MaxSigned16Value : (value)))
+
+// OIS to Linux duration
+#define LinuxInfiniteDuration 0xFFFF
+#define OISDurationUnitMS 1000 // OIS duration unit (microseconds), expressed in milliseconds (theLinux duration unit)
+
+// linux/input.h : All duration values are expressed in ms. Values above 32767 ms (0x7fff)
+// should not be used and have unspecified results.
+#define LinuxDuration(oisDuration) ((oisDuration) == Effect::OIS_INFINITE ? LinuxInfiniteDuration \
+ : toUnsigned15((oisDuration)/OISDurationUnitMS))
+
+
+// OIS to Linux levels
+#define OISMaxLevel 10000
+#define LinuxMaxLevel 0x7FFF
+
+// linux/input.h : Valid range for the attack and fade levels is 0x0000 - 0x7fff
+#define LinuxPositiveLevel(oisLevel) toUnsigned15(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
+
+#define LinuxSignedLevel(oisLevel) toSigned16(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
+
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_setCommonProperties(struct ff_effect *event,
+ struct ff_envelope *ffenvelope,
+ const Effect* effect, const Envelope *envelope )
+{
+ memset(event, 0, sizeof(struct ff_effect));
+
+ if (envelope && ffenvelope && envelope->isUsed()) {
+ ffenvelope->attack_length = LinuxDuration(envelope->attackLength);
+ ffenvelope->attack_level = LinuxPositiveLevel(envelope->attackLevel);
+ ffenvelope->fade_length = LinuxDuration(envelope->fadeLength);
+ ffenvelope->fade_level = LinuxPositiveLevel(envelope->fadeLevel);
+ }
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << endl;
+ if (envelope && ffenvelope)
+ {
+ cout << " Enveloppe :" << endl
+ << " AttackLen : " << envelope->attackLength
+ << " => " << ffenvelope->attack_length << endl
+ << " AttackLvl : " << envelope->attackLevel
+ << " => " << ffenvelope->attack_level << endl
+ << " FadeLen : " << envelope->fadeLength
+ << " => " << ffenvelope->fade_length << endl
+ << " FadeLvl : " << envelope->fadeLevel
+ << " => " << ffenvelope->fade_level << endl;
+ }
+#endif
+
+ event->direction = (__u16)(1 + (effect->direction*45.0+135.0)*0xFFFFUL/360.0);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " Direction : " << Effect::getDirectionName(effect->direction)
+ << " => 0x" << hex << event->direction << dec << endl;
+#endif
+
+ // TODO trigger_button 0 vs. -1
+ event->trigger.button = effect->trigger_button; // < 0 ? 0 : effect->trigger_button;
+ event->trigger.interval = LinuxDuration(effect->trigger_interval);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " Trigger :" << endl
+ << " Button : " << effect->trigger_button
+ << " => " << event->trigger.button << endl
+ << " Interval : " << effect->trigger_interval
+ << " => " << event->trigger.interval << endl;
+#endif
+
+ event->replay.length = LinuxDuration(effect->replay_length);
+ event->replay.delay = LinuxDuration(effect->replay_delay);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " Replay :" << endl
+ << " Length : " << effect->replay_length
+ << " => " << event->replay.length << endl
+ << " Delay : " << effect->replay_delay
+ << " => " << event->replay.delay << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updateConstantEffect( const Effect* eff )
+{
+ struct ff_effect event;
+
+ ConstantEffect *effect = static_cast<ConstantEffect*>(eff->getForceEffect());
+
+ _setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
+
+ event.type = FF_CONSTANT;
+ event.id = -1;
+
+ event.u.constant.level = LinuxSignedLevel(effect->level);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " Level : " << effect->level
+ << " => " << event.u.constant.level << endl;
+#endif
+
+ _upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updateRampEffect( const Effect* eff )
+{
+ struct ff_effect event;
+
+ RampEffect *effect = static_cast<RampEffect*>(eff->getForceEffect());
+
+ _setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
+
+ event.type = FF_RAMP;
+ event.id = -1;
+
+ event.u.ramp.start_level = LinuxSignedLevel(effect->startLevel);
+ event.u.ramp.end_level = LinuxSignedLevel(effect->endLevel);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " StartLevel : " << effect->startLevel
+ << " => " << event.u.ramp.start_level << endl
+ << " EndLevel : " << effect->endLevel
+ << " => " << event.u.ramp.end_level << endl;
+#endif
+
+ _upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updatePeriodicEffect( const Effect* eff )
+{
+ struct ff_effect event;
+
+ PeriodicEffect *effect = static_cast<PeriodicEffect*>(eff->getForceEffect());
+
+ _setCommonProperties(&event, &event.u.periodic.envelope, eff, &effect->envelope);
+
+ event.type = FF_PERIODIC;
+ event.id = -1;
+
+ switch( eff->type )
+ {
+ case OIS::Effect::Square:
+ event.u.periodic.waveform = FF_SQUARE;
+ break;
+ case OIS::Effect::Triangle:
+ event.u.periodic.waveform = FF_TRIANGLE;
+ break;
+ case OIS::Effect::Sine:
+ event.u.periodic.waveform = FF_SINE;
+ break;
+ case OIS::Effect::SawToothUp:
+ event.u.periodic.waveform = FF_SAW_UP;
+ break;
+ case OIS::Effect::SawToothDown:
+ event.u.periodic.waveform = FF_SAW_DOWN;
+ break;
+ // Note: No support for Custom periodic force effect for the moment
+ //case OIS::Effect::Custom:
+ //event.u.periodic.waveform = FF_CUSTOM;
+ //break;
+ default:
+ OIS_EXCEPT(E_General, "No such available effect for Periodic force!");
+ break;
+ }
+
+ event.u.periodic.period = LinuxDuration(effect->period);
+ event.u.periodic.magnitude = LinuxPositiveLevel(effect->magnitude);
+ event.u.periodic.offset = LinuxPositiveLevel(effect->offset);
+ event.u.periodic.phase = (__u16)(effect->phase*event.u.periodic.period/36000.0); // ?????
+
+ // Note: No support for Custom periodic force effect for the moment
+ event.u.periodic.custom_len = 0;
+ event.u.periodic.custom_data = 0;
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " Magnitude : " << effect->magnitude
+ << " => " << event.u.periodic.magnitude << endl
+ << " Period : " << effect->period
+ << " => " << event.u.periodic.period << endl
+ << " Offset : " << effect->offset
+ << " => " << event.u.periodic.offset << endl
+ << " Phase : " << effect->phase
+ << " => " << event.u.periodic.phase << endl;
+#endif
+
+ _upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updateConditionalEffect( const Effect* eff )
+{
+ struct ff_effect event;
+
+ ConditionalEffect *effect = static_cast<ConditionalEffect*>(eff->getForceEffect());
+
+ _setCommonProperties(&event, NULL, eff, NULL);
+
+ switch( eff->type )
+ {
+ case OIS::Effect::Friction:
+ event.type = FF_FRICTION;
+ break;
+ case OIS::Effect::Damper:
+ event.type = FF_DAMPER;
+ break;
+ case OIS::Effect::Inertia:
+ event.type = FF_INERTIA;
+ break;
+ case OIS::Effect::Spring:
+ event.type = FF_SPRING;
+ break;
+ default:
+ OIS_EXCEPT(E_General, "No such available effect for Conditional force!");
+ break;
+ }
+
+ event.id = -1;
+
+ event.u.condition[0].right_saturation = LinuxSignedLevel(effect->rightSaturation);
+ event.u.condition[0].left_saturation = LinuxSignedLevel(effect->leftSaturation);
+ event.u.condition[0].right_coeff = LinuxSignedLevel(effect->rightCoeff);
+ event.u.condition[0].left_coeff = LinuxSignedLevel(effect->leftCoeff);
+ event.u.condition[0].deadband = LinuxPositiveLevel(effect->deadband);// Unit ??
+ event.u.condition[0].center = LinuxSignedLevel(effect->center); // Unit ?? TODO ?
+
+ // TODO support for second condition
+ event.u.condition[1] = event.u.condition[0];
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << " Condition[0] : " << endl
+ << " RightSaturation : " << effect->rightSaturation
+ << " => " << event.u.condition[0].right_saturation << endl
+ << " LeftSaturation : " << effect->leftSaturation
+ << " => " << event.u.condition[0]. left_saturation << endl
+ << " RightCoefficient : " << effect->rightCoeff
+ << " => " << event.u.condition[0].right_coeff << endl
+ << " LeftCoefficient : " << effect->leftCoeff
+ << " => " << event.u.condition[0].left_coeff << endl
+ << " DeadBand : " << effect->deadband
+ << " => " << event.u.condition[0].deadband << endl
+ << " Center : " << effect->center
+ << " => " << event.u.condition[0].center << endl;
+ cout << " Condition[1] : Not implemented" << endl;
+#endif
+ _upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_upload( struct ff_effect* ffeffect, const Effect* effect)
+{
+ struct ff_effect *linEffect = 0;
+
+ //Get the effect - if it exists
+ EffectList::iterator i = mEffectList.find(effect->_handle);
+ //It has been created already
+ if( i != mEffectList.end() )
+ linEffect = i->second;
+
+ if( linEffect == 0 )
+ {
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Adding new effect : "
+ << Effect::getEffectTypeName(effect->type) << endl;
+#endif
+
+ //This effect has not yet been created, so create it in the device
+ if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
+ // TODO device full check
+ // OIS_EXCEPT(E_DeviceFull, "Remove an effect before adding more!");
+ OIS_EXCEPT(E_General, "Unknown error creating effect (may be the device is full)->..");
+ }
+
+ // Save returned effect handle
+ effect->_handle = ffeffect->id;
+
+ // Save a copy of the uploaded effect for later simple modifications
+ linEffect = (struct ff_effect *)calloc(1, sizeof(struct ff_effect));
+ memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
+
+ mEffectList[effect->_handle] = linEffect;
+
+ // Start playing the effect.
+ _start(effect->_handle);
+ }
+ else
+ {
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Replacing effect : "
+ << Effect::getEffectTypeName(effect->type) << endl;
+#endif
+
+ // Keep same id/handle, as this is just an update in the device.
+ ffeffect->id = effect->_handle;
+
+ // Update effect in the device.
+ if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
+ OIS_EXCEPT(E_General, "Unknown error updating an effect->..");
+ }
+
+ // Update local linEffect for next time.
+ memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
+ }
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << "LinuxForceFeedback("<< mJoyStick
+ << ") : Effect handle : " << effect->_handle << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_stop( int handle) {
+ struct input_event stop;
+
+ stop.type = EV_FF;
+ stop.code = handle;
+ stop.value = 0;
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << endl << "LinuxForceFeedback("<< mJoyStick
+ << ") : Stopping effect with handle " << handle << endl;
+#endif
+
+ if (write(mJoyStick, &stop, sizeof(stop)) != sizeof(stop)) {
+ OIS_EXCEPT(E_General, "Unknown error stopping effect->..");
+ }
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_start( int handle) {
+ struct input_event play;
+
+ play.type = EV_FF;
+ play.code = handle;
+ play.value = 1; // Play once.
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << endl << "LinuxForceFeedback("<< mJoyStick
+ << ") : Starting effect with handle " << handle << endl;
+#endif
+
+ if (write(mJoyStick, &play, sizeof(play)) != sizeof(play)) {
+ OIS_EXCEPT(E_General, "Unknown error playing effect->..");
+ }
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_unload( int handle)
+{
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+ cout << endl << "LinuxForceFeedback("<< mJoyStick
+ << ") : Removing effect with handle " << handle << endl;
+#endif
+
+ if (ioctl(mJoyStick, EVIOCRMFF, handle) == -1) {
+ OIS_EXCEPT(E_General, "Unknown error removing effect->..");
+ }
+}
Modified: code/branches/resource2/src/ois/linux/LinuxForceFeedback.h
===================================================================
--- code/branches/resource2/src/ois/linux/LinuxForceFeedback.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/linux/LinuxForceFeedback.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -25,13 +25,14 @@
#include "linux/LinuxPrereqs.h"
#include "OISForceFeedback.h"
+#include <linux/input.h>
namespace OIS
{
class LinuxForceFeedback : public ForceFeedback
{
public:
- LinuxForceFeedback();
+ LinuxForceFeedback(int deviceID);
~LinuxForceFeedback();
/** @copydoc ForceFeedback::setMasterGain */
@@ -49,8 +50,36 @@
/** @copydoc ForceFeedback::remove */
void remove( const Effect* effect );
- /** FF is not yet implemented fully on Linux.. just retun 0 for now. todo, xxx */
- short int getFFAxesNumber() { return 0; }
+ /** FF is not yet implemented fully on Linux.. just return -1 for now. todo, xxx */
+ short int getFFAxesNumber() { return -1; }
+
+ /** @copydoc ForceFeedback::getFFMemoryLoad */
+ unsigned short getFFMemoryLoad();
+
+ protected:
+
+ //Sets the common properties to all effects
+ void _setCommonProperties(struct ff_effect *event, struct ff_envelope *ffenvelope,
+ const Effect* effect, const Envelope *envelope );
+
+ //Specific Effect Settings
+ void _updateConstantEffect( const Effect* effect );
+ void _updateRampEffect( const Effect* effect );
+ void _updatePeriodicEffect( const Effect* effect );
+ void _updateConditionalEffect( const Effect* effect );
+ //void _updateCustomEffect( const Effect* effect );
+
+ void _upload( struct ff_effect* ffeffect, const Effect* effect);
+ void _stop( int handle);
+ void _start( int handle);
+ void _unload( int handle);
+
+ // Map of currently uploaded effects (handle => effect)
+ typedef std::map<int, struct ff_effect *> EffectList;
+ EffectList mEffectList;
+
+ // Joystick device (file) descriptor.
+ int mJoyStick;
};
}
#endif //OIS_LinuxForceFeedBack_H
Modified: code/branches/resource2/src/ois/linux/LinuxJoyStickEvents.cpp
===================================================================
--- code/branches/resource2/src/ois/linux/LinuxJoyStickEvents.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/linux/LinuxJoyStickEvents.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -36,16 +36,13 @@
#include <sstream>
+# include <iostream>
+using namespace std;
using namespace OIS;
//#define OIS_LINUX_JOY_DEBUG
-#ifdef OIS_LINUX_JOY_DEBUG
-# include <iostream>
- using namespace std;
-#endif
-
//-------------------------------------------------------------------//
LinuxJoyStick::LinuxJoyStick(InputManager* creator, bool buffered, const JoyStickInfo& js)
: JoyStick(js.vendor, buffered, js.devId, creator)
@@ -113,7 +110,7 @@
int button = mButtonMap[js[i].code];
#ifdef OIS_LINUX_JOY_DEBUG
- std::cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << std::endl;
+ cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
#endif
//Check to see whether push or released event...
@@ -131,14 +128,15 @@
}
break;
}
- case EV_ABS: //Absoulte Axis
+
+ case EV_ABS: //Absolute Axis
{
//A Stick (BrakeDefine is the highest possible Axis)
if( js[i].code <= ABS_BRAKE )
{
int axis = mAxisMap[js[i].code];
- assert( axis < 32 && "Too many axes, not supported. Report this to OIS forums!" );
-
+ assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
+
axisMoved[axis] = true;
//check for rescaling:
@@ -189,8 +187,13 @@
}
break;
}
- //Relative Axes (Do any joysticks actually have a relative axis?)
- case EV_REL:
+
+
+ case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
+#ifdef OIS_LINUX_JOY_DEBUG
+ cout << "\nWarning: Relatives axes not supported yet" << endl;
+#endif
+ break;
default: break;
}
}
@@ -242,14 +245,14 @@
//xxx move this to InputManager, as it can also scan all other events
for(int i = 0; i < 64; ++i )
{
- std::stringstream s;
+ stringstream s;
s << "/dev/input/event" << i;
- int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK );
+ int fd = open( s.str().c_str(), O_RDWR |O_NONBLOCK );
if(fd == -1)
continue;
-
+
#ifdef OIS_LINUX_JOY_DEBUG
- std::cout << "\nOpening " << s.str() << "...";
+ cout << "Opening " << s.str() << "..." << endl;
#endif
try
{
@@ -258,13 +261,13 @@
{
joys.push_back(js);
#ifdef OIS_LINUX_JOY_DEBUG
- std::cout << "\n__Joystick added to list";
+ cout << "=> Joystick added to list." << endl;
#endif
}
else
{
#ifdef OIS_LINUX_JOY_DEBUG
- std::cout << "\n__Not a joystick!!";
+ cout << "=> Not a joystick." << endl;
#endif
close(fd);
}
@@ -272,7 +275,7 @@
catch(...)
{
#ifdef OIS_LINUX_JOY_DEBUG
- std::cout << "\nException caught!!";
+ cout << "Exception caught!!" << endl;
#endif
close(fd);
}
Modified: code/branches/resource2/src/ois/win32/Win32ForceFeedback.cpp
===================================================================
--- code/branches/resource2/src/ois/win32/Win32ForceFeedback.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32ForceFeedback.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -24,16 +24,26 @@
#include "OISException.h"
#include <Math.h>
-#if defined (_DEBUG)
+// 0 = No trace; 1 = Important traces; 2 = Debug traces
+#define OIS_WIN32_JOYFF_DEBUG 1
+
+#if (defined (_DEBUG) || defined(OIS_WIN32_JOYFF_DEBUG))
+ #include <iostream>
#include <sstream>
+ using namespace std;
#endif
using namespace OIS;
//--------------------------------------------------------------//
-Win32ForceFeedback::Win32ForceFeedback(IDirectInputDevice8* joy) :
- mHandles(0), mJoyStick(joy)
+Win32ForceFeedback::Win32ForceFeedback(IDirectInputDevice8* pDIJoy, const DIDEVCAPS* pDIJoyCaps) :
+ mHandles(0), mJoyStick(pDIJoy), mFFAxes(0), mpDIJoyCaps(pDIJoyCaps)
{
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+ cout << "FFSamplePeriod : " << mpDIJoyCaps->dwFFSamplePeriod << " mu-s, "
+ << "FFMinTimeResolution : " << mpDIJoyCaps->dwFFMinTimeResolution << " mu-s,"
+ << "" << endl;
+#endif
}
//--------------------------------------------------------------//
@@ -44,13 +54,44 @@
{
LPDIRECTINPUTEFFECT dxEffect = i->second;
if( dxEffect )
+ {
dxEffect->Unload();
+ dxEffect->Release();
+ }
}
mEffectList.clear();
}
//--------------------------------------------------------------//
+short Win32ForceFeedback::getFFAxesNumber()
+{
+ return mFFAxes;
+}
+
+//--------------------------------------------------------------//
+unsigned short Win32ForceFeedback::getFFMemoryLoad()
+{
+ DIPROPDWORD dipdw; // DIPROPDWORD contains a DIPROPHEADER structure.
+ dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+ dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ dipdw.diph.dwObj = 0; // device property
+ dipdw.diph.dwHow = DIPH_DEVICE;
+ dipdw.dwData = 0; // In case of any error.
+
+ const HRESULT hr = mJoyStick->GetProperty(DIPROP_FFLOAD, &dipdw.diph);
+ if(FAILED(hr))
+ {
+ if (hr == DIERR_NOTEXCLUSIVEACQUIRED)
+ OIS_EXCEPT(E_General, "Can't query FF memory load as device was not acquired in exclusive mode");
+ else
+ OIS_EXCEPT(E_General, "Unknown error querying FF memory load ->..");
+ }
+
+ return (unsigned short)dipdw.dwData;
+}
+
+//--------------------------------------------------------------//
void Win32ForceFeedback::upload( const Effect* effect )
{
switch( effect->force )
@@ -85,7 +126,10 @@
//We care about the return value - as the effect might not
//have been unlaoded
if( SUCCEEDED(dxEffect->Unload()) )
+ {
+ dxEffect->Release();
mEffectList.erase(i);
+ }
}
else
mEffectList.erase(i);
@@ -110,71 +154,103 @@
DIPropGain.diph.dwHow = DIPH_DEVICE;
DIPropGain.dwData = gain_level;
- mJoyStick->SetProperty(DIPROP_FFGAIN, &DIPropGain.diph);
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+ cout << "Win32ForceFeedback("<< mJoyStick << ") : Setting master gain to "
+ << level << " => " << DIPropGain.dwData << endl;
+#endif
+
+ const HRESULT hr = mJoyStick->SetProperty(DIPROP_FFGAIN, &DIPropGain.diph);
+
+#if defined (_DEBUG)
+ if(FAILED(hr))
+ cout << "Failed to change master gain" << endl;
+#endif
}
//--------------------------------------------------------------//
void Win32ForceFeedback::setAutoCenterMode( bool auto_on )
{
- //DI Property DIPROPAUTOCENTER_OFF = 0, 1 is on
DIPROPDWORD DIPropAutoCenter;
DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter);
DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
DIPropAutoCenter.diph.dwObj = 0;
DIPropAutoCenter.diph.dwHow = DIPH_DEVICE;
- DIPropAutoCenter.dwData = auto_on;
+ DIPropAutoCenter.dwData = (auto_on ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF);
- //hr =
- mJoyStick->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+ cout << "Win32ForceFeedback("<< mJoyStick << ") : Setting auto-center mode to "
+ << auto_on << " => " << DIPropAutoCenter.dwData << endl;
+#endif
+
+ const HRESULT hr = mJoyStick->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
+
+#if defined (_DEBUG)
+ if(FAILED(hr))
+ cout << "Failed to change auto-center mode" << endl;
+#endif
}
//--------------------------------------------------------------//
void Win32ForceFeedback::_updateConstantEffect( const Effect* effect )
{
+ ConstantEffect *eff = static_cast<ConstantEffect*>(effect->getForceEffect());
+
DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG rglDirection[2] = { 0, 0 };
+ DIENVELOPE diEnvelope;
DICONSTANTFORCE cf;
DIEFFECT diEffect;
//Currently only support 1 axis
//if( effect->getNumAxes() == 1 )
- cf.lMagnitude = static_cast<ConstantEffect*>(effect->getForceEffect())->level;
+ cf.lMagnitude = eff->level;
- _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DICONSTANTFORCE), &cf, effect);
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+ cout << " Level : " << eff->level
+ << " => " << cf.lMagnitude << endl;
+#endif
+
+ _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICONSTANTFORCE), &cf, effect, &eff->envelope);
_upload(GUID_ConstantForce, &diEffect, effect);
}
//--------------------------------------------------------------//
void Win32ForceFeedback::_updateRampEffect( const Effect* effect )
{
+ RampEffect *eff = static_cast<RampEffect*>(effect->getForceEffect());
+
DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG rglDirection[2] = { 0, 0 };
+ DIENVELOPE diEnvelope;
DIRAMPFORCE rf;
DIEFFECT diEffect;
//Currently only support 1 axis
- rf.lStart = static_cast<RampEffect*>(effect->getForceEffect())->startLevel;
- rf.lEnd = static_cast<RampEffect*>(effect->getForceEffect())->endLevel;
+ rf.lStart = eff->startLevel;
+ rf.lEnd = eff->endLevel;
- _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DIRAMPFORCE), &rf, effect);
+ _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DIRAMPFORCE), &rf, effect, &eff->envelope );
_upload(GUID_RampForce, &diEffect, effect);
}
//--------------------------------------------------------------//
void Win32ForceFeedback::_updatePeriodicEffect( const Effect* effect )
{
+ PeriodicEffect *eff = static_cast<PeriodicEffect*>(effect->getForceEffect());
+
DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG rglDirection[2] = { 0, 0 };
+ DIENVELOPE diEnvelope;
DIPERIODIC pf;
DIEFFECT diEffect;
//Currently only support 1 axis
- pf.dwMagnitude = static_cast<PeriodicEffect*>(effect->getForceEffect())->magnitude;
- pf.lOffset = static_cast<PeriodicEffect*>(effect->getForceEffect())->offset;
- pf.dwPhase = static_cast<PeriodicEffect*>(effect->getForceEffect())->phase;
- pf.dwPeriod = static_cast<PeriodicEffect*>(effect->getForceEffect())->period;
+ pf.dwMagnitude = eff->magnitude;
+ pf.lOffset = eff->offset;
+ pf.dwPhase = eff->phase;
+ pf.dwPeriod = eff->period;
- _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DIPERIODIC), &pf, effect);
+ _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DIPERIODIC), &pf, effect, &eff->envelope );
switch( effect->type )
{
@@ -190,19 +266,22 @@
//--------------------------------------------------------------//
void Win32ForceFeedback::_updateConditionalEffect( const Effect* effect )
{
+ ConditionalEffect *eff = static_cast<ConditionalEffect*>(effect->getForceEffect());
+
DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
LONG rglDirection[2] = { 0, 0 };
+ DIENVELOPE diEnvelope;
DICONDITION cf;
DIEFFECT diEffect;
- cf.lOffset = static_cast<ConditionalEffect*>(effect->getForceEffect())->deadband;
- cf.lPositiveCoefficient = static_cast<ConditionalEffect*>(effect->getForceEffect())->rightCoeff;
- cf.lNegativeCoefficient = static_cast<ConditionalEffect*>(effect->getForceEffect())->leftCoeff;
- cf.dwPositiveSaturation = static_cast<ConditionalEffect*>(effect->getForceEffect())->rightSaturation;
- cf.dwNegativeSaturation = static_cast<ConditionalEffect*>(effect->getForceEffect())->leftSaturation;
- cf.lDeadBand = static_cast<ConditionalEffect*>(effect->getForceEffect())->deadband;
+ cf.lOffset = eff->deadband;
+ cf.lPositiveCoefficient = eff->rightCoeff;
+ cf.lNegativeCoefficient = eff->leftCoeff;
+ cf.dwPositiveSaturation = eff->rightSaturation;
+ cf.dwNegativeSaturation = eff->leftSaturation;
+ cf.lDeadBand = eff->deadband;
- _setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DICONDITION), &cf, effect);
+ _setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICONDITION), &cf, effect, 0 );
switch( effect->type )
{
@@ -217,40 +296,98 @@
//--------------------------------------------------------------//
void Win32ForceFeedback::_updateCustomEffect( const Effect* /*effect*/ )
{
+ //CustomEffect *eff = static_cast<CustomEffect*>(effect->getForceEffect());
+ //
//DWORD rgdwAxes[2] = { DIJOFS_X, DIJOFS_Y };
//LONG rglDirection[2] = { 0, 0 };
+ //DIENVELOPE diEnvelope;
//DICUSTOMFORCE cf;
//DIEFFECT diEffect;
//cf.cChannels = 0;
//cf.dwSamplePeriod = 0;
//cf.cSamples = 0;
//cf.rglForceData = 0;
- //_setCommonProperties(&diEffect, rgdwAxes, rglDirection, sizeof(DICUSTOMFORCE), &cf, effect);
+ //_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICUSTOMFORCE), &cf, effect, &eff->envelope);
//_upload(GUID_CustomForce, &diEffect, effect);
}
//--------------------------------------------------------------//
void Win32ForceFeedback::_setCommonProperties(
DIEFFECT* diEffect, DWORD* rgdwAxes,
- LONG* rglDirection, DWORD struct_size,
- LPVOID struct_type, const Effect* effect )
+ LONG* rglDirection, DIENVELOPE* diEnvelope, DWORD struct_size,
+ LPVOID struct_type, const Effect* effect, const Envelope* envelope )
{
ZeroMemory(diEffect, sizeof(DIEFFECT));
diEffect->dwSize = sizeof(DIEFFECT);
diEffect->dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
- diEffect->dwDuration = effect->replay_length;
- diEffect->dwSamplePeriod = 0;
diEffect->dwGain = DI_FFNOMINALMAX;
- diEffect->dwTriggerButton = DIEB_NOTRIGGER;
- diEffect->dwTriggerRepeatInterval = 0;
- diEffect->cAxes = effect->getNumAxes();
+
+ diEffect->dwTriggerButton = DIEB_NOTRIGGER; // effect->trigger_button; // TODO: Conversion
+ diEffect->dwTriggerRepeatInterval = effect->trigger_interval;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+ cout << " Trigger :" << endl
+ << " Button : " << effect->trigger_button
+ << " => " << diEffect->dwTriggerButton << endl
+ << " Interval : " << effect->trigger_interval
+ << " => " << diEffect->dwTriggerRepeatInterval << endl;
+#endif
+
+ diEffect->cAxes = 1; // effect->getNumAxes();
diEffect->rgdwAxes = rgdwAxes;
- diEffect->rglDirection = rglDirection;
- diEffect->lpEnvelope = 0;
+
+ diEffect->rglDirection = rglDirection; // TODO: conversion from effect->direction
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+ cout << " Direction : " << Effect::getDirectionName(effect->direction)
+ << " => {";
+ for (int iDir=0; iDir < (int)diEffect->cAxes; iDir++)
+ cout << " " << diEffect->rglDirection[iDir];
+ cout << "}" << endl;
+#endif
+
+ if (diEnvelope && envelope && envelope->isUsed())
+ {
+ diEnvelope->dwSize = sizeof(DIENVELOPE);
+ diEnvelope->dwAttackLevel = envelope->attackLevel;
+ diEnvelope->dwAttackTime = envelope->attackLength;
+ diEnvelope->dwFadeLevel = envelope->fadeLevel;
+ diEnvelope->dwFadeTime = envelope->fadeLength;
+ diEffect->lpEnvelope = diEnvelope;
+ }
+ else
+ diEffect->lpEnvelope = 0;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+ if (diEnvelope && envelope && envelope->isUsed())
+ {
+ cout << " Enveloppe :" << endl
+ << " AttackLen : " << envelope->attackLength
+ << " => " << diEnvelope->dwAttackTime << endl
+ << " AttackLvl : " << envelope->attackLevel
+ << " => " << diEnvelope->dwAttackLevel << endl
+ << " FadeLen : " << envelope->fadeLength
+ << " => " << diEnvelope->dwFadeTime << endl
+ << " FadeLvl : " << envelope->fadeLevel
+ << " => " << diEnvelope->dwFadeLevel << endl;
+ }
+#endif
+
+ diEffect->dwSamplePeriod = 0;
+ diEffect->dwDuration = effect->replay_length;
+ diEffect->dwStartDelay = effect->replay_delay;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+ cout << " Replay :" << endl
+ << " Length : " << effect->replay_length
+ << " => " << diEffect->dwDuration << endl
+ << " Delay : " << effect->replay_delay
+ << " => " << diEffect->dwStartDelay << endl;
+#endif
+
diEffect->cbTypeSpecificParams = struct_size;
diEffect->lpvTypeSpecificParams = struct_type;
- diEffect->dwStartDelay = effect->replay_delay;
}
//--------------------------------------------------------------//
@@ -294,33 +431,99 @@
//--------------------------------------------------------------//
void Win32ForceFeedback::_addEffectSupport( LPCDIEFFECTINFO pdei )
{
- //Determine what the effect is and how it corresponds to our OIS's Enums
- //We could save the GUIDs too, however, we will just use the predefined
- //ones later
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+ // Dump some usefull information about the effect type.
+ cout << "Adding support for '" << pdei->tszName << "' effect type" << endl;
+ cout << " Supported static params: ";
+ if (pdei->dwStaticParams & DIEP_AXES) cout << " Axes";
+ if (pdei->dwStaticParams & DIEP_DIRECTION) cout << " Direction";
+ if (pdei->dwStaticParams & DIEP_DURATION) cout << " Duration";
+ if (pdei->dwStaticParams & DIEP_ENVELOPE) cout << " Envelope";
+ if (pdei->dwStaticParams & DIEP_GAIN) cout << " Gain";
+ if (pdei->dwStaticParams & DIEP_SAMPLEPERIOD) cout << " SamplePeriod";
+ if (pdei->dwStaticParams & DIEP_STARTDELAY) cout << " StartDelay";
+ if (pdei->dwStaticParams & DIEP_TRIGGERBUTTON) cout << " TriggerButton";
+ if (pdei->dwStaticParams & DIEP_TRIGGERREPEATINTERVAL) cout << " TriggerRepeatInterval";
+ if (pdei->dwStaticParams & DIEP_TYPESPECIFICPARAMS) cout << " TypeSpecificParams";
+ cout << endl;
+ cout << " Supported dynamic params: ";
+ if (pdei->dwDynamicParams & DIEP_AXES) cout << " Axes";
+ if (pdei->dwDynamicParams & DIEP_DIRECTION) cout << " Direction";
+ if (pdei->dwDynamicParams & DIEP_DURATION) cout << " Duration";
+ if (pdei->dwDynamicParams & DIEP_ENVELOPE) cout << " Envelope";
+ if (pdei->dwDynamicParams & DIEP_GAIN) cout << " Gain";
+ if (pdei->dwDynamicParams & DIEP_SAMPLEPERIOD) cout << " SamplePeriod";
+ if (pdei->dwDynamicParams & DIEP_STARTDELAY) cout << " StartDelay";
+ if (pdei->dwDynamicParams & DIEP_TRIGGERBUTTON) cout << " TriggerButton";
+ if (pdei->dwDynamicParams & DIEP_TRIGGERREPEATINTERVAL) cout << " TriggerRepeatInterval";
+ if (pdei->dwDynamicParams & DIEP_TYPESPECIFICPARAMS) cout << " TypeSpecificParams";
+ cout << endl;
+ cout << " More details about supported parameters support: ";
+ if (pdei->dwEffType & DIEFT_STARTDELAY) cout << " StartDelay";
+ if (pdei->dwEffType & DIEFT_FFATTACK) cout << " Attack";
+ if (pdei->dwEffType & DIEFT_FFFADE) cout << " Fade";
+ if (pdei->dwEffType & DIEFT_DEADBAND) cout << " DeadBand";
+ if (pdei->dwEffType & DIEFT_SATURATION) cout << " Saturation";
+ if (pdei->dwEffType & DIEFT_POSNEGSATURATION) cout << " PosNegaturation";
+ if (pdei->dwEffType & DIEFT_POSNEGCOEFFICIENTS) cout << " PosNegCoefficients";
+ if (pdei->dwEffType & DIEFT_HARDWARE) cout << " HardwareSpecific";
+ cout << endl;
+#endif
+
+ Effect::EForce eForce;
+ switch (DIEFT_GETTYPE(pdei->dwEffType))
+ {
+ case DIEFT_CONSTANTFORCE:
+ eForce = Effect::ConstantForce;
+ break;
+ case DIEFT_RAMPFORCE:
+ eForce = Effect::RampForce;
+ break;
+ case DIEFT_PERIODIC:
+ eForce = Effect::PeriodicForce;
+ break;
+ case DIEFT_CONDITION:
+ eForce = Effect::ConditionalForce;
+ break;
+ case DIEFT_CUSTOMFORCE:
+ eForce = Effect::CustomForce;
+ break;
+ default:
+ eForce = Effect::UnknownForce;
+#if defined (_DEBUG)
+ cout << "Win32ForceFeedback: DirectInput8 Effect type support not implemented: "
+ << "DIEFT_GETTYPE="<< (int)DIEFT_GETTYPE(pdei->dwEffType) << endl;
+#endif
+ return;
+ }
+
+ //Determine what the effect type is and how it corresponds to our OIS's Enums
+ //We could save the GUIDs too, however, we will just use the predefined ones later
if( pdei->guid == GUID_ConstantForce )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Constant );
+ _addEffectTypes(eForce, Effect::Constant );
else if( pdei->guid == GUID_Triangle )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Triangle );
+ _addEffectTypes(eForce, Effect::Triangle );
else if( pdei->guid == GUID_Spring )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Spring );
+ _addEffectTypes(eForce, Effect::Spring );
else if( pdei->guid == GUID_Friction )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Friction );
+ _addEffectTypes(eForce, Effect::Friction );
else if( pdei->guid == GUID_Square )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Square );
+ _addEffectTypes(eForce, Effect::Square );
else if( pdei->guid == GUID_Sine )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Sine );
+ _addEffectTypes(eForce, Effect::Sine );
else if( pdei->guid == GUID_SawtoothUp )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::SawToothUp );
+ _addEffectTypes(eForce, Effect::SawToothUp );
else if( pdei->guid == GUID_SawtoothDown )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::SawToothDown );
+ _addEffectTypes(eForce, Effect::SawToothDown );
else if( pdei->guid == GUID_Damper )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Damper );
+ _addEffectTypes(eForce, Effect::Damper );
else if( pdei->guid == GUID_Inertia )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Inertia );
+ _addEffectTypes(eForce, Effect::Inertia );
else if( pdei->guid == GUID_CustomForce )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Custom );
+ _addEffectTypes(eForce, Effect::Custom );
else if( pdei->guid == GUID_RampForce )
- _addEffectTypes((Effect::EForce)DIEFT_GETTYPE(pdei->dwEffType), Effect::Ramp );
+ _addEffectTypes(eForce, Effect::Ramp );
+
#if defined (_DEBUG)
//Only care about this for Debugging Purposes
//else
@@ -332,3 +535,9 @@
//}
#endif
}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_addFFAxis()
+{
+ mFFAxes++;
+}
Modified: code/branches/resource2/src/ois/win32/Win32ForceFeedback.h
===================================================================
--- code/branches/resource2/src/ois/win32/Win32ForceFeedback.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32ForceFeedback.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -33,7 +33,7 @@
{
Win32ForceFeedback() {}
public:
- Win32ForceFeedback(IDirectInputDevice8* joy);
+ Win32ForceFeedback(IDirectInputDevice8* pDIJoy, const DIDEVCAPS* pDIJoyCaps);
~Win32ForceFeedback();
/** @copydoc ForceFeedback::upload */
@@ -51,11 +51,12 @@
/** @copydoc ForceFeedback::setAutoCenterMode */
void setAutoCenterMode( bool auto_on );
- /** @copydoc ForceFeedback::getFFAxesNumber
- xxx todo - Actually return correct number
- */
- short getFFAxesNumber() {return 1;}
+ /** @copydoc ForceFeedback::getFFAxesNumber */
+ short getFFAxesNumber();
+ /** @copydoc ForceFeedback::getFFMemoryLoad */
+ unsigned short getFFMemoryLoad();
+
/**
@remarks
Internal use.. Used during enumeration to build a list of a devices
@@ -63,27 +64,45 @@
*/
void _addEffectSupport( LPCDIEFFECTINFO pdei );
+ /**
+ @remarks
+ Internal use.. Used during axis enumeration to get number of FF axes
+ support effects.
+ */
+ void _addFFAxis();
+
protected:
+
//Specific Effect Settings
void _updateConstantEffect( const Effect* effect );
void _updateRampEffect( const Effect* effect );
void _updatePeriodicEffect( const Effect* effect );
void _updateConditionalEffect( const Effect* effect );
void _updateCustomEffect( const Effect* effect );
+
//Sets the common properties to all effects
void _setCommonProperties( DIEFFECT* diEffect, DWORD* rgdwAxes,
- LONG* rglDirection, DWORD struct_size,
- LPVOID struct_type, const Effect* effect );
+ LONG* rglDirection, DIENVELOPE* diEnvelope, DWORD struct_size,
+ LPVOID struct_type, const Effect* effect, const Envelope* envelope );
//Actually do the upload
void _upload( GUID, DIEFFECT*, const Effect* );
+ // Map of currently uploaded effects (handle => effect)
typedef std::map<int,LPDIRECTINPUTEFFECT> EffectList;
EffectList mEffectList;
- //Simple unique handle creation - allows for upto 2+ million effects
+
+ //Simple unique handle creation - allows for upto 2+ billion effects
//during the lifetime of application. Hopefully, that is enough.
int mHandles;
+ // Joystick device descriptor.
IDirectInputDevice8* mJoyStick;
+
+ // Joystick capabilities.
+ const DIDEVCAPS* mpDIJoyCaps;
+
+ // Number of axis supporting FF.
+ short mFFAxes;
};
}
#endif //OIS_Win32ForceFeedBack_H
Modified: code/branches/resource2/src/ois/win32/Win32InputManager.cpp
===================================================================
--- code/branches/resource2/src/ois/win32/Win32InputManager.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32InputManager.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -74,13 +74,15 @@
hInst = GetModuleHandle(0);
- //Create the device
+ //Create the input system
hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mDirectInput, NULL );
if (FAILED(hr))
OIS_EXCEPT( E_General, "Win32InputManager::Win32InputManager >> Not able to init DirectX8 Input!");
//Ok, now we have DirectInput, parse whatever extra settings were sent to us
_parseConfigSettings( paramList );
+
+ // Enumerate devices ...
_enumerateDevices();
}
@@ -115,13 +117,15 @@
void Win32InputManager::_enumerateDevices()
{
//Enumerate all attached devices
- mDirectInput->EnumDevices(NULL, _DIEnumKbdCallback, this, DIEDFL_ATTACHEDONLY);
+ mDirectInput->EnumDevices(NULL , _DIEnumDevCallback, this, DIEDFL_ATTACHEDONLY);
}
//--------------------------------------------------------------------------------//
-BOOL CALLBACK Win32InputManager::_DIEnumKbdCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
+BOOL CALLBACK Win32InputManager::_DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
Win32InputManager *_this_ = static_cast<Win32InputManager*>(pvRef);
+
+ // Register only game devices (keyboard and mouse are managed differently).
if( GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_JOYSTICK ||
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_1STPERSON ||
Modified: code/branches/resource2/src/ois/win32/Win32InputManager.h
===================================================================
--- code/branches/resource2/src/ois/win32/Win32InputManager.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32InputManager.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -80,7 +80,7 @@
void _enumerateDevices();
//! Used during device enumeration
- static BOOL CALLBACK _DIEnumKbdCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
+ static BOOL CALLBACK _DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
//! Keep a list of all joysticks enumerated, but not in use
JoyStickInfoList unusedJoyStickList;
Modified: code/branches/resource2/src/ois/win32/Win32JoyStick.cpp
===================================================================
--- code/branches/resource2/src/ois/win32/Win32JoyStick.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32JoyStick.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -81,32 +81,37 @@
//Clear old state
mState.mAxes.clear();
- delete ff_device;
- ff_device = 0;
+ if (ff_device)
+ {
+ delete ff_device;
+ ff_device = 0;
+ }
- DIPROPDWORD dipdw;
-
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dipdw.diph.dwObj = 0;
- dipdw.diph.dwHow = DIPH_DEVICE;
- dipdw.dwData = JOYSTICK_DX_BUFFERSIZE;
-
+ // Create direct input joystick device.
if(FAILED(mDirectInput->CreateDevice(deviceGuid, &mJoyStick, NULL)))
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
+ // Set DIJoystick2 data format.
if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
+ // Set cooperative level as specified when creating input manager.
HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
-
if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
+ // Set buffer size.
+ DIPROPDWORD dipdw;
+ dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+ dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ dipdw.diph.dwObj = 0;
+ dipdw.diph.dwHow = DIPH_DEVICE;
+ dipdw.dwData = JOYSTICK_DX_BUFFERSIZE;
+
if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
- OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
+ OIS_EXCEPT( E_General, "Win32JoyStick::_initialize >> Failed to set buffer size property" );
- //Enumerate all axes/buttons/sliders/etc before aquiring
+ // Enumerate all axes/buttons/sliders/force feedback/etc before aquiring
_enumerate();
mState.clear();
@@ -117,23 +122,25 @@
//--------------------------------------------------------------------------------------------------//
void Win32JoyStick::_enumerate()
{
- //We can check force feedback here too
- DIDEVCAPS DIJoyCaps;
- DIJoyCaps.dwSize = sizeof(DIDEVCAPS);
- mJoyStick->GetCapabilities(&DIJoyCaps);
+ // Get joystick capabilities.
+ mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
+ if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
+ OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
- mPOVs = (short)DIJoyCaps.dwPOVs;
+ // => Number of POVs
+ mPOVs = (short)mDIJoyCaps.dwPOVs;
- mState.mButtons.resize(DIJoyCaps.dwButtons);
- mState.mAxes.resize(DIJoyCaps.dwAxes);
+ // => Number of buttons and axes.
+ mState.mButtons.resize(mDIJoyCaps.dwButtons);
+ mState.mAxes.resize(mDIJoyCaps.dwAxes);
+ // Enumerate all Force Feedback effects (if any)
+ mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
+
//Reset the axis mapping enumeration value
_AxisNumber = 0;
- //Enumerate Force Feedback (if any)
- mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
-
- //Enumerate and set axis constraints (and check FF Axes)
+ // Enumerate and set axis constraints (and check FF Axes)
mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
}
@@ -180,15 +187,24 @@
if (FAILED(_this->mJoyStick->SetProperty(DIPROP_RANGE, &diprg.diph)))
OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" );
- //Check if FF Axes
+ //Check if FF Axes, and if so, increment counter
if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
{
if( _this->ff_device )
{
- //todo - increment force feedback axis count
+ _this->ff_device->_addFFAxis();
}
}
+ //Force the flags for gain and auto-center support to true,
+ //as DInput has no API to query the device for these capabilities
+ //(the only way to know is to try them ...)
+ if( _this->ff_device )
+ {
+ _this->ff_device->_setGainSupport(true);
+ _this->ff_device->_setAutoCenterSupport(true);
+ }
+
return DIENUM_CONTINUE;
}
@@ -197,9 +213,9 @@
{
Win32JoyStick* _this = (Win32JoyStick*)pvRef;
- //Create the FF class after we know there is at least one effect type
+ //Create the FF instance only after we know there is at least one effect type
if( _this->ff_device == 0 )
- _this->ff_device = new Win32ForceFeedback(_this->mJoyStick);
+ _this->ff_device = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
_this->ff_device->_addEffectSupport( pdei );
Modified: code/branches/resource2/src/ois/win32/Win32JoyStick.h
===================================================================
--- code/branches/resource2/src/ois/win32/Win32JoyStick.h 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32JoyStick.h 2009-08-22 21:16:34 UTC (rev 5668)
@@ -59,6 +59,8 @@
IDirectInput8* mDirectInput;
IDirectInputDevice8* mJoyStick;
+ DIDEVCAPS mDIJoyCaps;
+
DWORD coopSetting;
GUID deviceGuid;
Modified: code/branches/resource2/src/ois/win32/Win32KeyBoard.cpp
===================================================================
--- code/branches/resource2/src/ois/win32/Win32KeyBoard.cpp 2009-08-22 20:51:21 UTC (rev 5667)
+++ code/branches/resource2/src/ois/win32/Win32KeyBoard.cpp 2009-08-22 21:16:34 UTC (rev 5668)
@@ -237,10 +237,9 @@
if( vk == 0 )
return 0;
- unsigned char buff[3] = {0,0,0};
- int ascii = ToAsciiEx(vk, kc, keyState, (LPWORD) buff, 0, layout);
- //WCHAR wide[3];
- //int ascii = ToUnicodeEx(vk, kc, keyState, wide, 3, 0, layout);
+ WCHAR buff[3] = {0};
+ int ascii = ToUnicodeEx(vk, kc, keyState, buff, 3, 0, layout);
+
if(ascii == 1 && deadKey != '\0' )
{
// A dead key is stored and we have just converted a character key
More information about the Orxonox-commit
mailing list