diff --git a/System/FTDI/Internal.hs b/System/FTDI/Internal.hs
--- a/System/FTDI/Internal.hs
+++ b/System/FTDI/Internal.hs
@@ -14,7 +14,7 @@
 -- Imports
 -------------------------------------------------------------------------------
 
--- base
+-- from base:
 import Control.Applicative       ( Applicative, (<$>), Alternative )
 import Control.Exception         ( Exception, bracket, throwIO )
 import Control.Monad             ( Functor
@@ -24,6 +24,9 @@
                                  )
 import Control.Monad.Fix         ( MonadFix )
 import Data.Bool                 ( Bool, otherwise )
+#ifdef __HADDOCK__
+import Data.Bool                 ( Bool(False, True) )
+#endif
 import Data.Bits                 ( Bits, (.|.)
                                  , setBit, shiftL, shiftR, testBit
                                  )
@@ -50,30 +53,31 @@
 import Text.Read                 ( Read )
 import Text.Show                 ( Show )
 
--- base-unicode-symbols
+-- from base-unicode-symbols:
 import Data.Eq.Unicode           ( (≡) )
 import Data.Function.Unicode     ( (∘) )
 import Data.Monoid.Unicode       ( (⊕) )
 import Prelude.Unicode           ( (⋅), (÷) )
 
--- bytestring
-import qualified Data.ByteString as BS ( drop, length, null, splitAt, unpack )
-#ifdef __HADDOCK__
-import qualified Data.ByteString as BS ( empty )
-#endif
+-- from bytestring:
+import qualified Data.ByteString as BS ( empty, drop, length
+                                       , null, splitAt, unpack
+                                       )
 import Data.ByteString           ( ByteString )
 
--- ftdi
+-- from ftdi:
 import System.FTDI.Utils         ( divRndUp, clamp, genFromEnum, orBits )
 
--- safe
+-- from monads-fd:
+import Control.Monad.Trans       ( MonadTrans, MonadIO, lift, liftIO )
+
+-- from safe:
 import Safe                      ( atMay, headMay )
 
--- transformers
-import Control.Monad.Trans       ( MonadTrans, MonadIO, liftIO )
+-- from transformers:
 import Control.Monad.Trans.State ( StateT, get, put, runStateT )
 
--- usb
+-- from usb:
 import qualified System.USB as USB
 
 
@@ -158,7 +162,7 @@
 -- Devices
 -------------------------------------------------------------------------------
 
