2 * Linux rfkill helper functions for driver wrappers
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "utils/common.h"
19 #include "utils/eloop.h"
22 #define RFKILL_EVENT_SIZE_V1 8
32 enum rfkill_operation {
42 RFKILL_TYPE_BLUETOOTH,
53 struct rfkill_config *cfg;
59 static void rfkill_receive(int sock, void *eloop_ctx, void *sock_ctx)
61 struct rfkill_data *rfkill = eloop_ctx;
62 struct rfkill_event event;
66 len = read(rfkill->fd, &event, sizeof(event));
68 wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",
72 if (len != RFKILL_EVENT_SIZE_V1) {
73 wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size "
75 (int) len, RFKILL_EVENT_SIZE_V1);
78 wpa_printf(MSG_DEBUG, "rfkill: event: idx=%u type=%d "
79 "op=%u soft=%u hard=%u",
80 event.idx, event.type, event.op, event.soft,
82 if (event.op != RFKILL_OP_CHANGE || event.type != RFKILL_TYPE_WLAN)
86 wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
88 } else if (event.soft) {
89 wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
92 wpa_printf(MSG_INFO, "rfkill: WLAN unblocked");
96 if (new_blocked != rfkill->blocked) {
97 rfkill->blocked = new_blocked;
99 rfkill->cfg->blocked_cb(rfkill->cfg->ctx);
101 rfkill->cfg->unblocked_cb(rfkill->cfg->ctx);
106 struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
108 struct rfkill_data *rfkill;
109 struct rfkill_event event;
112 rfkill = os_zalloc(sizeof(*rfkill));
117 rfkill->fd = open("/dev/rfkill", O_RDONLY);
118 if (rfkill->fd < 0) {
119 wpa_printf(MSG_INFO, "rfkill: Cannot open RFKILL control "
124 if (fcntl(rfkill->fd, F_SETFL, O_NONBLOCK) < 0) {
125 wpa_printf(MSG_ERROR, "rfkill: Cannot set non-blocking mode: "
126 "%s", strerror(errno));
131 len = read(rfkill->fd, &event, sizeof(event));
134 break; /* No more entries */
135 wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",
139 if (len != RFKILL_EVENT_SIZE_V1) {
140 wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size "
142 (int) len, RFKILL_EVENT_SIZE_V1);
145 wpa_printf(MSG_DEBUG, "rfkill: initial event: idx=%u type=%d "
146 "op=%u soft=%u hard=%u",
147 event.idx, event.type, event.op, event.soft,
149 if (event.op != RFKILL_OP_ADD ||
150 event.type != RFKILL_TYPE_WLAN)
153 wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
155 } else if (event.soft) {
156 wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
161 eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL);
173 void rfkill_deinit(struct rfkill_data *rfkill)
178 if (rfkill->fd >= 0) {
179 eloop_unregister_read_sock(rfkill->fd);
183 os_free(rfkill->cfg);
188 int rfkill_is_blocked(struct rfkill_data *rfkill)
193 return rfkill->blocked;