-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Type-safe communication with USB devices.
--
-- The usb library provides a standard Haskell abstraction layer over
-- bindings-libusb providing: abstract types instead of Ptrs, 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 by Oleg Kiselyov and Chung-chieh Shan.
-- See:
--
-- http://okmij.org/ftp/Haskell/regions.html#light-weight
--
-- 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:
--
-- darcs get
-- http://code.haskell.org/~basvandijk/code/usb-safe-examples
@package usb-safe
@version 0.4
-- | This modules provides the following guarantees for working with USB
-- devices:
--
--
-- - You can't reference handles to devices that are closed. In other
-- words: no I/O with closed handles is possible.
-- - The programmer can specify 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 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
--
-- See: http://okmij.org/ftp/Haskell/regions.html#light-weight
--
-- This technique is implemented in the regions package of which
-- the Control.Monad.Trans.Region module is re-exported by this
-- module.
--
-- See the usb-safe-examples package for examples how to use
-- this library:
--
-- darcs get
-- http://code.haskell.org/~basvandijk/code/usb-safe-examples
module System.USB.Safe
-- | Handy type synonym for a region in which USB devices can be opened
-- which are automatically closed when the region terminates.
--
-- You can run a device region with runRegionT.
type DeviceRegionT s pr ± = RegionT Device s pr ±
-- | Handy type synonym for a device region which has IO as its
-- parent region which enables it to be:
--
--
type TopDeviceRegion s ± = TopRegion Device s ±
-- | Handy type synonym for a regional handle to an opened USB device.
--
-- A regional handle to an opened USB device can be created by applying
-- open or with to the USB device you wish to open.
--
-- Note that you can also duplicate a regional device handle by
-- applying dup to it.
type RegionalDeviceHandle r = RegionalHandle Device r
-- | Convenience function for retrieving the device from the given regional
-- handle.
getDevice :: RegionalDeviceHandle r -> Device
class GetDescriptor ± desc | ± -> desc, desc -> ±
getDesc :: (GetDescriptor ± desc) => ± -> desc
-- | Perform a USB port reset to reinitialize a device. The system will
-- attempt to restore the previous configuration and alternate settings
-- after the reset has completed.
--
-- Note the constraint: pr `ParentOf` cr. This allows this
-- function to be executed in any child region cr of the parent
-- region pr in which the given regional handle was created.
--
-- You can only reset a device when all computations passed to
-- setConfig, useActiveConfig and setConfigWhich
-- have been terminated. If you call resetDevice and such a
-- computation is still running a SettingAlreadySet exception is
-- thrown.
--
-- If the reset fails, the descriptors change, or the previous state
-- cannot be restored, the device will appear to be disconnected and
-- reconnected. This means that the device handle is no longer valid (you
-- should close it) and rediscover the device. A NotFoundException is
-- raised to indicate that this is the case.
--
-- TODO: Think about how to handle the implications of the the
-- previous paragraph!
--
-- This is a blocking function which usually incurs a noticeable delay.
--
-- Exceptions:
--
--
resetDevice :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> cr ()
-- | A supported configuration of a USB device parameterized by the region
-- r in which it was created.
--
-- Note that, just like a regional device handle, a configuration can be
-- duplicated to a parent region using dup.
data Config r :: (* -> *)
-- | Retrieve the supported configurations from the given regional handle.
--
-- Note that the configuration is parameterized by the same region
-- r in which the regional handle was created. This ensures you
-- can never use a configuration outside that region.
getConfigs :: RegionalDeviceHandle r -> [Config r]
-- | A handle to an active Config which you can get using:
-- setConfig, useActiveConfig or setConfigWhich. The
-- type variable sCfg is used to ensure that you can't return
-- this handle from these functions.
data ConfigHandle sCfg
-- | Set the active configuration for a device and then apply the given
-- function to the resulting configuration handle.
--
-- USB devices support multiple configurations of which only one can be
-- active at any given time. When a configuration is set using
-- setConfig, useActiveConfig or setConfigWhich no
-- threads can set a new configuration until the computation passed to
-- these functions terminates. If you do try to set one a
-- SettingAlreadySet exception will be thrown.
--
-- The operating system may or may not have already set an active
-- configuration on the device. It is up to your application to ensure
-- the correct configuration is selected before you attempt to claim
-- interfaces and perform other operations. If you want to use the
-- current active configuration use useActiveConfig.
--
-- If you call this function on a device already configured with the
-- selected configuration, then this function will act as a lightweight
-- device reset: it will issue a SET_CONFIGURATION request using the
-- current configuration, causing most USB-related device state to be
-- reset (altsetting reset to zero, endpoint halts cleared, toggles
-- reset).
--
-- You cannot change/reset configuration if other applications or drivers
-- have claimed interfaces.
--
-- This is a blocking function.
--
-- Exceptions:
--
--
setConfig :: (ParentOf pr cr, MonadCatchIO cr) => Config pr -> (forall sCfg. ConfigHandle sCfg -> cr ±) -> cr ±
-- | This exception can be thrown in:
--
--
--
-- to indicate that the device was already configured with a setting.
data SettingAlreadySet
-- | Apply the given function to the configuration handle of the current
-- active configuration of the given device handle.
--
-- This function needs to determine the current active configuration.
-- This information may be cached by the operating system. If it isn't
-- cached this function will block while a control transfer is submitted
-- to retrieve the information.
--
-- Exceptions:
--
--
useActiveConfig :: (ParentOf pr cr, MonadCatchIO cr) => RegionalDeviceHandle pr -> (forall sCfg. ConfigHandle sCfg -> cr ±) -> cr ±
-- | This exception can be thrown in useActiveConfig to indicate
-- that the device is currently not configured.
data NoActiveConfig
-- | Convenience function which finds the first configuration of the given
-- device handle which satisfies the given predicate on its descriptor,
-- then sets that configuration and applies the given function to the
-- resulting configuration handle.
--
-- This function calls setConfig so do see its documentation.
--
-- Exceptions:
--
--
-- - NotFound if no configuration is found that satisfies the
-- given predicate.
-- - BusyException if interfaces are currently claimed.
-- - NoDeviceException if the device has been disconnected
-- - SettingAlreadySet if a configuration has already been set
-- using setConfig, useActiveConfig or
-- setConfigWhich.
-- - Another USBException.
--
setConfigWhich :: (ParentOf pr cr, MonadCatchIO cr) => RegionalDeviceHandle pr -> (ConfigDesc -> Bool) -> (forall sCfg. ConfigHandle sCfg -> cr ±) -> cr ±
-- | This exception will be thrown in setConfigWhich or
-- setAlternateWhich to indicate that no setting was found which
-- satisfies the given predicate.
data NotFound
-- | A supported interface of a configuration which you can retrieve using
-- getInterfaces.
--
-- To retrieve the Interface descriptors of an interface use
-- getDesc.
data Interface sCfg
-- | Retrieve the supported interfaces from the configuration handle.
--
-- Note that the interface is parameterized by the sCfg of the
-- configuration handle it is derived from. This ensures that it can
-- never be returned from the functions that created this configuration
-- handle: setConfig, useActiveConfig and
-- setConfigWhich.
--
-- The latter is useful because outside those functions the active
-- configuration may change. If at that moment you still have an
-- interface of the old configuration claiming it would be an error.
getInterfaces :: ConfigHandle sCfg -> [Interface sCfg]
-- | Handy type synonym for a region in which interfaces can be claimed
-- which are automatically released when the region terminates.
--
-- You can run an interface region with runRegionT.
type IfRegionT sCfg s pr ± = RegionT (Interface sCfg) s pr ±
-- | Handy type synonym for a regional handle to a claimed interface.
--
-- A regional handle to a claimed interface can be created by applying
-- claim or with to the interface you wish to claim.
type RegionalIfHandle sCfg r = RegionalHandle (Interface sCfg) r
-- | Claim the given interface in the interface region.
--
-- Note that: claim = open which just reads better when
-- applied to an interface.
--
-- Note that it is allowed to claim an already-claimed interface.
--
-- Claiming of interfaces is a purely logical operation; it does not
-- cause any requests to be sent over the bus. Interface claiming is used
-- to instruct the underlying operating system that your application
-- wishes to take ownership of the interface.
--
-- This is a non-blocking function.
--
-- Exceptions:
--
--
-- - BusyException if the interface is already claimed.
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
claim :: (MonadCatchIO pr) => Interface sCfg -> IfRegionT sCfg s pr (RegionalIfHandle sCfg (RegionT (Interface sCfg) s pr))
-- | A supported Interface alternate setting.
data Alternate sCfg r :: (* -> *)
-- | Retrieve the supported alternate settings from the interface handle.
--
-- Note that the alternate setting is parameterized by the same type
-- variables as the interface handle. This ensures you can never use an
-- alternate setting outside the region in which the interface handle was
-- created.
getAlternates :: RegionalIfHandle sCfg r -> [Alternate sCfg r]
-- | A handle to a setted alternate setting.
--
-- You get a handle to an alternate using setAlternate,
-- useActiveAlternate or setAlternateWhich. The type
-- variable sAlt is used to ensure that you can't return this
-- handle from these functions.
data AlternateHandle sCfg sAlt r :: (* -> *)
-- | Activate an alternate setting for an interface and then apply the
-- given function to the resulting alternate handle.
--
-- Simillary to configurations, interfaces support multiple alternate
-- settings of which only one can be active at any given time. When an
-- alternate is set using setAlternate, useActiveAlternate
-- or setAlternateWhich no threads can set a new alternate until
-- the computation passed to these functions terminates. If you do try to
-- set one a SettingAlreadySet exception will be thrown.
--
-- The operating system may already have set an alternate for the
-- interface. If you want to use this current active alternate use
-- useActiveAlternate.
--
-- This is a blocking function.
--
-- Exceptions:
--
--
setAlternate :: (ParentOf pr cr, MonadCatchIO cr) => Alternate sCfg pr -> (forall sAlt. AlternateHandle sCfg sAlt pr -> cr ±) -> cr ±
-- | Apply the given function to the alternate handle of the current active
-- alternate of the give interface handle.
--
-- To determine the current active alternate this function will block
-- while a control transfer is submitted to retrieve the information.
--
-- Exceptions:
--
--
useActiveAlternate :: (ParentOf pr cr, MonadCatchIO cr) => RegionalIfHandle sCfg pr -> (forall sAlt. AlternateHandle sCfg sAlt pr -> cr ±) -> cr ±
-- | Convenience function which finds the first alternate of the given
-- interface handle which satisfies the given predicate on its
-- descriptor, then sets that alternate and applies the given function to
-- the resulting alternate handle.
--
-- This function calls setAlternate so do see its documentation.
--
-- Exceptions:
--
--
setAlternateWhich :: (ParentOf pr cr, MonadCatchIO cr) => RegionalIfHandle sCfg pr -> (InterfaceDesc -> Bool) -> (forall sAlt. AlternateHandle sCfg sAlt pr -> cr ±) -> cr ±
-- | I/O operations on endpoints are type-safe. You can only read from an
-- endpoint with an IN transfer direction and you can only write
-- to an endpoint with an OUT transfer direction.
--
-- Reading and writing also have different implementations for the
-- different endpoint transfer types like: BULK and
-- INTERRUPT. I/O with endpoints of other transfer types like
-- CONTROL and ISOCHRONOUS is not possible.
--
-- This type lifts the transfer direction and transfer type information
-- to the type-level so that I/O operations like readEndpoint and
-- writeEndpoint can specify which endpoints they support.
--
-- You can retrieve the endpoints of an alternate by using
-- getEndpoints.
data Endpoint transDir transType sAlt r :: (* -> *)
-- | Retrieve all the endpoints from the given alternate handle which are
-- of the given transfer direction and transfer type.
getEndpoints :: AlternateHandle sCfg sAlt r -> TransferDirection transDir -> TransferType transType -> [Endpoint transDir transType sAlt r]
-- | Clear the halt/stall condition for an endpoint.
--
-- Endpoints with halt status are unable to receive or transmit data
-- until the halt condition is stalled.
--
-- You should cancel all pending transfers before attempting to clear the
-- halt condition.
--
-- This is a blocking function.
--
-- Exceptions:
--
--
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
clearHalt :: (ParentOf pr cr, MonadIO cr) => Endpoint transDir transType sAlt pr -> cr ()
data TransferDirection transDir
Out :: TransferDirection OUT
In :: TransferDirection IN
-- | Out transfer direction (host -> device) used for writing.
data OUT
-- | In transfer direction (device -> host) used for reading.
data IN
data TransferType transType
Control :: TransferType CONTROL
Isochronous :: TransferType ISOCHRONOUS
Bulk :: TransferType BULK
Interrupt :: TransferType INTERRUPT
data CONTROL
data ISOCHRONOUS
data BULK
data INTERRUPT
-- | Handy type synonym for read transfers.
--
-- A ReadAction is a function which takes a timeout and a size
-- which defines how many bytes to read. The function returns an action
-- which, when executed, performs the actual read and returns the
-- bytestring that was read paired with an indication if the transfer
-- timed out.
type ReadAction r = Timeout -> Size -> r (ByteString, Bool)
-- | Handy type synonym for write transfers.
--
-- A WriteAction is a function which takes a timeout and the
-- bytestring to write. The function returns an action which, when
-- exectued, returns the number of bytes that were actually written
-- paired with an indication if the transfer timed out.
type WriteAction r = Timeout -> ByteString -> r (Size, Bool)
-- | Read bytes from an IN endpoint with either a BULK or
-- INTERRUPT transfer type.
readEndpoint :: (ReadEndpoint transType, ParentOf pr cr, MonadIO cr) => Endpoint IN transType sAlt pr -> ReadAction cr
-- | Write bytes to an OUT endpoint with either a BULK or
-- INTERRUPT transfer type.
writeEndpoint :: (WriteEndpoint transType, ParentOf pr cr, MonadIO cr) => Endpoint OUT transType sAlt pr -> WriteAction 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.
data RequestType
Class :: RequestType
Vendor :: RequestType
-- | Perform a USB control request that does not transfer data.
--
-- The value and index values should be given in
-- host-endian byte order.
--
-- Exceptions:
--
--
-- - TimeoutException if the transfer timed out.
-- - PipeException if the control request was not supported by the
-- device
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
control :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> RequestType -> Recipient -> Word8 -> Word16 -> Word16 -> Timeout -> cr ()
-- | Perform a USB control read.
--
-- The value and index values should be given in
-- host-endian byte order.
--
-- Exceptions:
--
--
-- - PipeException if the control request was not supported by the
-- device
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
readControl :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> RequestType -> Recipient -> Word8 -> Word16 -> Word16 -> ReadAction cr
-- | Perform a USB control write.
--
-- The value and index values should be given in
-- host-endian byte order.
--
-- Exceptions:
--
--
-- - PipeException if the control request was not supported by the
-- device
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
writeControl :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> RequestType -> Recipient -> Word8 -> Word16 -> Word16 -> WriteAction cr
-- | Retrieve a list of supported languages.
--
-- This function may throw USBExceptions.
getLanguages :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> cr [LangId]
-- | Retrieve a string descriptor from a device.
--
-- This is a convenience function which formulates the appropriate
-- control message to retrieve the descriptor. The string returned is
-- Unicode, as detailed in the USB specifications.
--
-- This function may throw USBExceptions.
--
-- TODO: The following can be made more type-safe!
--
-- When I call getStrDesc I would like the type system to
-- guarantee that the given StrIx and LangId actually
-- belong to the given Handle. In other words I would like to
-- get a type error when they are some arbitrary number or come from
-- another device.
getStrDesc :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> StrIx -> LangId -> Size -> cr String
-- | Retrieve a string descriptor from a device using the first supported
-- language.
--
-- This is a convenience function which formulates the appropriate
-- control message to retrieve the descriptor. The string returned is
-- Unicode, as detailed in the USB specifications.
--
-- This function may throw USBExceptions.
getStrDescFirstLang :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> StrIx -> Size -> cr String
-- | Determine if a kernel driver is active on an interface.
--
-- If a kernel driver is active, you cannot claim the interface, and
-- libusb will be unable to perform I/O.
--
-- Exceptions:
--
--
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
kernelDriverActive :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> InterfaceNumber -> cr Bool
-- | Detach a kernel driver from an interface.
--
-- If successful, you will then be able to claim the interface and
-- perform I/O.
--
-- Exceptions:
--
--
-- - NotFoundException if no kernel driver was active.
-- - InvalidParamException if the interface does not exist.
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
detachKernelDriver :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> InterfaceNumber -> cr ()
-- | Re-attach an interface's kernel driver, which was previously detached
-- using detachKernelDriver.
--
-- Exceptions:
--
--
-- - NotFoundException if no kernel driver was active.
-- - InvalidParamException if the interface does not exist.
-- - NoDeviceException if the device has been disconnected.
-- - BusyException if the driver cannot be attached because the
-- interface is claimed by a program or driver.
-- - Another USBException.
--
attachKernelDriver :: (ParentOf pr cr, MonadIO cr) => RegionalDeviceHandle pr -> InterfaceNumber -> cr ()
-- | If a kernel driver is active on the specified interface the driver is
-- detached and the given action is executed. If the action terminates,
-- whether by normal termination or by raising an exception, the kernel
-- driver is attached again. If a kernel driver is not active on the
-- specified interface the action is just executed.
--
-- Exceptions:
--
--
-- - NoDeviceException if the device has been disconnected.
-- - Another USBException.
--
withDetachedKernelDriver :: (ParentOf pr cr, MonadCatchIO cr) => RegionalDeviceHandle pr -> InterfaceNumber -> cr ± -> cr ±
instance [overlap ok] Typeable NotFound
instance [overlap ok] Typeable NoActiveConfig
instance [overlap ok] Typeable SettingAlreadySet
instance [overlap ok] Show NotFound
instance [overlap ok] Show NoActiveConfig
instance [overlap ok] Show SettingAlreadySet
instance [overlap ok] WriteEndpoint INTERRUPT
instance [overlap ok] WriteEndpoint BULK
instance [overlap ok] ReadEndpoint INTERRUPT
instance [overlap ok] ReadEndpoint BULK
instance [overlap ok] GetDescriptor (Endpoint transDir transType sAlt r) EndpointDesc
instance [overlap ok] Dup (Alternate sCfg) (Interface sCfg)
instance [overlap ok] GetDescriptor (Alternate sIntrf r) InterfaceDesc
instance [overlap ok] Resource (Interface sCfg)
instance [overlap ok] GetDescriptor (Interface sCfg) Interface
instance [overlap ok] Exception NotFound
instance [overlap ok] Exception NoActiveConfig
instance [overlap ok] Exception SettingAlreadySet
instance [overlap ok] Dup Config Device
instance [overlap ok] GetDescriptor (Config r) ConfigDesc
instance [overlap ok] GetDescriptor Device DeviceDesc
instance [overlap ok] Resource Device