-
Notifications
You must be signed in to change notification settings - Fork 13
/
parrot.rs
55 lines (47 loc) · 1.58 KB
/
parrot.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//! Example kernel module that creates a device, /dev/parrot, that when read
//! from will generate an animation.
use core::{cmp::min, time::Duration};
use kernel::{
delay::coarse_sleep,
file::{File, Operations},
io_buffer::IoBufferWriter,
miscdev::Registration,
prelude::*,
};
mod frames;
use frames::{calc_frame_and_offset, FRAMES};
module! {
type: ParrotSafe,
name: "party_parrot",
author: "John Baublitz <john.m.baublitz@gmail.com>",
description: "Get the party started",
license: "GPL",
}
struct ParrotSafe(Pin<Box<Registration<ParrotOps>>>);
impl kernel::Module for ParrotSafe {
fn init(_: &'static CStr, _: &'static ThisModule) -> Result<Self> {
Ok(ParrotSafe(Registration::new_pinned(fmt!("parrot"), ())?))
}
}
struct ParrotOps;
#[vtable]
impl Operations for ParrotOps {
fn open(_: &Self::OpenData, _: &File) -> Result<Self::Data> {
Ok(())
}
fn read(_: (), _: &File, buf: &mut impl IoBufferWriter, offset: u64) -> Result<usize> {
if buf.len() < 1 {
pr_info!("parrot device driver requires a buffer of at least 1 byte");
return Err(EINVAL);
}
let (frame, frame_offset) = calc_frame_and_offset(offset);
let frame = FRAMES.get(frame).ok_or(EIO)?;
let offset_usize: usize = frame_offset.try_into()?;
let s = &frame.as_bytes()[offset_usize..][..min(frame.len() - offset_usize, buf.len())];
buf.write_slice(s)?;
if offset_usize + s.len() == frame.len() {
coarse_sleep(Duration::from_millis(50));
}
Ok(s.len())
}
}