diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-06 11:53:02 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-06 11:53:02 -0800 |
commit | c095f606729b6916e9f5f535f975af5e05d4a165 (patch) | |
tree | 848d1ca07b238a027bb29bb8af0c1515cdc2594e | |
download | rfkill-c095f606729b6916e9f5f535f975af5e05d4a165.tar.gz rfkill-c095f606729b6916e9f5f535f975af5e05d4a165.tar.bz2 rfkill-c095f606729b6916e9f5f535f975af5e05d4a165.zip |
Imported Upstream version 0.4upstream/0.4upstream
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | COPYING | 15 | ||||
-rw-r--r-- | Makefile | 62 | ||||
-rw-r--r-- | README | 12 | ||||
-rw-r--r-- | core.h | 8 | ||||
-rw-r--r-- | rfkill.8 | 38 | ||||
-rw-r--r-- | rfkill.c | 355 | ||||
-rw-r--r-- | rfkill.h | 390 | ||||
-rwxr-xr-x | version.sh | 32 |
9 files changed, 917 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..528816d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +version.c +*.o +rfkill +*~ +*.gz @@ -0,0 +1,15 @@ +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8d6c700 --- /dev/null +++ b/Makefile @@ -0,0 +1,62 @@ +MAKEFLAGS += --no-print-directory + +PREFIX ?= /usr +SBINDIR ?= $(PREFIX)/sbin +MANDIR ?= $(PREFIX)/share/man + +MKDIR ?= mkdir -p +INSTALL ?= install +CC ?= "gcc" + +CFLAGS ?= -O2 -g +CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration + +OBJS = rfkill.o version.o +ALL = rfkill + +ifeq ($(V),1) +Q= +NQ=true +else +Q=@ +NQ=echo +endif + +all: $(ALL) + +VERSION_OBJS := $(filter-out version.o, $(OBJS)) + +version.c: version.sh $(patsubst %.o,%.c,$(VERSION_OBJS)) rfkill.h Makefile \ + $(wildcard .git/index .git/refs/tags) + @$(NQ) ' GEN ' $@ +ifeq (,$(VERSION_SUFFIX)) + $(Q)./version.sh $@ +else + $(Q)./version.sh --suffix "$(VERSION_SUFFIX)" $@ +endif + +%.o: %.c rfkill.h + @$(NQ) ' CC ' $@ + $(Q)$(CC) $(CFLAGS) -c -o $@ $< + +rfkill: $(OBJS) + @$(NQ) ' CC ' rfkill + $(Q)$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o rfkill + +check: + $(Q)$(MAKE) all CC="REAL_CC=$(CC) CHECK=\"sparse -Wall\" cgcc" + +%.gz: % + @$(NQ) ' GZIP' $< + $(Q)gzip < $< > $@ + +install: rfkill rfkill.8.gz + @$(NQ) ' INST rfkill' + $(Q)$(MKDIR) $(DESTDIR)$(SBINDIR) + $(Q)$(INSTALL) -m 755 -t $(DESTDIR)$(SBINDIR) rfkill + @$(NQ) ' INST rfkill.8' + $(Q)$(MKDIR) $(DESTDIR)$(MANDIR)/man8/ + $(Q)$(INSTALL) -m 644 -t $(DESTDIR)$(MANDIR)/man8/ rfkill.8.gz + +clean: + $(Q)rm -f rfkill *.o *~ *.gz version.c *-stamp @@ -0,0 +1,12 @@ + +This is 'rfkill', a tool to use /dev/rfkill. + + +To build rfkill, just enter 'make'. + +'rfkill' is currently maintained at http://git.sipsolutions.net/rfkill.git/, +some more documentation is available at +http://wireless.kernel.org/en/users/Documentation/rfkill. + +Please send all patches to Johannes Berg <johannes@sipsolutions.net> +and CC linux-wireless@vger.kernel.org for community review. @@ -0,0 +1,8 @@ +#ifndef __CORE +#define __CORE + +#include "rfkill.h" + +extern const char rfkill_version[]; + +#endif diff --git a/rfkill.8 b/rfkill.8 new file mode 100644 index 0000000..aa11fde --- /dev/null +++ b/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" or "fm". +.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/rfkill.c b/rfkill.c new file mode 100644 index 0000000..bda649a --- /dev/null +++ b/rfkill.c @@ -0,0 +1,355 @@ +/* + * rfkill userspace tool + */ + +#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]; + ssize_t len; + 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)); + len = 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 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" }, + { .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/rfkill.h b/rfkill.h new file mode 100644 index 0000000..97059d0 --- /dev/null +++ b/rfkill.h @@ -0,0 +1,390 @@ +#ifndef __RFKILL_H +#define __RFKILL_H + +/* + * Copyright (C) 2006 - 2007 Ivo van Doorn + * Copyright (C) 2007 Dmitry Torokhov + * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> + * + * 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 <linux/types.h> + +/* define userspace visible states */ +#define RFKILL_STATE_SOFT_BLOCKED 0 +#define RFKILL_STATE_UNBLOCKED 1 +#define RFKILL_STATE_HARD_BLOCKED 2 + +/** + * enum rfkill_type - type of rfkill switch. + * + * @RFKILL_TYPE_ALL: toggles all switches (userspace only) + * @RFKILL_TYPE_WLAN: switch is on a 802.11 wireless network device. + * @RFKILL_TYPE_BLUETOOTH: switch is on a bluetooth device. + * @RFKILL_TYPE_UWB: switch is on a ultra wideband device. + * @RFKILL_TYPE_WIMAX: switch is on a WiMAX device. + * @RFKILL_TYPE_WWAN: switch is on a wireless WAN device. + * @RFKILL_TYPE_GPS: switch is on a GPS device. + * @RFKILL_TYPE_FM: switch is on a FM radio device. + * @NUM_RFKILL_TYPES: number of defined rfkill types + */ +enum rfkill_type { + RFKILL_TYPE_ALL = 0, + RFKILL_TYPE_WLAN, + RFKILL_TYPE_BLUETOOTH, + RFKILL_TYPE_UWB, + RFKILL_TYPE_WIMAX, + RFKILL_TYPE_WWAN, + RFKILL_TYPE_GPS, + RFKILL_TYPE_FM, + NUM_RFKILL_TYPES, +}; + +/** + * enum rfkill_operation - operation types + * @RFKILL_OP_ADD: a device was added + * @RFKILL_OP_DEL: a device was removed + * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device + * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all) + */ +enum rfkill_operation { + RFKILL_OP_ADD = 0, + RFKILL_OP_DEL, + RFKILL_OP_CHANGE, + RFKILL_OP_CHANGE_ALL, +}; + +/** + * struct rfkill_event - events for userspace on /dev/rfkill + * @idx: index of dev rfkill + * @type: type of the rfkill struct + * @op: operation code + * @hard: hard state (0/1) + * @soft: soft state (0/1) + * + * Structure used for userspace communication on /dev/rfkill, + * used for events from the kernel and control to the kernel. + */ +struct rfkill_event { + __u32 idx; + __u8 type; + __u8 op; + __u8 soft, hard; +} __packed; + +/* + * We are planning to be backward and forward compatible with changes + * to the event struct, by adding new, optional, members at the end. + * When reading an event (whether the kernel from userspace or vice + * versa) we need to accept anything that's at least as large as the + * version 1 event size, but might be able to accept other sizes in + * the future. + * + * One exception is the kernel -- we already have two event sizes in + * that we've made the 'hard' member optional since our only option + * is to ignore it anyway. + */ +#define RFKILL_EVENT_SIZE_V1 8 + +/* ioctl for turning off rfkill-input (if present) */ +#define RFKILL_IOC_MAGIC 'R' +#define RFKILL_IOC_NOINPUT 1 +#define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT) + +/* and that's all userspace gets */ +#ifdef __KERNEL__ +/* don't allow anyone to use these in the kernel */ +enum rfkill_user_states { + RFKILL_USER_STATE_SOFT_BLOCKED = RFKILL_STATE_SOFT_BLOCKED, + RFKILL_USER_STATE_UNBLOCKED = RFKILL_STATE_UNBLOCKED, + RFKILL_USER_STATE_HARD_BLOCKED = RFKILL_STATE_HARD_BLOCKED, +}; +#undef RFKILL_STATE_SOFT_BLOCKED +#undef RFKILL_STATE_UNBLOCKED +#undef RFKILL_STATE_HARD_BLOCKED + +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/leds.h> +#include <linux/err.h> + +/* this is opaque */ +struct rfkill; + +/** + * struct rfkill_ops - rfkill driver methods + * + * @poll: poll the rfkill block state(s) -- only assign this method + * when you need polling. When called, simply call one of the + * rfkill_set{,_hw,_sw}_state family of functions. If the hw + * is getting unblocked you need to take into account the return + * value of those functions to make sure the software block is + * properly used. + * @query: query the rfkill block state(s) and call exactly one of the + * rfkill_set{,_hw,_sw}_state family of functions. Assign this + * method if input events can cause hardware state changes to make + * the rfkill core query your driver before setting a requested + * block. + * @set_block: turn the transmitter on (blocked == false) or off + * (blocked == true) -- ignore and return 0 when hard blocked. + * This callback must be assigned. + */ +struct rfkill_ops { + void (*poll)(struct rfkill *rfkill, void *data); + void (*query)(struct rfkill *rfkill, void *data); + int (*set_block)(void *data, bool blocked); +}; + +#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) +/** + * rfkill_alloc - allocate rfkill structure + * @name: name of the struct -- the string is not copied internally + * @parent: device that has rf switch on it + * @type: type of the switch (RFKILL_TYPE_*) + * @ops: rfkill methods + * @ops_data: data passed to each method + * + * This function should be called by the transmitter driver to allocate an + * rfkill structure. Returns %NULL on failure. + */ +struct rfkill * __must_check rfkill_alloc(const char *name, + struct device *parent, + const enum rfkill_type type, + const struct rfkill_ops *ops, + void *ops_data); + +/** + * rfkill_register - Register a rfkill structure. + * @rfkill: rfkill structure to be registered + * + * This function should be called by the transmitter driver to register + * the rfkill structure. Before calling this function the driver needs + * to be ready to service method calls from rfkill. + * + * If rfkill_init_sw_state() is not called before registration, + * set_block() will be called to initialize the software blocked state + * to a default value. + * + * If the hardware blocked state is not set before registration, + * it is assumed to be unblocked. + */ +int __must_check rfkill_register(struct rfkill *rfkill); + +/** + * rfkill_pause_polling(struct rfkill *rfkill) + * + * Pause polling -- say transmitter is off for other reasons. + * NOTE: not necessary for suspend/resume -- in that case the + * core stops polling anyway + */ +void rfkill_pause_polling(struct rfkill *rfkill); + +/** + * rfkill_resume_polling(struct rfkill *rfkill) + * + * Pause polling -- say transmitter is off for other reasons. + * NOTE: not necessary for suspend/resume -- in that case the + * core stops polling anyway + */ +void rfkill_resume_polling(struct rfkill *rfkill); + + +/** + * rfkill_unregister - Unregister a rfkill structure. + * @rfkill: rfkill structure to be unregistered + * + * This function should be called by the network driver during device + * teardown to destroy rfkill structure. Until it returns, the driver + * needs to be able to service method calls. + */ +void rfkill_unregister(struct rfkill *rfkill); + +/** + * rfkill_destroy - free rfkill structure + * @rfkill: rfkill structure to be destroyed + * + * Destroys the rfkill structure. + */ +void rfkill_destroy(struct rfkill *rfkill); + +/** + * rfkill_set_hw_state - Set the internal rfkill hardware block state + * @rfkill: pointer to the rfkill class to modify. + * @state: the current hardware block state to set + * + * rfkill drivers that get events when the hard-blocked state changes + * use this function to notify the rfkill core (and through that also + * userspace) of the current state. They should also use this after + * resume if the state could have changed. + * + * You need not (but may) call this function if poll_state is assigned. + * + * This function can be called in any context, even from within rfkill + * callbacks. + * + * The function returns the combined block state (true if transmitter + * should be blocked) so that drivers need not keep track of the soft + * block state -- which they might not be able to. + */ +bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked); + +/** + * rfkill_set_sw_state - Set the internal rfkill software block state + * @rfkill: pointer to the rfkill class to modify. + * @state: the current software block state to set + * + * rfkill drivers that get events when the soft-blocked state changes + * (yes, some platforms directly act on input but allow changing again) + * use this function to notify the rfkill core (and through that also + * userspace) of the current state. + * + * Drivers should also call this function after resume if the state has + * been changed by the user. This only makes sense for "persistent" + * devices (see rfkill_init_sw_state()). + * + * This function can be called in any context, even from within rfkill + * callbacks. + * + * The function returns the combined block state (true if transmitter + * should be blocked). + */ +bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked); + +/** + * rfkill_init_sw_state - Initialize persistent software block state + * @rfkill: pointer to the rfkill class to modify. + * @state: the current software block state to set + * + * rfkill drivers that preserve their software block state over power off + * use this function to notify the rfkill core (and through that also + * userspace) of their initial state. It should only be used before + * registration. + * + * In addition, it marks the device as "persistent", an attribute which + * can be read by userspace. Persistent devices are expected to preserve + * their own state when suspended. + */ +void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked); + +/** + * rfkill_set_states - Set the internal rfkill block states + * @rfkill: pointer to the rfkill class to modify. + * @sw: the current software block state to set + * @hw: the current hardware block state to set + * + * This function can be called in any context, even from within rfkill + * callbacks. + */ +void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw); + +/** + * rfkill_blocked - query rfkill block + * + * @rfkill: rfkill struct to query + */ +bool rfkill_blocked(struct rfkill *rfkill); +#else /* !RFKILL */ +static inline struct rfkill * __must_check +rfkill_alloc(const char *name, + struct device *parent, + const enum rfkill_type type, + const struct rfkill_ops *ops, + void *ops_data) +{ + return ERR_PTR(-ENODEV); +} + +static inline int __must_check rfkill_register(struct rfkill *rfkill) +{ + if (rfkill == ERR_PTR(-ENODEV)) + return 0; + return -EINVAL; +} + +static inline void rfkill_pause_polling(struct rfkill *rfkill) +{ +} + +static inline void rfkill_resume_polling(struct rfkill *rfkill) +{ +} + +static inline void rfkill_unregister(struct rfkill *rfkill) +{ +} + +static inline void rfkill_destroy(struct rfkill *rfkill) +{ +} + +static inline bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked) +{ + return blocked; +} + +static inline bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) +{ + return blocked; +} + +static inline void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked) +{ +} + +static inline void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) +{ +} + +static inline bool rfkill_blocked(struct rfkill *rfkill) +{ + return false; +} +#endif /* RFKILL || RFKILL_MODULE */ + + +#ifdef CONFIG_RFKILL_LEDS +/** + * rfkill_get_led_trigger_name - Get the LED trigger name for the button's LED. + * This function might return a NULL pointer if registering of the + * LED trigger failed. Use this as "default_trigger" for the LED. + */ +const char *rfkill_get_led_trigger_name(struct rfkill *rfkill); + +/** + * rfkill_set_led_trigger_name -- set the LED trigger name + * @rfkill: rfkill struct + * @name: LED trigger name + * + * This function sets the LED trigger name of the radio LED + * trigger that rfkill creates. It is optional, but if called + * must be called before rfkill_register() to be effective. + */ +void rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name); +#else +static inline const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) +{ + return NULL; +} + +static inline void +rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name) +{ +} +#endif + +#endif /* __KERNEL__ */ + +#endif /* RFKILL_H */ diff --git a/version.sh b/version.sh new file mode 100755 index 0000000..2843797 --- /dev/null +++ b/version.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +VERSION="0.4" + +SUFFIX= +if test "x$1" = x--suffix; then + shift + SUFFIX="-$1" + shift +fi +OUT="$1" + +if test "x$SUFFIX" != 'x'; then + v="$VERSION$SUFFIX" +elif head=`git rev-parse --verify HEAD 2>/dev/null`; then + git update-index --refresh --unmerged > /dev/null + descr=$(git describe 2>/dev/null || echo "v$VERSION") + + # on git builds check that the version number above + # is correct... + [ "${descr%%-*}" = "v$VERSION" ] || exit 2 + + echo -n 'const char rfkill_version[] = "' > "$OUT" + v="${descr#v}" + if git diff-index --name-only HEAD | read dummy ; then + v="$v"-dirty + fi +else + v="$VERSION" +fi + +echo "const char rfkill_version[] = \"$v\";" > "$OUT" |