Luna/kernel/src/fs/devices/Framebuffer.cpp
apio 249c79f8a3 Kernel, libc: Add ioctl()
Right now, only the framebuffer supports this system call, to query its dimensions.
2022-11-02 20:59:42 +01:00

74 lines
2.1 KiB
C++

#include "fs/devices/Framebuffer.h"
#include "std/stdio.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "memory/MemoryManager.h"
#include "utils/Addresses.h"
#include "misc/utils.h"
#include "std/errno.h"
#include "bootboot.h"
extern BOOTBOOT bootboot;
extern char fb[1];
#define MAP_FAIL(errno) 0xffffffffffffff00 | (unsigned char)(errno)
extern uint64_t clock_now();
VFS::Node* FramebufferDevice::create_new(const char* devname)
{
VFS::Node* dev = new VFS::Node;
dev->write_func = FramebufferDevice::write;
dev->mmap_func = FramebufferDevice::mmap;
dev->ioctl_func = FramebufferDevice::ioctl;
dev->inode = 0;
dev->length = 0;
dev->type = VFS_DEVICE;
dev->flags = 0;
dev->uid = dev->gid = 0;
dev->mode = 0222;
dev->atime = dev->ctime = dev->mtime = clock_now();
strncpy(dev->name, devname, sizeof(dev->name));
return dev;
}
uintptr_t FramebufferDevice::mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset)
{
if (!node) return -1;
int real_prot = prot & ~(MAP_AS_OWNED_BY_TASK);
if(round_down_to_nearest_page(offset) != (uintptr_t)offset)
{
return MAP_FAIL(EINVAL);
}
if((size + offset) > bootboot.fb_size)
{
return MAP_FAIL(ERANGE); // FIXME: Should probably be EOVERFLOW.
}
MemoryManager::map_several_pages(bootboot.fb_ptr + offset, addr, Utilities::get_blocks_from_size(PAGE_SIZE, size), real_prot);
return addr;
}
ssize_t FramebufferDevice::write(VFS::Node* node, size_t offset, size_t size, const char* buffer)
{
if (!node) return -1;
if((size + offset) > (uint64_t)bootboot.fb_size)
{
size = (uint64_t)bootboot.fb_size - offset;
}
memcpy(fb + offset, buffer, size);
return (ssize_t)size;
}
#define FB_GET_WIDTH 0
#define FB_GET_HEIGHT 1
long FramebufferDevice::ioctl(VFS::Node* node, int cmd, uintptr_t)
{
if (!node) return -1;
switch(cmd)
{
case FB_GET_WIDTH: return (long)bootboot.fb_width;
case FB_GET_HEIGHT: return (long)bootboot.fb_height;
default: return -EINVAL;
}
}