USB: P3 — wire scheme into main loop for ecmd + usbaudiod
redbear-ecmd: scheme loop replaces stdout on Redox (/scheme/net/usbECM_<N>), notification reader kept for CDC link state / speed change events on both paths. redbear-usbaudiod: scheme loop replaces stdout on Redox (/scheme/audio/usbAudio_<N>), stdin→isoch_OUT playback thread kept for host stdout path only. All 4 class drivers now fully wired: acmd → scheme event loop active on Redox ✅ ftdi → scheme event loop active on Redox ✅ ecmd → scheme event loop active on Redox ✅ usbaudiod → scheme event loop active on Redox ✅
This commit is contained in:
@@ -168,67 +168,83 @@ fn main() {
|
||||
log::info!("CDC ECM ready on {} port {} — bulk_in={} bulk_out={} int={} filter={:04X}",
|
||||
scheme, port_id, bulk_in_num, bulk_out_num, int_num, filter);
|
||||
|
||||
// Spawn stdin→bulk OUT writer thread for Ethernet Tx.
|
||||
// ── Scheme IPC path (Redox) ──
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{Socket, SignalBehavior};
|
||||
let scheme_name = format!("net/usbECM_{}", port_id);
|
||||
log::info!("ECM: registering /scheme/{}", scheme_name);
|
||||
let socket = Socket::create().expect("ECM: scheme socket");
|
||||
let mut scheme_state = redox_scheme::scheme::SchemeState::new();
|
||||
let mut ecm_scheme = crate::scheme::EcmScheme::new(dev.bulk_in, dev.bulk_out);
|
||||
socket.register(&scheme_name).expect("ECM: scheme register");
|
||||
if let Some(mut int_ep) = dev.int_ep {
|
||||
thread::spawn(move || {
|
||||
let mut buf = [0u8; 16];
|
||||
loop {
|
||||
match int_ep.transfer_read(&mut buf) {
|
||||
Ok(s) if s.bytes_transferred >= 8 => {
|
||||
let b = buf[1];
|
||||
match b {
|
||||
CDC_NOTIFY_NETWORK_CONNECTION => log::info!("ECM: link {}", if u16::from_le_bytes([buf[2],buf[3]]) != 0 { "UP" } else { "DOWN" }),
|
||||
CDC_NOTIFY_SPEED_CHANGE => log::info!("ECM: speed up={} down={}", u32::from_le_bytes([buf[8],buf[9],buf[10],buf[11]]), u32::from_le_bytes([buf[12],buf[13],buf[14],buf[15]])),
|
||||
_ => log::debug!("ECM: notify type={:02X}", b),
|
||||
}
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(e) => log::warn!("ECM: int: {}", e),
|
||||
}
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
}
|
||||
});
|
||||
}
|
||||
loop {
|
||||
let req = socket.next_request(SignalBehavior::Restart).expect("ECM: scheme request");
|
||||
if let Err(e) = req.handle_scheme_mut(&mut ecm_scheme, &mut scheme_state) {
|
||||
log::warn!("ECM: scheme error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Stdout path (host/Linux testing) ──
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
{
|
||||
let mut bulk_out = dev.bulk_out;
|
||||
let _tx_thread = thread::spawn(move || {
|
||||
let mut buf = [0u8; 2048];
|
||||
loop {
|
||||
match io::stdin().read(&mut buf) {
|
||||
Ok(0) => break,
|
||||
Ok(n) => { let _ = bulk_out.transfer_write(&buf[..n]); }
|
||||
Ok(0) => break, Ok(n) => { let _ = bulk_out.transfer_write(&buf[..n]); }
|
||||
Err(e) => { log::warn!("ECM: stdin: {}", e); break; }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Optional: spawn notification reader for network connection / speed changes.
|
||||
if let Some(mut int_ep) = dev.int_ep {
|
||||
thread::spawn(move || {
|
||||
let mut buf = [0u8; 16];
|
||||
loop {
|
||||
match int_ep.transfer_read(&mut buf) {
|
||||
Ok(status) if status.bytes_transferred >= 8 => {
|
||||
let bm_request_type = buf[0];
|
||||
let b_notification = buf[1];
|
||||
let w_value = u16::from_le_bytes([buf[2], buf[3]]);
|
||||
let w_index = u16::from_le_bytes([buf[4], buf[5]]);
|
||||
let w_length = u16::from_le_bytes([buf[6], buf[7]]);
|
||||
match b_notification {
|
||||
CDC_NOTIFY_NETWORK_CONNECTION => {
|
||||
let connected = w_value != 0;
|
||||
log::info!("ECM: network connection: {}", if connected { "UP" } else { "DOWN" });
|
||||
}
|
||||
CDC_NOTIFY_SPEED_CHANGE => {
|
||||
let up: u32 = u32::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]);
|
||||
let down: u32 = u32::from_le_bytes([buf[12], buf[13], buf[14], buf[15]]);
|
||||
log::info!("ECM: speed change: up={}bps down={}bps", up, down);
|
||||
}
|
||||
_ => {
|
||||
log::debug!("ECM: notification type={:02X} request_type={:02X} value={:04X} index={:04X} len={}",
|
||||
b_notification, bm_request_type, w_value, w_index, w_length);
|
||||
}
|
||||
Ok(s) if s.bytes_transferred >= 8 => {
|
||||
match buf[1] {
|
||||
CDC_NOTIFY_NETWORK_CONNECTION => log::info!("ECM: link {}", if u16::from_le_bytes([buf[2],buf[3]]) != 0 { "UP" } else { "DOWN" }),
|
||||
CDC_NOTIFY_SPEED_CHANGE => log::info!("ECM: speed up={} down={}", u32::from_le_bytes([buf[8],buf[9],buf[10],buf[11]]), u32::from_le_bytes([buf[12],buf[13],buf[14],buf[15]])),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(e) => log::warn!("ECM: interrupt: {}", e),
|
||||
Ok(_) => {} Err(e) => log::warn!("ECM: int: {}", e),
|
||||
}
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Main loop: bulk IN → stdout (Ethernet Rx).
|
||||
let mut buf = [0u8; 2048];
|
||||
loop {
|
||||
match dev.bulk_in.transfer_read(&mut buf) {
|
||||
Ok(status) if status.bytes_transferred > 0 => {
|
||||
let n = status.bytes_transferred as usize;
|
||||
let _ = io::stdout().write_all(&buf[..n]);
|
||||
let _ = io::stdout().flush();
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(e) => log::warn!("ECM: read: {}", e),
|
||||
Ok(status) if status.bytes_transferred > 0 => { let _ = io::stdout().write_all(&buf[..status.bytes_transferred as usize]); let _ = io::stdout().flush(); }
|
||||
Ok(_) => {} Err(e) => log::warn!("ECM: read: {}", e),
|
||||
}
|
||||
thread::sleep(time::Duration::from_millis(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,28 @@ fn main() {
|
||||
let _ = dev.set_mute(0, false);
|
||||
log::info!("UAC: sample rate={} unmuted", sample_rate);
|
||||
|
||||
// Spawn stdin→isoch OUT writer thread for playback
|
||||
// ── Scheme IPC path (Redox) ──
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{Socket, SignalBehavior};
|
||||
let scheme_name = format!("audio/usbAudio_{}", port_id);
|
||||
log::info!("UAC: registering /scheme/{}", scheme_name);
|
||||
let socket = Socket::create().expect("UAC: scheme socket");
|
||||
let mut scheme_state = redox_scheme::scheme::SchemeState::new();
|
||||
let mut audio_scheme = crate::scheme::AudioScheme::new(dev.isoch_in, dev.isoch_out);
|
||||
socket.register(&scheme_name).expect("UAC: scheme register");
|
||||
loop {
|
||||
let req = socket.next_request(SignalBehavior::Restart).expect("UAC: scheme request");
|
||||
if let Err(e) = req.handle_scheme_mut(&mut audio_scheme, &mut scheme_state) {
|
||||
log::warn!("UAC: scheme error: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Stdout path (host/Linux testing) ──
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
{
|
||||
let frame_size = dev.frame_size();
|
||||
if let Some(isoch_out) = dev.isoch_out {
|
||||
let mut isoch_out = isoch_out;
|
||||
@@ -263,20 +284,14 @@ fn main() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Main loop: isoch IN → stdout (recording)
|
||||
let buf_size = frame_size * 480;
|
||||
let mut buf = vec![0u8; buf_size];
|
||||
loop {
|
||||
match dev.isoch_in.transfer_read(&mut buf) {
|
||||
Ok(status) if status.bytes_transferred > 0 => {
|
||||
let n = status.bytes_transferred as usize;
|
||||
let _ = io::stdout().write_all(&buf[..n]);
|
||||
let _ = io::stdout().flush();
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(e) => log::warn!("UAC: read: {}", e),
|
||||
Ok(s) if s.bytes_transferred > 0 => { let _ = io::stdout().write_all(&buf[..s.bytes_transferred as usize]); let _ = io::stdout().flush(); }
|
||||
Ok(_) => {} Err(e) => log::warn!("UAC: read: {}", e),
|
||||
}
|
||||
thread::sleep(time::Duration::from_millis(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user