1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use std::fs::{File, OpenOptions}; 6 use std::io; 7 use std::io::{Read, Write}; 8 use std::os::windows::io::AsRawHandle; 9 10 use super::winapi::DeviceCapabilities; 11 use crate::consts::{CID_BROADCAST, FIDO_USAGE_PAGE, FIDO_USAGE_U2FHID, MAX_HID_RPT_SIZE}; 12 use crate::u2ftypes::{U2FDevice, U2FDeviceInfo}; 13 14 #[derive(Debug)] 15 pub struct Device { 16 path: String, 17 file: File, 18 cid: [u8; 4], 19 dev_info: Option<U2FDeviceInfo>, 20 } 21 22 impl Device { new(path: String) -> io::Result<Self>23 pub fn new(path: String) -> io::Result<Self> { 24 let file = OpenOptions::new().read(true).write(true).open(&path)?; 25 Ok(Self { 26 path, 27 file, 28 cid: CID_BROADCAST, 29 dev_info: None, 30 }) 31 } 32 is_u2f(&self) -> bool33 pub fn is_u2f(&self) -> bool { 34 match DeviceCapabilities::new(self.file.as_raw_handle()) { 35 Ok(caps) => caps.usage() == FIDO_USAGE_U2FHID && caps.usage_page() == FIDO_USAGE_PAGE, 36 _ => false, 37 } 38 } 39 } 40 41 impl PartialEq for Device { eq(&self, other: &Device) -> bool42 fn eq(&self, other: &Device) -> bool { 43 self.path == other.path 44 } 45 } 46 47 impl Read for Device { read(&mut self, bytes: &mut [u8]) -> io::Result<usize>48 fn read(&mut self, bytes: &mut [u8]) -> io::Result<usize> { 49 // Windows always includes the report ID. 50 let mut input = [0u8; MAX_HID_RPT_SIZE + 1]; 51 let _ = self.file.read(&mut input)?; 52 bytes.clone_from_slice(&input[1..]); 53 Ok(bytes.len() as usize) 54 } 55 } 56 57 impl Write for Device { write(&mut self, bytes: &[u8]) -> io::Result<usize>58 fn write(&mut self, bytes: &[u8]) -> io::Result<usize> { 59 self.file.write(bytes) 60 } 61 flush(&mut self) -> io::Result<()>62 fn flush(&mut self) -> io::Result<()> { 63 self.file.flush() 64 } 65 } 66 67 impl U2FDevice for Device { get_cid<'a>(&'a self) -> &'a [u8; 4]68 fn get_cid<'a>(&'a self) -> &'a [u8; 4] { 69 &self.cid 70 } 71 set_cid(&mut self, cid: [u8; 4])72 fn set_cid(&mut self, cid: [u8; 4]) { 73 self.cid = cid; 74 } 75 in_rpt_size(&self) -> usize76 fn in_rpt_size(&self) -> usize { 77 MAX_HID_RPT_SIZE 78 } 79 out_rpt_size(&self) -> usize80 fn out_rpt_size(&self) -> usize { 81 MAX_HID_RPT_SIZE 82 } 83 get_property(&self, _prop_name: &str) -> io::Result<String>84 fn get_property(&self, _prop_name: &str) -> io::Result<String> { 85 Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) 86 } 87 get_device_info(&self) -> U2FDeviceInfo88 fn get_device_info(&self) -> U2FDeviceInfo { 89 // unwrap is okay, as dev_info must have already been set, else 90 // a programmer error 91 self.dev_info.clone().unwrap() 92 } 93 set_device_info(&mut self, dev_info: U2FDeviceInfo)94 fn set_device_info(&mut self, dev_info: U2FDeviceInfo) { 95 self.dev_info = Some(dev_info); 96 } 97 } 98