1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use crate::Device;
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum StickPosition {
Center = 0,
Up = 1,
UpRight = 2,
Right = 3,
DownRight = 4,
Down = 5,
DownLeft = 6,
Left = 7,
UpLeft = 8,
}
impl Default for StickPosition {
fn default() -> Self {
StickPosition::Center
}
}
impl StickPosition {
pub fn new() -> Self {
StickPosition::default()
}
pub fn from_u8(position: u8) -> Option<Self> {
match position {
0 => Some(StickPosition::Center),
1 => Some(StickPosition::Up),
2 => Some(StickPosition::UpRight),
3 => Some(StickPosition::Right),
4 => Some(StickPosition::DownRight),
5 => Some(StickPosition::Down),
6 => Some(StickPosition::DownLeft),
7 => Some(StickPosition::Left),
8 => Some(StickPosition::UpLeft),
_ => None,
}
}
}
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct State {
pub stick_position: StickPosition,
pub button_1: bool,
pub button_2: bool,
pub button_back: bool,
pub button_menu: bool,
pub button_fuji: bool,
pub roll: u16,
}
impl State {
pub fn from_report(data: &[u8]) -> Self {
assert!(data.len() >= 6);
assert_eq!(data[0], 1);
msg_to_state(&data[1..])
}
}
fn msg_to_state(msg: &[u8]) -> State {
assert_eq!(msg.len(), 5);
State {
stick_position: StickPosition::from_u8(msg[2] >> 4).unwrap_or_default(),
button_1: (msg[1] & 1) == 1,
button_2: ((msg[1] >> 1) & 1) == 1,
button_back: (msg[2] & 1) == 1,
button_menu: ((msg[2] >> 1) & 1) == 1,
button_fuji: ((msg[2] >> 2) & 1) == 1,
roll: u16::from(msg[3]) + (u16::from(msg[4]) << 8),
}
}
pub fn process_input<D>(mut device: D) -> Result<Option<State>, D::Error>
where
D: Device,
{
let mut buf = [0; 6];
buf.fill(0);
let mut has_msg = false;
let mut last_amount = 0;
device.set_blocking(false)?;
let msg = loop {
let amount = device.read(&mut buf)?;
if amount == 0 && !has_msg {
break &buf[0..0];
} else if amount != 0 {
has_msg = true;
last_amount = amount;
continue;
}
let msg = &buf[..last_amount];
break msg;
};
if !msg.is_empty() {
if msg.len() != 5 {
eprintln!(
"Special report #{:02X}: {:?}",
buf[0],
msg,
);
Ok(None)
} else {
Ok(Some(msg_to_state(msg)))
}
} else {
Ok(None)
}
}