feat: (devfs) a new filesystem for device exposure.
[lunaix-os.git] / lunaix-os / kernel / device / device.c
diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c
new file mode 100644 (file)
index 0000000..aafdf0e
--- /dev/null
@@ -0,0 +1,127 @@
+#include <klibc/stdio.h>
+#include <lunaix/device.h>
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+static DEFINE_LLIST(root_list);
+
+static volatile dev_t devid = 0;
+
+struct device*
+__device_add(struct device* parent,
+             void* underlay,
+             char* name_fmt,
+             uint32_t type,
+             va_list args)
+{
+    struct device* dev = vzalloc(sizeof(struct device));
+
+    if (parent) {
+        assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
+    }
+
+    size_t strlen =
+      __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
+
+    dev->dev_id = devid++;
+    dev->name = HSTR(dev->name_val, strlen);
+    dev->parent = parent;
+    dev->underlay = underlay;
+    dev->dev_type = type;
+
+    hstr_rehash(&dev->name, HSTR_FULL_HASH);
+    llist_append(&root_list, &dev->siblings);
+
+    return dev;
+}
+
+struct device*
+device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      __device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      __device_add(parent, underlay, name_fmt, DEV_IFVOL, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev = __device_add(parent, NULL, name_fmt, DEV_IFCAT, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (pos->dev_id == id) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+struct device*
+device_getbyname(struct llist_header* devlist, struct hstr* name)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (HSTR_EQ(&pos->name, name)) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+void
+device_remove(struct device* dev)
+{
+    llist_delete(&dev->siblings);
+    vfree(dev);
+}
+
+struct device*
+device_getbyoffset(struct llist_header* devlist, int offset)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    int off = 0;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (off++ >= offset) {
+            return pos;
+        }
+    }
+    return NULL;
+}
\ No newline at end of file