Skip to content

Commit

Permalink
Merge pull request #29 from KaiseiYokoyama/dev/0.3.0
Browse files Browse the repository at this point in the history
Dev/0.3.0
  • Loading branch information
KaiseiYokoyama authored Apr 26, 2020
2 parents 5ec5164 + 3947313 commit da6e3ad
Show file tree
Hide file tree
Showing 8 changed files with 418 additions and 60 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/Murakumo.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "joycon-rs"
version = "0.2.0"
version = "0.3.0"
authors = ["Kaisei Yokoyama <[email protected]>"]
edition = "2018"
description = " a framework for dealing with Nintendo Switch Joy-Con on Rust easily and efficiently"
Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,58 @@ managed_devices.into_iter()
.unwrap();
```

### Rumble
```no_run
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(())
}
```

### More Examples
[Here](examples).

# Features
You can use `Joycon-rs` for...
- Manage Joy-Cons
Expand Down
48 changes: 48 additions & 0 deletions examples/home_light.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#![allow(unused_must_use)]

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

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)?;

let pattern =
LightEmittingPattern::new(100, 0, 0u8.into())
.add_phase(100,500,0)
.add_phase(0,500,0);
driver.set_home_light(&pattern);

Ok(())
})?;

Ok(())
}
112 changes: 72 additions & 40 deletions src/joycon/device.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,109 @@
use super::*;
use std::convert::TryInto;


pub fn is_joycon(device_info: &DeviceInfo) -> JoyConResult<()> {
if device_info.vendor_id() != JoyConDevice::VENDOR_ID {
Err(JoyConDeviceError::InvalidVendorID(device_info.vendor_id()))?;
}

match device_info.product_id() {
JoyConDevice::PRODUCT_ID_JOYCON_L | JoyConDevice::PRODUCT_ID_JOYCON_R => Ok(()),
other => Err(JoyConDeviceError::InvalidProductID(other))?,
}
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub enum JoyConDeviceType {
JoyConL = 0,
JoyConR = 1,
ProCon = 2,
}

pub enum JoyConDevice {
Connected(HidDevice),
Disconnected,
pub struct JoyConDevice {
hid_device: Option<HidDevice>,
serial_number: String,
device_type: JoyConDeviceType,
}

impl JoyConDevice {
pub const VENDOR_ID: u16 = 1406;
pub const PRODUCT_ID_JOYCON_L: u16 = 8198;
pub const PRODUCT_ID_JOYCON_R: u16 = 8199;
pub const PRODUCT_ID_PROCON: u16 = 8201;

pub fn check_type_of_device(device_info: &DeviceInfo) -> JoyConResult<JoyConDeviceType> {
if device_info.vendor_id() != JoyConDevice::VENDOR_ID {
Err(JoyConDeviceError::InvalidVendorID(device_info.vendor_id()))?;
}

match device_info.product_id() {
JoyConDevice::PRODUCT_ID_JOYCON_L => Ok(JoyConDeviceType::JoyConL),
JoyConDevice::PRODUCT_ID_JOYCON_R => Ok(JoyConDeviceType::JoyConR),
JoyConDevice::PRODUCT_ID_PROCON => Ok(JoyConDeviceType::ProCon),
other => Err(JoyConDeviceError::InvalidProductID(other))?,
}
}

pub fn is_connected(&self) -> bool {
self.hid_device.is_some()
}

pub fn serial_number(&self) -> &str {
&self.serial_number
}

pub fn device_type(&self) -> JoyConDeviceType {
self.device_type.clone()
}

pub fn reset_device(&mut self, hid_device: HidDevice) {
self.hid_device = Some(hid_device);
}

pub fn forget_device(&mut self) {
self.hid_device = None;
}

pub fn new(device_info: &DeviceInfo, hidapi: &HidApi) -> JoyConResult<Self> {
is_joycon(device_info)?;
let device_type = Self::check_type_of_device(device_info)?;

let serial = device_info.serial_number().unwrap_or("");
let device = hidapi.open_serial(device_info.vendor_id(),
device_info.product_id(),
serial)?;
// let device = device_info.open_device(&hidapi)?;
Ok(JoyConDevice::Connected(device))
let hid_device = hidapi.open_serial(device_info.vendor_id(),
device_info.product_id(),
serial)?;

Ok(
JoyConDevice {
hid_device: Some(hid_device),
serial_number: serial.to_string(),
device_type,
}
)
}

pub fn write(&self, data: &[u8]) -> JoyConResult<usize> {
match &self {
JoyConDevice::Connected(hid_device) => Ok(hid_device.write(data)?),
JoyConDevice::Disconnected => Err(JoyConError::Disconnected),
if let Some(hid_device) = &self.hid_device {
Ok(hid_device.write(data)?)
} else {
Err(JoyConError::Disconnected)
}
}

pub fn read(&self, buf: &mut [u8]) -> JoyConResult<usize> {
match &self {
JoyConDevice::Connected(hid_device) => Ok(hid_device.read(buf)?),
JoyConDevice::Disconnected => Err(JoyConError::Disconnected),
}
}

pub fn is_connected(&self) -> bool {
match &self {
JoyConDevice::Connected(_) => true,
JoyConDevice::Disconnected => false,
if let Some(hid_device) = &self.hid_device {
Ok(hid_device.read(buf)?)
} else {
Err(JoyConError::Disconnected)
}
}
}

impl Debug for JoyConDevice {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", match &self {
JoyConDevice::Connected(_) => "Connected",
JoyConDevice::Disconnected => "Disconnected",
})
writeln!(f, "JoyConDevice {{ hid_device: {}, serial_number: {}, device_type: {:?} }}",
if self.is_connected() {
"Connected"
} else { "Disconnected" },
&self.serial_number,
&self.device_type
)
}
}

impl<'a> TryInto<&'a HidDevice> for &'a JoyConDevice {
type Error = JoyConError;

fn try_into(self) -> Result<&'a HidDevice, Self::Error> {
match self {
JoyConDevice::Connected(d) => Ok(d),
JoyConDevice::Disconnected => Err(JoyConError::Disconnected),
}
self.hid_device.as_ref()
.ok_or(JoyConError::Disconnected)
}
}
Loading

0 comments on commit da6e3ad

Please sign in to comment.