diff options
Diffstat (limited to 'src/Xmobar')
| -rw-r--r-- | src/Xmobar/Plugins/Monitors.hs | 8 | ||||
| -rw-r--r-- | src/Xmobar/Plugins/Monitors/Wireless.hs | 73 | 
2 files changed, 73 insertions, 8 deletions
| diff --git a/src/Xmobar/Plugins/Monitors.hs b/src/Xmobar/Plugins/Monitors.hs index d6fc0a0..322d401 100644 --- a/src/Xmobar/Plugins/Monitors.hs +++ b/src/Xmobar/Plugins/Monitors.hs @@ -42,7 +42,7 @@ import Xmobar.Plugins.Monitors.CatInt  #ifdef UVMETER  import Xmobar.Plugins.Monitors.UVMeter  #endif -#ifdef IWLIB +#if defined IWLIB || defined USE_NL80211  import Xmobar.Plugins.Monitors.Wireless  #endif  #ifdef LIBMPD @@ -85,7 +85,7 @@ data Monitors = Network      Interface   Args Rate  #ifdef UVMETER                | UVMeter      Station     Args Rate  #endif -#ifdef IWLIB +#if defined IWLIB || defined USE_NL80211                | Wireless Interface  Args Rate  #endif  #ifdef LIBMPD @@ -142,7 +142,7 @@ instance Exec Monitors where  #ifdef UVMETER      alias (UVMeter s _ _) = "uv " ++ s  #endif -#ifdef IWLIB +#if defined IWLIB || defined USE_NL80211      alias (Wireless i _ _) = i ++ "wi"  #endif  #ifdef LIBMPD @@ -186,7 +186,7 @@ instance Exec Monitors where  #ifdef UVMETER      start (UVMeter s a r) = startUVMeter s a r  #endif -#ifdef IWLIB +#if defined IWLIB || defined USE_NL80211      start (Wireless i a r) = runM a wirelessConfig (runWireless i) r  #endif  #ifdef LIBMPD 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 | 
