diff --git a/src/controller_match_rule.cpp b/src/controller_match_rule.cpp index cea7a0b..b2076a8 100644 --- a/src/controller_match_rule.cpp +++ b/src/controller_match_rule.cpp @@ -22,7 +22,8 @@ bool ControllerMatchRule::match(int vendor, int product, - int bus, int dev) const + int bus, int dev, + const char* serial) const { switch(m_type) { @@ -35,6 +36,9 @@ ControllerMatchRule::match(int vendor, int product, case kMatchUSBPath: return (bus == m_bus && dev == m_dev); + case kMatchUSBSerial: + return serial && (m_serial == serial); + case kMatchEvdevPath: assert(!"not implemented"); return false; @@ -50,7 +54,7 @@ ControllerMatchRule::create_usb_id(int vendor, int product) { ControllerMatchRule rule; rule.m_type = kMatchUSBId; - rule.m_vendor = vendor; + rule.m_vendor = vendor; rule.m_product = product; return rule; } @@ -65,6 +69,15 @@ ControllerMatchRule::create_usb_path(int bus, int dev) return rule; } +ControllerMatchRule +ControllerMatchRule::create_usb_serial(const std::string& serial) +{ + ControllerMatchRule rule; + rule.m_type = kMatchUSBSerial; + rule.m_serial = serial; + return rule; +} + ControllerMatchRule ControllerMatchRule::create_evdev_path(const std::string& path) { diff --git a/src/controller_match_rule.hpp b/src/controller_match_rule.hpp index 8fe5829..9e3c720 100644 --- a/src/controller_match_rule.hpp +++ b/src/controller_match_rule.hpp @@ -28,6 +28,7 @@ public: kMatchEverything, kMatchUSBId, kMatchUSBPath, + kMatchUSBSerial, kMatchEvdevPath } m_type; @@ -39,20 +40,25 @@ public: std::string m_path; + std::string m_serial; + ControllerMatchRule() : m_type(kMatchEverything), m_bus(), m_dev(), m_vendor(), m_product(), - m_path() + m_path(), + m_serial() {} bool match(int vendor, int product, - int bus, int dev) const; + int bus, int dev, + const char* serial) const; static ControllerMatchRule create_usb_id(int vendor, int product); static ControllerMatchRule create_usb_path(int bus, int dev); + static ControllerMatchRule create_usb_serial(const std::string& serial); static ControllerMatchRule create_evdev_path(const std::string& path); }; diff --git a/src/options.cpp b/src/options.cpp index a68b4a1..0e01be1 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -269,6 +269,17 @@ Options::add_match(const std::string& lhs, const std::string& rhs) get_controller_slot().add_match_rule(ControllerMatchRule::create_usb_path(bus, dev)); } } + else if (lhs == "usbserial") + { + if (args.size() != 1) + { + raise_exception(std::runtime_error, "usbserial rule requires SERIAL argument"); + } + else + { + get_controller_slot().add_match_rule(ControllerMatchRule::create_usb_serial(args[0])); + } + } else if (lhs == "evdev") { if (args.size() != 1) diff --git a/src/xboxdrv_daemon.cpp b/src/xboxdrv_daemon.cpp index 2134e59..fb41612 100644 --- a/src/xboxdrv_daemon.cpp +++ b/src/xboxdrv_daemon.cpp @@ -166,7 +166,9 @@ XboxdrvDaemon::process_match(const Options& opts, struct udev_device* device) } else { - ControllerSlot* slot = find_free_slot(vendor, product, bus, dev); + const char* serial = udev_device_get_property_value(device, "ID_SERIAL_SHORT"); + + ControllerSlot* slot = find_free_slot(vendor, product, bus, dev, serial); if (!slot) { log_error("no free controller slot found, controller will be ignored"); @@ -386,8 +388,8 @@ XboxdrvDaemon::print_info(struct udev_device* device) //udev_device_get_sysattr_value(device, "busnum"); //udev_device_get_sysattr_value(device, "devnum"); -#if FIXME - // only works with newer versions of libudev +#if 0 + // FIXME: only works with newer versions of libudev { log_debug("list: "); struct udev_list_entry* it = udev_device_get_tags_list_entry(device); @@ -430,7 +432,8 @@ XboxdrvDaemon::print_info(struct udev_device* device) XboxdrvDaemon::ControllerSlot* XboxdrvDaemon::find_free_slot(uint16_t vendor, uint16_t product, - int bus, int dev) const + int bus, int dev, + const char* serial) const { // first pass, look for slots where the rules match the given vendor:product, bus:dev for(ControllerSlots::const_iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i) @@ -440,7 +443,7 @@ XboxdrvDaemon::find_free_slot(uint16_t vendor, uint16_t product, // found a free slot, check if the rules match for(std::vector<ControllerMatchRule>::const_iterator rule = i->rules.begin(); rule != i->rules.end(); ++rule) { - if (rule->match(vendor, product, bus, dev)) + if (rule->match(vendor, product, bus, dev, serial)) { // FIXME: ugly const_cast return const_cast<ControllerSlot*>(&(*i)); diff --git a/src/xboxdrv_daemon.hpp b/src/xboxdrv_daemon.hpp index 568f615..b117764 100644 --- a/src/xboxdrv_daemon.hpp +++ b/src/xboxdrv_daemon.hpp @@ -98,7 +98,7 @@ private: void run_loop(const Options& opts); ControllerSlot* find_free_slot(uint16_t vendor, uint16_t product, - int bus, int dev) const; + int bus, int dev, const char* serial) const; void cleanup_threads(); void process_match(const Options& opts, struct udev_device* device);