Skip to content

Commit 72ae59c

Browse files
committed
Local fixes I never pushed
1 parent ed1f7c0 commit 72ae59c

File tree

8 files changed

+286
-257
lines changed

8 files changed

+286
-257
lines changed

stick/src/connector.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ use lookit::Lookit;
88

99
use crate::{Controller, Remap};
1010

11+
#[cfg(windows)]
12+
mod lookit {
13+
#[derive(Debug)]
14+
pub(crate) struct Lookit {}
15+
}
16+
1117
/// Future that you can `.await` to connect to
1218
/// [`Controller`](crate::Controller)s
1319
#[derive(Debug)]

stick/src/ctlr.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,22 @@ use std::{
1010
use lookit::It;
1111

1212
use crate::{
13-
platform::{connect, platform, PlatformController, Support},
13+
platform::{platform, CtlrId, Support},
1414
Event,
1515
};
1616

17+
#[cfg(windows)]
18+
pub(crate) mod lookit {
19+
#[derive(Debug)]
20+
pub(crate) struct It {}
21+
22+
impl It {
23+
pub fn id(&self) -> u8 {
24+
todo!()
25+
}
26+
}
27+
}
28+
1729
#[repr(i8)]
1830
enum Btn {
1931
Exit = 0,
@@ -271,7 +283,7 @@ pub struct Controller {
271283
// Shared remapping.
272284
remap: Arc<Info>,
273285
//
274-
raw: PlatformController,
286+
raw: CtlrId,
275287
// Button states
276288
btns: u128,
277289
// Number button states
@@ -298,7 +310,7 @@ impl Controller {
298310
let btns = 0;
299311
let nums = 0;
300312
let axis = [0.0; Axs::Count as usize];
301-
let (id, name, raw) = connect(which)?;
313+
let (id, name, raw) = platform().connect(which)?;
302314
let remap = remap.0.get(&id).cloned().unwrap_or_default();
303315
let ready = true;
304316
Some(Self {
@@ -581,7 +593,7 @@ impl Future for Controller {
581593
let mut this = self.as_mut();
582594

583595
if this.ready {
584-
if let Some(event) = platform().event(&mut this.raw) {
596+
if let Poll::Ready(event) = platform().event(&mut this.raw) {
585597
let out = Self::process(&mut *this, event);
586598
return if out.is_pending() {
587599
Self::poll(self, cx)

stick/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ mod platform {
116116

117117
mod platform;
118118

119-
pub(crate) use platform::{connect, platform, PlatformController, Support};
119+
pub(crate) use platform::{platform, CtlrId, Support};
120120
}
121121

122122
mod connector;

stick/src/linux/controller.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ pub(crate) struct Controller {
1717
}
1818

1919
pub(crate) fn connect(it: It) -> Option<(u64, String, Controller)> {
20+
// Some controllers may not have haptic force feedback while others might
21+
// ONLY have haptic force feedback and no controls.
2022
let file = it.file_open() // Try Read & Write first
2123
.or_else(|it| it.file_open_r()) // Then Readonly second
2224
.or_else(|it| it.file_open_w()) // Then Writeonly third

stick/src/platform/platform.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
11
#![allow(unsafe_code)]
22

3-
use lookit::It;
3+
use std::task::{Context, Poll};
4+
5+
use crate::Event;
46

57
// Choose platform driver implementation.
68
#[allow(unused_attributes)]
79
#[cfg_attr(target_os = "linux", path = "../linux/linux.rs")]
10+
#[cfg_attr(target_os = "windows", path = "../windows/windows.rs")]
811
#[path = "unsupported.rs"]
912
mod driver;
1013

11-
// Import the device type from the target platform.
12-
pub(crate) use driver::Controller as PlatformController;
13-
14-
// Single required method for each platform.
15-
pub(crate) fn connect(it: It) -> Option<(u64, String, PlatformController)> {
16-
driver::connect(it)
17-
}
14+
/// Controller ID.
15+
pub(crate) struct CtlrId(u32);
1816

17+
/// Required platform support trait.
1918
pub(crate) trait Support {
19+
/// Window gained focus, start receiving events.
2020
fn enable(self);
21+
/// Window lost focus, stop receiving events.
2122
fn disable(self);
22-
fn rumble(self, controller: &mut PlatformController, left: f32, right: f32);
23-
fn event(self, device: &mut PlatformController) -> Option<crate::Event>;
23+
/// Set left and right rumble value for controller.
24+
fn rumble(self, ctlr: &CtlrId, left: f32, right: f32);
25+
/// Attempt getting a new event from a connected controller.
26+
fn event(self, ctlr: &CtlrId, cx: &mut Context<'_>) -> Poll<Event>;
27+
/// Attempt connecting to a new controller.
28+
fn connect(self, cx: &mut Context<'_>) -> Poll<(u64, String, CtlrId)>;
2429
}
2530

31+
/// Get platform support implementation.
32+
///
33+
/// Each platform must implement this function to work.
2634
pub(crate) fn platform() -> impl Support {
2735
driver::platform()
2836
}

stick/src/windows/controller.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use std::rc::Rc;
2+
use crate::Event;
3+
use winapi::shared::minwindef::DWORD;
4+
use super::XInputHandle;
5+
use crate::ctlr::lookit::It;
6+
7+
pub(crate) struct Controller {
8+
pub(crate) xinput: Rc<XInputHandle>,
9+
pub(crate) device_id: u8,
10+
pub(crate) pending_events: Vec<Event>,
11+
pub(crate) last_packet: DWORD,
12+
}
13+
14+
impl Controller {
15+
#[allow(unused)]
16+
fn new(device_id: u8, xinput: Rc<XInputHandle>) -> Self {
17+
Self {
18+
xinput,
19+
device_id,
20+
pending_events: Vec::new(),
21+
last_packet: 0,
22+
}
23+
}
24+
25+
/// Stereo rumble effect (left is low frequency, right is high frequency).
26+
pub(super) fn rumble(&mut self, left: f32, right: f32) {
27+
self.xinput
28+
.set_state(
29+
self.device_id as u32,
30+
(u16::MAX as f32 * left) as u16,
31+
(u16::MAX as f32 * right) as u16,
32+
)
33+
.unwrap()
34+
}
35+
}
36+
37+
pub(crate) fn connect(it: It) -> Option<(u64, String, Controller)> {
38+
let name = "XInput Controller";
39+
let controller = Controller::new(it.id(), todo!());
40+
Some((0, name.to_string(), controller))
41+
}

stick/src/windows/windows.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use self::controller::Controller;
2+
use self::xinput::XInputHandle;
3+
use super::{CtlrId, Support};
4+
use crate::Event;
5+
use std::mem::MaybeUninit;
6+
use std::sync::Once;
7+
use std::sync::atomic::{AtomicU8, Ordering};
8+
use std::task::{Context, Poll};
9+
use std::rc::Rc;
10+
11+
mod controller;
12+
mod xinput;
13+
14+
static mut PLATFORM: MaybeUninit<Platform> = MaybeUninit::uninit();
15+
static ONCE: Once = Once::new();
16+
static CONNECTED: AtomicU8 = AtomicU8::new(0);
17+
static READY: AtomicU8 = AtomicU8::new(0);
18+
19+
pub(super) struct Platform(Option<Rc<XInputHandle>>);
20+
21+
impl Support for &Platform {
22+
fn enable(self) {
23+
if let Some(ref xinput) = self.0 {
24+
unsafe { (xinput.xinput_enable)(true as _) };
25+
}
26+
}
27+
28+
fn disable(self) {
29+
if let Some(ref xinput) = self.0 {
30+
unsafe { (xinput.xinput_enable)(false as _) };
31+
}
32+
}
33+
34+
fn rumble(self, ctlr: &CtlrId, left: f32, right: f32) {
35+
todo!()
36+
}
37+
38+
fn event(self, ctlr: &CtlrId, cx: &mut Context<'_>) -> Poll<Event> {
39+
todo!()
40+
}
41+
42+
fn connect(self, cx: &mut Context<'_>) -> Poll<(u64, String, CtlrId)> {
43+
// Early return optimization if timeout hasn't passed yet.
44+
// FIXME
45+
46+
// DirectInput only allows for 4 controllers
47+
let connected = CONNECTED.load(Ordering::Relaxed);
48+
for id in 0..4 {
49+
let mask = 1 << id;
50+
let was_connected = (connected & mask) != 0;
51+
if let Some(ref xinput) = self.0 {
52+
if xinput.get_state(id).is_ok() {
53+
CONNECTED.fetch_or(mask, Ordering::Relaxed);
54+
if !was_connected {
55+
// we have a new device!
56+
return Poll::Ready(CtlrId(id));
57+
}
58+
} else {
59+
// set deviceto unplugged
60+
CONNECTED.fetch_and(!mask, Ordering::Relaxed);
61+
}
62+
}
63+
}
64+
65+
xinput::register_wake_timeout(100, cx.waker());
66+
67+
Poll::Pending
68+
}
69+
}
70+
71+
pub(super) fn platform() -> &'static Platform {
72+
ONCE.call_once(|| unsafe {
73+
PLATFORM = MaybeUninit::new(Platform(if let Ok(xinput) = XInputHandle::load_default() {
74+
Some(xinput)
75+
} else {
76+
None
77+
}));
78+
});
79+
80+
unsafe {
81+
PLATFORM.assume_init_ref()
82+
}
83+
}

0 commit comments

Comments
 (0)