Reimplemented support for naming devices

This commit is contained in:
Ingo Ruhnke 2011-01-28 23:00:13 +01:00
parent beed2d0861
commit 929bd68be8
14 changed files with 226 additions and 41 deletions

17
TODO
View file

@ -42,6 +42,21 @@ $ dput my-ppa ../xboxdrv_0.7.1-1~lucid1_source.changes
Stuff to do before 0.7.1 release:
=================================
* implement set_dpad_as_button(), set_dpad_only()
* --name DEVNAME must work with multple controller slots and multiple
devices, also allow a way to rename mouse and keyboard emulation devices
turn --name into --ui-name SLOT=foo
--ui-name 1=MouseEmulation:0500:0500,2=Keyboard,mouse=Mouse
--ui-name 1=MouseEmulation,2=Keyboard,mouse=Mouse
--ui-vendor =
--ui-product
--ui-bcdversion
* document match rules
* improve output in daemon mode, when --quiet is not given print the number of allocated controller slots
* [ERROR] XboxdrvDaemon::process_match(): no free controller slot found, controller will be ignored
@ -120,8 +135,6 @@ Stuff to do before 0.7.2 release:
* extend usbid match rule to bcd device
* --name DEVNAME must work with multple controller slots and multiple devices
* cleanup device_id, don't manually do (slot<<16) | devid (only an
issue in force feedback code)

View file

