Created
May 3, 2020 00:36
-
-
Save RKennedy9064/de8000f8f63e14d9aa198240d7d9effb to your computer and use it in GitHub Desktop.
Code for async mouse task
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern "x86-interrupt" fn mouse_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { | |
let mut port = PortReadOnly::new(0x60); | |
let packet = unsafe { port.read() }; | |
crate::task::mouse::add_mouse_packet(packet); | |
unsafe { | |
PICS.lock() | |
.notify_end_of_interrupt(InterruptIndex::Mouse.into()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub fn init() { | |
// New code | |
task::mouse::init(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// New code | |
executor.spawn(Task::new(mouse::process_packets())); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// New code in task/mod.rs | |
pub mod mouse; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// New code in task/mouse.rs | |
use crate::println; | |
use conquer_once::spin::{Lazy, OnceCell}; | |
use core::{ | |
pin::Pin, | |
task::{Context, Poll}, | |
}; | |
use crossbeam_queue::ArrayQueue; | |
use futures_util::{ | |
stream::{Stream, StreamExt}, | |
task::AtomicWaker, | |
}; | |
use ps2_mouse::{Mouse, MouseState}; | |
use spinning_top::Spinlock; | |
static WAKER: AtomicWaker = AtomicWaker::new(); | |
pub static MOUSE: Lazy<Spinlock<Mouse>> = Lazy::new(|| Spinlock::new(Mouse::new())); | |
static MOUSE_PACKET_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit(); | |
pub(crate) fn add_mouse_packet(packet: u8) { | |
if let Ok(queue) = MOUSE_PACKET_QUEUE.try_get() { | |
if let Err(_) = queue.push(packet) { | |
println!("WARNING: mouse packet queue full; dropping mouse input"); | |
} else { | |
WAKER.wake(); | |
} | |
} else { | |
println!("WARNING: mouse packet queue uninitialized"); | |
} | |
} | |
pub(crate) fn init() { | |
let mut mouse = MOUSE.lock(); | |
mouse.init().expect("failed to initialize mouse"); | |
mouse.set_on_complete(on_complete); | |
} | |
pub struct MousePacketStream { | |
_private: (), | |
} | |
impl MousePacketStream { | |
pub fn new() -> MousePacketStream { | |
// Default mouse settings generate packets at 100 packets per second/ | |
// This will overflow quickly if the queue is set too low. | |
MOUSE_PACKET_QUEUE | |
.try_init_once(|| ArrayQueue::new(500)) | |
.expect("MousePacketStream::new should only be called once"); | |
MousePacketStream { _private: () } | |
} | |
} | |
impl Stream for MousePacketStream { | |
type Item = u8; | |
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<u8>> { | |
let queue = MOUSE_PACKET_QUEUE | |
.try_get() | |
.expect("mouse state queue not initialized"); | |
if let Ok(packet) = queue.pop() { | |
return Poll::Ready(Some(packet)); | |
} | |
WAKER.register(&cx.waker()); | |
match queue.pop() { | |
Ok(packet) => { | |
WAKER.take(); | |
Poll::Ready(Some(packet)) | |
} | |
Err(crossbeam_queue::PopError) => Poll::Pending, | |
} | |
} | |
} | |
fn on_complete(mouse_state: MouseState) { | |
use crate::serial_println; | |
serial_println!("{:?}", mouse_state); | |
} | |
pub async fn process_packets() { | |
let mut mouse = MOUSE.lock(); | |
let mut packets = MousePacketStream::new(); | |
while let Some(packet) = packets.next().await { | |
mouse.process_packet(packet); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment