-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Monads for GPIO in Haskell
--   
--   This package provides an embedded DSL for writing cross-platform GPIO
--   programs in Haskell. Currently only Linux is supported (via the
--   <tt>sysfs</tt> filesystem), but other Unix GPIO platforms will be
--   supported in the future.
--   
--   Monads and low-level actions are also provided for each supported
--   platform's native GPIO API, if you want to program directly to the
--   platform API.
--   
--   Example programs are provided in the <a>examples</a> directory of the
--   source code distribution. There is also a <a>System.GPIO.Tutorial</a>
--   module, which explains how to use the cross-platform DSL.
@package hpio
@version 0.9.0.6


-- | Basic GPIO types.
module System.GPIO.Types

-- | A GPIO pin, identified by pin number.
--   
--   Note that GPIO pin numbering is platform- and runtime-dependent. See
--   the documentation for your particular platform for an explanation of
--   how pin numbers are assigned to physical pins.
newtype Pin
Pin :: Int -> Pin

-- | GPIO pins may support a number of different physical configurations
--   when used as a digital input.
--   
--   Pins that are capable of input will at least support the
--   <a>InputDefault</a> mode. <a>InputDefault</a> mode is special in that,
--   unlike the other input modes, it does not represent a unique physical
--   configuration, but is simply a pseudonym for another (actual) input
--   mode. Exactly which mode is used by the hardware when
--   <a>InputDefault</a> mode is specified is platform-dependent. By using
--   <tt>InputDefaut</tt> mode, you are saying that you don't care about
--   the pin's actual configuration, other than the fact that it's being
--   used for input.
data PinInputMode

-- | The pin's default input mode, i.e., the mode used when a more specific
--   mode is not specified
InputDefault :: PinInputMode

-- | A floating / high-impedance / tri-state mode which uses little power,
--   but when disconnected, may cause the pin's value to be indeterminate
InputFloating :: PinInputMode

-- | The pin is connected to an internal pull-up resistor such that, when
--   the pin is disconnected or connected to a floating / high-impedance
--   node, its physical value will be <a>High</a>
InputPullUp :: PinInputMode

-- | The pin is connected to an internal pull-down resistor such that, when
--   the pin is disconnected or connected to a floating / high-impedance
--   node, its physical value will be <a>Low</a>
InputPullDown :: PinInputMode

-- | GPIO pins may support a number of different physical configurations
--   when used as a digital output.
--   
--   Pins that are capable of output will at least support the
--   <a>OutputDefault</a> mode. <a>OutputDefault</a> mode is special in
--   that, unlike the other output modes, it does not represent a unique
--   physical configuration, but is simply a pseudonym for another (actual)
--   output mode. Exactly which mode is used by the hardware when
--   <a>OutputDefault</a> mode is specified is platform-dependent. By using
--   <tt>OutputDefaut</tt> mode, you are saying that you don't care about
--   the pin's actual configuration, other than the fact that it's being
--   used for output.
data PinOutputMode

-- | The pin's default output mode, i.e., the mode used when a more
--   specific mode is not specified
OutputDefault :: PinOutputMode

-- | The output actively drives both the <a>High</a> and <a>Low</a> states
OutputPushPull :: PinOutputMode

-- | The output actively drives the <a>Low</a> state, but <a>High</a> is
--   left floating (also known as <i>open collector</i>)
OutputOpenDrain :: PinOutputMode

-- | The output actively drives the <a>Low</a> state, and is connected to
--   an internal pull-up resistor in the <a>High</a> state.
OutputOpenDrainPullUp :: PinOutputMode

-- | The output actively drives the <a>High</a> state, but <a>Low</a> is
--   left floating (also known as <i>open emitter</i>)
OutputOpenSource :: PinOutputMode

-- | The output actively drives the <a>High</a> state, and is connected to
--   an internal pull-down resistor in the <a>Low</a> state.
OutputOpenSourcePullDown :: PinOutputMode

-- | Catalog a pin's capabilities.
data PinCapabilities
PinCapabilities :: Set PinInputMode -> Set PinOutputMode -> Bool -> PinCapabilities

-- | The set of input modes that the pin supports
[_inputModes] :: PinCapabilities -> Set PinInputMode

-- | The set of output modes that the pin supports
[_outputModes] :: PinCapabilities -> Set PinOutputMode

-- | Does the pin support interrupts in input mode?
[_interrupts] :: PinCapabilities -> Bool

-- | A pin's direction (input/output).
data PinDirection
In :: PinDirection
Out :: PinDirection

-- | A pin's active level (active-high/active-low).
data PinActiveLevel
ActiveLow :: PinActiveLevel
ActiveHigh :: PinActiveLevel

-- | A pin's signal level as a binary value.
data PinValue
Low :: PinValue
High :: PinValue

-- | A pin's interrupt mode.
--   
--   Note that the pin's interrupt mode is defined in terms of the pin's
--   <i>logical</i> signal value; i.e., when the pin is configured for
--   active-low logic, <a>RisingEdge</a> refers to the physical signal's
--   trailing edge, and <a>FallingEdge</a> refers to the physical signal's
--   rising edge.
data PinInterruptMode

-- | Interrupts are disabled
Disabled :: PinInterruptMode

-- | Interrupt on the pin's (logical) rising edge
RisingEdge :: PinInterruptMode

-- | Interrupt on the pin's (logical) falling edge
FallingEdge :: PinInterruptMode

-- | Interrupt on any change to the pin's signal level
Level :: PinInterruptMode

-- | Get the pin number as an <a>Int</a>.
--   
--   <pre>
--   &gt;&gt;&gt; pinNumber (Pin 5)
--   5
--   </pre>
pinNumber :: Pin -> Int

-- | Invert a <a>PinDirection</a> value.
--   
--   <pre>
--   &gt;&gt;&gt; invertDirection In
--   Out
--   
--   &gt;&gt;&gt; invertDirection Out
--   In
--   </pre>
invertDirection :: PinDirection -> PinDirection

-- | Invert a <a>PinValue</a>.
--   
--   <pre>
--   &gt;&gt;&gt; invertValue High
--   Low
--   
--   &gt;&gt;&gt; invertValue Low
--   High
--   </pre>
invertValue :: PinValue -> PinValue

-- | Convert a <a>PinValue</a> to its logical boolean equivalent.
--   
--   <pre>
--   &gt;&gt;&gt; valueToBool High
--   True
--   
--   &gt;&gt;&gt; valueToBool Low
--   False
--   </pre>
valueToBool :: PinValue -> Bool

-- | Convert a <a>Bool</a> to its logical <a>PinValue</a> equivalent.
--   
--   <pre>
--   &gt;&gt;&gt; boolToValue True
--   High
--   
--   &gt;&gt;&gt; boolToValue False
--   Low
--   </pre>
boolToValue :: Bool -> PinValue

-- | The top level of the GPIO exception hierarchy.
data SomeGpioException
SomeGpioException :: e -> SomeGpioException

-- | Convert <a>SomeGpioException</a> to <a>SomeException</a>.
gpioExceptionToException :: Exception e => e -> SomeException

-- | Ask whether an exception is <a>SomeGpioException</a>.
gpioExceptionFromException :: Exception e => SomeException -> Maybe e
instance GHC.Generics.Generic System.GPIO.Types.PinInterruptMode
instance GHC.Show.Show System.GPIO.Types.PinInterruptMode
instance GHC.Read.Read System.GPIO.Types.PinInterruptMode
instance GHC.Classes.Ord System.GPIO.Types.PinInterruptMode
instance Data.Data.Data System.GPIO.Types.PinInterruptMode
instance GHC.Classes.Eq System.GPIO.Types.PinInterruptMode
instance GHC.Enum.Enum System.GPIO.Types.PinInterruptMode
instance GHC.Enum.Bounded System.GPIO.Types.PinInterruptMode
instance GHC.Generics.Generic System.GPIO.Types.PinValue
instance GHC.Arr.Ix System.GPIO.Types.PinValue
instance GHC.Show.Show System.GPIO.Types.PinValue
instance GHC.Read.Read System.GPIO.Types.PinValue
instance GHC.Classes.Ord System.GPIO.Types.PinValue
instance Data.Data.Data System.GPIO.Types.PinValue
instance GHC.Classes.Eq System.GPIO.Types.PinValue
instance GHC.Enum.Enum System.GPIO.Types.PinValue
instance GHC.Enum.Bounded System.GPIO.Types.PinValue
instance GHC.Generics.Generic System.GPIO.Types.PinActiveLevel
instance GHC.Arr.Ix System.GPIO.Types.PinActiveLevel
instance GHC.Show.Show System.GPIO.Types.PinActiveLevel
instance GHC.Read.Read System.GPIO.Types.PinActiveLevel
instance GHC.Classes.Ord System.GPIO.Types.PinActiveLevel
instance Data.Data.Data System.GPIO.Types.PinActiveLevel
instance GHC.Classes.Eq System.GPIO.Types.PinActiveLevel
instance GHC.Enum.Enum System.GPIO.Types.PinActiveLevel
instance GHC.Enum.Bounded System.GPIO.Types.PinActiveLevel
instance GHC.Generics.Generic System.GPIO.Types.PinDirection
instance GHC.Arr.Ix System.GPIO.Types.PinDirection
instance GHC.Show.Show System.GPIO.Types.PinDirection
instance GHC.Read.Read System.GPIO.Types.PinDirection
instance GHC.Classes.Ord System.GPIO.Types.PinDirection
instance Data.Data.Data System.GPIO.Types.PinDirection
instance GHC.Classes.Eq System.GPIO.Types.PinDirection
instance GHC.Enum.Enum System.GPIO.Types.PinDirection
instance GHC.Enum.Bounded System.GPIO.Types.PinDirection
instance GHC.Generics.Generic System.GPIO.Types.PinCapabilities
instance GHC.Show.Show System.GPIO.Types.PinCapabilities
instance GHC.Classes.Eq System.GPIO.Types.PinCapabilities
instance GHC.Generics.Generic System.GPIO.Types.PinOutputMode
instance GHC.Show.Show System.GPIO.Types.PinOutputMode
instance GHC.Read.Read System.GPIO.Types.PinOutputMode
instance Data.Data.Data System.GPIO.Types.PinOutputMode
instance GHC.Classes.Ord System.GPIO.Types.PinOutputMode
instance GHC.Classes.Eq System.GPIO.Types.PinOutputMode
instance GHC.Enum.Enum System.GPIO.Types.PinOutputMode
instance GHC.Enum.Bounded System.GPIO.Types.PinOutputMode
instance GHC.Generics.Generic System.GPIO.Types.PinInputMode
instance GHC.Show.Show System.GPIO.Types.PinInputMode
instance GHC.Read.Read System.GPIO.Types.PinInputMode
instance Data.Data.Data System.GPIO.Types.PinInputMode
instance GHC.Classes.Ord System.GPIO.Types.PinInputMode
instance GHC.Classes.Eq System.GPIO.Types.PinInputMode
instance GHC.Enum.Enum System.GPIO.Types.PinInputMode
instance GHC.Enum.Bounded System.GPIO.Types.PinInputMode
instance GHC.Generics.Generic System.GPIO.Types.Pin
instance GHC.Show.Show System.GPIO.Types.Pin
instance GHC.Arr.Ix System.GPIO.Types.Pin
instance GHC.Read.Read System.GPIO.Types.Pin
instance GHC.Classes.Ord System.GPIO.Types.Pin
instance Data.Data.Data System.GPIO.Types.Pin
instance GHC.Classes.Eq System.GPIO.Types.Pin
instance GHC.Enum.Enum System.GPIO.Types.Pin
instance GHC.Enum.Bounded System.GPIO.Types.Pin
instance GHC.Show.Show System.GPIO.Types.SomeGpioException
instance GHC.Exception.Exception System.GPIO.Types.SomeGpioException
instance Test.QuickCheck.Arbitrary.Arbitrary System.GPIO.Types.PinInterruptMode
instance Data.Bits.Bits System.GPIO.Types.PinValue
instance Data.Bits.FiniteBits System.GPIO.Types.PinValue
instance Test.QuickCheck.Arbitrary.Arbitrary System.GPIO.Types.PinValue
instance Test.QuickCheck.Arbitrary.Arbitrary System.GPIO.Types.PinActiveLevel
instance Test.QuickCheck.Arbitrary.Arbitrary System.GPIO.Types.PinDirection
instance Test.QuickCheck.Arbitrary.Arbitrary System.GPIO.Types.Pin


-- | A monadic context for GPIO computations.
module System.GPIO.Monad

-- | A GPIO pin, identified by pin number.
--   
--   Note that GPIO pin numbering is platform- and runtime-dependent. See
--   the documentation for your particular platform for an explanation of
--   how pin numbers are assigned to physical pins.
newtype Pin
Pin :: Int -> Pin

-- | Get the pin number as an <a>Int</a>.
--   
--   <pre>
--   &gt;&gt;&gt; pinNumber (Pin 5)
--   5
--   </pre>
pinNumber :: Pin -> Int

-- | GPIO pins may support a number of different physical configurations
--   when used as a digital input.
--   
--   Pins that are capable of input will at least support the
--   <a>InputDefault</a> mode. <a>InputDefault</a> mode is special in that,
--   unlike the other input modes, it does not represent a unique physical
--   configuration, but is simply a pseudonym for another (actual) input
--   mode. Exactly which mode is used by the hardware when
--   <a>InputDefault</a> mode is specified is platform-dependent. By using
--   <tt>InputDefaut</tt> mode, you are saying that you don't care about
--   the pin's actual configuration, other than the fact that it's being
--   used for input.
data PinInputMode

-- | The pin's default input mode, i.e., the mode used when a more specific
--   mode is not specified
InputDefault :: PinInputMode

-- | A floating / high-impedance / tri-state mode which uses little power,
--   but when disconnected, may cause the pin's value to be indeterminate
InputFloating :: PinInputMode

-- | The pin is connected to an internal pull-up resistor such that, when
--   the pin is disconnected or connected to a floating / high-impedance
--   node, its physical value will be <a>High</a>
InputPullUp :: PinInputMode

-- | The pin is connected to an internal pull-down resistor such that, when
--   the pin is disconnected or connected to a floating / high-impedance
--   node, its physical value will be <a>Low</a>
InputPullDown :: PinInputMode

-- | GPIO pins may support a number of different physical configurations
--   when used as a digital output.
--   
--   Pins that are capable of output will at least support the
--   <a>OutputDefault</a> mode. <a>OutputDefault</a> mode is special in
--   that, unlike the other output modes, it does not represent a unique
--   physical configuration, but is simply a pseudonym for another (actual)
--   output mode. Exactly which mode is used by the hardware when
--   <a>OutputDefault</a> mode is specified is platform-dependent. By using
--   <tt>OutputDefaut</tt> mode, you are saying that you don't care about
--   the pin's actual configuration, other than the fact that it's being
--   used for output.
data PinOutputMode

-- | The pin's default output mode, i.e., the mode used when a more
--   specific mode is not specified
OutputDefault :: PinOutputMode

-- | The output actively drives both the <a>High</a> and <a>Low</a> states
OutputPushPull :: PinOutputMode

-- | The output actively drives the <a>Low</a> state, but <a>High</a> is
--   left floating (also known as <i>open collector</i>)
OutputOpenDrain :: PinOutputMode

