{-# LANGUAGE CPP #-}

-- |This module provides the serial port interface.
--
-- > import qualified Data.ByteString.Char8 as B
-- > import System.Hardware.Serialport
-- > let port = "COM3"          -- Windows
-- > let port = "/dev/ttyUSB0"  -- Linux
-- > s <- openSerial port defaultSerialSettings { commSpeed = CS2400 }
-- > send s $ B.pack "AT\r"
-- > recv s 10 >>= print
-- > closeSerial s
--
-- Or use the experimental interface with standard handles:
--
-- > import System.IO
-- > import System.Hardware.Serialport
-- > let port = "COM3"           -- Windows
-- > let port = "/dev/ttyUSB0"   -- Linux
-- > h <- hOpenSerial port defaultSerialSettings
-- > hPutStr h "AT\r"
-- > hGetLine h >>= print
-- > hClose h


module System.Hardware.Serialport (
  -- * Types
   CommSpeed(..)
  ,StopBits(..)
  ,Parity(..)
  ,FlowControl(..)
  ,SerialPort
  -- * Configure port
  -- | You don't need the get or set functions, they are used by openSerial
  ,SerialPortSettings(..)
  ,defaultSerialSettings
  ,setSerialSettings
  ,getSerialSettings
  -- * Serial methods
  -- ** Device
  ,hOpenSerial
  ,openSerial
  ,closeSerial
  ,withSerial
  ,hWithSerial
  -- ** Sending & receiving
  ,send
  ,recv
  ,flush
  -- ** Line control
  ,setDTR
  ,setRTS
  ) where

#if defined(mingw32_HOST_OS)
import System.Hardware.Serialport.Windows
#else
import System.Hardware.Serialport.Posix
#endif
import System.Hardware.Serialport.Types

import System.IO (Handle, hClose)
import qualified Control.Exception as Ex


-- |Safer device function, so you don't forget to close the device
withSerial :: FilePath -> SerialPortSettings -> ( SerialPort -> IO a ) -> IO a
withSerial :: FilePath -> SerialPortSettings -> (SerialPort -> IO a) -> IO a
withSerial FilePath
dev SerialPortSettings
settings = IO SerialPort
-> (SerialPort -> IO ()) -> (SerialPort -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
Ex.bracket (FilePath -> SerialPortSettings -> IO SerialPort
openSerial FilePath
dev SerialPortSettings
settings) SerialPort -> IO ()
closeSerial

-- |Like `withSerial` but using `Handle`
hWithSerial :: FilePath -> SerialPortSettings -> (Handle -> IO a) -> IO a
hWithSerial :: FilePath -> SerialPortSettings -> (Handle -> IO a) -> IO a
hWithSerial FilePath
dev SerialPortSettings
settings = IO Handle -> (Handle -> IO ()) -> (Handle -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
Ex.bracket (FilePath -> SerialPortSettings -> IO Handle
hOpenSerial FilePath
dev SerialPortSettings
settings) Handle -> IO ()
hClose