Temp got sim to work with tcp device by stripping out a lot of the logic.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use clap::Parser;
|
||||
use std::io::{Read, Write};
|
||||
use std::io::{Read, Write, Result};
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
@@ -26,7 +26,6 @@ struct SimulationArgs {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Parse command‐line arguments
|
||||
let args = SimulationArgs::parse();
|
||||
|
||||
// Build the bind address, e.g. "127.0.0.1:9999"
|
||||
@@ -38,24 +37,26 @@ fn main() {
|
||||
.unwrap_or_else(|err| panic!("failed to bind {}: {}", bind_address, err));
|
||||
|
||||
// Accept connections in a loop
|
||||
for incoming in listener.incoming() {
|
||||
match incoming {
|
||||
for incoming_connection in listener.incoming() {
|
||||
match incoming_connection {
|
||||
Ok(client_stream) => {
|
||||
// Spawn a thread per client
|
||||
thread::spawn(move || handle_client_connection(client_stream));
|
||||
thread::spawn(move || {
|
||||
if let Err(err) = handle_client_connection(client_stream) {
|
||||
eprintln!("connection error: {}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(err) => eprintln!("Error accepting connection: {}", err),
|
||||
Err(err) => eprintln!("error accepting connection: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle a single client connection
|
||||
fn handle_client_connection(mut connection: TcpStream) {
|
||||
// Track a "current frequency"
|
||||
let mut current_frequency_hz: u32 = 0;
|
||||
|
||||
fn handle_client_connection(mut connection: TcpStream) -> Result<()> {
|
||||
println!("Connection established");
|
||||
loop {
|
||||
// Read the 4-byte header: [tag:1][bRequest:1][length:2]
|
||||
// Read the 4-byte header: [tag:1][bRequest:1][length:2 LE]
|
||||
let mut header_buffer = [0u8; 4];
|
||||
if connection.read_exact(&mut header_buffer).is_err() {
|
||||
// Client closed on error
|
||||
@@ -63,79 +64,68 @@ fn handle_client_connection(mut connection: TcpStream) {
|
||||
}
|
||||
|
||||
let message_tag = header_buffer[0];
|
||||
let b_request = header_buffer[1];
|
||||
let _b_request = header_buffer[1];
|
||||
let payload_length = u16::from_le_bytes([header_buffer[2], header_buffer[3]]) as usize;
|
||||
|
||||
// println!("Received message '{:02x}' with payload length {}", message_tag, payload_length);
|
||||
|
||||
// Read the optional payload
|
||||
let mut payload_buffer = vec![0u8; payload_length];
|
||||
if payload_length > 0 {
|
||||
if connection.read_exact(&mut payload_buffer).is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// let mut payload_buffer = vec![0u8; payload_length];
|
||||
// if payload_length > 0 {
|
||||
// if connection.read(&mut payload_buffer).is_err() {
|
||||
// eprintln!("error reading payload buffer");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Dispatch based on the framing tag
|
||||
match message_tag {
|
||||
TAG_CONTROL_OUT => {
|
||||
// Simulate accepting a CONTROL_OUT (e.g. SET_FREQ)
|
||||
if b_request == 0x02 && payload_buffer.len() == 4 {
|
||||
current_frequency_hz = u32::from_le_bytes([
|
||||
payload_buffer[0],
|
||||
payload_buffer[1],
|
||||
payload_buffer[2],
|
||||
payload_buffer[3],
|
||||
]);
|
||||
println!("SET_FREQ -> {} Hz", current_frequency_hz);
|
||||
}
|
||||
// Acknowledge with a single byte = 0 (OK)
|
||||
connection.write_all(&[0u8]).ok();
|
||||
// println!("Received control out");
|
||||
// Acknowledge with a status OK
|
||||
connection.write_all(&[0u8])?;
|
||||
}
|
||||
TAG_CONTROL_IN => {
|
||||
dbg!(message_tag);
|
||||
// Simulate a CONTROL_IN reply with a fixed pattern
|
||||
|
||||
// Status byte
|
||||
let _ = connection.write_all(&[0u8]);
|
||||
|
||||
// 2-byte little-endian length
|
||||
let length_u16 = payload_length as u16;
|
||||
let _ = connection.write_all(&length_u16.to_le_bytes());
|
||||
|
||||
// Payload (0x42 repeated)
|
||||
let reply = vec![0x42; payload_length];
|
||||
let _ = connection.write_all(&reply).ok();
|
||||
// println!("Received control in");
|
||||
// STATUS(1) + LENGTH(2) + dummy payload
|
||||
connection.write_all(&[0x00])?;
|
||||
connection.write_all(&(payload_length as u16).to_le_bytes())?;
|
||||
connection.write_all(&vec![0x42; payload_length])?;
|
||||
}
|
||||
TAG_BULK => {
|
||||
dbg!(message_tag);
|
||||
// Generate a ADS-B IQ burst
|
||||
let iq_samples = generate_adsb_iq_samples();
|
||||
let length_u32 = (iq_samples.len() as u32).to_le_bytes();
|
||||
|
||||
// Send status byte = 0 (OK)
|
||||
let _ = connection.write_all(&[0u8]);
|
||||
|
||||
// Send 4-byte little-endian length (bulk uses u32)
|
||||
let _ = connection.write_all(&length_u32);
|
||||
|
||||
// Send the IQ payload
|
||||
let _ = connection.write_all(&iq_samples);
|
||||
// println!("Received bulk message");
|
||||
let iq = generate_adsb_iq();
|
||||
// STATUS(1) + LENGTH(4) + IQ data
|
||||
connection.write_all(&[0x00])?;
|
||||
connection.write_all(&(iq.len() as u32).to_le_bytes())?;
|
||||
connection.write_all(&iq)?;
|
||||
|
||||
// Throttle a bit to simulate real USB/bulk behavior
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
}
|
||||
_unknown_tag => {
|
||||
// On any unrecognized tag, break out
|
||||
eprintln!("Unknown message tag {}", _unknown_tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Connection closed");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_adsb_iq() -> Vec<u8> {
|
||||
let mut v = Vec::with_capacity(ADSB_MESSAGE.len() * 2);
|
||||
for &b in &ADSB_MESSAGE {
|
||||
v.push(b); // I
|
||||
v.push(0x80); // Q fixed
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
/// Build one preamble (8 bits) + 112 data bits
|
||||
/// Sampled at 2 Mhz (1 sample per half-bit). Interleaved I/Q bytes
|
||||
fn generate_adsb_iq_samples() -> Vec<u8> {
|
||||
fn _generate_adsb_iq_samples() -> Vec<u8> {
|
||||
// Preamble bits (1us per bit at 2 Mhz -> 2 samples per bit)
|
||||
// Preamble is 8 bits: 1,0,1,0,1,0,0,0
|
||||
let preamble_bits = [1, 0, 1, 0, 1, 0, 0, 0];
|
||||
|
||||
Reference in New Issue
Block a user