$NetBSD: patch-third__party_rust_authenticator_src_netbsd_uhid.rs,v 1.1 2020/10/07 11:10:35 wiz Exp $ Add NetBSD support for U2F. Submitted upstream: https://github.com/mozilla/authenticator-rs/pull/116 --- third_party/rust/authenticator/src/netbsd/uhid.rs.orig 2020-07-15 16:29:34.213005315 +0000 +++ third_party/rust/authenticator/src/netbsd/uhid.rs @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +extern crate libc; + +use std::io; +use std::mem; +use std::os::raw::c_int; +use std::os::raw::c_uchar; + +use hidproto::ReportDescriptor; +use hidproto::has_fido_usage; +use platform::fd::Fd; +use util::io_err; + +/* sys/ioccom.h */ + +const IOCPARM_MASK: u32 = 0x1fff; +const IOCPARM_SHIFT: u32 = 16; +const IOCGROUP_SHIFT: u32 = 8; + +//const IOC_VOID: u32 = 0x20000000; +const IOC_OUT: u32 = 0x40000000; +const IOC_IN: u32 = 0x80000000; +//const IOC_INOUT: u32 = IOC_IN|IOC_OUT; + +macro_rules! ioctl { + ($dir:expr, $name:ident, $group:expr, $nr:expr, $ty:ty) => { + unsafe fn $name(fd: libc::c_int, val: *mut $ty) + -> io::Result { + let ioc = ($dir as u32) + | ((mem::size_of::<$ty>() as u32 & IOCPARM_MASK) + << IOCPARM_SHIFT) + | (($group as u32) << IOCGROUP_SHIFT) + | ($nr as u32); + let rv = libc::ioctl(fd, ioc as libc::c_ulong, val); + if rv == -1 { + return Err(io::Error::last_os_error()); + } + Ok(rv) + } + }; +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct usb_ctl_report_desc { + ucrd_size: c_int, + ucrd_data: [c_uchar; 1024], +} + +ioctl!(IOC_OUT, usb_get_report_desc, b'U', 21, usb_ctl_report_desc); + +fn read_report_descriptor(fd: &Fd) -> io::Result { + let mut desc = unsafe { mem::zeroed() }; + unsafe { usb_get_report_desc(fd.fileno, &mut desc) }?; + if desc.ucrd_size < 0 { + return Err(io_err("negative report descriptor size")); + } + let size = desc.ucrd_size as usize; + let value = Vec::from(&desc.ucrd_data[..size]); + Ok(ReportDescriptor { value }) +} + +pub fn is_u2f_device(fd: &Fd) -> bool { + match read_report_descriptor(fd) { + Ok(desc) => has_fido_usage(desc), + Err(_) => false, + } +} + +ioctl!(IOC_IN, usb_hid_set_raw_ioctl, b'h', 2, c_int); + +pub fn hid_set_raw(fd: &Fd, raw: bool) -> io::Result<()> { + let mut raw_int: c_int = if raw { 1 } else { 0 }; + unsafe { usb_hid_set_raw_ioctl(fd.fileno, &mut raw_int) }?; + Ok(()) +}