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() :
m_msg_cb(),
m_disconnect_cb(),
m_activation_cb(),
m_is_disconnected(false),
m_is_active(true),
m_udev_device()
{
}
@ -64,6 +66,26 @@ Controller::get_udev_device() const
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
Controller::is_disconnected() const
{

View file

@ -33,7 +33,9 @@ class Controller
protected:
boost::function<void (const XboxGenericMsg&)> m_msg_cb;
boost::function<void ()> m_disconnect_cb;
boost::function<void ()> m_activation_cb;
bool m_is_disconnected;
bool m_is_active;
udev_device* m_udev_device;
public:
@ -43,9 +45,16 @@ public:
virtual void set_rumble(uint8_t left, uint8_t right) =0;
virtual void set_led(uint8_t status) =0;
virtual bool is_active() const { return true; }
virtual void set_activation_cb(const boost::function<void ()>& callback) {}
/** Wireless Controller start out inactive when they are not synced
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 void set_disconnect_cb(const boost::function<void ()>& callback);
virtual void send_disconnect();

View file

@ -30,14 +30,15 @@
Xbox360WirelessController::Xbox360WirelessController(libusb_device* dev, int controller_id,
bool try_detach) :
USBController(dev),
m_active(false),
m_endpoint(),
m_interface(),
m_battery_status(),
m_serial(),
m_led_status(0),
m_activation_cb()
m_led_status(0)
{
// FIXME: A little bit of a hack
m_is_active = false;
assert(controller_id >= 0 && controller_id < 4);
// FIXME: Is hardcoding those ok?
@ -200,24 +201,4 @@ Xbox360WirelessController::parse(uint8_t* data, int len, XboxGenericMsg* msg_out
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 */

View file

@ -30,15 +30,12 @@ struct XPadDevice;
class Xbox360WirelessController : public USBController
{
private:
bool m_active;
int m_endpoint;
int m_interface;
int m_battery_status;
std::string m_serial;
int m_led_status;
boost::function<void ()> m_activation_cb;
public:
Xbox360WirelessController(libusb_device* dev, int controller_id, bool try_detach);
virtual ~Xbox360WirelessController();
@ -48,12 +45,7 @@ public:
void set_rumble(uint8_t left, uint8_t right);
void set_led(uint8_t status);
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:
Xbox360WirelessController (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
XboxdrvDaemon::find_free_slot(udev_device* dev)
{
@ -332,7 +322,8 @@ XboxdrvDaemon::launch_controller_thread(udev_device* udev_dev,
{
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
controller->set_udev_device(udev_dev);
@ -358,7 +349,6 @@ XboxdrvDaemon::launch_controller_thread(udev_device* udev_dev,
}
else // if (!controller->is_active())
{
controller->set_activation_cb(boost::bind(&XboxdrvDaemon::wakeup, this));
m_inactive_controllers.push_back(controller);
}
}
@ -469,10 +459,12 @@ XboxdrvDaemon::on_disconnect(ControllerSlotPtr slot)
void
XboxdrvDaemon::on_controller_disconnect()
{
log_tmp("on_controller_disconnect");
// cleanup active controllers in slots
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
}
@ -485,9 +477,12 @@ XboxdrvDaemon::on_controller_disconnect()
}
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
@ -541,4 +536,75 @@ XboxdrvDaemon::on_sigint(int)
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 */

View file

@ -82,13 +82,20 @@ private:
void on_disconnect(ControllerSlotPtr slot);
void on_controller_disconnect();
void on_controller_activate();
void wakeup();
void check_thread_status();
void cleanup_threads();
private:
bool on_wakeup();
static gboolean on_wakeup_wrap(gpointer data) {
return static_cast<XboxdrvDaemon*>(data)->on_wakeup();
static gboolean on_controller_disconnect_wrap(gpointer data) {
static_cast<XboxdrvDaemon*>(data)->on_controller_disconnect();
return false;
}
static gboolean on_controller_activate_wrap(gpointer data) {
static_cast<XboxdrvDaemon*>(data)->on_controller_activate();
return false;
}
private: