Kernel, libc: Add ioctl()
Right now, only the framebuffer supports this system call, to query its dimensions.
This commit is contained in:
parent
feab66c0d3
commit
249c79f8a3
@ -34,6 +34,8 @@ struct Descriptor
|
||||
|
||||
uintptr_t mmap(uintptr_t addr, size_t size, int prot, off_t offset);
|
||||
|
||||
long ioctl(int cmd, uintptr_t arg);
|
||||
|
||||
void open(VFS::Node* node, bool can_read, bool can_write, bool able_to_block, bool close_on_exec);
|
||||
|
||||
int seek(long offset);
|
||||
|
@ -24,6 +24,7 @@ namespace VFS
|
||||
typedef int (*node_block)(Node*);
|
||||
typedef Node* (*node_readdir)(Node*, long);
|
||||
typedef uintptr_t (*node_mmap)(Node*, uintptr_t, size_t, int, off_t);
|
||||
typedef long (*node_ioctl)(Node*, int, uintptr_t);
|
||||
|
||||
struct Node
|
||||
{
|
||||
@ -47,6 +48,7 @@ namespace VFS
|
||||
node_write write_func;
|
||||
node_block block_func;
|
||||
node_mmap mmap_func;
|
||||
node_ioctl ioctl_func;
|
||||
Node* link;
|
||||
};
|
||||
|
||||
|
@ -8,4 +8,6 @@ namespace FramebufferDevice
|
||||
ssize_t write(VFS::Node* node, size_t offset, size_t size, const char* buffer);
|
||||
|
||||
uintptr_t mmap(VFS::Node* node, uintptr_t addr, size_t size, int prot, off_t offset);
|
||||
|
||||
long ioctl(VFS::Node* node, int cmd, uintptr_t arg);
|
||||
}
|
@ -30,6 +30,7 @@
|
||||
#define SYS_setuid 24
|
||||
#define SYS_setgid 25
|
||||
#define SYS_umask 26
|
||||
#define SYS_ioctl 27
|
||||
|
||||
struct stat;
|
||||
struct pstat;
|
||||
@ -68,3 +69,4 @@ void sys_dup2(Context* context, int fd, int fd2);
|
||||
void sys_setuid(Context* context, int new_uid, int new_euid);
|
||||
void sys_setgid(Context* context, int new_gid, int new_egid);
|
||||
void sys_umask(Context* context, mode_t cmask);
|
||||
void sys_ioctl(Context* context, int fd, int request, uintptr_t arg);
|
@ -45,6 +45,12 @@ uintptr_t Descriptor::mmap(uintptr_t addr, size_t size, int prot, off_t offset)
|
||||
return m_node->mmap_func(m_node, addr, size, prot, offset);
|
||||
}
|
||||
|
||||
long Descriptor::ioctl(int cmd, uintptr_t arg)
|
||||
{
|
||||
if(!m_node->ioctl_func) return MAP_FAIL(ENOTSUP);
|
||||
return m_node->ioctl_func(m_node, cmd, arg);
|
||||
}
|
||||
|
||||
int Descriptor::seek(long offset)
|
||||
{
|
||||
if (m_node->type == VFS_FILE && (uint64_t)offset > m_node->length)
|
||||
|
@ -20,6 +20,7 @@ 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;
|
||||
@ -57,3 +58,17 @@ ssize_t FramebufferDevice::write(VFS::Node* node, size_t offset, size_t size, co
|
||||
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;
|
||||
}
|
||||
}
|
@ -40,6 +40,7 @@ void Syscall::entry(Context* context)
|
||||
case SYS_setuid: sys_setuid(context, (int)context->rdi, (int)context->rsi); break;
|
||||
case SYS_setgid: sys_setgid(context, (int)context->rdi, (int)context->rsi); break;
|
||||
case SYS_umask: sys_umask(context, (mode_t)context->rdi); break;
|
||||
case SYS_ioctl: sys_ioctl(context, (int)context->rdi, (int)context->rsi, (uintptr_t)context->rdx); break;
|
||||
default: context->rax = -ENOSYS; break;
|
||||
}
|
||||
VMM::exit_syscall_context();
|
||||
|
@ -358,12 +358,7 @@ void sys_dup2(Context* context, int fd, int fd2)
|
||||
context->rax = -err;
|
||||
return;
|
||||
}
|
||||
if (!file1->is_open())
|
||||
{
|
||||
context->rax = -EBADF;
|
||||
return;
|
||||
}
|
||||
Descriptor* file2 = Scheduler::current_task()->descriptor_from_fd(fd2, err);
|
||||
Descriptor* file2 = Scheduler::current_task()->descriptor_from_fd(fd2, err); // FIXME: This will return EBADF if fd2 is not open, but we want to replace it with fd1 if it is not open.
|
||||
if (!file2)
|
||||
{
|
||||
context->rax = -err;
|
||||
@ -381,3 +376,16 @@ void sys_umask(Context* context, mode_t cmask)
|
||||
context->rax = current_task->umask;
|
||||
current_task->umask = cmask;
|
||||
}
|
||||
|
||||
void sys_ioctl(Context* context, int fd, int cmd, uintptr_t arg)
|
||||
{
|
||||
int err;
|
||||
Descriptor* file = Scheduler::current_task()->descriptor_from_fd(fd, err);
|
||||
if (!file)
|
||||
{
|
||||
context->rax = -err;
|
||||
return;
|
||||
}
|
||||
kinfoln("ioctl(): fd %d, cmd %d, arg %lu", fd, cmd, arg);
|
||||
context->rax = file->ioctl(cmd, arg);
|
||||
}
|
23
libs/libc/include/sys/ioctl.h
Normal file
23
libs/libc/include/sys/ioctl.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _SYS_IOCTL_H
|
||||
#define _SYS_IOCTL_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Get the width of a framebuffer device. */
|
||||
#define FB_GET_WIDTH 0
|
||||
/* Get the height of a framebuffer device. */
|
||||
#define FB_GET_HEIGHT 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Perform an arbitrary operation on an open file descriptor. Many operations are device-specific. */
|
||||
int ioctl(int fd, int cmd, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -28,5 +28,6 @@
|
||||
#define SYS_setuid 24
|
||||
#define SYS_setgid 25
|
||||
#define SYS_umask 26
|
||||
#define SYS_ioctl 27
|
||||
|
||||
#endif
|
17
libs/libc/src/sys/ioctl.cpp
Normal file
17
libs/libc/src/sys/ioctl.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <luna/syscall.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int ioctl(int fd, int cmd, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, cmd);
|
||||
long result = __lc_fast_syscall3(SYS_ioctl, fd, cmd, va_arg(ap, uintptr_t));
|
||||
va_end(ap);
|
||||
return (int)result;
|
||||
}
|
||||
}
|
@ -41,6 +41,7 @@ extern "C" long syscall(long number, ...)
|
||||
case SYS_seek:
|
||||
case SYS_write:
|
||||
case SYS_read:
|
||||
case SYS_ioctl:
|
||||
case SYS_mprotect:
|
||||
case SYS_waitpid: {
|
||||
arg arg0 = va_arg(ap, arg);
|
||||
|
Loading…
Reference in New Issue
Block a user