Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/ois/linux/EventHelpers.cpp @ 1259

Last change on this file since 1259 was 1219, checked in by rgrieder, 17 years ago

merged input branch back to trunk. Not yet tested on tardis

File size: 7.2 KB
RevLine 
[1195]1/*
2The zlib/libpng License
3
4Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
5
6This software is provided 'as-is', without any express or implied warranty. In no event will
7the authors be held liable for any damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose, including commercial
10applications, and to alter it and redistribute it freely, subject to the following
11restrictions:
12
13    1. The origin of this software must not be misrepresented; you must not claim that
14                you wrote the original software. If you use this software in a product,
15                an acknowledgment in the product documentation would be appreciated but is
16                not required.
17
18    2. Altered source versions must be plainly marked as such, and must not be
19                misrepresented as being the original software.
20
21    3. This notice may not be removed or altered from any source distribution.
22*/
23#include "linux/EventHelpers.h"
24#include "linux/LinuxPrereqs.h"
25#include "linux/LinuxForceFeedback.h"
26#include "OISException.h"
27#include "OISJoyStick.h"
28
29#include <linux/input.h>
30#include <cstring>
31
32//#define OIS_LINUX_JOY_DEBUG
33
34#ifdef OIS_LINUX_JOY_DEBUG
35# include <iostream>
36  using namespace std;
37#endif
38
39using namespace OIS;
40
41class DeviceComponentInfo
42{
43public:
44        std::vector<int> buttons, relAxes, absAxes, hats;
45};
46
47bool inline isBitSet(unsigned long bits[], unsigned int bit)
48{
49        return (bits[bit/(sizeof(long)*8)] >> ((bit)%(sizeof(long)*8))) & 1;
50}
51//-----------------------------------------------------------------------------//
52DeviceComponentInfo getComponentInfo( int deviceID )
53{
54        unsigned long info[2][((KEY_MAX-1)/(sizeof(long)*8)) +1];
55        memset( info, 0, sizeof(info) );
56
57        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]);
61
62        for (int i = 0; i < EV_MAX; i++)
63        {
64                if( isBitSet(info[0], i) )
65                {
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++)
69                        {
70                                if( isBitSet(info[1], j) )
71                                {
72                                        if(i == EV_ABS)
73                                        {
74                                                //input_absinfo abInfo;
75                                                //ioctl( fd, EVIOCGABS(j), abInfo );
76                                                if( j >= ABS_HAT0X && j <= ABS_HAT3Y )
77                                                {
78                                                        components.hats.push_back(j);
79                                                }
80                                                else
81                                                {
82                                                        components.absAxes.push_back(j);
83                                                        //input_absinfo absinfo;
84                                                        //ioctl(deviceID, EVIOCGABS(j), &absinfo);
85                                                        //We cannot actually change these values :|
86                                                        //absinfo.minimum = JoyStick::MIN_AXIS;
87                                                        //absinfo.maximum = JoyStick::MAX_AXIS;
88                                                        //ioctl(deviceID, EVIOCSABS(j), &absinfo);
89                                                }
90                                        }
91                                        else if(i == EV_REL)
92                                        {
93                                                components.relAxes.push_back(j);
94                                        }
95                                        else if(i == EV_KEY)
96                                        {
97                                                components.buttons.push_back(j);
98                                        }
99                                }
100                        }
101                }
102        }
103
104        return components;
105}
106
107//-----------------------------------------------------------------------------//
108bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js )
109{
110        if( deviceID == -1 ) OIS_EXCEPT( E_General, "Error with File Descriptor" );
111
112        DeviceComponentInfo info = getComponentInfo( deviceID );
113
114        int buttons = 0;
115        bool joyButtonFound = false;
116        js.button_map.clear();
117
118        #ifdef OIS_LINUX_JOY_DEBUG
119          cout << "\n\nDisplaying ButtonMapping Status:";
120        #endif
121        for(std::vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
122        {
123                //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 ) )
125                        joyButtonFound = true;
126
127                js.button_map[*i] = buttons++;
128
129                #ifdef OIS_LINUX_JOY_DEBUG
130                  cout << "\nButton Mapping ID (hex): " << hex << *i << " OIS Button Num: " << dec << (buttons-1);
131                #endif
132        }
133
134        //Joy Buttons found, so it must be a joystick or pad
135        if( joyButtonFound )
136        {
137                js.joyFileD = deviceID;
138                js.vendor = getName(deviceID);
139                js.buttons = buttons;
140                js.axes = info.relAxes.size() + info.absAxes.size();
141                js.hats = info.hats.size();
142
143                //Map the Axes
144                #ifdef OIS_LINUX_JOY_DEBUG
145                  cout << "\n\nDisplaying AxisMapping Status:";
146                #endif
147                int axes = 0;
148                for(std::vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
149                {
150                        js.axis_map[*i] = axes;
151
152                        input_absinfo absinfo;
153                        ioctl(deviceID, EVIOCGABS(*i), &absinfo);
154                        js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum);
155
156                        #ifdef OIS_LINUX_JOY_DEBUG
157                          cout << "\nAxis Mapping ID (hex): " << hex << *i << " OIS Axis Num: " << dec << axes;
158                        #endif
159
160                        ++axes;
161                }
162        }
163
164        return joyButtonFound;
165}
166
167//-----------------------------------------------------------------------------//
168std::string EventUtils::getName( int deviceID )
169{
170        char name[OIS_DEVICE_NAME];
171        ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name);
172        return std::string(name);
173}
174
175//-----------------------------------------------------------------------------//
176void EventUtils::enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff )
177{
178        //Linux Event to OIS Event Mappings
179        std::map<int, Effect::EType> typeMap;
180        typeMap[FF_CONSTANT] = Effect::Constant;
181        typeMap[FF_RAMP]     = Effect::Ramp;
182        typeMap[FF_SPRING]   = Effect::Spring;
183        typeMap[FF_FRICTION] = Effect::Friction;
184        typeMap[FF_SQUARE]   = Effect::Square;
185        typeMap[FF_TRIANGLE] = Effect::Triangle;
186        typeMap[FF_SINE]     = Effect::Sine;
187        typeMap[FF_SAW_UP]   = Effect::SawToothUp;
188        typeMap[FF_SAW_DOWN] = Effect::SawToothDown;
189        typeMap[FF_DAMPER]   = Effect::Damper;
190        typeMap[FF_INERTIA]  = Effect::Inertia;
191        typeMap[FF_CUSTOM]   = Effect::Custom;
192
193        std::map<int, Effect::EForce> forceMap;
194        forceMap[FF_CONSTANT] = Effect::ConstantForce;
195        forceMap[FF_RAMP] = Effect::RampForce;
196        forceMap[FF_PERIODIC] = Effect::PeriodicForce;
197        forceMap[FF_CUSTOM] = Effect::CustomForce;
198
199        //Remove any previously existing memory and create fresh
200        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);
208
209        //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
213
214        //FF Effects
215        for( int effect = ABS_WHEEL+1; effect < FF_MAX; effect++ )
216        {
217                if(isBitSet(info, effect))
218                {
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                        }
228                }
229        }
230
231        //Check to see if any effects were added, else destroy the pointer
232        const ForceFeedback::SupportedEffectList &list = (*ff)->getSupportedEffects();
233        if( list.size() == 0 )
234                removeForceFeedback( ff );
235}
236
237//-----------------------------------------------------------------------------//
238void EventUtils::removeForceFeedback( LinuxForceFeedback** ff )
239{
240        delete *ff;
241        *ff = 0;
242}
Note: See TracBrowser for help on using the repository browser.