2 * Linux rfkill helper functions for driver wrappers
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
12 #include "utils/common.h"
13 #include "utils/eloop.h"
16 #define RFKILL_EVENT_SIZE_V1 8
26 enum rfkill_operation {
36 RFKILL_TYPE_BLUETOOTH,
47 struct rfkill_config *cfg;
53 static void rfkill_receive(int sock, void *eloop_ctx, void *sock_ctx)
55 struct rfkill_data *rfkill = eloop_ctx;
56 struct rfkill_event event;
60 len = read(rfkill->fd, &event, sizeof(event));
62 wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",
66 if (len != RFKILL_EVENT_SIZE_V1) {
67 wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size "
69 (int) len, RFKILL_EVENT_SIZE_V1);
72 wpa_printf(MSG_DEBUG, "rfkill: event: idx=%u type=%d "
73 "op=%u soft=%u hard=%u",
74 event.idx, event.type, event.op, event.soft,
76 if (event.op != RFKILL_OP_CHANGE || event.type != RFKILL_TYPE_WLAN)
80 wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
82 } else if (event.soft) {
83 wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
86 wpa_printf(MSG_INFO, "rfkill: WLAN unblocked");
90 if (new_blocked != rfkill->blocked) {
91 rfkill->blocked = new_blocked;
93 rfkill->cfg->blocked_cb(rfkill->cfg->ctx);
95 rfkill->cfg->unblocked_cb(rfkill->cfg->ctx);
100 struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
102 struct rfkill_data *rfkill;
103 struct rfkill_event event;
106 rfkill = os_zalloc(sizeof(*rfkill));
111 rfkill->fd = open("/dev/rfkill", O_RDONLY);
112 if (rfkill->fd < 0) {
113 wpa_printf(MSG_INFO, "rfkill: Cannot open RFKILL control "
118 if (fcntl(rfkill->fd, F_SETFL, O_NONBLOCK) < 0) {
119 wpa_printf(MSG_ERROR, "rfkill: Cannot set non-blocking mode: "
120 "%s", strerror(errno));
125 len = read(rfkill->fd, &event, sizeof(event));
128 break; /* No more entries */
129 wpa_printf(MSG_ERROR, "rfkill: Event read failed: %s",
133 if (len != RFKILL_EVENT_SIZE_V1) {
134 wpa_printf(MSG_DEBUG, "rfkill: Unexpected event size "
136 (int) len, RFKILL_EVENT_SIZE_V1);
139 wpa_printf(MSG_DEBUG, "rfkill: initial event: idx=%u type=%d "
140 "op=%u soft=%u hard=%u",
141 event.idx, event.type, event.op, event.soft,
143 if (event.op != RFKILL_OP_ADD ||
144 event.type != RFKILL_TYPE_WLAN)
147 wpa_printf(MSG_INFO, "rfkill: WLAN hard blocked");
149 } else if (event.soft) {
150 wpa_printf(MSG_INFO, "rfkill: WLAN soft blocked");
155 eloop_register_read_sock(rfkill->fd, rfkill_receive, rfkill, NULL);
167 void rfkill_deinit(struct rfkill_data *rfkill)
172 if (rfkill->fd >= 0) {
173 eloop_unregister_read_sock(rfkill->fd);
177 os_free(rfkill->cfg);
182 int rfkill_is_blocked(struct rfkill_data *rfkill)
187 return rfkill->blocked;