joycon_rs/lib.rs
1#![doc(html_favicon_url = "https://raw.githubusercontent.com/KaiseiYokoyama/joycon-rs/master/images/favicon.ico")]
2#![doc(html_logo_url = "https://raw.githubusercontent.com/KaiseiYokoyama/joycon-rs/master/images/logo.png")]
3//! # Joycon-rs Library Documentation
4//!
5//! Hello, and welcome to joycon-rs documentation.
6//!
7//! Joycon-rs is a framework for dealing with Nintendo Switch Joy-Con on Rust easily and efficiently.
8//! In a way, this library is a wrapper of [`hidapi-rs`].
9//! This is a free and open source library, the source code is available for download on [Github].
10//!
11//! Joycon-rs is in development and is still incomplete.
12//! Please be aware that the update will include breaking changes for the time being. Pardon out dust!
13//!
14//! # Usage
15//! First, add dependency to `Cargo.toml`
16//!
17//! ```toml
18//! [dependencies]
19//! joycon_rs = "*"
20//! ```
21//!
22//! Then, `use` prelude on `.rs` file.
23//! ```
24//! use joycon_rs::prelude::*;
25//! ```
26//!
27//! Perfect! Now you have Joycon-rs available in code.
28//!
29//! ### Receive reports
30//! For starters, let's take a simple signal from JoyCon.
31//! If you have more than one JoyCon, [`mspc`] can be very helpful.
32//!
33//! ```no_run
34//! use joycon_rs::prelude::*;
35//!
36//! let (tx, rx) = std::sync::mpsc::channel();
37//! let _output = std::thread::spawn( move || {
38//! while let Ok(update) = rx.recv() {
39//! dbg!(update);
40//! }
41//! });
42//!
43//! let manager = JoyConManager::get_instance();
44//!
45//! let devices = {
46//! let lock = manager.lock();
47//! match lock {
48//! Ok(manager) => manager.new_devices(),
49//! Err(_) => return,
50//! }
51//! };
52//!
53//! devices.iter()
54//! .flat_map(|dev| SimpleJoyConDriver::new(&dev))
55//! .try_for_each::<_, JoyConResult<()>>(|driver| {
56//! // Change JoyCon to Simple hid mode.
57//! let simple_hid_mode = SimpleHIDMode::new(driver)?;
58//!
59//! let tx = tx.clone();
60//!
61//! // Spawn thread
62//! std::thread::spawn( move || {
63//! loop {
64//! // Forward the report to the main thread
65//! tx.send(simple_hid_mode.read_input_report()).unwrap();
66//! }
67//! });
68//!
69//! Ok(())
70//! })
71//! .unwrap();
72//! ```
73//!
74//! ### Set player lights
75//! Then, lets deal with player lights.
76//!
77//! ```no_run
78//! use joycon_rs::prelude::{*, lights::*};
79//! use joycon_rs::joycon::input_report_mode::StandardInputReport;
80//! use joycon_rs::joycon::input_report_mode::sub_command_mode::SubCommandReport;
81//!
82//! let (tx, rx) =
83//! std::sync::mpsc::channel::<JoyConResult<SubCommandReply<StandardInputReport<SubCommandReport<LightsStatus>>>>>();
84//!
85//! // Receive status of player lights
86//! std::thread::spawn(move ||{
87//! while let Ok(Ok(SubCommandReply::Checked(light_status))) = rx.recv() {
88//! assert_eq!(
89//! light_status.extra.reply,
90//! LightsStatus {
91//! light_up: vec![LightUp::LED1, LightUp::LED3],
92//! flash: vec![Flash::LED0, Flash::LED2],
93//! }
94//! )
95//! }
96//! });
97//!
98//! let manager = JoyConManager::get_instance();
99//!
100//! let devices = {
101//! let lock = manager.lock();
102//! match lock {
103//! Ok(manager) => manager.new_devices(),
104//! Err(_) => return,
105//! }
106//! };
107//!
108//! devices.iter()
109//! .flat_map(|dev| SimpleJoyConDriver::new(&dev))
110//! .try_for_each::<_, JoyConResult<()>>(|mut driver| {
111//! // Set player lights
112//! // [SL BUTTON] πΈπ‘πΈπ‘ [SR BUTTON]
113//! driver.set_player_lights(&vec![LightUp::LED1, LightUp::LED3], &vec![Flash::LED0, Flash::LED2]).unwrap();
114//! tx.send(driver.get_player_lights()).unwrap();
115//! Ok(())
116//! })
117//! .unwrap();
118//! ```
119//!
120//! # Features
121//! You can use `Joycon-rs` for...
122//! - Manage Joy-Cons
123//! - Connection / Disconnection / Reconnection
124//! - [Send] / [Receive] raw packets (u8 array) to / from Joy-Con
125//! - [Receive input to Joy-Con][input_report_mode]
126//! - [Receive pushed buttons, and stick directions (one of 8 directions) on every button pressed.][SimpleHIDMode<D>]
127//! - [Receive pushed buttons, stick directions (analog value), and 6-Axis sensor at 60Hz.][StandardFullMode<D>]
128//! - [Get status of Joy-Con][SubCommandMode<D, RD>]
129//! - [Deal with LED (Player lights)]
130//! - [Vibration (Rumble)]
131//!
132//! ## Planning
133//! - Receive NFC/IR data
134//! - Deal with HOME light
135//!
136//! [Github]: https://github.com/KaiseiYokoyama/joycon-rs
137//! [`hidapi-rs`]: https://github.com/ruabmbua/hidapi-rs
138//! [`mspc`]: https://doc.rust-lang.org/book/ch16-02-message-passing.html
139//! [Send]: joycon/trait.JoyConDriver.html#tymethod.write
140//! [Receive]: joycon/trait.JoyConDriver.html#tymethod.read
141//! [input_report_mode]: joycon/input_report_mode/index.html
142//! [SimpleHIDMode<D>]: joycon/input_report_mode/simple_hid_mode/struct.SimpleHIDMode.html
143//! [StandardFullMode<D>]: joycon/input_report_mode/standard_full_mode/struct.StandardFullMode.html
144//! [SubCommandMode<D, RD>]: joycon/input_report_mode/sub_command_mode/struct.SubCommandMode.html
145//! [Deal with LED (Player lights)]: joycon/lights/index.html
146//! [Vibration (Rumble)]:joycon/struct.Rumble.html
147extern crate hidapi;
148#[macro_use]
149extern crate lazy_static;
150
151pub mod joycon;
152
153#[cfg(doctest)]
154#[macro_use]
155extern crate doc_comment;
156
157#[cfg(doctest)]
158doctest!("../README.md");
159
160pub mod prelude {
161 #[cfg(feature = "use_serde")]
162 pub(crate) use serde::{Serialize, Deserialize};
163 pub use hidapi::*;
164 pub use crossbeam_channel;
165 pub use crate::result::*;
166 pub use crate::joycon::*;
167}
168
169pub mod result {
170 // use crate::prelude::SubCommand;
171 use hidapi::HidError;
172
173 #[derive(Debug)]
174 pub enum JoyConError {
175 HidApiError(hidapi::HidError),
176 // SubCommandError(SubCommand),
177 SubCommandError(u8, Vec<u8>),
178 JoyConDeviceError(JoyConDeviceError),
179 JoyConReportError(JoyConReportError),
180 Disconnected,
181 }
182
183 impl From<hidapi::HidError> for JoyConError {
184 fn from(e: HidError) -> Self {
185 JoyConError::HidApiError(e)
186 }
187 }
188
189 #[derive(Debug)]
190 pub enum JoyConDeviceError {
191 InvalidVendorID(u16),
192 InvalidProductID(u16),
193 FailedStickParameterLoading,
194 FailedStickCalibrationLoading,
195 FailedIMUOffsetsLoading,
196 FailedIMUCalibrationLoading,
197 FailedColorLoading,
198 }
199
200 impl From<JoyConDeviceError> for JoyConError {
201 fn from(e: JoyConDeviceError) -> Self {
202 JoyConError::JoyConDeviceError(e)
203 }
204 }
205
206 #[derive(Debug)]
207 pub enum JoyConReportError {
208 InvalidSimpleHidReport(InvalidSimpleHIDReport),
209 InvalidStandardInputReport(InvalidStandardInputReport),
210 EmptyReport,
211 }
212
213 impl From<JoyConReportError> for JoyConError {
214 fn from(e: JoyConReportError) -> Self {
215 JoyConError::JoyConReportError(e)
216 }
217 }
218
219 #[derive(Debug)]
220 pub enum InvalidSimpleHIDReport {
221 InvalidReport(Vec<u8>),
222 InvalidStickDirection(u8),
223 }
224
225 impl From<InvalidSimpleHIDReport> for JoyConReportError {
226 fn from(e: InvalidSimpleHIDReport) -> Self {
227 JoyConReportError::InvalidSimpleHidReport(e)
228 }
229 }
230
231 impl From<InvalidSimpleHIDReport> for JoyConError {
232 fn from(e: InvalidSimpleHIDReport) -> Self {
233 let report_error = JoyConReportError::from(e);
234 JoyConError::from(report_error)
235 }
236 }
237
238 #[derive(Debug)]
239 pub enum InvalidStandardInputReport {
240 InvalidReport(Vec<u8>),
241 InvalidExtraReport(Vec<u8>),
242 Battery(u8),
243 ConnectionInfo(u8),
244 InvalidInputReportId(u8),
245 }
246
247 impl From<InvalidStandardInputReport> for JoyConReportError {
248 fn from(e: InvalidStandardInputReport) -> Self {
249 JoyConReportError::InvalidStandardInputReport(e)
250 }
251 }
252
253 impl From<InvalidStandardInputReport> for JoyConError {
254 fn from(e: InvalidStandardInputReport) -> Self {
255 let report_error = JoyConReportError::from(e);
256 JoyConError::from(report_error)
257 }
258 }
259
260 pub type JoyConResult<T> = Result<T, JoyConError>;
261}
262
263#[cfg(test)]
264mod tests {
265 #[test]
266 fn it_works() {
267 assert_eq!(2 + 2, 4);
268 }
269}