{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InterruptibleFFI #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module System.GPIO.Linux.Sysfs.IO
(
SysfsIOT(..)
) where
import Protolude hiding (bracket)
import Control.Monad.Base (MonadBase)
import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow, bracket)
import Control.Monad.Cont (MonadCont)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Logger (MonadLogger, MonadLoggerIO)
import Control.Monad.RWS (MonadRWS)
import Control.Monad.Trans.Class (MonadTrans(..))
import Control.Monad.Trans.Control
(ComposeSt, MonadBaseControl(..), MonadTransControl(..),
defaultLiftBaseWith, defaultRestoreM)
import Control.Monad.Writer (MonadWriter)
import qualified Data.ByteString as BS (readFile, writeFile)
import Foreign.C.Error (throwErrnoIfMinus1Retry)
import Foreign.C.Types (CInt(..))
import qualified System.Directory as D (doesDirectoryExist, doesFileExist, getDirectoryContents)
import "unix" System.Posix.IO (OpenMode(ReadOnly, WriteOnly), closeFd, defaultFileFlags, openFd)
import "unix-bytestring" System.Posix.IO.ByteString (fdWrite)
import System.GPIO.Linux.Sysfs.Monad (MonadSysfs(..))
newtype SysfsIOT m a = SysfsIOT
{ runSysfsIOT :: m a
} deriving ( Functor
, Alternative
, Applicative
, Monad
, MonadBase b
, MonadFix
, MonadPlus
, MonadThrow
, MonadCatch
, MonadMask
, MonadCont
, MonadIO
, MonadReader r
, MonadError e
, MonadWriter w
, MonadState s
, MonadRWS r w s
, MonadLogger
, MonadLoggerIO
)
instance MonadTrans SysfsIOT where
lift = SysfsIOT
instance MonadBaseControl b m => MonadBaseControl b (SysfsIOT m) where
type StM (SysfsIOT m) a = ComposeSt SysfsIOT m a
liftBaseWith = defaultLiftBaseWith
restoreM = defaultRestoreM
{-# INLINABLE liftBaseWith #-}
{-# INLINABLE restoreM #-}
instance MonadTransControl SysfsIOT where
type StT SysfsIOT a = a
liftWith f = SysfsIOT $ f runSysfsIOT
restoreT = SysfsIOT
{-# INLINABLE liftWith #-}
{-# INLINABLE restoreT #-}
instance (MonadIO m, MonadThrow m) => MonadSysfs (SysfsIOT m) where
doesDirectoryExist = liftIO . D.doesDirectoryExist
doesFileExist = liftIO . D.doesFileExist
getDirectoryContents = liftIO . D.getDirectoryContents
readFile = liftIO . BS.readFile
writeFile fn bs = liftIO $ BS.writeFile fn bs
unlockedWriteFile fn bs = liftIO $ unlockedWriteFileIO fn bs
pollFile fn timeout = liftIO $ pollFileIO fn timeout
unlockedWriteFileIO :: FilePath -> ByteString -> IO ()
unlockedWriteFileIO fn bs =
bracket
(openFd fn WriteOnly Nothing defaultFileFlags)
closeFd
(\fd -> void $ fdWrite fd bs)
foreign import ccall interruptible "pollSysfs" pollSysfs :: CInt -> CInt -> IO CInt
pollFileIO :: FilePath -> Int -> IO CInt
pollFileIO fn timeout =
bracket
(openFd fn ReadOnly Nothing defaultFileFlags)
closeFd
(\fd -> throwErrnoIfMinus1Retry "pollSysfs" $ pollSysfs (fromIntegral fd) (fromIntegral timeout))