Module: PWN::FFI::SoapySDR

Extended by:
Library
Defined in:
lib/pwn/ffi/soapy_sdr.rb

Overview

Thin SoapySDR C-API binding (libSoapySDR). Inventory-focused first — enumerate devices and report API version so Extrospection probe_rf can list every Soapy-backed front-end (RTL-SDR, HackRF, Airspy, Pluto, UHD, …) without shelling out to SoapySDRUtil.

Full streaming can be layered later; today this is the discovery surface. Missing lib → .available? false, pure-Ruby / CLI fallbacks.

Defined Under Namespace

Classes: Kwargs

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.load_errorObject (readonly)

Returns the value of attribute load_error.



27
28
29
# File 'lib/pwn/ffi/soapy_sdr.rb', line 27

def load_error
  @load_error
end

Class Method Details

.authorsObject

Author(s)

0day Inc. support@0dayinc.com



157
158
159
# File 'lib/pwn/ffi/soapy_sdr.rb', line 157

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <support@0dayinc.com>\n"
end

.available?Boolean

Supported Method Parameters

PWN::FFI::SoapySDR.available?

Returns:

  • (Boolean)


66
67
68
69
70
# File 'lib/pwn/ffi/soapy_sdr.rb', line 66

public_class_method def self.available?
  !@load_error && respond_to?(:SoapySDR_getAPIVersion, true)
rescue StandardError
  false
end

.device_keys(opts = {}) ⇒ Object

Supported Method Parameters

meta = PWN::FFI::SoapySDR.device_keys(device: pointer) Returns { driver:, hardware: }.



145
146
147
148
149
150
151
152
153
# File 'lib/pwn/ffi/soapy_sdr.rb', line 145

public_class_method def self.device_keys(opts = {})
  dev = opts[:device]
  raise 'ERROR: :device required' if dev.nil? || dev.null?

  {
    driver: SoapySDRDevice_getDriverKey(dev).to_s,
    hardware: SoapySDRDevice_getHardwareKey(dev).to_s
  }
end

.helpObject

Display Usage for this Module



163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/pwn/ffi/soapy_sdr.rb', line 163

public_class_method def self.help
  puts "USAGE:
    #{self}.available?
    #{self}.info
    #{self}.list_devices
    dev = #{self}.make(args: 'driver=rtlsdr')
    #{self}.device_keys(device: dev)
    #{self}.unmake(device: dev)

    #{self}.authors
  "
end

.infoObject

Supported Method Parameters

info = PWN::FFI::SoapySDR.info Returns { available:, api:, abi:, lib: }.



76
77
78
79
80
81
82
83
84
85
# File 'lib/pwn/ffi/soapy_sdr.rb', line 76

public_class_method def self.info
  return { available: false, error: @load_error&.message } unless available?

  {
    available: true,
    api: SoapySDR_getAPIVersion().to_s,
    abi: SoapySDR_getABIVersion().to_s,
    lib: SoapySDR_getLibVersion().to_s
  }
end

.list_devicesObject

Supported Method Parameters

devices = PWN::FFI::SoapySDR.list_devices Returns Array of keyword→value maps for every enumerated device.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/pwn/ffi/soapy_sdr.rb', line 91

public_class_method def self.list_devices
  raise 'ERROR: libSoapySDR not available' unless available?

  len_ptr = PubFFI::MemoryPointer.new(:size_t)
  # pass NULL args → enumerate everything
  list_ptr = SoapySDRDevice_enumerate(nil, len_ptr)
  length = len_ptr.read_ulong
  return [] if list_ptr.null? || length.zero?

  results = []
  length.times do |i|
    kw = Kwargs.new(list_ptr + (i * Kwargs.size))
    h = {}
    kw[:size].times do |j|
      key = kw[:keys].get_pointer(j * PubFFI::Pointer.size)
      val = kw[:vals].get_pointer(j * PubFFI::Pointer.size)
      h[key.read_string.to_sym] = val.read_string unless key.null?
    end
    results << h
  end
  SoapySDRKwargsList_clear(list_ptr, length)
  results
end

.make(opts = {}) ⇒ Object

Supported Method Parameters

dev = PWN::FFI::SoapySDR.make(args: 'driver=rtlsdr') Returns opaque pointer (SoapySDRDevice*) or raises. ALWAYS pair with .unmake.



120
121
122
123
124
125
126
127
128
# File 'lib/pwn/ffi/soapy_sdr.rb', line 120

public_class_method def self.make(opts = {})
  raise 'ERROR: libSoapySDR not available' unless available?

  args = opts[:args].to_s
  dev = SoapySDRDevice_makeStrArgs(args)
  raise "ERROR: SoapySDRDevice_makeStrArgs(#{args.inspect}) returned NULL" if dev.null?

  dev
end

.unmake(opts = {}) ⇒ Object

Supported Method Parameters

PWN::FFI::SoapySDR.unmake(device: pointer)



133
134
135
136
137
138
139
# File 'lib/pwn/ffi/soapy_sdr.rb', line 133

public_class_method def self.unmake(opts = {})
  dev = opts[:device]
  return unless dev && !dev.null?

  SoapySDRDevice_unmake(dev)
  nil
end