13da5c369Sopenharmony_ci#![allow(dead_code)]
23da5c369Sopenharmony_ci
33da5c369Sopenharmony_ci// Simple tests to ensure macro generated fns compile
43da5c369Sopenharmony_ciioctl_none_bad!(do_bad, 0x1234);
53da5c369Sopenharmony_ciioctl_read_bad!(do_bad_read, 0x1234, u16);
63da5c369Sopenharmony_ciioctl_write_int_bad!(do_bad_write_int, 0x1234);
73da5c369Sopenharmony_ciioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8);
83da5c369Sopenharmony_ciioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32);
93da5c369Sopenharmony_ciioctl_none!(do_none, 0, 0);
103da5c369Sopenharmony_ciioctl_read!(read_test, 0, 0, u32);
113da5c369Sopenharmony_ciioctl_write_int!(write_ptr_int, 0, 0);
123da5c369Sopenharmony_ciioctl_write_ptr!(write_ptr_u8, 0, 0, u8);
133da5c369Sopenharmony_ciioctl_write_ptr!(write_ptr_u32, 0, 0, u32);
143da5c369Sopenharmony_ciioctl_write_ptr!(write_ptr_u64, 0, 0, u64);
153da5c369Sopenharmony_ciioctl_readwrite!(readwrite_test, 0, 0, u64);
163da5c369Sopenharmony_ciioctl_read_buf!(readbuf_test, 0, 0, u32);
173da5c369Sopenharmony_ciconst SPI_IOC_MAGIC: u8 = b'k';
183da5c369Sopenharmony_ciconst SPI_IOC_MESSAGE: u8 = 0;
193da5c369Sopenharmony_ciioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8);
203da5c369Sopenharmony_ciioctl_write_buf!(writebuf_test_u8, 0, 0, u8);
213da5c369Sopenharmony_ciioctl_write_buf!(writebuf_test_u32, 0, 0, u32);
223da5c369Sopenharmony_ciioctl_write_buf!(writebuf_test_u64, 0, 0, u64);
233da5c369Sopenharmony_ciioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
243da5c369Sopenharmony_ci
253da5c369Sopenharmony_ci// See C code for source of values for op calculations (does NOT work for mips/powerpc):
263da5c369Sopenharmony_ci// https://gist.github.com/posborne/83ea6880770a1aef332e
273da5c369Sopenharmony_ci//
283da5c369Sopenharmony_ci// TODO:  Need a way to compute these constants at test time.  Using precomputed
293da5c369Sopenharmony_ci// values is fragile and needs to be maintained.
303da5c369Sopenharmony_ci
313da5c369Sopenharmony_ci#[cfg(any(target_os = "linux", target_os = "android"))]
323da5c369Sopenharmony_cimod linux {
333da5c369Sopenharmony_ci    // The cast is not unnecessary on all platforms.
343da5c369Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
353da5c369Sopenharmony_ci    #[test]
363da5c369Sopenharmony_ci    fn test_op_none() {
373da5c369Sopenharmony_ci        if cfg!(any(
383da5c369Sopenharmony_ci            target_arch = "mips",
393da5c369Sopenharmony_ci            target_arch = "mips64",
403da5c369Sopenharmony_ci            target_arch = "powerpc",
413da5c369Sopenharmony_ci            target_arch = "powerpc64"
423da5c369Sopenharmony_ci        )) {
433da5c369Sopenharmony_ci            assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A);
443da5c369Sopenharmony_ci            assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF);
453da5c369Sopenharmony_ci        } else {
463da5c369Sopenharmony_ci            assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A);
473da5c369Sopenharmony_ci            assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF);
483da5c369Sopenharmony_ci        }
493da5c369Sopenharmony_ci    }
503da5c369Sopenharmony_ci
513da5c369Sopenharmony_ci    // The cast is not unnecessary on all platforms.
523da5c369Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
533da5c369Sopenharmony_ci    #[test]
543da5c369Sopenharmony_ci    fn test_op_write() {
553da5c369Sopenharmony_ci        if cfg!(any(
563da5c369Sopenharmony_ci            target_arch = "mips",
573da5c369Sopenharmony_ci            target_arch = "mips64",
583da5c369Sopenharmony_ci            target_arch = "powerpc",
593da5c369Sopenharmony_ci            target_arch = "powerpc64"
603da5c369Sopenharmony_ci        )) {
613da5c369Sopenharmony_ci            assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A);
623da5c369Sopenharmony_ci            assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A);
633da5c369Sopenharmony_ci        } else {
643da5c369Sopenharmony_ci            assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A);
653da5c369Sopenharmony_ci            assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A);
663da5c369Sopenharmony_ci        }
673da5c369Sopenharmony_ci    }
683da5c369Sopenharmony_ci
693da5c369Sopenharmony_ci    #[cfg(target_pointer_width = "64")]
703da5c369Sopenharmony_ci    #[test]
713da5c369Sopenharmony_ci    fn test_op_write_64() {
723da5c369Sopenharmony_ci        if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) {
733da5c369Sopenharmony_ci            assert_eq!(
743da5c369Sopenharmony_ci                request_code_write!(b'z', 10, 1u64 << 32) as u32,
753da5c369Sopenharmony_ci                0x8000_7A0A
763da5c369Sopenharmony_ci            );
773da5c369Sopenharmony_ci        } else {
783da5c369Sopenharmony_ci            assert_eq!(
793da5c369Sopenharmony_ci                request_code_write!(b'z', 10, 1u64 << 32) as u32,
803da5c369Sopenharmony_ci                0x4000_7A0A
813da5c369Sopenharmony_ci            );
823da5c369Sopenharmony_ci        }
833da5c369Sopenharmony_ci    }
843da5c369Sopenharmony_ci
853da5c369Sopenharmony_ci    // The cast is not unnecessary on all platforms.
863da5c369Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
873da5c369Sopenharmony_ci    #[test]
883da5c369Sopenharmony_ci    fn test_op_read() {
893da5c369Sopenharmony_ci        if cfg!(any(
903da5c369Sopenharmony_ci            target_arch = "mips",
913da5c369Sopenharmony_ci            target_arch = "mips64",
923da5c369Sopenharmony_ci            target_arch = "powerpc",
933da5c369Sopenharmony_ci            target_arch = "powerpc64"
943da5c369Sopenharmony_ci        )) {
953da5c369Sopenharmony_ci            assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A);
963da5c369Sopenharmony_ci            assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A);
973da5c369Sopenharmony_ci        } else {
983da5c369Sopenharmony_ci            assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A);
993da5c369Sopenharmony_ci            assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A);
1003da5c369Sopenharmony_ci        }
1013da5c369Sopenharmony_ci    }
1023da5c369Sopenharmony_ci
1033da5c369Sopenharmony_ci    #[cfg(target_pointer_width = "64")]
1043da5c369Sopenharmony_ci    #[test]
1053da5c369Sopenharmony_ci    fn test_op_read_64() {
1063da5c369Sopenharmony_ci        if cfg!(any(target_arch = "mips64", target_arch = "powerpc64")) {
1073da5c369Sopenharmony_ci            assert_eq!(
1083da5c369Sopenharmony_ci                request_code_read!(b'z', 10, 1u64 << 32) as u32,
1093da5c369Sopenharmony_ci                0x4000_7A0A
1103da5c369Sopenharmony_ci            );
1113da5c369Sopenharmony_ci        } else {
1123da5c369Sopenharmony_ci            assert_eq!(
1133da5c369Sopenharmony_ci                request_code_read!(b'z', 10, 1u64 << 32) as u32,
1143da5c369Sopenharmony_ci                0x8000_7A0A
1153da5c369Sopenharmony_ci            );
1163da5c369Sopenharmony_ci        }
1173da5c369Sopenharmony_ci    }
1183da5c369Sopenharmony_ci
1193da5c369Sopenharmony_ci    // The cast is not unnecessary on all platforms.
1203da5c369Sopenharmony_ci    #[allow(clippy::unnecessary_cast)]
1213da5c369Sopenharmony_ci    #[test]
1223da5c369Sopenharmony_ci    fn test_op_read_write() {
1233da5c369Sopenharmony_ci        assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
1243da5c369Sopenharmony_ci        assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A);
1253da5c369Sopenharmony_ci    }
1263da5c369Sopenharmony_ci
1273da5c369Sopenharmony_ci    #[cfg(target_pointer_width = "64")]
1283da5c369Sopenharmony_ci    #[test]
1293da5c369Sopenharmony_ci    fn test_op_read_write_64() {
1303da5c369Sopenharmony_ci        assert_eq!(
1313da5c369Sopenharmony_ci            request_code_readwrite!(b'z', 10, 1u64 << 32) as u32,
1323da5c369Sopenharmony_ci            0xC000_7A0A
1333da5c369Sopenharmony_ci        );
1343da5c369Sopenharmony_ci    }
1353da5c369Sopenharmony_ci}
1363da5c369Sopenharmony_ci
1373da5c369Sopenharmony_ci#[cfg(any(
1383da5c369Sopenharmony_ci    target_os = "dragonfly",
1393da5c369Sopenharmony_ci    target_os = "freebsd",
1403da5c369Sopenharmony_ci    target_os = "ios",
1413da5c369Sopenharmony_ci    target_os = "macos",
1423da5c369Sopenharmony_ci    target_os = "netbsd",
1433da5c369Sopenharmony_ci    target_os = "openbsd"
1443da5c369Sopenharmony_ci))]
1453da5c369Sopenharmony_cimod bsd {
1463da5c369Sopenharmony_ci    #[test]
1473da5c369Sopenharmony_ci    fn test_op_none() {
1483da5c369Sopenharmony_ci        assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
1493da5c369Sopenharmony_ci        assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
1503da5c369Sopenharmony_ci    }
1513da5c369Sopenharmony_ci
1523da5c369Sopenharmony_ci    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
1533da5c369Sopenharmony_ci    #[test]
1543da5c369Sopenharmony_ci    fn test_op_write_int() {
1553da5c369Sopenharmony_ci        assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
1563da5c369Sopenharmony_ci        assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
1573da5c369Sopenharmony_ci    }
1583da5c369Sopenharmony_ci
1593da5c369Sopenharmony_ci    #[test]
1603da5c369Sopenharmony_ci    fn test_op_write() {
1613da5c369Sopenharmony_ci        assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
1623da5c369Sopenharmony_ci        assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
1633da5c369Sopenharmony_ci    }
1643da5c369Sopenharmony_ci
1653da5c369Sopenharmony_ci    #[cfg(target_pointer_width = "64")]
1663da5c369Sopenharmony_ci    #[test]
1673da5c369Sopenharmony_ci    fn test_op_write_64() {
1683da5c369Sopenharmony_ci        assert_eq!(request_code_write!(b'z', 10, 1u64 << 32), 0x8000_7A0A);
1693da5c369Sopenharmony_ci    }
1703da5c369Sopenharmony_ci
1713da5c369Sopenharmony_ci    #[test]
1723da5c369Sopenharmony_ci    fn test_op_read() {
1733da5c369Sopenharmony_ci        assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
1743da5c369Sopenharmony_ci        assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
1753da5c369Sopenharmony_ci    }
1763da5c369Sopenharmony_ci
1773da5c369Sopenharmony_ci    #[cfg(target_pointer_width = "64")]
1783da5c369Sopenharmony_ci    #[test]
1793da5c369Sopenharmony_ci    fn test_op_read_64() {
1803da5c369Sopenharmony_ci        assert_eq!(request_code_read!(b'z', 10, 1u64 << 32), 0x4000_7A0A);
1813da5c369Sopenharmony_ci    }
1823da5c369Sopenharmony_ci
1833da5c369Sopenharmony_ci    #[test]
1843da5c369Sopenharmony_ci    fn test_op_read_write() {
1853da5c369Sopenharmony_ci        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
1863da5c369Sopenharmony_ci        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
1873da5c369Sopenharmony_ci    }
1883da5c369Sopenharmony_ci
1893da5c369Sopenharmony_ci    #[cfg(target_pointer_width = "64")]
1903da5c369Sopenharmony_ci    #[test]
1913da5c369Sopenharmony_ci    fn test_op_read_write_64() {
1923da5c369Sopenharmony_ci        assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32), 0xC000_7A0A);
1933da5c369Sopenharmony_ci    }
1943da5c369Sopenharmony_ci}
1953da5c369Sopenharmony_ci
1963da5c369Sopenharmony_ci#[cfg(any(target_os = "android", target_os = "linux"))]
1973da5c369Sopenharmony_cimod linux_ioctls {
1983da5c369Sopenharmony_ci    use std::mem;
1993da5c369Sopenharmony_ci    use std::os::unix::io::AsRawFd;
2003da5c369Sopenharmony_ci
2013da5c369Sopenharmony_ci    use libc::{termios, TCGETS, TCSBRK, TCSETS, TIOCNXCL};
2023da5c369Sopenharmony_ci    use tempfile::tempfile;
2033da5c369Sopenharmony_ci
2043da5c369Sopenharmony_ci    use nix::errno::Errno;
2053da5c369Sopenharmony_ci
2063da5c369Sopenharmony_ci    ioctl_none_bad!(tiocnxcl, TIOCNXCL);
2073da5c369Sopenharmony_ci    #[test]
2083da5c369Sopenharmony_ci    fn test_ioctl_none_bad() {
2093da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2103da5c369Sopenharmony_ci        let res = unsafe { tiocnxcl(file.as_raw_fd()) };
2113da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
2123da5c369Sopenharmony_ci    }
2133da5c369Sopenharmony_ci
2143da5c369Sopenharmony_ci    ioctl_read_bad!(tcgets, TCGETS, termios);
2153da5c369Sopenharmony_ci    #[test]
2163da5c369Sopenharmony_ci    fn test_ioctl_read_bad() {
2173da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2183da5c369Sopenharmony_ci        let mut termios = unsafe { mem::zeroed() };
2193da5c369Sopenharmony_ci        let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
2203da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
2213da5c369Sopenharmony_ci    }
2223da5c369Sopenharmony_ci
2233da5c369Sopenharmony_ci    ioctl_write_int_bad!(tcsbrk, TCSBRK);
2243da5c369Sopenharmony_ci    #[test]
2253da5c369Sopenharmony_ci    fn test_ioctl_write_int_bad() {
2263da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2273da5c369Sopenharmony_ci        let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
2283da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
2293da5c369Sopenharmony_ci    }
2303da5c369Sopenharmony_ci
2313da5c369Sopenharmony_ci    ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
2323da5c369Sopenharmony_ci    #[test]
2333da5c369Sopenharmony_ci    fn test_ioctl_write_ptr_bad() {
2343da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2353da5c369Sopenharmony_ci        let termios: termios = unsafe { mem::zeroed() };
2363da5c369Sopenharmony_ci        let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
2373da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
2383da5c369Sopenharmony_ci    }
2393da5c369Sopenharmony_ci
2403da5c369Sopenharmony_ci    // FIXME: Find a suitable example for `ioctl_readwrite_bad`
2413da5c369Sopenharmony_ci
2423da5c369Sopenharmony_ci    // From linux/videodev2.h
2433da5c369Sopenharmony_ci    ioctl_none!(log_status, b'V', 70);
2443da5c369Sopenharmony_ci    #[test]
2453da5c369Sopenharmony_ci    fn test_ioctl_none() {
2463da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2473da5c369Sopenharmony_ci        let res = unsafe { log_status(file.as_raw_fd()) };
2483da5c369Sopenharmony_ci        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
2493da5c369Sopenharmony_ci    }
2503da5c369Sopenharmony_ci
2513da5c369Sopenharmony_ci    #[repr(C)]
2523da5c369Sopenharmony_ci    pub struct v4l2_audio {
2533da5c369Sopenharmony_ci        index: u32,
2543da5c369Sopenharmony_ci        name: [u8; 32],
2553da5c369Sopenharmony_ci        capability: u32,
2563da5c369Sopenharmony_ci        mode: u32,
2573da5c369Sopenharmony_ci        reserved: [u32; 2],
2583da5c369Sopenharmony_ci    }
2593da5c369Sopenharmony_ci
2603da5c369Sopenharmony_ci    // From linux/videodev2.h
2613da5c369Sopenharmony_ci    ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
2623da5c369Sopenharmony_ci    #[test]
2633da5c369Sopenharmony_ci    fn test_ioctl_write_ptr() {
2643da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2653da5c369Sopenharmony_ci        let data: v4l2_audio = unsafe { mem::zeroed() };
2663da5c369Sopenharmony_ci        let res = unsafe { s_audio(file.as_raw_fd(), &data) };
2673da5c369Sopenharmony_ci        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
2683da5c369Sopenharmony_ci    }
2693da5c369Sopenharmony_ci
2703da5c369Sopenharmony_ci    // From linux/net/bluetooth/hci_sock.h
2713da5c369Sopenharmony_ci    const HCI_IOC_MAGIC: u8 = b'H';
2723da5c369Sopenharmony_ci    const HCI_IOC_HCIDEVUP: u8 = 201;
2733da5c369Sopenharmony_ci    ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
2743da5c369Sopenharmony_ci    #[test]
2753da5c369Sopenharmony_ci    fn test_ioctl_write_int() {
2763da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2773da5c369Sopenharmony_ci        let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
2783da5c369Sopenharmony_ci        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
2793da5c369Sopenharmony_ci    }
2803da5c369Sopenharmony_ci
2813da5c369Sopenharmony_ci    // From linux/videodev2.h
2823da5c369Sopenharmony_ci    ioctl_read!(g_audio, b'V', 33, v4l2_audio);
2833da5c369Sopenharmony_ci    #[test]
2843da5c369Sopenharmony_ci    fn test_ioctl_read() {
2853da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2863da5c369Sopenharmony_ci        let mut data: v4l2_audio = unsafe { mem::zeroed() };
2873da5c369Sopenharmony_ci        let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
2883da5c369Sopenharmony_ci        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
2893da5c369Sopenharmony_ci    }
2903da5c369Sopenharmony_ci
2913da5c369Sopenharmony_ci    // From linux/videodev2.h
2923da5c369Sopenharmony_ci    ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
2933da5c369Sopenharmony_ci    #[test]
2943da5c369Sopenharmony_ci    fn test_ioctl_readwrite() {
2953da5c369Sopenharmony_ci        let file = tempfile().unwrap();
2963da5c369Sopenharmony_ci        let mut data: v4l2_audio = unsafe { mem::zeroed() };
2973da5c369Sopenharmony_ci        let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
2983da5c369Sopenharmony_ci        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
2993da5c369Sopenharmony_ci    }
3003da5c369Sopenharmony_ci
3013da5c369Sopenharmony_ci    // FIXME: Find a suitable example for `ioctl_read_buf`.
3023da5c369Sopenharmony_ci
3033da5c369Sopenharmony_ci    #[repr(C)]
3043da5c369Sopenharmony_ci    pub struct spi_ioc_transfer {
3053da5c369Sopenharmony_ci        tx_buf: u64,
3063da5c369Sopenharmony_ci        rx_buf: u64,
3073da5c369Sopenharmony_ci        len: u32,
3083da5c369Sopenharmony_ci        speed_hz: u32,
3093da5c369Sopenharmony_ci        delay_usecs: u16,
3103da5c369Sopenharmony_ci        bits_per_word: u8,
3113da5c369Sopenharmony_ci        cs_change: u8,
3123da5c369Sopenharmony_ci        tx_nbits: u8,
3133da5c369Sopenharmony_ci        rx_nbits: u8,
3143da5c369Sopenharmony_ci        pad: u16,
3153da5c369Sopenharmony_ci    }
3163da5c369Sopenharmony_ci
3173da5c369Sopenharmony_ci    // From linux/spi/spidev.h
3183da5c369Sopenharmony_ci    ioctl_write_buf!(
3193da5c369Sopenharmony_ci        spi_ioc_message,
3203da5c369Sopenharmony_ci        super::SPI_IOC_MAGIC,
3213da5c369Sopenharmony_ci        super::SPI_IOC_MESSAGE,
3223da5c369Sopenharmony_ci        spi_ioc_transfer
3233da5c369Sopenharmony_ci    );
3243da5c369Sopenharmony_ci    #[test]
3253da5c369Sopenharmony_ci    fn test_ioctl_write_buf() {
3263da5c369Sopenharmony_ci        let file = tempfile().unwrap();
3273da5c369Sopenharmony_ci        let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
3283da5c369Sopenharmony_ci        let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
3293da5c369Sopenharmony_ci        assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
3303da5c369Sopenharmony_ci    }
3313da5c369Sopenharmony_ci
3323da5c369Sopenharmony_ci    // FIXME: Find a suitable example for `ioctl_readwrite_buf`.
3333da5c369Sopenharmony_ci}
3343da5c369Sopenharmony_ci
3353da5c369Sopenharmony_ci#[cfg(target_os = "freebsd")]
3363da5c369Sopenharmony_cimod freebsd_ioctls {
3373da5c369Sopenharmony_ci    use std::mem;
3383da5c369Sopenharmony_ci    use std::os::unix::io::AsRawFd;
3393da5c369Sopenharmony_ci
3403da5c369Sopenharmony_ci    use libc::termios;
3413da5c369Sopenharmony_ci    use tempfile::tempfile;
3423da5c369Sopenharmony_ci
3433da5c369Sopenharmony_ci    use nix::errno::Errno;
3443da5c369Sopenharmony_ci
3453da5c369Sopenharmony_ci    // From sys/sys/ttycom.h
3463da5c369Sopenharmony_ci    const TTY_IOC_MAGIC: u8 = b't';
3473da5c369Sopenharmony_ci    const TTY_IOC_TYPE_NXCL: u8 = 14;
3483da5c369Sopenharmony_ci    const TTY_IOC_TYPE_GETA: u8 = 19;
3493da5c369Sopenharmony_ci    const TTY_IOC_TYPE_SETA: u8 = 20;
3503da5c369Sopenharmony_ci
3513da5c369Sopenharmony_ci    ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL);
3523da5c369Sopenharmony_ci    #[test]
3533da5c369Sopenharmony_ci    fn test_ioctl_none() {
3543da5c369Sopenharmony_ci        let file = tempfile().unwrap();
3553da5c369Sopenharmony_ci        let res = unsafe { tiocnxcl(file.as_raw_fd()) };
3563da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
3573da5c369Sopenharmony_ci    }
3583da5c369Sopenharmony_ci
3593da5c369Sopenharmony_ci    ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
3603da5c369Sopenharmony_ci    #[test]
3613da5c369Sopenharmony_ci    fn test_ioctl_read() {
3623da5c369Sopenharmony_ci        let file = tempfile().unwrap();
3633da5c369Sopenharmony_ci        let mut termios = unsafe { mem::zeroed() };
3643da5c369Sopenharmony_ci        let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
3653da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
3663da5c369Sopenharmony_ci    }
3673da5c369Sopenharmony_ci
3683da5c369Sopenharmony_ci    ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
3693da5c369Sopenharmony_ci    #[test]
3703da5c369Sopenharmony_ci    fn test_ioctl_write_ptr() {
3713da5c369Sopenharmony_ci        let file = tempfile().unwrap();
3723da5c369Sopenharmony_ci        let termios: termios = unsafe { mem::zeroed() };
3733da5c369Sopenharmony_ci        let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
3743da5c369Sopenharmony_ci        assert_eq!(res, Err(Errno::ENOTTY));
3753da5c369Sopenharmony_ci    }
3763da5c369Sopenharmony_ci}
377