-- | The output actively drives the <a>Low</a> state, and is connected to
--   an internal pull-up resistor in the <a>High</a> state.
OutputOpenDrainPullUp :: PinOutputMode

-- | The output actively drives the <a>High</a> state, but <a>Low</a> is
--   left floating (also known as <i>open emitter</i>)
OutputOpenSource :: PinOutputMode

-- | The output actively drives the <a>High</a> state, and is connected to
--   an internal pull-down resistor in the <a>Low</a> state.
OutputOpenSourcePullDown :: PinOutputMode

-- | Catalog a pin's capabilities.
data PinCapabilities
PinCapabilities :: Set PinInputMode -> Set PinOutputMode -> Bool -> PinCapabilities

-- | The set of input modes that the pin supports
[_inputModes] :: PinCapabilities -> Set PinInputMode

-- | The set of output modes that the pin supports
[_outputModes] :: PinCapabilities -> Set PinOutputMode

-- | Does the pin support interrupts in input mode?
[_interrupts] :: PinCapabilities -> Bool

-- | A pin's direction (input/output).
data PinDirection
In :: PinDirection
Out :: PinDirection

-- | A pin's active level (active-high/active-low).
data PinActiveLevel
ActiveLow :: PinActiveLevel
ActiveHigh :: PinActiveLevel

-- | A pin's signal level as a binary value.
data PinValue
Low :: PinValue
High :: PinValue

-- | A pin's interrupt mode.
--   
--   Note that the pin's interrupt mode is defined in terms of the pin's
--   <i>logical</i> signal value; i.e., when the pin is configured for
--   active-low logic, <a>RisingEdge</a> refers to the physical signal's
--   trailing edge, and <a>FallingEdge</a> refers to the physical signal's
--   rising edge.
data PinInterruptMode

-- | Interrupts are disabled
Disabled :: PinInterruptMode

-- | Interrupt on the pin's (logical) rising edge
RisingEdge :: PinInterruptMode

-- | Interrupt on the pin's (logical) falling edge
FallingEdge :: PinInterruptMode

-- | Interrupt on any change to the pin's signal level
Level :: PinInterruptMode
type MaskGpioM h m = (MonadMask m, MonadGpio h m)
type ThrowGpioM h m = (MonadThrow m, MonadGpio h m)

-- | A monad type class for GPIO computations. The type class specifies a
--   DSL for writing portable GPIO programs, and instances of the type
--   class provide the interpreter needed to run these programs on a
--   particular GPIO platform.
--   
--   In the type signature, <tt>h</tt> represents a (platform-dependent)
--   abstract pin handle for operating on opened pins. It is analogous to a
--   file handle.
--   
--   <h2>Active-high versus active-low logic</h2>
--   
--   The DSL supports both <i>active-high</i> and <i>active-low</i> logic.
--   That is, the <i>active level</i> of a GPIO pin can be configured as
--   <a>ActiveHigh</a> or <a>ActiveLow</a>. If a pin's active level is
--   <a>ActiveHigh</a>, then for that pin, a <a>PinValue</a> of <a>High</a>
--   corresponds to a "high" physical signal level, and a <a>PinValue</a>
--   of <a>Low</a> corresponds to a "low" physical signal level. The
--   converse is true when the pin's active level is <a>ActiveLow</a>.
--   
--   Despite the potential confusion, the advantage of supporting
--   active-low logic is that you can, if you choose, write your program in
--   terms of "positive" logic (where <a>High</a> always means "on" and
--   <a>Low</a> always means "off"), and, with the same program, interface
--   with either positive (active-high) or negative (active-low) logic
--   simply by setting the pin's active level before running the program.
--   
--   In the documentation for this package, whenever you see a reference to
--   a "pin value" or "signal level," unless otherwise noted, we mean the
--   <i>logical</i> value or level, not the <i>physical</i> value or level;
--   that is, we mean the abstract notion of the pin being "on" or "off,"
--   independent of the voltage level seen on the physical pin. If the pin
--   is configured as active-high, then the logical and physical values are
--   one and the same; if not, they are the inverse of each other.
--   
--   Note that the active-high/active-low setting is per-pin; each pin's
--   active level is independent of the others.
--   
--   Not all platforms natively support active-low logic. On platforms
--   without native support, the platform interpreter will invert values
--   (both read and written) in software when a pin is configured as
--   active-low.
class Monad m => MonadGpio h m | m -> h

-- | Get a list of available GPIO pins on the system.
--   
--   This command makes a best-effort attempt to find the available pins,
--   but some systems may not make the complete list available at runtime.
--   Therefore, there may be more pins available than are returned by this
--   action.
pins :: MonadGpio h m => m [Pin]

-- | Query the pin's capabilities.
pinCapabilities :: MonadGpio h m => Pin -> m PinCapabilities

-- | Open a pin for use and return a handle to it.
--   
--   Note that on some platforms (notably Linux), pin handles are global
--   resources and it is, strictly speaking, an error to attempt to open a
--   pin which has already been opened. However, because there is generally
--   no way to perform an atomic "only open the pin if it hasn't already
--   been opened" operation on such platforms, this action will squash that
--   particular error on those platforms and return the global handle
--   anyway, without making any other state changes to the already-opened
--   pin.
--   
--   Keep in mind, however, that on these platforms where pin handles are
--   global resources, closing one pin handle will effectively invalidate
--   all other handles for the same pin. Be very careful to coordinate the
--   opening and closing of pins if you are operating on the same pin in
--   multiple threads.
openPin :: MonadGpio h m => Pin -> m h

-- | Close the pin; i.e., indicate to the system that you no longer intend
--   to use the pin via the given handle.
--   
--   Note that on some platforms (notably Linux), pin handles are global
--   resources and it is, strictly speaking, an error to attempt to close a
--   pin which has already been closed via another handle to the same pin.
--   However, this action will squash that error on those platforms and
--   will simply return without making any changes to the GPIO environment.
--   
--   Keep in mind, however, that on these platforms where pin handles are
--   global resources, opening multiple handles for the same pin and then
--   closing one of those handles will render all other handles for the
--   same pin invalid. Be very careful to coordinate the opening and
--   closing of pins if you are operating on the same pin in multiple
--   threads.
--   
--   Note that there are also platforms (again, notably certain Linux
--   systems) where some pins are effectively always open and cannot be
--   closed. Invoking this action on such a pin will squash any error that
--   occurs when attempting to close the pin, and the action will simply
--   return without making any changes to the GPIO environment.
closePin :: MonadGpio h m => h -> m ()

-- | Get the pin's currently configured direction.
--   
--   Note that there is no <tt>setPinDirection</tt> action. You set the
--   pin's direction indirectly by setting its input mode or output mode
--   via <a>setPinInputMode</a> and <a>setPinOutputMode</a>, respectively.
--   
--   Rarely, a particular pin's direction may not be available in a
--   cross-platform way. In these cases, calling this action is an error.
--   In general, though, if the pin's capabilities indicate that it
--   supports at least one <a>PinInputMode</a> or <a>PinOutputMode</a>,
--   it's safe to call this action.
getPinDirection :: MonadGpio h m => h -> m PinDirection

-- | Get the pin's input mode.
--   
--   If the pin is not currently configured for input, it's an error to
--   call this action.
getPinInputMode :: MonadGpio h m => h -> m PinInputMode

-- | Set the pin's input mode. This action will also set the pin's
--   direction to <a>In</a>.
--   
--   It is an error to call this action if the given pin does not support
--   the given input mode.
setPinInputMode :: MonadGpio h m => h -> PinInputMode -> m ()

-- | Get the pin's output mode.
--   
--   If the pin is not currently configured for output, it's an error to
--   call this action.
getPinOutputMode :: MonadGpio h m => h -> m PinOutputMode

-- | Set the pin's output mode and value. This action will also set the
--   pin's direction to <a>Out</a>
--   
--   If the pin is already in output mode and you only want to change its
--   value, use <a>writePin</a>.
--   
--   It is an error to call this action if the given pin does not support
--   the given output mode.
setPinOutputMode :: MonadGpio h m => h -> PinOutputMode -> PinValue -> m ()

-- | Read the pin's value.
--   
--   Note that this action never blocks.
readPin :: MonadGpio h m => h -> m PinValue

-- | Block the current thread until an event occurs on the pin which
--   corresponds to the pin's current interrupt mode. Upon detection of the
--   event, return the pin's value.
--   
--   If the pin does not support interrupts, then this action's behavior is
--   plaform-dependent.
--   
--   It is an error to call this action when the pin is not configured for
--   input.
--   
--   Note: due to its interaction with the threading system, this action
--   may behave differently across different implementations of Haskell. It
--   has only been tested with GHC. (On GHC, you should compile any program
--   that uses this action with the <tt>-threaded</tt> option.)
pollPin :: MonadGpio h m => h -> m PinValue

-- | Same as <a>pollPin</a>, except with a timeout, specified in
--   microseconds. If no event occurs before the timeout expires, this
--   action returns <a>Nothing</a>; otherwise, it returns the pin's signal
--   level wrapped in a <a>Just</a>.
--   
--   If the timeout value is negative, this action behaves just like
--   <a>pollPin</a>.
--   
--   If the pin does not support interrupts, then this action's behavior is
--   platform-dependent.
--   
--   It is an error to call this action when the pin is not configured for
--   input.
--   
--   Note: due to its interaction with the threading system, this action
--   may behave differently across different implementations of Haskell. It
--   has only been tested with GHC. (On GHC, you should compile any program
--   that uses this action with the <tt>-threaded</tt> option.)
pollPinTimeout :: MonadGpio h m => h -> Int -> m (Maybe PinValue)

-- | Set the pin's output value.
--   
--   It is an error to call this action when the pin is not configured for
--   output.
writePin :: MonadGpio h m => h -> PinValue -> m ()

-- | Toggle the pin's output value and return the pin's new output value.
--   
--   It is an error to call this action when the pin is not configured for
--   output.
togglePin :: MonadGpio h m => h -> m PinValue

-- | Get the pin's interrupt mode.
--   
--   If the pin does not support interrupts, it is an error to call this
--   action.
--   
--   (Note that <a>RisingEdge</a> and <a>FallingEdge</a> are relative to
--   the pin's active level; i.e., they refer to the pin's <i>logical</i>
--   signal edges, not its physical signal edges.)
getPinInterruptMode :: MonadGpio h m => h -> m PinInterruptMode

-- | Set the pin's interrupt mode (only when the pin is configured for
--   input).
--   
--   A pin's interrupt mode determines the behavior of the <a>pollPin</a>
--   and <a>pollPinTimeout</a> actions. Those actions will block the
--   current thread on an input pin until a particular event occurs on that
--   pin's signal waveform: a low-to-high transition (<a>RisingEdge</a>), a
--   high-to-low transition (<a>FallingEdge</a>), or any change of level
--   (<a>Level</a>).
--   
--   You can also disable interrupts on the pin so that <a>pollPin</a> will
--   block the current thread indefinitely (or until a timer expires, in
--   the case of <a>pollPinTimeout</a>). This functionality is useful when,
--   for example, one thread is dedicated to servicing interrupts on a pin,
--   and another thread wants to mask interrupts on that pin for some
--   period of time.
--   
--   Some pins (or even some GPIO platforms) may not support interrupts. In
--   such cases, it is an error to call this action.
--   
--   It is an error to use this action on a pin configured for output.
setPinInterruptMode :: MonadGpio h m => h -> PinInterruptMode -> m ()

-- | Get the pin's active level.
getPinActiveLevel :: MonadGpio h m => h -> m PinActiveLevel

-- | Set the pin's active level.
setPinActiveLevel :: MonadGpio h m => h -> PinActiveLevel -> m ()

-- | Toggle the pin's active level. Returns the pin's new level.
togglePinActiveLevel :: MonadGpio h m => h -> m PinActiveLevel

-- | Get a list of available GPIO pins on the system.
--   
--   This command makes a best-effort attempt to find the available pins,
--   but some systems may not make the complete list available at runtime.
--   Therefore, there may be more pins available than are returned by this
--   action.
pins :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => m [Pin]

-- | Query the pin's capabilities.
pinCapabilities :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => Pin -> m PinCapabilities

-- | Open a pin for use and return a handle to it.
--   
--   Note that on some platforms (notably Linux), pin handles are global
--   resources and it is, strictly speaking, an error to attempt to open a
--   pin which has already been opened. However, because there is generally
--   no way to perform an atomic "only open the pin if it hasn't already
--   been opened" operation on such platforms, this action will squash that
--   particular error on those platforms and return the global handle
--   anyway, without making any other state changes to the already-opened
--   pin.
--   
--   Keep in mind, however, that on these platforms where pin handles are
--   global resources, closing one pin handle will effectively invalidate
--   all other handles for the same pin. Be very careful to coordinate the
--   opening and closing of pins if you are operating on the same pin in
--   multiple threads.
openPin :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => Pin -> m h

-- | Close the pin; i.e., indicate to the system that you no longer intend
--   to use the pin via the given handle.
--   
--   Note that on some platforms (notably Linux), pin handles are global
--   resources and it is, strictly speaking, an error to attempt to close a
--   pin which has already been closed via another handle to the same pin.
--   However, this action will squash that error on those platforms and
--   will simply return without making any changes to the GPIO environment.
--   
--   Keep in mind, however, that on these platforms where pin handles are
--   global resources, opening multiple handles for the same pin and then
--   closing one of those handles will render all other handles for the
--   same pin invalid. Be very careful to coordinate the opening and
--   closing of pins if you are operating on the same pin in multiple
--   threads.
--   
--   Note that there are also platforms (again, notably certain Linux
--   systems) where some pins are effectively always open and cannot be
--   closed. Invoking this action on such a pin will squash any error that
--   occurs when attempting to close the pin, and the action will simply
--   return without making any changes to the GPIO environment.
closePin :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m ()

-- | Get the pin's currently configured direction.
--   
--   Note that there is no <tt>setPinDirection</tt> action. You set the
--   pin's direction indirectly by setting its input mode or output mode
--   via <a>setPinInputMode</a> and <a>setPinOutputMode</a>, respectively.
--   
--   Rarely, a particular pin's direction may not be available in a
--   cross-platform way. In these cases, calling this action is an error.
--   In general, though, if the pin's capabilities indicate that it
--   supports at least one <a>PinInputMode</a> or <a>PinOutputMode</a>,
--   it's safe to call this action.
getPinDirection :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinDirection

-- | Get the pin's input mode.
--   
--   If the pin is not currently configured for input, it's an error to
--   call this action.
getPinInputMode :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinInputMode

-- | Set the pin's input mode. This action will also set the pin's
--   direction to <a>In</a>.
--   
--   It is an error to call this action if the given pin does not support
--   the given input mode.
setPinInputMode :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> PinInputMode -> m ()

-- | Get the pin's output mode.
--   
--   If the pin is not currently configured for output, it's an error to
--   call this action.
getPinOutputMode :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinOutputMode

-- | Set the pin's output mode and value. This action will also set the
--   pin's direction to <a>Out</a>
--   
--   If the pin is already in output mode and you only want to change its
--   value, use <a>writePin</a>.
--   
--   It is an error to call this action if the given pin does not support
--   the given output mode.
setPinOutputMode :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> PinOutputMode -> PinValue -> m ()

-- | Read the pin's value.
--   
--   Note that this action never blocks.
readPin :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinValue

