As proposed on tech-net@, introduce a new switch type, PSWITCH_TYPE_RADIO,

to be used to report to userland hardware radio switch changes.
powerd(8) will call a "radio_button" script to handle the event.
This script can e.g. start or stop wpa_supplicant.
Update wpi(4) to report PSWITCH_TYPE_RADIO events to sysmon.
This commit is contained in:
bouyer 2015-01-06 15:39:54 +00:00
parent 87706a3247
commit 87fe8c7aca
5 changed files with 93 additions and 9 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: sysmon_pswitch.9,v 1.5 2014/03/18 18:20:40 riastradh Exp $
.\" $NetBSD: sysmon_pswitch.9,v 1.6 2015/01/06 15:39:54 bouyer Exp $
.\"
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 26, 2010
.Dd January 6, 2015
.Dt SYSMON_PSWITCH 9
.Os
.Sh NAME
@ -75,6 +75,7 @@ The following types are defined:
.It PSWITCH_TYPE_RESET
.It PSWITCH_TYPE_ACADAPTER
.It PSWITCH_TYPE_HOTKEY
.It PSWITCH_TYPE_RADIO
.El
.Pp
If the type is

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $ */
/* $NetBSD: if_wpi.c,v 1.70 2015/01/06 15:39:54 bouyer Exp $ */
/*-
* Copyright (c) 2006, 2007
@ -18,7 +18,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.70 2015/01/06 15:39:54 bouyer Exp $");
/*
* Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $");
#include <sys/kauth.h>
#include <sys/callout.h>
#include <sys/proc.h>
#include <sys/kthread.h>
#include <sys/bus.h>
#include <machine/endian.h>
@ -48,6 +49,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.69 2014/12/19 11:54:02 bouyer Exp $");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/sysmon/sysmonvar.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_arp.h>
@ -153,6 +156,7 @@ static void wpi_stop(struct ifnet *, int);
static bool wpi_resume(device_t, const pmf_qual_t *);
static int wpi_getrfkill(struct wpi_softc *);
static void wpi_sysctlattach(struct wpi_softc *);
static void wpi_rsw_thread(void *);
#ifdef WPI_DEBUG
#define DPRINTF(x) do { if (wpi_debug > 0) printf x; } while (0)
@ -214,6 +218,22 @@ wpi_attach(device_t parent __unused, device_t self, void *aux)
sc->sc_pct = pa->pa_pc;
sc->sc_pcitag = pa->pa_tag;
sc->sc_rsw_status = WPI_RSW_UNKNOWN;
sc->sc_rsw.smpsw_name = device_xname(self);
sc->sc_rsw.smpsw_type = PSWITCH_TYPE_RADIO;
error = sysmon_pswitch_register(&sc->sc_rsw);
if (error) {
aprint_error_dev(self,
"unable to register radio switch with sysmon\n");
return;
}
mutex_init(&sc->sc_rsw_mtx, MUTEX_DEFAULT, IPL_NONE);
cv_init(&sc->sc_rsw_cv, "wpirsw");
if (kthread_create(PRI_NONE, 0, NULL,
wpi_rsw_thread, sc, &sc->sc_rsw_lwp, "%s", device_xname(self))) {
aprint_error_dev(self, "couldn't create switch thread\n");
}
callout_init(&sc->calib_to, 0);
callout_setfunc(&sc->calib_to, wpi_calib_timeout, sc);
@ -411,6 +431,13 @@ wpi_detach(device_t self, int flags __unused)
pci_intr_disestablish(sc->sc_pct, sc->sc_ih);
sc->sc_ih = NULL;
}
mutex_enter(&sc->sc_rsw_mtx);
sc->sc_dying = 1;
cv_signal(&sc->sc_rsw_cv);
while (sc->sc_rsw_lwp != NULL)
cv_wait(&sc->sc_rsw_cv, &sc->sc_rsw_mtx);
mutex_exit(&sc->sc_rsw_mtx);
sysmon_pswitch_unregister(&sc->sc_rsw);
bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz);
@ -418,7 +445,8 @@ wpi_detach(device_t self, int flags __unused)
sc->fw_used = false;
wpi_release_firmware();
}
cv_destroy(&sc->sc_rsw_cv);
mutex_destroy(&sc->sc_rsw_mtx);
return 0;
}
@ -1688,6 +1716,8 @@ wpi_notif_intr(struct wpi_softc *sc)
if (le32toh(*status) & 1) {
/* the radio button has to be pushed */
/* wake up thread to signal powerd */
cv_signal(&sc->sc_rsw_cv);
aprint_error_dev(sc->sc_dev,
"Radio transmitter is off\n");
/* turn the interface down */
@ -3276,6 +3306,23 @@ wpi_getrfkill(struct wpi_softc *sc)
tmp = wpi_mem_read(sc, WPI_MEM_RFKILL);
wpi_mem_unlock(sc);
KASSERT(mutex_owned(&sc->sc_rsw_mtx));
if (tmp & 0x01) {
/* switch is on */
if (sc->sc_rsw_status != WPI_RSW_ON) {
sc->sc_rsw_status = WPI_RSW_ON;
sysmon_pswitch_event(&sc->sc_rsw,
PSWITCH_EVENT_PRESSED);
}
} else {
/* switch is off */
if (sc->sc_rsw_status != WPI_RSW_OFF) {
sc->sc_rsw_status = WPI_RSW_OFF;
sysmon_pswitch_event(&sc->sc_rsw,
PSWITCH_EVENT_RELEASED);
}
}
return !(tmp & 0x01);
}
@ -3289,7 +3336,9 @@ wpi_sysctl_radio(SYSCTLFN_ARGS)
node = *rnode;
sc = (struct wpi_softc *)node.sysctl_data;
mutex_enter(&sc->sc_rsw_mtx);
val = !wpi_getrfkill(sc);
mutex_exit(&sc->sc_rsw_mtx);
node.sysctl_data = &val;
error = sysctl_lookup(SYSCTLFN_CALL(&node));
@ -3334,3 +3383,22 @@ wpi_sysctlattach(struct wpi_softc *sc)
err:
aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
}
static void
wpi_rsw_thread(void *arg)
{
struct wpi_softc *sc = (struct wpi_softc *)arg;
mutex_enter(&sc->sc_rsw_mtx);
for (;;) {
cv_timedwait(&sc->sc_rsw_cv, &sc->sc_rsw_mtx, hz);
if (sc->sc_dying) {
sc->sc_rsw_lwp = NULL;
cv_broadcast(&sc->sc_rsw_cv);
mutex_exit(&sc->sc_rsw_mtx);
kthread_exit(0);
}
wpi_getrfkill(sc);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_wpivar.h,v 1.18 2014/08/09 15:07:06 jmcneill Exp $ */
/* $NetBSD: if_wpivar.h,v 1.19 2015/01/06 15:39:54 bouyer Exp $ */
/*-
* Copyright (c) 2006
@ -187,4 +187,13 @@ struct wpi_softc {
bool is_scanning;
struct sysctllog *sc_sysctllog;
struct sysmon_pswitch sc_rsw; /* for radio switch events */
int sc_rsw_status;
#define WPI_RSW_UNKNOWN 0
#define WPI_RSW_OFF 1
#define WPI_RSW_ON 2
struct lwp *sc_rsw_lwp;
struct kmutex sc_rsw_mtx;
struct kcondvar sc_rsw_cv;
int sc_dying;
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysmon_power.c,v 1.48 2014/11/21 23:28:57 joerg Exp $ */
/* $NetBSD: sysmon_power.c,v 1.49 2015/01/06 15:39:54 bouyer Exp $ */
/*-
* Copyright (c) 2007 Juan Romero Pardines.
@ -69,7 +69,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.48 2014/11/21 23:28:57 joerg Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysmon_power.c,v 1.49 2015/01/06 15:39:54 bouyer Exp $");
#include "opt_compat_netbsd.h"
#include <sys/param.h>
@ -121,6 +121,7 @@ static const struct power_event_description pswitch_type_desc[] = {
{ PSWITCH_TYPE_RESET, "reset_button" },
{ PSWITCH_TYPE_ACADAPTER, "acadapter" },
{ PSWITCH_TYPE_HOTKEY, "hotkey_button" },
{ PSWITCH_TYPE_RADIO, "radio_button" },
{ -1, NULL }
};

View File

@ -1,4 +1,4 @@
/* $NetBSD: power.h,v 1.19 2013/03/30 19:05:20 christos Exp $ */
/* $NetBSD: power.h,v 1.20 2015/01/06 15:39:54 bouyer Exp $ */
/*
* Copyright (c) 2003 Wasabi Systems, Inc.
@ -83,6 +83,10 @@
* of switch has state. We know if it is open
* or closed.
*
* Radio switch This is e.g. the switch of the transmitter
* of a wifi interface. We know if it is
* on or off.
*
*/
#define PSWITCH_TYPE_POWER 0 /* power button */
@ -111,6 +115,7 @@
#define PSWITCH_HK_VOLUME_DOWN "volume-down"
#define PSWITCH_HK_VOLUME_MUTE "volume-mute"
#endif /* THINKPAD_NORMAL_HOTKEYS */
#define PSWITCH_TYPE_RADIO 6 /* radio switch */
#define PSWITCH_EVENT_PRESSED 0 /* button pressed, lid closed, AC off */
#define PSWITCH_EVENT_RELEASED 1 /* button released, lid open, AC on */