1use std::fmt;
2use std::ptr;
3
4use std::ffi::OsStr;
5use std::io::Result;
6use std::ops::Deref;
7use std::os::unix::io::{AsRawFd, RawFd};
8
9use io_lifetimes::{AsFd, BorrowedFd};
10#[cfg(feature = "mio06")]
11use mio::{event::Evented, unix::EventedFd, Poll, PollOpt, Ready, Token};
12#[cfg(any(feature = "mio07", feature = "mio08", feature = "mio10"))]
13use mio::{event::Source, unix::SourceFd, Interest, Registry, Token};
14
15use Udev;
16use {ffi, util};
17
18use {AsRaw, AsRawWithContext, Device, FromRaw};
19
20pub struct Builder {
26 udev: Udev,
27 monitor: *mut ffi::udev_monitor,
28}
29
30impl Clone for Builder {
31 fn clone(&self) -> Self {
32 Self {
33 udev: self.udev.clone(),
34 monitor: unsafe { ffi::udev_monitor_ref(self.monitor) },
35 }
36 }
37}
38
39impl Drop for Builder {
40 fn drop(&mut self) {
41 unsafe {
42 ffi::udev_monitor_unref(self.monitor);
43 }
44 }
45}
46
47#[cfg(feature = "send")]
48unsafe impl Send for Builder {}
49#[cfg(feature = "sync")]
50unsafe impl Sync for Builder {}
51
52as_ffi_with_context!(Builder, monitor, ffi::udev_monitor, ffi::udev_monitor_ref);
53
54pub(crate) enum EventSource {
56 Udev,
57 Kernel,
58}
59
60impl Builder {
61 pub fn new() -> Result<Self> {
63 Self::with_udev(Udev::new()?)
67 }
68
69 pub fn new_kernel() -> Result<Self> {
71 Self::with_kernel(Udev::new()?)
72 }
73
74 pub(crate) fn with_udev(udev: Udev) -> Result<Self> {
76 Self::with_source(udev, EventSource::Udev)
77 }
78
79 pub(crate) fn with_kernel(udev: Udev) -> Result<Self> {
81 Self::with_source(udev, EventSource::Kernel)
82 }
83
84 pub(crate) fn with_source(udev: Udev, source: EventSource) -> Result<Self> {
86 let name = match source {
87 EventSource::Udev => b"udev\0".as_ptr() as *const libc::c_char,
88 EventSource::Kernel => b"kernel\0".as_ptr() as *const libc::c_char,
89 };
90
91 let ptr = try_alloc!(unsafe { ffi::udev_monitor_new_from_netlink(udev.as_raw(), name) });
92
93 Ok(Self { udev, monitor: ptr })
94 }
95
96 pub fn match_subsystem<T: AsRef<OsStr>>(self, subsystem: T) -> Result<Self> {
98 let subsystem = util::os_str_to_cstring(subsystem)?;
99
100 util::errno_to_result(unsafe {
101 ffi::udev_monitor_filter_add_match_subsystem_devtype(
102 self.monitor,
103 subsystem.as_ptr(),
104 ptr::null(),
105 )
106 })
107 .and(Ok(self))
108 }
109
110 pub fn match_subsystem_devtype<T: AsRef<OsStr>, U: AsRef<OsStr>>(
112 self,
113 subsystem: T,
114 devtype: U,
115 ) -> Result<Self> {
116 let subsystem = util::os_str_to_cstring(subsystem)?;
117 let devtype = util::os_str_to_cstring(devtype)?;
118
119 util::errno_to_result(unsafe {
120 ffi::udev_monitor_filter_add_match_subsystem_devtype(
121 self.monitor,
122 subsystem.as_ptr(),
123 devtype.as_ptr(),
124 )
125 })
126 .and(Ok(self))
127 }
128
129 pub fn match_tag<T: AsRef<OsStr>>(self, tag: T) -> Result<Self> {
131 let tag = util::os_str_to_cstring(tag)?;
132
133 util::errno_to_result(unsafe {
134 ffi::udev_monitor_filter_add_match_tag(self.monitor, tag.as_ptr())
135 })
136 .and(Ok(self))
137 }
138
139 pub fn clear_filters(self) -> Result<Self> {
141 util::errno_to_result(unsafe { ffi::udev_monitor_filter_remove(self.monitor) })
142 .and(Ok(self))
143 }
144
145 pub fn listen(self) -> Result<Socket> {
149 util::errno_to_result(unsafe { ffi::udev_monitor_enable_receiving(self.monitor) })?;
150
151 Ok(Socket { inner: self })
152 }
153}
154
155impl AsRawFd for Builder {
157 fn as_raw_fd(&self) -> RawFd {
159 unsafe { ffi::udev_monitor_get_fd(self.monitor) }
160 }
161}
162
163impl AsFd for Builder {
165 fn as_fd(&self) -> BorrowedFd<'_> {
167 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
168 }
169}
170
171pub struct Socket {
180 inner: Builder,
181}
182
183impl Socket {
184 pub fn iter(&self) -> SocketIter {
186 SocketIter::new(&self)
187 }
188}
189
190impl AsRaw<ffi::udev_monitor> for Socket {
191 fn as_raw(&self) -> *mut ffi::udev_monitor {
192 self.inner.monitor
193 }
194
195 fn into_raw(self) -> *mut ffi::udev_monitor {
196 self.inner.monitor
197 }
198}
199
200impl AsRawFd for Socket {
202 fn as_raw_fd(&self) -> RawFd {
204 self.inner.as_raw_fd()
205 }
206}
207
208impl AsFd for Socket {
210 fn as_fd(&self) -> BorrowedFd<'_> {
212 self.inner.as_fd()
213 }
214}
215
216pub struct SocketIter<'a> {
218 socket: &'a Socket,
219}
220
221impl<'a> SocketIter<'a> {
222 fn new(socket: &'a Socket) -> SocketIter<'a> {
224 SocketIter { socket }
225 }
226}
227
228impl<'a> Iterator for SocketIter<'a> {
229 type Item = Event;
230
231 fn next(&mut self) -> Option<Event> {
232 let ptr = unsafe { ffi::udev_monitor_receive_device(self.socket.inner.monitor) };
233
234 if ptr.is_null() {
235 None
236 } else {
237 let device = Device::from_raw(self.socket.inner.udev.clone(), ptr);
238 Some(Event { device })
239 }
240 }
241}
242
243#[derive(Debug, Clone, Copy, PartialEq, Eq)]
245pub enum EventType {
246 Add,
248
249 Change,
251
252 Remove,
254
255 Bind,
257
258 Unbind,
260
261 Unknown,
263}
264
265impl Default for EventType {
266 fn default() -> Self {
267 EventType::Unknown
268 }
269}
270
271impl fmt::Display for EventType {
272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273 f.write_str(match *self {
274 EventType::Add => "add",
275 EventType::Change => "change",
276 EventType::Remove => "remove",
277 EventType::Bind => "bind",
278 EventType::Unbind => "unbind",
279 EventType::Unknown => "unknown",
280 })
281 }
282}
283
284pub struct Event {
286 device: Device,
287}
288
289impl std::fmt::Debug for Event {
290 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
291 f.debug_struct("Event")
292 .field("device", &self.device())
293 .field("event_type", &self.event_type())
294 .field("sequence_number", &self.sequence_number())
295 .finish()
296 }
297}
298
299impl Deref for Event {
301 type Target = Device;
302
303 fn deref(&self) -> &Device {
304 &self.device
305 }
306}
307
308impl Event {
309 pub fn event_type(&self) -> EventType {
311 let value = match self.device.property_value("ACTION") {
312 Some(s) => s.to_str(),
313 None => None,
314 };
315
316 match value {
317 Some("add") => EventType::Add,
318 Some("change") => EventType::Change,
319 Some("remove") => EventType::Remove,
320 Some("bind") => EventType::Bind,
321 Some("unbind") => EventType::Unbind,
322 _ => EventType::Unknown,
323 }
324 }
325
326 pub fn sequence_number(&self) -> u64 {
328 unsafe { ffi::udev_device_get_seqnum(self.device.as_raw()) as u64 }
329 }
330
331 pub fn device(&self) -> Device {
333 self.device.clone()
334 }
335}
336
337#[cfg(feature = "mio06")]
338impl Evented for Socket {
339 fn register(
340 &self,
341 poll: &Poll,
342 token: Token,
343 interest: Ready,
344 opts: PollOpt,
345 ) -> std::io::Result<()> {
346 EventedFd(&self.as_raw_fd()).register(poll, token, interest, opts)
347 }
348
349 fn reregister(
350 &self,
351 poll: &Poll,
352 token: Token,
353 interest: Ready,
354 opts: PollOpt,
355 ) -> std::io::Result<()> {
356 EventedFd(&self.as_raw_fd()).reregister(poll, token, interest, opts)
357 }
358
359 fn deregister(&self, poll: &Poll) -> std::io::Result<()> {
360 EventedFd(&self.as_raw_fd()).deregister(poll)
361 }
362}
363
364#[cfg(any(feature = "mio07", feature = "mio08", feature = "mio10"))]
365impl Source for Socket {
366 fn register(
367 &mut self,
368 registry: &Registry,
369 token: Token,
370 interest: Interest,
371 ) -> std::io::Result<()> {
372 SourceFd(&self.as_raw_fd()).register(registry, token, interest)
373 }
374
375 fn reregister(
376 &mut self,
377 registry: &Registry,
378 token: Token,
379 interest: Interest,
380 ) -> std::io::Result<()> {
381 SourceFd(&self.as_raw_fd()).reregister(registry, token, interest)
382 }
383
384 fn deregister(&mut self, registry: &Registry) -> std::io::Result<()> {
385 SourceFd(&self.as_raw_fd()).deregister(registry)
386 }
387}