1use std::{fmt, mem, ptr};
2use std::borrow::Borrow;
3use crate::*;
4
5#[cfg(feature = "unstable_ds4")]
7#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
8#[repr(C)]
9pub struct DS4Report {
10 pub thumb_lx: u8,
11 pub thumb_ly: u8,
12 pub thumb_rx: u8,
13 pub thumb_ry: u8,
14 pub buttons: u16,
15 pub special: u8,
16 pub trigger_l: u8,
17 pub trigger_r: u8,
18}
19#[cfg(feature = "unstable_ds4")]
20impl Default for DS4Report {
21 #[inline]
22 fn default() -> Self {
23 DS4Report {
24 thumb_lx: 0x80,
25 thumb_ly: 0x80,
26 thumb_rx: 0x80,
27 thumb_ry: 0x80,
28 buttons: 0x8,
29 special: 0,
30 trigger_l: 0,
31 trigger_r: 0,
32 }
33 }
34}
35
36pub struct DualShock4Wired<CL: Borrow<Client>> {
66 client: CL,
67 event: Event,
68 serial_no: u32,
69 id: TargetId,
70}
71
72impl<CL: Borrow<Client>> DualShock4Wired<CL> {
73 #[inline]
75 pub fn new(client: CL, id: TargetId) -> DualShock4Wired<CL> {
76 let event = Event::new(false, false);
77 DualShock4Wired { client, event, serial_no: 0, id }
78 }
79
80 #[inline]
82 pub fn is_attached(&self) -> bool {
83 self.serial_no != 0
84 }
85
86 #[inline]
88 pub fn id(&self) -> TargetId {
89 self.id
90 }
91
92 #[inline]
94 pub fn client(&self) -> &CL {
95 &self.client
96 }
97
98 #[inline]
100 pub fn drop(mut self) -> CL {
101 let _ = self.unplug();
102
103 unsafe {
104 let client = (&self.client as *const CL).read();
105 ptr::drop_in_place(&mut self.event);
106 mem::forget(self);
107 client
108 }
109 }
110
111 #[inline(never)]
113 pub fn plugin(&mut self) -> Result<(), Error> {
114 if self.is_attached() {
115 return Err(Error::AlreadyConnected);
116 }
117
118 self.serial_no = unsafe {
119 let mut plugin = bus::PluginTarget::ds4_wired(1, self.id.vendor, self.id.product);
120 let device = self.client.borrow().device;
121
122 while plugin.ioctl(device, self.event.handle).is_err() {
124 plugin.SerialNo += 1;
125 if plugin.SerialNo >= u16::MAX as u32 {
126 return Err(Error::NoFreeSlot);
127 }
128 }
129
130 plugin.SerialNo
131 };
132
133 Ok(())
134 }
135
136 #[inline(never)]
138 pub fn unplug(&mut self) -> Result<(), Error> {
139 if !self.is_attached() {
140 return Err(Error::NotPluggedIn);
141 }
142
143 unsafe {
144 let mut unplug = bus::UnplugTarget::new(self.serial_no);
145 let device = self.client.borrow().device;
146 unplug.ioctl(device, self.event.handle)?;
147 }
148
149 self.serial_no = 0;
150 Ok(())
151 }
152
153 #[inline(never)]
157 pub fn wait_ready(&mut self) -> Result<(), Error> {
158 if !self.is_attached() {
159 return Err(Error::NotPluggedIn);
160 }
161
162 unsafe {
163 let mut wait = bus::WaitDeviceReady::new(self.serial_no);
164 let device = self.client.borrow().device;
165 wait.ioctl(device, self.event.handle)?;
166 }
167
168 Ok(())
169 }
170
171 #[cfg(feature = "unstable_ds4")]
173 #[inline(never)]
174 pub fn update(&mut self, report: &DS4Report) -> Result<(), Error> {
175 if !self.is_attached() {
176 return Err(Error::NotPluggedIn);
177 }
178
179 unsafe {
180 let mut dsr = bus::DS4SubmitReport::new(self.serial_no, *report);
181 let device = self.client.borrow().device;
182 dsr.ioctl(device, self.event.handle)?;
183 }
184
185 Ok(())
186 }
187
188 }
196
197impl<CL: Borrow<Client>> fmt::Debug for DualShock4Wired<CL> {
198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199 f.debug_struct("DualShock4Wired")
200 .field("serial_no", &self.serial_no)
201 .field("vendor_id", &self.id.vendor)
202 .field("product_id", &self.id.product)
203 .finish()
204 }
205}
206
207impl<CL: Borrow<Client>> Drop for DualShock4Wired<CL> {
208 #[inline]
209 fn drop(&mut self) {
210 let _ = self.unplug();
211 }
212}