#include "devfs.h"
#include "errno.h"
-#include "tty.h"
-#include "pty.h"
#include "utils.h"
extern uint32_t get_tick_count(void);
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) {
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;
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;
}
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;
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);
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) {
#include "pty.h"
+#include "devfs.h"
#include "errno.h"
#include "process.h"
#include "waitqueue.h"
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) {
#include "tty.h"
+#include "devfs.h"
#include "keyboard.h"
#include "process.h"
#include "waitqueue.h"
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;
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) {