Module: PWN::FFI::HackRF

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

Overview

Thin libhackrf binding for inventory / RX of raw I/Q.

Intentionally control-plane first: init/open/tune/rate/gains + one-shot sync-style helpers used by Extrospection probe_rf and by wideband PWN::SDR::Decoder::* modules that need real I/Q (not GQRX audio). Streaming callbacks stay opt-in — Ruby GC must not run on the libusb transfer thread, so call sites that need continuous RX should buffer into a Queue from a dedicated thread.

Constant Summary collapse

HACKRF_SUCCESS =
0

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.load_errorObject (readonly)

Returns the value of attribute load_error.



30
31
32
# File 'lib/pwn/ffi/hack_rf.rb', line 30

def load_error
  @load_error
end

Class Method Details

.authorsObject

Author(s)

0day Inc. support@0dayinc.com



162
163
164
# File 'lib/pwn/ffi/hack_rf.rb', line 162

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

.available?Boolean

Supported Method Parameters

PWN::FFI::HackRF.available?

Returns:

  • (Boolean)


59
60
61
62
63
# File 'lib/pwn/ffi/hack_rf.rb', line 59

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

.close(opts = {}) ⇒ Object

Supported Method Parameters

PWN::FFI::HackRF.close(device: pointer)



101
102
103
104
105
106
107
108
# File 'lib/pwn/ffi/hack_rf.rb', line 101

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

  check!(hackrf_close(dev))
  hackrf_exit
  nil
end

.configure(opts = {}) ⇒ Object

rubocop:disable Naming/PredicateMethod



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/pwn/ffi/hack_rf.rb', line 121

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] || 10_000_000).to_f
  lna  = (opts[:lna_gain] || 16).to_i
  vga  = (opts[:vga_gain] || 20).to_i
  amp  = opts[:amp] ? 1 : 0

  check!(hackrf_set_freq(dev, freq))
  check!(hackrf_set_sample_rate(dev, rate))
  check!(hackrf_set_lna_gain(dev, lna))
  check!(hackrf_set_vga_gain(dev, vga))
  check!(hackrf_set_amp_enable(dev, amp))
  check!(hackrf_set_baseband_filter_bandwidth(dev, opts[:bb_bw_hz].to_i)) if opts[:bb_bw_hz]
  true
end

.device_info(opts = {}) ⇒ Object

Supported Method Parameters

meta = PWN::FFI::HackRF.device_info(device: pointer) Returns { board_id:, board_name:, version: }



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/pwn/ffi/hack_rf.rb', line 144

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

  bid_ptr = PubFFI::MemoryPointer.new(:uint8)
  check!(hackrf_board_id_read(dev, bid_ptr))
  bid = bid_ptr.read_uint8
  ver_buf = PubFFI::MemoryPointer.new(:char, 255)
  check!(hackrf_version_string_read(dev, ver_buf, 255))
  {
    board_id: bid,
    board_name: hackrf_board_id_name(bid).to_s,
    version: ver_buf.read_string
  }
end

.helpObject

Display Usage for this Module



168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/pwn/ffi/hack_rf.rb', line 168

public_class_method def self.help
  puts "USAGE:
    #{self}.available?
    #{self}.info
    dev = #{self}.open(serial: nil)
    #{self}.configure(device: dev, freq_hz:, rate_hz: 10e6, lna_gain: 16, vga_gain: 20, amp: false)
    #{self}.device_info(device: dev)
    #{self}.close(device: dev)

    #{self}.authors
  "
end

.infoObject

Supported Method Parameters

info = PWN::FFI::HackRF.info Returns Hash with library_version / library_release / available.



69
70
71
72
73
74
75
76
77
# File 'lib/pwn/ffi/hack_rf.rb', line 69

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

  {
    available: true,
    library_version: hackrf_library_version.to_s,
    library_release: hackrf_library_release.to_s
  }
end

.open(opts = {}) ⇒ Object

Supported Method Parameters

dev = PWN::FFI::HackRF.open(serial: nil) Returns FFI::Pointer (opaque hackrf_device*) or raises.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/pwn/ffi/hack_rf.rb', line 83

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

  check!(hackrf_init)
  dev_ptr = PubFFI::MemoryPointer.new(:pointer)
  serial = opts[:serial]
  rc = if serial
         hackrf_open_by_serial(serial.to_s, dev_ptr)
       else
         hackrf_open(dev_ptr)
       end
  check!(rc)
  dev_ptr.read_pointer
end