[PATCH 2/2] staging:brcm80211:brcmfmac:add rfkill interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add rfkill interface.
This interface will collaborate with wi-fi off or
airplane mode on event from user space.
This feature is essential in fullmac wi-fi model
because it needs to control power tightly.


Signed-off-by: Nohee Ko <noheek@xxxxxxxxxxxx>
---
 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c |   62 ++++++++++++++++++++++
 drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h |    3 +
 2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index 792cffb..014300d 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -342,6 +342,12 @@ static void wl_set_mpc(struct net_device *ndev, int mpc);
 static int wl_debugfs_add_netdev_params(struct wl_priv *wl);
 static void wl_debugfs_remove_netdev(struct wl_priv *wl);
 
+/*
+* rfkill support
+*/
+static int wl_setup_rfkill(struct wl_priv *wl);
+static int wl_rfkill_set(void *data, bool blocked);
+
 #define WL_PRIV_GET() 							\
 	({								\
 	struct wl_iface *ci;						\
@@ -3160,6 +3166,7 @@ static s32 wl_init_priv(struct wl_priv *wl)
 	wl->active_scan = true;	/* we do active scan for
 				 specific scan per default */
 	wl->dongle_up = false;	/* dongle is not up yet */
+	wl->rf_blocked = false;
 	wl_init_eq(wl);
 	err = wl_init_priv_mem(wl);
 	if (unlikely(err))
@@ -3224,6 +3231,12 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
 		WL_ERR(("Failed to init iwm_priv (%d)\n", err));
 		goto cfg80211_attach_out;
 	}
+	err = wl_setup_rfkill(wl);
+	if (unlikely(err)) {
+		WL_ERR(("Failed to setup rfkill %d\n", err));
+		goto cfg80211_attach_out;
+	}
+
 	wl_set_drvdata(wl_cfg80211_dev, ci);
 	set_bit(WL_STATUS_READY, &wl->status);
 
@@ -3240,6 +3253,9 @@ void wl_cfg80211_detach(void)
 
 	wl = WL_PRIV_GET();
 
+	rfkill_unregister(wl->rfkill);
+	rfkill_destroy(wl->rfkill);
+
 	wl_deinit_priv(wl);
 	wl_free_wdev(wl);
 	wl_set_drvdata(wl_cfg80211_dev, NULL);
@@ -4264,3 +4280,49 @@ static __used void wl_dongle_poweroff(struct wl_priv *wl)
 	net_os_set_dtim_skip(ndev, 0);
 	dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
 }
+
+static const struct rfkill_ops wl_rfkill_ops = {
+	.set_block = wl_rfkill_set,
+};
+
+static int wl_rfkill_set(void *data, bool blocked)
+{
+	struct wl_priv *wl = (struct wl_priv *)data;
+
+	WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
+
+	if (blocked) {
+		if (!wl->rf_blocked)
+			wl_dongle_poweroff(wl);
+	} else {
+		if (wl->rf_blocked)
+			wl_dongle_poweron(wl);
+	}
+
+	wl->rf_blocked = blocked;
+
+	return 0;
+}
+
+static int wl_setup_rfkill(struct wl_priv *wl)
+{
+	s32 err;
+
+	wl->rfkill = rfkill_alloc("brcmfmac-wifi",
+		&wl_cfg80211_get_sdio_func()->dev,
+		RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
+
+	if (!wl->rfkill) {
+		err =  -ENOMEM;
+		goto err_out;
+	}
+
+	err = rfkill_register(wl->rfkill);
+
+	if (err)
+		rfkill_destroy(wl->rfkill);
+
+err_out:
+	return err;
+
+}
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
index f90ecae..d5c6fe8 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -23,6 +23,7 @@
 #include <wlioctl.h>
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
+#include <linux/rfkill.h>
 
 struct wl_conf;
 struct wl_iface;
@@ -342,6 +343,8 @@ struct wl_priv {
 	u8 *ioctl_buf;	/* ioctl buffer */
 	u8 *extra_buf;	/* maily to grab assoc information */
 	struct dentry *debugfsdir;
+	struct rfkill *rfkill;
+	bool rf_blocked;
 	u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
 };
 
-- 
1.7.0.4

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux