1use std::{
2 io::{Read, Write},
3 str, time,
4};
5
6use crate::platform;
7
8#[derive(Debug)]
12pub struct BtSocket(platform::BtSocket);
13
14impl BtSocket {
15 pub fn new(protocol: BtProtocol) -> Result<BtSocket, BtError> {
17 Ok(From::from(platform::BtSocket::new(protocol)?))
18 }
19
20 pub fn connect(&mut self, addr: BtAddr) -> Result<(), BtError> {
25 let evtloop = mio::Poll::new().unwrap();
27 let token = mio::Token(0);
28 let mut events = mio::Events::with_capacity(2);
29
30 let mut connect = self.0.connect(addr);
32
33 loop {
34 match connect.advance()? {
35 BtAsync::WaitFor(evented, interest) => {
36 let mut event_received = false;
37 while !event_received {
38 evtloop
40 .register(evented, token, interest, mio::PollOpt::oneshot())
41 .unwrap();
42
43 evtloop.poll(&mut events, None).unwrap();
45
46 for event in events.iter() {
47 if event.token() == token {
48 event_received = true;
49 evtloop.deregister(evented).unwrap();
50 }
51 }
52 }
53 }
54
55 BtAsync::Done => {
56 return Ok(());
57 }
58 }
59 }
60 }
61
62 pub fn connect_async(&mut self, addr: BtAddr) -> BtSocketConnect {
70 BtSocketConnect(self.0.connect(addr))
71 }
72}
73
74impl From<platform::BtSocket> for BtSocket {
75 fn from(socket: platform::BtSocket) -> BtSocket {
76 BtSocket(socket)
77 }
78}
79
80impl mio::Evented for BtSocket {
81 fn register(
82 &self,
83 poll: &mio::Poll,
84 token: mio::Token,
85 interest: mio::Ready,
86 opts: mio::PollOpt,
87 ) -> std::io::Result<()> {
88 self.0.register(poll, token, interest, opts)
89 }
90
91 fn reregister(
92 &self,
93 poll: &mio::Poll,
94 token: mio::Token,
95 interest: mio::Ready,
96 opts: mio::PollOpt,
97 ) -> std::io::Result<()> {
98 self.0.reregister(poll, token, interest, opts)
99 }
100
101 fn deregister(&self, poll: &mio::Poll) -> std::io::Result<()> {
102 self.0.deregister(poll)
103 }
104}
105
106impl Read for BtSocket {
107 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
108 self.0.read(buf)
109 }
110}
111
112impl Write for BtSocket {
113 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
114 self.0.write(buf)
115 }
116
117 fn flush(&mut self) -> std::io::Result<()> {
118 self.0.flush()
119 }
120}
121
122#[allow(missing_debug_implementations)] pub enum BtAsync<'a> {
125 WaitFor(&'a mio::Evented, mio::Ready),
127
128 Done,
130}
131
132#[derive(Debug)]
134pub struct BtSocketConnect<'a>(platform::BtSocketConnect<'a>);
135
136impl<'a> BtSocketConnect<'a> {
137 pub fn advance(&mut self) -> Result<BtAsync, BtError> {
145 self.0.advance()
146 }
147}
148
149pub fn scan_devices(timeout: time::Duration) -> Result<Vec<BtDevice>, BtError> {
153 platform::scan_devices(timeout)
154}
155
156#[derive(Debug)]
158pub enum BtError {
159 Unknown,
161
162 Errno(u32, String),
164
165 Desc(String),
167
168 IoError(std::io::Error),
170}
171
172impl std::fmt::Display for BtError {
173 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
174 write!(f, "{:}", std::error::Error::description(self))
175 }
176}
177
178impl std::error::Error for BtError {
179 fn description(&self) -> &str {
180 match self {
181 BtError::Unknown => "Unknown Bluetooth Error",
182 BtError::Errno(_, ref message) => message.as_str(),
183 BtError::Desc(ref message) => message.as_str(),
184 BtError::IoError(ref err) => err.description(),
185 }
186 }
187}
188
189impl From<std::io::Error> for BtError {
190 fn from(error: std::io::Error) -> Self {
191 BtError::IoError(error)
192 }
193}
194
195#[repr(C, packed)]
197#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
198pub struct BtAddr(pub [u8; 6]);
199
200impl std::fmt::Debug for BtAddr {
201 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
202 write!(
203 f,
204 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
205 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
206 )
207 }
208}
209
210impl BtAddr {
211 pub fn any() -> BtAddr {
213 BtAddr([0, 0, 0, 0, 0, 0])
214 }
215
216 #[doc(hidden)]
219 #[inline(always)]
220 #[cfg(target_endian = "little")]
221 pub fn convert_host_byteorder(mut self) -> BtAddr {
222 {
223 let (value_1, value_2) = (&mut self.0).split_at_mut(3);
224 std::mem::swap(&mut value_1[0], &mut value_2[2]);
225 std::mem::swap(&mut value_1[1], &mut value_2[1]);
226 std::mem::swap(&mut value_1[2], &mut value_2[0]);
227 }
228
229 self
230 }
231
232 #[doc(hidden)]
233 #[inline(always)]
234 #[cfg(target_endian = "big")]
235 pub fn convert_host_byteorder(self) -> BtAddr {
236 self
238 }
239}
240
241impl ToString for BtAddr {
242 fn to_string(&self) -> String {
244 format!(
245 "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
246 self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
247 )
248 }
249}
250
251impl str::FromStr for BtAddr {
252 type Err = ();
253 fn from_str(s: &str) -> Result<Self, Self::Err> {
255 let splits_iter = s.split(':');
256 let mut addr = BtAddr::any();
257 let mut i = 0;
258 for split_str in splits_iter {
259 if i == 6 || split_str.len() != 2 {
260 return Err(());
261 } let high = (split_str.as_bytes()[0] as char).to_digit(16).ok_or(())?;
263 let low = (split_str.as_bytes()[1] as char).to_digit(16).ok_or(())?;
264 addr.0[i] = (high * 16 + low) as u8;
265 i += 1;
266 }
267 if i != 6 {
268 return Err(());
269 }
270 Ok(addr)
271 }
272}
273
274#[derive(Debug, Clone, PartialEq, Eq)]
276pub struct BtDevice {
277 pub name: String,
279
280 pub addr: BtAddr,
282}
283
284#[derive(Clone, Copy, Debug)]
288pub enum BtProtocol {
289 RFCOMM, }
299
300impl BtDevice {
301 pub fn new(name: String, addr: BtAddr) -> BtDevice {
303 BtDevice { name, addr }
304 }
305}
306
307#[cfg(test)]
308mod tests {
309 use super::*;
310 use std::str::FromStr;
311
312 #[test()]
313 fn btaddr_from_string() {
314 match BtAddr::from_str("00:00:00:00:00:00") {
315 Ok(addr) => assert_eq!(addr, BtAddr([0u8; 6])),
316 Err(_) => panic!(""),
317 }
318
319 let fail_strings = [
320 "addr : String",
321 "00:00:00:00:00",
322 "00:00:00:00:00:00:00",
323 "-00:00:00:00:00:00",
324 "0G:00:00:00:00:00",
325 ];
326 for &s in &fail_strings {
327 match BtAddr::from_str(s) {
328 Ok(_) => panic!("Somehow managed to parse \"{}\" as an address?!", s),
329 Err(_) => (),
330 }
331 }
332 }
333
334 #[test()]
335 fn btaddr_to_string() {
336 assert_eq!(BtAddr::any().to_string(), "00:00:00:00:00:00");
337 assert_eq!(BtAddr([1, 2, 3, 4, 5, 6]).to_string(), "01:02:03:04:05:06");
338 }
339
340 #[test()]
341 fn btaddr_roundtrips_to_from_str() {
342 let addr = BtAddr([0, 22, 4, 1, 33, 192]);
343 let addr_string = "00:ff:ee:ee:dd:12";
344
345 assert_eq!(addr, BtAddr::from_str(&addr.to_string()).unwrap());
346 assert!(
347 addr_string.eq_ignore_ascii_case(&BtAddr::from_str(addr_string).unwrap().to_string())
348 );
349 }
350
351 #[cfg(not(feature = "test_without_hardware"))]
352 #[test()]
353 fn creates_rfcomm_socket() {
354 BtSocket::new(BtProtocol::RFCOMM).unwrap();
355 }
356
357 #[cfg(not(feature = "test_without_hardware"))]
358 #[test()]
359 fn scans_devices() {
360 scan_devices(time::Duration::from_secs(20)).unwrap();
361 }
362}