Skip to content

Commit

Permalink
Merge pull request #25 from KaiseiYokoyama/dev/0.2.0
Browse files Browse the repository at this point in the history
Dev/0.2.0
  • Loading branch information
KaiseiYokoyama authored Apr 24, 2020
2 parents a3f05e6 + 0a6f2d8 commit d2b8749
Show file tree
Hide file tree
Showing 13 changed files with 1,083 additions and 406 deletions.
13 changes: 10 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "joycon-rs"
version = "0.1.1"
version = "0.2.0"
authors = ["Kaisei Yokoyama <[email protected]>"]
edition = "2018"
description = " a framework for dealing with Nintendo Switch Joy-Con on Rust easily and efficiently"
Expand All @@ -11,7 +11,11 @@ license = "Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
hidapi = "1.2.1"
hidapi = { git = "https://github.com/KaiseiYokoyama/hidapi-rs" }
crossbeam-channel = "0.4.2"

[dev-dependencies]
doc-comment = "0.3.3"

[[example]]
name = "scan_for_joycons"
Expand All @@ -23,4 +27,7 @@ name = "player_lights"
name = "standard_full_report"

[[example]]
name = "simple_hid_report"
name = "simple_hid_report"

[[example]]
name = "rumble"
184 changes: 98 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,97 +17,109 @@ Please see the documentation comments for detailed instructions on how to use it
On macOS or Windows, there are no preparation.

On linux,
```
sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
```bash
$ sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
```

# Usage
First, add dependency to `Cargo.toml`
# Usage
First, add dependency to `Cargo.toml`

```toml
```toml
[dependencies]
joycon_rs = "*"
```

Then, `use` prelude on `.rs` file.
```
use joycon_rs::prelude::*;
```

Perfect! Now you have Joycon-rs available in code.

### Receive reports
For starters, let's take a simple signal from JoyCon.
If you have more than one JoyCon, [`mspc`] can be very helpful.

```no_run
use joycon_rs::prelude::*;
let (tx, rx) = std::sync::mpsc::channel();
JoyConManager::new()
.unwrap()
.connected_joycon_devices
.into_iter()
.flat_map(|dev| SimpleJoyConDriver::new(dev))
.try_for_each::<_, JoyConResult<()>>(|driver| {
// Change JoyCon to Simple hid mode.
let simple_hid_mode = SimpleHIDMode::new(driver)?;
let tx = tx.clone();
// Spawn thread
std::thread::spawn( move || {
loop {
// Forward the report to the main thread
tx.send(simple_hid_mode.read_input_report()).unwrap();
}
});
Ok(())
})
.unwrap();
// Receive reports from threads
while let Ok(report) = rx.recv() {
// Output report
dbg!(report);
}
```

### Ser player lights
Then, lets deal with player lights.

