diff --git a/SConstruct b/SConstruct index 695cdac..2e538c5 100644 --- a/SConstruct +++ b/SConstruct @@ -6,6 +6,7 @@ env.Program("inputdrv", ["inputdrv.cpp", "xbox360_driver.cpp", "control.cpp", + "uinput_driver.cpp", "toggle_button.cpp"], LIBS=['boost_signals', 'usb']) diff --git a/inputdrv.cpp b/inputdrv.cpp index 821ff5a..9b48621 100644 --- a/inputdrv.cpp +++ b/inputdrv.cpp @@ -61,10 +61,10 @@ int main() toggle_out->connect(xbox360.get_btn_port_in(0)); - xbox360.get_abs_port_out(Xbox360Driver::XBOX360_AXIS_Y1) + xbox360.get_abs_port_out(Xbox360Driver::XBOX360_AXIS_LT) ->connect(xbox360.get_abs_port_in(Xbox360Driver::ABS_PORT_IN_RUMBLE_L)); - xbox360.get_abs_port_out(Xbox360Driver::XBOX360_AXIS_Y2) + xbox360.get_abs_port_out(Xbox360Driver::XBOX360_AXIS_RT) ->connect(xbox360.get_abs_port_in(Xbox360Driver::ABS_PORT_IN_RUMBLE_R)); xbox360.get_btn_port_out(Xbox360Driver::XBOX360_BTN_B)->connect(btn_change); diff --git a/uinput.cpp b/uinput.cpp index 150e698..28483a1 100644 --- a/uinput.cpp +++ b/uinput.cpp @@ -82,7 +82,7 @@ void uInput::setup_xbox360_gamepad(GamepadType type) { ioctl(fd, UI_SET_EVBIT, EV_ABS); - ioctl(fd, UI_SET_EVBIT, EV_KEY); + ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_ABSBIT, ABS_X); ioctl(fd, UI_SET_ABSBIT, ABS_Y); diff --git a/uinput_driver.cpp b/uinput_driver.cpp new file mode 100644 index 0000000..a40d716 --- /dev/null +++ b/uinput_driver.cpp @@ -0,0 +1,136 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 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 2 +** 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, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +** 02111-1307, USA. +*/ + +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <linux/uinput.h> +#include <boost/bind.hpp> +#include "uinput_driver.hpp" + +UInputDriver::UInputDriver() + : abs_bit(false), + key_bit(false), + fd(-1) +{ + memset(&user_dev, 0, sizeof(user_dev)); + + // Open the input device + char* uinput_filename[] = { "/dev/input/uinput", "/dev/uinput", "/dev/misc/uinput" }; + const int uinput_filename_count = (sizeof(uinput_filename)/sizeof(char*)); + + for (int i = 0; i < uinput_filename_count; ++i) + { + if ((fd = open(uinput_filename[i], O_WRONLY | O_NDELAY)) >= 0) + { + break; + } + else + { + std::cout << "Error: " << uinput_filename[i] << ": " << strerror(errno) << std::endl; + } + } + + if (fd < 0) + { + std::cout << "Error: No stuitable uinput device found" << std::endl; + std::cout << "" << std::endl; + std::cout << "Troubleshooting:" << std::endl; + std::cout << " * make sure uinput kernel module is loaded " << std::endl; + std::cout << " * make sure joydev kernel module is loaded " << std::endl; + std::cout << " * make sure you have permissions to access the uinput device" << std::endl; + std::cout << " * start the driver with ./xboxdrv -v --no-uinput to see if the driver itself works" << std::endl; + std::cout << "" << std::endl; + exit(EXIT_FAILURE); + } +} + +void +UInputDriver::add_abs(uint16_t code, int min, int max) +{ + if (!abs_bit) + { + ioctl(fd, UI_SET_EVBIT, EV_ABS); + abs_bit = true; + } + + ioctl(fd, UI_SET_ABSBIT, code); + + user_dev.absmin[code] = min; + user_dev.absmax[code] = max; + + + abs_port_in.push_back(new AbsPortIn("UInput", min, max, + boost::bind(&UInputDriver::on_abs, this, _1, code))); +} + +void +UInputDriver::on_btn(BtnPortOut* port, uint16_t code) +{ + struct input_event ev; + memset(&ev, 0, sizeof(ev)); + + gettimeofday(&ev.time, NULL); + ev.type = EV_KEY; + ev.code = code; + ev.value = port->get_state(); + + write(fd, &ev, sizeof(ev)); +} + +void +UInputDriver::on_abs(AbsPortOut* port, uint16_t code) +{ + struct input_event ev; + memset(&ev, 0, sizeof(ev)); + + gettimeofday(&ev.time, NULL); + ev.type = EV_ABS; + ev.code = code; + ev.value = port->get_state(); + + write(fd, &ev, sizeof(ev)); +} + +void +UInputDriver::add_btn(uint16_t code) +{ + if (!key_bit) + { + ioctl(fd, UI_SET_EVBIT, EV_KEY); + key_bit = true; + } + + ioctl(fd, UI_SET_KEYBIT, code); +} + +void +UInputDriver::finish() +{ + write(fd, &user_dev, sizeof(user_dev)); +} + +/* EOF */ diff --git a/uinput_driver.hpp b/uinput_driver.hpp new file mode 100644 index 0000000..26b2a2a --- /dev/null +++ b/uinput_driver.hpp @@ -0,0 +1,57 @@ +/* $Id$ +** __ __ __ ___ __ __ __ __ +** / \ / \__| ____ __| _/_______/ |_|__| | | | ____ +** \ \/\/ / |/ \ / __ |/ ___/\ __\ | | | | _/ __ \ +** \ /| | | \/ /_/ |\___ \ | | | | |_| |_\ ___/ +** \__/\ / |__|___| /\____ /____ > |__| |__|____/____/\___ > +** \/ \/ \/ \/ \/ +** Copyright (C) 2007 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 2 +** 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, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +** 02111-1307, USA. +*/ + +#ifndef HEADER_UINPUT_DRIVER_HPP +#define HEADER_UINPUT_DRIVER_HPP + +#include <linux/uinput.h> +#include "control.hpp" + +/** */ +class UInputDriver : public Control +{ +private: + uinput_user_dev user_dev; + bool abs_bit; + bool key_bit; + int fd; + +public: + UInputDriver(); + + void add_abs(uint16_t code, int min, int max); + void add_btn(uint16_t code); + void finish(); + + void on_abs(AbsPortOut* port, uint16_t code); + void on_btn(BtnPortOut* port, uint16_t code); +private: + UInputDriver (const UInputDriver&); + UInputDriver& operator= (const UInputDriver&); +}; + +#endif + +/* EOF */