1use std::fmt;
2use std::io;
3use std::os::fd::{AsRawFd, RawFd};
4use std::path::PathBuf;
5
6pub type Result<T> = std::result::Result<T, Error>;
7
8#[derive(Debug)]
9pub enum Error {
10 Io { source: io::Error, path: PathBuf },
12 FileNotFound { path: PathBuf, source: io::Error },
14 Ioctl {
17 fd: RawFd,
18 code: io::Error,
19 api: libc::c_ulong,
20 },
21 NotSupportedIoctl {
23 fd: RawFd,
24 code: libc::c_int,
25 api: libc::c_ulong,
26 },
27 DeviceIsBusy {
29 fd: RawFd,
30 code: libc::c_int,
31 api: libc::c_ulong,
32 },
33 RequestIsAlreadyQueued {
35 fd: RawFd,
36 code: libc::c_int,
37 api: libc::c_ulong,
38 },
39 RequestNotContainBuffers {
41 fd: RawFd,
42 code: libc::c_int,
43 api: libc::c_ulong,
44 },
45 OutOfMemory {
47 fd: RawFd,
48 code: libc::c_int,
49 api: libc::c_ulong,
50 },
51 RequestHasInvalidData {
53 fd: RawFd,
54 code: libc::c_int,
55 api: libc::c_ulong,
56 },
57 HardwareBadState {
59 fd: RawFd,
60 code: libc::c_int,
61 api: libc::c_ulong,
62 },
63 InterfaceTypeParseError { from: u32 },
65 EntityFunctionsParseError { from: u32 },
67 EntityFlagsParseError { from: u32 },
69 PadFlagsParseError { from: u32 },
71 LinkFlagsParseError { from: u32 },
73}
74
75impl Error {
76 pub fn ioctl_error<F>(fd: F, code: libc::c_int, api: libc::c_ulong) -> Error
86 where
87 F: AsRawFd,
88 {
89 use Error::*;
90 let fd = fd.as_raw_fd();
91 match code {
92 libc::EBUSY => DeviceIsBusy { fd, code, api },
93 libc::ENOTTY => NotSupportedIoctl { fd, code, api },
94 _ => Ioctl {
95 fd,
96 code: io::Error::from_raw_os_error(code),
97 api,
98 },
99 }
100 }
101}
102
103impl fmt::Display for Error {
104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
105 use Error::*;
106 match self {
107 Io { path, .. } => write!(f, "io error: {}", path.display()),
108 FileNotFound { path, .. } => write!(f, "file not found: {}", path.display()),
109 Ioctl { fd, code, api } => {
110 write!(f, "generic ioctl error {}: 0x{:02X}: {}", fd, api, code)
111 }
112 NotSupportedIoctl { fd, code, api } => write!(
113 f,
114 "the ioctl is not supported by the file descriptor {}: 0x{:02X}: {}",
115 fd, api, code
116 ),
117 DeviceIsBusy { fd, code, api } => {
118 write!(f, "the device is busy {}: 0x{:02X}: {}", fd, api, code)
119 }
120 RequestIsAlreadyQueued { fd, code, api } => {
121 write!(
122 f,
123 "the request is already queued {}: 0x{:02X}: {}",
124 fd, api, code
125 )
126 }
127 RequestNotContainBuffers { fd, code, api } => {
128 write!(
129 f,
130 "the request did not contain any buffers {}: 0x{:02X}: {}",
131 fd, api, code
132 )
133 }
134 OutOfMemory { fd, code, api } => {
135 write!(f, "Out of memory when allocating internal data structures for this request. {}: 0x{:02X}: {}", fd, api, code)
136 }
137 RequestHasInvalidData { fd, code, api } => {
138 write!(
139 f,
140 "The request has invalid data. {}: 0x{:02X}: {}",
141 fd, api, code
142 )
143 }
144 HardwareBadState { fd, code, api } => {
145 write!(f, "The hardware is in a bad state. To recover, the application needs to stop streaming to reset the hardware state and then try to restart streaming. {}: 0x{:02X}: {}", fd, api, code)
146 }
147 InterfaceTypeParseError { from, .. } => {
148 write!(f, "interface type parse error: {}", from)
149 }
150 EntityFunctionsParseError { from, .. } => {
151 write!(f, "entity functions parse error: {}", from)
152 }
153 EntityFlagsParseError { from, .. } => {
154 write!(f, "entity flags parse error: {}", from)
155 }
156 PadFlagsParseError { from, .. } => {
157 write!(f, "pad flags parse error: {}", from)
158 }
159 LinkFlagsParseError { from, .. } => {
160 write!(f, "link flags parse error: {}", from)
161 }
162 }
163 }
164}
165
166pub fn trap_io_error(err: io::Error, path: PathBuf) -> Error {
167 use io::ErrorKind::*;
168 match err.kind() {
169 NotFound => Error::FileNotFound { path, source: err },
170 _ => Error::Io { source: err, path },
171 }
172}
173
174#[cfg(test)]
175pub mod test {
176 use super::*;
177
178 #[test]
180 fn enotty_is_not_supported() {
181 use Error::*;
182 let err = NotSupportedIoctl {
183 fd: 0,
184 code: libc::ENOTTY,
185 api: 0,
186 };
187 assert!(matches!(
188 err,
189 NotSupportedIoctl {
190 code: libc::ENOTTY,
191 ..
192 }
193 ));
194 }
195}