Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <fstream>
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <sstream>
00016 #include <fcntl.h>
00017 #include <linux/joystick.h>
00018 #include <cstring>
00019 #include <exception>
00020 #include <iosfwd>
00021 #include <labust/xml/XMLReader.hpp>
00022 #include <boost/foreach.hpp>
00023
00024 #include "JoystickReader.h"
00025
00026 using namespace std;
00027
00028 namespace LABUST
00029 {
00034
00035 JoystickReader::JoystickReader(const std::string& path, std::string configToUse)
00036 {
00037 labust::xml::Reader reader(path,true);
00038 std::string configQuery;
00039 if (configToUse.empty())
00040 {
00041 configQuery = "//peripheralConfig[@type='joystick']";
00042 }
00043 else
00044 {
00045 configQuery = "//peripheralConfig[@type='joystick' and @name='" + configToUse + "']";
00046 }
00047
00048 int deviceNumber;
00049 bool loadButtonsCount = false, loadAxesCount = false;
00050
00051 reader.useRootNode();
00052 _xmlNode* configNode = NULL;
00053 if (reader.try_value(configQuery, &configNode))
00054 {
00055 reader.useNode(configNode);
00056
00057 if (!reader.try_value("param[@name='DeviceNumber']/@value", &deviceNumber))
00058 {
00059 throw std::runtime_error("Missing joystick number");
00060 }
00061 if(!reader.try_value("param[@name='Axes']/@value", &axes))
00062 {
00063 loadAxesCount = true;
00064 }
00065 if(!reader.try_value("param[@name='Buttons']/@value", &buttons))
00066 {
00067 loadButtonsCount = true;
00068 }
00069 }
00070 else
00071 {
00072 throw std::runtime_error("Unable to open joystick, missing config");
00073 }
00074
00075
00076 stringstream joystickPath;
00077 joystickPath << "/dev/input/js" << deviceNumber;
00078
00079
00080
00081 if ((deviceDescriptor = open(joystickPath.str().c_str(), O_RDONLY)) >= 0)
00082 {
00083 if(loadButtonsCount)
00084 {
00085 ioctl(deviceDescriptor, JSIOCGBUTTONS, &buttons);
00086 }
00087
00088 if(loadAxesCount)
00089 {
00090 ioctl(deviceDescriptor, JSIOCGAXES, &axes);
00091 }
00092
00093 axisGains.resize(axes);
00094 for(int i=0; i<axes; i++)
00095 {
00096 axisGains[i] = 1;
00097 }
00098 using namespace labust::xml;
00099
00100 NodeCollectionPtr gains = reader.value<NodeCollectionPtr>("param[@name='AxisGain']");
00101
00102 _xmlNode* curr=reader.currentNode();
00103 BOOST_FOREACH(_xmlNode* axisGain, *gains)
00104 {
00105 int axisNumber;
00106 float gain;
00107 reader.useNode(axisGain);
00108 std::string axisGainPair = reader.value<std::string>("@value");
00109 std::replace(axisGainPair.begin(),axisGainPair.end(),':',' ');
00110 std::stringstream buffer;
00111 buffer << axisGainPair;
00112 buffer >> axisNumber >> gain;
00113 axisGains[axisNumber] = gain;
00114 }
00115
00116 reader.useNode(curr);
00117 axisGains.resize(axes);
00118 joystickData.axes.resize(axes);
00119 joystickData.buttons.resize(buttons);
00120
00121
00122 }
00123 else
00124 {
00125 std::stringstream buffer;
00126 buffer<<"Error opening joystick "<<joystickPath;
00127 throw std::runtime_error(buffer.str());
00128 }
00129 running = true;
00130 joystickThread = boost::thread(boost::bind(&JoystickReader::ThreadFunction,this));
00131
00132 }
00133
00138
00139 JoystickReader::JoystickReader(const labust::xml::Reader& reader, std::string configToUse)
00140 {
00141 std::string configQuery;
00142 if (configToUse.empty())
00143 {
00144 configQuery = "peripheralConfig[@type='joystick']";
00145 }
00146 else
00147 {
00148 configQuery = "peripheralConfig[@type='joystick' and @name='" + configToUse + "']";
00149 }
00150
00151 int deviceNumber;
00152 bool loadButtonsCount = false, loadAxesCount = false;
00153
00154 _xmlNode* configNode = NULL;
00155 if (reader.try_value(configQuery, &configNode))
00156 {
00157 const_cast<labust::xml::Reader&>(reader).useNode(configNode);
00158
00159 if (!reader.try_value("param[@name='DeviceNumber']/@value", &deviceNumber))
00160 {
00161 throw std::runtime_error("Missing joystick number");
00162 }
00163 if(!reader.try_value("param[@name='Axes']/@value", &axes))
00164 {
00165 loadAxesCount = true;
00166 }
00167 if(!reader.try_value("param[@name='Buttons']/@value", &buttons))
00168 {
00169 loadButtonsCount = true;
00170 }
00171 }
00172 else
00173 {
00174 throw std::runtime_error("Unable to open joystick, missing config");
00175 }
00176
00177
00178
00179 stringstream joystickPath;
00180 joystickPath << "/dev/input/js" << deviceNumber;
00181
00182
00183
00184 if ((deviceDescriptor = open(joystickPath.str().c_str(), O_RDONLY)) >= 0)
00185 {
00186 if(loadButtonsCount)
00187 {
00188 ioctl(deviceDescriptor, JSIOCGBUTTONS, &buttons);
00189 }
00190
00191 if(loadAxesCount)
00192 {
00193 ioctl(deviceDescriptor, JSIOCGAXES, &axes);
00194 }
00195 joystickData.axes.resize(axes);
00196 joystickData.buttons.resize(buttons);
00197 }
00198 else
00199 {
00200 std::stringstream buffer;
00201 buffer<<"Error opening joystick "<<joystickPath;
00202 throw std::runtime_error(buffer.str());
00203 }
00204 running = true;
00205 joystickThread = boost::thread(boost::bind(&JoystickReader::ThreadFunction,this));
00206 }
00207
00208 JoystickReader::~JoystickReader()
00209 {
00210
00211 running = false;
00212
00213
00214 pthread_cancel(joystickThread.native_handle());
00215 pthread_join(joystickThread.native_handle(),NULL);
00216 close(deviceDescriptor);
00217 }
00218
00221
00222 JoystickData JoystickReader::ReadJoystickData()
00223 {
00224 boost::mutex::scoped_lock lockJoystickData(joystickMutex);
00225 return joystickData;
00226 }
00227
00228 void JoystickReader::ThreadFunction()
00229 {
00230 while(running)
00231 {
00232 js_event event;
00233 if (read(deviceDescriptor, &event, sizeof (event)) > 0)
00234 {
00235 boost::mutex::scoped_lock lockJoystickData(joystickMutex);
00236 switch (event.type)
00237 {
00238 case JS_EVENT_AXIS:
00239 std::cout<<"Event number:"<<int(event.number)<<","<<joystickData.axes.size()<<","<<axisGains.size()<<std::endl;
00240 joystickData.axes[event.number] = event.value;
00241 break;
00242
00243 case JS_EVENT_BUTTON:
00244
00245 break;
00246
00247 case JS_EVENT_INIT:
00248 break;
00249
00250 default:
00251 break;
00252 }
00253 }
00254 }
00255 }
00256 }