1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3
4#include "mos/filesystem/vfs_types.hpp"
5
6#include <mos/lib/structures/list.hpp>
7
8struct sysfs_file_t;
9
10typedef enum
11{
12 _SYSFS_INVALID = 0,
13 SYSFS_RO,
14 SYSFS_RW,
15 SYSFS_WO,
16 SYSFS_MEM, ///< memory-backed file
17 SYSFS_DYN, ///< dynamic directory items
18} sysfs_item_type_t;
19
20typedef struct _sysfs_item
21{
22 const mos::string name;
23 sysfs_item_type_t type;
24 bool (*show)(sysfs_file_t *file);
25 size_t (*store)(sysfs_file_t *file, const char *buf, size_t count, off_t offset);
26 ino_t ino;
27
28 struct
29 {
30 bool (*mmap)(sysfs_file_t *file, vmap_t *vmap, off_t offset);
31 bool (*munmap)(sysfs_file_t *file, vmap_t *vmap, bool *unmapped);
32 size_t size;
33 } mem;
34
35 as_linked_list;
36 void (*dyn_iterate)(struct _sysfs_item *item, dentry_t *dentry, vfs_listdir_state_t *iterator_state, dentry_iterator_op op);
37 bool (*dyn_lookup)(inode_t *parent_dir, dentry_t *dentry);
38 bool (*dyn_create)(inode_t *parent_dir, dentry_t *dentry, file_type_t type, file_perm_t perm);
39} sysfs_item_t;
40
41// clang-format off
42#define SYSFS_RO_ITEM(_name, _show_fn) { .name = _name, .type = SYSFS_RO, .show = _show_fn }
43#define SYSFS_RW_ITEM(_name, _show_fn, _store_fn) { .name = _name, .type = SYSFS_RW, .show = _show_fn, .store = _store_fn }
44#define SYSFS_WO_ITEM(_name, _store_fn) { .name = _name, .type = SYSFS_WO, .store = _store_fn }
45#define SYSFS_MEM_ITEM(_name, _mmap_fn, _munmap_fn) { .name = _name, .type = SYSFS_MEM, .mem = { .mmap = _mmap_fn, .munmap = _munmap_fn } }
46#define SYSFS_DYN_ITEMS(_name, _iterate_fn, _lookup_fn) { .type = SYSFS_DYN, .dyn_iterate = _iterate_fn, .dyn_lookup = _lookup_fn }
47#define SYSFS_DYN_DIR(_name, _iterate_fn, _lookup_fn, _create_fn) { .type = SYSFS_DYN, .dyn_iterate = _iterate_fn, .dyn_lookup = _lookup_fn, .dyn_create = _create_fn }
48// clang-format on
49
50#define SYSFS_ITEM_RO_PRINTF(name, fmt, ...) \
51 static bool name(sysfs_file_t *file) \
52 { \
53 sysfs_printf(file, fmt, ##__VA_ARGS__); \
54 return true; \
55 }
56
57#define SYSFS_ITEM_RO_STRING(name, value) SYSFS_ITEM_RO_PRINTF(name, "%s\n", value)
58
59#define SYSFS_DEFINE_DIR(sysfs_name, sysfs_items) static sysfs_dir_t __sysfs_##sysfs_name(#sysfs_name, sysfs_items, MOS_ARRAY_SIZE(sysfs_items))
60
61struct sysfs_dir_t
62{
63 as_linked_list;
64 mos::string name;
65 sysfs_item_t *const items;
66 const size_t num_items = 0;
67
68 sysfs_dir_t(mos::string_view name, sysfs_item_t *items, size_t num_items) : name(name), items(items), num_items(num_items) {};
69
70 dentry_t *_dentry; ///< for internal use only
71 list_head _dynamic_items; ///< for internal use only
72};
73
74/**
75 * @brief Register a sysfs directory
76 *
77 * @param entry the sysfs directory to register
78 */
79void sysfs_register(sysfs_dir_t *entry);
80
81/**
82 * @brief Register an entry in a sysfs directory
83 *
84 * @param sysfs_dir the sysfs directory to register the item in
85 * @param item the sysfs item to register
86 */
87void sysfs_register_file(sysfs_dir_t *sysfs_dir, sysfs_item_t *item);
88
89/**
90 * @brief Register an entry in the sysfs root directory
91 *
92 * @param item the sysfs item to register
93 */
94should_inline void sysfs_register_root_file(sysfs_item_t *item)
95{
96 sysfs_register_file(NULL, item);
97}
98
99void sysfs_file_set_data(sysfs_file_t *file, void *data);
100void *sysfs_file_get_data(sysfs_file_t *file);
101sysfs_item_t *sysfs_file_get_item(sysfs_file_t *file);
102
103inode_t *sysfs_create_inode(file_type_t type, void *data);
104
105__printf(2, 3) ssize_t sysfs_printf(sysfs_file_t *file, const char *fmt, ...);
106ssize_t sysfs_put_data(sysfs_file_t *file, const void *data, size_t count);
107