{-# LANGUAGE RecordWildCards #-}

module System.Hardware.Acquisition.Connection.Serial
	( Config (..)
	, module System.Serial
	, open
	) where

import Prelude
import Control.Monad.Error
import Data.Word
import System.IO

import System.Serial
	( BaudRate (..)
	, Parity (..)
	, StopBits (..)
	, FlowControl (..)
	)
import qualified System.Serial as Serial
import qualified Data.ByteString as BS

import System.Hardware.Acquisition

data Config = Config
	{ baud :: BaudRate
	, bits :: Int
	, parity :: Parity
	, stop :: StopBits
	, flow :: FlowControl
	} deriving ()

open :: Config -> FilePath -> IO Connection
open c devpath = do
	h <- Serial.openSerial devpath (baud c) (bits c) (stop c) (parity c) (flow c)

	let getWord8 :: (Error e, MonadError e m, MonadIO m) => m Word8
	    getWord8 = do
			forM [hIsClosed, hIsEOF] $ \ f -> do
				liftIO (f h) >>= flip when (throwError (strMsg "end of file?"))
			return head `ap` liftIO (BS.unpack `fmap` BS.hGet h 1)

	let disconnect :: MonadIO m => m ()
	    disconnect = liftIO (hClose h)

	return Connection {..}