From d047b207ee5668f1d2eb862168c6b36af3ab9458 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke <grumbel@gmx.de> Date: Wed, 29 Jul 2009 15:43:23 +0200 Subject: [PATCH] Some experimental work on using threads for reading from USB --- src/usb_read_thread.cpp | 96 +++++++++++++++++++++++++++++++++++++++++ src/usb_read_thread.hpp | 63 +++++++++++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 src/usb_read_thread.cpp create mode 100644 src/usb_read_thread.hpp diff --git a/src/usb_read_thread.cpp b/src/usb_read_thread.cpp new file mode 100644 index 0000000..9be1d32 --- /dev/null +++ b/src/usb_read_thread.cpp @@ -0,0 +1,96 @@ +/* +** Xbox/Xbox360 USB Gamepad Userspace Driver +** Copyright (C) 2008 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 <assert.h> +#include <boost/thread/thread.hpp> +#include <usb.h> +#include "usb_read_thread.hpp" + +USBReadThread::USBReadThread(struct usb_dev_handle* handle, int endpoint, int len) : + m_handle(handle), + m_read_endpoint(endpoint), + m_read_length(len), + m_stop(false) +{ +} + +USBReadThread::~USBReadThread() +{ +} + +void +USBReadThread::start_thread() +{ + m_stop = false; + m_thread = boost::thread(boost::bind(&USBReadThread::run, this)); +} + +void +USBReadThread::stop_thread() +{ + m_stop = true; + m_thread.join(); +} + +int +USBReadThread::read(uint8_t* data, int len) +{ + boost::mutex::scoped_lock lock(m_read_buffer_mutex); + + if (m_read_buffer.empty()) + { + return 0; + } + else + { + assert(len == m_read_length); + + Paket& paket = m_read_buffer.front(); + + memcpy(data, paket.data, m_read_length); + delete[] paket.data; + int ret = paket.length; + + m_read_buffer.pop_front(); + + return ret; + } +} + +void +USBReadThread::run() +{ + while(!m_stop) + { + uint8_t* data = new uint8_t[m_read_length]; + + int ret = usb_interrupt_read(m_handle, m_read_endpoint, (char*)data, sizeof(data), 0 /*timeout*/); + + { + boost::mutex::scoped_lock lock(m_read_buffer_mutex); + + Paket paket; + paket.data = data; + paket.length = ret; + + m_read_buffer.push_back(paket); + } + } +} + +/* EOF */ diff --git a/src/usb_read_thread.hpp b/src/usb_read_thread.hpp new file mode 100644 index 0000000..318716a --- /dev/null +++ b/src/usb_read_thread.hpp @@ -0,0 +1,63 @@ +/* +** Windstille - A Sci-Fi Action-Adventure Game +** Copyright (C) 2009 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_USB_READ_THREAD_HPP +#define HEADER_USB_READ_THREAD_HPP + +#include <boost/thread/mutex.hpp> +#include <boost/thread/thread.hpp> +#include <list> + +class USBReadThread +{ +private: + struct usb_dev_handle* m_handle; + const int m_read_endpoint; + const int m_read_length; + + struct Paket { + uint8_t* data; + int length; + }; + + std::list<Paket> m_read_buffer; + boost::mutex m_read_buffer_mutex; + boost::thread m_thread; + + bool m_stop; + +public: + USBReadThread(struct usb_dev_handle* handle, int endpoint, int len); + ~USBReadThread(); + + int read(uint8_t* data, int len); + + void start_thread(); + void stop_thread(); + +private: + void run(); + +private: + USBReadThread(const USBReadThread&); + USBReadThread& operator=(const USBReadThread&); +}; + +#endif + +/* EOF */