Fixed issues with Controller activation, moved activation code into Controller
This commit is contained in:
parent
3ed8af3b8b
commit
be39c5db49
6 changed files with 129 additions and 52 deletions
|
@ -26,7 +26,9 @@
|
||||||
Controller::Controller() :
|
Controller::Controller() :
|
||||||
m_msg_cb(),
|
m_msg_cb(),
|
||||||
m_disconnect_cb(),
|
m_disconnect_cb(),
|
||||||
|
m_activation_cb(),
|
||||||
m_is_disconnected(false),
|
m_is_disconnected(false),
|
||||||
|
m_is_active(true),
|
||||||
m_udev_device()
|
m_udev_device()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -64,6 +66,26 @@ Controller::get_udev_device() const
|
||||||
return m_udev_device;
|
return m_udev_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Controller::set_active(bool v)
|
||||||
|
{
|
||||||
|
if (m_is_active != v)
|
||||||
|
{
|
||||||
|
log_debug("activation status: " << v << " " << m_activation_cb);
|
||||||
|
m_is_active = v;
|
||||||
|
if (m_activation_cb)
|
||||||
|
{
|
||||||
|
m_activation_cb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Controller::set_activation_cb(const boost::function<void ()>& callback)
|
||||||
|
{
|
||||||
|
m_activation_cb = callback;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Controller::is_disconnected() const
|
Controller::is_disconnected() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,9 @@ class Controller
|
||||||
protected:
|
protected:
|
||||||
boost::function<void (const XboxGenericMsg&)> m_msg_cb;
|
boost::function<void (const XboxGenericMsg&)> m_msg_cb;
|
||||||
boost::function<void ()> m_disconnect_cb;
|
boost::function<void ()> m_disconnect_cb;
|
||||||
|
boost::function<void ()> m_activation_cb;
|
||||||
bool m_is_disconnected;
|
bool m_is_disconnected;
|
||||||
|
bool m_is_active;
|
||||||
udev_device* m_udev_device;
|
udev_device* m_udev_device;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -43,9 +45,16 @@ public:
|
||||||
virtual void set_rumble(uint8_t left, uint8_t right) =0;
|
virtual void set_rumble(uint8_t left, uint8_t right) =0;
|
||||||
virtual void set_led(uint8_t status) =0;
|
virtual void set_led(uint8_t status) =0;
|
||||||
|
|
||||||
virtual bool is_active() const { return true; }
|
/** Wireless Controller start out inactive when they are not synced
|
||||||
virtual void set_activation_cb(const boost::function<void ()>& callback) {}
|
with their receiver and become active after the sync. Regular
|
||||||
|
USB controller are always active. Active controllers can become
|
||||||
|
inactive and vice versa. */
|
||||||
|
virtual bool is_active() const { return m_is_active; }
|
||||||
|
virtual void set_active(bool v);
|
||||||
|
virtual void set_activation_cb(const boost::function<void ()>& callback);
|
||||||
|
|
||||||
|
/** Controllers with a disconnect status have been unplugged and are
|
||||||
|
not coming back, thus the Controller object can be destroyed */
|
||||||
virtual bool is_disconnected() const;
|
virtual bool is_disconnected() const;
|
||||||
virtual void set_disconnect_cb(const boost::function<void ()>& callback);
|
virtual void set_disconnect_cb(const boost::function<void ()>& callback);
|
||||||
virtual void send_disconnect();
|
virtual void send_disconnect();
|
||||||
|
|
|
@ -30,14 +30,15 @@
|
||||||
Xbox360WirelessController::Xbox360WirelessController(libusb_device* dev, int controller_id,
|
Xbox360WirelessController::Xbox360WirelessController(libusb_device* dev, int controller_id,
|
||||||
bool try_detach) :
|
bool try_detach) :
|
||||||
USBController(dev),
|
USBController(dev),
|
||||||
m_active(false),
|
|
||||||
m_endpoint(),
|
m_endpoint(),
|
||||||
m_interface(),
|
m_interface(),
|
||||||
m_battery_status(),
|
m_battery_status(),
|
||||||
m_serial(),
|
m_serial(),
|
||||||
m_led_status(0),
|
m_led_status(0)
|
||||||
m_activation_cb()
|
|
||||||
{
|
{
|
||||||
|
// FIXME: A little bit of a hack
|
||||||
|
m_is_active = false;
|
||||||
|
|
||||||
assert(controller_id >= 0 && controller_id < 4);
|
assert(controller_id >= 0 && controller_id < 4);
|
||||||
|
|
||||||
// FIXME: Is hardcoding those ok?
|
// FIXME: Is hardcoding those ok?
|
||||||
|
@ -200,24 +201,4 @@ Xbox360WirelessController::parse(uint8_t* data, int len, XboxGenericMsg* msg_out
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Xbox360WirelessController::set_active(bool v)
|
|
||||||
{
|
|
||||||
if (m_active != v)
|
|
||||||
{
|
|
||||||
log_debug("activation status: " << v);
|
|
||||||
m_active = v;
|
|
||||||
if (m_activation_cb)
|
|
||||||
{
|
|
||||||
m_activation_cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Xbox360WirelessController::set_activation_cb(const boost::function<void ()> callback)
|
|
||||||
{
|
|
||||||
m_activation_cb = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -30,15 +30,12 @@ struct XPadDevice;
|
||||||
class Xbox360WirelessController : public USBController
|
class Xbox360WirelessController : public USBController
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool m_active;
|
|
||||||
int m_endpoint;
|
int m_endpoint;
|
||||||
int m_interface;
|
int m_interface;
|
||||||
int m_battery_status;
|
int m_battery_status;
|
||||||
std::string m_serial;
|
std::string m_serial;
|
||||||
int m_led_status;
|
int m_led_status;
|
||||||
|
|
||||||
boost::function<void ()> m_activation_cb;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Xbox360WirelessController(libusb_device* dev, int controller_id, bool try_detach);
|
Xbox360WirelessController(libusb_device* dev, int controller_id, bool try_detach);
|
||||||
virtual ~Xbox360WirelessController();
|
virtual ~Xbox360WirelessController();
|
||||||
|
@ -48,11 +45,6 @@ public:
|
||||||
void set_rumble(uint8_t left, uint8_t right);
|
void set_rumble(uint8_t left, uint8_t right);
|
||||||
void set_led(uint8_t status);
|
void set_led(uint8_t status);
|
||||||
uint8_t get_battery_status() const;
|
uint8_t get_battery_status() const;
|
||||||
bool is_active() const { return m_active; }
|
|
||||||
void set_activation_cb(const boost::function<void ()> callback);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void set_active(bool v);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Xbox360WirelessController (const Xbox360WirelessController&);
|
Xbox360WirelessController (const Xbox360WirelessController&);
|
||||||
|
|
|
@ -268,16 +268,6 @@ XboxdrvDaemon::create_pid_file()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
XboxdrvDaemon::on_wakeup()
|
|
||||||
{
|
|
||||||
log_info("got a wakeup call");
|
|
||||||
|
|
||||||
on_controller_disconnect();
|
|
||||||
|
|
||||||
return false; // remove the registered idle callback
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerSlotPtr
|
ControllerSlotPtr
|
||||||
XboxdrvDaemon::find_free_slot(udev_device* dev)
|
XboxdrvDaemon::find_free_slot(udev_device* dev)
|
||||||
{
|
{
|
||||||
|
@ -332,7 +322,8 @@ XboxdrvDaemon::launch_controller_thread(udev_device* udev_dev,
|
||||||
{
|
{
|
||||||
ControllerPtr& controller = *i;
|
ControllerPtr& controller = *i;
|
||||||
|
|
||||||
controller->set_disconnect_cb(boost::bind(&XboxdrvDaemon::wakeup, this));
|
controller->set_disconnect_cb(boost::bind(&g_idle_add, &XboxdrvDaemon::on_controller_disconnect_wrap, this));
|
||||||
|
controller->set_activation_cb(boost::bind(&g_idle_add, &XboxdrvDaemon::on_controller_activate_wrap, this));
|
||||||
|
|
||||||
// FIXME: Little dirty hack
|
// FIXME: Little dirty hack
|
||||||
controller->set_udev_device(udev_dev);
|
controller->set_udev_device(udev_dev);
|
||||||
|
@ -358,7 +349,6 @@ XboxdrvDaemon::launch_controller_thread(udev_device* udev_dev,
|
||||||
}
|
}
|
||||||
else // if (!controller->is_active())
|
else // if (!controller->is_active())
|
||||||
{
|
{
|
||||||
controller->set_activation_cb(boost::bind(&XboxdrvDaemon::wakeup, this));
|
|
||||||
m_inactive_controllers.push_back(controller);
|
m_inactive_controllers.push_back(controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,10 +459,12 @@ XboxdrvDaemon::on_disconnect(ControllerSlotPtr slot)
|
||||||
void
|
void
|
||||||
XboxdrvDaemon::on_controller_disconnect()
|
XboxdrvDaemon::on_controller_disconnect()
|
||||||
{
|
{
|
||||||
|
log_tmp("on_controller_disconnect");
|
||||||
|
|
||||||
// cleanup active controllers in slots
|
// cleanup active controllers in slots
|
||||||
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
||||||
{
|
{
|
||||||
if ((*i)->get_controller()->is_disconnected())
|
if ((*i)->get_controller() && (*i)->get_controller()->is_disconnected())
|
||||||
{
|
{
|
||||||
disconnect(*i); // discard the ControllerPtr
|
disconnect(*i); // discard the ControllerPtr
|
||||||
}
|
}
|
||||||
|
@ -485,9 +477,12 @@ XboxdrvDaemon::on_controller_disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
XboxdrvDaemon::wakeup()
|
XboxdrvDaemon::on_controller_activate()
|
||||||
{
|
{
|
||||||
g_idle_add(&XboxdrvDaemon::on_wakeup_wrap, this);
|
log_tmp("on_controller_activate");
|
||||||
|
|
||||||
|
cleanup_threads();
|
||||||
|
check_thread_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
@ -541,4 +536,75 @@ XboxdrvDaemon::on_sigint(int)
|
||||||
XboxdrvDaemon::current()->shutdown();
|
XboxdrvDaemon::current()->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XboxdrvDaemon::cleanup_threads()
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
||||||
|
{
|
||||||
|
if ((*i)->is_connected())
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
on_disconnect(*i);
|
||||||
|
|
||||||
|
// disconnect slot and put the controller back into the inactive group
|
||||||
|
m_inactive_controllers.push_back((*i)->disconnect());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
log_info("cleaned up " << count << " thread(s), free slots: " <<
|
||||||
|
get_free_slot_count() << "/" << m_controller_slots.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XboxdrvDaemon::check_thread_status()
|
||||||
|
{
|
||||||
|
// check for inactive controller and free the slots
|
||||||
|
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
||||||
|
{
|
||||||
|
// if a slot contains an inactive controller, disconnect it and save
|
||||||
|
// the controller for later when it might be active again
|
||||||
|
if ((*i)->get_controller() && !(*i)->get_controller()->is_active())
|
||||||
|
{
|
||||||
|
ControllerPtr controller = disconnect(*i);
|
||||||
|
m_inactive_controllers.push_back(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for activated controller and connect them to a slot
|
||||||
|
for(Controllers::iterator i = m_inactive_controllers.begin(); i != m_inactive_controllers.end(); ++i)
|
||||||
|
{
|
||||||
|
if (!*i)
|
||||||
|
{
|
||||||
|
log_error("NULL in m_inactive_controllers, shouldn't happen");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((*i)->is_active())
|
||||||
|
{
|
||||||
|
ControllerSlotPtr slot = find_free_slot((*i)->get_udev_device());
|
||||||
|
if (!slot)
|
||||||
|
{
|
||||||
|
log_info("couldn't find a free slot for activated controller");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connect(slot, *i);
|
||||||
|
|
||||||
|
// successfully connected the controller, so set it to NULL and cleanup later
|
||||||
|
*i = ControllerPtr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup inactive controller
|
||||||
|
m_inactive_controllers.erase(std::remove(m_inactive_controllers.begin(), m_inactive_controllers.end(), ControllerPtr()),
|
||||||
|
m_inactive_controllers.end());
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -82,13 +82,20 @@ private:
|
||||||
void on_disconnect(ControllerSlotPtr slot);
|
void on_disconnect(ControllerSlotPtr slot);
|
||||||
|
|
||||||
void on_controller_disconnect();
|
void on_controller_disconnect();
|
||||||
|
void on_controller_activate();
|
||||||
|
|
||||||
void wakeup();
|
void check_thread_status();
|
||||||
|
void cleanup_threads();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool on_wakeup();
|
static gboolean on_controller_disconnect_wrap(gpointer data) {
|
||||||
static gboolean on_wakeup_wrap(gpointer data) {
|
static_cast<XboxdrvDaemon*>(data)->on_controller_disconnect();
|
||||||
return static_cast<XboxdrvDaemon*>(data)->on_wakeup();
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean on_controller_activate_wrap(gpointer data) {
|
||||||
|
static_cast<XboxdrvDaemon*>(data)->on_controller_activate();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue