GithubHelp home page GithubHelp logo

ardaku / stick Goto Github PK

View Code? Open in Web Editor NEW
73.0 4.0 14.0 1.06 MB

Rust library for platform-agnostic asynchronous gamepad, joystick, and flightstick interaction

Home Page: https://crates.io/crates/stick

License: Apache License 2.0

Rust 100.00%
joystick rust controller joysticks gamepad flight-controller joystick-library

stick's Introduction

Stick

Folders in this repository:

  • stick/: The Stick crate.
  • sdb/: The Stick Public Domain database of controllers (not limited to game controllers).
  • gcdb/: Git Submodule to grab optional SDL mappings from.
  • xtask/: Scripts run with cargo-xtask.

Xtask

Stick uses the xtask repository model to have various scripts written in Rust process controller data, also allowing serde to not be a direct dependency.

Available Commands

  • cargo xtask, cargo xtask --help - Print help
  • cargo xtask sdb - Generate the embeddable bytecode databases.

TOML Format

File names are 64-bit hexadecimal values with leading zeros followed by .toml within a folder referring to the platform.

name = "My Controller Name"
type = "xbox"

[remap]
TriggerR = {} # Ignore events
TriggerL = {}
HatUp = "Up" # Map hat to dpad when you're not using a flightstick
HatDown = "Down"
HatLeft = "Left"
HatRight = "Right"
CamX = { event = "CamX", deadzone = 0.075 } # Adjust deadzones
CamY = { event = "CamY", deadzone = 0.075 }
JoyZ = { event = "TriggerR", max = 1024 } # Set higher-precision axis ranges (usually 255)
CamZ = { event = "TriggerL", max = 1024 }

type

Type can be any of the following:

  • xbox - An Xbox Gamepad (W3 Standard Gamepad Compliant)
  • flight - A Flightstick
  • playstation - A PlayStation Gamepad (W3 Standard Gamepad Compliant)
  • nintendo - A Nintendo Gamepad (W3 Standard Gamepad Compliant)
  • gamepad - A generic Gamepad (W3 Standard Gamepad Compliant)

License

Copyright © 2017-2023 The Stick Contributors.

Licensed under any of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed as described above, without any additional terms or conditions.

Help

If you want help using or contributing to this library, feel free to send me an email at [email protected].

stick's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

stick's Issues

small mapping issues for the xbox one controller in 0.12.1

Current Mapping
Left Bumper mapped as ActionH
Right Bumper mapped as ActionD
MenuL mapped as BumperL
MenuR mapped as BumperR
Left Trigger mapped as JoyZ
Right Trigger mapped as CamZ
X Button mapped as ActionC
Y Button mapped as ActionV
Xbox Button (big one in the middle) unmapped Unmapped Linux Button 139

Desktop (please complete the following information):

  • OS: Linux

Reduce Bloat In Resulting Executable

Currently, stick generates a lot of code. I think making the database included as in a binary format would decrease the size of the executable, compared to including complex control flow.

Clean Up / Transform The Database

In the TOML files in ./pad_db/pad/mapping, it looks like

name = "Joystick Name"
type = "Unknown"

[[button]]
code = 2
event = "ActionA"

[[button]]
code = 0
# ...

Tasks

  • Names should be consistent PS, PlayStation, Playstation, Play Station => PlayStation; GC, GameCube, Gamecube, Game Cube => GameCube
  • Types should not be "UNKNOWN", except for xxxxxxxxxxxxxxxx.toml, they should be things like FLIGHT, GAMECUBE, NES, XBOX, WII
  • Types should be all caps, no underscores, spaces or any other separators
  • Button entries should be sorted by code, smallest to largest
  • Axes entries should be sorted by code, smallest to largest
  • Three-way entries should be sorted by code, smallest to largest
  • Trigger entries should be sorted by code, smallest to largest

Some of these tasks may be done using scripts, but I will only include the scripts in the repository if it's written in Rust or Python. Other tasks will need to be done manually. There is now a script in Rust in the repository. The remaining tasks don't need a script.

