]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
refactor: decouple DevFS from TTY/PTY drivers via device registration API
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 07:01:14 +0000 (04:01 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:44:55 +0000 (23:44 -0300)
Added devfs_register_device() API so device drivers register their own
fs_node_t with DevFS. DevFS is now a generic device registry that
dispatches through function pointers — it no longer includes tty.h or
pty.h and has zero knowledge of TTY/PTY internals.

- tty.c: registers /dev/console and /dev/tty with VFS-compatible wrappers
- pty.c: registers /dev/ptmx and /dev/pts (with finddir/readdir moved
  from devfs.c)
- devfs.c: only owns built-in devices (null, zero, random, urandom);
  all other devices come from the registry

This enables any future driver to register device nodes without
modifying devfs.c.

include/devfs.h
src/kernel/devfs.c
src/kernel/pty.c
src/kernel/tty.c

index ba6256df407255a45ef448e156378ce72eaef145..24d475bf473d8427f4160f81c575c066d7331cbd 100644 (file)
@@ -3,6 +3,16 @@
 
 #include "fs.h"
 
+#define DEVFS_MAX_DEVICES 32
+
 fs_node_t* devfs_create_root(void);
 
+/*
+ * Register a device node with devfs.
+ * The caller owns the fs_node_t storage (must remain valid for the
+ * lifetime of the device).  DevFS stores only a pointer.
+ * Returns 0 on success, -1 if the registry is full.
+ */
+int devfs_register_device(fs_node_t *node);
+
 #endif
index 444f17663178cb0c3649c5225afd99021a5f6b56..4c815f85c0c13b622ad17adc585a50db99816bfb 100644 (file)
@@ -1,8 +1,6 @@
 #include "devfs.h"
 
 #include "errno.h"
-#include "tty.h"
-#include "pty.h"
 #include "utils.h"
 
 extern uint32_t get_tick_count(void);
@@ -16,12 +14,19 @@ static fs_node_t g_dev_null;
 static fs_node_t g_dev_zero;
 static fs_node_t g_dev_random;
 static fs_node_t g_dev_urandom;
-static fs_node_t g_dev_console;
-static fs_node_t g_dev_tty;
-static fs_node_t g_dev_ptmx;
-static fs_node_t g_dev_pts_dir;
 static uint32_t g_devfs_inited = 0;
 
+/* --- Device registry --- */
+static fs_node_t* g_registered[DEVFS_MAX_DEVICES];
+static int g_registered_count = 0;
+
+int devfs_register_device(fs_node_t *node) {
+    if (!node) return -1;
+    if (g_registered_count >= DEVFS_MAX_DEVICES) return -1;
+    g_registered[g_registered_count++] = node;
+    return 0;
+}
+
 static uint32_t prng_state = 0x12345678;
 
 static uint32_t dev_null_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
@@ -90,56 +95,6 @@ static uint32_t dev_random_write(fs_node_t* node, uint32_t offset, uint32_t size
     return size;
 }
 
-static uint32_t dev_console_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
-    (void)node;
-    (void)offset;
-    int rc = tty_read_kbuf(buffer, size);
-    if (rc < 0) return 0;
-    return (uint32_t)rc;
-}
-
-static uint32_t dev_console_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
-    (void)node;
-    (void)offset;
-    int rc = tty_write_kbuf((const uint8_t*)buffer, size);
-    if (rc < 0) return 0;
-    return (uint32_t)rc;
-}
-
-static uint32_t dev_tty_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
-    (void)node;
-    (void)offset;
-    int rc = tty_read_kbuf(buffer, size);
-    if (rc < 0) return 0;
-    return (uint32_t)rc;
-}
-
-static uint32_t dev_tty_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
-    (void)node;
-    (void)offset;
-    int rc = tty_write_kbuf((const uint8_t*)buffer, size);
-    if (rc < 0) return 0;
-    return (uint32_t)rc;
-}
-
-static uint32_t dev_ptmx_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
-    (void)offset;
-    int idx = pty_ino_to_idx(node->inode);
-    if (idx < 0) idx = 0;
-    int rc = pty_master_read_idx(idx, buffer, size);
-    if (rc < 0) return 0;
-    return (uint32_t)rc;
-}
-
-static uint32_t dev_ptmx_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
-    (void)offset;
-    int idx = pty_ino_to_idx(node->inode);
-    if (idx < 0) idx = 0;
-    int rc = pty_master_write_idx(idx, buffer, size);
-    if (rc < 0) return 0;
-    return (uint32_t)rc;
-}
-
 static struct fs_node* devfs_finddir_impl(struct fs_node* node, const char* name) {
     (void)node;
     if (!name || name[0] == 0) return 0;
@@ -148,24 +103,10 @@ static struct fs_node* devfs_finddir_impl(struct fs_node* node, const char* name
     if (strcmp(name, "zero") == 0) return &g_dev_zero;
     if (strcmp(name, "random") == 0) return &g_dev_random;
     if (strcmp(name, "urandom") == 0) return &g_dev_urandom;
-    if (strcmp(name, "console") == 0) return &g_dev_console;
-    if (strcmp(name, "tty") == 0) return &g_dev_tty;
-    if (strcmp(name, "ptmx") == 0) return &g_dev_ptmx;
-    if (strcmp(name, "pts") == 0) return &g_dev_pts_dir;
-    return 0;
-}
 
-static struct fs_node* devfs_pts_finddir_impl(struct fs_node* node, const char* name) {
-    (void)node;
-    if (!name || name[0] == 0) return 0;
-    int count = pty_pair_count();
-    for (int i = 0; i < count; i++) {
-        char num[4];
-        num[0] = '0' + (char)i;
-        num[1] = '\0';
-        if (strcmp(name, num) == 0) {
-            return pty_get_slave_node(i);
-        }
+    for (int i = 0; i < g_registered_count; i++) {
+        if (strcmp(g_registered[i]->name, name) == 0)
+            return g_registered[i];
     }
     return 0;
 }
@@ -175,18 +116,16 @@ static int devfs_readdir_impl(struct fs_node* node, uint32_t* inout_index, void*
     if (!inout_index || !buf) return -1;
     if (buf_len < sizeof(struct vfs_dirent)) return -1;
 
-    static const struct { const char* name; uint32_t ino; uint8_t type; } devs[] = {
+    /* Built-in devices (owned by devfs) */
+    static const struct { const char* name; uint32_t ino; uint8_t type; } builtins[] = {
         { "null",    2,  FS_CHARDEVICE },
         { "zero",    7,  FS_CHARDEVICE },
         { "random",  8,  FS_CHARDEVICE },
         { "urandom", 9,  FS_CHARDEVICE },
-        { "console", 10, FS_CHARDEVICE },
-        { "tty",     3,  FS_CHARDEVICE },
-        { "ptmx",    4,  FS_CHARDEVICE },
-        { "pts",     5,  FS_DIRECTORY },
     };
-    enum { NDEVS = 8 };
+    enum { NBUILTINS = 4 };
 
+    uint32_t total = (uint32_t)(NBUILTINS + g_registered_count);
     uint32_t idx = *inout_index;
     uint32_t cap = buf_len / (uint32_t)sizeof(struct vfs_dirent);
     struct vfs_dirent* ents = (struct vfs_dirent*)buf;
@@ -202,48 +141,17 @@ static int devfs_readdir_impl(struct fs_node* node, uint32_t* inout_index, void*
             e.d_ino = 1; e.d_type = FS_DIRECTORY; strcpy(e.d_name, "..");
         } else {
             uint32_t di = idx - 2;
-            if (di >= NDEVS) break;
-            e.d_ino = devs[di].ino;
-            e.d_type = devs[di].type;
-            strcpy(e.d_name, devs[di].name);
-        }
-
-        e.d_reclen = (uint16_t)sizeof(e);
-        ents[written] = e;
-        written++;
-        idx++;
-    }
-
-    *inout_index = idx;
-    return (int)(written * (uint32_t)sizeof(struct vfs_dirent));
-}
-
-static int devfs_pts_readdir_impl(struct fs_node* node, uint32_t* inout_index, void* buf, uint32_t buf_len) {
-    (void)node;
-    if (!inout_index || !buf) return -1;
-    if (buf_len < sizeof(struct vfs_dirent)) return -1;
-
-    int count = pty_pair_count();
-    uint32_t idx = *inout_index;
-    uint32_t cap = buf_len / (uint32_t)sizeof(struct vfs_dirent);
-    struct vfs_dirent* ents = (struct vfs_dirent*)buf;
-    uint32_t written = 0;
-
-    while (written < cap) {
-        struct vfs_dirent e;
-        memset(&e, 0, sizeof(e));
-
-        if (idx == 0) {
-            e.d_ino = 5; e.d_type = FS_DIRECTORY; strcpy(e.d_name, ".");
-        } else if (idx == 1) {
-            e.d_ino = 1; e.d_type = FS_DIRECTORY; strcpy(e.d_name, "..");
-        } else {
-            int pi = (int)(idx - 2);
-            if (pi >= count) break;
-            e.d_ino = PTY_SLAVE_INO_BASE + (uint32_t)pi;
-            e.d_type = FS_CHARDEVICE;
-            e.d_name[0] = '0' + (char)pi;
-            e.d_name[1] = '\0';
+            if (di >= total) break;
+            if (di < NBUILTINS) {
+                e.d_ino = builtins[di].ino;
+                e.d_type = builtins[di].type;
+                strcpy(e.d_name, builtins[di].name);
+            } else {
+                fs_node_t* rn = g_registered[di - NBUILTINS];
+                e.d_ino = rn->inode;
+                e.d_type = (uint8_t)rn->flags;
+                strcpy(e.d_name, rn->name);
+            }
         }
 
         e.d_reclen = (uint16_t)sizeof(e);
@@ -303,44 +211,6 @@ static void devfs_init_once(void) {
     g_dev_urandom.inode = 9;
     g_dev_urandom.read = &dev_random_read;
     g_dev_urandom.write = &dev_random_write;
-
-    memset(&g_dev_console, 0, sizeof(g_dev_console));
-    strcpy(g_dev_console.name, "console");
-    g_dev_console.flags = FS_CHARDEVICE;
-    g_dev_console.inode = 10;
-    g_dev_console.read = &dev_console_read;
-    g_dev_console.write = &dev_console_write;
-
-    memset(&g_dev_tty, 0, sizeof(g_dev_tty));
-    strcpy(g_dev_tty.name, "tty");
-    g_dev_tty.flags = FS_CHARDEVICE;
-    g_dev_tty.inode = 3;
-    g_dev_tty.length = 0;
-    g_dev_tty.read = &dev_tty_read;
-    g_dev_tty.write = &dev_tty_write;
-    g_dev_tty.open = 0;
-    g_dev_tty.close = 0;
-    g_dev_tty.finddir = 0;
-
-    memset(&g_dev_ptmx, 0, sizeof(g_dev_ptmx));
-    strcpy(g_dev_ptmx.name, "ptmx");
-    g_dev_ptmx.flags = FS_CHARDEVICE;
-    g_dev_ptmx.inode = PTY_MASTER_INO_BASE;
-    g_dev_ptmx.read = &dev_ptmx_read;
-    g_dev_ptmx.write = &dev_ptmx_write;
-
-    memset(&g_dev_pts_dir, 0, sizeof(g_dev_pts_dir));
-    strcpy(g_dev_pts_dir.name, "pts");
-    g_dev_pts_dir.flags = FS_DIRECTORY;
-    g_dev_pts_dir.inode = 5;
-    g_dev_pts_dir.length = 0;
-    g_dev_pts_dir.read = 0;
-    g_dev_pts_dir.write = 0;
-    g_dev_pts_dir.open = 0;
-    g_dev_pts_dir.close = 0;
-    g_dev_pts_dir.finddir = &devfs_pts_finddir_impl;
-    g_dev_pts_dir.readdir = &devfs_pts_readdir_impl;
-
 }
 
 fs_node_t* devfs_create_root(void) {
index 617d62e7ae2d10dd6bd289627b9690f3c5a868fa..52282f9c0036bb412370c01dfdc35c1150d1b883 100644 (file)
@@ -1,5 +1,6 @@
 #include "pty.h"
 
+#include "devfs.h"
 #include "errno.h"
 #include "process.h"
 #include "waitqueue.h"
@@ -101,12 +102,106 @@ static void pty_init_pair(int idx) {
     p->slave_node.write = &pty_slave_write_fn;
 }
 
+/* --- DevFS pts directory callbacks --- */
+
+static fs_node_t g_dev_ptmx_node;
+static fs_node_t g_dev_pts_dir_node;
+
+static uint32_t pty_ptmx_read_fn(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+    (void)offset;
+    int idx = pty_ino_to_idx(node->inode);
+    if (idx < 0) idx = 0;
+    int rc = pty_master_read_idx(idx, buffer, size);
+    if (rc < 0) return 0;
+    return (uint32_t)rc;
+}
+
+static uint32_t pty_ptmx_write_fn(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
+    (void)offset;
+    int idx = pty_ino_to_idx(node->inode);
+    if (idx < 0) idx = 0;
+    int rc = pty_master_write_idx(idx, buffer, size);
+    if (rc < 0) return 0;
+    return (uint32_t)rc;
+}
+
+static struct fs_node* pty_pts_finddir(struct fs_node* node, const char* name) {
+    (void)node;
+    if (!name || name[0] == 0) return 0;
+    int count = pty_pair_count();
+    for (int i = 0; i < count; i++) {
+        char num[4];
+        num[0] = '0' + (char)i;
+        num[1] = '\0';
+        if (strcmp(name, num) == 0) {
+            return pty_get_slave_node(i);
+        }
+    }
+    return 0;
+}
+
+static int pty_pts_readdir(struct fs_node* node, uint32_t* inout_index, void* buf, uint32_t buf_len) {
+    (void)node;
+    if (!inout_index || !buf) return -1;
+    if (buf_len < sizeof(struct vfs_dirent)) return -1;
+
+    int count = pty_pair_count();
+    uint32_t idx = *inout_index;
+    uint32_t cap = buf_len / (uint32_t)sizeof(struct vfs_dirent);
+    struct vfs_dirent* ents = (struct vfs_dirent*)buf;
+    uint32_t written = 0;
+
+    while (written < cap) {
+        struct vfs_dirent e;
+        memset(&e, 0, sizeof(e));
+
+        if (idx == 0) {
+            e.d_ino = 5; e.d_type = FS_DIRECTORY; strcpy(e.d_name, ".");
+        } else if (idx == 1) {
+            e.d_ino = 1; e.d_type = FS_DIRECTORY; strcpy(e.d_name, "..");
+        } else {
+            int pi = (int)(idx - 2);
+            if (pi >= count) break;
+            e.d_ino = PTY_SLAVE_INO_BASE + (uint32_t)pi;
+            e.d_type = FS_CHARDEVICE;
+            e.d_name[0] = '0' + (char)pi;
+            e.d_name[1] = '\0';
+        }
+
+        e.d_reclen = (uint16_t)sizeof(e);
+        ents[written] = e;
+        written++;
+        idx++;
+    }
+
+    *inout_index = idx;
+    return (int)(written * (uint32_t)sizeof(struct vfs_dirent));
+}
+
 void pty_init(void) {
     spinlock_init(&pty_lock);
     memset(g_ptys, 0, sizeof(g_ptys));
     g_pty_count = 0;
     pty_init_pair(0);
     g_pty_count = 1;
+
+    /* Register /dev/ptmx */
+    memset(&g_dev_ptmx_node, 0, sizeof(g_dev_ptmx_node));
+    strcpy(g_dev_ptmx_node.name, "ptmx");
+    g_dev_ptmx_node.flags = FS_CHARDEVICE;
+    g_dev_ptmx_node.inode = PTY_MASTER_INO_BASE;
+    g_dev_ptmx_node.read = &pty_ptmx_read_fn;
+    g_dev_ptmx_node.write = &pty_ptmx_write_fn;
+    devfs_register_device(&g_dev_ptmx_node);
+
+    /* Register /dev/pts directory */
+    memset(&g_dev_pts_dir_node, 0, sizeof(g_dev_pts_dir_node));
+    strcpy(g_dev_pts_dir_node.name, "pts");
+    g_dev_pts_dir_node.flags = FS_DIRECTORY;
+    g_dev_pts_dir_node.inode = 5;
+    g_dev_pts_dir_node.finddir = &pty_pts_finddir;
+    g_dev_pts_dir_node.readdir = &pty_pts_readdir;
+    devfs_register_device(&g_dev_pts_dir_node);
 }
 
 int pty_alloc_pair(void) {
index e7a4d1e384890fb31fb08871cecd8dda545c110d..6a344f28cb51b1c328cbd4f1c1ceecc5c50e5784 100644 (file)
@@ -1,5 +1,6 @@
 #include "tty.h"
 
+#include "devfs.h"
 #include "keyboard.h"
 #include "process.h"
 #include "waitqueue.h"
@@ -375,6 +376,25 @@ static void tty_keyboard_cb(char c) {
     tty_input_char(c);
 }
 
+/* --- DevFS VFS-compatible wrappers --- */
+
+static fs_node_t g_dev_console_node;
+static fs_node_t g_dev_tty_node;
+
+static uint32_t tty_devfs_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+    (void)node; (void)offset;
+    int rc = tty_read_kbuf(buffer, size);
+    if (rc < 0) return 0;
+    return (uint32_t)rc;
+}
+
+static uint32_t tty_devfs_write(fs_node_t* node, uint32_t offset, uint32_t size, const uint8_t* buffer) {
+    (void)node; (void)offset;
+    int rc = tty_write_kbuf(buffer, size);
+    if (rc < 0) return 0;
+    return (uint32_t)rc;
+}
+
 void tty_init(void) {
     spinlock_init(&tty_lock);
     line_len = 0;
@@ -384,6 +404,24 @@ void tty_init(void) {
     tty_fg_pgrp = 0;
 
     keyboard_set_callback(tty_keyboard_cb);
+
+    /* Register /dev/console */
+    memset(&g_dev_console_node, 0, sizeof(g_dev_console_node));
+    strcpy(g_dev_console_node.name, "console");
+    g_dev_console_node.flags = FS_CHARDEVICE;
+    g_dev_console_node.inode = 10;
+    g_dev_console_node.read = &tty_devfs_read;
+    g_dev_console_node.write = &tty_devfs_write;
+    devfs_register_device(&g_dev_console_node);
+
+    /* Register /dev/tty */
+    memset(&g_dev_tty_node, 0, sizeof(g_dev_tty_node));
+    strcpy(g_dev_tty_node.name, "tty");
+    g_dev_tty_node.flags = FS_CHARDEVICE;
+    g_dev_tty_node.inode = 3;
+    g_dev_tty_node.read = &tty_devfs_read;
+    g_dev_tty_node.write = &tty_devfs_write;
+    devfs_register_device(&g_dev_tty_node);
 }
 
 int tty_write(const void* user_buf, uint32_t len) {