• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(dead_code)]
2 
3 // Simple tests to ensure macro generated fns compile
4 ioctl_none_bad!(do_bad, 0x1234);
5 ioctl_read_bad!(do_bad_read, 0x1234, u16);
6 ioctl_write_int_bad!(do_bad_write_int, 0x1234);
7 ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8);
8 ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32);
9 ioctl_none!(do_none, 0, 0);
10 ioctl_read!(read_test, 0, 0, u32);
11 ioctl_write_int!(write_ptr_int, 0, 0);
12 ioctl_write_ptr!(write_ptr_u8, 0, 0, u8);
13 ioctl_write_ptr!(write_ptr_u32, 0, 0, u32);
14 ioctl_write_ptr!(write_ptr_u64, 0, 0, u64);
15 ioctl_readwrite!(readwrite_test, 0, 0, u64);
16 ioctl_read_buf!(readbuf_test, 0, 0, u32);
17 const SPI_IOC_MAGIC: u8 = b'k';
18 const SPI_IOC_MESSAGE: u8 = 0;
19 ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8);
20 ioctl_write_buf!(writebuf_test_u8, 0, 0, u8);
21 ioctl_write_buf!(writebuf_test_u32, 0, 0, u32);
22 ioctl_write_buf!(writebuf_test_u64, 0, 0, u64);
23 ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
24 
25 // See C code for source of values for op calculations (does NOT work for mips/powerpc):
26 // https://gist.github.com/posborne/83ea6880770a1aef332e
27 //
28 // TODO:  Need a way to compute these constants at test time.  Using precomputed
29 // values is fragile and needs to be maintained.
30 
31 #[cfg(any(target_os = "linux", target_os = "android"))]
32 mod linux {
33     #[test]
test_op_none()34     fn test_op_none() {
35         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
36             assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A);
37             assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF);
38         } else {
39             assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A);
40             assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF);
41         }
42     }
43 
44     #[test]
test_op_write()45     fn test_op_write() {
46         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
47             assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A);
48             assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A);
49         } else {
50             assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A);
51             assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A);
52         }
53     }
54 
55     #[cfg(target_pointer_width = "64")]
56     #[test]
test_op_write_64()57     fn test_op_write_64() {
58         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
59             assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32,
60                        0x8000_7A0A);
61         } else {
62             assert_eq!(request_code_write!(b'z', 10, 1u64 << 32) as u32,
63                        0x4000_7A0A);
64         }
65 
66     }
67 
68     #[test]
test_op_read()69     fn test_op_read() {
70         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
71             assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A);
72             assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A);
73         } else {
74             assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A);
75             assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A);
76         }
77     }
78 
79     #[cfg(target_pointer_width = "64")]
80     #[test]
test_op_read_64()81     fn test_op_read_64() {
82         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
83             assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32,
84                        0x4000_7A0A);
85         } else {
86             assert_eq!(request_code_read!(b'z', 10, 1u64 << 32) as u32,
87                        0x8000_7A0A);
88         }
89     }
90 
91     #[test]
test_op_read_write()92     fn test_op_read_write() {
93         assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
94         assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A);
95     }
96 
97     #[cfg(target_pointer_width = "64")]
98     #[test]
test_op_read_write_64()99     fn test_op_read_write_64() {
100         assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32) as u32,
101                    0xC000_7A0A);
102     }
103 }
104 
105 #[cfg(any(target_os = "dragonfly",
106           target_os = "freebsd",
107           target_os = "ios",
108           target_os = "macos",
109           target_os = "netbsd",
110           target_os = "openbsd"))]
111 mod bsd {
112     #[test]
test_op_none()113     fn test_op_none() {
114         assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
115         assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
116     }
117 
118     #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
119     #[test]
test_op_write_int()120     fn test_op_write_int() {
121         assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
122         assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
123     }
124 
125     #[test]
test_op_write()126     fn test_op_write() {
127         assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
128         assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
129     }
130 
131     #[cfg(target_pointer_width = "64")]
132     #[test]
test_op_write_64()133     fn test_op_write_64() {
134         assert_eq!(request_code_write!(b'z', 10, 1u64 << 32), 0x8000_7A0A);
135     }
136 
137     #[test]
test_op_read()138     fn test_op_read() {
139         assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
140         assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
141     }
142 
143     #[cfg(target_pointer_width = "64")]
144     #[test]
test_op_read_64()145     fn test_op_read_64() {
146         assert_eq!(request_code_read!(b'z', 10, 1u64 << 32), 0x4000_7A0A);
147     }
148 
149     #[test]
test_op_read_write()150     fn test_op_read_write() {
151         assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
152         assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
153     }
154 
155     #[cfg(target_pointer_width = "64")]
156     #[test]
test_op_read_write_64()157     fn test_op_read_write_64() {
158         assert_eq!(request_code_readwrite!(b'z', 10, 1u64 << 32), 0xC000_7A0A);
159     }
160 }
161 
162 #[cfg(any(target_os = "android", target_os = "linux"))]
163 mod linux_ioctls {
164     use std::mem;
165     use std::os::unix::io::AsRawFd;
166 
167     use tempfile::tempfile;
168     use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios};
169 
170     use nix::errno::Errno;
171 
172     ioctl_none_bad!(tiocnxcl, TIOCNXCL);
173     #[test]
test_ioctl_none_bad()174     fn test_ioctl_none_bad() {
175         let file = tempfile().unwrap();
176         let res = unsafe { tiocnxcl(file.as_raw_fd()) };
177         assert_eq!(res, Err(Errno::ENOTTY));
178     }
179 
180     ioctl_read_bad!(tcgets, TCGETS, termios);
181     #[test]
test_ioctl_read_bad()182     fn test_ioctl_read_bad() {
183         let file = tempfile().unwrap();
184         let mut termios = unsafe { mem::zeroed() };
185         let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
186         assert_eq!(res, Err(Errno::ENOTTY));
187     }
188 
189     ioctl_write_int_bad!(tcsbrk, TCSBRK);
190     #[test]
test_ioctl_write_int_bad()191     fn test_ioctl_write_int_bad() {
192         let file = tempfile().unwrap();
193         let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
194         assert_eq!(res, Err(Errno::ENOTTY));
195     }
196 
197     ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
198     #[test]
test_ioctl_write_ptr_bad()199     fn test_ioctl_write_ptr_bad() {
200         let file = tempfile().unwrap();
201         let termios: termios = unsafe { mem::zeroed() };
202         let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
203         assert_eq!(res, Err(Errno::ENOTTY));
204     }
205 
206     // FIXME: Find a suitable example for `ioctl_readwrite_bad`
207 
208     // From linux/videodev2.h
209     ioctl_none!(log_status, b'V', 70);
210     #[test]
test_ioctl_none()211     fn test_ioctl_none() {
212         let file = tempfile().unwrap();
213         let res = unsafe { log_status(file.as_raw_fd()) };
214         assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
215     }
216 
217     #[repr(C)]
218     pub struct v4l2_audio {
219         index: u32,
220         name: [u8; 32],
221         capability: u32,
222         mode: u32,
223         reserved: [u32; 2],
224     }
225 
226     // From linux/videodev2.h
227     ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
228     #[test]
test_ioctl_write_ptr()229     fn test_ioctl_write_ptr() {
230         let file = tempfile().unwrap();
231         let data: v4l2_audio = unsafe { mem::zeroed() };
232         let res = unsafe { s_audio(file.as_raw_fd(), &data) };
233         assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
234     }
235 
236     // From linux/net/bluetooth/hci_sock.h
237     const HCI_IOC_MAGIC: u8 = b'H';
238     const HCI_IOC_HCIDEVUP: u8 = 201;
239     ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
240     #[test]
test_ioctl_write_int()241     fn test_ioctl_write_int() {
242         let file = tempfile().unwrap();
243         let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
244         assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
245     }
246 
247     // From linux/videodev2.h
248     ioctl_read!(g_audio, b'V', 33, v4l2_audio);
249     #[test]
test_ioctl_read()250     fn test_ioctl_read() {
251         let file = tempfile().unwrap();
252         let mut data: v4l2_audio = unsafe { mem::zeroed() };
253         let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
254         assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
255     }
256 
257     // From linux/videodev2.h
258     ioctl_readwrite!(enum_audio,  b'V', 65, v4l2_audio);
259     #[test]
test_ioctl_readwrite()260     fn test_ioctl_readwrite() {
261         let file = tempfile().unwrap();
262         let mut data: v4l2_audio = unsafe { mem::zeroed() };
263         let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
264         assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
265     }
266 
267     // FIXME: Find a suitable example for `ioctl_read_buf`.
268 
269     #[repr(C)]
270     pub struct spi_ioc_transfer {
271         tx_buf: u64,
272         rx_buf: u64,
273         len: u32,
274         speed_hz: u32,
275         delay_usecs: u16,
276         bits_per_word: u8,
277         cs_change: u8,
278         tx_nbits: u8,
279         rx_nbits: u8,
280         pad: u16,
281     }
282 
283     // From linux/spi/spidev.h
284     ioctl_write_buf!(spi_ioc_message, super::SPI_IOC_MAGIC, super::SPI_IOC_MESSAGE, spi_ioc_transfer);
285     #[test]
test_ioctl_write_buf()286     fn test_ioctl_write_buf() {
287         let file = tempfile().unwrap();
288         let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
289         let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
290         assert!(res == Err(Errno::ENOTTY) || res == Err(Errno::ENOSYS));
291     }
292 
293     // FIXME: Find a suitable example for `ioctl_readwrite_buf`.
294 }
295 
296 #[cfg(target_os = "freebsd")]
297 mod freebsd_ioctls {
298     use std::mem;
299     use std::os::unix::io::AsRawFd;
300 
301     use tempfile::tempfile;
302     use libc::termios;
303 
304     use nix::errno::Errno;
305 
306     // From sys/sys/ttycom.h
307     const TTY_IOC_MAGIC: u8 = b't';
308     const TTY_IOC_TYPE_NXCL: u8 = 14;
309     const TTY_IOC_TYPE_GETA: u8 = 19;
310     const TTY_IOC_TYPE_SETA: u8 = 20;
311 
312     ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL);
313     #[test]
test_ioctl_none()314     fn test_ioctl_none() {
315         let file = tempfile().unwrap();
316         let res = unsafe { tiocnxcl(file.as_raw_fd()) };
317         assert_eq!(res, Err(Errno::ENOTTY));
318     }
319 
320     ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
321     #[test]
test_ioctl_read()322     fn test_ioctl_read() {
323         let file = tempfile().unwrap();
324         let mut termios = unsafe { mem::zeroed() };
325         let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
326         assert_eq!(res, Err(Errno::ENOTTY));
327     }
328 
329     ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
330     #[test]
test_ioctl_write_ptr()331     fn test_ioctl_write_ptr() {
332         let file = tempfile().unwrap();
333         let termios: termios = unsafe { mem::zeroed() };
334         let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
335         assert_eq!(res, Err(Errno::ENOTTY));
336     }
337 }
338