Fixed issues with Controller activation, moved activation code into Controller

This commit is contained in:
Ingo Ruhnke 2011-05-23 14:38:12 +02:00
parent 3ed8af3b8b
commit be39c5db49
6 changed files with 129 additions and 52 deletions

View file

@ -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
{ {

View file

@ -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();

View file

@ -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 */

View file

@ -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,12 +45,7 @@ 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&);
Xbox360WirelessController& operator= (const Xbox360WirelessController&); Xbox360WirelessController& operator= (const Xbox360WirelessController&);

View file

@ -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 */

View file

@ -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: