summaryrefslogtreecommitdiffhomepage
path: root/src/Xmobar/Plugins/Monitors/Wireless.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Xmobar/Plugins/Monitors/Wireless.hs')
-rw-r--r--src/Xmobar/Plugins/Monitors/Wireless.hs73
1 files changed, 69 insertions, 4 deletions
diff --git a/src/Xmobar/Plugins/Monitors/Wireless.hs b/src/Xmobar/Plugins/Monitors/Wireless.hs
index f2b1e6a..28aba50 100644
--- a/src/Xmobar/Plugins/Monitors/Wireless.hs
+++ b/src/Xmobar/Plugins/Monitors/Wireless.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeApplications, CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Monitors.Wireless
@@ -8,16 +9,68 @@
-- Stability : unstable
-- Portability : unportable
--
--- A monitor reporting ESSID and link quality for wireless interfaces
+-- A monitor reporting SSID and signal level for wireless interfaces
--
-----------------------------------------------------------------------------
module Xmobar.Plugins.Monitors.Wireless (wirelessConfig, runWireless) where
import System.Console.GetOpt
+import Data.Maybe (fromMaybe)
import Xmobar.Plugins.Monitors.Common
+
+#ifdef IWLIB
import Network.IWlib
+#elif defined USE_NL80211
+import Control.Exception (bracket)
+import qualified Data.Map as M
+import GHC.Int (Int8)
+import Data.Maybe (listToMaybe)
+import Control.Monad.IO.Class (liftIO)
+import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
+import Data.ByteString.Char8 (unpack)
+import Data.Serialize.Put (runPut, putWord32host, putByteString)
+import Data.Serialize.Get (runGet)
+
+import System.Linux.Netlink hiding (query)
+import System.Linux.Netlink.GeNetlink.NL80211
+import System.Linux.Netlink.GeNetlink.NL80211.StaInfo
+import System.Linux.Netlink.GeNetlink.NL80211.Constants
+import System.Posix.IO (closeFd)
+
+data IwData = IwData { wiEssid :: String, wiSignal :: Maybe Int, wiQuality :: Int }
+
+getWirelessInfo :: String -> IO IwData
+getWirelessInfo ifname = do
+ bracket makeNL80211Socket (closeFd . getFd) (\s -> do
+ iflist <- getInterfaceList s
+ iwdata <- runMaybeT $ do
+ ifidx <- MaybeT . return $ foldr (\(n, i) z ->
+ if (ifname == "" || ifname == n) then Just i else z)
+ Nothing
+ iflist
+ scanp <- liftIO (getConnectedWifi s ifidx) >>=
+ MaybeT . return . listToMaybe
+ bssid <- MaybeT . return $ M.lookup eNL80211_ATTR_BSS (packetAttributes scanp) >>=
+ rightToMaybe . runGet getAttributes >>=
+ M.lookup eNL80211_BSS_BSSID
+ stap <- liftIO (query s eNL80211_CMD_GET_STATION True $ M.fromList
+ [(eNL80211_ATTR_IFINDEX, runPut $ putWord32host ifidx),
+ (eNL80211_ATTR_MAC, runPut $ putByteString bssid)]) >>=
+ MaybeT . return . listToMaybe
+ let ssid = fromMaybe "" $ getWifiAttributes scanp >>= M.lookup eWLAN_EID_SSID >>=
+ return . unpack
+ signal = staInfoFromPacket stap >>= staSignalMBM >>=
+ return . fromIntegral @Int8 . fromIntegral
+ qlty = fromMaybe (-1) (round @Float . (/ 0.7) . (+ 110) .
+ clamp (-110) (-40) . fromIntegral <$> signal)
+ MaybeT . return $ Just $ IwData ssid signal qlty
+ return $ fromMaybe (IwData "" Nothing (-1)) iwdata)
+ where
+ rightToMaybe = either (const Nothing) Just
+ clamp lb up v = if v < lb then lb else if v > up then up else v
+#endif
newtype WirelessOpts = WirelessOpts
{ qualityIconPattern :: Maybe IconPattern
@@ -36,29 +89,41 @@ options =
wirelessConfig :: IO MConfig
wirelessConfig =
- mkMConfig "<essid> <quality>"
- ["essid", "quality", "qualitybar", "qualityvbar", "qualityipat"]
+ mkMConfig "<ssid> <quality>"
+ ["ssid", "essid", "signal", "quality", "qualitybar", "qualityvbar", "qualityipat"]
runWireless :: String -> [String] -> Monitor String
runWireless iface args = do
opts <- io $ parseOptsWith options defaultOpts args
+#ifdef IWLIB
iface' <- if "" == iface then io findInterface else return iface
+#else
+ let iface' = iface
+#endif
wi <- io $ getWirelessInfo iface'
na <- getConfigValue naString
let essid = wiEssid wi
qlty = fromIntegral $ wiQuality wi
e = if essid == "" then na else essid
ep <- showWithPadding e
+#ifdef USE_NL80211
+ let s = wiSignal wi
+#else
+ let s = if qlty >= 0 then Just (qlty * 0.7 - 110) else Nothing
+#endif
+ sp <- showWithPadding $ fromMaybe "" (show <$> s)
q <- if qlty >= 0
then showPercentWithColors (qlty / 100)
else showWithPadding ""
qb <- showPercentBar qlty (qlty / 100)
qvb <- showVerticalBar qlty (qlty / 100)
qipat <- showIconPattern (qualityIconPattern opts) (qlty / 100)
- parseTemplate [ep, q, qb, qvb, qipat]
+ parseTemplate [ep, ep, sp, q, qb, qvb, qipat]
+#ifdef IWLIB
findInterface :: IO String
findInterface = do
c <- readFile "/proc/net/wireless"
let nds = lines c
return $ if length nds > 2 then takeWhile (/= 'c') (nds!!2) else []
+#endif