diff --git a/System/Hardware/Serialport.hs b/System/Hardware/Serialport.hs
--- a/System/Hardware/Serialport.hs
+++ b/System/Hardware/Serialport.hs
@@ -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
diff --git a/System/Hardware/Serialport/Posix.hsc b/System/Hardware/Serialport/Posix.hsc
--- a/System/Hardware/Serialport/Posix.hsc
+++ b/System/Hardware/Serialport/Posix.hsc
@@ -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
diff --git a/System/Hardware/Serialport/Types.hs b/System/Hardware/Serialport/Types.hs
--- a/System/Hardware/Serialport/Types.hs
+++ b/System/Hardware/Serialport/Types.hs
@@ -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 =
diff --git a/System/Hardware/Serialport/Windows.hs b/System/Hardware/Serialport/Windows.hs
--- a/System/Hardware/Serialport/Windows.hs
+++ b/System/Hardware/Serialport/Windows.hs
@@ -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
diff --git a/System/Win32/Comm.hsc b/System/Win32/Comm.hsc
--- a/System/Win32/Comm.hsc
+++ b/System/Win32/Comm.hsc
@@ -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)
diff --git a/serialport.cabal b/serialport.cabal
--- a/serialport.cabal
+++ b/serialport.cabal
@@ -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)
