USB: fix scheme API — match actual redox-scheme SchemeSync trait
Cross-referenced with wifictl's working scheme registration pattern. scheme.rs fixes (acmd + ftdi): - openat: 5→6 params (add &mut self, fcntl_flags: u32) - read: 4→6 params (add offset: u64, fcntl_flags: u32) - write: 4→6 params (add offset: u64, fcntl_flags: u32) - Removed close() method (not in SchemeSync trait) - OpenResult.flags: usize→NewFdFlags (via from_bits_truncate) - Removed unused imports main.rs fixes (acmd): - Replaced register_async_scheme + handle_scheme_mut with wifictl pattern: setrens(0,0) + request.handle_sync() + socket.write_response() + RequestKind::Call match - Socket::next_request returns Option<Request>, handle Ok(None)/Err gracefully instead of expect() Verified: cargo check --offline passes on host.
This commit is contained in:
@@ -89,18 +89,29 @@ fn main() {
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{Socket, SignalBehavior};
|
||||
use redox_scheme::{RequestKind, SignalBehavior, Socket};
|
||||
let scheme_name = format!("ttys/usbACM_{}", port_id);
|
||||
log::info!("CDC ACM: registering /scheme/{}", scheme_name);
|
||||
let socket = Socket::create().expect("CDC ACM: scheme socket");
|
||||
let mut scheme_state = redox_scheme::scheme::SchemeState::new();
|
||||
let mut acm_scheme = crate::scheme::AcmScheme::new(dev.bulk_in, dev.bulk_out);
|
||||
socket.register(&scheme_name).expect("CDC ACM: scheme register");
|
||||
let _ = libredox::call::setrens(0, 0);
|
||||
log::info!("CDC ACM: scheme /scheme/{} ready", scheme_name);
|
||||
loop {
|
||||
let req = socket.next_request(SignalBehavior::Restart).expect("CDC ACM: scheme request");
|
||||
if let Err(e) = req.handle_scheme_mut(&mut acm_scheme, &mut scheme_state) {
|
||||
log::warn!("CDC ACM: scheme error: {}", e);
|
||||
let request = match socket.next_request(SignalBehavior::Restart) {
|
||||
Ok(Some(req)) => req,
|
||||
Ok(None) => { log::info!("CDC ACM: scheme socket closed"); break; }
|
||||
Err(err) => { log::error!("CDC ACM: scheme request error: {}", err); break; }
|
||||
};
|
||||
match request.kind() {
|
||||
RequestKind::Call(call) => {
|
||||
let response = call.handle_sync(&mut acm_scheme, &mut scheme_state);
|
||||
if let Err(err) = socket.write_response(response, SignalBehavior::Restart) {
|
||||
log::error!("CDC ACM: response error: {}", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ use std::sync::Mutex;
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{CallerCtx, OpenResult};
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL};
|
||||
use syscall::flag::{MODE_FILE, O_RDWR, O_STAT};
|
||||
use syscall::flag::{O_RDWR, O_STAT};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
|
||||
use xhcid_interface::XhciEndpHandle;
|
||||
|
||||
@@ -15,89 +16,38 @@ pub struct AcmScheme {
|
||||
|
||||
impl AcmScheme {
|
||||
pub fn new(bulk_in: XhciEndpHandle, bulk_out: XhciEndpHandle) -> Self {
|
||||
Self {
|
||||
bulk_in: Mutex::new(bulk_in),
|
||||
bulk_out: Mutex::new(bulk_out),
|
||||
open_count: Mutex::new(0),
|
||||
}
|
||||
Self { bulk_in: Mutex::new(bulk_in), bulk_out: Mutex::new(bulk_out), open_count: Mutex::new(0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeSync for AcmScheme {
|
||||
fn openat(
|
||||
&self,
|
||||
id: usize,
|
||||
path: &str,
|
||||
_flags: usize,
|
||||
_ctx: &CallerCtx,
|
||||
) -> Result<OpenResult> {
|
||||
if id != 1 {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
fn openat(&mut self, fd: usize, path: &str, _flags: usize, _fcntl_flags: u32, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
if fd != 1 { return Err(Error::new(EBADF)); }
|
||||
if path.is_empty() || path == "." || path == "/" {
|
||||
// Root directory listing
|
||||
if path.is_empty() {
|
||||
*self.open_count.lock().unwrap_or_else(|e| e.into_inner()) += 1;
|
||||
return Ok(OpenResult::ThisScheme {
|
||||
number: 1,
|
||||
flags: O_STAT | MODE_FILE,
|
||||
});
|
||||
}
|
||||
return Err(Error::new(EINVAL));
|
||||
*self.open_count.lock().unwrap_or_else(|e| e.into_inner()) += 1;
|
||||
return Ok(OpenResult::ThisScheme { number: 1, flags: NewFdFlags::from_bits_truncate(O_STAT) });
|
||||
}
|
||||
// Opening the device (path == "tty" or "" on open)
|
||||
let mut count = self.open_count.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let next_id = 2 + *count;
|
||||
*count += 1;
|
||||
Ok(OpenResult::OtherScheme {
|
||||
number: next_id,
|
||||
flags: O_RDWR,
|
||||
})
|
||||
let next_id = 2 + *count; *count += 1;
|
||||
Ok(OpenResult::OtherScheme { number: next_id, flags: NewFdFlags::from_bits_truncate(O_RDWR) })
|
||||
}
|
||||
|
||||
fn read(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result<usize> {
|
||||
if id < 2 || buf.is_empty() {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
fn read(&mut self, id: usize, buf: &mut [u8], _offset: u64, _fcntl_flags: u32, _ctx: &CallerCtx) -> Result<usize> {
|
||||
if id < 2 || buf.is_empty() { return Err(Error::new(EBADF)); }
|
||||
let mut bulk_in = self.bulk_in.lock().unwrap_or_else(|e| e.into_inner());
|
||||
match bulk_in.transfer_read(buf) {
|
||||
Ok(status) if status.bytes_transferred > 0 => {
|
||||
Ok(status.bytes_transferred as usize)
|
||||
}
|
||||
Ok(status) if status.bytes_transferred > 0 => Ok(status.bytes_transferred as usize),
|
||||
Ok(_) => Ok(0),
|
||||
Err(e) => {
|
||||
log::warn!("ACM scheme: read: {}", e);
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
Err(e) => { log::warn!("ACM scheme: read: {}", e); Err(Error::new(EINVAL)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, id: usize, buf: &[u8], _ctx: &CallerCtx) -> Result<usize> {
|
||||
if id < 2 || buf.is_empty() {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
fn write(&mut self, id: usize, buf: &[u8], _offset: u64, _fcntl_flags: u32, _ctx: &CallerCtx) -> Result<usize> {
|
||||
if id < 2 || buf.is_empty() { return Err(Error::new(EBADF)); }
|
||||
let mut bulk_out = self.bulk_out.lock().unwrap_or_else(|e| e.into_inner());
|
||||
match bulk_out.transfer_write(buf) {
|
||||
Ok(status) if status.bytes_transferred > 0 => {
|
||||
Ok(status.bytes_transferred as usize)
|
||||
}
|
||||
Ok(status) if status.bytes_transferred > 0 => Ok(status.bytes_transferred as usize),
|
||||
Ok(_) => Ok(0),
|
||||
Err(e) => {
|
||||
log::warn!("ACM scheme: write: {}", e);
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
Err(e) => { log::warn!("ACM scheme: write: {}", e); Err(Error::new(EINVAL)) }
|
||||
}
|
||||
}
|
||||
|
||||
fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&self, id: usize, _ctx: &CallerCtx) -> Result<()> {
|
||||
if id >= 2 {
|
||||
let mut count = self.open_count.lock().unwrap_or_else(|e| e.into_inner());
|
||||
*count = count.saturating_sub(1);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> { Ok(()) }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ use std::sync::Mutex;
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{CallerCtx, OpenResult};
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL};
|
||||
use syscall::flag::{MODE_FILE, O_RDWR, O_STAT};
|
||||
use syscall::flag::{O_RDWR, O_STAT};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
|
||||
use xhcid_interface::XhciEndpHandle;
|
||||
|
||||
@@ -20,17 +21,17 @@ impl FtdiScheme {
|
||||
}
|
||||
|
||||
impl SchemeSync for FtdiScheme {
|
||||
fn openat(&self, id: usize, path: &str, _flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
if id != 1 { return Err(Error::new(EBADF)); }
|
||||
fn openat(&mut self, fd: usize, path: &str, _flags: usize, _fcntl_flags: u32, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
if fd != 1 { return Err(Error::new(EBADF)); }
|
||||
if path.is_empty() || path == "." || path == "/" {
|
||||
*self.open_count.lock().unwrap_or_else(|e| e.into_inner()) += 1;
|
||||
return Ok(OpenResult::ThisScheme { number: 1, flags: O_STAT | MODE_FILE });
|
||||
return Ok(OpenResult::ThisScheme { number: 1, flags: NewFdFlags::from_bits_truncate(O_STAT) });
|
||||
}
|
||||
let mut count = self.open_count.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let next_id = 2 + *count; *count += 1;
|
||||
Ok(OpenResult::OtherScheme { number: next_id, flags: O_RDWR })
|
||||
Ok(OpenResult::OtherScheme { number: next_id, flags: NewFdFlags::from_bits_truncate(O_RDWR) })
|
||||
}
|
||||
fn read(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> Result<usize> {
|
||||
fn read(&mut self, id: usize, buf: &mut [u8], _offset: u64, _fcntl_flags: u32, _ctx: &CallerCtx) -> Result<usize> {
|
||||
if id < 2 || buf.is_empty() { return Err(Error::new(EBADF)); }
|
||||
let mut bulk_in = self.bulk_in.lock().unwrap_or_else(|e| e.into_inner());
|
||||
match bulk_in.transfer_read(buf) {
|
||||
@@ -39,7 +40,7 @@ impl SchemeSync for FtdiScheme {
|
||||
Err(e) => { log::warn!("FTDI scheme: read: {}", e); Err(Error::new(EINVAL)) }
|
||||
}
|
||||
}
|
||||
fn write(&mut self, id: usize, buf: &[u8], _ctx: &CallerCtx) -> Result<usize> {
|
||||
fn write(&mut self, id: usize, buf: &[u8], _offset: u64, _fcntl_flags: u32, _ctx: &CallerCtx) -> Result<usize> {
|
||||
if id < 2 || buf.is_empty() { return Err(Error::new(EBADF)); }
|
||||
let mut bulk_out = self.bulk_out.lock().unwrap_or_else(|e| e.into_inner());
|
||||
match bulk_out.transfer_write(buf) {
|
||||
@@ -49,11 +50,4 @@ impl SchemeSync for FtdiScheme {
|
||||
}
|
||||
}
|
||||
fn fsync(&mut self, _id: usize, _ctx: &CallerCtx) -> Result<()> { Ok(()) }
|
||||
fn close(&self, id: usize, _ctx: &CallerCtx) -> Result<()> {
|
||||
if id >= 2 {
|
||||
let mut count = self.open_count.lock().unwrap_or_else(|e| e.into_inner());
|
||||
*count = count.saturating_sub(1);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user