Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Aug 30, 2009, 2:22:00 AM (15 years ago)
Author:
rgrieder
Message:

Merged resource2 branch back to trunk.

IMPORTANT NOTE:
Upon this merge you need to specifically call your data directory "data_extern" when checking it out (when you don't provide a name, it will be just called 'trunk').
The new CMake variable is EXTERNAL_DATA_DIRECTORY. DATA_DIRECTORY now points to the one the source part of the repository.
UPDATE YOUR DATA DIRECTORY AS WELL!!!

Location:
code/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/ois/linux/EventHelpers.cpp

    r1505 r5695  
    3434#ifdef OIS_LINUX_JOY_DEBUG
    3535# include <iostream>
    36   using namespace std;
    37 #endif
    38 
     36#endif
     37
     38// Fixes for missing macros in input.h
     39#ifndef FF_EFFECT_MIN
     40#define FF_EFFECT_MIN FF_RUMBLE
     41#endif
     42#ifndef FF_EFFECT_MAX
     43#define FF_EFFECT_MAX FF_RAMP
     44#endif
     45#ifndef FF_WAVEFORM_MIN
     46#define FF_WAVEFORM_MIN FF_SQUARE
     47#endif
     48#ifndef FF_WAVEFORM_MAX
     49#define FF_WAVEFORM_MAX FF_CUSTOM
     50#endif
     51
     52using namespace std;
    3953using namespace OIS;
    4054
     
    4256{
    4357public:
    44         std::vector<int> buttons, relAxes, absAxes, hats;
     58        vector<int> buttons, relAxes, absAxes, hats;
    4559};
    4660
    47 bool inline isBitSet(unsigned long bits[], unsigned int bit)
    48 {
    49         return (bits[bit/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1;
    50 }
     61bool inline isBitSet(unsigned char bits[], unsigned int bit)
     62{
     63  return (bits[(bit)/(sizeof(unsigned char)*8)] >> ((bit)%(sizeof(unsigned char)*8))) & 1;
     64}
     65
    5166//-----------------------------------------------------------------------------//
    5267DeviceComponentInfo getComponentInfo( int deviceID )
    5368{
    54         unsigned long info[2][((KEY_MAX-1)/(sizeof(long)*8)) +1];
    55         memset( info, 0, sizeof(info) );
     69        unsigned char ev_bits[1 + EV_MAX/8/sizeof(unsigned char)];
     70        memset( ev_bits, 0, sizeof(ev_bits) );
     71
     72        //Read "all" (hence 0) components of the device
     73#ifdef OIS_LINUX_JOY_DEBUG
     74        cout << "EventUtils::getComponentInfo(" << deviceID
     75                 << ") : Reading device events features" << endl;
     76#endif
     77        if (ioctl(deviceID, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1)
     78                OIS_EXCEPT( E_General, "Could not read device events features");
    5679
    5780        DeviceComponentInfo components;
    58 
    59         //Read "all" (hence 0) components of the device - read into first entry
    60         ioctl(deviceID, EVIOCGBIT(0, EV_MAX), info[0]);
    6181
    6282        for (int i = 0; i < EV_MAX; i++)
    6383        {
    64                 if( isBitSet(info[0], i) )
     84                if( isBitSet(ev_bits, i) )
    6585                {
    66                         memset( info[1], 0, sizeof(info) / 2 );
    67                         ioctl(deviceID, EVIOCGBIT(i, KEY_MAX), info[1]);
    68                         for (int j = 0; j < KEY_MAX; j++)
     86                    // Absolute axis.
     87                    if(i == EV_ABS)
    6988                        {
    70                                 if( isBitSet(info[1], j) )
     89                            unsigned char abs_bits[1 + ABS_MAX/8/sizeof(unsigned char)];
     90                            memset( abs_bits, 0, sizeof(abs_bits) );
     91
     92#ifdef OIS_LINUX_JOY_DEBUG
     93                                cout << "EventUtils::getComponentInfo(" << deviceID
     94                                         << ") : Reading device absolute axis features" << endl;
     95#endif
     96
     97                                if (ioctl(deviceID, EVIOCGBIT(i, sizeof(abs_bits)), abs_bits) == -1)
     98                                    OIS_EXCEPT( E_General, "Could not read device absolute axis features");
     99
     100                                for (int j = 0; j < ABS_MAX; j++)
    71101                                {
    72                                         if(i == EV_ABS)
     102                                    if( isBitSet(abs_bits, j) )
    73103                                        {
    74104                                                //input_absinfo abInfo;
     
    89119                                                }
    90120                                        }
    91                                         else if(i == EV_REL)
     121                                }
     122                        }
     123                        else if(i == EV_REL)
     124                        {
     125                            unsigned char rel_bits[1 + REL_MAX/8/sizeof(unsigned char)];
     126                                memset( rel_bits, 0, sizeof(rel_bits) );
     127                               
     128#ifdef OIS_LINUX_JOY_DEBUG
     129                                cout << "EventUtils::getComponentInfo(" << deviceID
     130                                         << ") : Reading device relative axis features" << endl;
     131#endif
     132
     133                                if (ioctl(deviceID, EVIOCGBIT(i, sizeof(rel_bits)), rel_bits) == -1)
     134                                    OIS_EXCEPT( E_General, "Could not read device relative axis features");
     135                               
     136                                for (int j = 0; j < REL_MAX; j++)
     137                                {
     138                                    if( isBitSet(rel_bits, j) )
    92139                                        {
    93                                                 components.relAxes.push_back(j);
     140                                            components.relAxes.push_back(j);
    94141                                        }
    95                                         else if(i == EV_KEY)
     142                                }
     143                        }
     144                        else if(i == EV_KEY)
     145                        {
     146                            unsigned char key_bits[1 + KEY_MAX/8/sizeof(unsigned char)];
     147                                memset( key_bits, 0, sizeof(key_bits) );
     148                               
     149#ifdef OIS_LINUX_JOY_DEBUG
     150                                cout << "EventUtils::getComponentInfo(" << deviceID
     151                                         << ") : Reading device buttons features" << endl;
     152#endif
     153
     154                                if (ioctl(deviceID, EVIOCGBIT(i, sizeof(key_bits)), key_bits) == -1)
     155                                    OIS_EXCEPT( E_General, "Could not read device buttons features");
     156                               
     157                                for (int j = 0; j < KEY_MAX; j++)
     158                                {
     159                                    if( isBitSet(key_bits, j) )
    96160                                        {
    97                                                 components.buttons.push_back(j);
     161                                            components.buttons.push_back(j);
    98162                                        }
    99163                                }
     
    108172bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js )
    109173{
    110         if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" );
     174        if( deviceID == -1 )
     175                OIS_EXCEPT( E_General, "Error with File Descriptor" );
    111176
    112177        DeviceComponentInfo info = getComponentInfo( deviceID );
     
    117182
    118183        #ifdef OIS_LINUX_JOY_DEBUG
    119           cout << "\n\nDisplaying ButtonMapping Status:";
     184        cout << endl << "Displaying ButtonMapping Status:" << endl;
    120185        #endif
    121         for(std::vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
     186        for(vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
    122187        {
    123188                //Check to ensure we find at least one joy only button
    124                 if( (*i >= BTN_JOYSTICK && *i <= BTN_THUMBR) || (*i >= BTN_WHEEL && *i <= BTN_GEAR_UP ) )
     189                if( (*i >= BTN_JOYSTICK && *i < BTN_GAMEPAD) 
     190                        || (*i >= BTN_GAMEPAD && *i < BTN_DIGI)
     191                        || (*i >= BTN_WHEEL && *i < KEY_OK) )
    125192                        joyButtonFound = true;
    126193
     
    128195
    129196                #ifdef OIS_LINUX_JOY_DEBUG
    130                   cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1);
     197                  cout << "Button Mapping ID (hex): " << hex << *i
     198                           << " OIS Button Num: " << dec << buttons-1 << endl;
    131199                #endif
    132200        }
     201        #ifdef OIS_LINUX_JOY_DEBUG
     202        cout << endl;
     203        #endif
    133204
    134205        //Joy Buttons found, so it must be a joystick or pad
     
    140211                js.axes = info.relAxes.size() + info.absAxes.size();
    141212                js.hats = info.hats.size();
     213                #ifdef OIS_LINUX_JOY_DEBUG
     214                  cout << endl << "Device name:" << js.vendor << endl;
     215                  cout << "Device unique Id:" << getUniqueId(deviceID) << endl;
     216                  cout << "Device physical location:" << getPhysicalLocation(deviceID) << endl;
     217                #endif
    142218
    143219                //Map the Axes
    144220                #ifdef OIS_LINUX_JOY_DEBUG
    145                   cout << "\n\nDisplaying AxisMapping Status:";
     221                  cout << endl << "Displaying AxisMapping Status:" << endl;
    146222                #endif
    147223                int axes = 0;
    148                 for(std::vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
     224                for(vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
    149225                {
    150226                        js.axis_map[*i] = axes;
    151227
     228#ifdef OIS_LINUX_JOY_DEBUG
     229                        cout << "EventUtils::isJoyStick(" << deviceID
     230                                          << ") : Reading device absolute axis #" << *i << " features" << endl;
     231#endif
     232
    152233                        input_absinfo absinfo;
    153                         ioctl(deviceID, EVIOCGABS(*i), &absinfo);
     234                        if (ioctl(deviceID, EVIOCGABS(*i), &absinfo) == -1)
     235                                OIS_EXCEPT( E_General, "Could not read device absolute axis features");
    154236                        js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum);
    155237
    156238                        #ifdef OIS_LINUX_JOY_DEBUG
    157                           cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes;
     239                          cout << "Axis Mapping ID (hex): " << hex << *i
     240                                   << " OIS Axis Num: " << dec << axes << endl;
    158241                        #endif
    159242
     
    166249
    167250//-----------------------------------------------------------------------------//
    168 std::string EventUtils::getName( int deviceID )
    169 {
     251string EventUtils::getName( int deviceID )
     252{
     253#ifdef OIS_LINUX_JOY_DEBUG
     254        cout << "EventUtils::getName(" << deviceID
     255                 << ") : Reading device name" << endl;
     256#endif
     257
    170258        char name[OIS_DEVICE_NAME];
    171         ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name);
    172         return std::string(name);
     259        if (ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name) == -1)
     260                OIS_EXCEPT( E_General, "Could not read device name");
     261        return string(name);
     262}
     263
     264//-----------------------------------------------------------------------------//
     265string EventUtils::getUniqueId( int deviceID )
     266{
     267#ifdef OIS_LINUX_JOY_DEBUG
     268        cout << "EventUtils::getUniqueId(" << deviceID
     269                 << ") : Reading device unique Id" << endl;
     270#endif
     271
     272#define OIS_DEVICE_UNIQUE_ID 128
     273        char uId[OIS_DEVICE_UNIQUE_ID];
     274        if (ioctl(deviceID, EVIOCGUNIQ(OIS_DEVICE_UNIQUE_ID), uId) == -1)
     275                OIS_EXCEPT( E_General, "Could not read device unique Id");
     276        return string(uId);
     277}
     278
     279//-----------------------------------------------------------------------------//
     280string EventUtils::getPhysicalLocation( int deviceID )
     281{
     282#ifdef OIS_LINUX_JOY_DEBUG
     283        cout << "EventUtils::getPhysicalLocation(" << deviceID
     284                 << ") : Reading device physical location" << endl;
     285#endif
     286
     287#define OIS_DEVICE_PHYSICAL_LOCATION 128
     288        char physLoc[OIS_DEVICE_PHYSICAL_LOCATION];
     289        if (ioctl(deviceID, EVIOCGPHYS(OIS_DEVICE_PHYSICAL_LOCATION), physLoc) == -1)
     290                OIS_EXCEPT( E_General, "Could not read device physical location");
     291        return string(physLoc);
    173292}
    174293
     
    177296{
    178297        //Linux Event to OIS Event Mappings
    179         std::map<int, Effect::EType> typeMap;
     298        map<int, Effect::EType> typeMap;
    180299        typeMap[FF_CONSTANT] = Effect::Constant;
    181300        typeMap[FF_RAMP]     = Effect::Ramp;
     
    191310        typeMap[FF_CUSTOM]   = Effect::Custom;
    192311
    193         std::map<int, Effect::EForce> forceMap;
     312        map<int, Effect::EForce> forceMap;
    194313        forceMap[FF_CONSTANT] = Effect::ConstantForce;
    195         forceMap[FF_RAMP] = Effect::RampForce;
    196         forceMap[FF_PERIODIC] = Effect::PeriodicForce;
    197         forceMap[FF_CUSTOM] = Effect::CustomForce;
     314        forceMap[FF_RAMP]     = Effect::RampForce;
     315        forceMap[FF_SPRING]   = Effect::ConditionalForce;
     316        forceMap[FF_FRICTION] = Effect::ConditionalForce;
     317        forceMap[FF_SQUARE]   = Effect::PeriodicForce;
     318        forceMap[FF_TRIANGLE] = Effect::PeriodicForce;
     319        forceMap[FF_SINE]     = Effect::PeriodicForce;
     320        forceMap[FF_SAW_UP]   = Effect::PeriodicForce;
     321        forceMap[FF_SAW_DOWN] = Effect::PeriodicForce;
     322        forceMap[FF_DAMPER]   = Effect::ConditionalForce;
     323        forceMap[FF_INERTIA]  = Effect::ConditionalForce;
     324        forceMap[FF_CUSTOM]   = Effect::CustomForce;
    198325
    199326        //Remove any previously existing memory and create fresh
    200327        removeForceFeedback( ff );
    201         *ff = new LinuxForceFeedback();
    202 
    203         unsigned long info[4] = {0,0,0,0};
    204         unsigned long subinfo[4]= {0,0,0,0};
    205 
    206         //Read overall force feedback components of the device
    207         ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(long)*4), info);
     328        *ff = new LinuxForceFeedback(deviceID);
     329
     330        //Read overall force feedback features
     331        unsigned char ff_bits[1 + FF_MAX/8/sizeof(unsigned char)];
     332        memset(ff_bits, 0, sizeof(ff_bits));
     333
     334#ifdef OIS_LINUX_JOY_DEBUG
     335        cout << "EventUtils::enumerateForceFeedback(" << deviceID
     336                 << ") : Reading device force feedback features" << endl;
     337#endif
     338
     339        if (ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(ff_bits)), ff_bits) == -1)
     340                OIS_EXCEPT( E_General, "Could not read device force feedback features");
     341
     342
     343    #ifdef OIS_LINUX_JOY_DEBUG
     344        cout << "FF bits: " << hex;
     345        for (int i = 0; i < sizeof(ff_bits); i++)
     346                cout << (int)ff_bits[i];
     347        cout << endl << dec;
     348    #endif
    208349
    209350        //FF Axes
    210         //if( isBitSet(info, ABS_X) ) //X Axis
    211         //if( isBitSet(info, ABS_Y) ) //Y Axis
    212         //if( isBitSet(info, ABS_WHEEL) ) //Wheel
     351        //if( isBitSet(ff_bits, ABS_X) ) //X Axis
     352        //if( isBitSet(ff_bits, ABS_Y) ) //Y Axis
     353        //if( isBitSet(ff_bits, ABS_WHEEL) ) //Wheel
    213354
    214355        //FF Effects
    215         for( int effect = ABS_WHEEL+1; effect < FF_MAX; effect++ )
     356        for( int effect = FF_EFFECT_MIN; effect <= FF_WAVEFORM_MAX; effect++ )
    216357        {
    217                 if(isBitSet(info, effect))
     358                // The RUMBLE force type is ignored, as periodic force one is more powerfull.
     359                // The PERIODIC force type is processed later, for each associated periodic effect type.
     360                if (effect == FF_RUMBLE || effect == FF_PERIODIC)
     361                        continue;
     362
     363                if(isBitSet(ff_bits, effect))
    218364                {
    219                         //std::cout << "\tEffect Type: " << effect << std::endl;
    220                         memset(subinfo, 0, sizeof(subinfo));
    221                         //Read any info about this supported effect
    222                         ioctl(deviceID, EVIOCGBIT(effect, sizeof(long)*4), subinfo);
    223                         for( int force = 0; force < FF_MAX; force++ )
    224                         {
    225                                 if(isBitSet(subinfo, force))
    226                                         (*ff)->_addEffectTypes( forceMap[force], typeMap[effect] );
    227                         }
     365                        #ifdef OIS_LINUX_JOY_DEBUG
     366                    cout << "  Effect Type: " << Effect::getEffectTypeName(typeMap[effect]) << endl;
     367                        #endif
     368
     369                        (*ff)->_addEffectTypes( forceMap[effect], typeMap[effect] );
    228370                }
    229371        }
     372
     373        //FF device properties
     374        if (isBitSet(ff_bits, FF_GAIN))
     375                (*ff)->_setGainSupport(true);
     376               
     377        if (isBitSet(ff_bits, FF_AUTOCENTER))
     378                (*ff)->_setAutoCenterSupport(true);
    230379
    231380        //Check to see if any effects were added, else destroy the pointer
  • code/trunk/src/ois/linux/EventHelpers.h

    r1505 r5695  
    4343
    4444                static std::string getName( int deviceID );
     45                static std::string getUniqueId( int deviceID );
     46                static std::string getPhysicalLocation( int deviceID );
    4547        };
    4648}
  • code/trunk/src/ois/linux/LinuxForceFeedback.cpp

    r1505 r5695  
    2424#include "OISException.h"
    2525
     26#include <cstdlib>
     27#include <errno.h>
     28#include <memory.h>
     29
    2630using namespace OIS;
    2731
    28 //--------------------------------------------------------------//
    29 LinuxForceFeedback::LinuxForceFeedback()
    30 {
    31 }
     32// 0 = No trace; 1 = Important traces; 2 = Debug traces
     33#define OIS_LINUX_JOYFF_DEBUG 1
     34
     35#ifdef OIS_LINUX_JOYFF_DEBUG
     36# include <iostream>
     37  using namespace std;
     38#endif
     39
     40//--------------------------------------------------------------//
     41LinuxForceFeedback::LinuxForceFeedback(int deviceID) :
     42        ForceFeedback(), mJoyStick(deviceID)
     43{
     44}
     45
    3246//--------------------------------------------------------------//
    3347LinuxForceFeedback::~LinuxForceFeedback()
    3448{
    35 }
    36 
    37 //--------------------------------------------------------------//
    38 void LinuxForceFeedback::setMasterGain(float)
    39 {
    40 }
    41 
    42 //--------------------------------------------------------------//
    43 void LinuxForceFeedback::setAutoCenterMode(bool)
    44 {
    45 }
    46 
    47 //--------------------------------------------------------------//
    48 void LinuxForceFeedback::upload( const Effect* /*effect*/ )
    49 {
    50 }
    51 
    52 //--------------------------------------------------------------//
    53 void LinuxForceFeedback::modify( const Effect* /*effect*/ )
    54 {
    55 }
    56 
    57 //--------------------------------------------------------------//
    58 void LinuxForceFeedback::remove( const Effect* /*effect*/ )
    59 {
    60 }
    61 
     49        // Unload all effects.
     50        for(EffectList::iterator i = mEffectList.begin(); i != mEffectList.end(); ++i )
     51        {
     52                struct ff_effect *linEffect = i->second;
     53                if( linEffect )
     54                        _unload(linEffect->id);
     55        }
     56
     57        mEffectList.clear();
     58}
     59
     60//--------------------------------------------------------------//
     61unsigned short LinuxForceFeedback::getFFMemoryLoad()
     62{
     63        int nEffects = -1;
     64        if (ioctl(mJoyStick, EVIOCGEFFECTS, &nEffects) == -1)
     65                OIS_EXCEPT(E_General, "Unknown error reading max number of uploaded effects.");
     66#if (OIS_LINUX_JOYFF_DEBUG > 1)
     67        cout << "LinuxForceFeedback("<< mJoyStick 
     68                 << ") : Read device max number of uploaded effects : " << nEffects << endl;
     69#endif
     70
     71        return (unsigned short int)(nEffects > 0 ? 100.0*mEffectList.size()/nEffects : 100);
     72}
     73
     74//--------------------------------------------------------------//
     75void LinuxForceFeedback::setMasterGain(float value)
     76{
     77        if (!mSetGainSupport)
     78        {
     79#if (OIS_LINUX_JOYFF_DEBUG > 0)
     80                cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain "
     81                         << "is not supported by the device" << endl;
     82#endif
     83                return;
     84        }
     85
     86        struct input_event event;
     87
     88        memset(&event, 0, sizeof(event));
     89        event.type = EV_FF;
     90        event.code = FF_GAIN;
     91        if (value < 0.0)
     92                value = 0.0;
     93        else if (value > 1.0)
     94                value = 1.0;
     95        event.value = (__s32)(value * 0xFFFFUL);
     96
     97#if (OIS_LINUX_JOYFF_DEBUG > 0)
     98        cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain to "
     99                 << value << " => " << event.value << endl;
     100#endif
     101
     102        if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
     103                OIS_EXCEPT(E_General, "Unknown error changing master gain.");
     104        }
     105}
     106
     107//--------------------------------------------------------------//
     108void LinuxForceFeedback::setAutoCenterMode(bool enabled)
     109{
     110        if (!mSetAutoCenterSupport)
     111        {
     112#if (OIS_LINUX_JOYFF_DEBUG > 0)
     113                cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting auto-center mode "
     114                         << "is not supported by the device" << endl;
     115#endif
     116                return;
     117        }
     118
     119        struct input_event event;
     120
     121        memset(&event, 0, sizeof(event));
     122        event.type = EV_FF;
     123        event.code = FF_AUTOCENTER;
     124        event.value = (__s32)(enabled*0xFFFFFFFFUL);
     125
     126#if (OIS_LINUX_JOYFF_DEBUG > 0)
     127        cout << "LinuxForceFeedback("<< mJoyStick << ") : Toggling auto-center to "
     128                 << enabled << " => 0x" << hex << event.value << dec << endl;
     129#endif
     130
     131        if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
     132                OIS_EXCEPT(E_General, "Unknown error toggling auto-center.");
     133        }
     134}
     135
     136//--------------------------------------------------------------//
     137void LinuxForceFeedback::upload( const Effect* effect )
     138{
     139        switch( effect->force )
     140        {
     141                case OIS::Effect::ConstantForce:
     142                        _updateConstantEffect(effect); 
     143                        break;
     144                case OIS::Effect::ConditionalForce:
     145                        _updateConditionalEffect(effect);
     146                        break;
     147                case OIS::Effect::PeriodicForce:
     148                        _updatePeriodicEffect(effect);
     149                        break;
     150                case OIS::Effect::RampForce:
     151                        _updateRampEffect(effect);     
     152                        break;
     153                case OIS::Effect::CustomForce:
     154                        //_updateCustomEffect(effect);
     155                        //break;
     156                default:
     157                        OIS_EXCEPT(E_NotImplemented, "Requested force not implemented yet, sorry!");
     158                        break;
     159        }
     160}
     161
     162//--------------------------------------------------------------//
     163void LinuxForceFeedback::modify( const Effect* effect )
     164{
     165        upload(effect);
     166}
     167
     168//--------------------------------------------------------------//
     169void LinuxForceFeedback::remove( const Effect* effect )
     170{
     171        //Get the effect - if it exists
     172        EffectList::iterator i = mEffectList.find(effect->_handle);
     173        if( i != mEffectList.end() )
     174        {
     175                struct ff_effect *linEffect = i->second;
     176                if( linEffect )
     177                {
     178                        _stop(effect->_handle);
     179
     180                        _unload(effect->_handle);
     181
     182                        free(linEffect);
     183
     184                        mEffectList.erase(i);
     185                }
     186                else
     187                        mEffectList.erase(i);
     188        }
     189}
     190
     191//--------------------------------------------------------------//
     192// To Signed16/Unsigned15 safe conversions
     193#define MaxUnsigned15Value 0x7FFF
     194#define toUnsigned15(value) \
     195        (__u16)((value) < 0 ? 0 : ((value) > MaxUnsigned15Value ? MaxUnsigned15Value : (value)))
     196
     197#define MaxSigned16Value  0x7FFF
     198#define MinSigned16Value -0x7FFF
     199#define toSigned16(value) \
     200  (__s16)((value) < MinSigned16Value ? MinSigned16Value : ((value) > MaxSigned16Value ? MaxSigned16Value : (value)))
     201
     202// OIS to Linux duration
     203#define LinuxInfiniteDuration 0xFFFF
     204#define OISDurationUnitMS 1000 // OIS duration unit (microseconds), expressed in milliseconds (theLinux duration unit)
     205
     206// linux/input.h : All duration values are expressed in ms. Values above 32767 ms (0x7fff)
     207//                 should not be used and have unspecified results.
     208#define LinuxDuration(oisDuration) ((oisDuration) == Effect::OIS_INFINITE ? LinuxInfiniteDuration \
     209                                                                        : toUnsigned15((oisDuration)/OISDurationUnitMS))
     210
     211
     212// OIS to Linux levels
     213#define OISMaxLevel 10000
     214#define LinuxMaxLevel 0x7FFF
     215
     216// linux/input.h : Valid range for the attack and fade levels is 0x0000 - 0x7fff
     217#define LinuxPositiveLevel(oisLevel) toUnsigned15(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
     218
     219#define LinuxSignedLevel(oisLevel) toSigned16(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
     220
     221
     222//--------------------------------------------------------------//
     223void LinuxForceFeedback::_setCommonProperties(struct ff_effect *event,
     224                                                                                          struct ff_envelope *ffenvelope,
     225                                                                                          const Effect* effect, const Envelope *envelope )
     226{
     227        memset(event, 0, sizeof(struct ff_effect));
     228
     229        if (envelope && ffenvelope && envelope->isUsed()) {
     230                ffenvelope->attack_length = LinuxDuration(envelope->attackLength);
     231                ffenvelope->attack_level = LinuxPositiveLevel(envelope->attackLevel);
     232                ffenvelope->fade_length = LinuxDuration(envelope->fadeLength);
     233                ffenvelope->fade_level = LinuxPositiveLevel(envelope->fadeLevel);
     234        }
     235       
     236#if (OIS_LINUX_JOYFF_DEBUG > 1)
     237        cout << endl;
     238        if (envelope && ffenvelope)
     239        {
     240                cout << "  Enveloppe :" << endl
     241                         << "    AttackLen : " << envelope->attackLength
     242                         << " => " << ffenvelope->attack_length << endl
     243                         << "    AttackLvl : " << envelope->attackLevel
     244                         << " => " << ffenvelope->attack_level << endl
     245                         << "    FadeLen   : " << envelope->fadeLength
     246                         << " => " << ffenvelope->fade_length << endl
     247                         << "    FadeLvl   : " << envelope->fadeLevel
     248                         << " => " << ffenvelope->fade_level << endl;
     249        }
     250#endif
     251       
     252        event->direction = (__u16)(1 + (effect->direction*45.0+135.0)*0xFFFFUL/360.0);
     253
     254#if (OIS_LINUX_JOYFF_DEBUG > 1)
     255        cout << "  Direction : " << Effect::getDirectionName(effect->direction)
     256                 << " => 0x" << hex << event->direction << dec << endl;
     257#endif
     258
     259        // TODO trigger_button 0 vs. -1
     260        event->trigger.button = effect->trigger_button; // < 0 ? 0 : effect->trigger_button;
     261        event->trigger.interval = LinuxDuration(effect->trigger_interval);
     262
     263#if (OIS_LINUX_JOYFF_DEBUG > 1)
     264        cout << "  Trigger :" << endl
     265                 << "    Button   : " << effect->trigger_button
     266                 << " => " << event->trigger.button << endl
     267                 << "    Interval : " << effect->trigger_interval
     268                 << " => " << event->trigger.interval << endl;
     269#endif
     270
     271        event->replay.length = LinuxDuration(effect->replay_length);
     272        event->replay.delay = LinuxDuration(effect->replay_delay);
     273
     274#if (OIS_LINUX_JOYFF_DEBUG > 1)
     275        cout << "  Replay :" << endl
     276                 << "    Length : " << effect->replay_length
     277                 << " => " << event->replay.length << endl
     278                 << "    Delay  : " << effect->replay_delay
     279                 << " => " << event->replay.delay << endl;
     280#endif
     281}
     282
     283//--------------------------------------------------------------//
     284void LinuxForceFeedback::_updateConstantEffect( const Effect* eff )
     285{
     286        struct ff_effect event;
     287
     288        ConstantEffect *effect = static_cast<ConstantEffect*>(eff->getForceEffect());
     289
     290        _setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
     291
     292        event.type = FF_CONSTANT;
     293        event.id = -1;
     294
     295        event.u.constant.level = LinuxSignedLevel(effect->level);
     296
     297#if (OIS_LINUX_JOYFF_DEBUG > 1)
     298        cout << "  Level : " << effect->level
     299                 << " => " << event.u.constant.level << endl;
     300#endif
     301
     302        _upload(&event, eff);
     303}
     304
     305//--------------------------------------------------------------//
     306void LinuxForceFeedback::_updateRampEffect( const Effect* eff )
     307{
     308        struct ff_effect event;
     309
     310        RampEffect *effect = static_cast<RampEffect*>(eff->getForceEffect());
     311
     312        _setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
     313
     314        event.type = FF_RAMP;
     315        event.id = -1;
     316
     317        event.u.ramp.start_level = LinuxSignedLevel(effect->startLevel);
     318        event.u.ramp.end_level = LinuxSignedLevel(effect->endLevel);
     319
     320#if (OIS_LINUX_JOYFF_DEBUG > 1)
     321        cout << "  StartLevel : " << effect->startLevel
     322                 << " => " << event.u.ramp.start_level << endl
     323                 << "  EndLevel   : " << effect->endLevel
     324                 << " => " << event.u.ramp.end_level << endl;
     325#endif
     326
     327        _upload(&event, eff);
     328}
     329
     330//--------------------------------------------------------------//
     331void LinuxForceFeedback::_updatePeriodicEffect( const Effect* eff )
     332{
     333        struct ff_effect event;
     334
     335        PeriodicEffect *effect = static_cast<PeriodicEffect*>(eff->getForceEffect());
     336
     337        _setCommonProperties(&event, &event.u.periodic.envelope, eff, &effect->envelope);
     338
     339        event.type = FF_PERIODIC;
     340        event.id = -1;
     341
     342        switch( eff->type )
     343        {
     344                case OIS::Effect::Square:
     345                        event.u.periodic.waveform = FF_SQUARE;
     346                        break;
     347                case OIS::Effect::Triangle:
     348                        event.u.periodic.waveform = FF_TRIANGLE;
     349                        break;
     350                case OIS::Effect::Sine:
     351                        event.u.periodic.waveform = FF_SINE;
     352                        break;
     353                case OIS::Effect::SawToothUp:
     354                        event.u.periodic.waveform = FF_SAW_UP;
     355                        break;
     356                case OIS::Effect::SawToothDown:
     357                        event.u.periodic.waveform = FF_SAW_DOWN;
     358                        break;
     359                // Note: No support for Custom periodic force effect for the moment
     360                //case OIS::Effect::Custom:
     361                        //event.u.periodic.waveform = FF_CUSTOM;
     362                        //break;
     363                default:
     364                        OIS_EXCEPT(E_General, "No such available effect for Periodic force!");
     365                        break;
     366        }
     367
     368        event.u.periodic.period    = LinuxDuration(effect->period);
     369        event.u.periodic.magnitude = LinuxPositiveLevel(effect->magnitude);
     370        event.u.periodic.offset    = LinuxPositiveLevel(effect->offset);
     371        event.u.periodic.phase     = (__u16)(effect->phase*event.u.periodic.period/36000.0); // ?????
     372
     373        // Note: No support for Custom periodic force effect for the moment
     374        event.u.periodic.custom_len = 0;
     375        event.u.periodic.custom_data = 0;
     376
     377#if (OIS_LINUX_JOYFF_DEBUG > 1)
     378        cout << "  Magnitude : " << effect->magnitude
     379                 << " => " << event.u.periodic.magnitude << endl
     380                 << "  Period    : " << effect->period
     381                 << " => " << event.u.periodic.period  << endl
     382                 << "  Offset    : " << effect->offset
     383                 << " => " << event.u.periodic.offset << endl
     384                 << "  Phase     : " << effect->phase
     385                 << " => " << event.u.periodic.phase << endl;
     386#endif
     387
     388        _upload(&event, eff);
     389}
     390
     391//--------------------------------------------------------------//
     392void LinuxForceFeedback::_updateConditionalEffect( const Effect* eff )
     393{
     394        struct ff_effect event;
     395
     396        ConditionalEffect *effect = static_cast<ConditionalEffect*>(eff->getForceEffect());
     397
     398        _setCommonProperties(&event, NULL, eff, NULL);
     399
     400        switch( eff->type )
     401        {
     402                case OIS::Effect::Friction:
     403                        event.type = FF_FRICTION;
     404                        break;
     405                case OIS::Effect::Damper:
     406                        event.type = FF_DAMPER;
     407                        break;
     408                case OIS::Effect::Inertia:
     409                        event.type = FF_INERTIA;
     410                        break;
     411                case OIS::Effect::Spring:
     412                        event.type = FF_SPRING;
     413                        break;
     414                default:
     415                        OIS_EXCEPT(E_General, "No such available effect for Conditional force!");
     416                        break;
     417        }
     418
     419        event.id = -1;
     420
     421        event.u.condition[0].right_saturation = LinuxSignedLevel(effect->rightSaturation);
     422        event.u.condition[0].left_saturation  = LinuxSignedLevel(effect->leftSaturation);
     423        event.u.condition[0].right_coeff      = LinuxSignedLevel(effect->rightCoeff);
     424        event.u.condition[0].left_coeff       = LinuxSignedLevel(effect->leftCoeff);
     425        event.u.condition[0].deadband         = LinuxPositiveLevel(effect->deadband);// Unit ??
     426        event.u.condition[0].center           = LinuxSignedLevel(effect->center); // Unit ?? TODO ?
     427
     428        // TODO support for second condition
     429        event.u.condition[1] = event.u.condition[0];
     430
     431#if (OIS_LINUX_JOYFF_DEBUG > 1)
     432        cout << "  Condition[0] : " << endl
     433                 << "    RightSaturation  : " << effect->rightSaturation
     434                 << " => " << event.u.condition[0].right_saturation << endl
     435                 << "    LeftSaturation   : " << effect->leftSaturation
     436                 << " => " << event.u.condition[0]. left_saturation << endl
     437                 << "    RightCoefficient : " << effect->rightCoeff
     438                 << " => " << event.u.condition[0].right_coeff << endl
     439                 << "    LeftCoefficient : " << effect->leftCoeff
     440                 << " => " << event.u.condition[0].left_coeff << endl
     441                 << "    DeadBand        : " << effect->deadband
     442                 << " => " << event.u.condition[0].deadband  << endl
     443                 << "    Center          : " << effect->center
     444                 << " => " << event.u.condition[0].center << endl;
     445        cout << "  Condition[1] : Not implemented" << endl;
     446#endif
     447        _upload(&event, eff);
     448}
     449
     450//--------------------------------------------------------------//
     451void LinuxForceFeedback::_upload( struct ff_effect* ffeffect, const Effect* effect)
     452{
     453        struct ff_effect *linEffect = 0;
     454
     455        //Get the effect - if it exists
     456        EffectList::iterator i = mEffectList.find(effect->_handle);
     457        //It has been created already
     458        if( i != mEffectList.end() )
     459                linEffect = i->second;
     460
     461        if( linEffect == 0 )
     462        {
     463#if (OIS_LINUX_JOYFF_DEBUG > 1)
     464                cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Adding new effect : "
     465                         << Effect::getEffectTypeName(effect->type) << endl;
     466#endif
     467
     468                //This effect has not yet been created, so create it in the device
     469                if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
     470                        // TODO device full check
     471                        // OIS_EXCEPT(E_DeviceFull, "Remove an effect before adding more!");
     472                        OIS_EXCEPT(E_General, "Unknown error creating effect (may be the device is full)->..");
     473                }
     474
     475                // Save returned effect handle
     476                effect->_handle = ffeffect->id;
     477
     478                // Save a copy of the uploaded effect for later simple modifications
     479                linEffect = (struct ff_effect *)calloc(1, sizeof(struct ff_effect));
     480                memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
     481
     482                mEffectList[effect->_handle] = linEffect;
     483
     484                // Start playing the effect.
     485                _start(effect->_handle);
     486        }
     487        else
     488        {
     489#if (OIS_LINUX_JOYFF_DEBUG > 1)
     490                cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Replacing effect : "
     491                         << Effect::getEffectTypeName(effect->type) << endl;
     492#endif
     493
     494                // Keep same id/handle, as this is just an update in the device.
     495                ffeffect->id = effect->_handle;
     496
     497                // Update effect in the device.
     498                if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
     499                        OIS_EXCEPT(E_General, "Unknown error updating an effect->..");
     500                }
     501
     502                // Update local linEffect for next time.
     503                memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
     504        }
     505
     506#if (OIS_LINUX_JOYFF_DEBUG > 1)
     507        cout << "LinuxForceFeedback("<< mJoyStick
     508                 << ") : Effect handle : " << effect->_handle << endl;
     509#endif
     510}
     511
     512//--------------------------------------------------------------//
     513void LinuxForceFeedback::_stop( int handle) {
     514        struct input_event stop;
     515
     516        stop.type = EV_FF;
     517        stop.code = handle;
     518        stop.value = 0;
     519
     520#if (OIS_LINUX_JOYFF_DEBUG > 1)
     521        cout << endl << "LinuxForceFeedback("<< mJoyStick
     522                 << ") : Stopping effect with handle " << handle << endl;
     523#endif
     524
     525        if (write(mJoyStick, &stop, sizeof(stop)) != sizeof(stop)) {
     526                OIS_EXCEPT(E_General, "Unknown error stopping effect->..");
     527        }
     528}
     529
     530//--------------------------------------------------------------//
     531void LinuxForceFeedback::_start( int handle) {
     532        struct input_event play;
     533
     534        play.type = EV_FF;
     535        play.code = handle;
     536        play.value = 1; // Play once.
     537
     538#if (OIS_LINUX_JOYFF_DEBUG > 1)
     539        cout << endl << "LinuxForceFeedback("<< mJoyStick
     540                 << ") : Starting effect with handle " << handle << endl;
     541#endif
     542
     543        if (write(mJoyStick, &play, sizeof(play)) != sizeof(play)) {
     544                OIS_EXCEPT(E_General, "Unknown error playing effect->..");
     545        }
     546}
     547
     548//--------------------------------------------------------------//
     549void LinuxForceFeedback::_unload( int handle)
     550{
     551#if (OIS_LINUX_JOYFF_DEBUG > 1)
     552        cout << endl << "LinuxForceFeedback("<< mJoyStick
     553                 << ") : Removing effect with handle " << handle << endl;
     554#endif
     555
     556        if (ioctl(mJoyStick, EVIOCRMFF, handle) == -1) {
     557                OIS_EXCEPT(E_General, "Unknown error removing effect->..");
     558        }
     559}
  • code/trunk/src/ois/linux/LinuxForceFeedback.h

    r1505 r5695  
    2626#include "linux/LinuxPrereqs.h"
    2727#include "OISForceFeedback.h"
     28#include <linux/input.h>
    2829
    2930namespace OIS
     
    3233        {
    3334        public:
    34                 LinuxForceFeedback();
     35                LinuxForceFeedback(int deviceID);
    3536                ~LinuxForceFeedback();
    3637
     
    5051                void remove( const Effect* effect );
    5152
    52                 /** FF is not yet implemented fully on Linux.. just retun 0 for now. todo, xxx */
    53                 short int getFFAxesNumber() { return 0; }
     53                /** FF is not yet implemented fully on Linux.. just return -1 for now. todo, xxx */
     54                short int getFFAxesNumber() { return -1; }
     55
     56                /** @copydoc ForceFeedback::getFFMemoryLoad */
     57                unsigned short getFFMemoryLoad();
     58
     59        protected:
     60
     61                //Sets the common properties to all effects
     62                void _setCommonProperties(struct ff_effect *event, struct ff_envelope *ffenvelope,
     63                                                                  const Effect* effect, const Envelope *envelope );
     64
     65                //Specific Effect Settings
     66                void _updateConstantEffect( const Effect* effect );
     67                void _updateRampEffect( const Effect* effect );
     68                void _updatePeriodicEffect( const Effect* effect );
     69                void _updateConditionalEffect( const Effect* effect );
     70                //void _updateCustomEffect( const Effect* effect );
     71
     72                void _upload( struct ff_effect* ffeffect, const Effect* effect);
     73                void _stop( int handle);
     74                void _start( int handle);
     75                void _unload( int handle);
     76
     77                // Map of currently uploaded effects (handle => effect)
     78                typedef std::map<int, struct ff_effect *> EffectList;
     79                EffectList mEffectList;
     80
     81                // Joystick device (file) descriptor.
     82                int mJoyStick;
    5483        };
    5584}
  • code/trunk/src/ois/linux/LinuxJoyStickEvents.cpp

    r1505 r5695  
    3737
    3838#include <sstream>
     39# include <iostream>
     40using namespace std;
    3941
    4042using namespace OIS;
    4143
    4244//#define OIS_LINUX_JOY_DEBUG
    43 
    44 #ifdef OIS_LINUX_JOY_DEBUG
    45 # include <iostream>
    46   using namespace std;
    47 #endif
    4845
    4946//-------------------------------------------------------------------//
     
    114111
    115112                        #ifdef OIS_LINUX_JOY_DEBUG
    116                           std::cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << std::endl;
     113                          cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
    117114                        #endif
    118115
     
    132129                        break;
    133130                }
    134                 case EV_ABS:  //Absoulte Axis
     131
     132                case EV_ABS:  //Absolute Axis
    135133                {
    136134                        //A Stick (BrakeDefine is the highest possible Axis)
     
    138136                        {
    139137                                int axis = mAxisMap[js[i].code];
    140                                 assert( axis < 32 && "Too many axes, not supported. Report this to OIS forums!" );
    141                                
     138                                assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
     139
    142140                                axisMoved[axis] = true;
    143141
     
    190188                        break;
    191189                }
    192                 //Relative Axes (Do any joysticks actually have a relative axis?)
    193                 case EV_REL:
     190
     191               
     192                case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
     193#ifdef OIS_LINUX_JOY_DEBUG
     194                    cout << "\nWarning: Relatives axes not supported yet" << endl;
     195#endif
     196                        break;
    194197                default: break;
    195198                }
     
    243246        for(int i = 0; i < 64; ++i )
    244247        {
    245                 std::stringstream s;
     248                stringstream s;
    246249                s << "/dev/input/event" << i;
    247                 int fd = open( s.str().c_str(), O_RDONLY |O_NONBLOCK );
     250                int fd = open( s.str().c_str(), O_RDWR |O_NONBLOCK );
    248251                if(fd == -1)
    249252                        continue;
    250                
     253
    251254        #ifdef OIS_LINUX_JOY_DEBUG
    252           std::cout << "\nOpening " << s.str() << "...";
     255                  cout << "Opening " << s.str() << "..." << endl;
    253256        #endif
    254257                try
     
    259262                                joys.push_back(js);
    260263                #ifdef OIS_LINUX_JOY_DEBUG
    261                   std::cout << "\n__Joystick added to list";
     264                  cout << "=> Joystick added to list." << endl;
    262265                #endif
    263266                        }
     
    265268                        {
    266269                #ifdef OIS_LINUX_JOY_DEBUG
    267                   std::cout << "\n__Not a joystick!!";
     270                  cout << "=> Not a joystick." << endl;
    268271                #endif
    269272                                close(fd);
     
    273276                {
    274277            #ifdef OIS_LINUX_JOY_DEBUG
    275               std::cout << "\nException caught!!";
     278              cout << "Exception caught!!" << endl;
    276279            #endif
    277280                        close(fd);
Note: See TracChangeset for help on using the changeset viewer.