@ -28,6 +28,7 @@
#include "ini_parser.hpp"
#include "ini_schema_builder.hpp"
#include "options.hpp"
#include "ui_event.hpp"
#include "axisfilter/relative_axis_filter.hpp"
#include "axisfilter/calibration_axis_filter.hpp"
@ -67,6 +68,7 @@ enum {
OPTION_BUTTONMAP,
OPTION_AXISMAP,
OPTION_NAME,
OPTION_DEVICE_NAME,
OPTION_NEXT_CONFIG,
OPTION_NEXT_CONTROLLER,
OPTION_CONFIG_SLOT,
@ -271,7 +273,8 @@ CommandLineParser::init_argp()
.add_text("Uinput Configuration Options: ")
.add_option(OPTION_NO_UINPUT, 0, "no-uinput", "", "do not try to start uinput event dispatching")
.add_option(OPTION_NO_EXTRA_DEVICES, 0, "no-extra-devices", "", "Do not create separate virtual keyboard and mouse devices, just use a single virtual device")
.add_option(OPTION_NAME, 0, "name", "DEVNAME", "Changes the descriptive name the device will have")
.add_option(OPTION_NAME, 0, "name", "NAME", "Changes the name prefix used for devices in the current slot")
.add_option(OPTION_DEVICE_NAME, 0, "device-name", "DEVID=NAME", "Changes the descriptive name the given device")
.add_option(OPTION_UI_CLEAR, 0, "ui-clear", "", "Removes all existing uinput bindings")
.add_option(OPTION_UI_BUTTONMAP, 0, "ui-buttonmap", "MAP", "Changes the uinput events send when hitting a button (example: X=BTN_Y,A=KEY_A)")
.add_option(OPTION_UI_AXISMAP, 0, "ui-axismap", "MAP", "Changes the uinput events send when moving a axis (example: X1=ABS_X2)")
@ -609,8 +612,12 @@ CommandLineParser::parse_args(int argc, char** argv, Options* options)
process_name_value_string(opt.argument, boost::bind(&CommandLineParser::set_axismap, this, _1, _2));
break;
case OPTION_DEVICE_NAME:
process_name_value_string(opt.argument, boost::bind(&CommandLineParser::set_device_name, this, _1, _2));
break;
case OPTION_NAME:
opts.get_controller_options().uinput.device_name = opt.argument;
opts.set_device_name(opt.argument);
break;
case OPTION_NEXT_CONFIG:
@ -925,6 +932,36 @@ CommandLineParser::set_modifier(const std::string& name, const std::string& valu
m_options->get_controller_options().modifier.push_back(ModifierPtr(Modifier::from_string(name, value)));
}
void
CommandLineParser::set_device_name(const std::string& name, const std::string& value)
{
// FIXME: insert magic to resolve symbolic names
std::string::size_type p = name.find('.');
if (p == std::string::npos)
{
uint16_t device_id = str2deviceid(name.substr());
uint16_t slot_id = m_options->controller_slot;
uint32_t devid = UInput::create_device_id(slot_id, device_id);
m_options->uinput_device_names[devid] = value;
}
else
{
uint16_t device_id = str2deviceid(name.substr(0, p));
uint16_t slot_id = str2slotid(name.substr(p+1));
if (slot_id == DEVICEID_AUTO)
{
slot_id = m_options->controller_slot;
}
uint32_t devid = UInput::create_device_id(slot_id, device_id);
m_options->uinput_device_names[devid] = value;
}
}
void
CommandLineParser::set_ui_buttonmap(const std::string& name, const std::string& value)
{

View file

@ -44,6 +44,8 @@ public:
void create_ini_schema(Options* opts);
private:
void set_device_name(const std::string& name, const std::string& value);
void set_ui_buttonmap(const std::string& name, const std::string& value);
void set_ui_axismap(const std::string& name, const std::string& value);
void set_modifier(const std::string& name, const std::string& value);

View file

@ -23,6 +23,7 @@
#include "helper.hpp"
#include "raise_exception.hpp"
#include "uinput.hpp"
Options* g_options;
@ -68,7 +69,8 @@ Options::Options() :
config_toggle_button(XBOX_BTN_UNKNOWN),
controller_slot(0),
config_slot(0),
extra_devices(true)
extra_devices(true),
uinput_device_names()
{
// create the entry if not already available
controller_slots[controller_slot].get_options(config_slot);
@ -162,7 +164,8 @@ Options::set_debug()
void
Options::set_device_name(const std::string& name)
{
//get_controller().uinput.mouse();
uint32_t device_id = UInput::create_device_id(controller_slot, DEVICEID_AUTO);
uinput_device_names[device_id] = name;
}
void
@ -192,11 +195,13 @@ Options::set_trigger_as_zaxis()
void
Options::set_dpad_as_button()
{
// FIXME: implement me
}
void
Options::set_dpad_only()
{
// FIXME: implement me
}
void

View file

@ -116,6 +116,8 @@ public:
bool extra_devices;
std::map<uint32_t, std::string> uinput_device_names;
public:
Options();

View file

@ -143,8 +143,6 @@ UIEvent::get_device_id() const
return UInput::create_device_id(m_slot_id, m_device_id);
}
namespace {
int str2deviceid(const std::string& device)
{
if (device == "auto" || device.empty())
@ -181,8 +179,6 @@ int str2slotid(const std::string& slot)
}
}
}
void split_event_name(const std::string& str, std::string* event_str, int* slot_id, int* device_id)
{
std::string::size_type p = str.find('@');

View file

@ -68,6 +68,9 @@ private:
*/
void split_event_name(const std::string& str, std::string* event_str, int* slot_id, int* device_id);
int str2deviceid(const std::string& device);
int str2slotid(const std::string& slot);
#endif
/* EOF */

View file

@ -21,12 +21,98 @@
#include "log.hpp"
UInput::UInput() :
uinput_devs(),
rel_repeat_lst(),
m_uinput_devs(),
m_device_names(),
m_rel_repeat_lst(),
m_mutex()
{
}
std::string
UInput::get_device_name(uint32_t device_id) const
{
uint16_t slot_id = get_slot_id(device_id);
uint16_t type_id = get_type_id(device_id);
DeviceNames::const_iterator it = m_device_names.find(device_id);
if (it != m_device_names.end())
{
// found an exact match, return it
return it->second;
}
else
{
it = m_device_names.find(create_device_id(slot_id, DEVICEID_AUTO));
if (it != m_device_names.end())
{
// found a match for the slot, build a name and return it
std::ostringstream str;
str << it->second;
switch(type_id)
{
case DEVICEID_JOYSTICK:
break;
case DEVICEID_MOUSE:
str << " - Mouse Emulation";
break;
case DEVICEID_KEYBOARD:
str << " - Keyboard Emulation";
break;
default:
str << " - " << device_id+1;
break;
}
return str.str();
}
else
{
it = m_device_names.find(create_device_id(SLOTID_AUTO, type_id));
if (it != m_device_names.end())
{
// found match for the type, build name and return it
std::ostringstream str;
str << it->second;
if (slot_id > 0)
{
str << " #" << slot_id;
}
return str.str();
}
else
{
std::ostringstream str;
str << "Xbox Gamepad (userspace driver)";
switch(type_id)
{
case DEVICEID_JOYSTICK:
break;
case DEVICEID_MOUSE:
str << " - Mouse Emulation";
break;
case DEVICEID_KEYBOARD:
str << " - Keyboard Emulation";
break;
default:
str << " - " << device_id+1;
break;
}
if (slot_id > 0)
{
str << " #" << slot_id;
}
return str.str();
}
}
}
}
LinuxUinput*
UInput::create_uinput_device(uint32_t device_id)
{
@ -34,8 +120,8 @@ UInput::create_uinput_device(uint32_t device_id)
// have called resolve_device_id()
assert(device_id != DEVICEID_AUTO);
UInputDevs::iterator it = uinput_devs.find(device_id);
if (it != uinput_devs.end())
UInputDevs::iterator it = m_uinput_devs.find(device_id);
if (it != m_uinput_devs.end())
{
// device already exist, so return it
return it->second.get();
@ -44,8 +130,6 @@ UInput::create_uinput_device(uint32_t device_id)
{
log_debug("create device: " << device_id);
LinuxUinput::DeviceType device_type = LinuxUinput::kGenericDevice;
std::ostringstream dev_name;
dev_name << "Xbox Gamepad (userspace driver)";
switch (device_id)
{
@ -55,23 +139,21 @@ UInput::create_uinput_device(uint32_t device_id)
case DEVICEID_MOUSE:
device_type = LinuxUinput::kMouseDevice;
dev_name << " - Mouse Emulation";
break;
case DEVICEID_KEYBOARD:
device_type = LinuxUinput::kGenericDevice;
dev_name << " - Keyboard Emulation";
break;
default:
dev_name << " - " << device_id+1;
break;
}
boost::shared_ptr<LinuxUinput> dev(new LinuxUinput(device_type, dev_name.str(), 0x0000, 0x0000));
uinput_devs.insert(std::pair<int, boost::shared_ptr<LinuxUinput> >(device_id, dev));
std::string dev_name = get_device_name(device_id);
boost::shared_ptr<LinuxUinput> dev(new LinuxUinput(device_type, dev_name, 0x0000, 0x0000));
m_uinput_devs.insert(std::pair<int, boost::shared_ptr<LinuxUinput> >(device_id, dev));
log_debug("created uinput device: " << device_id << " - '" << dev_name.str() << "'");
log_debug("created uinput device: " << device_id << " - '" << dev_name << "'");
return dev.get();
}
@ -112,7 +194,7 @@ UInput::add_ff(uint32_t device_id, uint16_t code)
void
UInput::finish()
{
for(UInputDevs::iterator i = uinput_devs.begin(); i != uinput_devs.end(); ++i)
for(UInputDevs::iterator i = m_uinput_devs.begin(); i != m_uinput_devs.end(); ++i)
{
i->second->finish();
}
@ -142,7 +224,7 @@ UInput::send_key(uint32_t device_id, int ev_code, bool value)
void
UInput::update(int msec_delta)
{
for(std::map<UIEvent, RelRepeat>::iterator i = rel_repeat_lst.begin(); i != rel_repeat_lst.end(); ++i)
for(std::map<UIEvent, RelRepeat>::iterator i = m_rel_repeat_lst.begin(); i != m_rel_repeat_lst.end(); ++i)
{
i->second.time_count += msec_delta;
@ -153,7 +235,7 @@ UInput::update(int msec_delta)
}
}
for(UInputDevs::iterator i = uinput_devs.begin(); i != uinput_devs.end(); ++i)
for(UInputDevs::iterator i = m_uinput_devs.begin(); i != m_uinput_devs.end(); ++i)
{
i->second->update(msec_delta);
}
@ -162,7 +244,7 @@ UInput::update(int msec_delta)
void
UInput::sync()
{
for(UInputDevs::iterator i = uinput_devs.begin(); i != uinput_devs.end(); ++i)
for(UInputDevs::iterator i = m_uinput_devs.begin(); i != m_uinput_devs.end(); ++i)
{
i->second->sync();
}
@ -173,21 +255,21 @@ UInput::send_rel_repetitive(const UIEvent& code, int value, int repeat_interval)
{
if (repeat_interval < 0)
{ // remove rel_repeats from list
rel_repeat_lst.erase(code);
m_rel_repeat_lst.erase(code);
// no need to send a event for rel, as it defaults to 0 anyway
}
else
{ // add rel_repeats to list
std::map<UIEvent, RelRepeat>::iterator it = rel_repeat_lst.find(code);
std::map<UIEvent, RelRepeat>::iterator it = m_rel_repeat_lst.find(code);
if (it == rel_repeat_lst.end())
if (it == m_rel_repeat_lst.end())
{
RelRepeat rel_rep;
rel_rep.code = code;
rel_rep.value = value;
rel_rep.time_count = 0;
rel_rep.repeat_interval = repeat_interval;
rel_repeat_lst.insert(std::pair<UIEvent, RelRepeat>(code, rel_rep));
m_rel_repeat_lst.insert(std::pair<UIEvent, RelRepeat>(code, rel_rep));
// Send the event once
get_uinput(code.get_device_id())->send(EV_REL, code.code, value);
@ -205,8 +287,8 @@ UInput::send_rel_repetitive(const UIEvent& code, int value, int repeat_interval)
LinuxUinput*
UInput::get_uinput(uint32_t device_id) const
{
UInputDevs::const_iterator it = uinput_devs.find(device_id);
if (it != uinput_devs.end())
UInputDevs::const_iterator it = m_uinput_devs.find(device_id);
if (it != m_uinput_devs.end())
{
return it->second.get();
}
@ -219,6 +301,12 @@ UInput::get_uinput(uint32_t device_id) const
}
}
void
UInput::set_device_names(const std::map<uint32_t, std::string>& device_names)
{
m_device_names = device_names;
}
void
UInput::set_ff_callback(int device_id, const boost::function<void (uint8_t, uint8_t)>& callback)
{

View file

@ -31,14 +31,27 @@ struct Xbox360GuitarMsg;
class UInput
{
public:
static inline uint32_t create_device_id(uint16_t slot_id, uint16_t device_id)
static inline uint32_t create_device_id(uint16_t slot_id, uint16_t type_id)
{
return (slot_id << 16) | device_id;
return (slot_id << 16) | type_id;
}
static inline uint16_t get_type_id(uint32_t device_id)
{
return device_id & 0xffff;
}
static inline uint16_t get_slot_id(uint32_t device_id)
{
return ((device_id) >> 16) & 0xffff;
}
private:
typedef std::map<uint32_t, boost::shared_ptr<LinuxUinput> > UInputDevs;
UInputDevs uinput_devs;
UInputDevs m_uinput_devs;
typedef std::map<uint32_t, std::string> DeviceNames;
DeviceNames m_device_names;
struct RelRepeat
{
@ -48,7 +61,7 @@ private:
int repeat_interval;
};
std::map<UIEvent, RelRepeat> rel_repeat_lst;
std::map<UIEvent, RelRepeat> m_rel_repeat_lst;
boost::mutex m_mutex;
@ -58,6 +71,7 @@ public:
void update(int msec_delta);
void set_device_names(const std::map<uint32_t, std::string>& device_names);
void set_ff_callback(int device_id, const boost::function<void (uint8_t, uint8_t)>& callback);
/** Device construction functions
@ -93,6 +107,8 @@ private:
/** must only be called with a valid device_id */
LinuxUinput* get_uinput(uint32_t device_id) const;
std::string get_device_name(uint32_t device_id) const;
};
#endif

View file

@ -22,7 +22,6 @@
#include <linux/input.h>
UInputOptions::UInputOptions() :
device_name("Xbox Gamepad (userspace driver)"),
m_btn_map(),
m_axis_map()
{
@ -56,7 +55,8 @@ UInputOptions::get_axis_map() const
void
UInputOptions::mimic_xpad()
{
device_name = "Microsoft X-Box 360 pad";
// FIXME: need to set this somewhere:
// device_name = "Microsoft X-Box 360 pad";
get_btn_map().bind(XBOX_BTN_START, ButtonEvent::create_key(BTN_START));
get_btn_map().bind(XBOX_BTN_GUIDE, ButtonEvent::create_key(BTN_MODE));

View file

@ -24,9 +24,6 @@
class UInputOptions
{
public:
std::string device_name;
private:
ButtonMap m_btn_map;
AxisMap m_axis_map;

View file

@ -443,6 +443,7 @@ Xboxdrv::run_main(const Options& opts)
if (!opts.quiet)
std::cout << "Starting with uinput" << std::endl;
uinput = std::auto_ptr<UInput>(new UInput());
uinput->set_device_names(opts.uinput_device_names);
}
else
{

View file

@ -203,6 +203,7 @@ XboxdrvDaemon::init_uinput(const Options& opts)
log_info("starting with UInput");
m_uinput.reset(new UInput());
m_uinput->set_device_names(opts.uinput_device_names);
// create controller slots
int slot_count = 0;

24
test/xboxdrv-match-rules.sh Executable file
View file

@ -0,0 +1,24 @@
#!/bin/sh
echo "Use flightstick config for regular Xbox360 controller and fighting game config for arcade stick"
echo
./xboxdrv --daemon \
`# regular Xbox360 controller gets flightstick threatment` \
--name "Fightstick" \
--match-group usbserial=13FEF2D \
--trigger-as-zaxis --square-axis \
--relative-axis y2=64000 \
--axismap -y2=x2,x2=y2 \
--next-controller \
`# arcade stick gets fighting config` \
--name "Xbox360 Controller" \
--match-group usbserial=89E88EEF \
--dpad-only \
--trigger-as-button \
--buttonmap lb=1,x=2,y=3,lt=4,a=5,b=6 \
--buttonmap rb=1,rb=2,rb=3 \
--buttonmap rt=4,rt=5,rt=6 \
"$@"
# EOF #