diff options
Diffstat (limited to 'lib/op-rfkill.c')
-rw-r--r-- | lib/op-rfkill.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/lib/op-rfkill.c b/lib/op-rfkill.c new file mode 100644 index 0000000..a5695c9 --- /dev/null +++ b/lib/op-rfkill.c @@ -0,0 +1,129 @@ +/* + * Linux WiMax + * Export the kernel's WiMAX stack wimaxll_rfkill() function + * + * + * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#define _GNU_SOURCE +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <errno.h> +#include <assert.h> +#include <linux/types.h> +#include <netlink/msg.h> +#include <netlink/netlink.h> +#include <netlink/genl/genl.h> +#include <wimaxll.h> +#include "internal.h" +#define D_LOCAL 0 +#include "debug.h" + + +/** + * Control the software RF Kill switch and obtain switch status + * + * \param wmx WiMAX device handle + * + * \param state State to which you want to toggle the sofware RF Kill + * switch (%WIMAX_RF_ON, %WIMAX_RF_OFF or %WIMAX_RF_QUERY for just + * querying the current state of the hardware and software + * switches). + * + * \return Negative errno code on error. Otherwise, radio kill switch + * status (bit 0 \e hw switch, bit 1 \e sw switch, \e 0 OFF, \e 1 + * ON): + * - 3 @c 0b11: Both HW and SW switches are \e on, radio is \e on + * - 2 @c 0b10: HW switch is \e off, radio is \e off + * - 1 @c 0b01: SW switch is \e on, radio is \e off + * - 0 @c 0b00: Both HW and SW switches are \e off, radio is \e off + * + * Allows the caller to control the state of the software RF Kill + * switch (if present) and in return, obtain the current status of + * both the hardware and software RF Kill switches. + * + * If there is no hardware or software switch, that switch is assumed + * to be always on (radio on). + * + * Changing the radio state might cause the device to change state, + * and cause the kernel to send reports indicating so. + * + * \note The state of the radio (\e ON or \e OFF) is the inverse of + * the state of the RF-Kill switch (\e enabled/on kills the + * radio, radio \e off; \e disabled/off allows the radio to + * work, radio \e on). + * + * \ingroup device_management + * \internal + * + * This implementation simply marshalls the call to the kernel's + * wimax_rfkill() and returns it's return code. + */ +int wimaxll_rfkill(struct wimaxll_handle *wmx, enum wimax_rf_state state) +{ + ssize_t result; + struct nl_msg *msg; + + msg = nlmsg_new(); + if (msg == NULL) { + result = errno; + wimaxll_msg(wmx, "E: RFKILL: cannot allocate generic netlink " + "message: %m\n"); + goto error_msg_alloc; + } + if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, + wimaxll_family_id(wmx), 0, 0, + WIMAX_GNL_OP_RFKILL, WIMAX_GNL_VERSION) == NULL) { + result = -ENOMEM; + wimaxll_msg(wmx, "E: RFKILL: error preparing message: " + "%d 0x%08x\n", result, result); + goto error_msg_prep; + } + nla_put_u32(msg, WIMAX_GNL_RFKILL_STATE, (__u32) state); + result = nl_send_auto_complete(wmx->nlh_tx, msg); + if (result < 0) { + wimaxll_msg(wmx, "E: RFKILL: error sending message: %zd\n", + result); + goto error_msg_send; + } + /* Read the message ACK from netlink */ + result = wimaxll_wait_for_rp_result(wmx); + nl_wait_for_ack(wmx->nlh_tx); + if (result < 0) + wimaxll_msg(wmx, "E: RFKILL: operation failed: %zd\n", result); +error_msg_prep: +error_msg_send: + nlmsg_free(msg); +error_msg_alloc: + return result; +} |