rtlsdr (empty) → 0.1.0.0
raw patch · 4 files changed
+434/−0 lines, 4 filesdep +arraydep +basesetup-changed
Dependencies added: array, base
Files
- LICENSE +30/−0
- RTLSDR.chs +368/−0
- Setup.hs +2/−0
- rtlsdr.cabal +34/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Adam Walker++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Adam Walker nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ RTLSDR.chs view
@@ -0,0 +1,368 @@+{-# LANGUAGE EmptyDataDecls #-}+module RTLSDR (+ getDeviceCount,+ getDeviceName,+ getDeviceUSBString,+ GIBSError(..),+ getIndexBySerial,+ RTLSDR,+ open,+ close,+ setXtalFreq,+ getXtalFreq,+ getUSBStrings,+ EEPROMError(..),+ writeEEPROM,+ readEEPROM,+ setCenterFreq,+ getCenterFreq,+ setFreqCorrection,+ getFreqCorrection,+ Tuner(..),+ getTunerType,+ getTunerGains,+ setTunerGain,+ getTunerGain,+ setTunerIFGain,+ setTunerGainMode,+ setSampleRate,+ getSampleRate,+ setTestMode,+ setAGCMode,+ DirectSamplingMode(..),+ setDirectSampling,+ getDirectSampling,+ setOffsetTuning,+ getOffsetTuning,+ resetBuffer,+ readSync,+ ReadCallback,+ readAsync,+ cancelAsync+ ) where++#include <rtl-sdr.h>++import Foreign.C.Types+import Foreign.C.String+import Foreign.Marshal.Alloc+import Foreign.Marshal.Array+import Foreign.Ptr+import Foreign.Storable++import Data.Word+import Data.Int+import Control.Monad+import Data.Array.MArray+import Data.Array.Storable++justWhenM :: Monad m => Bool -> m a -> m (Maybe a)+justWhenM cond act = if cond then liftM Just act else return Nothing++b2int :: Num i => Bool -> i+b2int False = 0+b2int True = 1++foreign import ccall unsafe "rtlsdr_get_device_count"+ c_getDeviceCount :: IO CUInt++getDeviceCount :: IO Word32+getDeviceCount = liftM fromIntegral c_getDeviceCount++foreign import ccall unsafe "rtlsdr_get_device_name"+ c_rtlsdrGetDeviceName :: CUInt -> IO CString++getDeviceName :: Word32 -> IO String+getDeviceName index = c_rtlsdrGetDeviceName (fromIntegral index) >>= peekCString ++foreign import ccall unsafe "rtlsdr_get_device_usb_strings"+ c_getDeviceUSBStrings :: CUInt -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt++getDeviceUSBString :: Word32 -> IO (Maybe (String, String, String))+getDeviceUSBString index = + allocaArray 256 $ \mp -> + allocaArray 256 $ \pp -> + allocaArray 256 $ \sp -> do+ res <- c_getDeviceUSBStrings (fromIntegral index) mp pp sp + justWhenM (res==0) $ do+ m <- peekCString mp+ p <- peekCString pp+ s <- peekCString sp+ return (m, p, s)+ +foreign import ccall unsafe "rtlsdr_get_index_by_serial"+ c_getIndexBySerial :: CString -> IO CInt++-- Get Index By Serial Error+data GIBSError = NameNull+ | NoDevices+ | NoMatching+ deriving (Show)++toGIBSError :: Int -> GIBSError+toGIBSError (-1) = NameNull+toGIBSError (-2) = NoDevices+toGIBSError (-3) = NoMatching+toGIBSError _ = error "rtlsdr_get_index_by_serial returned invalid error code"++getIndexBySerial :: String -> IO (Either GIBSError Int)+getIndexBySerial serial = liftM (func . fromIntegral) $ withCString serial c_getIndexBySerial + where func res + | res < 0 = Left (toGIBSError res)+ | otherwise = Right res++data CRTLSDR+data RTLSDR = RTLSDR (Ptr CRTLSDR)++foreign import ccall unsafe "rtlsdr_open"+ c_open :: Ptr (Ptr CRTLSDR) -> CInt -> IO CInt++open :: Word32 -> IO (Maybe RTLSDR)+open index = alloca $ \ptr -> do+ res <- c_open ptr (fromIntegral index)+ justWhenM (res >= 0) $ do+ res <- peek ptr+ return $ RTLSDR res++foreign import ccall unsafe "rtlsdr_close"+ c_close :: Ptr CRTLSDR -> IO CInt++close :: RTLSDR -> IO ()+close (RTLSDR ptr) = void $ c_close ptr++foreign import ccall unsafe "rtlsdr_set_xtal_freq"+ c_setXtalFreq :: Ptr CRTLSDR -> CUInt -> CUInt -> IO CInt++setXtalFreq :: RTLSDR -> Word32 -> Word32 -> IO Bool+setXtalFreq (RTLSDR ptr) rtlFreq tunerFreq = liftM (==0) $ c_setXtalFreq ptr (fromIntegral rtlFreq) (fromIntegral tunerFreq)++foreign import ccall unsafe "rtlsdr_get_xtal_freq"+ c_getXtalFreq :: Ptr CRTLSDR -> Ptr CUInt -> Ptr CUInt -> IO CInt++getXtalFreq :: RTLSDR -> IO (Maybe (Word32, Word32))+getXtalFreq (RTLSDR ptr) = + alloca $ \rp -> + alloca $ \tp -> do+ res <- c_getXtalFreq ptr rp tp+ justWhenM (res /= 0) $ do+ r <- peek rp+ t <- peek tp+ return (fromIntegral r, fromIntegral t)++foreign import ccall unsafe "rtlsdr_get_usb_strings"+ c_getUSBStrings :: Ptr CRTLSDR -> Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt++getUSBStrings :: RTLSDR -> IO (Maybe (String, String, String))+getUSBStrings (RTLSDR ptr) = + allocaArray 256 $ \mp -> + allocaArray 256 $ \pp -> + allocaArray 256 $ \sp -> do+ res <- c_getUSBStrings ptr mp pp sp + justWhenM (res == 0) $ do+ m <- peekCString mp+ p <- peekCString pp+ s <- peekCString sp+ return (m, p, s)++data EEPROMError = InvalidHandle+ | SizeExceeded+ | NoEEPROM+ deriving(Show)++toEEPROMError :: Int -> EEPROMError+toEEPROMError (-1) = InvalidHandle+toEEPROMError (-2) = SizeExceeded+toEEPROMError (-3) = NoEEPROM+toEEPROMError _ = error "librtlsdr returned invalid EEPROM error code"++foreign import ccall unsafe "rtlsdr_write_eeprom"+ c_writeEEPROM :: Ptr CRTLSDR -> Ptr CUChar -> CUChar -> CUShort -> IO CInt++writeEEPROM :: RTLSDR -> [Word8] -> Int -> IO (Maybe EEPROMError)+writeEEPROM (RTLSDR ptr) dataa offset = + liftM (func . fromIntegral) $ withArrayLen (map fromIntegral dataa) $ \size ptrd -> c_writeEEPROM ptr ptrd (fromIntegral offset) (fromIntegral size)+ where func x+ | x < 0 = Just $ toEEPROMError x+ | otherwise = Nothing++foreign import ccall unsafe "rtlsdr_read_eeprom"+ c_readEEPROM :: Ptr CRTLSDR -> Ptr CUChar -> CUChar -> CUShort -> IO CInt++readEEPROM :: RTLSDR -> Int -> Int -> IO (Either EEPROMError [Word8])+readEEPROM (RTLSDR ptr) offset len = allocaArray len $ \ptrd -> do+ res <- c_readEEPROM ptr ptrd (fromIntegral offset) (fromIntegral len)+ case res < 0 of+ True -> return $ Left $ toEEPROMError $ fromIntegral res+ False -> do+ res <- peekArray len ptrd+ return $ Right $ map fromIntegral res++foreign import ccall unsafe "rtlsdr_set_center_freq"+ c_setCenterFreq :: Ptr CRTLSDR -> CUInt -> IO CInt++setCenterFreq :: RTLSDR -> Word32 -> IO Bool+setCenterFreq (RTLSDR ptr) freq = liftM (==0) $ c_setCenterFreq ptr (fromIntegral freq)++foreign import ccall unsafe "rtlsdr_get_center_freq"+ c_getCenterFreq :: Ptr CRTLSDR -> IO CUInt++getCenterFreq :: RTLSDR -> IO (Maybe Word32)+getCenterFreq (RTLSDR ptr) = liftM func $ c_getCenterFreq ptr+ where func 0 = Nothing+ func x = Just $ fromIntegral x++foreign import ccall unsafe "rtlsdr_set_freq_correction"+ c_setFreqCorrection :: Ptr CRTLSDR -> CInt -> IO CInt++setFreqCorrection :: RTLSDR -> Int32 -> IO Bool+setFreqCorrection (RTLSDR ptr) ppm = liftM (==0) $ c_setFreqCorrection ptr (fromIntegral ppm)++foreign import ccall unsafe "rtlsdr_get_freq_correction"+ c_getFreqCorrection :: Ptr CRTLSDR -> IO CInt++getFreqCorrection :: RTLSDR -> IO Int32 +getFreqCorrection (RTLSDR ptr) = liftM fromIntegral $ c_getFreqCorrection ptr++{#enum rtlsdr_tuner as Tuner {underscoreToCase} deriving (Show, Eq) #}++foreign import ccall unsafe "rtlsdr_get_tuner_type"+ c_getTunerType :: Ptr CRTLSDR -> IO CInt++getTunerType :: RTLSDR -> IO Tuner+getTunerType (RTLSDR ptr) = liftM (toEnum . fromIntegral) $ c_getTunerType ptr++foreign import ccall unsafe "rtlsdr_get_tuner_gains"+ c_getTunerGains :: Ptr CRTLSDR -> Ptr CInt -> IO CInt++getTunerGains :: RTLSDR -> IO (Maybe [Int])+getTunerGains (RTLSDR ptr) = do+ num <- c_getTunerGains ptr nullPtr + justWhenM (num >= 0) $ + allocaArray (fromIntegral num) $ \ptrg -> do+ c_getTunerGains ptr ptrg+ res <- peekArray (fromIntegral num) ptrg+ return $ map fromIntegral res++foreign import ccall unsafe "rtlsdr_set_tuner_gain"+ c_setTunerGain :: Ptr CRTLSDR -> CInt -> IO CInt++setTunerGain :: RTLSDR -> Int32 -> IO Bool+setTunerGain (RTLSDR ptr) gain = liftM (==0) $ c_setTunerGain ptr (fromIntegral gain)++foreign import ccall unsafe "rtlsdr_get_tuner_gain"+ c_getTunerGain :: Ptr CRTLSDR -> IO CInt++getTunerGain :: RTLSDR -> IO (Maybe Int32)+getTunerGain (RTLSDR ptr) = liftM func $ c_getTunerGain ptr+ where func 0 = Nothing+ func x = Just $ fromIntegral x++foreign import ccall unsafe "rtlsdr_set_tuner_if_gain"+ c_setTunerIFGain :: Ptr CRTLSDR -> CInt -> CInt -> IO CInt++setTunerIFGain :: RTLSDR -> Int -> Int -> IO Bool+setTunerIFGain (RTLSDR ptr) stage gain = liftM (==0) $ c_setTunerIFGain ptr (fromIntegral stage) (fromIntegral gain)++foreign import ccall unsafe "rtlsdr_set_tuner_gain_mode"+ c_setTunerGainMode :: Ptr CRTLSDR -> CInt -> IO CInt++setTunerGainMode :: RTLSDR -> Bool -> IO Bool+setTunerGainMode (RTLSDR ptr) mode = liftM (==0) $ c_setTunerGainMode ptr (b2int mode)++foreign import ccall unsafe "rtlsdr_set_sample_rate"+ c_setSampleRate :: Ptr CRTLSDR -> CUInt -> IO CInt++setSampleRate :: RTLSDR -> Word32 -> IO Bool+setSampleRate (RTLSDR ptr) rate = liftM (==0) $ c_setSampleRate ptr (fromIntegral rate)++foreign import ccall unsafe "rtlsdr_get_sample_rate"+ c_getSampleRate :: Ptr CRTLSDR -> IO CUInt++getSampleRate :: RTLSDR -> IO (Maybe Word32)+getSampleRate (RTLSDR ptr) = liftM func $ c_getSampleRate ptr+ where func 0 = Nothing+ func x = Just $ fromIntegral x++foreign import ccall unsafe "rtlsdr_set_testmode"+ c_setTestmode :: Ptr CRTLSDR -> CInt -> IO CInt++setTestMode :: RTLSDR -> Bool -> IO Bool+setTestMode (RTLSDR ptr) on = liftM (==0) $ c_setTestmode ptr (b2int on)++foreign import ccall unsafe "rtlsdr_set_agc_mode"+ c_setAGCMode :: Ptr CRTLSDR -> CInt -> IO CInt++setAGCMode :: RTLSDR -> Bool -> IO Bool+setAGCMode (RTLSDR ptr) on = liftM (==0) $ c_setAGCMode ptr (b2int on)++data DirectSamplingMode = DSDisabled+ | DSI+ | DSQ+ deriving (Enum, Show, Eq)++foreign import ccall unsafe "rtlsdr_set_direct_sampling"+ c_setDirectSampling :: Ptr CRTLSDR -> CInt -> IO CInt++setDirectSampling :: RTLSDR -> DirectSamplingMode -> IO Bool+setDirectSampling (RTLSDR ptr) mode = liftM (==0) $ c_setDirectSampling ptr (fromIntegral $ fromEnum mode)++foreign import ccall unsafe "rtlsdr_get_direct_sampling"+ c_getDirectSampling :: Ptr CRTLSDR -> IO CInt++getDirectSampling :: RTLSDR -> IO (Maybe DirectSamplingMode)+getDirectSampling (RTLSDR ptr) = do+ res <- c_getDirectSampling ptr+ justWhenM (res >= 0) $ + return $ toEnum $ fromIntegral res++foreign import ccall unsafe "rtlsdr_set_offset_tuning"+ c_setOffsetTuning :: Ptr CRTLSDR -> CInt -> IO CInt++setOffsetTuning :: RTLSDR -> Bool -> IO Bool+setOffsetTuning (RTLSDR ptr) on = liftM (==0) $ c_setOffsetTuning ptr (b2int on)++foreign import ccall unsafe "rtlsdr_get_offset_tuning"+ c_getOffsetTuning :: Ptr CRTLSDR -> IO CInt++getOffsetTuning :: RTLSDR -> IO (Maybe Bool)+getOffsetTuning (RTLSDR ptr) = do+ res <- c_getOffsetTuning ptr+ justWhenM (res >= 0) $ + return $ res == 1++foreign import ccall unsafe "rtlsdr_reset_buffer"+ c_resetBuffer :: Ptr CRTLSDR -> IO CInt++resetBuffer :: RTLSDR -> IO Int+resetBuffer (RTLSDR ptr) = liftM fromIntegral $ c_resetBuffer ptr++foreign import ccall unsafe "rtlsdr_read_sync"+ c_readSync :: Ptr CRTLSDR -> Ptr CUChar -> CInt -> Ptr CInt -> IO CInt++readSync :: RTLSDR -> Ptr CUChar -> Int -> IO Bool+readSync (RTLSDR ptr) aptr len = do+ res <- alloca $ c_readSync ptr aptr (fromIntegral len) + return $ res >= 0 ++type ReadCallback = Ptr CUChar -> Word32 -> Ptr CInt -> IO ()++foreign import ccall "wrapper"+ wrap :: ReadCallback -> IO (FunPtr ReadCallback)++foreign import ccall safe "rtlsdr_read_async"+ c_readAsync :: Ptr CRTLSDR -> FunPtr ReadCallback -> Ptr () -> CUInt -> CUInt -> IO CInt++readAsync :: RTLSDR -> Word32 -> Word32 -> (Ptr CUChar -> Int -> IO ()) -> IO Bool+readAsync (RTLSDR ptr) bufNum bufLen callback = do+ cb <- wrap f+ res <- c_readAsync ptr cb nullPtr (fromIntegral bufNum) (fromIntegral bufLen)+ return $ res == 0+ where+ f buf len ctx = callback buf (fromIntegral len)++foreign import ccall unsafe "rtlsdr_cancel_async"+ c_cancelAsync :: Ptr CRTLSDR -> IO CInt++cancelAsync :: RTLSDR -> IO Bool+cancelAsync (RTLSDR ptr) = liftM (==0) $ c_cancelAsync ptr+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ rtlsdr.cabal view
@@ -0,0 +1,34 @@+-- Initial rtlsdr.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++name: rtlsdr+version: 0.1.0.0+synopsis: Bindings to librtlsdr+description: + Bindings to librtlsdr. Turns your Realtek RTL2832 based DVB dongle into a SDR receiver. + .+ For more information see: http://sdr.osmocom.org/trac/wiki/rtl-sdr+license: BSD3+license-file: LICENSE+author: Adam Walker+maintainer: adamwalker10@gmail.com+copyright: 2014 Adam Walker+category: Software defined radio+build-type: Simple+-- extra-source-files: +cabal-version: >=1.10++source-repository head+ type: git+ location: https://github.com/adamwalker/hrtlsdr++library+ exposed-modules: RTLSDR+ -- other-modules: + other-extensions: EmptyDataDecls+ build-depends: base >=4.6 && <4.8, array >=0.4 && <0.6+ -- hs-source-dirs: + build-tools: c2hs+ default-language: Haskell2010+ extra-libraries: rtlsdr+ -- ghc-options: -Wall