packages feed

usb-safe 0.12 → 0.13

raw patch · 4 files changed

+471/−110 lines, 4 filesdep +usb-iterateedep −usb-enumeratordep ~basedep ~iterateedep ~regions

Dependencies added: usb-iteratee

Dependencies removed: usb-enumerator

Dependency ranges changed: base, iteratee, regions, usb

Files

+ NEWS view
@@ -0,0 +1,211 @@+0.12++(Released on: Wed Mar 9 12:22:15 UTC 2011)++* Exported the ReadEndpoint, WriteEndpoint and EnumReadEndpoint type classes+  This way you can refer to them in type signatures.++* Support usb-0.8:+  getStrDesc and getStrDescFirstLang now return a Text instead of a String.++* Switched from monad-peel to monad-control.++* Support regions-0.9.++* Support usb-enumerator-0.3.++* Support iteratee-0.8.*.+++0.11.0.2++(Released on: Mon Jan 17 22:04:53 UTC 2011)++* Support usb-0.7 and iteratee-0.7.+++0.11.0.1++(Released on: Sat Nov 13 21:28:28 UTC 2010)++* Support iteratee-0.6.++* Documentation fix.+++0.11++(Released on: Sat Nov 6 15:57:49 UTC 2010)++* Released during BelHac 2010!++* Depend on regions-0.8.++* Rename ParentOf to AncestorRegion.++* Use MonadPeelIO instead of MonadCatchIO.++* Support iteratee-0.5.++* Support GHC-7.+++0.10++(Released on: Sat Sep 11 14:20:03 UTC 2010)++* Support usb-0.6.++* Never throw a SettingAlreadySet exception from useActiveConfig or useActiveAlternate+  These functions don't change the current setting so they're always safe to use.++* Added strictness flags to all arguments of data constructors.+++0.9++(Released on: Wed Sep 1 20:12:10 UTC 2010)++* Support iteratee-0.4.* and regions-0.7.++* Added the overloaded constructor functions mkTransferDirection and mkTransferType++  class MkTransferDirection transDir where+      -- | An overloaded constructor function for transfer directions.+      mkTransferDirection ∷ TransferDirection transDir++  instance MkTransferDirection Out where mkTransferDirection = Out+  instance MkTransferDirection In  where mkTransferDirection = In++* Added getEndpoints' which uses these overloaded functions.++  getEndpoints' ∷ ∀ transDir transType sAlt r+                . MkTransferDirection transDir+                ⇒ MkTransferType transType+                ⇒ AlternateHandle sAlt r+                → [Endpoint transDir transType sAlt r]+  getEndpoints' altHndl = getEndpoints altHndl mkTransferDirection mkTransferType+++0.8++(Released on: Mon Jul 26 05:49:15 UTC 2010)++* Support usb-0.5 &+  Depend on the new usb-enumerator package++* Added function: readControlExact++* Remove custom NotFound exception+  and replaced it with the USB.NotFoundException+++0.7++(Released on: Wed Jun 16 09:12:24 UTC 2010)++* Export type 'ControlAction'++* Add 'enumReadEndpoint'++* Support usb-0.4++* Use regions >= 0.6+++0.6++(Released on: Sun May 2 20:26:33 UTC 2010)++* Added function withDeviceWhich++* Updated dependencies+  base-unicode-symbols      >= 0.1.1 && < 0.3+  regions                   >= 0.5   && < 0.6+  transformers              >= 0.2   && < 0.3+  MonadCatchIO-transformers >= 0.2   && < 0.3++* Uncapitalized the transfer direction and transfer type types+++0.5.1.1++(Released on: Thu Feb 4 10:21:29 UTC 2010)++* Depend on regions-0.4.*++* Depend on more compatible versions of MonadCatchIO-transformers+++0.5.1++(Released on: Sat Jan 23 14:25:41 UTC 2010)++* Depend on new regions == 0.3.*++* Bumped version to 0.5.1 because the API of regions got changed and+  this package re-exports a module from that package+++0.5++(Released on: Thu Jan 7 14:17:19 UTC 2010)++* Make use of the new regions-0.2+++0.4.1++(Released on: Wed Dec 23 13:47:36 UTC 2009)++* Tested with base-4.2++* Depend on base-unicode-symbols instead of unicode-symbols++* Exported function withInterfaceWhich+++0.4++(Released on: Mon Dec 21 09:57:10 UTC 2009)++* Generalized regions and moved them to their own package: regions++* Added derived Functor, Applicative, Alternative, MonadPlus and+  MonadFix instances for DeviceRegionT++* Added function setConfigWhich and setAlternateWhich++* Filtering endpoints now works with given transfer direction and+  transfer type as GADTs+++0.3++(Released on: Wed Dec 9 22:53:04 UTC 2009)++* Renamed EndpointHandle to FilteredEndpoint+++0.2++(Released on: Wed Dec 9 14:43:25 UTC 2009)++* Added TopDeviceRegion++* Added 'type TopDeviceRegion s = DeviceRegionT s IO'++* Added function 'runTopDeviceRegion'++* Renamed 'forkDeviceRegionT' to 'forkTopDeviceRegion'++* Changed the type of it to:+  'forkTopDeviceRegion :: MonadIO m =>+     TopDeviceRegion s () -> DeviceRegionT s m ThreadId'+++0.1++(Released on: Tue Dec 8 21:07:09 UTC 2009)++* Initial release
+ README.markdown view
@@ -0,0 +1,55 @@+The [usb] package provides a standard Haskell abstraction layer over+[bindings-libusb] providing: abstract types instead of `Ptr`s, automatic+marshalling and unmarshalling, automatic garbage collection, exceptions instead+of integer return codes, etc..++While all that is very nice there are still some things that you can do+wrong. For example doing I/O with a closed device or reading from or writing to+an endpoint which doesn't belong to the claimed interface. Or reading from an+Out endpoint or writing to an In endpoint.++`usb-safe` provides the following guarantees:++* You can't reference handles to devices that are closed. In other words: no I/O+   with closed handles is possible.++* The programmer specifies the *region* in which devices should remain open. On+  exit from the region the opened devices will be closed automatically.++* You can't reference handles to configurations that have not been set.++* You can't reference handles to interfaces that have not been claimed.++* Just like with devices, the programmer can specify the region in which+  interfaces should remain claimed. On exit from the region the claimed+  interfaces will be released automatically.++* You can't reference handles to alternates that have not been set.++* You can't reference endpoints that don't belong to a setted alternate.++* You can't read from an endpoint with an Out transfer direction.++* You can't write to an endpoint with an In transfer direction.++* You can't read from or write to endpoints with the unsupported transfer types+  Control and Isochronous. Only I/O with endpoints with the Bulk and Interrupt+  transfer types is allowed.++The primary technique used in `usb-safe` is called "Lightweight monadic regions"+which was [invented][1] by Oleg Kiselyov and Chung-chieh Shan.++This technique is implemented in the [regions] package which is re-exported from+`usb-safe`.++See the [usb-safe-examples] package for examples how to use this library:++    git clone git://github.com/basvandijk/usb-safe-examples.git++[1]: http://okmij.org/ftp/Haskell/regions.html#light-weight++[bindings-libusb]: http://hackage.haskell.org/package/bindings-libusb+[usb]:             http://hackage.haskell.org/package/usb+[regions]:         http://hackage.haskell.org/package/regions++[usb-safe-examples]: https://github.com/basvandijk/usb-safe-examples
System/USB/Safe.hs view
@@ -7,6 +7,7 @@            , FunctionalDependencies            , TypeSynonymInstances            , FlexibleContexts+           , FlexibleInstances            , UndecidableInstances            , GADTs            , EmptyDataDecls@@ -45,10 +46,6 @@ -- -- * You can't write to an endpoint with an 'In' transfer direction. ----- * You can't read from or write to endpoints with the unsupported transfer---   types 'Control' and 'Isochronous'. Only I/O with endpoints with the---   supported 'Bulk' and 'Interrupt' transfer types is allowed.--- -- This modules makes use of a technique called /Lightweight monadic regions/ -- invented by Oleg Kiselyov and Chung-chieh Shan --@@ -59,7 +56,7 @@ -- -- See the @usb-safe-examples@ package for examples how to use this library: ----- @darcs get@ <http://code.haskell.org/~basvandijk/code/usb-safe-examples>+-- @git clone <https://github.com/basvandijk/usb-safe-examples>@ -- -------------------------------------------------------------------------------- @@ -146,17 +143,27 @@     , ReadAction     , WriteAction +      -- ** Bulk and interrupt transfers     , ReadEndpoint(readEndpoint)     , WriteEndpoint(writeEndpoint)      , EnumReadEndpoint(enumReadEndpoint) +#ifdef HAS_EVENT_MANAGER+      -- ** Isochronous transfers+      -- | /WARNING:/ You need to enable the threaded runtime (@-threaded@) when using+      -- the isochronous functions. They throw a runtime error otherwise!+    , readIsochronousEndpoint+    , writeIsochronousEndpoint++    , enumReadIsochronousEndpoint+#endif       -- ** Control transfers     , ControlAction     , RequestType(..)     , control-    , readControl, readControlExact-    , writeControl+    , readControl,  readControlExact+    , writeControl, writeControlExact        -- * String descriptors     , getLanguages@@ -209,22 +216,18 @@ import Control.Monad.IO.Class     ( MonadIO, liftIO )  -- from monad-control:-import Control.Monad.IO.Control   ( MonadControlIO, liftIOOp_ )+import Control.Monad.IO.Control   ( MonadControlIO ) import Control.Exception.Control  ( throwIO )  -- from regions: import Control.Monad.Trans.Region.OnExit ( FinalizerHandle, onExit )+import Control.Monad.Trans.Region.Unsafe ( unsafeControlIO, unsafeLiftIOOp_ ) import Control.Monad.Trans.Region     -- (re-exported entirely)  -- from iteratee:-#if MIN_VERSION_iteratee(0,4,0) import Data.Iteratee.Iteratee           ( Enumerator ) import Data.Iteratee.Base.ReadableChunk ( ReadableChunk ) import Data.NullPoint                   ( NullPoint )-#else-import Data.Iteratee.Base               ( EnumeratorGM )-import Data.Iteratee.Base.StreamChunk   ( ReadableChunk )-#endif  -- from usb: import qualified System.USB.Initialization as USB@@ -256,13 +259,16 @@     , getLanguages, LangId, StrIx, getStrDesc, getStrDescFirstLang     ) -import qualified System.USB.IO.Synchronous as USB-    ( Timeout, TimedOut, Size+import qualified System.USB.IO as USB+    ( Timeout, Status, Size     , RequestType(Class, Vendor)     , Recipient, Request, Value, Index-    , control, readControl, readControlExact, writeControl+    , control, readControl, readControlExact, writeControl, writeControlExact     , readBulk,  readInterrupt     , writeBulk, writeInterrupt+#ifdef HAS_EVENT_MANAGER+    , readIsochronous, writeIsochronous+#endif     )  import qualified System.USB.IO.StandardDeviceRequests as USB@@ -275,15 +281,20 @@ import System.USB.Descriptors ( maxPacketSize, endpointMaxPacketSize ) #endif --- from usb-enumerator:-import qualified System.USB.IO.Synchronous.Enumerator as USB-    ( enumReadBulk, enumReadInterrupt )+-- from usb-iteratee:+import qualified System.USB.IO.Iteratee as USB+    ( enumReadBulk+    , enumReadInterrupt+#ifdef HAS_EVENT_MANAGER+    , enumReadIsochronous+#endif+    )  #if MIN_VERSION_base(4,3,0)-import Control.Exception.Control  ( mask_ )+import Control.Exception ( mask_ ) #else-import Control.Exception.Control  ( block )-mask_ ∷ MonadControlIO m ⇒ m α → m α+import Control.Exception ( block )+mask_ ∷ IO α → IO α mask_ = block #endif @@ -323,7 +334,7 @@ -} openDevice ∷ MonadControlIO pr            ⇒ USB.Device → RegionT s pr (RegionalDeviceHandle (RegionT s pr))-openDevice dev = mask_ $ do+openDevice dev = unsafeLiftIOOp_ mask_ $ do                    h  ← liftIO $ USB.openDevice dev                    mv ← liftIO $ newMVar False                    ch ← onExit $ USB.closeDevice h@@ -548,35 +559,33 @@   * Another 'USB.USBException'. -}-setConfig ∷ ∀ pr cr α-          . (pr `AncestorRegion` cr, MonadControlIO cr)-          ⇒ Config pr                          -- ^ The configuration you wish to set.-          → (∀ sCfg. ConfigHandle sCfg → cr α) -- ^ Continuation function.-          → cr α+setConfig ∷ ∀ pr cr s α+          . (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)+          ⇒ Config pr -- ^ The configuration you wish to set.+          → (∀ sCfg. ConfigHandle sCfg → RegionT s cr α) -- ^ Continuation function.+          → RegionT s cr α setConfig (Config (RegionalDeviceHandle internalDevHndl mv _) configDesc) f =-    withUnsettedMVar mv $ do-      liftIO $ USB.setConfig internalDevHndl $ Just $ USB.configValue configDesc-      f $ ConfigHandle internalDevHndl configDesc+    unsafeControlIO $ \runInIO → withUnsettedMVar mv $ do+      USB.setConfig internalDevHndl $ Just $ USB.configValue configDesc+      runInIO $ f $ ConfigHandle internalDevHndl configDesc  -- | Internally used function which throws a 'SettingAlreadySet' exception if -- the given @MVar@ was set. If the given @MVar@ wasn't set it will be set -- before the given computation is performed. When the computation terminates, -- wheter normally or by raising an exception, the @MVar@ will be unset again.-withUnsettedMVar ∷ MonadControlIO m ⇒ MVar Bool → m α → m α-withUnsettedMVar mv = liftIOOp_ $ bracket_-                        (do alreadySet ← takeMVar mv-                            if alreadySet-                              then do putMVar mv alreadySet-                                      throwIO SettingAlreadySet-                              else putMVar mv True)-                        (overwriteMVar mv False)+withUnsettedMVar ∷ MVar Bool → IO α → IO α+withUnsettedMVar mv = bracket_ (do alreadySet ← takeMVar mv+                                   if alreadySet+                                     then do putMVar mv alreadySet+                                             throwIO SettingAlreadySet+                                     else putMVar mv True)+                               (overwriteMVar mv False)  -- | Internally used function which sets the @MVar@ before the computation is -- performed. When the computation terminates, wheter normally or by raising an -- exception, the @MVar@ will be unset again.-withSettedMVar ∷ MonadControlIO m ⇒ MVar Bool → m α → m α-withSettedMVar mv = liftIOOp_ $ bracket_ (overwriteMVar mv True)-                                         (overwriteMVar mv False)+withSettedMVar ∷ MVar Bool → IO α → IO α+withSettedMVar mv = bracket_ (overwriteMVar mv True) (overwriteMVar mv False)  -- | Internally used function which overwrites the value in the @MVar@. --@@ -616,23 +625,23 @@   * Another 'USB.USBException'. -}-useActiveConfig ∷ ∀ pr cr α-                . (pr `AncestorRegion` cr, MonadControlIO cr)+useActiveConfig ∷ ∀ pr cr s α+                . (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)                 ⇒ RegionalDeviceHandle pr -- ^ Regional handle to the device                                           --   from which you want to use the                                           --   active configuration.-                → (∀ sCfg. ConfigHandle sCfg → cr α) -- ^ Continuation function-                → cr α+                → (∀ sCfg. ConfigHandle sCfg → RegionT s cr α) -- ^ Continuation function+                → RegionT s cr α useActiveConfig (RegionalDeviceHandle internalDevHndl mv _) f =-    withSettedMVar mv $ do-      mbActiveConfigValue ← liftIO $ USB.getConfig internalDevHndl+    unsafeControlIO $ \runInIO → withSettedMVar mv $ do+      mbActiveConfigValue ← USB.getConfig internalDevHndl       case mbActiveConfigValue of         Nothing → throwIO NoActiveConfig         Just activeConfigValue →           let activeConfigHandle = ConfigHandle internalDevHndl activeConfigDesc               activeConfigDesc = fromJust $ find isActive $ getConfigDescs internalDevHndl               isActive = (activeConfigValue ≡) ∘ USB.configValue-          in f activeConfigHandle+          in runInIO $ f activeConfigHandle  {-| This exception can be thrown in 'useActiveConfig' to indicate that the device is currently not configured.@@ -662,15 +671,15 @@   * Another 'USB.USBException'. -}-setConfigWhich ∷ ∀ pr cr α-               . (pr `AncestorRegion` cr, MonadControlIO cr)+setConfigWhich ∷ ∀ pr cr s α+               . (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)                ⇒ RegionalDeviceHandle pr -- ^ Regional handle to the device for                                          --   which you want to set a                                          --   configuration.                → (USB.ConfigDesc → Bool) -- ^ Predicate on the configuration                                          --   descriptor.-               → (∀ sCfg. ConfigHandle sCfg → cr α) -- ^ Continuation function.-               → cr α+               → (∀ sCfg. ConfigHandle sCfg → RegionT s cr α) -- ^ Continuation function.+               → RegionT s cr α setConfigWhich h = useWhich (getConfigs h) setConfig  @@ -754,7 +763,7 @@       → RegionT s pr           (RegionalInterfaceHandle sCfg             (RegionT s pr))-claim interface@(Interface internalDevHndl ifNum _) = mask_ $ do+claim interface@(Interface internalDevHndl ifNum _) = unsafeLiftIOOp_ mask_ $ do   mv ← liftIO $ newMVar False   liftIO $ USB.claimInterface internalDevHndl ifNum   ch ← onExit $ USB.releaseInterface internalDevHndl ifNum@@ -865,19 +874,19 @@   * Another 'USB.USBException'. -}-setAlternate ∷ ∀ pr cr sCfg α-             . (pr `AncestorRegion` cr, MonadControlIO cr)+setAlternate ∷ ∀ pr cr s sCfg α+             . (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)              ⇒ Alternate sCfg pr -- ^ The alternate you wish to set.-             → (∀ sAlt. AlternateHandle sAlt pr → cr α) -- ^ Continuation function.-             → cr α+             → (∀ sAlt. AlternateHandle sAlt pr → RegionT s cr α) -- ^ Continuation function.+             → RegionT s cr α setAlternate (Alternate               (RegionalInterfaceHandle (Interface internalDevHndl ifNum _) mv _)               ifDesc) f =-  withUnsettedMVar mv $ do-    liftIO $ USB.setInterfaceAltSetting internalDevHndl+  unsafeControlIO $ \runInIO → withUnsettedMVar mv $ do+    USB.setInterfaceAltSetting internalDevHndl                                         ifNum                                         (USB.interfaceAltSetting ifDesc)-    f $ AlternateHandle internalDevHndl ifDesc+    runInIO $ f $ AlternateHandle internalDevHndl ifDesc   {-| Apply the given function to the alternate handle of the current active@@ -896,25 +905,25 @@   * Another 'USB.USBException'. -}-useActiveAlternate ∷ ∀ pr cr sCfg α-                   . (pr `AncestorRegion` cr, MonadControlIO cr)+useActiveAlternate ∷ ∀ pr cr s sCfg α+                   . (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)                    ⇒ RegionalInterfaceHandle sCfg pr -- ^ Regional handle to the                                               --   interface from which you want                                               --   to use the active alternate.-                   → (∀ sAlt. AlternateHandle sAlt pr → cr α) -- ^ Continuation function.-                   → cr α+                   → (∀ sAlt. AlternateHandle sAlt pr → RegionT s cr α) -- ^ Continuation function.+                   → RegionT s cr α useActiveAlternate (RegionalInterfaceHandle (Interface internalDevHndl ifNum alts)                                             mv _                    ) f =-    withSettedMVar mv $ do+    unsafeControlIO $ \runInIO → withSettedMVar mv $ do       let timeout = 5000 -- ms-      activeAltValue ← liftIO $ USB.getInterfaceAltSetting internalDevHndl-                                                           ifNum-                                                           timeout+      activeAltValue ← USB.getInterfaceAltSetting internalDevHndl+                                                  ifNum+                                                  timeout       let activeAltHandle = AlternateHandle internalDevHndl activeAlt           activeAlt = fromJust $ find isActive alts           isActive = (activeAltValue ≡) ∘ USB.interfaceAltSetting-      f activeAltHandle+      runInIO $ f activeAltHandle   {-| Convenience function which finds the first alternate of the given interface@@ -935,15 +944,15 @@   * Another 'USB.USBException'. -}-setAlternateWhich ∷ ∀ pr cr sCfg α-                  . (pr `AncestorRegion` cr, MonadControlIO cr)+setAlternateWhich ∷ ∀ pr cr sCfg s α+                  . (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)                   ⇒ RegionalInterfaceHandle sCfg pr -- ^ Regional handle to the                                                     --   interface for which you want                                                     --   to set an alternate.                   → (USB.InterfaceDesc → Bool)      -- ^ Predicate on the interface                                                     --   descriptor.-                  → (∀ sAlt. AlternateHandle sAlt pr → cr α) -- ^ Continuation function-                  → cr α+                  → (∀ sAlt. AlternateHandle sAlt pr → RegionT s cr α) -- ^ Continuation function+                  → RegionT s cr α setAlternateWhich h = useWhich (getAlternates h) setAlternate  @@ -1097,7 +1106,7 @@ performs the actual read and returns the bytestring that was read paired with an indication if the transfer timed out. -}-type ReadAction r = USB.Size → USB.Timeout → r (ByteString, USB.TimedOut)+type ReadAction r = USB.Size → USB.Timeout → r (ByteString, USB.Status)  -- | Class of transfer types that support reading. class ReadEndpoint transType where@@ -1142,7 +1151,7 @@ of bytes that were actually written paired with an indication if the transfer timed out. -}-type WriteAction r = ByteString → USB.Timeout → r (USB.Size, USB.TimedOut)+type WriteAction r = ByteString → USB.Timeout → r (USB.Size, USB.Status)  -- | Class of transfer types that support writing class WriteEndpoint transType where@@ -1167,14 +1176,12 @@  -------------------------------------------------------------------------------- --- | Class of transfer types that support enumerating.+-- | Class of transfer types that support enumeration. class EnumReadEndpoint transType where     -- | An enumerator for an 'In' endpoint     -- with either a 'Bulk' or 'Interrupt' transfer type.-    enumReadEndpoint ∷ ( pr `AncestorRegion` cr, MonadControlIO cr, ReadableChunk s Word8-#if MIN_VERSION_iteratee(0,4,0)-                       , NullPoint s-#endif+    enumReadEndpoint ∷ ( pr `AncestorRegion` cr, MonadControlIO cr+                       , ReadableChunk s Word8, NullPoint s                        )                      ⇒ Endpoint In transType sAlt pr                      → USB.Size    -- ^ Chunk size. A good value for this would be@@ -1183,15 +1190,84 @@                                    --   should wait for each chunk before giving up                                    --   due to no response being received.  For no                                    --   timeout, use value 0.-#if MIN_VERSION_iteratee(0,4,0)                      → Enumerator s cr α-#else-                     → EnumeratorGM s Word8 cr α-#endif+ instance EnumReadEndpoint Bulk      where enumReadEndpoint = wrap USB.enumReadBulk instance EnumReadEndpoint Interrupt where enumReadEndpoint = wrap USB.enumReadInterrupt +#ifdef HAS_EVENT_MANAGER+-------------------------------------------------------------------------------- +{-| Perform a USB /isochronous/ read.++/WARNING:/ You need to enable the threaded runtime (@-threaded@) for this+function to work correctly. It throws a runtime error otherwise!++Exceptions:++ * 'USB.PipeException' if the endpoint halted.++ * 'USB.OverflowException' if the device offered more data,+   see /Packets and overflows/ in the @libusb@ documentation:+   <http://libusb.sourceforge.net/api-1.0/packetoverflow.html>.++ * 'USB.NoDeviceException' if the device has been disconnected.++ * Another 'USB.USBException'.+-}+readIsochronousEndpoint ∷ (pr `AncestorRegion` cr, MonadIO cr)+                        ⇒ Endpoint In Isochronous sAlt pr+                        → [USB.Size] -- ^ Sizes of isochronous packets+                        → USB.Timeout+                        → cr [ByteString]+readIsochronousEndpoint (Endpoint internalDevHndl endpointDesc) sizes timeout =+    liftIO $ USB.readIsochronous internalDevHndl+                                 (USB.endpointAddress endpointDesc)+                                 sizes+                                 timeout++{-| Perform a USB /isochronous/ write.++/WARNING:/ You need to enable the threaded runtime (@-threaded@) for this+function to work correctly. It throws a runtime error otherwise!++Exceptions:++ * 'USB.PipeException' if the endpoint halted.++ * 'USB.OverflowException' if the device offered more data,+   see /Packets and overflows/ in the @libusb@ documentation:+   <http://libusb.sourceforge.net/api-1.0/packetoverflow.html>.++ * 'USB.NoDeviceException' if the device has been disconnected.++ * Another 'USB.USBException'.+-}+writeIsochronousEndpoint ∷ (pr `AncestorRegion` cr, MonadIO cr)+                         ⇒ Endpoint Out Isochronous sAlt pr+                         → [ByteString] -- ^ Sizes of isochronous packets+                         → USB.Timeout+                         → cr [USB.Size]+writeIsochronousEndpoint (Endpoint internalDevHndl endpointDesc) isoPackets timeout =+    liftIO $ USB.writeIsochronous internalDevHndl+                                  (USB.endpointAddress endpointDesc)+                                  isoPackets+                                  timeout++-- | Iteratee enumerator for reading /isochronous/ endpoints.+--+-- /WARNING:/ You need to enable the threaded runtime (@-threaded@) for this+-- function to work correctly. It throws a runtime error otherwise!+enumReadIsochronousEndpoint ∷ ∀ s pr cr sAlt α+                            . ( ReadableChunk s Word8+                              , pr `AncestorRegion` cr, MonadControlIO cr+                              )+                            ⇒ Endpoint In Isochronous sAlt pr+                            → [USB.Size]+                            → USB.Timeout+                            → Enumerator [s] cr α+enumReadIsochronousEndpoint = wrap USB.enumReadIsochronous+#endif -------------------------------------------------------------------------------- -- ** Control transfers --------------------------------------------------------------------------------@@ -1204,6 +1280,9 @@                      → USB.Index                      → α +type ReadExactAction  cr = USB.Size   → USB.Timeout → cr ByteString+type WriteExactAction cr = ByteString → USB.Timeout → cr ()+ {-| Control transfers can have three request types: @Standard@, @Class@ and @Vendor@. We disallow @Standard@ requests however because with them you can destroy the safety guarantees that this module provides.@@ -1263,17 +1342,16 @@ -- specified number of bytes to read were actually read. -- Throws an 'USB.IOException' if this is not the case. readControlExact ∷ ∀ pr cr. (pr `AncestorRegion` cr, MonadIO cr)-                 ⇒ RegionalDeviceHandle pr → ControlAction-                     (USB.Size → USB.Timeout → cr ByteString)-readControlExact regionalDevHndl = \reqType reqRecipient request value index → \timeout size →+                 ⇒ RegionalDeviceHandle pr → ControlAction (ReadExactAction cr)+readControlExact regionalDevHndl = \reqType reqRecipient request value index → \size timeout →     liftIO $ USB.readControlExact (getInternalDevHndl regionalDevHndl)                                   (reqTypeToInternal reqType)                                   reqRecipient                                   request                                   value                                   index-                                  timeout                                   size+                                  timeout  {-| Perform a USB /control/ write. @@ -1287,16 +1365,30 @@ -} writeControl ∷ ∀ pr cr. (pr `AncestorRegion` cr, MonadIO cr)              ⇒ RegionalDeviceHandle pr → ControlAction (WriteAction cr)-writeControl regionalDevHndl = \reqType reqRecipient request value index → \timeout input →+writeControl regionalDevHndl = \reqType reqRecipient request value index → \input timeout →     liftIO $ USB.writeControl (getInternalDevHndl regionalDevHndl)                               (reqTypeToInternal reqType)                               reqRecipient                               request                               value                               index-                              timeout                               input+                              timeout +-- | A convenience function similar to 'writeControl' which checks if the given+-- bytes were actually fully written.+-- Throws an 'incompleteWriteException' if this is not the case.+writeControlExact ∷ ∀ pr cr. (pr `AncestorRegion` cr, MonadIO cr)+                 ⇒ RegionalDeviceHandle pr → ControlAction (WriteExactAction cr)+writeControlExact regionalDevHndl = \reqType reqRecipient request value index → \input timeout →+    liftIO $ USB.writeControlExact (getInternalDevHndl regionalDevHndl)+                                   (reqTypeToInternal reqType)+                                   reqRecipient+                                   request+                                   value+                                   index+                                   input+                                   timeout  -------------------------------------------------------------------------------- -- *** Standard Device Requests@@ -1451,15 +1543,15 @@   * Another 'USB.USBException'. -}-withDetachedKernelDriver ∷ (pr `AncestorRegion` cr, MonadControlIO cr)+withDetachedKernelDriver ∷ (pr `AncestorRegion` RegionT s cr, MonadControlIO cr)                          ⇒ RegionalDeviceHandle pr                          → USB.InterfaceNumber-                         → cr α-                         → cr α+                         → RegionT s cr α+                         → RegionT s cr α withDetachedKernelDriver regionalDevHndl ifNum =-    liftIOOp_ $ USB.withDetachedKernelDriver-                  (getInternalDevHndl regionalDevHndl)-                  ifNum+    unsafeLiftIOOp_ $ USB.withDetachedKernelDriver+                        (getInternalDevHndl regionalDevHndl)+                        ifNum   -- The End ---------------------------------------------------------------------
usb-safe.cabal view
@@ -1,5 +1,5 @@ name:          usb-safe-version:       0.12+version:       0.13 cabal-version: >=1.6 build-type:    Custom license:       BSD3@@ -7,6 +7,8 @@ copyright:     2009–2010 Bas van Dijk author:        Bas van Dijk <v.dijk.bas@gmail.com> maintainer:    Bas van Dijk <v.dijk.bas@gmail.com>+homepage:      https://github.com/basvandijk/usb-safe/+bug-reports:   https://github.com/basvandijk/usb-safe/issues stability:     experimental category:      System, Monadic Regions synopsis:      Type-safe communication with USB devices.@@ -46,10 +48,6 @@   .   * You can't write to an endpoint with an In transfer direction.   .-  * You can't read from or write to endpoints with the unsupported transfer-    types Control and Isochronous. Only I/O with endpoints with the Bulk and-    Interrupt transfer types is allowed.-  .   The primary technique used in usb-safe is called \"Lightweight monadic   regions\" which was invented by Oleg Kiselyov and Chung-chieh Shan.   See:@@ -61,22 +59,27 @@   .   See the @usb-safe-examples@ package for examples how to use this library:   .-  @darcs get@ <http://code.haskell.org/~basvandijk/code/usb-safe-examples>+  @git clone <https://github.com/basvandijk/usb-safe-examples>@ +extra-source-files: README.markdown, NEWS+ source-repository head-  Type:     darcs-  Location: http://code.haskell.org/~basvandijk/code/usb-safe+  Type:     git+  Location: git://github.com/basvandijk/usb-safe.git  Library   GHC-Options: -Wall -fno-warn-orphans-  build-depends: base                      >= 4     && < 4.4+  build-depends: base                      >= 4     && < 4.5                , base-unicode-symbols      >= 0.1.1 && < 0.3-               , usb                       >= 0.8   && < 0.9-               , usb-enumerator            >= 0.3   && < 0.4-               , iteratee                  >= 0.3.5 && < 0.9+               , usb                       >= 1.0   && < 1.1+               , usb-iteratee              >= 0.4   && < 0.5+               , iteratee                  >= 0.4   && < 0.9                , bytestring                >= 0.9   && < 0.10                , text                      >= 0.5   && < 0.12-               , regions                   >= 0.9   && < 0.10+               , regions                   >= 0.9   && < 0.11                , transformers              >= 0.2   && < 0.3                , monad-control             >= 0.2   && < 0.3   exposed-modules: System.USB.Safe++  if impl(ghc>7) && !os(windows)+    cpp-options: -DHAS_EVENT_MANAGER