2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/rfkill.h>
24 #include "sd-daemon.h"
26 #include "alloc-util.h"
32 #include "parse-util.h"
33 #include "proc-cmdline.h"
34 #include "string-table.h"
35 #include "string-util.h"
36 #include "udev-util.h"
39 #define EXIT_USEC (5 * USEC_PER_SEC)
41 static const char* const rfkill_type_table
[NUM_RFKILL_TYPES
] = {
42 [RFKILL_TYPE_ALL
] = "all",
43 [RFKILL_TYPE_WLAN
] = "wlan",
44 [RFKILL_TYPE_BLUETOOTH
] = "bluetooth",
45 [RFKILL_TYPE_UWB
] = "uwb",
46 [RFKILL_TYPE_WIMAX
] = "wimax",
47 [RFKILL_TYPE_WWAN
] = "wwan",
48 [RFKILL_TYPE_GPS
] = "gps",
49 [RFKILL_TYPE_FM
] = "fm",
50 [RFKILL_TYPE_NFC
] = "nfc",
53 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(rfkill_type
, int);
55 static int find_device(
57 const struct rfkill_event
*event
,
58 struct udev_device
**ret
) {
60 _cleanup_free_
char *sysname
= NULL
;
61 struct udev_device
*device
;
68 if (asprintf(&sysname
, "rfkill%i", event
->idx
) < 0)
71 device
= udev_device_new_from_subsystem_sysname(udev
, "rfkill", sysname
);
73 return log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open device: %m");
75 name
= udev_device_get_sysattr_value(device
, "name");
77 log_debug("Device has no name, ignoring.");
78 udev_device_unref(device
);
82 log_debug("Operating on rfkill device '%s'.", name
);
88 static int wait_for_initialized(
90 struct udev_device
*device
,
91 struct udev_device
**ret
) {
93 _cleanup_udev_monitor_unref_
struct udev_monitor
*monitor
= NULL
;
94 struct udev_device
*d
;
102 if (udev_device_get_is_initialized(device
) != 0) {
103 *ret
= udev_device_ref(device
);
107 assert_se(sysname
= udev_device_get_sysname(device
));
109 /* Wait until the device is initialized, so that we can get
110 * access to the ID_PATH property */
112 monitor
= udev_monitor_new_from_netlink(udev
, "udev");
114 return log_error_errno(errno
, "Failed to acquire monitor: %m");
116 r
= udev_monitor_filter_add_match_subsystem_devtype(monitor
, "rfkill", NULL
);
118 return log_error_errno(r
, "Failed to add rfkill udev match to monitor: %m");
120 r
= udev_monitor_enable_receiving(monitor
);
122 return log_error_errno(r
, "Failed to enable udev receiving: %m");
124 watch_fd
= udev_monitor_get_fd(monitor
);
126 return log_error_errno(watch_fd
, "Failed to get watch fd: %m");
128 /* Check again, maybe things changed */
129 d
= udev_device_new_from_subsystem_sysname(udev
, "rfkill", sysname
);
131 return log_full_errno(errno
== ENOENT
? LOG_DEBUG
: LOG_ERR
, errno
, "Failed to open device: %m");
133 if (udev_device_get_is_initialized(d
) != 0) {
139 _cleanup_udev_device_unref_
struct udev_device
*t
= NULL
;
141 r
= fd_wait_for_event(watch_fd
, POLLIN
, EXIT_USEC
);
145 return log_error_errno(r
, "Failed to watch udev monitor: %m");
147 log_error("Timed out wating for udev monitor.");
151 t
= udev_monitor_receive_device(monitor
);
155 if (streq_ptr(udev_device_get_sysname(t
), sysname
)) {
156 *ret
= udev_device_ref(t
);
162 static int determine_state_file(
164 const struct rfkill_event
*event
,
165 struct udev_device
*d
,
168 _cleanup_udev_device_unref_
struct udev_device
*device
= NULL
;
169 const char *path_id
, *type
;
177 r
= wait_for_initialized(udev
, d
, &device
);
181 assert_se(type
= rfkill_type_to_string(event
->type
));
183 path_id
= udev_device_get_property_value(device
, "ID_PATH");
185 _cleanup_free_
char *escaped_path_id
= NULL
;
187 escaped_path_id
= cescape(path_id
);
188 if (!escaped_path_id
)
191 state_file
= strjoin("/var/lib/systemd/rfkill/", escaped_path_id
, ":", type
);
193 state_file
= strjoin("/var/lib/systemd/rfkill/", type
);
202 static int load_state(
205 const struct rfkill_event
*event
) {
207 _cleanup_udev_device_unref_
struct udev_device
*device
= NULL
;
208 _cleanup_free_
char *state_file
= NULL
, *value
= NULL
;
209 struct rfkill_event we
;
213 assert(rfkill_fd
>= 0);
217 if (shall_restore_state() == 0)
220 r
= find_device(udev
, event
, &device
);
224 r
= determine_state_file(udev
, event
, device
, &state_file
);
228 r
= read_one_line_file(state_file
, &value
);
230 /* No state file? Then save the current state */
232 r
= write_string_file(state_file
, one_zero(event
->soft
), WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
234 return log_error_errno(r
, "Failed to write state file %s: %m", state_file
);
236 log_debug("Saved state '%s' to %s.", one_zero(event
->soft
), state_file
);
240 return log_error_errno(r
, "Failed to read state file %s: %m", state_file
);
242 b
= parse_boolean(value
);
244 return log_error_errno(b
, "Failed to parse state file %s: %m", state_file
);
246 we
= (struct rfkill_event
) {
247 .op
= RFKILL_OP_CHANGE
,
252 l
= write(rfkill_fd
, &we
, sizeof(we
));
254 return log_error_errno(errno
, "Failed to restore rfkill state for %i: %m", event
->idx
);
255 if (l
!= sizeof(we
)) {
256 log_error("Couldn't write rfkill event structure, too short.");
260 log_debug("Loaded state '%s' from %s.", one_zero(b
), state_file
);
264 static int save_state(
267 const struct rfkill_event
*event
) {
269 _cleanup_udev_device_unref_
struct udev_device
*device
= NULL
;
270 _cleanup_free_
char *state_file
= NULL
;
273 assert(rfkill_fd
>= 0);
277 r
= find_device(udev
, event
, &device
);
281 r
= determine_state_file(udev
, event
, device
, &state_file
);
285 r
= write_string_file(state_file
, one_zero(event
->soft
), WRITE_STRING_FILE_CREATE
|WRITE_STRING_FILE_ATOMIC
);
287 return log_error_errno(r
, "Failed to write state file %s: %m", state_file
);
289 log_debug("Saved state '%s' to %s.", one_zero(event
->soft
), state_file
);
293 int main(int argc
, char *argv
[]) {
294 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
295 _cleanup_close_
int rfkill_fd
= -1;
300 log_error("This program requires no arguments.");
304 log_set_target(LOG_TARGET_AUTO
);
305 log_parse_environment();
316 r
= mkdir_p("/var/lib/systemd/rfkill", 0755);
318 log_error_errno(r
, "Failed to create rfkill directory: %m");
322 n
= sd_listen_fds(false);
324 r
= log_error_errno(n
, "Failed to determine whether we got any file descriptors passed: %m");
328 log_error("Got too many file descriptors.");
334 rfkill_fd
= open("/dev/rfkill", O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NONBLOCK
);
336 if (errno
== ENOENT
) {
337 log_debug_errno(errno
, "Missing rfkill subsystem, or no device present, exiting.");
342 r
= log_error_errno(errno
, "Failed to open /dev/rfkill: %m");
346 rfkill_fd
= SD_LISTEN_FDS_START
;
348 r
= fd_nonblock(rfkill_fd
, 1);
350 log_error_errno(r
, "Failed to make /dev/rfkill socket non-blocking: %m");
356 struct rfkill_event event
;
360 l
= read(rfkill_fd
, &event
, sizeof(event
));
362 if (errno
== EAGAIN
) {
365 /* Notify manager that we are
367 * processing whatever was
369 (void) sd_notify(false, "READY=1");
373 /* Hang around for a bit, maybe there's more coming */
375 r
= fd_wait_for_event(rfkill_fd
, POLLIN
, EXIT_USEC
);
379 log_error_errno(r
, "Failed to poll() on device: %m");
385 log_debug("All events read and idle, exiting.");
389 log_error_errno(errno
, "Failed to read from /dev/rfkill: %m");
392 if (l
!= RFKILL_EVENT_SIZE_V1
) {
393 log_error("Read event structure of invalid size.");
398 type
= rfkill_type_to_string(event
.type
);
400 log_debug("An rfkill device of unknown type %i discovered, ignoring.", event
.type
);
407 log_debug("A new rfkill device has been added with index %i and type %s.", event
.idx
, type
);
408 (void) load_state(rfkill_fd
, udev
, &event
);
412 log_debug("An rfkill device has been removed with index %i and type %s", event
.idx
, type
);
415 case RFKILL_OP_CHANGE
:
416 log_debug("An rfkill device has changed state with index %i and type %s", event
.idx
, type
);
417 (void) save_state(rfkill_fd
, udev
, &event
);
421 log_debug("Unknown event %i from /dev/rfkill for index %i and type %s, ignoring.", event
.op
, event
.idx
, type
);
429 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;