Allow running `cargo xtask sdb` to take an additional argument for custom database.

Is your feature request related to a problem? Please describe.
Some people have expressed interest in wanting to create mappings without committing them to this repository.

Describe the solution you'd like
They should be able to build a TOML file and use cargo xtask sdb /path/to/my/database to generate the bytecode file.

Describe alternatives you've considered
A GUI could do this automatically.

Additional context
TODO: Add any other context or screenshots about the feature request here.

Listener returns hot-plugged devices twice

I am running under Linux, and if I plug in a controller while my program is running, Listener returns the Controller twice. If the controller is plugged in before the program starts, I only get the Controller once. There appears to be nothing in the structure returned that will allow me to de-duplicate the Controller instances. Both of them fire the same events, and I only have one such controller plugged in so, both structures represent the same exact device.

I am using stick 0.13.0 with pasts 0.14.3.

Nintendo Joycon gyro/accelerometer support

Thanks for creating this library!
Is there a way to access gyroscope and accelerometer data from Joycons currently? On Ubuntu 20.04 with the dkms-hid-nintendo, there are two input sources I can see:

/dev/input/js0
/dev/input/js1

js0 corresponds to buttons/analog stick and that works fine in stick. The gyro and accelerometer readings seem to be a part of js1. Is there a way I can use the "second" controller via stick?

I'm using the haptics example to test

Call for Participation - Test More Joysticks On Linux

