Luna/kernel/src/fs/devices/FramebufferDevice.cpp

79 lines
2.1 KiB
C++

#include "fs/devices/FramebufferDevice.h"
#include "arch/MMU.h"
#include "memory/SharedMemory.h"
#include "video/Framebuffer.h"
#include <bits/ioctl-defs.h>
#include <luna/CString.h>
Result<void> FramebufferDevice::create()
{
auto device = (SharedPtr<Device>)TRY(make_shared<FramebufferDevice>());
return DeviceRegistry::register_special_device(DeviceRegistry::Framebuffer, 0, device, 0600);
}
Result<usize> FramebufferDevice::read(u8*, usize, usize) const
{
return 0;
}
Result<usize> FramebufferDevice::write(const u8* buf, usize offset, usize length)
{
if ((offset + length) > size()) length = size() - offset;
memcpy(Framebuffer::ptr() + offset, buf, length);
return length;
}
Result<u64> FramebufferDevice::query_shared_memory(off_t offset, usize count)
{
if (offset + (count * ARCH_PAGE_SIZE) > Framebuffer::size()) return err(EINVAL);
if (!m_shmid.has_value())
{
u64 shmid = TRY(SharedMemory::create(Framebuffer::ptr() + offset, offset, count));
m_shmid = shmid;
auto* shm = g_shared_memory_map.try_get_ref(shmid);
shm->device = SharedPtr<Device> { this };
return shmid;
}
auto* shm = g_shared_memory_map.try_get_ref(*m_shmid);
if (!shm)
{
m_shmid = {};
return query_shared_memory(offset, count);
}
if (shm->offset > offset)
{
TRY(shm->grow_backward(Framebuffer::ptr() + offset, (shm->offset - offset) / ARCH_PAGE_SIZE));
}
if (shm->frames.size() < count)
{
TRY(shm->grow_forward(Framebuffer::ptr() + offset + (shm->frames.size() * ARCH_PAGE_SIZE),
count - shm->frames.size()));
}
return *m_shmid;
}
usize FramebufferDevice::size() const
{
return Framebuffer::size();
}
bool FramebufferDevice::will_block_if_read() const
{
return false;
}
Result<u64> FramebufferDevice::ioctl(int request, void*)
{
switch (request)
{
case FB_GET_WIDTH: return (u64)Framebuffer::width();
case FB_GET_HEIGHT: return (u64)Framebuffer::height();
case FB_GET_SCANLINE: return (u64)Framebuffer::scanline();
default: return err(EINVAL);
}
}