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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use super::*;

/// The controller user uses to play with.
/// If you're not happy with this implementation, you can use `JoyConDriver` trait.
///
/// # Examples
/// ```no_run
/// use joycon_rs::prelude::{JoyConManager, SimpleJoyConDriver, lights::*};
/// use joycon_rs::result::JoyConResult;
///
/// let manager = JoyConManager::get_instance();
///
/// let devices = {
///     let lock = manager.lock();
///     match lock {
///         Ok(manager) => manager.new_devices(),
///         Err(_) => return,
///     }
/// };
///
/// devices.iter()
///     .try_for_each::<_,JoyConResult<()>>(|device| {
///         let mut driver = SimpleJoyConDriver::new(&device)?;
///
///         // set player's lights
///         driver.set_player_lights(&vec![SimpleJoyConDriver::LIGHT_UP[0]], &vec![])?;
///
///         Ok(())
///     })
///     .unwrap();
/// ```
#[derive(Debug)]
pub struct SimpleJoyConDriver {
    /// The controller user uses
    pub joycon: Arc<Mutex<JoyConDevice>>,
    /// rotation of controller
    pub rotation: Rotation,
    rumble: (Option<Rumble>, Option<Rumble>),
    enabled_features: HashSet<JoyConFeature>,
    valid_reply: bool,
    /// Increment by 1 for each packet sent. It loops in 0x0 - 0xF range.
    global_packet_number: GlobalPacketNumber,
}

impl SimpleJoyConDriver {
    /// Constructs a new `SimpleJoyConDriver`.
    pub fn new(joycon: &Arc<Mutex<JoyConDevice>>) -> JoyConResult<Self> {
        // joycon.set_blocking_mode(true);
        // joycon.set_blocking_mode(false);

        let mut driver = Self {
            joycon: Arc::clone(joycon),
            rotation: Rotation::Portrait,
            rumble: (None, None),
            enabled_features: HashSet::new(),
            valid_reply: {
                let device = match joycon.lock() {
                    Ok(j) => j,
                    Err(e) => e.into_inner(),
                }.device_type();
                match device {
                    JoyConDeviceType::ProCon => false,
                    _ => true,
                }
            },
            global_packet_number: GlobalPacketNumber::default(),
        };

        let check_reply = {
            let device = match joycon.lock() {
                Ok(d) => d,
                Err(e) => e.into_inner(),
            };
            match device.device_type() {
                JoyConDeviceType::ProCon => false,
                _ => true,
            }
        };

        if check_reply {
            driver.reset()?;
        } else {
            let _ = driver.reset();
        }

        Ok(driver)
    }

    pub fn joycon(&self) -> MutexGuard<JoyConDevice> {
        // todo error handling
        match self.joycon.lock() {
            Ok(joycon) => joycon,
            Err(poisoned) => poisoned.into_inner(),
        }
    }
}


impl JoyConDriver for SimpleJoyConDriver {
    fn valid_reply(&self) -> bool {
        self.valid_reply
    }

    fn set_valid_reply(&mut self, valid: bool) {
        self.valid_reply = valid;
    }

    fn write(&self, data: &[u8]) -> JoyConResult<usize> {
        let joycon = self.joycon();
        Ok(joycon.write(data)?)
    }

    fn read(&self, buf: &mut [u8]) -> JoyConResult<usize> {
        Ok(self.joycon().read(buf)?)
    }

    fn read_timeout(&self, buf: &mut [u8], timeout: i32) -> JoyConResult<usize> {
        Ok(self.joycon().read_timeout(buf,timeout)?)
    }

    fn global_packet_number(&self) -> u8 {
        self.global_packet_number.into()
    }

    fn increase_global_packet_number(&mut self) {
        self.global_packet_number = self.global_packet_number.next();
    }

    fn set_rumble_status(&mut self, rumble_l_r: (Option<Rumble>, Option<Rumble>)) {
        self.rumble = rumble_l_r;
    }

    fn get_rumble_status(&self) -> (Option<Rumble>, Option<Rumble>) {
        self.rumble
    }

    fn enable_feature(&mut self, feature: JoyConFeature) -> JoyConResult<()> {
        match feature {
            JoyConFeature::IMUFeature(feature) => {
                let data: [u8; 4] = feature.into();
                // enable IMU
                self.send_sub_command(SubCommand::EnableIMU, &[0x01])?;
                // set config
                self.send_sub_command(SubCommand::SetIMUSensitivity, &data)?;
            }
            JoyConFeature::Vibration => {
                // enable vibration
                self.send_sub_command(SubCommand::EnableVibration, &[0x01])?;
            }
        }

        self.enabled_features.insert(feature);

        Ok(())
    }

    fn enabled_features(&self) -> &HashSet<JoyConFeature> {
        &self.enabled_features
    }

    fn devices(&self) -> Vec<Arc<Mutex<JoyConDevice>>> {
        vec![Arc::clone(&self.joycon)]
    }
}