0 | module Bindings.RtlSdr.Device
 1 |
 2 | import Bindings.RtlSdr.Raw.Device
 3 | import Bindings.RtlSdr.Raw.Support
 4 | import Bindings.RtlSdr.Error
 5 |
 6 | import public Bindings.RtlSdr.Raw.Device
 7 | --import public Bindings.RtlSdr.Raw.Device.get_device_count
 8 | --import public Bindings.RtlSdr.Raw.Device.get_device_name
 9 |
10 | import System.FFI
11 |
12 | %default total
13 |
14 | export
15 | rtlsdr_open : Nat -> IO (Maybe (Ptr RtlSdrHandle))
16 | rtlsdr_open idx = do
17 |   v <- prim__castPtr <$> malloc 4 -- ret
18 |   -- const void * idris_rtlsdr_open(uint32_t index, uint32_t *ret);
19 |   p <- fromPrim $ idris_rtlsdr_open (cast {to = Int} idx) v
20 |   let ret = peekInt v
21 |   free $ prim__forgetPtr v
22 |   io_pure $ if ret == 0 then Just (prim__castPtr p) else Nothing
23 |
24 |
25 | export
26 | rtlsdr_close : Ptr RtlSdrHandle -> IO (Either RTLSDR_ERROR ())
27 | rtlsdr_close h = do
28 |   r <- fromPrim $ close h
29 |   io_pure $ if r == 0 then Right () else Left RtlSdrError
30 |
31 |
32 | public export
33 | record DeviceUSBStrings where
34 |   constructor MkDeviceUSBStrings
35 |   manufact : String
36 |   product  : String
37 |   serial   : String
38 |
39 | export
40 | Show DeviceUSBStrings where
41 |   show ds = ds.manufact ++ ", " ++ ds.product ++ ", " ++ ds.serial ++ "."
42 |
43 | ||| Get USB device strings.
44 | |||
45 | ||| @i is the the device index
46 | export
47 | getDeviceUSBStrings : Nat -> IO (Either RTLSDR_ERROR DeviceUSBStrings)
48 | getDeviceUSBStrings i = do
49 |   -- REMARK: The C API is buggy and doesn't validate a dev is available
50 |   -- before attempting to read strings, therefore n > 0 otherwise error.
51 |   let n = get_device_count
52 |   -- NOTE: The string arguments must provide space for up to 256 bytes.
53 |   m <- prim__castPtr <$> malloc 256
54 |   p <- prim__castPtr <$> malloc 256
55 |   s <- prim__castPtr <$> malloc 256
56 |   let r = get_device_usb_strings (cast {to = Int} i) m p s
57 |   let ds = MkDeviceUSBStrings (idris_rtlsdr_getstring m) (idris_rtlsdr_getstring p) (idris_rtlsdr_getstring s)
58 |   -- NOTE: No use-after-free as getstring will incur a strcpy.
59 |   free $ prim__forgetPtr m
60 |   free $ prim__forgetPtr p
61 |   free $ prim__forgetPtr s
62 |   io_pure $ if (r == 0 && n > 0) then Right ds else Left RtlSdrError
63 |
64 | decodeRetError : Int -> RTLSDR_ERROR
65 | decodeRetError e = case e of
66 |                         -1 => RtlSdrDeviceNameEmpty
67 |                         -2 => RtlSdrDeviceNotFound
68 |                         -3 => RtlSdrDeviceFoundButNotMatching
69 |                         _ =>  RtlSdrError -- unknonwn
70 |
71 | ||| Get device index by USB serial string descriptor.
72 | |||
73 | ||| Returns the device index of first device where the name matched
74 | |||
75 | ||| @s is the serial string of the device
76 | export
77 | getDeviceIndexBySerial : String -> Either RTLSDR_ERROR Nat
78 | getDeviceIndexBySerial s = do
79 |   let r = get_index_by_serial s
80 |   if r < 0 then Left (decodeRetError r) else Right (cast {to = Nat} r)
81 |