Cleaned up debugging output, fixed bugs on shutdown and fixed reconnection issues in daemon

This commit is contained in:
Ingo Ruhnke 2011-03-20 21:39:45 +01:00
parent 3ca7573177
commit dbd033030a
12 changed files with 66 additions and 167 deletions

4
TODO
View file

@ -73,6 +73,10 @@ Checklist
* check that uinput gets its timeout/update calls (send_rel_event)
* cleanup a lot of the log_trace() and other temporary debug output
* check that repeated wireless controller connects and disconnects work
Stuff to do before 0.7.4 release:
=================================

View file

@ -1 +1 @@
0.7.4
0.8.0

View file

@ -37,7 +37,6 @@ Controller::~Controller()
void
Controller::submit_msg(const XboxGenericMsg& msg)
{
log_trace();
if (m_msg_cb)
{
m_msg_cb(msg);

View file

@ -33,8 +33,6 @@ ControllerThread::ControllerThread(ControllerPtr controller, const Options& opts
m_processor(),
m_controller(controller),
m_oldrealmsg(),
m_child_exec(opts.exec),
m_pid(-1),
m_timeout(opts.timeout),
m_timeout_id(),
m_timer(g_timer_new())
@ -66,8 +64,6 @@ ControllerThread::on_message(const XboxGenericMsg& msg)
{
m_oldrealmsg = msg;
log_trace();
int msec_delta = static_cast<int>(g_timer_elapsed(m_timer, NULL) * 1000.0f);
g_timer_reset(m_timer);

View file

@ -42,9 +42,6 @@ private:
XboxGenericMsg m_oldrealmsg; /// last data read from the device
std::vector<std::string> m_child_exec;
pid_t m_pid;
int m_timeout;
guint m_timeout_id;
GTimer* m_timer;

View file

@ -28,6 +28,7 @@
USBController::USBController(libusb_device* dev) :
m_dev(dev),
m_handle(0),
m_read_transfer(),
m_usbpath(),
m_usbid(),
m_name()
@ -77,6 +78,12 @@ USBController::USBController(libusb_device* dev) :
USBController::~USBController()
{
usb_cancel_read();
if (m_read_transfer)
{
libusb_free_transfer(m_read_transfer);
}
//libusb_release_interface(m_handle, 0);
libusb_close(m_handle);
}
@ -102,33 +109,38 @@ USBController::get_name() const
void
USBController::usb_submit_read(int endpoint, int len)
{
log_debug("ep: " << endpoint << " len: " << len);
assert(!m_read_transfer);
libusb_transfer* transfer = libusb_alloc_transfer(0);
//log_debug("ep: " << endpoint << " len: " << len);
m_read_transfer = libusb_alloc_transfer(0);
uint8_t* data = static_cast<uint8_t*>(malloc(sizeof(uint8_t) * len));
//FIXME: transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER;
libusb_fill_interrupt_transfer(transfer, m_handle,
m_read_transfer->flags |= LIBUSB_TRANSFER_FREE_BUFFER;
libusb_fill_interrupt_transfer(m_read_transfer, m_handle,
endpoint | LIBUSB_ENDPOINT_IN,
data, len,
&USBController::on_read_data_wrap, this,
0); // timeout
int ret;
ret = libusb_submit_transfer(transfer);
log_debug("libusb_submit_transfer: " << usb_strerror(ret));
ret = libusb_submit_transfer(m_read_transfer);
if (ret != LIBUSB_SUCCESS)
{
raise_exception(std::runtime_error, "libusb_submit_transfer(): " << usb_strerror(ret));
}
}
void
USBController::usb_cancel_read()
{
assert(!"implement me");
assert(m_read_transfer);
libusb_cancel_transfer(m_read_transfer);
m_read_transfer = 0;
}
void
USBController::on_read_data(libusb_transfer *transfer)
{
log_trace();
assert(transfer);
// process data

View file

@ -31,6 +31,8 @@ protected:
libusb_device* m_dev;
libusb_device_handle* m_handle;
libusb_transfer* m_read_transfer;
std::string m_usbpath;
std::string m_usbid;
std::string m_name;

View file

@ -24,10 +24,8 @@
#include <stdlib.h>
#include "log.hpp"
#include "usb_helper.hpp"
// GUSBSource
// documentation at: http://library.gnome.org/devel/glib/2.28/
USBGSource::USBGSource() :
m_source_funcs(),
m_source(),
@ -54,7 +52,6 @@ USBGSource::USBGSource() :
const libusb_pollfd** fds = libusb_get_pollfds(NULL);
for(const libusb_pollfd** i = fds; *i != NULL; ++i)
{
log_debug("adding pollfd: " << (*i)->fd);
on_usb_pollfd_added((*i)->fd, (*i)->events);
}
free(fds);
@ -68,6 +65,8 @@ USBGSource::USBGSource() :
USBGSource::~USBGSource()
{
// get rid of the callbacks as they will be triggered by libusb_exit()
libusb_set_pollfd_notifiers(NULL, NULL, NULL, NULL);
}
void
@ -80,7 +79,6 @@ USBGSource::attach(GMainContext* context)
void
USBGSource::on_usb_pollfd_added(int fd, short events)
{
log_debug(fd << " " << events);
GPollFD* gfd = new GPollFD;
gfd->fd = fd;
@ -95,8 +93,6 @@ USBGSource::on_usb_pollfd_added(int fd, short events)
void
USBGSource::on_usb_pollfd_removed(int fd)
{
log_debug(fd);
// find the GPollFD that matched the given \a fd
std::list<GPollFD*>::iterator it = m_pollfds.end();
for(std::list<GPollFD*>::iterator i = m_pollfds.begin(); i != m_pollfds.end(); ++i)
@ -119,41 +115,43 @@ USBGSource::on_usb_pollfd_removed(int fd)
gboolean
USBGSource::on_source_prepare(GSource* source, gint* timeout)
{
log_trace();
struct timeval tv;
int ret = libusb_get_next_timeout(NULL, &tv);
log_debug("libusb_get_next_timeout(): " << ret);
if (ret == LIBUSB_SUCCESS)
if (ret == 0) // no timeouts
{
// no timeout
*timeout = -1;
}
else if (ret == 1) // timeout was returned
{
*timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}
else
{
// convert tv
log_error("libusb_get_next_timeout() failed: " << usb_strerror(ret));
*timeout = -1;
}
// FALSE means the source isn't yet ready
return FALSE;
}
gboolean
USBGSource::on_source_check(GSource* source)
{
log_trace();
USBGSource* usb_source = reinterpret_cast<GUSBSource*>(source)->usb_source;
log_debug("Number of PollFD: " << usb_source->m_pollfds.size());
//log_debug("Number of PollFD: " << usb_source->m_pollfds.size());
for(std::list<GPollFD*>::iterator i = usb_source->m_pollfds.begin(); i != usb_source->m_pollfds.end(); ++i)
{
log_debug("GSource GPollFD: " << (*i)->fd);
log_debug("REvents: G_IO_OUT: " << ((*i)->revents & G_IO_OUT));
log_debug(" G_IO_IN: " << ((*i)->revents & G_IO_IN));
log_debug(" G_IO_PRI: " << ((*i)->revents & G_IO_PRI));
log_debug(" G_IO_HUP: " << ((*i)->revents & G_IO_HUP));
log_debug(" G_IO_ERR: " << ((*i)->revents & G_IO_ERR));
if (false)
{
log_debug("GSource GPollFD: " << (*i)->fd);
log_debug("REvents: G_IO_OUT: " << ((*i)->revents & G_IO_OUT));
log_debug(" G_IO_IN: " << ((*i)->revents & G_IO_IN));
log_debug(" G_IO_PRI: " << ((*i)->revents & G_IO_PRI));
log_debug(" G_IO_HUP: " << ((*i)->revents & G_IO_HUP));
log_debug(" G_IO_ERR: " << ((*i)->revents & G_IO_ERR));
}
if ((*i)->revents)
{
@ -167,16 +165,13 @@ USBGSource::on_source_check(GSource* source)
gboolean
USBGSource::on_source_dispatch(GSource* source, GSourceFunc callback, gpointer userdata)
{
log_trace();
return callback(userdata);
}
gboolean
USBGSource::on_source()
{
log_debug("libusb_handle_events()");
libusb_handle_events(NULL);
log_debug("libusb_handle_events() done");
return TRUE;
}

View file

@ -1,60 +0,0 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "wakeup_pipe.hpp"
#include <errno.h>
#include <stdexcept>
#include <string.h>
#include <unistd.h>
#include "raise_exception.hpp"
WakeupPipe::WakeupPipe()
{
int ret = pipe(m_pipefd);
if (ret < 0)
{
raise_exception(std::runtime_error, "pipe() failed: " << strerror(errno));
}
}
int
WakeupPipe::get_read_fd() const
{
return m_pipefd[0];
}
int
WakeupPipe::get_write_fd() const
{
return m_pipefd[1];
}
void
WakeupPipe::send_wakeup()
{
char buf[1] = {0};
ssize_t ret = write(get_write_fd(), buf, sizeof(buf));
if (ret < 0)
{
raise_exception(std::runtime_error, "write() to pipe failed: " << strerror(errno));
}
}
/* EOF */

View file

@ -1,42 +0,0 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2011 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_WAKEUP_PIPE_HPP
#define HEADER_XBOXDRV_WAKEUP_PIPE_HPP
class WakeupPipe
{
private:
int m_pipefd[2];
public:
WakeupPipe();
int get_read_fd() const;
int get_write_fd() const;
void send_wakeup();
private:
WakeupPipe(const WakeupPipe&);
WakeupPipe& operator=(const WakeupPipe&);
};
#endif
/* EOF */

View file

@ -115,9 +115,14 @@ XboxdrvDaemon::~XboxdrvDaemon()
assert(s_current);
s_current = 0;
m_inactive_controllers.clear();
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
{
(*i)->disconnect();
if ((*i)->is_connected())
{
(*i)->disconnect();
}
}
udev_monitor_unref(m_monitor);
@ -134,9 +139,10 @@ XboxdrvDaemon::cleanup_threads()
if ((*i)->is_connected())
{
count += 1;
// FIXME: we kill the thread in try_disconnect() but on_disconnect() needs it
on_disconnect(*i);
(*i)->disconnect();
// disconnect slot and put the controller back into the inactive group
m_inactive_controllers.push_back((*i)->disconnect());
}
}
@ -490,12 +496,6 @@ XboxdrvDaemon::on_udev_data(GIOChannel* channel, GIOCondition condition)
return true;
}
gboolean
XboxdrvDaemon::on_udev_data_wrap(GIOChannel* channel, GIOCondition condition, gpointer data)
{
return static_cast<XboxdrvDaemon*>(data)->on_udev_data(channel, condition);
}
void
XboxdrvDaemon::check_thread_status()
{
@ -811,20 +811,10 @@ XboxdrvDaemon::on_disconnect(ControllerSlotPtr slot)
}
}
gboolean
XboxdrvDaemon::on_wakeup_wrap(gpointer data)
{
log_info("wrapper called");
return static_cast<XboxdrvDaemon*>(data)->on_wakeup();
}
void
XboxdrvDaemon::wakeup()
{
log_info("received wakeup call");
g_idle_add(&XboxdrvDaemon::on_wakeup_wrap, this);
g_main_context_wakeup(NULL);
log_info("idle_add called");
}
std::string

View file

@ -96,12 +96,18 @@ private:
void wakeup();
private:
bool on_wakeup();
bool on_udev_data(GIOChannel* channel, GIOCondition condition);
private:
static gboolean on_udev_data_wrap(GIOChannel* channel, GIOCondition condition, gpointer data);
static gboolean on_wakeup_wrap(gpointer data);
static gboolean on_wakeup_wrap(gpointer data) {
return static_cast<XboxdrvDaemon*>(data)->on_wakeup();
}
static gboolean on_udev_data_wrap(GIOChannel* channel, GIOCondition condition, gpointer data) {
return static_cast<XboxdrvDaemon*>(data)->on_udev_data(channel, condition);
}
private:
XboxdrvDaemon(const XboxdrvDaemon&);