Merge branch 'readiness_based' into 'main'
Implement cancellation, reduce boilerplate, and update redox-scheme See merge request redox-os/base!8
This commit is contained in:
Generated
+34
-62
@@ -91,11 +91,13 @@ source = "git+https://gitlab.redox-os.org/redox-os/arg-parser.git#1c434b55f3e1a0
|
||||
name = "audiod"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ioslice",
|
||||
"libc",
|
||||
"libredox 0.0.3",
|
||||
"libredox",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.1.0",
|
||||
"redox_syscall 0.4.1",
|
||||
"redox-scheme 0.5.0 (git+https://gitlab.redox-os.org/redox-os/redox-scheme.git)",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -405,7 +407,7 @@ dependencies = [
|
||||
name = "init"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -422,11 +424,11 @@ dependencies = [
|
||||
name = "ipcd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.2.4",
|
||||
"redox_event",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -451,17 +453,6 @@ version = "0.2.171"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "962b650e6b934f95cec493e1464e0f5cba98dd9ba9ef2b1c42cdfdb7864cab5a"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"libc",
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
@@ -471,7 +462,7 @@ dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"ioslice",
|
||||
"libc",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -484,10 +475,10 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
name = "logd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -527,7 +518,7 @@ dependencies = [
|
||||
"arg_parser",
|
||||
"clap",
|
||||
"libc",
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"net2",
|
||||
"ntpclient",
|
||||
"pbr",
|
||||
@@ -636,11 +627,11 @@ dependencies = [
|
||||
name = "ptyd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.3.0",
|
||||
"redox_event",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
"redox_termios",
|
||||
]
|
||||
|
||||
@@ -664,10 +655,10 @@ name = "ramfs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
"slab",
|
||||
]
|
||||
|
||||
@@ -691,13 +682,13 @@ checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
name = "randd"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"raw-cpuid",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.2.4",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
@@ -717,7 +708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fbdeffdb03cf2961b211a2023e683d71f2c225ea93404da5dc34b0dc94f0341"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -732,24 +723,14 @@ dependencies = [
|
||||
"termion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox-scheme"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "425289b64797f9b7d98971e61d4838c67041c2ca13511e5a62539936873ae1a8"
|
||||
dependencies = [
|
||||
"libredox 0.0.3",
|
||||
"redox_syscall 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox-scheme"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6143c4d307e1c99ac14f60b5b07b2dccaf9d17137f7cee4e4e29977dd8014a1b"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"redox_syscall 0.5.11",
|
||||
"libredox",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -758,8 +739,8 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e7f06e1b19d8143043e959fbd7b76a37e759e3e9c6bbfc9c91c496b0b44d20"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"redox_syscall 0.5.11",
|
||||
"libredox",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -768,17 +749,17 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a96b9cfb034251dfb0aaa66a67059a7f0ea344039904d1d70cd36266af9c8a2f"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"redox_syscall 0.5.11",
|
||||
"libredox",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox-scheme"
|
||||
version = "0.5.0"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/redox-scheme.git#ce4eead6798c2d1d1d5a6d57b45481a4909ec62e"
|
||||
source = "git+https://gitlab.redox-os.org/redox-os/redox-scheme.git#ef9f1512f54758be20960717dfad193d6cd70dc7"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"redox_syscall 0.5.11",
|
||||
"libredox",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -788,7 +769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69609faa5d5992247a4ef379917bb3e39be281405d6a0ccd4f942429400b956f"
|
||||
dependencies = [
|
||||
"bitflags 2.9.0",
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -798,26 +779,17 @@ dependencies = [
|
||||
"anyhow",
|
||||
"dns-parser",
|
||||
"ioslice",
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"log",
|
||||
"netutils",
|
||||
"redox-daemon",
|
||||
"redox-log",
|
||||
"redox-scheme 0.5.0 (git+https://gitlab.redox-os.org/redox-os/redox-scheme.git)",
|
||||
"redox_event",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
"smoltcp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.11"
|
||||
@@ -946,7 +918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3669a69de26799d6321a5aa713f55f7e2cd37bd47be044b50f2acafc42c122bb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"numtoa",
|
||||
"redox_termios",
|
||||
]
|
||||
@@ -1283,8 +1255,8 @@ dependencies = [
|
||||
name = "zerod"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox 0.1.3",
|
||||
"libredox",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.2.4",
|
||||
"redox_syscall 0.5.11",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
+6
-4
@@ -2,11 +2,13 @@
|
||||
name = "audiod"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
redox-daemon = "0.1.2"
|
||||
redox_syscall = "0.4.1"
|
||||
redox_syscall = { version = "0.5", features = ["std"] }
|
||||
libc = "0.2"
|
||||
libredox = "0.0.3"
|
||||
redox-scheme = "0.1.0"
|
||||
libredox = { version = "0.1", features = ["mkns"] }
|
||||
redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" }
|
||||
anyhow = "1.0.97"
|
||||
ioslice = "0.6.0"
|
||||
|
||||
+30
-41
@@ -1,13 +1,15 @@
|
||||
extern crate syscall;
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr::addr_of_mut;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{mem, process, slice, thread};
|
||||
|
||||
use anyhow::Context;
|
||||
use ioslice::IoSlice;
|
||||
use libredox::flag;
|
||||
use libredox::{error::Result, Fd};
|
||||
use redox_scheme::{SignalBehavior, Socket};
|
||||
|
||||
use redox_scheme::wrappers::ReadinessBased;
|
||||
use redox_scheme::Socket;
|
||||
|
||||
use redox_daemon::Daemon;
|
||||
|
||||
@@ -18,9 +20,6 @@ mod scheme;
|
||||
extern "C" fn sigusr_handler(_sig: usize) {}
|
||||
|
||||
fn thread(scheme: Arc<Mutex<AudioScheme>>, pid: usize, hw_file: Fd) -> Result<()> {
|
||||
// Enter null namespace
|
||||
libredox::call::setrens(0, 0)?;
|
||||
|
||||
loop {
|
||||
let buffer = scheme.lock().unwrap().buffer();
|
||||
let buffer_u8 = unsafe {
|
||||
@@ -34,7 +33,7 @@ fn thread(scheme: Arc<Mutex<AudioScheme>>, pid: usize, hw_file: Fd) -> Result<()
|
||||
}
|
||||
}
|
||||
|
||||
fn daemon(daemon: Daemon) -> Result<()> {
|
||||
fn daemon(daemon: Daemon) -> anyhow::Result<()> {
|
||||
// Handle signals from the hw thread
|
||||
|
||||
let new_sigaction = unsafe {
|
||||
@@ -50,55 +49,45 @@ fn daemon(daemon: Daemon) -> Result<()> {
|
||||
|
||||
let hw_file = Fd::open("/scheme/audiohw", flag::O_WRONLY | flag::O_CLOEXEC, 0)?;
|
||||
|
||||
let socket = Socket::create("audio")?;
|
||||
let socket = Socket::create("audio").context("failed to create scheme")?;
|
||||
|
||||
let scheme = Arc::new(Mutex::new(AudioScheme::new()));
|
||||
|
||||
// Enter a constrained namespace
|
||||
let ns = libredox::call::mkns(&[
|
||||
//IoSlice::new(b"memory"), TODO: already included, uncommenting gives EEXIST
|
||||
IoSlice::new(b"rand"), // for HashMap
|
||||
IoSlice::new(b"thisproc"), // for thread::spawn
|
||||
]).context("failed to make namespace")?;
|
||||
libredox::call::setrens(ns, ns).context("failed to set namespace")?;
|
||||
|
||||
// Spawn a thread to mix and send audio data
|
||||
let scheme_thread = scheme.clone();
|
||||
let _thread = thread::spawn(move || thread(scheme_thread, pid, hw_file));
|
||||
|
||||
// Enter the null namespace - done after thread is created so
|
||||
// memory: can be accessed for stack allocation
|
||||
libredox::call::setrens(0, 0)?;
|
||||
let _thread = thread::spawn(move || {
|
||||
libredox::call::setrens(ns, ns).unwrap();
|
||||
thread(scheme_thread, pid, hw_file)
|
||||
});
|
||||
|
||||
// The scheme is now ready to accept requests, notify the original process
|
||||
daemon.ready().unwrap();
|
||||
|
||||
let mut pending = Vec::new();
|
||||
let mut readiness = ReadinessBased::new(&socket, 16);
|
||||
|
||||
loop {
|
||||
match socket.next_request(SignalBehavior::Interrupt) {
|
||||
Ok(Some(request)) => {
|
||||
match request.handle_scheme_block_mut(&mut *scheme.lock().unwrap()) {
|
||||
Ok(response) => {
|
||||
socket.write_responses(&[response], SignalBehavior::Restart)?;
|
||||
}
|
||||
Err(request) => pending.push(request),
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => match err.errno {
|
||||
libredox::errno::EINTR => {}
|
||||
_ => return Err(err),
|
||||
},
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
while i < pending.len() {
|
||||
let request = pending[i];
|
||||
match request.handle_scheme_block_mut(&mut *scheme.lock().unwrap()) {
|
||||
Ok(response) => {
|
||||
pending.remove(i);
|
||||
socket.write_responses(&[response], SignalBehavior::Restart)?;
|
||||
}
|
||||
Err(_) => i += 1,
|
||||
}
|
||||
if !readiness.read_requests()? {
|
||||
break;
|
||||
}
|
||||
readiness.process_requests(|| scheme.lock().unwrap());
|
||||
readiness.poll_all_requests(|| scheme.lock().unwrap())?;
|
||||
if !readiness.write_responses()? {
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let Err(err) = Daemon::new(|x| match daemon(x) {
|
||||
Ok(()) => {
|
||||
process::exit(0);
|
||||
|
||||
+57
-53
@@ -1,9 +1,10 @@
|
||||
use redox_scheme::{CallerCtx, OpenResult};
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::str;
|
||||
use syscall::error::{EBADF, EINVAL, ENOENT, EWOULDBLOCK, Error, Result};
|
||||
use syscall::flag::O_NONBLOCK;
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL, ENOENT, EWOULDBLOCK};
|
||||
|
||||
use redox_scheme::SchemeBlockMut;
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
|
||||
// The strict buffer size of the audiohw: driver
|
||||
const HW_BUFFER_SIZE: usize = 512;
|
||||
@@ -11,14 +12,10 @@ const HW_BUFFER_SIZE: usize = 512;
|
||||
const HANDLE_BUFFER_SIZE: usize = 4096;
|
||||
|
||||
enum Handle {
|
||||
Audio {
|
||||
flags: usize,
|
||||
buffer: VecDeque<(i16, i16)>,
|
||||
},
|
||||
//TODO: move volume to audiohw:?
|
||||
Volume {
|
||||
offset: usize,
|
||||
}
|
||||
Audio { buffer: VecDeque<(i16, i16)> },
|
||||
// TODO: move volume to audiohw:?
|
||||
// TODO: Use SYS_CALL to handle this better?
|
||||
Volume,
|
||||
}
|
||||
|
||||
pub struct AudioScheme {
|
||||
@@ -44,7 +41,7 @@ impl AudioScheme {
|
||||
let volume_factor = ((self.volume as f32) / 100.0).powi(3);
|
||||
for (_id, handle) in self.handles.iter_mut() {
|
||||
match handle {
|
||||
Handle::Audio { flags: _, ref mut buffer } => {
|
||||
Handle::Audio { ref mut buffer } => {
|
||||
let mut i = 0;
|
||||
while i < mix_buffer.len() {
|
||||
if let Some(sample) = buffer.pop_front() {
|
||||
@@ -57,7 +54,7 @@ impl AudioScheme {
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@@ -66,16 +63,16 @@ impl AudioScheme {
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemeBlockMut for AudioScheme {
|
||||
fn open(&mut self, path: &str, flags: usize, _uid: u32, _gid: u32) -> Result<Option<usize>> {
|
||||
let handle = match path.trim_matches('/') {
|
||||
"" => Handle::Audio {
|
||||
flags,
|
||||
buffer: VecDeque::new()
|
||||
},
|
||||
"volume" => Handle::Volume {
|
||||
offset: 0,
|
||||
},
|
||||
impl SchemeSync for AudioScheme {
|
||||
fn open(&mut self, path: &str, _flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
let (handle, flags) = match path.trim_matches('/') {
|
||||
"" => (
|
||||
Handle::Audio {
|
||||
buffer: VecDeque::new(),
|
||||
},
|
||||
NewFdFlags::empty(),
|
||||
),
|
||||
"volume" => (Handle::Volume, NewFdFlags::POSITIONED),
|
||||
_ => return Err(Error::new(ENOENT)),
|
||||
};
|
||||
|
||||
@@ -83,60 +80,68 @@ impl SchemeBlockMut for AudioScheme {
|
||||
self.next_id += 1;
|
||||
self.handles.insert(id, handle);
|
||||
|
||||
Ok(Some(id))
|
||||
Ok(OpenResult::ThisScheme { number: id, flags })
|
||||
}
|
||||
|
||||
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
|
||||
fn read(
|
||||
&mut self,
|
||||
id: usize,
|
||||
buf: &mut [u8],
|
||||
off: u64,
|
||||
_flags: u32,
|
||||
_ctx: &CallerCtx,
|
||||
) -> Result<usize> {
|
||||
//TODO: check flags for readable
|
||||
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
|
||||
Handle::Audio { flags: _, buffer: _ } => {
|
||||
Handle::Audio { buffer: _ } => {
|
||||
//TODO: audio input?
|
||||
Err(Error::new(EBADF))
|
||||
},
|
||||
Handle::Volume { ref mut offset } => {
|
||||
}
|
||||
Handle::Volume => {
|
||||
let Ok(off) = usize::try_from(off) else {
|
||||
return Ok(0);
|
||||
};
|
||||
//TODO: should we allocate every time?
|
||||
let string = format!("{}", self.volume);
|
||||
let bytes = string.as_bytes();
|
||||
let bytes = format!("{}", self.volume).into_bytes();
|
||||
let src = bytes.get(off..).unwrap_or(&[]);
|
||||
let len = src.len().min(buf.len());
|
||||
buf[..len].copy_from_slice(&src[..len]);
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() && *offset + i < bytes.len() {
|
||||
buf[i] = bytes[*offset + i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
*offset += i;
|
||||
Ok(Some(i))
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
|
||||
fn write(
|
||||
&mut self,
|
||||
id: usize,
|
||||
buf: &[u8],
|
||||
offset: u64,
|
||||
_flags: u32,
|
||||
_ctx: &CallerCtx,
|
||||
) -> Result<usize> {
|
||||
//TODO: check flags for writable
|
||||
match self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
|
||||
Handle::Audio { ref flags, ref mut buffer } => {
|
||||
Handle::Audio { ref mut buffer } => {
|
||||
if buffer.len() >= HANDLE_BUFFER_SIZE {
|
||||
if flags & O_NONBLOCK > 0 {
|
||||
Err(Error::new(EWOULDBLOCK))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
Err(Error::new(EWOULDBLOCK))
|
||||
} else {
|
||||
let mut i = 0;
|
||||
while i + 4 <= buf.len() {
|
||||
buffer.push_back((
|
||||
(buf[i] as i16) | ((buf[i + 1] as i16) << 8),
|
||||
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8)
|
||||
(buf[i + 2] as i16) | ((buf[i + 3] as i16) << 8),
|
||||
));
|
||||
|
||||
i += 4;
|
||||
}
|
||||
|
||||
Ok(Some(i))
|
||||
Ok(i)
|
||||
}
|
||||
},
|
||||
Handle::Volume { ref mut offset } => {
|
||||
}
|
||||
Handle::Volume => {
|
||||
//TODO: support other offsets?
|
||||
if *offset == 0 {
|
||||
if offset == 0 {
|
||||
let value = str::from_utf8(buf)
|
||||
.map_err(|_| Error::new(EINVAL))?
|
||||
.trim()
|
||||
@@ -144,14 +149,13 @@ impl SchemeBlockMut for AudioScheme {
|
||||
.map_err(|_| Error::new(EINVAL))?;
|
||||
if value >= 0 && value <= 100 {
|
||||
self.volume = value;
|
||||
*offset += buf.len();
|
||||
Ok(Some(buf.len()))
|
||||
Ok(buf.len())
|
||||
} else {
|
||||
Err(Error::new(EINVAL))
|
||||
}
|
||||
} else {
|
||||
// EOF
|
||||
Ok(Some(0))
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user