packages feed

fuyu-gpio-0.0.9.0: src/Fuyu/GPIO/Chip/Watch.hs

{-# LANGUAGE PatternSynonyms #-}

-- |
-- Module      : Fuyu.GPIO.Chip.Watch
-- Description : Operations for watching GPIO line status events.
-- Maintainer  : BassGT
-- Stability   : experimental
-- Portability : POSIX (Linux gpiod v2)
--
-- This module provides managed resource brackets ('withWatchLine', 'withEvent')
-- and functions for watching line status changes (e.g. requested, released, reconfigured).
--
-- It is designed to be imported qualified or used via top-level "Fuyu.GPIO":
--
-- @
-- import qualified Fuyu.GPIO.Chip.Watch as Watch
-- @
module Fuyu.GPIO.Chip.Watch
  ( -- * Types & Patterns
    Chip
  , ReadyChip(..)
  , readyToChip
  , WaitResult(..)
  , LineInfo
  , Offset
  , pattern Offset
  , Timeout
  , pattern Nanoseconds
  , pattern Immediate
  , pattern Infinite
  , Timestamp
  , InfoEvent
  , InfoEventType
  , pattern Requested
  , pattern Released
  , pattern ConfigChanged

    -- * Managed Brackets
  , withWatchLine
  , withEvent

    -- * Line Watch Operations
  , watchLine
  , unwatchLine
  , waitEvent

    -- * InfoEvent Accessors
  , eventType
  , timestampNs
  , lineInfo
  ) where

import Control.Exception (bracket)
import qualified Fuyu.GPIO.Direct as D
import Fuyu.GPIO.Chip.Watch.Unsafe (readInfoEvent, freeInfoEvent)
import Fuyu.GPIO.Exception
import Fuyu.GPIO.Types hiding (eventType)

-- | Start watching a line for status change events (e.g. requested, released, reconfigured)
-- within a bracket, automatically unwatching the line when finished.
--
-- Passes the initial 'LineInfo' snapshot of the line to the callback.
withWatchLine :: Chip -> Offset -> (LineInfo -> IO a) -> IO a
withWatchLine chip offset' = bracket (watchLine chip offset') (\_ -> unwatchLine chip offset')

-- | Start watching a line for status change events (e.g. requested, released, reconfigured).
-- Returns the initial 'LineInfo' snapshot of the line.
watchLine :: Chip -> Offset -> IO LineInfo
watchLine chip offset' = unwrapOrThrow LineInfoFailed (D.chipWatchLineInfo chip offset')

-- | Stop watching a line for status change events.
unwatchLine :: Chip -> Offset -> IO ()
unwatchLine chip offset' = unwrapOrThrow LineInfoFailed (D.chipUnwatchLineInfo chip offset')

-- | Wait for status change info events on any of the watched lines on the chip until the specified timeout.
-- Throws 'WaitInfoEventFailed' on error.
waitEvent :: Chip -> Timeout -> IO (WaitResult ReadyChip)
waitEvent chip timeout = do
  res <- unwrapOrThrow WaitInfoEventFailed (D.chipWaitInfoEvent chip timeout)
  pure $ case res of
    D.EventReady -> EventReady (ReadyChip chip)
    D.Timeout    -> TimeoutResult

-- | Read a status change info event from a chip once 'waitEvent' indicates it is ready,
-- and automatically free it afterwards.
withEvent :: ReadyChip -> (InfoEvent -> IO a) -> IO a
withEvent readyChip = bracket (readInfoEvent readyChip) freeInfoEvent

-- | Get the event type of an 'InfoEvent' ('Requested', 'Released', 'ConfigChanged').
eventType :: InfoEvent -> IO InfoEventType
eventType = D.infoEventType

-- | Get the timestamp in nanoseconds of an 'InfoEvent'.
timestampNs :: InfoEvent -> IO Timestamp
timestampNs = D.infoEventTimestamp

-- | Get the line info snapshot associated with an 'InfoEvent'.
lineInfo :: InfoEvent -> IO LineInfo
lineInfo = D.infoEventLineInfo