module Network.IWlib (WirelessInfo(..), getWirelessInfo) where
import Foreign
import Foreign.C.Types
import Foreign.C.String
data WirelessInfo = WirelessInfo { wiEssid :: String, wiQuality :: Int }
deriving Show
data WCfg
data WStats
data WRange
foreign import ccall "iwlib.h iw_sockets_open"
c_iw_open :: IO CInt
foreign import ccall "unistd.h close"
c_iw_close :: CInt -> IO ()
foreign import ccall "iwlib.h iw_get_basic_config"
c_iw_basic_config :: CInt -> CString -> Ptr WCfg -> IO CInt
foreign import ccall "iwlib.h iw_get_stats"
c_iw_stats :: CInt -> CString -> Ptr WStats -> Ptr WRange -> CInt -> IO CInt
foreign import ccall "iwlib.h iw_get_range_info"
c_iw_range :: CInt -> CString -> Ptr WRange -> IO CInt
getWirelessInfo :: String -> IO WirelessInfo
getWirelessInfo iface =
allocaBytes ((184)) $ \wc ->
allocaBytes ((32)) $ \stats ->
allocaBytes ((588)) $ \rng ->
withCString iface $ \istr -> do
i <- c_iw_open
bcr <- c_iw_basic_config i istr wc
str <- c_iw_stats i istr stats rng 1
rgr <- c_iw_range i istr rng
c_iw_close i
if bcr < 0 then return WirelessInfo { wiEssid = "", wiQuality = 0 } else
do hase <- ((\hsc_ptr -> peekByteOff hsc_ptr 128)) wc :: IO CInt
eon <- ((\hsc_ptr -> peekByteOff hsc_ptr 132)) wc :: IO CInt
essid <- if hase /= 0 && eon /= 0 then
do let e = ((\hsc_ptr -> hsc_ptr `plusPtr` 136)) wc
peekCString e
else return ""
q <- if str >= 0 && rgr >=0 then
do qualv <- xqual $ ((\hsc_ptr -> hsc_ptr `plusPtr` 2)) stats
mv <- xqual $ ((\hsc_ptr -> hsc_ptr `plusPtr` 44)) rng
let mxv = if mv /= 0 then fromIntegral mv else 1
return $ fromIntegral qualv / mxv
else return 0
let qv = round (100 * (q :: Double))
return WirelessInfo { wiEssid = essid, wiQuality = min 100 qv }
where xqual p = let qp = ((\hsc_ptr -> hsc_ptr `plusPtr` 0)) p in
((\hsc_ptr -> peekByteOff hsc_ptr 0)) qp :: IO CChar