I don't have all the possible game controllers that exist out there, and I can't afford to buy them all. So if you have one and feel like contributing, then try it out with the simple readme example in the repository (cargo run --example readme), and make sure all the buttons return an Event, and that the each axis goes from -1 to 1 if it rests at 0 - joysticks (if it only goes one direction it goes positive - L & R triggers). I also want to make sure each controller has the correct mapping of buttons (ActionA shouldn't be mapped to the B button, and ActionV should always be the top button of an ABXY style layout - always either X, Y, or Triangle).

For more advanced contributions, looking at how Firefox maps joysticks for the w3c gamepad API might be helpful, as the stick API is based on that. There might also be something similar in the SDL source code.

You can either report back by leaving a comment with all of the unknown button and axis ids, or you can make your own mapping file in the database at ./pad_db/pad/mapping/JOYSTICK_ID.toml and file a Pull Request:

name = "Name from the packaging or descriptive name (Don't abbreviate PlayStation PS)"
type = "PLAYSTATION" # or whatever other type of controller

[[button]]
code = 0
event = "ActionV" # Triangle Button

[[wheel]] # unusual event type, usually won't have to include
code = 0
event = "WheelX"

[[axis]]
code = 0
event = "JoyX"
max = 0.92 # OPTIONAL: divide axis by some number (usually not needed)

[[three_way]]
code = 1
neg = "DpadLeft"
pos = "DpadRight"

[[trigger]] # An unsigned axis from 0 to 255
code = 2
event = "TriggerL"
max = 0.25 # OPTIONAL: divide axis by some number (usually not needed)

If your gamepad/joystick already works plug-and-play there's no need to comment.

Thrustmaster Warthog support

Describe the bug
Ran the example code provided on the docs' homepage, and plugged my Warthog into the machine.

Connected p1, id: 44F0404, name: Thrustmaster Throttle - HOTAS Warthog
[/home/orion/.cargo/registry/src/github.com-1ecc6299db9ec823/stick-0.9.0/src/ffi/linux.rs:560] id = 422
Button 422 is Unknown, report at https://github.com/libcala/stick/issues
[/home/orion/.cargo/registry/src/github.com-1ecc6299db9ec823/stick-0.9.0/src/ffi/linux.rs:560] id = 422
Button 422 is Unknown, report at https://github.com/libcala/stick/issues
^C

The above spams the STDOUT.

To Reproduce
Steps to reproduce the behavior:

  1. cargo init rustpad
  2. cd rustpad
  3. cargo add stick pasts
  4. copy example program into src/main.rs
  5. cargo run
    Expected behavior

Expected Connected p1, id: 44F0404, name: Thrustmaster Throttle - HOTAS Warthog
and for the program to read joystick events, not spew errors over STDOUT.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

   Compiling smelling_salts v0.1.0
   Compiling pasts v0.4.0
   Compiling stick v0.9.0
   Compiling rustpad v0.1.0 (/home/orion/projects/skool/rover/movement/rustpad/rustpad)

thread 'main' panicked at 'assertion failed: `(left != right)` while running example on Linux

I am on Linux Mint and i tried to run the example code, however i gave me an error saying:

thread 'main' panicked at 'assertion failed: `(left != right)`
  left: `-1`,
 right: `-1`', stick/src/raw/linux.rs:569:9

I also run with back trace and i gave me this:

stack backtrace:
   0: rust_begin_unwind
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/std/src/panicking.rs:498:5
   1: core::panicking::panic_fmt
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/panicking.rs:107:14
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/panicking.rs:145:5
   4: stick::raw::ffi::Controller::new
             at ./stick/src/raw/linux.rs:569:9
   5: stick::raw::ffi::Listener::controller
             at ./stick/src/raw/linux.rs:748:30
   6: <stick::raw::ffi::Listener as stick::raw::Listener>::poll
             at ./stick/src/raw/linux.rs:765:21
   7: <stick::listener::Listener as core::future::future::Future>::poll
             at ./stick/src/listener.rs:45:9
   8: <pasts::race::Event<F,G,V,S,T,Z> as core::future::future::Future>::poll
             at /home/victorrandall/.cargo/registry/src/github.com-1ecc6299db9ec823/pasts-0.8.0/src/race.rs:121:13
   9: <pasts::race::EventSlice<F,G,V,S,T,Z> as core::future::future::Future>::poll
             at /home/victorrandall/.cargo/registry/src/github.com-1ecc6299db9ec823/pasts-0.8.0/src/race.rs:68:38
  10: <pasts::race::Loop<S,T,F> as core::future::future::Future>::poll
             at /home/victorrandall/.cargo/registry/src/github.com-1ecc6299db9ec823/pasts-0.8.0/src/race.rs:202:41
  11: haptic::event_loop::{{closure}}
             at ./stick/examples/haptic.rs:62:21
  12: <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/future/mod.rs:80:19
  13: <core::pin::Pin<P> as core::future::future::Future>::poll
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/future/future.rs:119:9
  14: pasts::exec::Executor::block_on_pinned
             at /home/victorrandall/.cargo/registry/src/github.com-1ecc6299db9ec823/pasts-0.8.0/src/exec.rs:79:54
  15: pasts::exec::Executor::block_on
             at /home/victorrandall/.cargo/registry/src/github.com-1ecc6299db9ec823/pasts-0.8.0/src/exec.rs:100:9
  16: pasts::exec::block_on
             at /home/victorrandall/.cargo/registry/src/github.com-1ecc6299db9ec823/pasts-0.8.0/src/exec.rs:144:5
  17: haptic::main
             at ./stick/examples/haptic.rs:71:5
  18: core::ops::function::FnOnce::call_once
             at /rustc/db9d1b20bba1968c1ec1fc49616d4742c1725b4b/library/core/src/ops/function.rs:227:5

Windows crash: 0xc0000005 (STATUS_ACCESS_VIOLATION)

Describe the bug
The haptic example causes the application to crash with 0xc0000005 (STATUS_ACCESS_VIOLATION) after event_loop is completed.

To Reproduce
Steps to reproduce the behavior:

  1. Setup the haptic example
  2. Change main to the following:
fn main() {
    pasts::block_on(event_loop());

    loop {
        println!("hello world");
        std::thread::sleep(std::time::Duration::from_millis(500));
    }
}
  1. cargo run and then trigger the MenuR event on a connected controller.
  2. Should crash almost immediately.

Expected behavior
No crash. It should print "hello world" forever after triggering MenuR.

Desktop:

  • OS: Windows 10 (10.0.19045 Build 19045)
  • Stick version: v0.12.4

Raw HID Support On Linux

There should be a way to read raw controller events on Linux from /dev/usb/ which can be reused for Fuchsia mappings. Unfortunately, this can't be the default way to connect to a joystick on Linux because of permission issues. Hopefully these mappings can also be re-used for Windows and MacOS.

edit: Maybe at some point if making a Flatpak that deals with the input access permissions is simple enough, it could be worth it to just support the one set of mappings.

Improve Build Times

Currently serde increases the compile time of this crate by a lot due to proc macros. Look into using a non-proc macro alternative.

Implement Another API For Windows

Is your feature request related to a problem? Please describe.
Currently, the Windows port of stick depends on xinput - this does not include other controllers that do not conform to the w3 standard gamepad such as flightsticks.

Describe the solution you'd like
Have an alternative way to connect controllers on Windows.

Describe alternatives you've considered
I currently believe a different API has to be implemented to support these controllers.

Additional context

Help needed: how to use stick in tokio?

Hi!
I want one thread to read stick events, another one to pick up the latest read event and send it off on a network socket. For networking purposes I'm using tokio, not pasts crate.

The issue is, I can't spawn a task with tokio as Controller has an Rc inside and rust is unhappy about it not being Send.

Here's the gist of the code:

let mut state = State::new(...);
let mut controller = get_ctl().await;
tokio::spawn(async move {  // => error here => future created by async block is not `Send`
    loop {
        let event = (&mut controller).await; // => also error => has type `Controller` which is not `Send`
        state.event(event);
    }
});

(Please forgive any stupid usage of rust / tokio / stick / async, I'm a newbie to both rust and async!)

Can you please guide me on how to achieve this? how should I send a controller through an async task? does this require fundamental changes to stick to use Arc?

examples/haptic.rs dosent run correctly

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behaviour:
copy 'examples/haptic.rs' into main.rs
compile,
run

Expected behaviour
should feel a rumble after running the program, however, I get no response.

Desktop (please complete the following information):

  • OS: Raspian (Linux)

Update Copyright Information

Move copyright dates into readme and update, and refer to collective contributors rather than individuals.

Makes maintaining this kind of thing so much easier, and will match recent changes in other ardaku crates.

Ability to poll raw controller input axis values

Is your feature request related to a problem? Please describe.
In addition to being able to poll the Events with a given axis to return a normalized f64, this would allow the raw i32 input to be read (on linux at least).

Describe the solution you'd like
Adding an enum such as RawEvent that is in the raw dir, or similar.

Describe alternatives you've considered
An alternative is to remap the floats back into i32s, but the conversion back and forth makes the casting lossy

Compile errors trying to build stick

I tried to include stick in my project, but I get errors, and they don't seem easy to fix.

Compiling stick v0.7.0
Compiling json v0.11.13
error[E0308]: mismatched types
--> /data/pavel/.cargo/registry/src/github.com-1ecc6299db9ec823/stick-0.7.0/src/devices.rs:249:24
|
249 | let old: [u8; 8] = float.load(Ordering::Relaxed).to_ne_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 8 elements, found one with 4 elements
|
= note: expected type [u8; 8]
found type [u8; 4]

error[E0308]: mismatched types
--> /data/pavel/.cargo/registry/src/github.com-1ecc6299db9ec823/stick-0.7.0/src/devices.rs:253:43
|
253 | let new: usize = usize::from_ne_bytes([new[0], new[1], new[2], new[3], 0, 0, 0, 0]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 4 elements, found one with 8 elements
|
= note: expected type [u8; 4]
found type [u8; 8]

error[E0308]: mismatched types
--> /data/pavel/.cargo/registry/src/github.com-1ecc6299db9ec823/stick-0.7.0/src/devices.rs:260:24
|
260 | let rtn: [u8; 8] = float.load(Ordering::Relaxed).to_ne_bytes();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a fixed size of 8 elements, found one with 4 elements
|
= note: expected type [u8; 8]
found type [u8; 4]

error: aborting due to 3 previous errors

For more information about this error, try rustc --explain E0308.

Unknown Linux Button 319

Describe the bug
When pressing M1 on a Flydigi Apex 2, it's not recognized by stick and an error is output. Error message as following:

  Unknown Linux Button 319
  Report at https://github.com/libcala/stick/issues

To Reproduce

Steps to reproduce the behavior:

  1. Use a Flydigi Apex 2. Other devices might work as well.
  2. Press M1, located on the inside of the right grip.
  3. Observe error message.

Expected behavior
Similar behavior as other buttons:

  p2: Number(15) Pushed
  p2: Number(15) Released

Desktop:

    ❯ lsb_release -a
    No LSB modules are available.
    Distributor ID: Pop
    Description:    Pop!_OS 21.04
    Release:        21.04
    Codename:       hirsute

Additional context
I assume Stick currently supports 16 buttons, numbered 0-15, although I haven't looked yet. I'm just reporting 'cause the program told me to.

Looking at the source code, I see where my button is supposed to go.

        0x130 /* BTN_A / BTN_SOUTH */ => Event::ActionA(pushed),
        0x131 /* BTN_B / BTN_EAST */ => Event::ActionB(pushed),
        0x132 /* BTN_C */ => Event::ActionC(pushed),
        0x133 /* BTN_X / BTN_NORTH */ => Event::ActionV(pushed),
        0x134 /* BTN_Y / BTN_WEST */ => Event::ActionH(pushed),
        0x135 /* BTN_Z */ => Event::ActionD(pushed),
        0x136 /* BTN_TL */ => Event::BumperL(pushed),
        0x137 /* BTN_TR */ => Event::BumperR(pushed),
        0x138 /* BTN_TL2 */ => Event::TriggerL(f64::from(u8::from(pushed)) * 255.0),
        0x139 /* BTN_TR2 */ => Event::TriggerR(f64::from(u8::from(pushed)) * 255.0),
        0x13A /* BTN_SELECT */ => Event::MenuL(pushed),
        0x13B /* BTN_START */ => Event::MenuR(pushed),
        0x13C /* BTN_MODE */ => Event::Exit(pushed),
        0x13D /* BTN_THUMBL */ => Event::Joy(pushed),
        0x13E /* BTN_THUMBR */ => Event::Cam(pushed),
        // <-- Right here, 0x13F

        0x220 /* BTN_DPAD_UP */ => Event::Up(pushed),
        0x221 /* BTN_DPAD_DOWN */ => Event::Down(pushed),
 	0x222 /* BTN_DPAD_LEFT */ => Event::Left(pushed),
 	0x223 /* BTN_DPAD_RIGHT */ => Event::Right(pushed),

0x13F, along with all the other specific named buttons. I'd add it myself but I don't understand the naming scheme used. What makes X and Y into V and H? The other buttons underneath my pad show up as numbers 11-13 so they're no help as a reference. Obviously adhering to a specific chinese novelty controller isn't of the highest priority, but given it's intended position in the code this button 0x13F needs a name and I don't know what.

Update the example

The example uses an out-of-date version of the pasts crate, please update it.

Panic error from Stick 0.11.1 if controller is connected via bluetooth.

Describe the bug
Getting thread 'main' panicked at 'Couldn't create inotify (2)!', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/stick-0.11.1/src/ffi/linux.rs:664:13 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
when running example code on raspian.

To Reproduce
Steps to reproduce the behaviour:

  1. Download example code
  2. compile for RPI0
  3. connect Xbox one controller over Bluetooth.
  4. execute on RPI0
  5. See error

Expected behavior
Example code to run as expected

Screenshots
over bluetooth:
image
wired:
image
(application hangs here and no longer responds. see: this )

Desktop (please complete the following information):

  • Device: RPI0
  • OS: Raspian (ARM)

Unknown Linux Button 158

Describe the bug
looks like the screenshare button on the box one controller isn't mapped.

To Reproduce
Steps to reproduce the behavior:

  1. connect xbox one controller
  2. start software
  3. press snapshot button (bottom left of the box logo)
  4. unknown linux button error

image

Expected behavior
should be mapped as MenuL

Screenshots
image

Desktop (please complete the following information):

  • OS: Linux

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.