Module: PWN::SDR::Decoder::Iridium
- Defined in:
- lib/pwn/sdr/decoder/iridium.rb
Overview
IRA protocol decoding from pre-synchronized symbol IQ, plus separate wideband energy observations (.detect). General raw-IQ acquisition and non-IRA message families are not implemented. See the independent RF vectors and BSD protocol-source notice in spec/fixtures/sdr/iridium/.
Defined Under Namespace
Classes: DemodIQ, RingAlert, RingAlertSymbolsIQ
Class Method Summary collapse
-
.authors ⇒ Object
- Author(s)
0day Inc.
-
.decode(opts = {}) ⇒ Object
Realtime options forwarded to Base: on_frame (Hash callback), output (writable IO), interactive (default true), duration (seconds), stop (callable), queue_size (bounded chunks), log_file (path or false).
-
.decode_ring_alert(opts = {}) ⇒ Object
IRA layout reference: muccc/iridium-toolkit bitsparser.py, BSD-2-Clause.
- .detect(opts = {}) ⇒ Object
- .help ⇒ Object
- .parse_line(opts = {}) ⇒ Object
Class Method Details
.authors ⇒ Object
- Author(s)
0day Inc. [email protected]
281 282 283 |
# File 'lib/pwn/sdr/decoder/iridium.rb', line 281 public_class_method def self. "AUTHOR(S):\n 0day Inc. <[email protected]>\n" end |
.decode(opts = {}) ⇒ Object
Realtime options forwarded to Base: on_frame (Hash callback), output (writable IO), interactive (default true), duration (seconds), stop (callable), queue_size (bounded chunks), log_file (path or false).
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/pwn/sdr/decoder/iridium.rb', line 228 public_class_method def self.decode(opts = {}) raise NotImplementedError, 'Wideband IQ protocol decoding is not implemented; only mode: :ira_symbols_iq (synchronized IRA symbols) is supported. Use .detect for energy observations.' unless opts[:mode] == :ira_symbols_iq rate = opts[:sample_rate] || 25_000 raise ArgumentError, 'IRA symbol IQ requires 25000 samples/s' unless rate == 25_000 explicit_source = opts[:source].respond_to?(:read) || (opts[:file] && [nil, :file].include?(opts[:source])) raise ArgumentError, 'Explicit file or readable symbol IQ source required; RF acquisition is not supported' unless explicit_source PWN::SDR::Decoder::Base.run_iq( **opts, freq_obj: opts[:freq_obj] || {}, protocol: 'IRIDIUM', sample_rate: rate, demod: RingAlertSymbolsIQ.new, note: 'IRA only: pre-synchronized complex symbols; no wideband acquisition or RS message families.' ) end |
.decode_ring_alert(opts = {}) ⇒ Object
IRA layout reference: muccc/iridium-toolkit bitsparser.py, BSD-2-Clause. See spec/fixtures/sdr/iridium/README.md for source and RF provenance. Accepts canonical differential/Gray bits INCLUDING the downlink UW; extractor RAW records swap each dibit and must be normalized first.
93 94 95 |
# File 'lib/pwn/sdr/decoder/iridium.rb', line 93 public_class_method def self.decode_ring_alert(opts = {}) RingAlert.new.decode(opts[:bits]) end |
.detect(opts = {}) ⇒ Object
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/pwn/sdr/decoder/iridium.rb', line 244 public_class_method def self.detect(opts = {}) freq_obj = opts[:freq_obj] || {} rate = (opts[:sample_rate] || freq_obj[:iq_rate] || 2_000_000).to_i proto = 'IRIDIUM' demod = DemodIQ.new( rate: rate, protocol: proto, modulation: 'DE-QPSK', extra: { threshold: 7.0 } ) PWN::SDR::Decoder::Base.run_iq( **opts, freq_obj: freq_obj, protocol: proto, sample_rate: rate, source: opts[:source], file: opts[:file], demod: demod, threshold: 7.0, note: '25 kbit/s DE-QPSK — true-air I/Q path reports burst timing/energy.', describe: proc { |_b| { modulation: 'DE-QPSK', symbol_rate: 25_000 } } ) end |
.help ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/pwn/sdr/decoder/iridium.rb', line 285 public_class_method def self.help puts "USAGE: # Decode IRA only from already channelized, carrier/timing-synchronized # symbol IQ. Not raw wideband IQ; no LCW, RS, voice or messaging support. #{self}.decode( mode: 'required - :ira_symbols_iq; default :iq raises NotImplementedError', source: 'required - :file or readable IO; never automatically acquires RF', file: 'optional - path required for file source', sample_rate: 'optional - exactly 25000 complex symbol samples/s', freq_obj: 'optional - metadata Hash; no radio control', iq_format: 'optional - :cs16 recommended for the supplied fixtures', on_frame: 'optional - decoded IRA Hash callback', interactive: 'optional - false for file replay', log_file: 'optional - path or false' ) # Decode a canonical downlink IRA bit frame, with BCH/parity checks. #{self}.decode_ring_alert( bits: 'required - binary String including access word; canonical RWA order' ) # Run detection only (not protocol decoding). #{self}.detect( freq_obj: 'required - freq_obj returned from PWN::SDR::GQRX.init_freq', on_frame: 'optional - callback receiving each emitted Hash', output: 'optional - writable IO (default stdout)', interactive: 'optional - false disables ENTER input', duration: 'optional - finite seconds to run', stop: 'optional - callable returning true to stop', queue_size: 'optional - bounded pending chunks (default 8)', log_file: 'optional - JSONL path or false to disable logging', sample_rate: 'optional - sample rate value consumed by #decode', source: 'optional - source value consumed by #decode', file: 'optional - filesystem path' ) # Run parse line and return its result #{self}.parse_line( line: 'optional - line value consumed by #parse_line' ) # Print the AUTHOR(S) string for this module. #{self}.authors " constants.sort end |
.parse_line(opts = {}) ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/pwn/sdr/decoder/iridium.rb', line 267 public_class_method def self.parse_line(opts = {}) line = opts[:line].to_s out = { protocol: 'IRIDIUM' } out[:frame_type] = ::Regexp.last_match(1) if line =~ /^([A-Z]{3}):/ out[:sat] = ::Regexp.last_match(1) if line =~ /sat:(\d+)/ out[:beam] = ::Regexp.last_match(1) if line =~ /beam:(\d+)/ out[:pos] = ::Regexp.last_match(1) if line =~ /pos=\(([^)]+)\)/ out[:ra_id] = ::Regexp.last_match(1) if line =~ /ric:(\d+)/ out[:summary] = "IRIDIUM #{out[:frame_type]} sat=#{out[:sat]} beam=#{out[:beam]}" out.compact end |