Module: PWN::FFI::RTLSdr
- Extended by:
- Library
- Defined in:
- lib/pwn/ffi/rtl_sdr.rb
Overview
Thin librtlsdr binding (no -dev headers required — symbols resolved
from the installed shared object). Control-plane + blocking
read_sync so PWN::SDR::Decoder::* / Extrospection probe_rf can pull
raw u8 I/Q without shelling out to rtl_sdr.
If librtlsdr is missing .available? is false and callers fall back.
Class Attribute Summary collapse
-
.load_error ⇒ Object
readonly
Returns the value of attribute load_error.
Class Method Summary collapse
-
.authors ⇒ Object
- Author(s)
0day Inc.
-
.available? ⇒ Boolean
- Supported Method Parameters
PWN::FFI::RTLSdr.available?.
-
.close(opts = {}) ⇒ Object
- Supported Method Parameters
PWN::FFI::RTLSdr.close(device: pointer).
-
.configure(opts = {}) ⇒ Object
rubocop:disable Naming/PredicateMethod.
-
.help ⇒ Object
Display Usage for this Module.
-
.list_devices ⇒ Object
- Supported Method Parameters
devices = PWN::FFI::RTLSdr.list_devices Returns Array
of { index:, name:, manufacturer:, product:, serial: }.
-
.open(opts = {}) ⇒ Object
- Supported Method Parameters
dev = PWN::FFI::RTLSdr.open(index: 0) Returns opaque FFI::Pointer (rtlsdr_dev_t*).
-
.read_sync(opts = {}) ⇒ Object
- Supported Method Parameters
iq_u8 = PWN::FFI::RTLSdr.read_sync( device: 'required - pointer from .open', bytes: 'optional - number of raw bytes to read (default 262144)' ) Returns a binary String of unsigned 8-bit interleaved I/Q samples.
-
.tuner_gains(opts = {}) ⇒ Object
- Supported Method Parameters
gains = PWN::FFI::RTLSdr.tuner_gains(device: pointer) Returns Array
of supported gains in tenths of a dB.
Class Attribute Details
.load_error ⇒ Object (readonly)
Returns the value of attribute load_error.
26 27 28 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 26 def load_error @load_error end |
Class Method Details
.authors ⇒ Object
- Author(s)
0day Inc. [email protected]
187 188 189 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 187 public_class_method def self. "AUTHOR(S):\n 0day Inc. <[email protected]>\n" end |
.available? ⇒ Boolean
- Supported Method Parameters
PWN::FFI::RTLSdr.available?
55 56 57 58 59 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 55 public_class_method def self.available? !@load_error && respond_to?(:rtlsdr_get_device_count, true) rescue StandardError false end |
.close(opts = {}) ⇒ Object
- Supported Method Parameters
PWN::FFI::RTLSdr.close(device: pointer)
102 103 104 105 106 107 108 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 102 public_class_method def self.close(opts = {}) dev = opts[:device] return unless dev && !dev.null? rtlsdr_close(dev) nil end |
.configure(opts = {}) ⇒ Object
rubocop:disable Naming/PredicateMethod
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 119 public_class_method def self.configure(opts = {}) # rubocop:disable Naming/PredicateMethod dev = opts[:device] raise 'ERROR: :device required' if dev.nil? || dev.null? freq = opts[:freq_hz].to_i rate = (opts[:rate_hz] || 2_048_000).to_i ppm = (opts[:ppm] || 0).to_i check!(rtlsdr_set_sample_rate(dev, rate), 'set_sample_rate') check!(rtlsdr_set_center_freq(dev, freq), 'set_center_freq') check!(rtlsdr_set_freq_correction(dev, ppm), 'set_freq_correction') if ppm != 0 if opts.key?(:gain_db) && !opts[:gain_db].nil? check!(rtlsdr_set_tuner_gain_mode(dev, 1), 'gain_mode manual') check!(rtlsdr_set_tuner_gain(dev, opts[:gain_db].to_i), 'set_tuner_gain') else check!(rtlsdr_set_tuner_gain_mode(dev, 0), 'gain_mode auto') rtlsdr_set_agc_mode(dev, 1) end check!(rtlsdr_reset_buffer(dev), 'reset_buffer') true end |
.help ⇒ Object
Display Usage for this Module
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 193 public_class_method def self.help puts "USAGE: # Run available and return its result #{self}.available? # Run list devices and return its result #{self}.list_devices # Open a session or connection and return a handle. #{self}.open( index: 'optional - index value consumed by #open' ) # Close a session previously returned by #open. #{self}.close( device: 'optional - device value consumed by #close' ) # Run configure and return its result #{self}.configure( device: 'required - pointer from .open', freq_hz: 'required - center frequency Hz', rate_hz: 'optional - sample rate (default 2.048e6)', gain_db: 'optional - tenths of dB (e.g. 496 = 49.6 dB). nil = auto', ppm: 'optional - freq correction ppm (default 0)' ) # Run read sync and return its result #{self}.read_sync( device: 'required - pointer from .open', bytes: 'optional - number of raw bytes to read (default 262144)' ) # Run tuner gains and return its result #{self}.tuner_gains( device: 'required - device value consumed by #tuner_gains' ) # Print the AUTHOR(S) string for this module. #{self}.authors " constants.sort end |
.list_devices ⇒ Object
- Supported Method Parameters
devices = PWN::FFI::RTLSdr.list_devices
Returns Array
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 65 public_class_method def self.list_devices raise 'ERROR: librtlsdr not available' unless available? count = rtlsdr_get_device_count Array.new(count) do |i| mfr = PubFFI::MemoryPointer.new(:char, 256) prod = PubFFI::MemoryPointer.new(:char, 256) ser = PubFFI::MemoryPointer.new(:char, 256) rtlsdr_get_device_usb_strings(i, mfr, prod, ser) { index: i, name: (rtlsdr_get_device_name(i) || '').to_s, manufacturer: mfr.read_string, product: prod.read_string, serial: ser.read_string } end end |
.open(opts = {}) ⇒ Object
- Supported Method Parameters
dev = PWN::FFI::RTLSdr.open(index: 0) Returns opaque FFI::Pointer (rtlsdr_dev_t*).
88 89 90 91 92 93 94 95 96 97 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 88 public_class_method def self.open(opts = {}) raise 'ERROR: librtlsdr not available' unless available? idx = (opts[:index] || 0).to_i dev_ptr = PubFFI::MemoryPointer.new(:pointer) rc = rtlsdr_open(dev_ptr, idx) raise "ERROR: rtlsdr_open rc=#{rc}" unless rc.zero? dev_ptr.read_pointer end |
.read_sync(opts = {}) ⇒ Object
- Supported Method Parameters
iq_u8 = PWN::FFI::RTLSdr.read_sync( device: 'required - pointer from .open', bytes: 'optional - number of raw bytes to read (default 262144)' ) Returns a binary String of unsigned 8-bit interleaved I/Q samples. Short, complete IQ reads are returned intact. Native errors and odd byte counts raise. librtlsdr sync reads provide no dropped-sample count; successful reads alone do not establish continuous hardware capture. Callers must finish an in-flight read before closing the device.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 153 public_class_method def self.read_sync(opts = {}) dev = opts[:device] raise 'ERROR: :device required' if dev.nil? || dev.null? nbytes = (opts[:bytes] || 262_144).to_i buf = PubFFI::MemoryPointer.new(:uint8, nbytes) n_read = PubFFI::MemoryPointer.new(:int) rc = rtlsdr_read_sync(dev, buf, nbytes, n_read) raise "ERROR: rtlsdr_read_sync rc=#{rc}" unless rc.zero? got = n_read.read_int raise "ERROR: rtlsdr_read_sync invalid IQ length #{got}/#{nbytes}" if got.negative? || got > nbytes || got.odd? buf.read_string(got) end |
.tuner_gains(opts = {}) ⇒ Object
- Supported Method Parameters
gains = PWN::FFI::RTLSdr.tuner_gains(device: pointer)
Returns Array
173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/pwn/ffi/rtl_sdr.rb', line 173 public_class_method def self.tuner_gains(opts = {}) dev = opts[:device] raise 'ERROR: :device required' if dev.nil? || dev.null? n = rtlsdr_get_tuner_gains(dev, nil) return [] if n <= 0 ptr = PubFFI::MemoryPointer.new(:int, n) rtlsdr_get_tuner_gains(dev, ptr) ptr.read_array_of_int(n) end |