1use std::fmt;
2use std::ptr;
3
4use std::ffi::OsStr;
5use std::ops::Deref;
6use std::os::unix::io::{RawFd, AsRawFd};
7
8use ::context::Context;
9use ::device::Device;
10use ::handle::Handle;
11
12
13pub struct Monitor {
19 monitor: *mut ::ffi::udev_monitor,
20}
21
22impl Drop for Monitor {
23 fn drop(&mut self) {
24 unsafe {
25 let udev = ::ffi::udev_monitor_get_udev(self.monitor);
26
27 ::ffi::udev_monitor_unref(self.monitor);
28 ::ffi::udev_unref(udev);
29 }
30 }
31}
32
33impl Monitor {
34 pub fn new(context: &Context) -> ::Result<Self> {
36 unsafe {
37 let ptr = try_alloc!(
38 ::ffi::udev_monitor_new_from_netlink(context.as_ptr(), b"udev\0".as_ptr() as *mut _)
39 );
40
41 ::ffi::udev_ref(context.as_ptr());
42
43 Ok(Monitor { monitor: ptr })
44 }
45 }
46
47 pub fn match_subsystem<T: AsRef<OsStr>>(&mut self, subsystem: T) -> ::Result<()> {
49 let subsystem = try!(::util::os_str_to_cstring(subsystem));
50
51 ::util::errno_to_result(unsafe {
52 ::ffi::udev_monitor_filter_add_match_subsystem_devtype(self.monitor, subsystem.as_ptr(), ptr::null())
53 })
54 }
55
56 pub fn match_subsystem_devtype<T: AsRef<OsStr>, U: AsRef<OsStr>>(&mut self, subsystem: T, devtype: U) -> ::Result<()> {
58 let subsystem = try!(::util::os_str_to_cstring(subsystem));
59 let devtype = try!(::util::os_str_to_cstring(devtype));
60
61 ::util::errno_to_result(unsafe {
62 ::ffi::udev_monitor_filter_add_match_subsystem_devtype(self.monitor, subsystem.as_ptr(), devtype.as_ptr())
63 })
64 }
65
66 pub fn match_tag<T: AsRef<OsStr>>(&mut self, tag: T) -> ::Result<()> {
68 let tag = try!(::util::os_str_to_cstring(tag));
69
70 ::util::errno_to_result(unsafe {
71 ::ffi::udev_monitor_filter_add_match_tag(self.monitor, tag.as_ptr())
72 })
73 }
74
75 pub fn clear_filters(&mut self) -> ::Result<()> {
77 ::util::errno_to_result(unsafe {
78 ::ffi::udev_monitor_filter_remove(self.monitor)
79 })
80 }
81
82 pub fn listen(self) -> ::Result<MonitorSocket> {
86 try!(::util::errno_to_result(unsafe {
87 ::ffi::udev_monitor_enable_receiving(self.monitor)
88 }));
89
90 Ok(MonitorSocket { inner: self })
91 }
92}
93
94
95pub struct MonitorSocket {
104 inner: Monitor,
105}
106
107impl AsRawFd for MonitorSocket {
109 fn as_raw_fd(&self) -> RawFd {
111 unsafe {
112 ::ffi::udev_monitor_get_fd(self.inner.monitor)
113 }
114 }
115}
116
117impl MonitorSocket {
118 pub fn receive_event(&mut self) -> Option<Event> {
122 let device = unsafe {
123 ::ffi::udev_monitor_receive_device(self.inner.monitor)
124 };
125
126 if !device.is_null() {
127 Some(Event {
128 device: unsafe { ::device::from_raw(device) },
129 })
130 }
131 else {
132 None
133 }
134 }
135}
136
137#[derive(Debug,Clone,Copy,PartialEq,Eq)]
139pub enum EventType {
140 Add,
142
143 Change,
145
146 Remove,
148
149 Unknown,
151}
152
153impl Default for EventType {
154 fn default() -> EventType {
155 EventType::Unknown
156 }
157}
158
159impl fmt::Display for EventType {
160 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
161 f.write_str(match self {
162 &EventType::Add => "add",
163 &EventType::Change => "change",
164 &EventType::Remove => "remove",
165 &EventType::Unknown => "unknown",
166 })
167 }
168}
169
170
171pub struct Event {
173 device: Device,
174}
175
176impl Deref for Event {
178 type Target = Device;
179
180 fn deref(&self) -> &Device {
181 &self.device
182 }
183}
184
185impl Event {
186 pub fn event_type(&self) -> EventType {
188 let value = match self.device.property_value("ACTION") {
189 Some(s) => s.to_str(),
190 None => None,
191 };
192
193 match value {
194 Some("add") => EventType::Add,
195 Some("change") => EventType::Change,
196 Some("remove") => EventType::Remove,
197 _ => EventType::Unknown
198 }
199 }
200
201 pub fn sequence_number(&self) -> u64 {
203 unsafe {
204 ::ffi::udev_device_get_seqnum(self.device.as_ptr()) as u64
205 }
206 }
207
208 pub fn device(&self) -> &Device {
210 &self.device
211 }
212}