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