diff options
author | Sami Kerola | 2017-06-24 21:03:38 +0200 |
---|---|---|
committer | Sami Kerola | 2017-08-30 21:32:48 +0200 |
commit | e69263c03bf03f85812eb2a2fdea45d8ef4f8f94 (patch) | |
tree | 02a22083aa813f41e4df0cb5a0dca18651ab9320 /sys-utils | |
parent | rfkill: merge rfkill.8 project to util-linux (diff) | |
download | kernel-qcow2-util-linux-e69263c03bf03f85812eb2a2fdea45d8ef4f8f94.tar.gz kernel-qcow2-util-linux-e69263c03bf03f85812eb2a2fdea45d8ef4f8f94.tar.xz kernel-qcow2-util-linux-e69263c03bf03f85812eb2a2fdea45d8ef4f8f94.zip |
rfkill: move files to appropriate locations
Also remove unnecessary items. Notice that the licence text from COPYING is
moved to top of the command in comment section.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'sys-utils')
-rw-r--r-- | sys-utils/rfkill.8 | 38 | ||||
-rw-r--r-- | sys-utils/rfkill.c | 373 | ||||
-rwxr-xr-x | sys-utils/rfkill.py | 150 |
3 files changed, 561 insertions, 0 deletions
diff --git a/sys-utils/rfkill.8 b/sys-utils/rfkill.8 new file mode 100644 index 000000000..24baccc67 --- /dev/null +++ b/sys-utils/rfkill.8 @@ -0,0 +1,38 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH RFKILL 8 "July 10, 2009" +.SH NAME +rfkill \- tool for enabling and disabling wireless devices +.SH SYNOPSIS +.B rfkill +.RI [ options ] " command" +.SH OPTIONS +.TP +.B \-\-version +Show the version of rfkill. +.SH COMMANDS +.TP +.B help +Show rfkill's built-in help text. +.TP +.B event +Listen for rfkill events and display them on stdout. +.TP +.B list [type] +List the current state of all available rfkill-using devices, +or just all of the given type. +.TP +.BI block " index|type" +Disable the device corresponding to the given index. +\fItype\fR is one of "all", "wifi", "wlan", "bluetooth", "uwb", +"ultrawideband", "wimax", "wwan", "gps", "fm" or "nfc". +.TP +.BI unblock " index|type" +Enable the device corresponding to the given index. If the device is +hard-blocked, e.g. via a hardware switch, it will remain unavailable though +it is now soft-unblocked. +.SH AUTHORS +rfkill was originally written by Johannes Berg <johannes@sipsolutions.net> +and Marcel Holtmann <marcel@holtmann.org>. +.PP +This manual page was written by Darren Salt <linux@youmustbejoking.demon.co.uk>, +for the Debian project (and may be used by others). diff --git a/sys-utils/rfkill.c b/sys-utils/rfkill.c new file mode 100644 index 000000000..60f8cdc27 --- /dev/null +++ b/sys-utils/rfkill.c @@ -0,0 +1,373 @@ +/* + * /dev/rfkill userspace tool + * + * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> + * Copyright 2009 Marcel Holtmann <marcel@holtmann.org> + * Copyright 2009 Tim Gardner <tim.gardner@canonical.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/poll.h> +#include <sys/time.h> + +#include "rfkill.h" +#include "core.h" + +static void rfkill_event(void) +{ + struct rfkill_event event; + struct timeval tv; + struct pollfd p; + ssize_t len; + int fd, n; + + fd = open("/dev/rfkill", O_RDONLY); + if (fd < 0) { + perror("Can't open RFKILL control device"); + return; + } + + memset(&p, 0, sizeof(p)); + p.fd = fd; + p.events = POLLIN | POLLHUP; + + while (1) { + n = poll(&p, 1, -1); + if (n < 0) { + perror("Failed to poll RFKILL control device"); + break; + } + + if (n == 0) + continue; + + len = read(fd, &event, sizeof(event)); + if (len < 0) { + perror("Reading of RFKILL events failed"); + break; + } + + if (len != RFKILL_EVENT_SIZE_V1) { + fprintf(stderr, "Wrong size of RFKILL event\n"); + continue; + } + + gettimeofday(&tv, NULL); + printf("%ld.%06u: idx %u type %u op %u soft %u hard %u\n", + (long) tv.tv_sec, (unsigned int) tv.tv_usec, + event.idx, event.type, event.op, event.soft, event.hard); + fflush(stdout); + } + + close(fd); +} + +static const char *get_name(__u32 idx) +{ + static char name[128] = {}; + char *pos, filename[64]; + int fd; + + snprintf(filename, sizeof(filename) - 1, + "/sys/class/rfkill/rfkill%u/name", idx); + + fd = open(filename, O_RDONLY); + if (fd < 0) + return NULL; + + memset(name, 0, sizeof(name)); + read(fd, name, sizeof(name) - 1); + + pos = strchr(name, '\n'); + if (pos) + *pos = '\0'; + + close(fd); + + return name; +} + +static const char *type2string(enum rfkill_type type) +{ + switch (type) { + case RFKILL_TYPE_ALL: + return "All"; + case RFKILL_TYPE_WLAN: + return "Wireless LAN"; + case RFKILL_TYPE_BLUETOOTH: + return "Bluetooth"; + case RFKILL_TYPE_UWB: + return "Ultra-Wideband"; + case RFKILL_TYPE_WIMAX: + return "WiMAX"; + case RFKILL_TYPE_WWAN: + return "Wireless WAN"; + case RFKILL_TYPE_GPS: + return "GPS"; + case RFKILL_TYPE_FM: + return "FM"; + case RFKILL_TYPE_NFC: + return "NFC"; + case NUM_RFKILL_TYPES: + return NULL; + } + + return NULL; +} + +struct rfkill_type_str { + enum rfkill_type type; + const char *name; +}; +static const struct rfkill_type_str rfkill_type_strings[] = { + { .type = RFKILL_TYPE_ALL, .name = "all" }, + { .type = RFKILL_TYPE_WLAN, .name = "wifi" }, + { .type = RFKILL_TYPE_WLAN, .name = "wlan" }, /* alias */ + { .type = RFKILL_TYPE_BLUETOOTH, .name = "bluetooth" }, + { .type = RFKILL_TYPE_UWB, .name = "uwb" }, + { .type = RFKILL_TYPE_UWB, .name = "ultrawideband" }, /* alias */ + { .type = RFKILL_TYPE_WIMAX, .name = "wimax" }, + { .type = RFKILL_TYPE_WWAN, .name = "wwan" }, + { .type = RFKILL_TYPE_GPS, .name = "gps" }, + { .type = RFKILL_TYPE_FM, .name = "fm" }, + { .type = RFKILL_TYPE_NFC, .name = "nfc" }, + { .name = NULL } +}; + +struct rfkill_id { + union { + enum rfkill_type type; + __u32 index; + }; + enum { + RFKILL_IS_INVALID, + RFKILL_IS_TYPE, + RFKILL_IS_INDEX, + } result; +}; + +static struct rfkill_id rfkill_id_to_type(const char *s) +{ + const struct rfkill_type_str *p; + struct rfkill_id ret; + + if (islower(*s)) { + for (p = rfkill_type_strings; p->name != NULL; p++) { + if ((strlen(s) == strlen(p->name)) && (!strcmp(s,p->name))) { + ret.type = p->type; + ret.result = RFKILL_IS_TYPE; + return ret; + } + } + } else if (isdigit(*s)) { + /* assume a numeric character implies an index. */ + ret.index = atoi(s); + ret.result = RFKILL_IS_INDEX; + return ret; + } + + ret.result = RFKILL_IS_INVALID; + return ret; +} + +static int rfkill_list(const char *param) +{ + struct rfkill_id id = { .result = RFKILL_IS_INVALID }; + struct rfkill_event event; + const char *name; + ssize_t len; + int fd; + + if (param) { + id = rfkill_id_to_type(param); + if (id.result == RFKILL_IS_INVALID) { + fprintf(stderr, "Bogus %s argument '%s'.\n", "list", param); + return 2; + } + /* don't filter "all" */ + if (id.result == RFKILL_IS_TYPE && id.type == RFKILL_TYPE_ALL) + id.result = RFKILL_IS_INVALID; + } + + fd = open("/dev/rfkill", O_RDONLY); + if (fd < 0) { + perror("Can't open RFKILL control device"); + return 1; + } + + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + perror("Can't set RFKILL control device to non-blocking"); + close(fd); + return 1; + } + + while (1) { + len = read(fd, &event, sizeof(event)); + if (len < 0) { + if (errno == EAGAIN) + break; + perror("Reading of RFKILL events failed"); + break; + } + + if (len != RFKILL_EVENT_SIZE_V1) { + fprintf(stderr, "Wrong size of RFKILL event\n"); + continue; + } + + if (event.op != RFKILL_OP_ADD) + continue; + + /* filter out unwanted results */ + switch (id.result) + { + case RFKILL_IS_TYPE: + if (event.type != id.type) + continue; + break; + case RFKILL_IS_INDEX: + if (event.idx != id.index) + continue; + break; + case RFKILL_IS_INVALID:; /* must be last */ + } + + name = get_name(event.idx); + + printf("%u: %s: %s\n", event.idx, name, + type2string(event.type)); + printf("\tSoft blocked: %s\n", event.soft ? "yes" : "no"); + printf("\tHard blocked: %s\n", event.hard ? "yes" : "no"); + } + + close(fd); + return 0; +} + +static int rfkill_block(__u8 block, const char *param) +{ + struct rfkill_id id; + struct rfkill_event event; + ssize_t len; + int fd; + + id = rfkill_id_to_type(param); + if (id.result == RFKILL_IS_INVALID) { + fprintf(stderr, "Bogus %s argument '%s'.\n", block ? "block" : "unblock", param); + return 2; + } + + fd = open("/dev/rfkill", O_RDWR); + if (fd < 0) { + perror("Can't open RFKILL control device"); + return 1; + } + + memset(&event, 0, sizeof(event)); + switch (id.result) { + case RFKILL_IS_TYPE: + event.op = RFKILL_OP_CHANGE_ALL; + event.type = id.type; + break; + case RFKILL_IS_INDEX: + event.op = RFKILL_OP_CHANGE; + event.idx = id.index; + break; + case RFKILL_IS_INVALID:; /* must be last */ + } + event.soft = block; + + len = write(fd, &event, sizeof(event)); + if (len < 0) + perror("Failed to change RFKILL state"); + + close(fd); + return 0; +} + +static const char *argv0; + +static void usage(void) +{ + const struct rfkill_type_str *p; + + fprintf(stderr, "Usage:\t%s [options] command\n", argv0); + fprintf(stderr, "Options:\n"); + fprintf(stderr, "\t--version\tshow version (%s)\n", rfkill_version); + fprintf(stderr, "Commands:\n"); + fprintf(stderr, "\thelp\n"); + fprintf(stderr, "\tevent\n"); + fprintf(stderr, "\tlist [IDENTIFIER]\n"); + fprintf(stderr, "\tblock IDENTIFIER\n"); + fprintf(stderr, "\tunblock IDENTIFIER\n"); + fprintf(stderr, "where IDENTIFIER is the index no. of an rfkill switch or one of:\n"); + fprintf(stderr, "\t<idx>"); + for (p = rfkill_type_strings; p->name != NULL; p++) + fprintf(stderr, " %s", p->name); + fprintf(stderr, "\n"); +} + +static void version(void) +{ + printf("rfkill %s\n", rfkill_version); +} + +int main(int argc, char **argv) +{ + int ret = 0; + + /* strip off self */ + argc--; + argv0 = *argv++; + + if (argc > 0 && strcmp(*argv, "--version") == 0) { + version(); + return 0; + } + + if (argc == 0 || strcmp(*argv, "help") == 0) { + usage(); + return 0; + } + + if (strcmp(*argv, "event") == 0) { + rfkill_event(); + } else if (strcmp(*argv, "list") == 0) { + argc--; + argv++; + rfkill_list(*argv); /* NULL is acceptable */ + } else if (strcmp(*argv, "block") == 0 && argc > 1) { + argc--; + argv++; + ret = rfkill_block(1,*argv); + } else if (strcmp(*argv, "unblock") == 0 && argc > 1) { + argc--; + argv++; + ret = rfkill_block(0,*argv); + } else { + usage(); + return 1; + } + + return ret; +} diff --git a/sys-utils/rfkill.py b/sys-utils/rfkill.py new file mode 100755 index 000000000..57dcddc06 --- /dev/null +++ b/sys-utils/rfkill.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# +# rfkill control code +# +# Copyright (c) 2015 Intel Corporation +# +# Author: Johannes Berg <johannes.berg@intel.com> +# +# This software may be distributed under the terms of the MIT license. +# See COPYING for more details. + +import struct +import fcntl +import os + +(TYPE_ALL, + TYPE_WLAN, + TYPE_BLUETOOTH, + TYPE_UWB, + TYPE_WIMAX, + TYPE_WWAN, + TYPE_GPS, + TYPE_FM, + TYPE_NFC) = range(9) + +(_OP_ADD, + _OP_DEL, + _OP_CHANGE, + _OP_CHANGE_ALL) = range(4) + +_type_names = { + TYPE_ALL: "all", + TYPE_WLAN: "Wireless LAN", + TYPE_BLUETOOTH: "Bluetooth", + TYPE_UWB: "Ultra-Wideband", + TYPE_WIMAX: "WiMAX", + TYPE_WWAN: "Wireless WAN", + TYPE_GPS: "GPS", + TYPE_FM: "FM", + TYPE_NFC: "NFC", +} + +# idx, type, op, soft, hard +_event_struct = '@IBBBB' +_event_sz = struct.calcsize(_event_struct) + +class RFKillException(Exception): + pass + +class RFKill(object): + def __init__(self, idx): + self._idx = idx + self._type = None + + @property + def idx(self): + return self._idx + + @property + def name(self): + return open('/sys/class/rfkill/rfkill%d/name' % self._idx, 'r').read().rstrip() + + @property + def type(self): + if not self._type: + for r, s, h in RFKill.list(): + if r.idx == self.idx: + self._type = r._type + break + return self._type + + @property + def type_name(self): + return _type_names.get(self._type, "unknown") + + @property + def blocked(self): + l = RFKill.list() + for r, s, h in l: + if r.idx == self.idx: + return (s, h) + raise RFKillException("RFKill instance no longer exists") + + @property + def soft_blocked(self): + return self.blocked[0] + + @soft_blocked.setter + def soft_blocked(self, block): + if block: + self.block() + else: + self.unblock() + + @property + def hard_blocked(self): + return self.blocked[1] + + def block(self): + rfk = open('/dev/rfkill', 'w') + s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 1, 0) + rfk.write(s) + rfk.close() + + def unblock(self): + rfk = open('/dev/rfkill', 'w') + s = struct.pack(_event_struct, self.idx, TYPE_ALL, _OP_CHANGE, 0, 0) + rfk.write(s) + rfk.close() + + @classmethod + def block_all(cls, t=TYPE_ALL): + rfk = open('/dev/rfkill', 'w') + print rfk + s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 1, 0) + rfk.write(s) + rfk.close() + + @classmethod + def unblock_all(cls, t=TYPE_ALL): + rfk = open('/dev/rfkill', 'w') + s = struct.pack(_event_struct, 0, t, _OP_CHANGE_ALL, 0, 0) + rfk.write(s) + rfk.close() + + @classmethod + def list(cls): + res = [] + rfk = open('/dev/rfkill', 'r') + fd = rfk.fileno() + flgs = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, flgs | os.O_NONBLOCK) + while True: + try: + d = rfk.read(_event_sz) + _idx, _t, _op, _s, _h = struct.unpack(_event_struct, d) + if _op != _OP_ADD: + continue + r = RFKill(_idx) + r._type = _t + res.append((r, _s, _h)) + except IOError: + break + return res + +if __name__ == "__main__": + for r, s, h in RFKill.list(): + print "%d: %s: %s" % (r.idx, r.name, r.type_name) + print "\tSoft blocked: %s" % ("yes" if s else "no") + print "\tHard blocked: %s" % ("yes" if h else "no") |