-- | Block the current thread until an event occurs on the pin which
--   corresponds to the pin's current interrupt mode. Upon detection of the
--   event, return the pin's value.
--   
--   If the pin does not support interrupts, then this action's behavior is
--   plaform-dependent.
--   
--   It is an error to call this action when the pin is not configured for
--   input.
--   
--   Note: due to its interaction with the threading system, this action
--   may behave differently across different implementations of Haskell. It
--   has only been tested with GHC. (On GHC, you should compile any program
--   that uses this action with the <tt>-threaded</tt> option.)
pollPin :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinValue

-- | Same as <a>pollPin</a>, except with a timeout, specified in
--   microseconds. If no event occurs before the timeout expires, this
--   action returns <a>Nothing</a>; otherwise, it returns the pin's signal
--   level wrapped in a <a>Just</a>.
--   
--   If the timeout value is negative, this action behaves just like
--   <a>pollPin</a>.
--   
--   If the pin does not support interrupts, then this action's behavior is
--   platform-dependent.
--   
--   It is an error to call this action when the pin is not configured for
--   input.
--   
--   Note: due to its interaction with the threading system, this action
--   may behave differently across different implementations of Haskell. It
--   has only been tested with GHC. (On GHC, you should compile any program
--   that uses this action with the <tt>-threaded</tt> option.)
pollPinTimeout :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> Int -> m (Maybe PinValue)

-- | Set the pin's output value.
--   
--   It is an error to call this action when the pin is not configured for
--   output.
writePin :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> PinValue -> m ()

-- | Toggle the pin's output value and return the pin's new output value.
--   
--   It is an error to call this action when the pin is not configured for
--   output.
togglePin :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinValue

-- | Get the pin's interrupt mode.
--   
--   If the pin does not support interrupts, it is an error to call this
--   action.
--   
--   (Note that <a>RisingEdge</a> and <a>FallingEdge</a> are relative to
--   the pin's active level; i.e., they refer to the pin's <i>logical</i>
--   signal edges, not its physical signal edges.)
getPinInterruptMode :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinInterruptMode

-- | Set the pin's interrupt mode (only when the pin is configured for
--   input).
--   
--   A pin's interrupt mode determines the behavior of the <a>pollPin</a>
--   and <a>pollPinTimeout</a> actions. Those actions will block the
--   current thread on an input pin until a particular event occurs on that
--   pin's signal waveform: a low-to-high transition (<a>RisingEdge</a>), a
--   high-to-low transition (<a>FallingEdge</a>), or any change of level
--   (<a>Level</a>).
--   
--   You can also disable interrupts on the pin so that <a>pollPin</a> will
--   block the current thread indefinitely (or until a timer expires, in
--   the case of <a>pollPinTimeout</a>). This functionality is useful when,
--   for example, one thread is dedicated to servicing interrupts on a pin,
--   and another thread wants to mask interrupts on that pin for some
--   period of time.
--   
--   Some pins (or even some GPIO platforms) may not support interrupts. In
--   such cases, it is an error to call this action.
--   
--   It is an error to use this action on a pin configured for output.
setPinInterruptMode :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> PinInterruptMode -> m ()

-- | Get the pin's active level.
getPinActiveLevel :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinActiveLevel

-- | Set the pin's active level.
setPinActiveLevel :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> PinActiveLevel -> m ()

-- | Toggle the pin's active level. Returns the pin's new level.
togglePinActiveLevel :: (MonadGpio h m, MonadTrans t, MonadGpio h m', t m' ~ m) => h -> m PinActiveLevel

-- | Exception-safe pin management.
--   
--   <a>withPin</a> opens a pin using <a>openPin</a> and passes the handle
--   to the given GPIO computation. Upon completion of the computation, or
--   an exception occuring within the computation, <a>withPin</a> closes
--   the handle using <a>closePin</a> and then propagates the result,
--   either by returning the value of the computation or by re-raising the
--   exception.
withPin :: (MaskGpioM h m) => Pin -> (h -> m a) -> m a

-- | A handle to a pin that's been configured for non-blocking reads only.
--   
--   You cannot poll an <a>InputPin</a> for interrupts. See
--   <a>InterruptPin</a>.
data InputPin h

-- | Like <a>withPin</a>, but for <a>InputPin</a>s. Sets the pin's input
--   mode to the specified <a>PinInputMode</a> value.
--   
--   If the optional active level argument is <a>Nothing</a>, then the
--   pin's active level is unchanged from its current state. Otherwise, the
--   pin's active level is set to the specified level.
--   
--   It is an error to call this action if the pin cannot be configured for
--   input, or if it does not support the specified input mode.
withInputPin :: (MaskGpioM h m) => Pin -> PinInputMode -> Maybe PinActiveLevel -> (InputPin h -> m a) -> m a

-- | Like <a>readPin</a>.
readInputPin :: (MonadGpio h m) => InputPin h -> m PinValue

-- | Like <a>getPinInputMode</a>.
getInputPinInputMode :: (MonadGpio h m) => InputPin h -> m PinInputMode

-- | Like <a>getPinActiveLevel</a>.
getInputPinActiveLevel :: (MonadGpio h m) => InputPin h -> m PinActiveLevel

-- | Like <a>setPinActiveLevel</a>.
setInputPinActiveLevel :: (MonadGpio h m) => InputPin h -> PinActiveLevel -> m ()

-- | Like <a>togglePinActiveLevel</a>.
toggleInputPinActiveLevel :: (MonadGpio h m) => InputPin h -> m PinActiveLevel

-- | A handle to a pin that's been configured both for non-blocking reads
--   and for interrupt-driven polling reads.
data InterruptPin h

-- | Like <a>withPin</a>, but for <a>InterruptPin</a>s. The pin is opened
--   for input, is input mode is set to the specified <a>PinInputMode</a>
--   value, and its interrupt mode is set to the specified
--   <a>PinInterruptMode</a> value.
--   
--   If the optional active level argument is <a>Nothing</a>, then the
--   pin's active level is unchanged from its current state. Otherwise, the
--   pin's active level is set to the specified level.
--   
--   It is an error to call this action if any of the following are true:
--   
--   <ul>
--   <li>The pin cannot be configured for input.</li>
--   <li>The pin does not support the specified input mode.</li>
--   <li>The pin does not support interrupts.</li>
--   </ul>
withInterruptPin :: (MaskGpioM h m) => Pin -> PinInputMode -> PinInterruptMode -> Maybe PinActiveLevel -> (InterruptPin h -> m a) -> m a

-- | Like <a>readPin</a>.
readInterruptPin :: (MonadGpio h m) => InterruptPin h -> m PinValue

-- | Like <a>pollPin</a>.
pollInterruptPin :: (MonadGpio h m) => InterruptPin h -> m PinValue

-- | Like <a>pollPinTimeout</a>.
pollInterruptPinTimeout :: (MonadGpio h m) => InterruptPin h -> Int -> m (Maybe PinValue)

-- | Like <a>getPinInputMode</a>.
getInterruptPinInputMode :: (MonadGpio h m) => InterruptPin h -> m PinInputMode

-- | Like <a>getPinInterruptMode</a>.
getInterruptPinInterruptMode :: (ThrowGpioM h m) => InterruptPin h -> m PinInterruptMode

-- | Like <a>setPinInterruptMode</a>.
setInterruptPinInterruptMode :: (MonadGpio h m) => InterruptPin h -> PinInterruptMode -> m ()

-- | Like <a>getPinActiveLevel</a>.
getInterruptPinActiveLevel :: (MonadGpio h m) => InterruptPin h -> m PinActiveLevel

-- | Like <a>setPinActiveLevel</a>.
setInterruptPinActiveLevel :: (MonadGpio h m) => InterruptPin h -> PinActiveLevel -> m ()

-- | Like <a>togglePinActiveLevel</a>.
toggleInterruptPinActiveLevel :: (MonadGpio h m) => InterruptPin h -> m PinActiveLevel

-- | A handle to a pin that's been configured for output only.
--   
--   Note that output pins can be both read and written. However, they only
--   support non-blocking reads, not interrupt-driven polling reads.
data OutputPin h

-- | Like <a>withPin</a>, but for <a>OutputPin</a>s. Sets the pin's output
--   mode to the specified <a>PinOutputMode</a> value.
--   
--   The <a>PinValue</a> argument specifies the pin's initial output value.
--   It is relative to the active level argument, or to the pin's current
--   active level if the active level argument is <a>Nothing</a>.
--   
--   It is an error to call this action if the pin cannot be configured for
--   output, or if it does not support the specified output mode.
withOutputPin :: (MaskGpioM h m) => Pin -> PinOutputMode -> Maybe PinActiveLevel -> PinValue -> (OutputPin h -> m a) -> m a

-- | Like <a>writePin</a>.
writeOutputPin :: (MonadGpio h m) => OutputPin h -> PinValue -> m ()

-- | Like <a>togglePin</a>.
toggleOutputPin :: (MonadGpio h m) => OutputPin h -> m PinValue

-- | Like <a>readPin</a>.
readOutputPin :: (MonadGpio h m) => OutputPin h -> m PinValue

-- | Like <a>getPinOutputMode</a>.
getOutputPinOutputMode :: (MonadGpio h m) => OutputPin h -> m PinOutputMode

-- | Like <a>getPinActiveLevel</a>.
getOutputPinActiveLevel :: (MonadGpio h m) => OutputPin h -> m PinActiveLevel

-- | Like <a>setPinActiveLevel</a>.
setOutputPinActiveLevel :: (MonadGpio h m) => OutputPin h -> PinActiveLevel -> m ()

-- | Like <a>togglePinActiveLevel</a>.
toggleOutputPinActiveLevel :: (MonadGpio h m) => OutputPin h -> m PinActiveLevel

-- | The top level of the GPIO exception hierarchy.
data SomeGpioException
SomeGpioException :: e -> SomeGpioException

-- | Convert <a>SomeGpioException</a> to <a>SomeException</a>.
gpioExceptionToException :: Exception e => e -> SomeException

-- | Ask whether an exception is <a>SomeGpioException</a>.
gpioExceptionFromException :: Exception e => SomeException -> Maybe e
instance GHC.Show.Show h => GHC.Show.Show (System.GPIO.Monad.OutputPin h)
instance GHC.Classes.Eq h => GHC.Classes.Eq (System.GPIO.Monad.OutputPin h)
instance GHC.Show.Show h => GHC.Show.Show (System.GPIO.Monad.InterruptPin h)
instance GHC.Classes.Eq h => GHC.Classes.Eq (System.GPIO.Monad.InterruptPin h)
instance GHC.Show.Show h => GHC.Show.Show (System.GPIO.Monad.InputPin h)
instance GHC.Classes.Eq h => GHC.Classes.Eq (System.GPIO.Monad.InputPin h)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Identity.IdentityT m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Cont.ContT r m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Catch.Pure.CatchT m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Except.ExceptT e m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.List.ListT m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Maybe.MaybeT m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Reader.ReaderT r m)
instance (System.GPIO.Monad.MonadGpio h m, GHC.Base.Monoid w) => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
instance (System.GPIO.Monad.MonadGpio h m, GHC.Base.Monoid w) => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.RWS.Strict.RWST r w s m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.State.Lazy.StateT s m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.State.Strict.StateT s m)
instance (System.GPIO.Monad.MonadGpio h m, GHC.Base.Monoid w) => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance (System.GPIO.Monad.MonadGpio h m, GHC.Base.Monoid w) => System.GPIO.Monad.MonadGpio h (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Logger.LoggingT m)
instance System.GPIO.Monad.MonadGpio h m => System.GPIO.Monad.MonadGpio h (Control.Monad.Logger.NoLoggingT m)


-- | Types used by the various Linux <tt>sysfs</tt> GPIO implementations.
module System.GPIO.Linux.Sysfs.Types

-- | Linux GPIO pins that can be configured to generate inputs have an
--   <tt>edge</tt> attribute in the <tt>sysfs</tt> GPIO filesystem. This
--   type represents the values that the <tt>edge</tt> attribute can take.
--   
--   Note that in Linux <tt>sysfs</tt> GPIO, the signal edge referred to by
--   the <tt>edge</tt> attribute refers to the signal's <i>logical</i>
--   value; i.e., it takes into account the value of the pin's
--   <tt>active_low</tt> attribute.
--   
--   This type is isomorphic to the <a>PinInterruptMode</a> type. See
--   <a>toPinInterruptMode</a> and <a>toSysfsEdge</a>.
data SysfsEdge

-- | Interrupts disabled
None :: SysfsEdge

-- | Interrupt on the (logical) signal's rising edge
Rising :: SysfsEdge

-- | Interrupt on the (logical) signal's falling edge
Falling :: SysfsEdge

-- | Interrupt on any change to the signal level
Both :: SysfsEdge

-- | Convert a <a>SysfsEdge</a> value to its equivalent
--   <a>PinInterruptMode</a> value.
--   
--   <pre>
--   &gt;&gt;&gt; toPinInterruptMode None
--   Disabled
--   
--   &gt;&gt;&gt; toPinInterruptMode Rising
--   RisingEdge
--   
--   &gt;&gt;&gt; toPinInterruptMode Falling
--   FallingEdge
--   
--   &gt;&gt;&gt; toPinInterruptMode Both
--   Level
--   </pre>
toPinInterruptMode :: SysfsEdge -> PinInterruptMode

-- | Convert a <a>PinInterruptMode</a> value to its equivalent
--   <a>SysfsEdge</a> value.
--   
--   <pre>
--   &gt;&gt;&gt; toSysfsEdge Disabled
--   None
--   
--   &gt;&gt;&gt; toSysfsEdge RisingEdge
--   Rising
--   
--   &gt;&gt;&gt; toSysfsEdge FallingEdge
--   Falling
--   
--   &gt;&gt;&gt; toSysfsEdge Level
--   Both
--   </pre>
toSysfsEdge :: PinInterruptMode -> SysfsEdge

-- | Exceptions that can be thrown by <tt>sysfs</tt> computations (in
--   addition to standard <a>IOError</a> exceptions, of course).
--   
--   The <tt>UnexpectedX</tt> values are truly exceptional and mean that,
--   while the <tt>sysfs</tt> attribute for the given pin exists, the
--   contents of the attribute do not match any expected value for that
--   attribute, which probably means that the package is incompatible with
--   the <tt>sysfs</tt> filesystem due to a kernel-level change.
data SysfsException

-- | The <tt>sysfs</tt> filesystem does not exist
SysfsNotPresent :: SysfsException

-- | Something in the <tt>sysfs</tt> filesystem does not behave as expected
--   (could indicate a change in <tt>sysfs</tt> behavior that the package
--   does not expect)
SysfsError :: SysfsException

-- | The <tt>sysfs</tt> operation is not permitted due to insufficient
--   permissions
SysfsPermissionDenied :: SysfsException