```no_run
use joycon_rs::prelude::{*, lights::*};
let (tx, rx) = std::sync::mpsc::channel();
JoyConManager::new()
.unwrap()
.connected_joycon_devices
.into_iter()
.flat_map(|dev| SimpleJoyConDriver::new(dev))
.try_for_each::<_, JoyConResult<()>>(|mut driver| {
// Set player lights
// [SL BUTTON] 📸💡📸💡 [SR BUTTON]
driver.set_player_lights(&vec![LightUp::LED1, LightUp::LED3], &vec![Flash::LED0, Flash::LED2]).unwrap();
tx.send(driver.get_player_lights()).unwrap();
Ok(())
})
.unwrap();
// Receive status of player lights
while let Ok(Ok(light_status)) = rx.recv() {
assert_eq!(
light_status.extra.reply,
LightsStatus {
light_up: vec![LightUp::LED1, LightUp::LED3],
flash: vec![Flash::LED0, Flash::LED2],
}
)
}
```
```

Then, `use` prelude on `.rs` file.
```
use joycon_rs::prelude::*;
```

Perfect! Now you have Joycon-rs available in code.

### Receive reports
For starters, let's take a simple signal from JoyCon.
If you use more than one JoyCon, [`mspc`] can be very helpful.

```no_run
use joycon_rs::prelude::*;
let (tx, rx) = std::sync::mpsc::channel();
let _output = std::thread::spawn(move || {
// Push buttons or tilt the stick please.
// Stop with `Cmd + C` or `Ctrl + C`
while let Ok(message) = rx.recv() {
dbg!(message);
}
});
let manager = JoyConManager::new().unwrap();
let (managed_devices, new_devices) = {
let lock = manager.lock();
match lock {
Ok(m) => (m.managed_devices(),m.new_devices()),
Err(_) => unreachable!()
}
};
managed_devices.into_iter()
.chain(new_devices)
.flat_map(|dev| SimpleJoyConDriver::new(&dev))
.try_for_each::<_, JoyConResult<()>>(|driver| {
// Change JoyCon to Simple hid mode.
let simple_hid_mode = SimpleHIDMode::new(driver)?;
let tx = tx.clone();
// Spawn thread
std::thread::spawn( move || {
loop {
// Forward the report to the main thread
tx.send(simple_hid_mode.read_input_report()).unwrap();
}
});
Ok(())
})
.unwrap();
```

### Ser player lights
Then, lets deal with player lights.

```no_run
use joycon_rs::prelude::{*, lights::*};
let (tx, rx) = std::sync::mpsc::channel();
let _output = std::thread::spawn(move || {
// Stop with `Cmd + C` or `Ctrl + C`
while let Ok(message) = rx.recv() {
dbg!(message);
}
});
let manager = JoyConManager::new().unwrap();
let (managed_devices, new_devices) = {
let lock = manager.lock();
match lock {
Ok(m) => (m.managed_devices(),m.new_devices()),
Err(_) => unreachable!()
}
};
managed_devices.into_iter()
.chain(new_devices)
.flat_map(|dev| SimpleJoyConDriver::new(&dev))
.try_for_each::<_, JoyConResult<()>>(|mut driver| {
// Set player lights
// [SL BUTTON] 📸💡📸💡 [SR BUTTON]
driver.set_player_lights(&vec![LightUp::LED1, LightUp::LED3], &vec![Flash::LED0, Flash::LED2]).unwrap();
tx.send(driver.get_player_lights()).unwrap();
Ok(())
})
.unwrap();
```

# Features
You can use `Joycon-rs` for...
Expand Down
40 changes: 33 additions & 7 deletions examples/player_lights.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
#![allow(unused_must_use)]

use joycon_rs::prelude::{*, lights::*};
use std::convert::TryInto;
use std::ops::Deref;

fn main() -> JoyConResult<()> {
// First, connect your Joy-Cons to your computer!
JoyConManager::new()?
.connected_joycon_devices
.into_iter()
.try_for_each::<_,JoyConResult<()>>(|d| {
let mut driver = SimpleJoyConDriver::new(d)?;

let manager =
JoyConManager::new()?;
let (managed_devices, new_devices) = {
let lock = manager.lock();
match lock {
Ok(manager) =>
(manager.managed_devices(), manager.new_devices()),
Err(_) => unreachable!(),
}
};

managed_devices.into_iter()
.chain(new_devices)
.inspect(|d| {
let lock = d.lock();
let device = match lock {
Ok(device) => device,
Err(e) => e.into_inner(),
};
let hid_device: JoyConResult<&HidDevice> = device.deref().try_into();
if let Ok(hid_device) = hid_device {
println!("{:?}", hid_device.get_product_string())
}
})
.try_for_each::<_, JoyConResult<()>>(|d| {
let mut driver = SimpleJoyConDriver::new(&d)?;

let lights_status = LightsStatus {
light_up: vec![LightUp::LED1,LightUp::LED2],
flash: vec![Flash::LED0,Flash::LED3]
light_up: vec![LightUp::LED1, LightUp::LED2],
flash: vec![Flash::LED0, Flash::LED3],
};

// Set player lights
Expand Down
46 changes: 46 additions & 0 deletions examples/rumble.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use joycon_rs::prelude::*;
use std::convert::TryInto;
use std::ops::Deref;
use joycon_rs::joycon::joycon_features::JoyConFeature;

fn main() -> JoyConResult<()> {
// First, connect your Joy-Cons to your computer!

let manager =
JoyConManager::new()?;
let (managed_devices, new_devices) = {
let lock = manager.lock();
match lock {
Ok(manager) =>
(manager.managed_devices(), manager.new_devices()),
Err(_) => unreachable!(),
}
};

managed_devices.into_iter()
.chain(new_devices)
.inspect(|d| {
let lock = d.lock();
let device = match lock {
Ok(device) => device,
Err(e) => e.into_inner(),
};
let hid_device: JoyConResult<&HidDevice> = device.deref().try_into();
if let Ok(hid_device) = hid_device {
println!("{:?}", hid_device.get_product_string())
}
})
.try_for_each::<_, JoyConResult<()>>(|d| {
let mut driver = SimpleJoyConDriver::new(&d)?;

driver.enable_feature(JoyConFeature::Vibration)?;

// let rumble = Rumble::new(80.0,0.2);
let rumble = Rumble::new(300.0,0.9);
driver.rumble((Some(rumble), Some(rumble)))?;

Ok(())
})?;

Ok(())
}
26 changes: 21 additions & 5 deletions examples/scan_for_joycons.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
#![allow(unused_must_use)]

use joycon_rs::prelude::*;
use std::convert::TryInto;
use std::ops::Deref;

fn main() -> JoyConResult<()>{
fn main() -> JoyConResult<()> {
// First, connect your Joy-Cons to your computer!
JoyConManager::new()?
.connected_joycon_devices
.iter()

let manager = JoyConManager::new()?;
let (managed_devices, new_devices) = {
let lock = manager.lock();
match lock {
Ok(m) => (m.managed_devices(), m.new_devices()),
Err(_) => unreachable!(),
}
};

managed_devices.into_iter()
.chain(new_devices)
.try_for_each::<_, JoyConResult<()>>(|d| {
println!("{:?}", d.get_product_string()?);
if let Ok(device) = d.lock() {
let device: &HidDevice = device.deref().try_into()?;
println!("{:?}", device.get_product_string()?);
}
Ok(())
})?;

Expand Down
Loading

0 comments on commit d2b8749

Please sign in to comment.