diff --git a/run/usb_gamepad_input.run b/run/usb_gamepad_input.run index b52f671..a5cb3a5 100644 --- a/run/usb_gamepad_input.run +++ b/run/usb_gamepad_input.run @@ -49,6 +49,7 @@ set config { + } @@ -116,10 +117,8 @@ append config { - - - + } diff --git a/src/drivers/usb_gamepad_input/gravis_gamepadpro.h b/src/drivers/usb_gamepad_input/gravis_gamepadpro.h new file mode 100644 index 0000000..4e0033d --- /dev/null +++ b/src/drivers/usb_gamepad_input/gravis_gamepadpro.h @@ -0,0 +1,129 @@ +/* + * \brief Gravis Gamepad Pro USB + * \author Emery Hemingway + * \date 2017-11-12 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _GRAVIS_GAMEPADPRO_H_ +#define _GRAVIS_GAMEPADPRO_H_ + +/* Genode includes */ +#include + +/* local includes */ +#include + + +struct Gravis_gamepadpro : Hid_device +{ + /* + * Supported devices + */ + struct { + uint16_t vendor_id; + uint16_t product_id; + } devices[1] = { + {0x0428, 0x4001} + }; + + enum { B_NUM = 8 }; + Input::Keycode butt_map[B_NUM] = { + Input::Keycode::BTN_Y, /* 0x01 Red */ + Input::Keycode::BTN_B, /* 0x02 Yellow */ + Input::Keycode::BTN_A, /* 0x04 Green */ + Input::Keycode::BTN_X, /* 0x08 Blue */ + Input::Keycode::BTN_TL, /* 0x10 */ + Input::Keycode::BTN_TR, /* 0x20 */ + Input::Keycode::BTN_TL2, /* 0x40 */ + Input::Keycode::BTN_TR2, /* 0x80 */ + }; + + Input::Keycode ss_map[2] = { + Input::Keycode::BTN_SELECT, /* 0x01 */ + Input::Keycode::BTN_START, /* 0x02 */ + }; + + enum { + IFACE_NUM = 0, + ALT_NUM = 0, + EP_NUM = 0, + + DATA_LENGTH = 4, + }; + + uint8_t old_data[DATA_LENGTH] = { }; + + Gravis_gamepadpro(Input::Session_component &input_session) + : Hid_device(input_session, "Gravis Gamepad Pro") { } + + /************************** + ** HID device interface ** + **************************/ + + bool probe(uint16_t vendor_id, uint16_t product_id) const override + { + for (size_t i = 0; i < sizeof(devices)/sizeof(devices[0]); i++) { + if ( vendor_id == devices[i].vendor_id + && product_id == devices[i].product_id) { + return true; + } + } + return false; + } + + void parse(uint8_t const *new_data, size_t len) override + { + using namespace Genode; + + if (len < DATA_LENGTH) return; + + /* submit D-pad events */ + { + uint8_t const xo = old_data[0]; + uint8_t const yo = old_data[1]; + uint8_t const xn = new_data[0]; + uint8_t const yn = new_data[1]; + + if (xo != xn) { + Input::Event ev( + xn == 0x7f ? Input::Event::RELEASE : Input::Event::PRESS, + (xn & xo) ? Input::Keycode::BTN_RIGHT : Input::Keycode::BTN_LEFT, + 0, 0, 0, 0); + input_session.submit(ev); + } + if (yo != yn) { + Input::Event ev( + yn == 0x7f ? Input::Event::RELEASE : Input::Event::PRESS, + (yn & yo) ? Input::Keycode::BTN_BACK : Input::Keycode::BTN_FORWARD, + 0, 0, 0, 0); + input_session.submit(ev); + } + } + + /* submit button events */ + Utils::check_buttons( + input_session, old_data[2], new_data[2], B_NUM, butt_map); + + /* Submit start/select events */ + Utils::check_buttons( + input_session, old_data[3], new_data[3], 2, ss_map); + + /* save for next poll */ + Genode::memcpy(old_data, new_data, DATA_LENGTH); + + /* Simple! And it was only $1.99! */ + } + + uint8_t iface() const { return IFACE_NUM; } + uint8_t ep() const { return EP_NUM; } + uint8_t alt() const { return ALT_NUM; } +}; + +#endif /* _GRAVIS_GAMEPADPRO_H_ */ diff --git a/src/drivers/usb_gamepad_input/main.cc b/src/drivers/usb_gamepad_input/main.cc index dcf81f5..eb97e04 100644 --- a/src/drivers/usb_gamepad_input/main.cc +++ b/src/drivers/usb_gamepad_input/main.cc @@ -38,6 +38,7 @@ #include #include #include +#include static bool const verbose_intr = false; @@ -77,8 +78,9 @@ struct Usb::Hid Retrolink_n64 retrolink_n64 { input_session }; Sony_ds3 sony_ds3 { input_session }; Sony_ds4 sony_ds4 { input_session }; + Gravis_gamepadpro gravis_gamepadpro { input_session }; - enum { MAX_DEVICES = 8, }; + enum { MAX_DEVICES = 9, }; Hid_device *devices[MAX_DEVICES] { &generic, &buffalo_snes, @@ -88,6 +90,7 @@ struct Usb::Hid &xboxone, &sony_ds3, &sony_ds4, + &gravis_gamepadpro }; Hid_device *device = &generic; @@ -541,7 +544,7 @@ struct Usb::Main Env &env; Heap heap { env.ram(), env.rm() }; - Input::Session_component input_session; + Input::Session_component input_session { env, env.pd() }; Static_root input_root { env.ep().manage(input_session) }; Usb::Hid hid { env, heap, input_session };