--- |A representation of an FTDI device. 
+-- |A representation of an FTDI device.
 data Device = Device
     { devUSB      ∷ USB.Device
     , devUSBConf  ∷ USB.ConfigDesc
@@ -279,7 +283,7 @@
 closeDevice ∷ DeviceHandle → IO ()
 closeDevice = USB.closeDevice ∘ devHndUSB
 
--- |The recommended way to acquire a handle. Ensures that the handles
+-- |The recommended way to acquire a handle. Ensures that the handle
 -- is released when the monadic computation is completed. Even, or
 -- especially, when an exception is thrown.
 withDeviceHandle ∷ Device → (DeviceHandle → IO α) → IO α
@@ -360,9 +364,9 @@
 @
   example &#x2237; 'InterfaceHandle' &#x2192; IO ()
   example ifHnd = do
-    (packets1, rest1) &#x2190; runChunkedReaderT ('readData' ifHnd 400) 'BS.empty'
+    (packets1, rest1) &#x2190; runChunkedReaderT ('readData' ifHnd (return 'False') 400) 'BS.empty'
     print $ 'BS.concat' packets1
-    (packets2, rest2) &#x2190; runChunkedReaderT ('readData' ifHnd 200) rest1
+    (packets2, rest2) &#x2190; runChunkedReaderT ('readData' ifHnd (return 'False') 200) rest1
     print $ 'BS.concat' packets2
 @
 
@@ -372,9 +376,9 @@
 @
   example &#x2237; 'InterfaceHandle' &#x2192; IO ()
   example ifHnd =
-    let reader = do packets1 &#x2190; 'readData' ifHnd 400
+    let reader = do packets1 &#x2190; 'readData' ifHnd (return 'False') 400
                     liftIO $ print $ 'BS.concat' packets1
-                    packets2 &#x2190; 'readData' ifHnd 200
+                    packets2 &#x2190; 'readData' ifHnd (return 'False') 200
                     liftIO $ print $ 'BS.concat' packets1
     in runChunkedReaderT reader 'BS.empty'
 @
@@ -385,23 +389,31 @@
 
 {-| Reads data from the given FTDI interface by performing bulk reads.
 
-This function produces an action in the ChunkedReaderT monad that, when
-executed, will read exactly the requested number of bytes. Executing the
-readData action will block until all data is read. The result value is a list
-of chunks, represented as ByteStrings. This representation was choosen for
-efficiency reasons.
+This function produces an action in the @ChunkedReaderT@ monad that
+will read exactly the requested number of bytes unless it is
+explicitly asked to stop early. Executing the @readData@ action will
+block until either:
 
-Data is read in packets. The function may choose to request more than needed in
-order to get the highest possible bandwidth. The excess of bytes is kept as the
-state of the ChunkedReaderT monad. A subsequent invocation of readData will
-first return bytes from the stored state before requesting more from the device
-itself. A consequence of this behaviour is that even when you request 100 bytes
-the function will actually request 512 bytes (depending on the packet size) and
-/block/ until all 512 bytes are read! There is no workaround since requesting
+ * All data are read
+
+ * The given checkStop action returns 'True'
+
+The result value is a list of chunks, represented as
+@ByteString@s. This representation was choosen for efficiency reasons.
+
+Data are read in packets. The function may choose to request more than
+needed in order to get the highest possible bandwidth. The excess of
+bytes is kept as the state of the @ChunkedReaderT@ monad. A subsequent
+invocation of @readData@ will first return bytes from the stored state
+before requesting more from the device itself. A consequence of this
+behaviour is that even when you request 100 bytes the function will
+actually request 512 bytes (depending on the packet size) and /block/
+until all 512 bytes are read! There is no workaround since requesting
 less bytes than the packet size is an error.
 
-USB timeouts will not interrupt readData. In case of a timeout readData will
-simply resume reading data. A small USB timeout can degrade performance.
+USB timeouts will not interrupt @readData@. In case of a timeout
+@readData@ will simply resume reading data. A small USB timeout can
+degrade performance.
 
 The FTDI latency timer can cause poor performance. If the FTDI chip can't fill
 a packet before the latency timer fires it is forced to send an incomplete
@@ -420,13 +432,16 @@
 
 @
   -- Read 100 data bytes from ifHnd
-  (packets, rest) &#x2190; 'runChunkedReaderT' ('readData' ifHnd 100) 'BS.empty'
+  (packets, rest) &#x2190; 'runChunkedReaderT' ('readData' ifHnd (return 'False') 100) 'BS.empty'
 @
 
 -}
--- TODO: timeout
-readData ∷ ∀ m. MonadIO m ⇒ InterfaceHandle → Int → ChunkedReaderT m [ByteString]
-readData ifHnd numBytes = ChunkedReaderT $
+readData ∷ ∀ m. MonadIO m
+         ⇒ InterfaceHandle
+         → m Bool -- ^ Check stop action
+         → Int -- ^ Number of bytes to read
+         → ChunkedReaderT m [ByteString]
+readData ifHnd checkStop numBytes = ChunkedReaderT $
     do prevRest ← get
        let readNumBytes = numBytes - BS.length prevRest
        if readNumBytes > 0
@@ -462,12 +477,15 @@
         --   receivedBytes < packetSize
         if receivedDataBytes < readNumBytes
           then let xs = splitPackets bytes
-               in liftM (xs ⊕) (readLoop $ readNumBytes - receivedDataBytes)
+               in lift checkStop >>= \stop →
+                  if stop
+                  then put BS.empty >> return xs
+                  else liftM (xs ⊕)
+                             (readLoop $ readNumBytes - receivedDataBytes)
           else -- We might have received too much data, since we can only
                -- request multiples of 'packetSize' bytes. Split the byte
                -- string at such an index that the first part contains
-               -- readNumBytes of data bytes. The rest is kept for future
-               -- usage.
+               -- readNumBytes of data. The rest is kept for future usage.
                let (bs, newRest) = BS.splitAt (splitIndex readNumBytes) bytes
                in put newRest >> return (splitPackets bs)
 
@@ -489,7 +507,7 @@
 
 -- |Perform a bulk read.
 --
--- Returns the data that was read (in the form of a 'ByteString') and a flag
+-- Returns the bytes that where read (in the form of a 'ByteString') and a flag
 -- which indicates whether a timeout occured during the request.
 readBulk ∷ InterfaceHandle
          → Int -- ^Number of bytes to read
diff --git a/ftdi.cabal b/ftdi.cabal
--- a/ftdi.cabal
+++ b/ftdi.cabal
@@ -1,5 +1,5 @@
 name:          ftdi
-version:       0.1
+version:       0.2
 cabal-version: >=1.6
 build-type:    Custom
 stability:     experimental
@@ -39,11 +39,12 @@
   exposed-modules: System.FTDI
   other-modules: System.FTDI.Internal
                , System.FTDI.Utils
-  build-depends: base                 >= 4     && < 4.3
-               , base-unicode-symbols >= 0.1.1 && < 0.2
+  build-depends: base                 >= 3.0.3 && < 4.3
+               , base-unicode-symbols >= 0.1.1 && < 0.3
                , bytestring           >= 0.9.1 && < 0.10
+               , monads-fd            >= 0.1   && < 0.2
                , safe                 >= 0.2   && < 0.3
-               , transformers         >= 0.1.4 && < 0.2
+               , transformers         >= 0.2   && < 0.3
                , usb                  >= 0.3   && < 0.4
   ghc-options: -Wall
 
