summaryrefslogtreecommitdiff
path: root/kernel/src/generic/evdev.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/generic/evdev.cpp')
-rw-r--r--kernel/src/generic/evdev.cpp185
1 files changed, 185 insertions, 0 deletions
diff --git a/kernel/src/generic/evdev.cpp b/kernel/src/generic/evdev.cpp
new file mode 100644
index 0000000..b7bb4c1
--- /dev/null
+++ b/kernel/src/generic/evdev.cpp
@@ -0,0 +1,185 @@
+#include <cstdint>
+#include <generic/evdev.hpp>
+#include <generic/vfs.hpp>
+#include <klibc/string.hpp>
+#include <generic/lock/mutex.hpp>
+#include <generic/pmm.hpp>
+#include <generic/hhdm.hpp>
+#include <utils/align.hpp>
+#include <utils/errno.hpp>
+#include <utils/assert.hpp>
+
+locks::mutex evdev_lock;
+evdev::evdev_node evroot_node = {};
+evdev::evdev_node* evhead_node = nullptr;
+std::uint32_t evdev_ptr = 0;
+
+evdev::evdev_node* evdev_lookup(char* path) {
+ evdev::evdev_node* current = evhead_node;
+ while(current) {
+ if(klibc::strcmp(current->name, path) == 0) {
+ return current;
+ }
+ }
+ return nullptr;
+}
+
+int __bitmap_size(int c) {
+ return ALIGNUP(c,8) / 8;
+}
+
+bool evdev_poll(file_descriptor* file, vfs_poll_type type) {
+ evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer);
+ assert(node->main_ring, "say gex !!!11!11151");
+ if(type == vfs_poll_type::pollin) {
+ return node->main_ring->is_not_empty(file->other.queue, file->other.cycle);
+ } else if(type == vfs_poll_type::pollout) {
+ return true;
+ }
+ return false;
+}
+
+std::int32_t evdev_ioctl(file_descriptor* file, std::uint64_t req, void* arg) {
+
+ evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer);
+
+ std::uint64_t size = _IOC_SIZE(req);
+
+ if (_IOC_DIR(req) == _IOC_READ && (_IOC_NR(req) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
+ switch(_IOC_NR(req) & EV_MAX) {
+ case 0:
+ klibc::memcpy(arg,node->ev_bitmap->pool,__bitmap_size(EV_MAX));
+ return 0;
+ }
+ assert(0,"doing req %d",_IOC_NR(req) & EV_MAX);
+ } else {
+ switch(EVIOC_MASK_SIZE(req)) {
+ case EVIOCGNAME(0):
+ klibc::memcpy(arg, node->name, size > (std::uint64_t)klibc::strlen(node->name) ? size : (std::uint64_t)klibc::strlen(node->name));
+ return 0;
+ };
+ }
+
+ assert(0, "ioctl req 0x%p arg 0x%p path %s rev 0x%p",EVIOC_MASK_SIZE(req),arg,node->path,_IOC_NR(req) & EV_MAX);
+ return -EFAULT;
+}
+
+signed long evdev_read(file_descriptor* file, void* buffer, std::size_t count) {
+ evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer);
+ assert(node->main_ring,"FAFASF");
+
+ return node->main_ring->receive((input_event*)buffer, count, &file->other.cycle, &file->other.queue);
+}
+
+void evdev::submit(int num, input_event event) {
+ evdev_lock.lock();
+ evdev::evdev_node* node = evhead_node;
+ while(node) {
+ if(node->num == num)
+ break;
+ }
+ assert(node, "hlehlpehspgfdkjfs");
+ assert(node->main_ring,"ffff");
+
+ node->main_ring->send(event);
+}
+
+int evdev::create(char* name, int type) {
+
+ evdev_lock.lock();
+ evdev::evdev_node* new_node = (evdev::evdev_node*)(pmm::freelist::alloc_4k() + etc::hhdm());
+ new_node->main_ring = new utils::ring_buffer<input_event>(256);
+
+ if(type == EVDEV_TYPE_KEYBOARD) {
+ new_node->ev_bitmap = new utils::bitmap(EV_MAX + 1);
+ new_node->ev_bitmap->set(EV_KEY);
+ new_node->ev_bitmap->set(EV_REP);
+ } else if(type == EVDEV_TYPE_MOUSE) {
+ new_node->ev_bitmap = new utils::bitmap(EV_MAX + 1);
+ new_node->ev_bitmap->set(EV_REL);
+ new_node->ev_bitmap->set(EV_SYN);
+ }
+
+ new_node->num = ++evdev_ptr;
+ klibc::__printfbuf(new_node->path, 256, "/event%d\r\n",new_node->num);
+ klibc::memcpy(new_node->name, name, klibc::strlen(name));
+
+ new_node->type = type;
+ new_node->next = evhead_node;
+ evhead_node = new_node;
+ return new_node->num;
+}
+
+std::int32_t evdev_readlink(filesystem* fs, char* path, char* buffer) {
+ (void)fs;
+ (void)path;
+ (void)buffer;
+ return -EINVAL;
+}
+
+std::int32_t evdev_create(filesystem* fs, char* path, vfs_file_type type, std::uint32_t mode) {
+ (void)fs;
+ (void)path;
+ (void)type;
+ (void)mode;
+ return -ENOTSUP;
+}
+
+signed long evdev_write(file_descriptor* file, void* buffer, std::size_t count) {
+ (void)file;
+ (void)buffer;
+ (void)count;
+ return -EACCES;
+}
+
+std::int32_t evdev_stat(file_descriptor* file, stat* out) {
+ evdev::evdev_node* node = (evdev::evdev_node*)(file->fs_specific.tmpfs_pointer);
+
+ klibc::memset(out, 0, sizeof(stat));
+
+ if(node->is_root) {
+ out->st_mode = S_IFDIR | 0666;
+ return 0;
+ }
+
+ out->st_size = 0;
+ out->st_blksize = 0;
+ out->st_blocks = 0;
+ out->st_mode = S_IFCHR | 0666;
+ out->st_ino = node->num;
+ return 0;
+}
+
+std::int32_t evdev_open(filesystem* fs, void* file_desc, char* path, bool is_directory) {
+
+ file_descriptor* fd = (file_descriptor*)file_desc;
+
+ if(klibc::strcmp(path, "/") == 0) {
+ fd->fs_specific.tmpfs_pointer = (std::uint64_t)&evroot_node;
+ return 0;
+ }
+
+ evdev_lock.lock();
+
+ if(is_directory)
+ return -EISDIR;
+
+ evdev::evdev_node* node = evdev_lookup(path);
+ fd->fs_specific.tmpfs_pointer = (std::uint64_t)node;
+ fd->vnode.read = evdev_read;
+ fd->vnode.ioctl = evdev_ioctl;
+ fd->vnode.write = evdev_write;
+ fd->vnode.stat = evdev_stat;
+
+ evdev_lock.unlock();
+ return 0;
+}
+
+void evdev::init_default(vfs::node* node) {
+ evroot_node.is_root = true;
+ klibc::memcpy(node->path, "/dev/input/\0\0", sizeof("/dev/input/\0\0") + 1);
+ node->fs->readlink = evdev_readlink;
+ node->fs->open = evdev_open;
+ node->fs->create = evdev_create;
+
+} \ No newline at end of file