2 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <ahornung@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/device.h>
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
40 #include <sys/queue.h>
42 #include <cpu/inttypes.h>
58 #include <libprop/proplib.h>
60 #define LIBDEVATTR_INTERNAL
64 struct udev
*udev_ctx
;
67 int user_socket
; /* maybe... one day... */
72 udev_monitor_new(struct udev
*udev_ctx
)
74 struct udev_monitor
*udev_monitor
;
77 ret
= conn_local_server(LISTEN_SOCKET_FILE
, SOCK_STREAM
, 0, &s
);
81 udev_monitor
= malloc(sizeof(struct udev_monitor
));
82 if (udev_monitor
== NULL
)
85 udev_monitor
->refs
= 1;
86 udev_monitor
->ev_filt
= NULL
;
87 udev_monitor
->socket
= s
;
88 udev_monitor
->user_socket
= 1;
89 udev_monitor
->udev_ctx
= udev_ref(udev_ctx
);
96 udev_monitor_ref(struct udev_monitor
*udev_monitor
)
98 atomic_add_int(&udev_monitor
->refs
, 1);
104 udev_monitor_unref(struct udev_monitor
*udev_monitor
)
108 refcount
= atomic_fetchadd_int(&udev_monitor
->refs
, -1);
111 atomic_subtract_int(&udev_monitor
->refs
, 0x400); /* in destruction */
112 if (udev_monitor
->ev_filt
!= NULL
)
113 prop_object_release(udev_monitor
->ev_filt
);
115 if (udev_monitor
->socket
!= -1)
116 close(udev_monitor
->socket
);
117 if (udev_monitor
->user_socket
!= -1)
118 close(udev_monitor
->user_socket
);
120 udev_unref(udev_monitor
->udev_ctx
);
126 udev_monitor_get_udev(struct udev_monitor
*udev_monitor
)
128 return udev_monitor
->udev_ctx
;
132 udev_monitor_get_fd(struct udev_monitor
*udev_monitor
)
134 return udev_monitor
->socket
;
138 udev_monitor_receive_device(struct udev_monitor
*udev_monitor
)
140 struct udev_device
*udev_dev
;
141 prop_dictionary_t dict
, evdict
;
146 if ((n
= read_xml(udev_monitor
->socket
, &xml
)) <= 0)
150 dict
= prop_dictionary_internalize(xml
);
155 pn
= prop_dictionary_get(dict
, "evtype");
157 prop_object_release(dict
);
161 evdict
= prop_dictionary_get(dict
, "evdict");
162 if (evdict
== NULL
) {
163 prop_object_release(dict
);
167 udev_dev
= udev_device_new_from_dictionary(udev_monitor
->udev_ctx
, evdict
);
168 if (udev_dev
== NULL
) {
169 prop_object_release(dict
);
173 udev_device_set_action(udev_dev
, prop_number_integer_value(pn
));
175 prop_object_release(dict
);
180 udev_monitor_enable_receiving(struct udev_monitor
*udev_monitor
)
182 prop_dictionary_t dict
;
185 /* ->socket, ->user_socket, ->ev_filt */
187 dict
= udevd_get_command_dict(__DECONST(char *, "monitor"));
191 /* Add event filters to message, if available */
192 if (udev_monitor
->ev_filt
!= NULL
) {
193 if (prop_dictionary_set(dict
, "filters",
194 udev_monitor
->ev_filt
) == false) {
195 prop_object_release(dict
);
200 xml
= prop_dictionary_externalize(dict
);
201 prop_object_release(dict
);
205 n
= send_xml(udev_monitor
->socket
, xml
);
214 udev_monitor_filter_add_match_subsystem_devtype(struct udev_monitor
*udev_monitor
,
215 const char *subsystem
,
216 const char *devtype __unused
)
220 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
221 EVENT_FILTER_TYPE_WILDCARD
,
224 __DECONST(char *, subsystem
));
230 udev_monitor_filter_add_match_expr(struct udev_monitor
*udev_monitor
,
236 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
237 EVENT_FILTER_TYPE_WILDCARD
,
246 udev_monitor_filter_add_nomatch_expr(struct udev_monitor
*udev_monitor
,
252 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
253 EVENT_FILTER_TYPE_WILDCARD
,
262 udev_monitor_filter_add_match_regex(struct udev_monitor
*udev_monitor
,
268 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
269 EVENT_FILTER_TYPE_REGEX
,
278 udev_monitor_filter_add_nomatch_regex(struct udev_monitor
*udev_monitor
,
284 ret
= _udev_monitor_filter_add_match_gen(udev_monitor
,
285 EVENT_FILTER_TYPE_REGEX
,
294 _udev_filter_add_match_gen(prop_array_t filters
,
300 prop_dictionary_t dict
;
308 dict
= prop_dictionary_create();
312 error
= _udev_dict_set_cstr(dict
, "key", __DECONST(char *, key
));
315 error
= _udev_dict_set_int(dict
, "type", type
);
318 error
= _udev_dict_set_cstr(dict
, "expr", expr
);
323 error
= _udev_dict_set_int(dict
, "negative", 1);
328 if (prop_array_add(filters
, dict
) == false)
334 prop_object_release(dict
);
339 _udev_monitor_filter_add_match_gen(struct udev_monitor
*udev_monitor
,
348 if (udev_monitor
->ev_filt
== NULL
) {
349 pa
= prop_array_create_with_capacity(5);
353 udev_monitor
->ev_filt
= pa
;
356 error
= _udev_filter_add_match_gen(udev_monitor
->ev_filt
, type
, neg
, key
, expr
);