-- | The operation on the specified pin is not permitted, either due to
--   insufficient permissions, or because the pin's attribute cannot be
--   modified (e.g., trying to write to a pin that's configured for input)
PermissionDenied :: Pin -> SysfsException

-- | The operation is invalid for the specified pin, or in the specified
--   pin's current configuration
InvalidOperation :: Pin -> SysfsException

-- | The pin has already been exported
AlreadyExported :: Pin -> SysfsException

-- | The specified pin does not exist
InvalidPin :: Pin -> SysfsException

-- | The pin has been un-exported or does not exist
NotExported :: Pin -> SysfsException

-- | The pin does not support the specified input mode
UnsupportedInputMode :: PinInputMode -> Pin -> SysfsException

-- | The pin does not support the specified output mode
UnsupportedOutputMode :: PinOutputMode -> Pin -> SysfsException

-- | The pin does not have a <tt>direction</tt> attribute
NoDirectionAttribute :: Pin -> SysfsException

-- | The pin does not have an <tt>edge</tt> attribute
NoEdgeAttribute :: Pin -> SysfsException

-- | An unexpected value was read from the pin's <tt>direction</tt>
--   attribute
UnexpectedDirection :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the pin's <tt>value</tt> attribute
UnexpectedValue :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the pin's <tt>edge</tt> attribute
UnexpectedEdge :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the pin's <tt>active_low</tt>
--   attribute
UnexpectedActiveLow :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the specified file
UnexpectedContents :: FilePath -> Text -> SysfsException

-- | An internal error has occurred in the interpreter, something which
--   should "never happen" and should be reported to the package maintainer
InternalError :: Text -> SysfsException
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Types.SysfsException
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Types.SysfsException
instance GHC.Generics.Generic System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Read.Read System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Classes.Ord System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance Data.Data.Data System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Enum.Enum System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Enum.Bounded System.GPIO.Linux.Sysfs.Types.SysfsEdge
instance GHC.Exception.Exception System.GPIO.Linux.Sysfs.Types.SysfsException
instance Test.QuickCheck.Arbitrary.Arbitrary System.GPIO.Linux.Sysfs.Types.SysfsEdge


-- | Useful low-level Linux <tt>sysfs</tt> functions.
module System.GPIO.Linux.Sysfs.Util

-- | The base path to Linux's <tt>sysfs</tt> GPIO filesystem.
--   
--   <pre>
--   &gt;&gt;&gt; sysfsPath
--   "/sys/class/gpio"
--   </pre>
sysfsPath :: FilePath

-- | The name of the control file used to export GPIO pins via
--   <tt>sysfs</tt>.
--   
--   <pre>
--   &gt;&gt;&gt; exportFileName
--   "/sys/class/gpio/export"
--   </pre>
exportFileName :: FilePath

-- | The name of the control file used to "unexport" GPIO pins via
--   <tt>sysfs</tt>.
--   
--   <pre>
--   &gt;&gt;&gt; unexportFileName
--   "/sys/class/gpio/unexport"
--   </pre>
unexportFileName :: FilePath

-- | Exporting a GPIO pin via <tt>sysfs</tt> creates a control directory
--   corresponding to that pin. <a>pinDirName</a> gives the name of that
--   directory for a given <a>Pin</a>.
--   
--   <pre>
--   &gt;&gt;&gt; pinDirName (Pin 16)
--   "/sys/class/gpio/gpio16"
--   </pre>
pinDirName :: Pin -> FilePath

-- | The name of the attribute file used to read and write the pin's
--   <tt>active_low</tt> value.
--   
--   <pre>
--   &gt;&gt;&gt; pinActiveLowFileName (Pin 16)
--   "/sys/class/gpio/gpio16/active_low"
--   </pre>
pinActiveLowFileName :: Pin -> FilePath

-- | Pins whose direction can be controlled via <tt>sysfs</tt> provide a
--   <tt>direction</tt> attribute file. <a>pinDirectionFileName</a> gives
--   the name of that file for a given <a>Pin</a>. Note that some pins'
--   direction cannot be set. In these cases, the file named by this
--   function does not actually exist.
--   
--   <pre>
--   &gt;&gt;&gt; pinDirectionFileName (Pin 16)
--   "/sys/class/gpio/gpio16/direction"
--   </pre>
pinDirectionFileName :: Pin -> FilePath

-- | Pins that can be configured as interrupt-generating inputs provide an
--   <tt>edge</tt> attribute file. <a>pinEdgeFileName</a> gives the name of
--   that file for a given <a>Pin</a>. Note that some pins' edge
--   configuration cannot be set. In these cases, the file named by this
--   function does not actually exist.
--   
--   <pre>
--   &gt;&gt;&gt; pinEdgeFileName (Pin 16)
--   "/sys/class/gpio/gpio16/edge"
--   </pre>
pinEdgeFileName :: Pin -> FilePath

-- | The name of the attribute file used to read and write the pin's
--   logical signal value.
--   
--   <pre>
--   &gt;&gt;&gt; pinValueFileName (Pin 16)
--   "/sys/class/gpio/gpio16/value"
--   </pre>
pinValueFileName :: Pin -> FilePath

-- | Convert a <a>PinDirection</a> value to the corresponding
--   <a>ByteString</a> value expected by a pin's <tt>direction</tt>
--   attribute in the <tt>sysfs</tt> GPIO filesystem.
--   
--   <pre>
--   &gt;&gt;&gt; pinDirectionToBS In
--   "in\n"
--   
--   &gt;&gt;&gt; pinDirectionToBS Out
--   "out\n"
--   </pre>
pinDirectionToBS :: PinDirection -> ByteString

-- | Convert a <a>PinValue</a> value to the corresponding <a>ByteString</a>
--   value expected by a pin's <tt>direction</tt> attribute in the
--   <tt>sysfs</tt> GPIO, which can be used to configure the pin for output
--   and simultaneously set the pin's (physical) signal level; see the
--   <a>Linux kernel documentation</a> for details.
--   
--   <pre>
--   &gt;&gt;&gt; pinDirectionValueToBS Low
--   "low\n"
--   
--   &gt;&gt;&gt; pinDirectionValueToBS High
--   "high\n"
--   </pre>
pinDirectionValueToBS :: PinValue -> ByteString

-- | When writing a pin's <tt>direction</tt> attribute in the
--   <tt>sysfs</tt> GPIO filesystem with a <a>ByteString</a> value,
--   <tt>in\n</tt> configures the pin for input, and <tt>out\n</tt>
--   configures the pin for output while also initializing the pin's
--   (physical) signal level to a low value.
--   
--   Furthermore, you may write <tt>low\n</tt> or <tt>high\n</tt> to the
--   <tt>direction</tt> attribute to configure the pin for output and
--   simulataneously set the pin's physical value.
--   
--   Therefore, writing a pin's <tt>direction</tt> attribute affects not
--   only its direction, but also (potentially) its value. This function's
--   return type reflects that possibility.
--   
--   See the <a>Linux kernel documentation</a> for details.
--   
--   This function converts a <tt>direction</tt> attribute value, encoded
--   as a strict <a>ByteString</a>, to its corresponding
--   <a>PinDirection</a> and (possible) <a>PinValue</a> pair; or
--   <a>Nothing</a> if the attribute encoding is invalid.
--   
--   <pre>
--   &gt;&gt;&gt; :set -XOverloadedStrings
--   
--   &gt;&gt;&gt; bsToPinDirection "in\n"
--   Just (In,Nothing)
--   
--   &gt;&gt;&gt; bsToPinDirection "out\n"
--   Just (Out,Just Low)
--   
--   &gt;&gt;&gt; bsToPinDirection "low\n"
--   Just (Out,Just Low)
--   
--   &gt;&gt;&gt; bsToPinDirection "high\n"
--   Just (Out,Just High)
--   
--   &gt;&gt;&gt; bsToPinDirection "foo\n"
--   Nothing
--   </pre>
bsToPinDirection :: ByteString -> Maybe (PinDirection, Maybe PinValue)

-- | Convert a <a>SysfsEdge</a> value to the <a>ByteString</a> value
--   expected by a pin's <tt>edge</tt> attribute in the <tt>sysfs</tt> GPIO
--   filesystem.
--   
--   <pre>
--   &gt;&gt;&gt; sysfsEdgeToBS None
--   "none\n"
--   
--   &gt;&gt;&gt; sysfsEdgeToBS Rising
--   "rising\n"
--   
--   &gt;&gt;&gt; sysfsEdgeToBS Falling
--   "falling\n"
--   
--   &gt;&gt;&gt; sysfsEdgeToBS Both
--   "both\n"
--   </pre>
sysfsEdgeToBS :: SysfsEdge -> ByteString

-- | Inverse of <a>sysfsEdgeToBS</a>.
--   
--   <pre>
--   &gt;&gt;&gt; :set -XOverloadedStrings
--   
--   &gt;&gt;&gt; bsToSysfsEdge "none\n"
--   Just None
--   
--   &gt;&gt;&gt; bsToSysfsEdge "rising\n"
--   Just Rising
--   
--   &gt;&gt;&gt; bsToSysfsEdge "falling\n"
--   Just Falling
--   
--   &gt;&gt;&gt; bsToSysfsEdge "both\n"
--   Just Both
--   
--   &gt;&gt;&gt; bsToSysfsEdge "foo\n"
--   Nothing
--   </pre>
bsToSysfsEdge :: ByteString -> Maybe SysfsEdge

-- | Convert a <a>PinValue</a> to the <a>ByteString</a> value expected by a
--   pin's <tt>value</tt> attribute in the <tt>sysfs</tt> GPIO filesystem.
--   
--   <pre>
--   &gt;&gt;&gt; pinValueToBS Low
--   "0\n"
--   
--   &gt;&gt;&gt; pinValueToBS High
--   "1\n"
--   </pre>
pinValueToBS :: PinValue -> ByteString

-- | Convert a <tt>value</tt> attribute value, encoded as a strict
--   <a>ByteString</a>, to its corresponding <a>PinValue</a>.
--   
--   Note that the <tt>sysfs</tt> <tt>value</tt> attribute is quite
--   liberal: a <a>ByteString</a> value of <tt>0\n</tt> will set the pin's
--   (logical) signal level to low, but any other (non-empty)
--   <a>ByteString</a> value will set it to high.
--   
--   <pre>
--   &gt;&gt;&gt; :set -XOverloadedStrings
--   
--   &gt;&gt;&gt; bsToPinValue "0\n"
--   Just Low
--   
--   &gt;&gt;&gt; bsToPinValue "1\n"
--   Just High
--   
--   &gt;&gt;&gt; bsToPinValue "high\n"
--   Just High
--   
--   &gt;&gt;&gt; bsToPinValue "low\n" -- nota bene!
--   Just High
--   
--   &gt;&gt;&gt; bsToPinValue "foo\n"
--   Just High
--   
--   &gt;&gt;&gt; bsToPinValue ""
--   Nothing
--   </pre>
bsToPinValue :: ByteString -> Maybe PinValue

-- | Convert a <a>Bool</a> to the <a>ByteString</a> value expected by a
--   pin's <tt>active_low</tt> attribute in the <tt>sysfs</tt> GPIO
--   filesystem.
--   
--   <pre>
--   &gt;&gt;&gt; activeLowToBS False
--   "0\n"
--   
--   &gt;&gt;&gt; activeLowToBS True
--   "1\n"
--   </pre>
activeLowToBS :: Bool -> ByteString

-- | Convert an <tt>active_low</tt> attribute value, encoded as a strict
--   <a>ByteString</a>, to its corresponding <a>Bool</a> value.
--   
--   Note that the <tt>sysfs</tt> <tt>active_low</tt> attribute is quite
--   liberal: a <a>ByteString</a> value of <tt>0\n</tt> returns
--   <a>False</a> and any other (non-empty) <a>ByteString</a> value returns
--   <a>True</a>.
--   
--   <pre>
--   &gt;&gt;&gt; :set -XOverloadedStrings
--   
--   &gt;&gt;&gt; bsToActiveLow "0\n"
--   Just False
--   
--   &gt;&gt;&gt; bsToActiveLow "1\n"
--   Just True
--   
--   &gt;&gt;&gt; bsToActiveLow "high\n"
--   Just True
--   
--   &gt;&gt;&gt; bsToActiveLow "low\n" -- nota bene!
--   Just True
--   
--   &gt;&gt;&gt; bsToActiveLow "foo\n"
--   Just True
--   
--   &gt;&gt;&gt; bsToActiveLow ""
--   Nothing
--   </pre>
bsToActiveLow :: ByteString -> Maybe Bool

-- | Convert an <a>Int</a> to a decimal ASCII encoding in a strict
--   <a>ByteString</a>.
--   
--   <pre>
--   &gt;&gt;&gt; intToBS 37
--   "37"
--   </pre>
intToBS :: Int -> ByteString

-- | Convert a strict decimal ASCII <a>ByteString</a> encoding of an
--   integer to an <a>Int</a> (maybe). If there are any extraneous trailing
--   characters after the decimal ASCII encoding, other than a single
--   newline character, this is treated as a failure (unlike
--   <a>readInt</a>, which returns the remaining string).
--   
--   <pre>
--   &gt;&gt;&gt; :set -XOverloadedStrings
--   
--   &gt;&gt;&gt; bsToInt "37"
--   Just 37
--   
--   &gt;&gt;&gt; bsToInt "37\n"
--   Just 37
--   
--   &gt;&gt;&gt; bsToInt "37abc"
--   Nothing
--   
--   &gt;&gt;&gt; bsToInt "37 a"
--   Nothing
--   </pre>
bsToInt :: ByteString -> Maybe Int


-- | Monad type classes and instances for Linux <tt>sysfs</tt> GPIO
--   operations.
module System.GPIO.Linux.Sysfs.Monad

-- | A type class for monads which implement (or mock) low-level Linux
--   <tt>sysfs</tt> GPIO operations.
class (Monad m) => MonadSysfs m

-- | Equivalent to <a>doesDirectoryExist</a>.
doesDirectoryExist :: MonadSysfs m => FilePath -> m Bool

-- | Equivalent to <a>doesFileExist</a>.
doesFileExist :: MonadSysfs m => FilePath -> m Bool

-- | Equivalent to <a>getDirectoryContents</a>.
getDirectoryContents :: MonadSysfs m => FilePath -> m [FilePath]

-- | Equivalent to <a>readFile</a>.
readFile :: MonadSysfs m => FilePath -> m ByteString

-- | Equivalent to <a>writeFile</a>.
writeFile :: MonadSysfs m => FilePath -> ByteString -> m ()

-- | <tt>sysfs</tt> control files which are global shared resources may be
--   written simultaneously by multiple threads. This is fine --
--   <tt>sysfs</tt> can handle this -- but Haskell's <a>writeFile</a>
--   cannot, as it locks the file and prevents multiple writers. We don't
--   want this behavior, so we use low-level operations to get around it.
unlockedWriteFile :: MonadSysfs m => FilePath -> ByteString -> m ()

-- | Poll a <tt>sysfs</tt> file for reading, as in POSIX.1-2001
--   <tt>poll(2)</tt>.
--   
--   Note that the implementation of this action is only guaranteed to work
--   for <tt>sysfs</tt> files, which have a peculiar way of signaling
--   readiness for reads. Do not use it for any other purpose.
pollFile :: MonadSysfs m => FilePath -> Int -> m CInt

-- | Equivalent to <a>doesDirectoryExist</a>.
doesDirectoryExist :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m Bool

-- | Equivalent to <a>doesFileExist</a>.
doesFileExist :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m Bool

-- | Equivalent to <a>getDirectoryContents</a>.
getDirectoryContents :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m [FilePath]

-- | Equivalent to <a>readFile</a>.
readFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m ByteString

-- | Equivalent to <a>writeFile</a>.
writeFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> ByteString -> m ()

-- | <tt>sysfs</tt> control files which are global shared resources may be
--   written simultaneously by multiple threads. This is fine --
--   <tt>sysfs</tt> can handle this -- but Haskell's <a>writeFile</a>
--   cannot, as it locks the file and prevents multiple writers. We don't
--   want this behavior, so we use low-level operations to get around it.
unlockedWriteFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> ByteString -> m ()

-- | Poll a <tt>sysfs</tt> file for reading, as in POSIX.1-2001
--   <tt>poll(2)</tt>.
--   
--   Note that the implementation of this action is only guaranteed to work
--   for <tt>sysfs</tt> files, which have a peculiar way of signaling
--   readiness for reads. Do not use it for any other purpose.
pollFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> Int -> m CInt

-- | The <tt>sysfs</tt> pin handle type. Currently it's just a newtype
--   wrapper around a <a>Pin</a>. The constructor is exported for
--   convenience, but note that the implementation may change in future
--   versions of the package.
newtype PinDescriptor
PinDescriptor :: Pin -> PinDescriptor
[_pin] :: PinDescriptor -> Pin

-- | An instance of <a>MonadGpio</a> which translates actions in that monad
--   to operations on Linux's native <tt>sysfs</tt> GPIO interface.
newtype SysfsGpioT m a
SysfsGpioT :: m a -> SysfsGpioT m a
[runSysfsGpioT] :: SysfsGpioT m a -> m a
type CatchSysfsM m = (Functor m, MonadCatch m, MonadSysfs m)
type ThrowSysfsM m = (Functor m, MonadThrow m, MonadSysfs m)
type ThrowCatchSysfsM m = (Functor m, MonadThrow m, MonadCatch m, MonadSysfs m)

-- | Test whether the <tt>sysfs</tt> GPIO filesystem is available.
sysfsIsPresent :: (MonadSysfs m) => m Bool

-- | Return a list of all pins that are exposed via the <tt>sysfs</tt> GPIO
--   filesystem. Note that the returned list may omit some pins that are
--   available on the host but which, for various reasons, are not exposed
--   via the <tt>sysfs</tt> GPIO filesystem.
availablePins :: (ThrowCatchSysfsM m) => m [Pin]

-- | Test whether the pin is already exported.
pinIsExported :: (MonadSysfs m) => Pin -> m Bool

-- | Export the given pin.
--   
--   Note that, if the pin is already exported, this is not an error; in
--   this situation, the pin remains exported and its state unchanged.
exportPin :: (CatchSysfsM m) => Pin -> m ()

-- | Export the given pin.
--   
--   Note that, unlike <a>exportPin</a>, it's an error to call this action
--   to export a pin that's already been exported. This is the standard
--   Linux <tt>sysfs</tt> GPIO behavior.
exportPinChecked :: (CatchSysfsM m) => Pin -> m ()

-- | Unexport the given pin.
--   
--   Note that, if the pin is already unexported or cannot be unexported,
--   this is not an error. In this situation, the pin remains exported and
--   its state unchanged.
unexportPin :: (CatchSysfsM m) => Pin -> m ()

-- | Unexport the given pin.
--   
--   Note that, unlike <a>unexportPin</a>, it is an error to call this
--   action if the pin is not currently exported. This is the standard
--   Linux <tt>sysfs</tt> GPIO behavior.
unexportPinChecked :: (CatchSysfsM m) => Pin -> m ()

-- | Test whether the pin's direction can be set via the <tt>sysfs</tt>
--   GPIO filesystem. (Some pins have a hard-wired direction, in which case
--   their direction must be determined by some other mechanism, as the
--   <tt>direction</tt> attribute does not exist for such pins.)
pinHasDirection :: (ThrowSysfsM m) => Pin -> m Bool

-- | Read the pin's direction.
--   
--   It is an error to call this action if the pin has no
--   <tt>direction</tt> attribute.
readPinDirection :: (ThrowCatchSysfsM m) => Pin -> m PinDirection

-- | Set the pin's direction.
--   
--   It is an error to call this action if the pin has no
--   <tt>direction</tt> attribute.
--   
--   Note that, in Linux <tt>sysfs</tt> GPIO, changing a pin's direction to
--   <tt>out</tt> will also set its <i>physical</i> signal level to
--   <tt>low</tt>.
--   
--   NB: in Linux <tt>sysfs</tt>, if an input pin is cofigured for edge- or
--   level-triggered reads, it's an error to set its direction to
--   <tt>out</tt>. However, this action will handle that case gracefully by
--   setting the pin's <tt>edge</tt> attribute to <tt>none</tt> before
--   setting the pin's direction to <tt>out</tt>.
writePinDirection :: (CatchSysfsM m) => Pin -> PinDirection -> m ()

-- | Pins whose direction can be set may be configured for output by
--   writing a <a>PinValue</a> to their <tt>direction</tt> attribute, such
--   that the given value will be driven on the pin as soon as it's
--   configured for output. This enables glitch-free output configuration,
--   assuming the pin is currently configured for input, or some kind of
--   tri-stated or floating high-impedance mode.
--   
--   It is an error to call this action if the pin has no
--   <tt>direction</tt> attribute.
--   
--   NB: for some unfathomable reason, writing <tt>high</tt> or
--   <tt>low</tt> to a pin's <tt>direction</tt> attribute sets its
--   <i>physical</i> signal level; i.e., it ignores the value of the pin's
--   <tt>active_low</tt> attribute. Contrast this behavior with the
--   behavior of writing to the pin's <tt>value</tt> attribute, which
--   respects the value of the pin's <tt>active_low</tt> attribute and sets
--   the pin's <i>logical</i> signal level.
--   
--   Rather than slavishly following the Linux <tt>sysfs</tt> GPIO spec, we
--   choose to be consistent by taking into account the pin's active level
--   when writing the <tt>direction</tt> attribute. In other words, the
--   <a>PinValue</a> argument to this action is the <i>logical</i> signal
--   level that will be set on the pin. If you're using this action to
--   program directly to the Linux <tt>sysfs</tt> GPIO interface and
--   expecting things to behave as they do with raw <tt>sysfs</tt> GPIO
--   operations, keep this in mind!
writePinDirectionWithValue :: (CatchSysfsM m) => Pin -> PinValue -> m ()

-- | Read the pin's signal level.
--   
--   Note that this action never blocks, regardless of the pin's
--   <tt>edge</tt> attribute setting.
readPinValue :: (ThrowCatchSysfsM m) => Pin -> m PinValue

-- | A blocking version of <a>readPinValue</a>. The current thread will
--   block until an event occurs on the pin as specified by the pin's
--   current <tt>edge</tt> attribute setting.
--   
--   If the pin has no <tt>edge</tt> attribute, then this action's behavior
--   is undefined. (Most likely, it will block indefinitely.)
pollPinValue :: (ThrowCatchSysfsM m) => Pin -> m PinValue

-- | Same as <a>pollPinValue</a>, except that a timeout value, specified in
--   microseconds, is provided. If no event occurs before the timeout
--   expires, this action returns <a>Nothing</a>; otherwise, it returns the
--   pin's value wrapped in a <a>Just</a>.
--   
--   If the timeout value is negative, this action behaves just like
--   <a>pollPinValue</a>.
--   
--   When specifying a timeout value, be careful not to exceed
--   <a>maxBound</a>.
--   
--   If the pin has no <tt>edge</tt> attribute, then this action's behavior
--   is undefined. (Most likely, it will time out after the specified delay
--   and return <a>Nothing</a>.)
--   
--   NB: the curent implementation of this action limits the timeout
--   precision to 1 millisecond, rather than 1 microsecond as the timeout
--   parameter implies.
pollPinValueTimeout :: (ThrowCatchSysfsM m) => Pin -> Int -> m (Maybe PinValue)

-- | Set the pin's signal level.
--   
--   It is an error to call this action if the pin is configured as an
--   input pin.
writePinValue :: (CatchSysfsM m) => Pin -> PinValue -> m ()

-- | Test whether the pin has an <tt>edge</tt> attribute, i.e., whether it
--   can be configured for edge- or level-triggered interrupts.
pinHasEdge :: (ThrowSysfsM m) => Pin -> m Bool

-- | Read the pin's <tt>edge</tt> attribute.
--   
--   It is an error to call this action when the pin has no <tt>edge</tt>
--   attribute.
readPinEdge :: (ThrowCatchSysfsM m) => Pin -> m SysfsEdge

-- | Write the pin's <tt>edge</tt> attribute.
--   
--   It is an error to call this action when the pin has no <tt>edge</tt>
--   attribute, or when the pin is configured for output.
writePinEdge :: (CatchSysfsM m) => Pin -> SysfsEdge -> m ()

-- | Read the pin's <tt>active_low</tt> attribute.
readPinActiveLow :: (ThrowCatchSysfsM m) => Pin -> m Bool

-- | Write the pin's <tt>active_low</tt> attribute.
writePinActiveLow :: (CatchSysfsM m) => Pin -> Bool -> m ()
instance Control.Monad.Logger.MonadLoggerIO m => Control.Monad.Logger.MonadLoggerIO (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Logger.MonadLogger m => Control.Monad.Logger.MonadLogger (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance (Control.Monad.State.Class.MonadState s m, Control.Monad.Writer.Class.MonadWriter w m, Control.Monad.Reader.Class.MonadReader r m) => Control.Monad.RWS.Class.MonadRWS r w s (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance GHC.Base.Monad m => GHC.Base.Monad (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance GHC.Base.Alternative m => GHC.Base.Alternative (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance GHC.Base.Functor m => GHC.Base.Functor (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance GHC.Classes.Ord System.GPIO.Linux.Sysfs.Monad.PinDescriptor
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Monad.PinDescriptor
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Monad.PinDescriptor
instance (Control.Monad.Catch.MonadMask m, System.GPIO.Linux.Sysfs.Monad.ThrowCatchSysfsM m) => System.GPIO.Monad.MonadGpio System.GPIO.Linux.Sysfs.Monad.PinDescriptor (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Trans.Class.MonadTrans System.GPIO.Linux.Sysfs.Monad.SysfsGpioT
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (System.GPIO.Linux.Sysfs.Monad.SysfsGpioT m)
instance Control.Monad.Trans.Control.MonadTransControl System.GPIO.Linux.Sysfs.Monad.SysfsGpioT
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Identity.IdentityT m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Cont.ContT r m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Catch.Pure.CatchT m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Except.ExceptT e m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.List.ListT m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Maybe.MaybeT m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Reader.ReaderT r m)
instance (System.GPIO.Linux.Sysfs.Monad.MonadSysfs m, GHC.Base.Monoid w) => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.RWS.Lazy.RWST r w s m)
instance (System.GPIO.Linux.Sysfs.Monad.MonadSysfs m, GHC.Base.Monoid w) => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.RWS.Strict.RWST r w s m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.State.Lazy.StateT s m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.State.Strict.StateT s m)
instance (System.GPIO.Linux.Sysfs.Monad.MonadSysfs m, GHC.Base.Monoid w) => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance (System.GPIO.Linux.Sysfs.Monad.MonadSysfs m, GHC.Base.Monoid w) => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Trans.Writer.Strict.WriterT w m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Logger.LoggingT m)
instance System.GPIO.Linux.Sysfs.Monad.MonadSysfs m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (Control.Monad.Logger.NoLoggingT m)


-- | The actual Linux <tt>sysfs</tt> implementation. This implementation
--   will only function properly on Linux systems with a <tt>sysfs</tt>
--   subsystem, obviously.
module System.GPIO.Linux.Sysfs.IO

-- | An instance of <a>MonadSysfs</a> which runs <a>MonadSysfs</a>
--   operations in IO. This instance must be run on an actual Linux
--   <tt>sysfs</tt> GPIO filesystem and will fail in any other environment.
--   
--   <h2>Interactions with threads</h2>
--   
--   Some parts of this implementation use the Haskell C FFI, and may block
--   on C I/O operations. (Specifically, <a>pollFile</a> will block in the
--   C FFI until its event is triggered.) When using this implementation
--   with GHC, you should compile your program with the <tt>-threaded</tt>
--   option, so that threads performing these blocking operations do not
--   block other Haskell threads in the system.
--   
--   Note that the C FFI bits in this implementation are marked as
--   <a>interruptible</a>, so that, on versions of GHC later than 7.8.1,
--   functions such as <a>throwTo</a> will work properly when targeting a
--   Haskell thread that uses this implementation.
--   
--   (On Haskell implementations other than GHC, the threading implications
--   are unknown; see the implementation's notes on how its threading
--   system interacts with the C FFI.)
newtype SysfsIOT m a
SysfsIOT :: m a -> SysfsIOT m a
[runSysfsIOT] :: SysfsIOT m a -> m a
instance Control.Monad.Logger.MonadLoggerIO m => Control.Monad.Logger.MonadLoggerIO (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Logger.MonadLogger m => Control.Monad.Logger.MonadLogger (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance (Control.Monad.State.Class.MonadState s m, Control.Monad.Writer.Class.MonadWriter w m, Control.Monad.Reader.Class.MonadReader r m) => Control.Monad.RWS.Class.MonadRWS r w s (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.State.Class.MonadState s m => Control.Monad.State.Class.MonadState s (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance GHC.Base.Monad m => GHC.Base.Monad (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance GHC.Base.Alternative m => GHC.Base.Alternative (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance GHC.Base.Functor m => GHC.Base.Functor (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Trans.Class.MonadTrans System.GPIO.Linux.Sysfs.IO.SysfsIOT
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)
instance Control.Monad.Trans.Control.MonadTransControl System.GPIO.Linux.Sysfs.IO.SysfsIOT
instance (Control.Monad.IO.Class.MonadIO m, Control.Monad.Catch.MonadThrow m) => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (System.GPIO.Linux.Sysfs.IO.SysfsIOT m)


-- | GPIO in Linux via the <tt>sysfs</tt> filesystem.
--   
--   See the <a>Linux kernel documentation</a> for the definitive
--   description of the Linux <tt>sysfs</tt>-based GPIO API and the
--   terminology used in this module.
--   
--   <h2>Pin numbering</h2>
--   
--   The <tt>sysfs</tt> GPIO implementation in this module uses the same
--   pin numbering scheme as the <tt>sysfs</tt> GPIO filesystem. For
--   example, <a>Pin</a> <tt>13</tt> corresponds to <tt>gpio13</tt> in the
--   <tt>sysfs</tt> filesystem. Note that the <tt>sysfs</tt> pin numbering
--   scheme is almost always different than the pin numbering scheme given
--   by the platform/hardware documentation. Consult your platform
--   documentation for the mapping of pin numbers between the two
--   namespaces.
module System.GPIO.Linux.Sysfs

-- | An instance of <a>MonadGpio</a> which translates actions in that monad
--   to operations on Linux's native <tt>sysfs</tt> GPIO interface.
data SysfsGpioT m a
runSysfsGpioT :: SysfsGpioT m a -> m a

-- | A specialization of <a>SysfsGpioT</a> which runs GPIO computations in
--   <a>IO</a> via <tt>sysfs</tt>.
type SysfsGpioIO = SysfsGpioT (SysfsIOT IO)

-- | Run GPIO computations in <a>IO</a> via <tt>sysfs</tt>.
runSysfsGpioIO :: SysfsGpioIO a -> IO a

-- | The <tt>sysfs</tt> pin handle type. Currently it's just a newtype
--   wrapper around a <a>Pin</a>. The constructor is exported for
--   convenience, but note that the implementation may change in future
--   versions of the package.
newtype PinDescriptor
PinDescriptor :: Pin -> PinDescriptor
[_pin] :: PinDescriptor -> Pin

-- | A type class for monads which implement (or mock) low-level Linux
--   <tt>sysfs</tt> GPIO operations.
class (Monad m) => MonadSysfs m

-- | Equivalent to <a>doesDirectoryExist</a>.
doesDirectoryExist :: MonadSysfs m => FilePath -> m Bool

-- | Equivalent to <a>doesFileExist</a>.
doesFileExist :: MonadSysfs m => FilePath -> m Bool

-- | Equivalent to <a>getDirectoryContents</a>.
getDirectoryContents :: MonadSysfs m => FilePath -> m [FilePath]

-- | Equivalent to <a>readFile</a>.
readFile :: MonadSysfs m => FilePath -> m ByteString

-- | Equivalent to <a>writeFile</a>.
writeFile :: MonadSysfs m => FilePath -> ByteString -> m ()

-- | <tt>sysfs</tt> control files which are global shared resources may be
--   written simultaneously by multiple threads. This is fine --
--   <tt>sysfs</tt> can handle this -- but Haskell's <a>writeFile</a>
--   cannot, as it locks the file and prevents multiple writers. We don't
--   want this behavior, so we use low-level operations to get around it.
unlockedWriteFile :: MonadSysfs m => FilePath -> ByteString -> m ()

-- | Poll a <tt>sysfs</tt> file for reading, as in POSIX.1-2001
--   <tt>poll(2)</tt>.
--   
--   Note that the implementation of this action is only guaranteed to work
--   for <tt>sysfs</tt> files, which have a peculiar way of signaling
--   readiness for reads. Do not use it for any other purpose.
pollFile :: MonadSysfs m => FilePath -> Int -> m CInt

-- | Equivalent to <a>doesDirectoryExist</a>.
doesDirectoryExist :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m Bool

-- | Equivalent to <a>doesFileExist</a>.
doesFileExist :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m Bool

-- | Equivalent to <a>getDirectoryContents</a>.
getDirectoryContents :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m [FilePath]

-- | Equivalent to <a>readFile</a>.
readFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> m ByteString

-- | Equivalent to <a>writeFile</a>.
writeFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> ByteString -> m ()

-- | <tt>sysfs</tt> control files which are global shared resources may be
--   written simultaneously by multiple threads. This is fine --
--   <tt>sysfs</tt> can handle this -- but Haskell's <a>writeFile</a>
--   cannot, as it locks the file and prevents multiple writers. We don't
--   want this behavior, so we use low-level operations to get around it.
unlockedWriteFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> ByteString -> m ()

-- | Poll a <tt>sysfs</tt> file for reading, as in POSIX.1-2001
--   <tt>poll(2)</tt>.
--   
--   Note that the implementation of this action is only guaranteed to work
--   for <tt>sysfs</tt> files, which have a peculiar way of signaling
--   readiness for reads. Do not use it for any other purpose.
pollFile :: (MonadSysfs m, MonadTrans t, MonadSysfs m', t m' ~ m) => FilePath -> Int -> m CInt

-- | An instance of <a>MonadSysfs</a> which runs <a>MonadSysfs</a>
--   operations in IO. This instance must be run on an actual Linux
--   <tt>sysfs</tt> GPIO filesystem and will fail in any other environment.
--   
--   <h2>Interactions with threads</h2>
--   
--   Some parts of this implementation use the Haskell C FFI, and may block
--   on C I/O operations. (Specifically, <a>pollFile</a> will block in the
--   C FFI until its event is triggered.) When using this implementation
--   with GHC, you should compile your program with the <tt>-threaded</tt>
--   option, so that threads performing these blocking operations do not
--   block other Haskell threads in the system.
--   
--   Note that the C FFI bits in this implementation are marked as
--   <a>interruptible</a>, so that, on versions of GHC later than 7.8.1,
--   functions such as <a>throwTo</a> will work properly when targeting a
--   Haskell thread that uses this implementation.
--   
--   (On Haskell implementations other than GHC, the threading implications
--   are unknown; see the implementation's notes on how its threading
--   system interacts with the C FFI.)
newtype SysfsIOT m a
SysfsIOT :: m a -> SysfsIOT m a
[runSysfsIOT] :: SysfsIOT m a -> m a

-- | Test whether the <tt>sysfs</tt> GPIO filesystem is available.
sysfsIsPresent :: (MonadSysfs m) => m Bool

-- | Return a list of all pins that are exposed via the <tt>sysfs</tt> GPIO
--   filesystem. Note that the returned list may omit some pins that are
--   available on the host but which, for various reasons, are not exposed
--   via the <tt>sysfs</tt> GPIO filesystem.
availablePins :: (ThrowCatchSysfsM m) => m [Pin]

-- | Test whether the pin is already exported.
pinIsExported :: (MonadSysfs m) => Pin -> m Bool

-- | Export the given pin.
--   
--   Note that, if the pin is already exported, this is not an error; in
--   this situation, the pin remains exported and its state unchanged.
exportPin :: (CatchSysfsM m) => Pin -> m ()

-- | Export the given pin.
--   
--   Note that, unlike <a>exportPin</a>, it's an error to call this action
--   to export a pin that's already been exported. This is the standard
--   Linux <tt>sysfs</tt> GPIO behavior.
exportPinChecked :: (CatchSysfsM m) => Pin -> m ()

-- | Unexport the given pin.
--   
--   Note that, if the pin is already unexported or cannot be unexported,
--   this is not an error. In this situation, the pin remains exported and
--   its state unchanged.
unexportPin :: (CatchSysfsM m) => Pin -> m ()

-- | Unexport the given pin.
--   
--   Note that, unlike <a>unexportPin</a>, it is an error to call this
--   action if the pin is not currently exported. This is the standard
--   Linux <tt>sysfs</tt> GPIO behavior.
unexportPinChecked :: (CatchSysfsM m) => Pin -> m ()

-- | Test whether the pin's direction can be set via the <tt>sysfs</tt>
--   GPIO filesystem. (Some pins have a hard-wired direction, in which case
--   their direction must be determined by some other mechanism, as the
--   <tt>direction</tt> attribute does not exist for such pins.)
pinHasDirection :: (ThrowSysfsM m) => Pin -> m Bool

-- | Read the pin's direction.
--   
--   It is an error to call this action if the pin has no
--   <tt>direction</tt> attribute.
readPinDirection :: (ThrowCatchSysfsM m) => Pin -> m PinDirection

-- | Set the pin's direction.
--   
--   It is an error to call this action if the pin has no
--   <tt>direction</tt> attribute.
--   
--   Note that, in Linux <tt>sysfs</tt> GPIO, changing a pin's direction to
--   <tt>out</tt> will also set its <i>physical</i> signal level to
--   <tt>low</tt>.
--   
--   NB: in Linux <tt>sysfs</tt>, if an input pin is cofigured for edge- or
--   level-triggered reads, it's an error to set its direction to
--   <tt>out</tt>. However, this action will handle that case gracefully by
--   setting the pin's <tt>edge</tt> attribute to <tt>none</tt> before
--   setting the pin's direction to <tt>out</tt>.
writePinDirection :: (CatchSysfsM m) => Pin -> PinDirection -> m ()

-- | Pins whose direction can be set may be configured for output by
--   writing a <a>PinValue</a> to their <tt>direction</tt> attribute, such
--   that the given value will be driven on the pin as soon as it's
--   configured for output. This enables glitch-free output configuration,
--   assuming the pin is currently configured for input, or some kind of
--   tri-stated or floating high-impedance mode.
--   
--   It is an error to call this action if the pin has no
--   <tt>direction</tt> attribute.
--   
--   NB: for some unfathomable reason, writing <tt>high</tt> or
--   <tt>low</tt> to a pin's <tt>direction</tt> attribute sets its
--   <i>physical</i> signal level; i.e., it ignores the value of the pin's
--   <tt>active_low</tt> attribute. Contrast this behavior with the
--   behavior of writing to the pin's <tt>value</tt> attribute, which
--   respects the value of the pin's <tt>active_low</tt> attribute and sets
--   the pin's <i>logical</i> signal level.
--   
--   Rather than slavishly following the Linux <tt>sysfs</tt> GPIO spec, we
--   choose to be consistent by taking into account the pin's active level
--   when writing the <tt>direction</tt> attribute. In other words, the
--   <a>PinValue</a> argument to this action is the <i>logical</i> signal
--   level that will be set on the pin. If you're using this action to
--   program directly to the Linux <tt>sysfs</tt> GPIO interface and
--   expecting things to behave as they do with raw <tt>sysfs</tt> GPIO
--   operations, keep this in mind!
writePinDirectionWithValue :: (CatchSysfsM m) => Pin -> PinValue -> m ()

-- | Read the pin's signal level.
--   
--   Note that this action never blocks, regardless of the pin's
--   <tt>edge</tt> attribute setting.
readPinValue :: (ThrowCatchSysfsM m) => Pin -> m PinValue

-- | A blocking version of <a>readPinValue</a>. The current thread will
--   block until an event occurs on the pin as specified by the pin's
--   current <tt>edge</tt> attribute setting.
--   
--   If the pin has no <tt>edge</tt> attribute, then this action's behavior
--   is undefined. (Most likely, it will block indefinitely.)
pollPinValue :: (ThrowCatchSysfsM m) => Pin -> m PinValue

-- | Same as <a>pollPinValue</a>, except that a timeout value, specified in
--   microseconds, is provided. If no event occurs before the timeout
--   expires, this action returns <a>Nothing</a>; otherwise, it returns the
--   pin's value wrapped in a <a>Just</a>.
--   
--   If the timeout value is negative, this action behaves just like
--   <a>pollPinValue</a>.
--   
--   When specifying a timeout value, be careful not to exceed
--   <a>maxBound</a>.
--   
--   If the pin has no <tt>edge</tt> attribute, then this action's behavior
--   is undefined. (Most likely, it will time out after the specified delay
--   and return <a>Nothing</a>.)
--   
--   NB: the curent implementation of this action limits the timeout
--   precision to 1 millisecond, rather than 1 microsecond as the timeout
--   parameter implies.
pollPinValueTimeout :: (ThrowCatchSysfsM m) => Pin -> Int -> m (Maybe PinValue)

-- | Set the pin's signal level.
--   
--   It is an error to call this action if the pin is configured as an
--   input pin.
writePinValue :: (CatchSysfsM m) => Pin -> PinValue -> m ()

-- | Test whether the pin has an <tt>edge</tt> attribute, i.e., whether it
--   can be configured for edge- or level-triggered interrupts.
pinHasEdge :: (ThrowSysfsM m) => Pin -> m Bool

-- | Read the pin's <tt>edge</tt> attribute.
--   
--   It is an error to call this action when the pin has no <tt>edge</tt>
--   attribute.
readPinEdge :: (ThrowCatchSysfsM m) => Pin -> m SysfsEdge

-- | Write the pin's <tt>edge</tt> attribute.
--   
--   It is an error to call this action when the pin has no <tt>edge</tt>
--   attribute, or when the pin is configured for output.
writePinEdge :: (CatchSysfsM m) => Pin -> SysfsEdge -> m ()

-- | Read the pin's <tt>active_low</tt> attribute.
readPinActiveLow :: (ThrowCatchSysfsM m) => Pin -> m Bool

-- | Write the pin's <tt>active_low</tt> attribute.
writePinActiveLow :: (CatchSysfsM m) => Pin -> Bool -> m ()

-- | Linux GPIO pins that can be configured to generate inputs have an
--   <tt>edge</tt> attribute in the <tt>sysfs</tt> GPIO filesystem. This
--   type represents the values that the <tt>edge</tt> attribute can take.
--   
--   Note that in Linux <tt>sysfs</tt> GPIO, the signal edge referred to by
--   the <tt>edge</tt> attribute refers to the signal's <i>logical</i>
--   value; i.e., it takes into account the value of the pin's
--   <tt>active_low</tt> attribute.
--   
--   This type is isomorphic to the <a>PinInterruptMode</a> type. See
--   <a>toPinInterruptMode</a> and <a>toSysfsEdge</a>.
data SysfsEdge

-- | Interrupts disabled
None :: SysfsEdge

-- | Interrupt on the (logical) signal's rising edge
Rising :: SysfsEdge

-- | Interrupt on the (logical) signal's falling edge
Falling :: SysfsEdge

-- | Interrupt on any change to the signal level
Both :: SysfsEdge

-- | Convert a <a>SysfsEdge</a> value to its equivalent
--   <a>PinInterruptMode</a> value.
--   
--   <pre>
--   &gt;&gt;&gt; toPinInterruptMode None
--   Disabled
--   
--   &gt;&gt;&gt; toPinInterruptMode Rising
--   RisingEdge
--   
--   &gt;&gt;&gt; toPinInterruptMode Falling
--   FallingEdge
--   
--   &gt;&gt;&gt; toPinInterruptMode Both
--   Level
--   </pre>
toPinInterruptMode :: SysfsEdge -> PinInterruptMode

-- | Convert a <a>PinInterruptMode</a> value to its equivalent
--   <a>SysfsEdge</a> value.
--   
--   <pre>
--   &gt;&gt;&gt; toSysfsEdge Disabled
--   None
--   
--   &gt;&gt;&gt; toSysfsEdge RisingEdge
--   Rising
--   
--   &gt;&gt;&gt; toSysfsEdge FallingEdge
--   Falling
--   
--   &gt;&gt;&gt; toSysfsEdge Level
--   Both
--   </pre>
toSysfsEdge :: PinInterruptMode -> SysfsEdge

-- | Exceptions that can be thrown by <tt>sysfs</tt> computations (in
--   addition to standard <a>IOError</a> exceptions, of course).
--   
--   The <tt>UnexpectedX</tt> values are truly exceptional and mean that,
--   while the <tt>sysfs</tt> attribute for the given pin exists, the
--   contents of the attribute do not match any expected value for that
--   attribute, which probably means that the package is incompatible with
--   the <tt>sysfs</tt> filesystem due to a kernel-level change.
data SysfsException

-- | The <tt>sysfs</tt> filesystem does not exist
SysfsNotPresent :: SysfsException

-- | Something in the <tt>sysfs</tt> filesystem does not behave as expected
--   (could indicate a change in <tt>sysfs</tt> behavior that the package
--   does not expect)
SysfsError :: SysfsException

-- | The <tt>sysfs</tt> operation is not permitted due to insufficient
--   permissions
SysfsPermissionDenied :: SysfsException

-- | The operation on the specified pin is not permitted, either due to
--   insufficient permissions, or because the pin's attribute cannot be
--   modified (e.g., trying to write to a pin that's configured for input)
PermissionDenied :: Pin -> SysfsException

-- | The operation is invalid for the specified pin, or in the specified
--   pin's current configuration
InvalidOperation :: Pin -> SysfsException

-- | The pin has already been exported
AlreadyExported :: Pin -> SysfsException

-- | The specified pin does not exist
InvalidPin :: Pin -> SysfsException

-- | The pin has been un-exported or does not exist
NotExported :: Pin -> SysfsException

-- | The pin does not support the specified input mode
UnsupportedInputMode :: PinInputMode -> Pin -> SysfsException

-- | The pin does not support the specified output mode
UnsupportedOutputMode :: PinOutputMode -> Pin -> SysfsException

-- | The pin does not have a <tt>direction</tt> attribute
NoDirectionAttribute :: Pin -> SysfsException

-- | The pin does not have an <tt>edge</tt> attribute
NoEdgeAttribute :: Pin -> SysfsException

-- | An unexpected value was read from the pin's <tt>direction</tt>
--   attribute
UnexpectedDirection :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the pin's <tt>value</tt> attribute
UnexpectedValue :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the pin's <tt>edge</tt> attribute
UnexpectedEdge :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the pin's <tt>active_low</tt>
--   attribute
UnexpectedActiveLow :: Pin -> Text -> SysfsException

-- | An unexpected value was read from the specified file
UnexpectedContents :: FilePath -> Text -> SysfsException

-- | An internal error has occurred in the interpreter, something which
--   should "never happen" and should be reported to the package maintainer
InternalError :: Text -> SysfsException


-- | Linux GPIO.
--   
--   Currently, this module is rather redundant, as it only re-exports the
--   top-level Linux <tt>sysfs</tt> GPIO module. That's because
--   <tt>sysfs</tt> GPIO is the only built-in GPIO implementation that the
--   Linux kernel currently supports. However, if future Linux kernels
--   provide a new GPIO system, that implementation would presumably also
--   be exported from here.
module System.GPIO.Linux


-- | Top-level re-exports for writing GPIO programs.
module System.GPIO


-- | Types and functions to emulate a (pure) rudimentary Posix-style
--   filesystem.
--   
--   This module was written for internal use only. Its interface may
--   change at any time. Documentation in this module is sparse, by design.
--   
--   N.B.: This mock filesystem implementation was written with the
--   intention of doing only just enough to emulate the operations needed
--   by the <a>MonadSysfs</a> type class. Though it may be possible to use
--   this implementation for other purposes, it has neither been designed
--   nor tested for that. Use at your own risk and please do not submit
--   requests for addtional functionality.
module System.GPIO.Linux.Sysfs.Mock.Internal
type Name = FilePath
data File
File :: !Name -> !FileType -> File
[_fileName] :: File -> !Name
[_fileType] :: File -> !FileType
data FileType
Constant :: [ByteString] -> FileType
Export :: FileType
Unexport :: FileType
Value :: Pin -> FileType
Direction :: Pin -> FileType
Edge :: Pin -> FileType
ActiveLow :: Pin -> FileType
data DirNode
DirNode :: !Name -> [File] -> DirNode
[_dirNodeName] :: DirNode -> !Name
[_files] :: DirNode -> [File]
type Directory = Tree DirNode
directory :: Name -> [File] -> [Directory] -> Directory
dirName :: Directory -> Name
files :: Directory -> [File]
dirNode :: Directory -> DirNode
subdirs :: Directory -> [Directory]
data MockFSCrumb
MockFSCrumb :: DirNode -> [Directory] -> [Directory] -> MockFSCrumb
[_node] :: MockFSCrumb -> DirNode
[_pred] :: MockFSCrumb -> [Directory]
[_succ] :: MockFSCrumb -> [Directory]

-- | An opaque type representing the current state of the mock
--   <tt>sysfs</tt> filesystem. Because the constructor is not exported via
--   the public interface, you cannot create these directly, but you can
--   manipulate them using the exposed mock <tt>sysfs</tt> operations and
--   then pass those <a>MockFSZipper</a>s around.
data MockFSZipper
MockFSZipper :: Directory -> [MockFSCrumb] -> MockFSZipper
[_cwd] :: MockFSZipper -> Directory
[_crumbs] :: MockFSZipper -> [MockFSCrumb]
cd :: FilePath -> MockFSZipper -> Either IOError MockFSZipper
pathFromRoot :: MockFSZipper -> FilePath
findFile :: Name -> Directory -> Maybe FileType
mkdir :: Name -> MockFSZipper -> Either IOError MockFSZipper
mkfile :: Name -> FileType -> Bool -> MockFSZipper -> Either IOError MockFSZipper
rmdir :: Name -> MockFSZipper -> Either IOError MockFSZipper
rmfile :: Name -> MockFSZipper -> Either IOError MockFSZipper
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.Internal.MockFSZipper
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.Internal.MockFSZipper
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.Internal.MockFSCrumb
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.Internal.MockFSCrumb
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.Internal.DirNode
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.Internal.DirNode
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.Internal.File
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.Internal.File
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.Internal.FileType
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.Internal.FileType


-- | A mock <a>MonadSysfs</a> instance, for testing GPIO programs.
--   
--   Note that this monad only mocks the subset of <tt>sysfs</tt>
--   functionality required for GPIO programs. It does not mock the entire
--   <tt>sysfs</tt> filesystem.
module System.GPIO.Linux.Sysfs.Mock

-- | The global state of a mock Linux GPIO subsystem with a <tt>sysfs</tt>
--   interface. It consists of the mock <tt>sysfs</tt> GPIO filesystem
--   state, along with the state of every mock pin.
--   
--   An actual Linux <tt>sysfs</tt> GPIO filesystem is not like a
--   general-purpose filesystem. The user cannot create files or
--   directories directly; they can only be created (or modified) via
--   prescribed operations on special conrol files, which are themselves
--   created by the kernel.
--   
--   Likewise, the kernel and hardware platform together determine which
--   GPIO pins are exposed to the user via the <tt>sysfs</tt> GPIO
--   filesystem.
--   
--   To preserve the illusion of an actual <tt>sysfs</tt> GPIO filesystem,
--   the <a>MockWorld</a> type is opaque and can only be manipulated via
--   the handful of actions that are implemented in this module. These
--   actions have been designed to keep the internal state of the mock
--   <tt>sysfs</tt> GPIO filesystem consistent with the behavior that would
--   be seen in an actual <tt>sysfs</tt> GPIO filesystem.
--   
--   The high/low signal level on a real GPIO pin can, of course, be
--   manipulated by the circuit to which the pin is conected. A future
--   version of this implementation may permit the direct manipulation of
--   mock pin values in order to simulate simple circuits, but currently
--   the only way to manipulate pin state is via the mock <tt>sysfs</tt>
--   GPIO filesystem.
data MockWorld

-- | A mock pin.
data MockPinState
MockPinState :: !PinDirection -> !Bool -> !Bool -> !PinValue -> Maybe SysfsEdge -> MockPinState

-- | The pin's direction
[_direction] :: MockPinState -> !PinDirection

-- | Is the pin's direction visible from the filesystem?
[_userVisibleDirection] :: MockPinState -> !Bool

-- | Is the pin configured as active-low?
[_activeLow] :: MockPinState -> !Bool

-- | The pin's <i>physical</i> signal level
[_value] :: MockPinState -> !PinValue

-- | The pin's interrupt mode (if supported)
[_edge] :: MockPinState -> Maybe SysfsEdge

-- | Default initial state of mock pins.
--   
--   <pre>
--   &gt;&gt;&gt; defaultMockPinState
--   MockPinState {_direction = Out, _userVisibleDirection = True, _activeLow = False, _value = Low, _edge = Just None}
--   </pre>
defaultMockPinState :: MockPinState

-- | Linux <tt>sysfs</tt> GPIO natively supports active-low logic levels. A
--   pin's "active" level is controlled by the pin's <tt>active_low</tt>
--   attribute. The pin's value relative to its <tt>active_low</tt>
--   attribute is called its <i>logical value</i>. This function returns
--   the mock pin's logical value.
--   
--   <pre>
--   &gt;&gt;&gt; logicalValue defaultMockPinState
--   Low
--   
--   &gt;&gt;&gt; logicalValue defaultMockPinState { _value = High }
--   High
--   
--   &gt;&gt;&gt; logicalValue defaultMockPinState { _activeLow = True }
--   High
--   
--   &gt;&gt;&gt; logicalValue defaultMockPinState { _activeLow = True, _value = High }
--   Low
--   </pre>
logicalValue :: MockPinState -> PinValue

-- | This function sets the <a>MockPinState</a> signal level to the given
--   <i>logical</i> value.
--   
--   <pre>
--   &gt;&gt;&gt; _value $ setLogicalValue High defaultMockPinState
--   High
--   
--   &gt;&gt;&gt; _value $ setLogicalValue High defaultMockPinState { _activeLow = True }
--   Low
--   </pre>
setLogicalValue :: PinValue -> MockPinState -> MockPinState

-- | A mock GPIO "chip." In the Linux <tt>sysfs</tt> GPIO filesystem, a
--   GPIO chip is a set of one or more GPIO pins.
--   
--   Note that the <a>_initialPinStates</a> list is used to construct the
--   pin state for a <a>MockWorld</a> (see <a>runSysfsMockT</a>). For each
--   <a>MockPinState</a> value in the list, a mock pin will be created in
--   the mock filesystem such that, when that pin is exported, its path is
--   <tt>/sys/class/gpio/gpioN</tt>, where <tt>N</tt> is <tt>_base</tt> +
--   the pin's index in the <a>_initialPinStates</a> list.
data MockGpioChip
MockGpioChip :: !Text -> !Int -> [MockPinState] -> MockGpioChip

-- | The name given to the chip in the filesystem
[_label] :: MockGpioChip -> !Text

-- | The pin number of the chip's first pin
[_base] :: MockGpioChip -> !Int

-- | The pins' initial states
[_initialPinStates] :: MockGpioChip -> [MockPinState]

-- | A type alias for a strict map of <a>Pin</a> to its
--   <a>MockPinState</a>.
type MockPins = Map Pin MockPinState

-- | Get the pin map from a <a>MockWorld</a>.
mockWorldPins :: MockWorld -> MockPins

-- | The initial <a>MockWorld</a>, representing a <tt>sysfs</tt> filesystem
--   with no pins.
initialMockWorld :: MockWorld

-- | A monad transformer which adds mock <tt>sysfs</tt> computations to an
--   inner monad <tt>m</tt>.
newtype SysfsMockT m a
SysfsMockT :: StateT MockWorld m a -> SysfsMockT m a
[unSysfsMockT] :: SysfsMockT m a -> StateT MockWorld m a

-- | Run a mock <tt>sysfs</tt> computation in monad <tt>m</tt> with an
--   initial mock world and list of <a>MockGpioChip</a>s; and return a
--   tuple containing the computation's value and the final
--   <a>MockWorld</a>. If an exception occurs in the mock computation, a
--   <a>MockFSException</a> is thrown.
--   
--   Before running the computation, the <a>MockWorld</a> is populated with
--   the GPIO pins as specified by the list of <a>MockGpioChip</a>s. If any
--   of the chips' pin ranges overlap, a <a>MockFSException</a> is thrown.
--   
--   Typically, you will only need this action if you're trying to mock
--   Linux <tt>sysfs</tt> GPIO computations using a custom monad
--   transformer stack. For simple cases, see <a>runSysfsGpioMock</a> or
--   <a>runSysfsGpioMockIO</a>.
runSysfsMockT :: (MockM m) => SysfsMockT m a -> MockWorld -> [MockGpioChip] -> m (a, MockWorld)

-- | Like <a>runSysfsMockT</a>, but returns only the computation's value.
evalSysfsMockT :: (MockM m) => SysfsMockT m a -> MockWorld -> [MockGpioChip] -> m a

-- | Like <a>runSysfsMockT</a>, but returns only the final
--   <a>MockWorld</a>.
execSysfsMockT :: (MockM m) => SysfsMockT m a -> MockWorld -> [MockGpioChip] -> m MockWorld

-- | A specialization of <a>SysfsGpioT</a> which runs (pure, fake) GPIO
--   computations via a mock <tt>sysfs</tt>.
type SysfsGpioMock = SysfsGpioT SysfsMock

-- | Run a <a>SysfsGpioMock</a> computation with an initial mock world and
--   list of <a>MockGpioChip</a>s, and return a tuple containing the
--   computation's value and the final <a>MockWorld</a>. Any exceptions
--   that occur in the mock computation are returned as a <a>Left</a>
--   value.
--   
--   Before running the computation, the <a>MockWorld</a> is populated with
--   the GPIO pins as specified by the list of <a>MockGpioChip</a>s. If any
--   of the chips' pin ranges overlap, a <a>MockFSException</a> is returned
--   in a <a>Left</a> value.
--   
--   <pre>
--   &gt;&gt;&gt; import System.GPIO.Monad
--   
--   &gt;&gt;&gt; let mockChip = MockGpioChip "chip0" 0 (replicate 16 defaultMockPinState)
--   
--   &gt;&gt;&gt; fst &lt;$&gt; runSysfsGpioMock pins initialMockWorld [mockChip]
--   Right [Pin 0,Pin 1,Pin 2,Pin 3,Pin 4,Pin 5,Pin 6,Pin 7,Pin 8,Pin 9,Pin 10,Pin 11,Pin 12,Pin 13,Pin 14,Pin 15]
--   
--   &gt;&gt;&gt; fst &lt;$&gt; runSysfsGpioMock (openPin (Pin 32)) initialMockWorld [mockChip]
--   Left InvalidPin (Pin 32)
--   </pre>
runSysfsGpioMock :: SysfsGpioMock a -> MockWorld -> [MockGpioChip] -> Either SomeException (a, MockWorld)

-- | Like <a>runSysfsGpioMock</a>, but returns only the computation's
--   value.
evalSysfsGpioMock :: SysfsGpioMock a -> MockWorld -> [MockGpioChip] -> Either SomeException a

-- | Like <a>runSysfsGpioMock</a>, but returns only the final
--   <a>MockWorld</a>.
execSysfsGpioMock :: SysfsGpioMock a -> MockWorld -> [MockGpioChip] -> Either SomeException MockWorld

-- | Like <a>SysfsGpioMock</a>, but wraps <a>IO</a> so that you can mix
--   <a>IO</a> actions and GPIO actions in a mock GPIO environment.
type SysfsGpioMockIO = SysfsGpioT SysfsMockIO

-- | Run a <a>SysfsGpioMockIO</a> computation with an initial mock world
--   and list of <a>MockGpioChip</a>s, and return a tuple containing the
--   computation's value and the final <a>MockWorld</a>.
--   
--   Before running the computation, the <a>MockWorld</a> is populated with
--   the GPIO pins as specified by the list of <a>MockGpioChip</a>s. If any
--   of the chips' pin ranges overlap, a <a>MockFSException</a> is thrown.
--   
--   <pre>
--   &gt;&gt;&gt; import System.GPIO.Monad
--   
--   &gt;&gt;&gt; let mockChip = MockGpioChip "chip0" 0 (replicate 16 defaultMockPinState)
--   
--   &gt;&gt;&gt; fst &lt;$&gt; runSysfsGpioMockIO pins initialMockWorld [mockChip]
--   [Pin 0,Pin 1,Pin 2,Pin 3,Pin 4,Pin 5,Pin 6,Pin 7,Pin 8,Pin 9,Pin 10,Pin 11,Pin 12,Pin 13,Pin 14,Pin 15]
--   
--   &gt;&gt;&gt; fst &lt;$&gt; runSysfsGpioMockIO (openPin (Pin 32)) initialMockWorld [mockChip]
--   *** Exception: InvalidPin (Pin 32)
--   </pre>
runSysfsGpioMockIO :: SysfsGpioMockIO a -> MockWorld -> [MockGpioChip] -> IO (a, MockWorld)

-- | Like <a>runSysfsGpioMockIO</a>, but returns only the computation's
--   value.
evalSysfsGpioMockIO :: SysfsGpioMockIO a -> MockWorld -> [MockGpioChip] -> IO a

-- | Like <a>runSysfsGpioMockIO</a>, but returns only the final
--   <a>MockWorld</a>.
execSysfsGpioMockIO :: SysfsGpioMockIO a -> MockWorld -> [MockGpioChip] -> IO MockWorld

-- | Exceptions that can be thrown by mock <tt>sysfs</tt> filesystem
--   operations.
--   
--   Note that, as much as is reasonably possible, when an error occurs,
--   the mock filesystem implementation throws the same exception as would
--   occur in an actual <tt>sysfs</tt> filesystem (i.e., <a>IOError</a>s).
--   However, in a few cases, there are exceptions that are specific to the
--   mock <tt>sysfs</tt> implementation; in these cases, a
--   <a>MockFSException</a> is thrown.
data MockFSException

-- | The user has defined defined at least two <a>MockGpioChip</a>s with
--   the same pin number, which is an invalid condition
GpioChipOverlap :: Pin -> MockFSException

-- | An internal error has occurred in the mock <tt>sysfs</tt> interpreter,
--   something which should "never happen" and should be reported to the
--   package maintainer.
InternalError :: Text -> MockFSException

-- | The simplest possible (pure) mock <tt>sysfs</tt> monad.
--   
--   NB: this monad <i>cannot</i> run GPIO computations; its only use is to
--   mock <tt>sysfs</tt> operations on an extremely limited mock
--   <tt>sysfs</tt> simulator.
--   
--   You probably do not want to use this monad; see either
--   <a>SysfsGpioMock</a> or <a>SysfsGpioMockIO</a>, which adds GPIO
--   computations to this mock <tt>sysfs</tt> environment.
type SysfsMock = SysfsMockT Catch

-- | A pure version of <a>runSysfsMockT</a> which returns errors in a
--   <a>Left</a>, and both the computation's value and the final state of
--   the <a>MockWorld</a> in a <a>Right</a>.
--   
--   <pre>
--   &gt;&gt;&gt; let mockChip = MockGpioChip "chip0" 0 (replicate 16 defaultMockPinState)
--   
--   &gt;&gt;&gt; fst &lt;$&gt; runSysfsMock (getDirectoryContents "/sys/class/gpio") initialMockWorld [mockChip]
--   Right ["gpiochip0","export","unexport"]
--   
--   &gt;&gt;&gt; runSysfsMock (getDirectoryContents "/sys/class/does_not_exist") initialMockWorld [mockChip]
--   Left /sys/class/does_not_exist: Mock.Internal.cd: does not exist
--   </pre>
runSysfsMock :: SysfsMock a -> MockWorld -> [MockGpioChip] -> Either SomeException (a, MockWorld)

-- | Like <a>runSysfsMock</a>, but returns only the computation's value.
evalSysfsMock :: SysfsMock a -> MockWorld -> [MockGpioChip] -> Either SomeException a

-- | Like <a>runSysfsMock</a>, but returns only the final <a>MockWorld</a>.
execSysfsMock :: SysfsMock a -> MockWorld -> [MockGpioChip] -> Either SomeException MockWorld

-- | The simplest possible (<a>IO</a>-enabled) mock <tt>sysfs</tt> monad.
--   Like <a>SysfsMock</a>, but allows you to mix <a>IO</a> operations into
--   your <tt>sysfs</tt> computations, as well.
--   
--   NB: this monad <i>cannot</i> run GPIO computations; its only use is to
--   mock <tt>sysfs</tt> operations on an extremely limited mock
--   <tt>sysfs</tt> simulator.
--   
--   You probably do not want to use this monad; see either
--   <a>SysfsGpioMock</a> or <a>SysfsGpioMockIO</a>, which adds GPIO
--   computations to this mock <tt>sysfs</tt> environment.
type SysfsMockIO = SysfsMockT IO

-- | An <a>IO</a> version of <a>runSysfsMockT</a>. Errors are expressed as
--   exceptions.
--   
--   <pre>
--   &gt;&gt;&gt; let mockChip = MockGpioChip "chip0" 0 (replicate 16 defaultMockPinState)
--   
--   &gt;&gt;&gt; fst &lt;$&gt; runSysfsMockIO (getDirectoryContents "/sys/class/gpio") initialMockWorld [mockChip]
--   ["gpiochip0","export","unexport"]
--   
--   &gt;&gt;&gt; runSysfsMockIO (getDirectoryContents "/sys/class/does_not_exist") initialMockWorld [mockChip]
--   *** Exception: /sys/class/does_not_exist: Mock.Internal.cd: does not exist
--   </pre>
runSysfsMockIO :: SysfsMockIO a -> MockWorld -> [MockGpioChip] -> IO (a, MockWorld)

-- | Like <a>runSysfsMockIO</a>, but returns only the computation's value.
evalSysfsMockIO :: SysfsMockIO a -> MockWorld -> [MockGpioChip] -> IO a

-- | Like <a>runSysfsMockIO</a>, but returns only the final
--   <a>MockWorld</a>.
execSysfsMockIO :: SysfsMockIO a -> MockWorld -> [MockGpioChip] -> IO MockWorld

-- | Check whether the specified directory exists in the mock filesystem.
doesDirectoryExist :: (MockM m) => FilePath -> SysfsMockT m Bool

-- | Check whether the specified file exists in the mock filesystem.
doesFileExist :: (MockM m) => FilePath -> SysfsMockT m Bool

-- | Get a directory listing for the specified directory in the mock
--   filesystem.
getDirectoryContents :: (MockM m) => FilePath -> SysfsMockT m [FilePath]

-- | Read the contents of the specified file in the mock filesystem.
readFile :: (MockM m) => FilePath -> SysfsMockT m ByteString

-- | Write the contents of the specified file in the mock filesystem.
writeFile :: (MockM m) => FilePath -> ByteString -> SysfsMockT m ()

-- | For the mock filesystem, this action is equivalent to
--   <a>writeFile</a>.
unlockedWriteFile :: (MockM m) => FilePath -> ByteString -> SysfsMockT m ()

-- | Polling is not implemented for the mock filesystem, so this action
--   always returns the value <tt>1</tt>.
pollFile :: (MockM m) => FilePath -> Int -> SysfsMockT m CInt
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.MockFSException
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.MockFSException
instance Control.Monad.Trans.Class.MonadTrans System.GPIO.Linux.Sysfs.Mock.SysfsMockT
instance Control.Monad.Logger.MonadLoggerIO m => Control.Monad.Logger.MonadLoggerIO (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Logger.MonadLogger m => Control.Monad.Logger.MonadLogger (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Base.Monad m => Control.Monad.State.Class.MonadState System.GPIO.Linux.Sysfs.Mock.MockWorld (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Writer.Class.MonadWriter w m => Control.Monad.Writer.Class.MonadWriter w (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Error.Class.MonadError e m => Control.Monad.Error.Class.MonadError e (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Reader.Class.MonadReader r m => Control.Monad.Reader.Class.MonadReader r (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Cont.Class.MonadCont m => Control.Monad.Cont.Class.MonadCont (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Base.MonadPlus m => GHC.Base.MonadPlus (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Base.Monad m => GHC.Base.Monad (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Base.Monad m => GHC.Base.Applicative (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Base.MonadPlus m => GHC.Base.Alternative (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Base.Functor m => GHC.Base.Functor (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.MockWorld
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.MockWorld
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.MockGpioChip
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.MockGpioChip
instance GHC.Classes.Eq System.GPIO.Linux.Sysfs.Mock.MockPinState
instance GHC.Show.Show System.GPIO.Linux.Sysfs.Mock.MockPinState
instance GHC.Exception.Exception System.GPIO.Linux.Sysfs.Mock.MockFSException
instance System.GPIO.Linux.Sysfs.Mock.MockM m => System.GPIO.Linux.Sysfs.Monad.MonadSysfs (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (System.GPIO.Linux.Sysfs.Mock.SysfsMockT m)
instance Control.Monad.Trans.Control.MonadTransControl System.GPIO.Linux.Sysfs.Mock.SysfsMockT

module System.GPIO.Tutorial

-- | A GPIO pin, identified by pin number.
--   
--   Note that GPIO pin numbering is platform- and runtime-dependent. See
--   the documentation for your particular platform for an explanation of
--   how pin numbers are assigned to physical pins.
newtype Pin
Pin :: Int -> Pin

-- | A pin's signal level as a binary value.
data PinValue
Low :: PinValue
High :: PinValue

-- | A pin's active level (active-high/active-low).
data PinActiveLevel
ActiveLow :: PinActiveLevel
ActiveHigh :: PinActiveLevel

-- | A pin's direction (input/output).
data PinDirection
In :: PinDirection
Out :: PinDirection

-- | GPIO pins may support a number of different physical configurations
--   when used as a digital input.
--   
--   Pins that are capable of input will at least support the
--   <a>InputDefault</a> mode. <a>InputDefault</a> mode is special in that,
--   unlike the other input modes, it does not represent a unique physical
--   configuration, but is simply a pseudonym for another (actual) input
--   mode. Exactly which mode is used by the hardware when
--   <a>InputDefault</a> mode is specified is platform-dependent. By using
--   <tt>InputDefaut</tt> mode, you are saying that you don't care about
--   the pin's actual configuration, other than the fact that it's being
--   used for input.
data PinInputMode

-- | The pin's default input mode, i.e., the mode used when a more specific
--   mode is not specified
InputDefault :: PinInputMode

-- | A floating / high-impedance / tri-state mode which uses little power,
--   but when disconnected, may cause the pin's value to be indeterminate
InputFloating :: PinInputMode

-- | The pin is connected to an internal pull-up resistor such that, when
--   the pin is disconnected or connected to a floating / high-impedance
--   node, its physical value will be <a>High</a>
InputPullUp :: PinInputMode

-- | The pin is connected to an internal pull-down resistor such that, when
--   the pin is disconnected or connected to a floating / high-impedance
--   node, its physical value will be <a>Low</a>
InputPullDown :: PinInputMode

-- | GPIO pins may support a number of different physical configurations
--   when used as a digital output.
--   
--   Pins that are capable of output will at least support the
--   <a>OutputDefault</a> mode. <a>OutputDefault</a> mode is special in
--   that, unlike the other output modes, it does not represent a unique
--   physical configuration, but is simply a pseudonym for another (actual)
--   output mode. Exactly which mode is used by the hardware when
--   <a>OutputDefault</a> mode is specified is platform-dependent. By using
--   <tt>OutputDefaut</tt> mode, you are saying that you don't care about
--   the pin's actual configuration, other than the fact that it's being
--   used for output.
data PinOutputMode

-- | The pin's default output mode, i.e., the mode used when a more
--   specific mode is not specified
OutputDefault :: PinOutputMode

-- | The output actively drives both the <a>High</a> and <a>Low</a> states
OutputPushPull :: PinOutputMode

-- | The output actively drives the <a>Low</a> state, but <a>High</a> is
--   left floating (also known as <i>open collector</i>)
OutputOpenDrain :: PinOutputMode

-- | The output actively drives the <a>Low</a> state, and is connected to
--   an internal pull-up resistor in the <a>High</a> state.
OutputOpenDrainPullUp :: PinOutputMode

-- | The output actively drives the <a>High</a> state, but <a>Low</a> is
--   left floating (also known as <i>open emitter</i>)
OutputOpenSource :: PinOutputMode

-- | The output actively drives the <a>High</a> state, and is connected to
--   an internal pull-down resistor in the <a>Low</a> state.
OutputOpenSourcePullDown :: PinOutputMode

-- | A pin's interrupt mode.
--   
--   Note that the pin's interrupt mode is defined in terms of the pin's
--   <i>logical</i> signal value; i.e., when the pin is configured for
--   active-low logic, <a>RisingEdge</a> refers to the physical signal's
--   trailing edge, and <a>FallingEdge</a> refers to the physical signal's
--   rising edge.
data PinInterruptMode

-- | Interrupts are disabled
Disabled :: PinInterruptMode

-- | Interrupt on the pin's (logical) rising edge
RisingEdge :: PinInterruptMode

-- | Interrupt on the pin's (logical) falling edge
FallingEdge :: PinInterruptMode

-- | Interrupt on any change to the pin's signal level
Level :: PinInterruptMode

-- | Catalog a pin's capabilities.
data PinCapabilities
PinCapabilities :: Set PinInputMode -> Set PinOutputMode -> Bool -> PinCapabilities

-- | The set of input modes that the pin supports
[_inputModes] :: PinCapabilities -> Set PinInputMode

-- | The set of output modes that the pin supports
[_outputModes] :: PinCapabilities -> Set PinOutputMode

-- | Does the pin support interrupts in input mode?
[_interrupts] :: PinCapabilities -> Bool

-- | Run a <tt>hpio</tt> program on a mock system with 17 GPIO pins.
runTutorial :: SysfsGpioMockIO a -> IO a

-- | A handle to a pin that's been configured for non-blocking reads only.
--   
--   You cannot poll an <a>InputPin</a> for interrupts. See
--   <a>InterruptPin</a>.
data InputPin h

-- | Like <a>withPin</a>, but for <a>InputPin</a>s. Sets the pin's input
--   mode to the specified <a>PinInputMode</a> value.
--   
--   If the optional active level argument is <a>Nothing</a>, then the
--   pin's active level is unchanged from its current state. Otherwise, the
--   pin's active level is set to the specified level.
--   
--   It is an error to call this action if the pin cannot be configured for
--   input, or if it does not support the specified input mode.
withInputPin :: (MaskGpioM h m) => Pin -> PinInputMode -> Maybe PinActiveLevel -> (InputPin h -> m a) -> m a

-- | A handle to a pin that's been configured both for non-blocking reads
--   and for interrupt-driven polling reads.
data InterruptPin h

-- | Like <a>withPin</a>, but for <a>InterruptPin</a>s. The pin is opened
--   for input, is input mode is set to the specified <a>PinInputMode</a>
--   value, and its interrupt mode is set to the specified
--   <a>PinInterruptMode</a> value.
--   
--   If the optional active level argument is <a>Nothing</a>, then the
--   pin's active level is unchanged from its current state. Otherwise, the
--   pin's active level is set to the specified level.
--   
--   It is an error to call this action if any of the following are true:
--   
--   <ul>
--   <li>The pin cannot be configured for input.</li>
--   <li>The pin does not support the specified input mode.</li>
--   <li>The pin does not support interrupts.</li>
--   </ul>
withInterruptPin :: (MaskGpioM h m) => Pin -> PinInputMode -> PinInterruptMode -> Maybe PinActiveLevel -> (InterruptPin h -> m a) -> m a

-- | A handle to a pin that's been configured for output only.
--   
--   Note that output pins can be both read and written. However, they only
--   support non-blocking reads, not interrupt-driven polling reads.
data OutputPin h

-- | Like <a>withPin</a>, but for <a>OutputPin</a>s. Sets the pin's output
--   mode to the specified <a>PinOutputMode</a> value.
--   
--   The <a>PinValue</a> argument specifies the pin's initial output value.
--   It is relative to the active level argument, or to the pin's current
--   active level if the active level argument is <a>Nothing</a>.
--   
--   It is an error to call this action if the pin cannot be configured for
--   output, or if it does not support the specified output mode.
withOutputPin :: (MaskGpioM h m) => Pin -> PinOutputMode -> Maybe PinActiveLevel -> PinValue -> (OutputPin h -> m a) -> m a
data TutorialEnv
type TutorialReaderGpioIO a = ReaderT TutorialEnv (SysfsGpioT (SysfsMockT IO)) a
