module LibBladeRF.LibBladeRF ( withBladeRF
, DeviceHandle(..)
, BladeRFError(..)
, BladeRFReturnType(..)
, bladeRFErrorValue
, bladeRFErrorTy
) where
import Foreign
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr
import Control.Exception
import Data.Typeable (Typeable, cast)
import Data.Maybe
import Data.Tuple
import Bindings.LibBladeRF
data BladeRFError = BLADERF_ERR_UNEXPECTED
| BLADERF_ERR_RANGE
| BLADERF_ERR_INVAL
| BLADERF_ERR_MEM
| BLADERF_ERR_IO
| BLADERF_ERR_TIMEOUT
| BLADERF_ERR_NODEV
| BLADERF_ERR_UNSUPPORTED
| BLADERF_ERR_MISALIGNED
| BLADERF_ERR_CHECKSUM
| BLADERF_ERR_NO_FILE
| BLADERF_ERR_UPDATE_FPGA
| BLADERF_ERR_UPDATE_FW
| BLADERF_ERR_TIME_PAST
deriving (Eq, Typeable)
instance Show BladeRFError where
show BLADERF_ERR_UNEXPECTED = "An unexpected failure occurred"
show BLADERF_ERR_RANGE = "Provided parameter is out of range"
show BLADERF_ERR_INVAL = "Invalid operation/parameter"
show BLADERF_ERR_MEM = "Memory allocation error"
show BLADERF_ERR_IO = "File/Device I/O error"
show BLADERF_ERR_TIMEOUT = "Operation timed out"
show BLADERF_ERR_NODEV = "No device(s) available"
show BLADERF_ERR_UNSUPPORTED = "Operation not supported"
show BLADERF_ERR_MISALIGNED = "Misaligned flash access"
show BLADERF_ERR_CHECKSUM = "Invalid checksum"
show BLADERF_ERR_NO_FILE = "File not found"
show BLADERF_ERR_UPDATE_FPGA = "An FPGA update is required"
show BLADERF_ERR_UPDATE_FW = "A firmware update is requied"
show BLADERF_ERR_TIME_PAST = "Requested timestamp is in the past"
instance Exception BladeRFError
instance Enum BladeRFError where
fromEnum = fromJust . flip lookup errors
toEnum = fromJust . flip lookup (map swap errors)
errors = [ (BLADERF_ERR_UNEXPECTED, c'BLADERF_ERR_UNEXPECTED)
, (BLADERF_ERR_RANGE, c'BLADERF_ERR_RANGE)
, (BLADERF_ERR_INVAL, c'BLADERF_ERR_INVAL)
, (BLADERF_ERR_MEM, c'BLADERF_ERR_MEM)
, (BLADERF_ERR_IO, c'BLADERF_ERR_IO)
, (BLADERF_ERR_TIMEOUT, c'BLADERF_ERR_TIMEOUT)
, (BLADERF_ERR_NODEV, c'BLADERF_ERR_NODEV)
, (BLADERF_ERR_UNSUPPORTED, c'BLADERF_ERR_UNSUPPORTED)
, (BLADERF_ERR_MISALIGNED, c'BLADERF_ERR_MISALIGNED)
, (BLADERF_ERR_CHECKSUM, c'BLADERF_ERR_CHECKSUM)
, (BLADERF_ERR_NO_FILE, c'BLADERF_ERR_NO_FILE)
, (BLADERF_ERR_UPDATE_FPGA, c'BLADERF_ERR_UPDATE_FPGA)
, (BLADERF_ERR_UPDATE_FW, c'BLADERF_ERR_UPDATE_FW)
, (BLADERF_ERR_TIME_PAST, c'BLADERF_ERR_TIME_PAST)
]
bladeRFErrorValue :: CInt -> BladeRFReturnType Int
bladeRFErrorValue c | c >= 0 = (Right . fromIntegral) c
| c < 0 = (Left . toEnum . fromIntegral) c
bladeRFErrorTy :: CInt -> BladeRFReturnType ()
bladeRFErrorTy c | c >= 0 = return ()
| c < 0 = (Left . toEnum . fromIntegral) c
type BladeRFReturnType a = Either BladeRFError a
newtype DeviceHandle = DeviceHandle { unDeviceHandle :: Ptr C'bladerf }
withBladeRF :: (DeviceHandle -> IO c) -> IO c
withBladeRF = bracket openBladeRF closeBladeRF
openBladeRF :: IO DeviceHandle
openBladeRF = do
r <- openBladeRF'
case r of
Left e -> throwIO e
Right dev -> return dev
openBladeRF' :: IO (BladeRFReturnType DeviceHandle)
openBladeRF' = alloca $ \ptr -> do
ret <- c'bladerf_open ptr nullPtr
if ret /= 0 then
return $ (Left . toEnum . fromIntegral) ret
else do
pdev <- peek ptr
return (Right (DeviceHandle pdev))
closeBladeRF :: DeviceHandle -> IO ()
closeBladeRF d = c'bladerf_close $ unDeviceHandle d