Trying to add some .ini support into xboxdrv, separated CommandLine parsing from Options class

This commit is contained in:
Ingo Ruhnke 2010-08-08 00:53:34 +02:00
parent d808092ce0
commit e1393fb40c
17 changed files with 971 additions and 183 deletions

View file

@ -20,6 +20,7 @@
#define HEADER_ARG_PARSER_HPP
#include <string>
#include <iostream>
#include <vector>
class ArgParser

View file

@ -16,6 +16,8 @@
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "command_line_options.hpp"
#include <stdio.h>
#include <iostream>
#include <stdexcept>
@ -26,7 +28,8 @@
#include "arg_parser.hpp"
#include "helper.hpp"
#include "uinput_deviceid.hpp"
#include "command_line_options.hpp"
#include "options.hpp"
#include "ini_schema.hpp"
#define RAISE_EXCEPTION(x) do { \
std::ostringstream kiJk8f08d4oMX; \
@ -34,7 +37,7 @@
throw std::runtime_error(kiJk8f08d4oMX.str()); \
} while(0)
CommandLineOptions* command_line_options = 0;
Options* g__options = 0;
enum {
OPTION_HELP,
@ -88,42 +91,9 @@ enum {
OPTION_HELP_DEVICES
};
CommandLineOptions::CommandLineOptions() :
mode(RUN_DEFAULT),
verbose(false),
silent (false),
quiet (false),
rumble (false),
led (-1),
rumble_l(-1),
rumble_r(-1),
rumble_gain(255),
controller_id(0),
wireless_id(0),
instant_exit(false),
no_uinput(false),
detach_kernel_driver(),
gamepad_type(GAMEPAD_UNKNOWN),
vendor_id(-1),
product_id(-1),
uinput_config(),
deadzone(0),
deadzone_trigger(0),
button_map(),
axis_map(),
autofire_map(),
relative_axis_map(),
calibration_map(),
axis_sensitivity_map(),
square_axis(false),
four_way_restrictor(false),
dpad_rotation(0),
evdev_device(),
CommandLineParser::CommandLineParser() :
argp()
{
busid[0] = '\0';
devid[0] = '\0';
argp
.add_usage("[OPTION]...")
.add_text("Xbox360 USB Gamepad Userspace Driver")
@ -264,23 +234,23 @@ void set_evdev_keymap(std::map<int, XboxButton>& keymap, const std::string& str)
}
void
CommandLineOptions::parse_args(int argc, char** argv)
CommandLineParser::parse_args(int argc, char** argv, Options* options)
{
ArgParser::ParsedOptions parsed = argp.parse_args(argc, argv);
for(ArgParser::ParsedOptions::const_iterator i = parsed.begin(); i != parsed.end(); ++i)
{
CommandLineOptions& opts = *this;
Options& opts = *options;
const ArgParser::ParsedOption& opt = *i;
switch (i->key)
{
case OPTION_HELP:
opts.mode = PRINT_HELP;
opts.mode = Options::PRINT_HELP;
break;
case OPTION_VERSION:
opts.mode = PRINT_VERSION;
opts.mode = Options::PRINT_VERSION;
break;
case OPTION_VERBOSE:
@ -297,7 +267,7 @@ CommandLineOptions::parse_args(int argc, char** argv)
case OPTION_DAEMON:
opts.silent = true;
opts.mode = RUN_DAEMON;
opts.mode = Options::RUN_DAEMON;
break;
case OPTION_TEST_RUMBLE:
@ -457,7 +427,7 @@ CommandLineOptions::parse_args(int argc, char** argv)
case OPTION_LED:
if (opt.argument == "help")
{
opts.mode = PRINT_LED_HELP;
opts.mode = Options::PRINT_LED_HELP;
}
else
{
@ -519,14 +489,14 @@ CommandLineOptions::parse_args(int argc, char** argv)
break;
case OPTION_DPAD_ROTATION:
{
int degree = boost::lexical_cast<int>(opt.argument);
degree /= 45;
degree %= 8;
if (degree < 0) degree += 8;
opts.dpad_rotation = degree;
}
break;
{
int degree = boost::lexical_cast<int>(opt.argument);
degree /= 45;
degree %= 8;
if (degree < 0) degree += 8;
opts.dpad_rotation = degree;
}
break;
case OPTION_SQUARE_AXIS:
opts.square_axis = true;
@ -544,46 +514,56 @@ CommandLineOptions::parse_args(int argc, char** argv)
break;
case OPTION_HELP_LED:
opts.mode = PRINT_LED_HELP;
opts.mode = Options::PRINT_LED_HELP;
break;
case OPTION_DEVICE_BY_ID:
{
unsigned int tmp_product_id;
unsigned int tmp_vendor_id;
if (sscanf(opt.argument.c_str(), "%x:%x", &tmp_vendor_id, &tmp_product_id) == 2)
{
opts.vendor_id = tmp_vendor_id;
opts.product_id = tmp_product_id;
unsigned int tmp_product_id;
unsigned int tmp_vendor_id;
if (sscanf(opt.argument.c_str(), "%x:%x", &tmp_vendor_id, &tmp_product_id) == 2)
{
opts.vendor_id = tmp_vendor_id;
opts.product_id = tmp_product_id;
}
else
{
RAISE_EXCEPTION(opt.option << " expected an argument in form PRODUCT:VENDOR (i.e. 046d:c626)");
}
break;
}
else
{
RAISE_EXCEPTION(opt.option << " expected an argument in form PRODUCT:VENDOR (i.e. 046d:c626)");
}
break;
}
case OPTION_DEVICE_BY_PATH:
if (sscanf(opt.argument.c_str(), "%3s:%3s", opts.busid, opts.devid) != 2)
{
RAISE_EXCEPTION(opt.option << " expected an argument in form BUS:DEV (i.e. 006:003)");
{
char busid[4] = { '\0' };
char devid[4] = { '\0' };
if (sscanf(opt.argument.c_str(), "%3s:%3s", busid, devid) != 2)
{
RAISE_EXCEPTION(opt.option << " expected an argument in form BUS:DEV (i.e. 006:003)");
}
else
{
opts.busid = busid;
opts.devid = devid;
}
}
break;
case OPTION_LIST_SUPPORTED_DEVICES:
opts.mode = RUN_LIST_SUPPORTED_DEVICES;
opts.mode = Options::RUN_LIST_SUPPORTED_DEVICES;
break;
case OPTION_LIST_SUPPORTED_DEVICES_XPAD:
opts.mode = RUN_LIST_SUPPORTED_DEVICES_XPAD;
opts.mode = Options::RUN_LIST_SUPPORTED_DEVICES_XPAD;
break;
case OPTION_LIST_CONTROLLER:
opts.mode = RUN_LIST_CONTROLLER;
opts.mode = Options::RUN_LIST_CONTROLLER;
break;
case OPTION_HELP_DEVICES:
opts.mode = PRINT_HELP_DEVICES;
opts.mode = Options::PRINT_HELP_DEVICES;
break;
case ArgParser::REST_ARG:
@ -598,13 +578,13 @@ CommandLineOptions::parse_args(int argc, char** argv)
}
void
CommandLineOptions::print_help() const
CommandLineParser::print_help() const
{
argp.print_help(std::cout);
}
void
CommandLineOptions::print_led_help() const
CommandLineParser::print_led_help() const
{
std::cout <<
"Possible values for '--led VALUE' are:\n\n"
@ -628,7 +608,7 @@ CommandLineOptions::print_led_help() const
}
void
CommandLineOptions::print_version() const
CommandLineParser::print_version() const
{
std::cout
<< "xboxdrv " PACKAGE_VERSION " - http://pingus.seul.org/~grumbel/xboxdrv/\n"
@ -638,4 +618,55 @@ CommandLineOptions::print_version() const
<< "This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details.\n";
}
void
CommandLineParser::create_ini_schema()
{
// INISchema ini;
// ini.section("general")
// ("verbose", &verbose)
// ("silent", &silent)
// ("quiet", &quiet)
// ("rumble", &rumble)
// ("led", &led)
// ("rumble_l", &rumble_l)
// ("rumble_r", &rumble_r)
// ("rumble_gain", &rumble_gain)
// ("controller-id", &controller_id)
// ("wireless-id", &wireless_id)
// ("instant-exit", &instant_exit)
// ("no-uinput", &no_uinput)
// ("detach-kernel-driver", &detach_kernel_driver);
// char busid[4];
// char devid[4];
// int deadzone;
// int deadzone_trigger;
// int vendor_id;
// int product_id;
// bool square_axis;
// bool four_way_restrictor;
// int dpad_rotation;
// std::string evdev_device;
// uInputCfg uinput_config;
//ini.section("ui-buttonmap", ui_buttonmap_cb);
//ini.section("ui-axismap", ui_buttonmap_cb);
// std::vector<ButtonMapping> button_map;
//ini.section("buttonmap", buttonmap_cb);
// std::vector<AxisMapping> axis_map;
//ini.section("axismap", axismap_cb);
// std::vector<AutoFireMapping> autofire_map;
// std::vector<RelativeAxisMapping> relative_axis_map;
// std::vector<CalibrationMapping> calibration_map;
// std::vector<AxisSensitivityMapping> axis_sensitivity_map;
// std::map<int, XboxAxis> evdev_absmap;
// std::map<int, XboxButton> evdev_keymap;
}
/* EOF */

View file

@ -29,70 +29,23 @@
class Xboxdrv;
class CommandLineOptions
class CommandLineParser
{
public:
enum { RUN_DEFAULT,
RUN_DAEMON,
RUN_LIST_CONTROLLER,
RUN_LIST_SUPPORTED_DEVICES,
RUN_LIST_SUPPORTED_DEVICES_XPAD,
PRINT_VERSION,
PRINT_HELP,
PRINT_HELP_DEVICES,
PRINT_LED_HELP
} mode;
bool verbose;
bool silent;
bool quiet;
bool rumble;
int led;
int rumble_l;
int rumble_r;
int rumble_gain;
int controller_id;
int wireless_id;
bool instant_exit;
bool no_uinput;
bool detach_kernel_driver;
GamepadType gamepad_type;
char busid[4];
char devid[4];
int vendor_id;
int product_id;
uInputCfg uinput_config;
int deadzone;
int deadzone_trigger;
std::vector<ButtonMapping> button_map;
std::vector<AxisMapping> axis_map;
std::vector<AutoFireMapping> autofire_map;
std::vector<RelativeAxisMapping> relative_axis_map;
std::vector<CalibrationMapping> calibration_map;
std::vector<AxisSensitivityMapping> axis_sensitivity_map;
bool square_axis;
bool four_way_restrictor;
int dpad_rotation;
std::string evdev_device;
std::map<int, XboxAxis> evdev_absmap;
std::map<int, XboxButton> evdev_keymap;
ArgParser argp;
public:
CommandLineOptions();
void parse_args(int argc, char** argv);
CommandLineParser();
void parse_args(int argc, char** argv, Options* options);
void print_help() const;
void print_led_help() const;
void print_version() const;
void create_ini_schema();
};
extern CommandLineOptions* command_line_options;
extern Options* g_options;
#endif

View file

@ -19,7 +19,7 @@
#include <stdlib.h>
#include <iostream>
#include <assert.h>
#include "command_line_options.hpp"
#include "options.hpp"
#include "force_feedback_handler.hpp"
std::ostream& operator<<(std::ostream& out, const struct ff_envelope& envelope)
@ -294,7 +294,7 @@ ForceFeedbackHandler::get_max_effects()
void
ForceFeedbackHandler::upload(const struct ff_effect& effect)
{
if (command_line_options->verbose)
if (g_options->verbose)
std::cout << "FF_UPLOAD("
<< "effect_id:" << effect.id
<< ", effect_type:" << effect.type
@ -325,7 +325,7 @@ ForceFeedbackHandler::upload(const struct ff_effect& effect)
void
ForceFeedbackHandler::erase(int id)
{
if (command_line_options->verbose)
if (g_options->verbose)
std::cout << "FF_ERASE(effect_id:" << id << ")" << std::endl;
std::map<int, ForceFeedbackEffect>::iterator i = effects.find(id);
@ -338,7 +338,7 @@ ForceFeedbackHandler::erase(int id)
void
ForceFeedbackHandler::play(int id)
{
if (command_line_options->verbose)
if (g_options->verbose)
std::cout << "FFPlay(effect_id:" << id << ")" << std::endl;
std::map<int, ForceFeedbackEffect>::iterator i = effects.find(id);
@ -351,7 +351,7 @@ ForceFeedbackHandler::play(int id)
void
ForceFeedbackHandler::stop(int id)
{
if (command_line_options->verbose)
if (g_options->verbose)
std::cout << "FFStop(effect_id:" << id << ")" << std::endl;
std::map<int, ForceFeedbackEffect>::iterator i = effects.find(id);

32
src/ini_builder.hpp Normal file
View file

@ -0,0 +1,32 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_INI_BUILDER_HPP
#define HEADER_XBOXDRV_INI_BUILDER_HPP
class INIBuilder
{
public:
virtual ~INIBuilder() {}
virtual void send_section(const std::string& section) =0;
virtual void send_pair(const std::string& name, const std::string& value) =0;
};
#endif
/* EOF */

268
src/ini_parser.cpp Normal file
View file

@ -0,0 +1,268 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ini_parser.hpp"
#include <stdlib.h>
#include <iostream>
#include <ctype.h>
#include <stdexcept>
#include "ini_builder.hpp"
INIParser::INIParser(std::istream& in, INIBuilder& builder, const std::string& context) :
m_in(in),
m_builder(builder),
m_context(context),
m_line(1),
m_column(0),
m_current_char(-1)
{}
void
INIParser::run()
{
// read the first char
next();
while(peek() != -1)
{
if (accept('['))
{
m_builder.send_section(get_section());
expect(']');
whitespace();
if (accept('#'))
eat_rest_of_line();
newline();
}
else if (accept(' ') || accept('\t') || accept('\n'))
{
// eat whitespace
}
else if (accept('#'))
{
eat_rest_of_line();
newline();
}
else // assume name=value pair
{
std::string n;
std::string v;
n = get_ident();
whitespace();
expect('=');
whitespace();
if (accept('#'))
{ // "foobar = # comment here, value empty"
eat_rest_of_line();
newline();
}
else
{
if (accept('"'))
{
v = get_string();
expect('"');
}
else
{
v = get_value();
}
whitespace();
if (accept('#'))
eat_rest_of_line();
newline();
}
m_builder.send_pair(n, v);
}
}
}
void
INIParser::error(const std::string& message)
{
std::ostringstream str;
str << m_context << ":" << m_line << ":" << m_column << ": error: " << message;
throw std::runtime_error(str.str());
}
int
INIParser::peek()
{
return m_current_char;
}
void
INIParser::next()
{
if (m_in.eof())
{
error("unexpected end of file");
}
else
{
m_current_char = m_in.get();
if (m_current_char == '\n')
{
m_line += 1;
m_column = 0;
}
}
}
bool
INIParser::accept(char c)
{
if (peek() != c)
{
return false;
}
else
{
next();
return true;
}
}
void
INIParser::expect(char c)
{
if (peek() != c)
{
std::ostringstream str;
str << "expected '" << c << "', got ";
if (peek() == -1)
str << "EOF";
else
str << "'" << static_cast<char>(peek()) << "'";
error(str.str());
}
else
{
next();
}
}
std::string
INIParser::get_value()
{
std::ostringstream str;
while(peek() != ' ' && peek() != '\t' && peek() != '\n')
{
str << (char)peek();
next();
}
return str.str();
}
std::string
INIParser::get_ident()
{
std::ostringstream str;
while(peek() != '=' && peek() != ' ' && peek() != '\t')
{
str << (char)peek();
next();
}
return str.str();
}
std::string
INIParser::get_string()
{
std::ostringstream str;
while(peek() != '"')
{
if (peek() == '\\')
{
next();
switch(peek())
{
case '\\': str << '\\'; break;
case '0': str << '\0'; break;
case 'a': str << '\a'; break;
case 'b': str << '\b'; break;
case 't': str << '\t'; break;
case 'r': str << '\r'; break;
case 'n': str << '\n'; break;
default: str << '\\' << (char)peek(); break;
}
}
else
{
str << (char)peek();
}
next();
}
return str.str();
}
void
INIParser::newline()
{
if (peek() != '\n')
{
error("expected newline");
}
else
{
next();
}
}
void
INIParser::eat_rest_of_line()
{
while(peek() != '\n')
{
next();
}
}
std::string
INIParser::get_section()
{
std::ostringstream str;
while(peek() != ']')
{
str << (char)peek();
next();
}
return str.str();
}
void
INIParser::whitespace()
{
while(peek() == ' ' || peek() == '\t')
{
next();
}
}
int
INIParser::getchar()
{
return m_in.get();
}
/* EOF */

65
src/ini_parser.hpp Normal file
View file

@ -0,0 +1,65 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_INI_PARSER_HPP
#define HEADER_XBOXDRV_INI_PARSER_HPP
#include <map>
#include <string>
#include <sstream>
class INIBuilder;
class INIParser
{
private:
std::istream& m_in;
INIBuilder& m_builder;
std::string m_context;
int m_line;
int m_column;
int m_current_char;
public:
INIParser(std::istream& in, INIBuilder& builder, const std::string& context);
void run();
private:
void error(const std::string& message);
int peek();
void next();
bool accept(char c);
void expect(char c);
std::string get_string();
std::string get_value();
std::string get_ident();
void newline();
void eat_rest_of_line();
std::string get_section();
void whitespace();
int getchar();
private:
INIParser(const INIParser&);
INIParser& operator=(const INIParser&);
};
#endif
/* EOF */

208
src/ini_schema.cpp Normal file
View file

@ -0,0 +1,208 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ini_schema.hpp"
class INIPairSchema
{
public:
virtual ~INIPairSchema() {}
};
class INIPairSchemaBool : public INIPairSchema
{
private:
bool* m_data;
public:
INIPairSchemaBool(bool* data) : m_data(data) {}
void call(const std::string& value)
{
if (value == "yes" || value == "true" || value == "1")
{
*m_data = true;
}
else if (value == "no" || value == "false" || value == "0")
{
*m_data = false;
}
else
{
throw std::runtime_error("unable to convert '" + value + "' to bool");
}
}
};
class INIPairSchemaInt : public INIPairSchema
{
private:
int* m_data;
public:
INIPairSchemaInt(int* data) : m_data(data) {}
void call(const std::string& value)
{
*m_data = atoi(value.c_str());
}
};
class INIPairSchemaFloat : public INIPairSchema
{
private:
float* m_data;
public:
INIPairSchemaFloat(float* data) : m_data(data) {}
void call(const std::string& value)
{
*m_data = atoi(value.c_str());
}
};
class INIPairSchemaString : public INIPairSchema
{
private:
std::string* m_data;
public:
INIPairSchemaString(std::string* data) : m_data(data) {}
void call(const std::string& value)
{
*m_data = value;
}
};
class INIPairSchemaCallback : public INIPairSchema
{
private:
boost::function<void (const std::string&)> m_callback;
public:
INIPairSchemaCallback(boost::function<void (const std::string&)> callback) : m_callback(callback) {}
void call(const std::string& value)
{
if (m_callback)
m_callback(value);
}
};
INISchemaSection::INISchemaSection()
{
}
INISchemaSection::~INISchemaSection()
{
for(Schema::iterator i = m_schema.begin(); i != m_schema.end(); ++i)
{
delete i->second;
}
}
INISchemaSection&
INISchemaSection::add(const std::string& name, INIPairSchema* schema)
{
Schema::iterator i = m_schema.find(name);
if (i != m_schema.end())
{
delete i->second;
}
m_schema.insert(std::pair<std::string, INIPairSchema*>(name, schema));
return *this;
}
INISchemaSection&
INISchemaSection::operator()(const std::string& name, bool* value)
{
add(name, new INIPairSchemaBool(value));
return *this;
}
INISchemaSection&
INISchemaSection::operator()(const std::string& name, int* value)
{
add(name, new INIPairSchemaInt(value));
return *this;
}
INISchemaSection&
INISchemaSection::operator()(const std::string& name, float* value)
{
add(name, new INIPairSchemaFloat(value));
return *this;
}
INISchemaSection&
INISchemaSection::operator()(const std::string& name, std::string* value)
{
add(name, new INIPairSchemaString(value));
return *this;
}
INISchemaSection&
INISchemaSection::operator()(const std::string& name, boost::function<void (const std::string&)> callback)
{
add(name, new INIPairSchemaCallback(callback));
return *this;
}
INISchema::INISchema() :
m_sections()
{
}
INISchema::~INISchema()
{
for(Sections::iterator i = m_sections.begin(); i != m_sections.end(); ++i)
{
delete i->second;
}
}
INISchemaSection&
INISchema::section(const std::string& name,
boost::function<void (const std::string&, const std::string&)> callback)
{
Sections::iterator i = m_sections.find(name);
if (i != m_sections.end())
{
delete i->second;
}
INISchemaSection* section = new INISchemaSection();
m_sections.insert(std::pair<std::string, INISchemaSection*>(name, section));
return *section;
}
INISchemaSection*
INISchema::get_section(const std::string& name)
{
Sections::iterator i = m_sections.find(name);
if (i != m_sections.end())
{
return i->second;
}
else
{
return 0;
}
}
/* EOF */

75
src/ini_schema.hpp Normal file
View file

@ -0,0 +1,75 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_INI_SCHEMA_HPP
#define HEADER_XBOXDRV_INI_SCHEMA_HPP
#include <map>
#include <string>
#include <boost/function.hpp>
class INIPairSchema;
class INISchemaSection
{
private:
typedef std::map<std::string, INIPairSchema*> Schema;
Schema m_schema;
public:
INISchemaSection();
~INISchemaSection();
INISchemaSection& operator()(const std::string& name, bool* value);
INISchemaSection& operator()(const std::string& name, int* value);
INISchemaSection& operator()(const std::string& name, float* value);
INISchemaSection& operator()(const std::string& name, std::string* value);
INISchemaSection& operator()(const std::string& name, boost::function<void (const std::string&)> callback);
private:
INISchemaSection& add(const std::string& name, INIPairSchema* schema);
private:
INISchemaSection(const INISchemaSection&);
INISchemaSection& operator=(const INISchemaSection&);
};
class INISchema
{
private:
typedef std::map<std::string, INISchemaSection*> Sections;
Sections m_sections;
public:
INISchema();
~INISchema();
INISchemaSection& section(const std::string& name,
boost::function<void (const std::string&, const std::string&)> callback
= boost::function<void (const std::string&, const std::string&)>());
INISchemaSection* get_section(const std::string& name);
private:
INISchema(const INISchema&);
INISchema& operator=(const INISchema&);
};
#endif
/* EOF */

View file

@ -22,7 +22,7 @@
#include <stdexcept>
#include <math.h>
#include "command_line_options.hpp"
#include "options.hpp"
#include "helper.hpp"
#include "modifier.hpp"
@ -310,7 +310,7 @@ void apply_square_axis(XboxGenericMsg& msg)
}
}
void apply_deadzone(XboxGenericMsg& msg, const CommandLineOptions& opts)
void apply_deadzone(XboxGenericMsg& msg, const Options& opts)
{
switch (msg.type)
{
@ -350,7 +350,7 @@ void apply_deadzone(XboxGenericMsg& msg, const CommandLineOptions& opts)
}
}
void apply_axis_sensitivity(XboxGenericMsg& msg, const CommandLineOptions& opts)
void apply_axis_sensitivity(XboxGenericMsg& msg, const Options& opts)
{
for(std::vector<AxisSensitivityMapping>::const_iterator i = opts.axis_sensitivity_map.begin();
i != opts.axis_sensitivity_map.end(); ++i)
@ -371,7 +371,7 @@ void apply_axis_sensitivity(XboxGenericMsg& msg, const CommandLineOptions& opts)
}
}
void apply_four_way_restrictor(XboxGenericMsg& msg, const CommandLineOptions& opts)
void apply_four_way_restrictor(XboxGenericMsg& msg, const Options& opts)
{
// left Stick
if (abs(get_axis(msg, XBOX_AXIS_X1)) > abs(get_axis(msg, XBOX_AXIS_Y1)))
@ -402,7 +402,7 @@ void apply_four_way_restrictor(XboxGenericMsg& msg, const CommandLineOptions& op
}
}
void apply_dpad_rotator(XboxGenericMsg& msg, const CommandLineOptions& opts)
void apply_dpad_rotator(XboxGenericMsg& msg, const Options& opts)
{
int up = get_button(msg, XBOX_DPAD_UP);
int down = get_button(msg, XBOX_DPAD_DOWN);

View file

@ -24,7 +24,7 @@
#include <vector>
#include "xboxmsg.hpp"
class CommandLineOptions;
class Options;
struct ButtonMapping {
static ButtonMapping from_string(const std::string& str);
@ -161,11 +161,11 @@ public:
void apply_button_map(XboxGenericMsg& msg, const std::vector<ButtonMapping>& lst);
void apply_axis_map(XboxGenericMsg& msg, const std::vector<AxisMapping>& lst);
void apply_calibration_map(XboxGenericMsg& msg, const std::vector<CalibrationMapping>& lst);
void apply_deadzone(XboxGenericMsg& msg, const CommandLineOptions& opts);
void apply_deadzone(XboxGenericMsg& msg, const Options& opts);
void apply_square_axis(XboxGenericMsg& msg);
void apply_axis_sensitivity(XboxGenericMsg& msg, const CommandLineOptions& opts);
void apply_four_way_restrictor(XboxGenericMsg& msg, const CommandLineOptions& opts);
void apply_dpad_rotator(XboxGenericMsg& msg, const CommandLineOptions& opts);
void apply_axis_sensitivity(XboxGenericMsg& msg, const Options& opts);
void apply_four_way_restrictor(XboxGenericMsg& msg, const Options& opts);
void apply_dpad_rotator(XboxGenericMsg& msg, const Options& opts);
#endif

57
src/options.cpp Normal file
View file

@ -0,0 +1,57 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "options.hpp"
Options* g_options;
Options::Options() :
mode(RUN_DEFAULT),
verbose(false),
silent (false),
quiet (false),
rumble (false),
led (-1),
rumble_l(-1),
rumble_r(-1),
rumble_gain(255),
controller_id(0),
wireless_id(0),
instant_exit(false),
no_uinput(false),
detach_kernel_driver(),
gamepad_type(GAMEPAD_UNKNOWN),
vendor_id(-1),
product_id(-1),
uinput_config(),
deadzone(0),
deadzone_trigger(0),
button_map(),
axis_map(),
autofire_map(),
relative_axis_map(),
calibration_map(),
axis_sensitivity_map(),
square_axis(false),
four_way_restrictor(false),
dpad_rotation(0),
evdev_device()
{
}
/* EOF */

89
src/options.hpp Normal file
View file

@ -0,0 +1,89 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_OPTIONS_HPP
#define HEADER_XBOXDRV_OPTIONS_HPP
#include <string>
#include <map>
#include <vector>
#include "xpad_device.hpp"
#include "uinput_cfg.hpp"
#include "modifier.hpp"
class Options
{
public:
enum { RUN_DEFAULT,
RUN_DAEMON,
RUN_LIST_CONTROLLER,
RUN_LIST_SUPPORTED_DEVICES,
RUN_LIST_SUPPORTED_DEVICES_XPAD,
PRINT_VERSION,
PRINT_HELP,
PRINT_HELP_DEVICES,
PRINT_LED_HELP
} mode;
bool verbose;
bool silent;
bool quiet;
bool rumble;
int led;
int rumble_l;
int rumble_r;
int rumble_gain;
int controller_id;
int wireless_id;
bool instant_exit;
bool no_uinput;
bool detach_kernel_driver;
GamepadType gamepad_type;
std::string busid;
std::string devid;
int vendor_id;
int product_id;
uInputCfg uinput_config;
int deadzone;
int deadzone_trigger;
std::vector<ButtonMapping> button_map;
std::vector<AxisMapping> axis_map;
std::vector<AutoFireMapping> autofire_map;
std::vector<RelativeAxisMapping> relative_axis_map;
std::vector<CalibrationMapping> calibration_map;
std::vector<AxisSensitivityMapping> axis_sensitivity_map;
bool square_axis;
bool four_way_restrictor;
int dpad_rotation;
std::string evdev_device;
std::map<int, XboxAxis> evdev_absmap;
std::map<int, XboxButton> evdev_keymap;
Options();
};
extern Options* g_options;
#endif
/* EOF */

View file

@ -24,7 +24,7 @@
#include <iostream>
#include <boost/format.hpp>
#include "command_line_options.hpp"
#include "options.hpp"
#include "helper.hpp"
#include "usb_helper.hpp"
#include "usb_read_thread.hpp"
@ -228,7 +228,7 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
}
else if (ret == 3 && data[0] == 0x08 && data[1] == 0x03)
{
if (!command_line_options->quiet)
if (!g_options->quiet)
{
if (data[2] == 0x00)
std::cout << "Headset: none";

View file

@ -44,6 +44,7 @@
#include "helper.hpp"
#include "evdev_helper.hpp"
#include "command_line_options.hpp"
#include "options.hpp"
#include "xbox_generic_controller.hpp"
#include "xboxdrv.hpp"
@ -56,13 +57,13 @@ void on_sigint(int)
{
if (global_exit_xboxdrv)
{
if (!command_line_options->quiet)
if (!g_options->quiet)
std::cout << "Ctrl-c pressed twice, exiting hard" << std::endl;
exit(EXIT_SUCCESS);
}
else
{
if (!command_line_options->quiet)
if (!g_options->quiet)
std::cout << "Shutdown initiated, press Ctrl-c again if nothing is happening" << std::endl;
global_exit_xboxdrv = true;
@ -73,7 +74,7 @@ void on_sigint(int)
void on_sigterm(int)
{
if (!command_line_options->quiet)
if (!g_options->quiet)
std::cout << "Shutdown initiated by SIGTERM" << std::endl;
if (global_controller)
@ -149,17 +150,17 @@ Xboxdrv::run_list_controller()
}
bool
Xboxdrv::find_controller_by_path(const char* busid, const char* devid,struct usb_device** xbox_device) const
Xboxdrv::find_controller_by_path(const std::string& busid, const std::string& devid,struct usb_device** xbox_device) const
{
struct usb_bus* busses = usb_get_busses();
for (struct usb_bus* bus = busses; bus; bus = bus->next)
{
if (strcmp(bus->dirname, busid) == 0)
if (bus->dirname == busid)
{
for (struct usb_device* dev = bus->devices; dev; dev = dev->next)
{
if (strcmp(dev->filename, devid) == 0)
if (dev->filename == devid)
{
*xbox_device = dev;
return true;
@ -272,7 +273,7 @@ Xboxdrv::find_xbox360_controller(int id, struct usb_device** xbox_device, XPadDe
}
void
Xboxdrv::apply_modifier(XboxGenericMsg& msg, int msec_delta, const CommandLineOptions& opts) const
Xboxdrv::apply_modifier(XboxGenericMsg& msg, int msec_delta, const Options& opts) const
{
apply_calibration_map(msg, opts.calibration_map);
@ -293,7 +294,7 @@ Xboxdrv::apply_modifier(XboxGenericMsg& msg, int msec_delta, const CommandLineOp
}
void
Xboxdrv::controller_loop(GamepadType type, uInput* uinput, XboxGenericController* controller, const CommandLineOptions& opts)
Xboxdrv::controller_loop(GamepadType type, uInput* uinput, XboxGenericController* controller, const Options& opts)
{
int timeout = 0; // 0 == no timeout
XboxGenericMsg oldmsg; // last data send to uinput
@ -392,7 +393,7 @@ Xboxdrv::controller_loop(GamepadType type, uInput* uinput, XboxGenericController
void
Xboxdrv::find_controller(struct usb_device*& dev,
XPadDevice& dev_type,
const CommandLineOptions& opts) const
const Options& opts) const
{
if (opts.busid[0] != '\0' && opts.devid[0] != '\0')
{
@ -453,11 +454,16 @@ Xboxdrv::find_controller(struct usb_device*& dev,
}
void
Xboxdrv::run_main(const CommandLineOptions& opts)
Xboxdrv::run_main(const Options& opts)
{
if (!opts.quiet)
{
opts.print_version();
std::cout
<< "xboxdrv " PACKAGE_VERSION " - http://pingus.seul.org/~grumbel/xboxdrv/\n"
<< "Copyright © 2008-2010 Ingo Ruhnke <grumbel@gmx.de>\n"
<< "Licensed under GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
<< "This program comes with ABSOLUTELY NO WARRANTY.\n"
<< "This is free software, and you are welcome to redistribute it under certain conditions; see the file COPYING for details.\n";
std::cout << std::endl;
}
@ -601,7 +607,7 @@ Xboxdrv::run_main(const CommandLineOptions& opts)
void
Xboxdrv::print_info(struct usb_device* dev,
const XPadDevice& dev_type,
const CommandLineOptions& opts) const
const Options& opts) const
{
std::cout << "USB Device: " << dev->bus->dirname << ":" << dev->filename << std::endl;
std::cout << "Controller: " << boost::format("\"%s\" (idVendor: 0x%04x, idProduct: 0x%04x)")
@ -748,7 +754,7 @@ Xboxdrv::run_help_devices()
}
void
Xboxdrv::run_daemon(const CommandLineOptions& opts)
Xboxdrv::run_daemon(const Options& opts)
{
pid_t pid = fork();
@ -773,45 +779,47 @@ Xboxdrv::main(int argc, char** argv)
signal(SIGINT, on_sigint);
signal(SIGTERM, on_sigterm);
CommandLineOptions opts;
opts.parse_args(argc, argv);
command_line_options = &opts;
Options opts;
g_options = &opts;
CommandLineParser cmd_parser;
cmd_parser.parse_args(argc, argv, &opts);
switch(opts.mode)
{
case CommandLineOptions::PRINT_HELP_DEVICES:
case Options::PRINT_HELP_DEVICES:
run_help_devices();
break;
case CommandLineOptions::RUN_LIST_SUPPORTED_DEVICES:
case Options::RUN_LIST_SUPPORTED_DEVICES:
run_list_supported_devices();
break;
case CommandLineOptions::RUN_LIST_SUPPORTED_DEVICES_XPAD:
case Options::RUN_LIST_SUPPORTED_DEVICES_XPAD:
run_list_supported_devices_xpad();
break;
case CommandLineOptions::PRINT_VERSION:
opts.print_version();
case Options::PRINT_VERSION:
cmd_parser.print_version();
break;
case CommandLineOptions::PRINT_HELP:
opts.print_help();
case Options::PRINT_HELP:
cmd_parser.print_help();
break;
case CommandLineOptions::PRINT_LED_HELP:
opts.print_led_help();
case Options::PRINT_LED_HELP:
cmd_parser.print_led_help();
break;
case CommandLineOptions::RUN_DEFAULT:
case Options::RUN_DEFAULT:
run_main(opts);
break;
case CommandLineOptions::RUN_DAEMON:
case Options::RUN_DAEMON:
run_daemon(opts);
break;
case CommandLineOptions::RUN_LIST_CONTROLLER:
case Options::RUN_LIST_CONTROLLER:
run_list_controller();
break;
}

View file

@ -22,15 +22,16 @@
#include "xboxmsg.hpp"
struct XPadDevice;
class CommandLineOptions;
class Options;
class Options;
class uInput;
class XboxGenericController;
class Xboxdrv
{
private:
void run_main(const CommandLineOptions& opts);
void run_daemon(const CommandLineOptions& opts);
void run_main(const Options& opts);
void run_daemon(const Options& opts);
void run_list_supported_devices();
void run_list_supported_devices_xpad();
void run_help_devices();
@ -38,16 +39,16 @@ private:
void print_info(struct usb_device* dev,
const XPadDevice& dev_type,
const CommandLineOptions& opts) const;
const Options& opts) const;
void controller_loop(GamepadType type, uInput* uinput,
XboxGenericController* controller,
const CommandLineOptions& opts);
void apply_modifier(XboxGenericMsg& msg, int msec_delta, const CommandLineOptions& opts) const;
const Options& opts);
void apply_modifier(XboxGenericMsg& msg, int msec_delta, const Options& opts) const;
bool find_controller_by_path(const char* busid, const char* devid,struct usb_device** xbox_device) const;
bool find_controller_by_path(const std::string& busid, const std::string& devid,struct usb_device** xbox_device) const;
void find_controller(struct usb_device*& dev,
XPadDevice& dev_type,
const CommandLineOptions& opts) const;
const Options& opts) const;
int find_jsdev_number() const;
int find_evdev_number() const;
bool find_controller_by_id(int id, int vendor_id, int product_id, struct usb_device** xbox_device) const;

View file

@ -22,7 +22,7 @@
#include <algorithm>
#include "helper.hpp"
#include "command_line_options.hpp"
#include "options.hpp"
#include "xboxmsg.hpp"
std::string gamepadtype_to_string(const GamepadType& type)
@ -152,7 +152,7 @@ std::ostream& operator<<(std::ostream& out, const Xbox360GuitarMsg& msg)
% int(msg.blue)
% int(msg.orange);
if (command_line_options->verbose)
if (g_options->verbose)
{
out << boost::format("| dummy: %d %d %d %d %02hhx %02hhx %04hx %04hx %02x %02x")
% int(msg.thumb_l)
@ -205,7 +205,7 @@ std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg)
out << boost::format(" LT:%3d RT:%3d")
% int(msg.lt) % int(msg.rt);
if (command_line_options->verbose)
if (g_options->verbose)
out << " Dummy: " << msg.dummy1 << " " << msg.dummy2 << " " << msg.dummy3;
return out;
@ -245,7 +245,7 @@ std::ostream& operator<<(std::ostream& out, const XboxMsg& msg)
% int(msg.lt)
% int(msg.rt);
if (command_line_options->verbose)
if (g_options->verbose)
out << " Dummy: " << msg.dummy;
return out;