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
20/// Monitors for device events.
21///
22/// A monitor communicates with the kernel over a socket. Filtering events is performed efficiently
23/// in the kernel, and only events that match the filters are received by the socket. Filters must
24/// be set up before listening for events.
25pub 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
54/// The event source to monitor.
55pub(crate) enum EventSource {
56 Udev,
57 Kernel,
58}
59
60impl Builder {
61 /// Creates a new udev event `Monitor`.
62 pub fn new() -> Result<Self> {
63 // Create a new Udev context for this monitor
64 // It would be more efficient to allow callers to create just one context and use multiple
65 // monitors, however that would be an API-breaking change.
66 Self::with_udev(Udev::new()?)
67 }
68
69 /// Creates a new kernel event `Monitor`.
70 pub fn new_kernel() -> Result<Self> {
71 Self::with_kernel(Udev::new()?)
72 }
73
74 /// Creates a new `Monitor` using an existing `Udev` instance
75 pub(crate) fn with_udev(udev: Udev) -> Result<Self> {
76 Self::with_source(udev, EventSource::Udev)
77 }
78
79 /// Creates a new kernel event `Monitor` using an existing `Udev` instance.
80 pub(crate) fn with_kernel(udev: Udev) -> Result<Self> {
81 Self::with_source(udev, EventSource::Kernel)
82 }
83
84 /// Creates a `Monitor` for the given source, using an existing `Udev` instance.
85 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 /// Adds a filter that matches events for devices with the given subsystem.
97 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 /// Adds a filter that matches events for devices with the given subsystem and device type.
111 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 /// Adds a filter that matches events for devices with the given tag.
130 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 /// Removes all filters currently set on the monitor.
140 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 /// Listens for events matching the current filters.
146 ///
147 /// This method consumes the `Monitor`.
148 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
155/// Provides raw access to the monitor's socket.
156impl AsRawFd for Builder {
157 /// Returns the file descriptor of the monitor's socket.
158 fn as_raw_fd(&self) -> RawFd {
159 unsafe { ffi::udev_monitor_get_fd(self.monitor) }
160 }
161}
162
163/// Provides raw access to the monitor's socket.
164impl AsFd for Builder {
165 /// Returns the file descriptor of the monitor's socket.
166 fn as_fd(&self) -> BorrowedFd<'_> {
167 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
168 }
169}
170
171/// An active monitor that can receive events.
172///
173/// The events received by a `Socket` match the filters set up by the `Monitor` that created
174/// the socket.
175///
176/// Monitors are initially set up to receive events from the kernel via a nonblocking socket. A
177/// variant of `poll()` should be used on the file descriptor returned by the `AsRawFd` trait to
178/// wait for new events.
179pub struct Socket {
180 inner: Builder,
181}
182
183impl Socket {
184 /// Create an iterator of socket event messages
185 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
200/// Provides raw access to the monitor's socket.
201impl AsRawFd for Socket {
202 /// Returns the file descriptor of the monitor's socket.
203 fn as_raw_fd(&self) -> RawFd {
204 self.inner.as_raw_fd()
205 }
206}
207
208/// Provides raw access to the monitor's socket.
209impl AsFd for Socket {
210 /// Returns the file descriptor of the monitor's socket.
211 fn as_fd(&self) -> BorrowedFd<'_> {
212 self.inner.as_fd()
213 }
214}
215
216/// Iterator of socket events
217pub struct SocketIter<'a> {
218 socket: &'a Socket,
219}
220
221impl<'a> SocketIter<'a> {
222 /// Create a socket by cloning the underlying udev instance
223 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: *mut udev_device = unsafe { ffi::udev_monitor_receive_device(self.socket.inner.monitor) };
233
234 if ptr.is_null() {
235 None
236 } else {
237 let device: Device = Device::from_raw(self.socket.inner.udev.clone(), ptr);
238 Some(Event { device })
239 }
240 }
241}
242
243/// Types of events that can be received from udev.
244#[derive(Debug, Clone, Copy, PartialEq, Eq)]
245pub enum EventType {
246 /// A device was added.
247 Add,
248
249 /// A device changed.
250 Change,
251
252 /// A device was removed.
253 Remove,
254
255 /// A device was bound to a driver.
256 Bind,
257
258 /// A device was unbound from a driver.
259 Unbind,
260
261 /// An unknown event occurred.
262 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(data: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
284/// An event that indicates a change in device state.
285pub 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&mut DebugStruct<'_, '_>.debug_struct("Event")
292 .field("device", &self.device())
293 .field("event_type", &self.event_type())
294 .field(name:"sequence_number", &self.sequence_number())
295 .finish()
296 }
297}
298
299/// Provides access to the device associated with the event.
300impl Deref for Event {
301 type Target = Device;
302
303 fn deref(&self) -> &Device {
304 &self.device
305 }
306}
307
308impl Event {
309 /// Returns the `EventType` corresponding to this event.
310 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 /// Returns the event's sequence number.
327 pub fn sequence_number(&self) -> u64 {
328 unsafe { ffi::udev_device_get_seqnum(self.device.as_raw()) as u64 }
329 }
330
331 /// Returns the device associated with this event.
332 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}
388