Skip to content

Commit

Permalink
kernel: Add initial mouse driver
Browse files Browse the repository at this point in the history
  • Loading branch information
mintsuki committed Jan 11, 2024
1 parent ce67d82 commit 91e59ac
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 0 deletions.
2 changes: 2 additions & 0 deletions kernel/main.v
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import dev.serial
import dev.streams
import dev.ahci
import dev.random
import dev.mouse
import syscall.table
import socket
import time
Expand Down Expand Up @@ -60,6 +61,7 @@ fn kmain_thread() {
fbdev.register_driver(simple.get_driver())
console.initialise()
serial.initialise()
mouse.initialise()

$if !prod {
ata.initialise()
Expand Down
220 changes: 220 additions & 0 deletions kernel/modules/dev/mouse/mouse.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
module mouse

import resource
import stat
import fs
import file
import event
import event.eventstruct
import klock
import katomic
import errno
import x86.kio
import x86.apic
import x86.idt

@[inline]
fn wait(t int) {
mut timeout := 100000;

if t == 0 {
for ; timeout != 0; timeout-- {
if kio.port_in<u8>(0x64) & (1 << 0) != 0 {
return
}
}
} else {
for ; timeout != 0; timeout-- {
if kio.port_in<u8>(0x64) & (1 << 1) == 0 {
return
}
}
}
}

@[inline]
fn write(val u8) {
wait(1)
kio.port_out<u8>(0x64, 0xd4)
wait(1)
kio.port_out<u8>(0x60, val)
}

@[inline]
fn read() u8 {
wait(0)
return kio.port_in<u8>(0x60)
}

struct MousePacket {
pub mut:
flags u8
x_mov u32
y_mov u32
}

struct Mouse {
pub mut:
stat stat.Stat
refcount int
l klock.Lock
event eventstruct.Event
status int
can_mmap bool

packet_avl bool
packet MousePacket
}

fn (mut this Mouse) mmap(page u64, flags int) voidptr {
panic('')
}

fn (mut this Mouse) read(_handle voidptr, buf voidptr, loc u64, count u64) ?i64 {
if count != sizeof(MousePacket) {
errno.set(errno.einval)
return none
}

handle := unsafe { &file.Handle(_handle) }

mouse_res.l.acquire()

for mouse_res.packet_avl == false {
mouse_res.l.release()

if handle.flags & resource.o_nonblock != 0 {
errno.set(errno.ewouldblock)
return none
}

mut events := [&mouse_res.event]
event.await(mut events, true) or {}

mouse_res.l.acquire()
}

unsafe {
C.memcpy(buf, &mouse_res.packet, sizeof(MousePacket))
}
mouse_res.packet_avl = false

mouse_res.status &= ~int(file.pollin)

mouse_res.l.release()

return sizeof(MousePacket)
}

fn (mut this Mouse) write(handle voidptr, buf voidptr, loc u64, count u64) ?i64 {
return i64(count)
}

fn (mut this Mouse) ioctl(handle voidptr, request u64, argp voidptr) ?int {
return resource.default_ioctl(handle, request, argp)
}

fn (mut this Mouse) unref(handle voidptr) ? {
katomic.dec(this.refcount)
}

fn (mut this Mouse) link(handle voidptr) ? {
katomic.inc(this.stat.nlink)
}

fn (mut this Mouse) unlink(handle voidptr) ? {
katomic.dec(this.stat.nlink)
}

fn (mut this Mouse) grow(handle voidptr, new_size u64) ? {
}

__global (
mouse_res Mouse
ps2_mouse_vector u8
)

fn handler() {
mut handler_cycle := 0
mut current_packet := MousePacket{}
mut discard_packet := false

for {
mut events := [&int_events[ps2_mouse_vector]]
event.await(mut events, true) or {}

// we will get some spurious packets at the beginning and they will screw
// up the alignment of the handler cycle so just ignore everything in
// the first 250 milliseconds after boot
if monotonic_clock.tv_sec == 0 && monotonic_clock.tv_nsec < 250000000 {
kio.port_in<u8>(0x60)
}

match handler_cycle {
0 {
current_packet.flags = read()
handler_cycle++
if current_packet.flags & (1 << 6) != 0 || current_packet.flags & (1 << 7) != 0 {
discard_packet = true
}
if current_packet.flags & (1 << 3) == 0 {
discard_packet = true
}
continue
}
1 {
current_packet.x_mov = read()
handler_cycle++
continue
}
2 {
current_packet.y_mov = read()
handler_cycle = 0

if discard_packet {
discard_packet = false
continue
}
}
else {}
}

if current_packet.flags & (1 << 4) != 0 {
current_packet.x_mov = u32(i8(u8(current_packet.x_mov)))
}
if current_packet.flags & (1 << 5) != 0 {
current_packet.y_mov = u32(i8(u8(current_packet.y_mov)))
}

mouse_res.l.acquire()
mouse_res.packet = current_packet
mouse_res.packet_avl = true
mouse_res.l.release()

mouse_res.status |= file.pollin
event.trigger(mut mouse_res.event, false)
}
}

pub fn initialise() {
write(0xf6)
read()

write(0xf4)
read()

mouse_res.stat.size = 0
mouse_res.stat.blocks = 0
mouse_res.stat.blksize = 512;
mouse_res.stat.rdev = resource.create_dev_id()
mouse_res.stat.mode = 0o644 | stat.ifchr

mouse_res.status |= file.pollout

fs.devtmpfs_add_device(&mouse_res, 'mouse')

ps2_mouse_vector = idt.allocate_vector()
apic.io_apic_set_irq_redirect(cpu_locals[0].lapic_id, ps2_mouse_vector, 12, true)

spawn handler()
}

0 comments on commit 91e59ac

Please sign in to comment.