serialport 0.4.2 → 0.4.3
raw patch · 6 files changed
+63/−97 lines, 6 filesdep +bytestring
Dependencies added: bytestring
Files
- System/Hardware/Serialport.hs +7/−11
- System/Hardware/Serialport/Posix.hsc +22/−33
- System/Hardware/Serialport/Types.hs +2/−2
- System/Hardware/Serialport/Windows.hs +28/−47
- System/Win32/Comm.hsc +2/−2
- serialport.cabal +2/−2
System/Hardware/Serialport.hs view
@@ -2,12 +2,13 @@ -- |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 }--- > sendString s "AT\r"--- > recvString s >>= print+-- > send s $ B.pack "AT\r"+-- > recv s 10 >>= print -- > closeSerial s -- @@ -30,10 +31,8 @@ ,closeSerial ,withSerial -- ** Sending & receiving- ,sendChar- ,sendString- ,recvChar- ,recvString+ ,send+ ,recv ,flush -- ** Line control ,setDTR@@ -47,11 +46,8 @@ #endif import System.Hardware.Serialport.Types +import qualified Control.Exception as Ex -- |Safer device function, so you don't forget to close the device withSerial :: String -> SerialPortSettings -> ( SerialPort -> IO a ) -> IO a-withSerial dev settings f = do- s <- openSerial dev settings- res <- f s- closeSerial s- return res+withSerial dev settings = Ex.bracket (openSerial dev settings) closeSerial
System/Hardware/Serialport/Posix.hsc view
@@ -2,7 +2,8 @@ {-# OPTIONS_HADDOCK hide #-} module System.Hardware.Serialport.Posix where -import System.IO.Error+import qualified Data.ByteString.Char8 as B+import qualified Control.Exception as Ex import System.Posix.IO import System.Posix.Types import System.Posix.Terminal@@ -12,43 +13,32 @@ -- |Open and configure a serial port-openSerial :: FilePath -- ^ The filename of the serial port, such as @\/dev\/ttyS0@ or @\/dev\/ttyUSB0@+openSerial :: FilePath -- ^ Serial port, such as @\/dev\/ttyS0@ or @\/dev\/ttyUSB0@ -> SerialPortSettings -> IO SerialPort openSerial dev settings = do fd' <- openFd dev ReadWrite Nothing defaultFileFlags { noctty = True }- let serial_port = (SerialPort fd' defaultSerialSettings)+ let serial_port = SerialPort fd' defaultSerialSettings return =<< setSerialSettings serial_port settings --- |Possibly receive a character unless the timeout given in openSerial is exceeded.-recvChar :: SerialPort -> IO (Maybe Char)-recvChar (SerialPort fd' _) = do- result <- try $ fdRead fd' 1- return $ case result of- Right (str, _) -> Just $ head str- Left _ -> Nothing----- |Receive a string-recvString :: SerialPort -> IO String-recvString (SerialPort fd' _) = do- result <- try $ fdRead fd' 128+-- |Receive bytes, given the maximum number+recv :: SerialPort -> Int -> IO B.ByteString+recv (SerialPort fd' _) n = do+ result <- Ex.try $ fdRead fd' count :: IO (Either IOError (String, ByteCount)) return $ case result of- Right (str, _) -> str- Left _ -> ""----- |Send a character-sendChar :: SerialPort -> Char -> IO ()-sendChar (SerialPort fd' _ ) c =- fdWrite fd' [c] >> return ()+ Right (str, _) -> B.pack str+ Left _ -> B.empty+ where+ count = fromIntegral n --- |Send a string-sendString :: SerialPort -> String -> IO ()-sendString (SerialPort fd' _) s =- fdWrite fd' s >> return ()+-- |Send bytes+send :: SerialPort+ -> B.ByteString+ -> IO Int -- ^ Number of bytes actually sent+send (SerialPort fd' _ ) msg =+ fromIntegral `fmap` fdWrite fd' (B.unpack msg) -- |Flush buffers@@ -59,8 +49,7 @@ -- |Close the serial port closeSerial :: SerialPort -> IO ()-closeSerial (SerialPort fd' _ ) =- closeFd fd'+closeSerial = closeFd . fd #include <sys/ioctl.h>@@ -114,7 +103,7 @@ -- |Get configuration from serial port getSerialSettings :: SerialPort -> SerialPortSettings-getSerialSettings (SerialPort _ settings) = settings+getSerialSettings = portSettings withParity :: TerminalAttributes -> Parity -> TerminalAttributes@@ -146,8 +135,8 @@ configureSettings :: TerminalAttributes -> SerialPortSettings -> TerminalAttributes configureSettings termOpts settings =- termOpts `withInputSpeed` (commSpeedToBaudRate (commSpeed settings))- `withOutputSpeed` (commSpeedToBaudRate (commSpeed settings))+ termOpts `withInputSpeed` commSpeedToBaudRate (commSpeed settings)+ `withOutputSpeed` commSpeedToBaudRate (commSpeed settings) `withBits` fromIntegral (bitsPerWord settings) `withStopBits` stopb settings `withParity` parity settings
System/Hardware/Serialport/Types.hs view
@@ -46,7 +46,7 @@ #else fd :: Fd, #endif- newSettings :: SerialPortSettings+ portSettings :: SerialPortSettings } @@ -62,7 +62,7 @@ -- -- - no flow control ----- - 0.1 millisecond receive timeout+-- - 0.1 second receive timeout -- defaultSerialSettings :: SerialPortSettings defaultSerialSettings =
System/Hardware/Serialport/Windows.hs view
@@ -2,23 +2,22 @@ module System.Hardware.Serialport.Windows where import Data.Bits+import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Unsafe as BU import qualified System.Win32.Comm as Comm import System.Win32.Types import System.Win32.File-import Foreign.C.Types-import Foreign.C.String-import Foreign.Marshal.Utils import Foreign.Marshal.Alloc-import Foreign.Storable import System.Hardware.Serialport.Types+import Control.Monad -- | Open and configure a serial port-openSerial :: String -- ^ The filename of the serial port, such as @COM5@ or @\/\/.\/CNCA0@+openSerial :: String -- ^ Serial port, such as @COM5@ or @CNCA0@ -> SerialPortSettings -> IO SerialPort openSerial dev settings = do- h <- createFile dev access_mode share_mode security_attr create_mode file_attr template_file+ h <- createFile ("\\\\.\\" ++ dev) access_mode share_mode security_attr create_mode file_attr template_file let serial_port = SerialPort h defaultSerialSettings return =<< setSerialSettings serial_port settings where@@ -30,61 +29,43 @@ template_file = Nothing --- |Possibly receive a character unless the timeout given in openSerial is exceeded.-recvChar :: SerialPort -> IO (Maybe Char)-recvChar (SerialPort h _) =- allocaBytes 1 $ \ p_n -> do- received <- win32_ReadFile h p_n count overlapped- if received == 0- then return Nothing- else do c <- peek p_n :: IO CChar- return $ Just $ castCCharToChar c- where- count = 1- overlapped = Nothing----- |Receive a string-recvString :: SerialPort -> IO String-recvString (SerialPort h _) =- allocaBytes 128 $ \ p_n -> do- recv_cnt <- win32_ReadFile h p_n count overlapped- peekCStringLen (p_n, fromIntegral recv_cnt)- where- count = 128- overlapped = Nothing----- |Send a character-sendChar :: SerialPort -> Char -> IO ()-sendChar (SerialPort h _) s =- with s (\ p_s -> do _ <- win32_WriteFile h p_s count overlapped- return () )+-- |Receive bytes, given the maximum number+recv :: SerialPort -> Int -> IO B.ByteString+recv (SerialPort h _) n =+ allocaBytes n $ \p -> do+ recv_cnt <- win32_ReadFile h p count overlapped+ B.packCStringLen (p, fromIntegral recv_cnt) where- count = 1+ count = fromIntegral n overlapped = Nothing --- |Send a string-sendString :: SerialPort -> String -> IO ()-sendString (SerialPort h _) s =- withCString s (\ p_s -> do _ <- win32_WriteFile h p_s (fromIntegral count) overlapped- return () )+-- |Send bytes+send :: SerialPort+ -> B.ByteString+ -> IO Int -- ^ Number of bytes actually sent+send (SerialPort h _) msg =+ BU.unsafeUseAsCString msg $ \p ->+ fromIntegral `fmap` win32_WriteFile h p count overlapped where- count = length s+ count = fromIntegral $ B.length msg overlapped = Nothing -- |Flush buffers flush :: SerialPort -> IO ()-flush (SerialPort h _) =+flush s@(SerialPort h _) = flushFileBuffers h+ >> consumeIncomingChars+ where+ consumeIncomingChars = do+ ch <- recv s 1+ unless (ch == B.empty) consumeIncomingChars -- |Close the serial port closeSerial :: SerialPort -> IO ()-closeSerial (SerialPort h _) =- closeHandle h+closeSerial = closeHandle . handle -- |Set the Data Terminal Ready level@@ -119,4 +100,4 @@ -- |Get configuration from serial port getSerialSettings :: SerialPort -> SerialPortSettings-getSerialSettings (SerialPort _ settings) = settings+getSerialSettings = portSettings
System/Win32/Comm.hsc view
@@ -46,12 +46,12 @@ #{poke DCB, XonLim} buf (2048 :: WORD) #{poke DCB, XoffLim} buf (512 :: WORD) #{poke DCB, ByteSize} buf (bitsPerWord settings :: BYTE)- #{poke DCB, Parity} buf (case (parity settings) of+ #{poke DCB, Parity} buf (case parity settings of NoParity -> #const NOPARITY Odd -> #const ODDPARITY Even -> #const EVENPARITY :: BYTE)- #{poke DCB, StopBits} buf (case (stopb settings) of+ #{poke DCB, StopBits} buf (case stopb settings of One -> #const ONESTOPBIT Two -> #const TWOSTOPBITS :: BYTE)
serialport.cabal view
@@ -1,5 +1,5 @@ Name: serialport-Version: 0.4.2+Version: 0.4.3 Cabal-Version: >= 1.6 Build-Type: Custom license: BSD3@@ -20,7 +20,7 @@ Library Exposed-Modules: System.Hardware.Serialport Other-Modules: System.Hardware.Serialport.Types- Build-Depends: base >= 4 && < 5+ Build-Depends: base >= 4 && < 5, bytestring ghc-options: -Wall if !os(windows)