Line data Source code
1 0 : /*
2 : * Copyright (c) 2018 Linaro Limited
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 : #ifndef ZEPHYR_INCLUDE_SYS_FDTABLE_H_
7 : #define ZEPHYR_INCLUDE_SYS_FDTABLE_H_
8 :
9 : #include <stdarg.h>
10 : #include <time.h>
11 :
12 : /* FIXME: For native_posix ssize_t, off_t. */
13 : #include <sys/types.h>
14 : #include <zephyr/kernel.h>
15 : #include <zephyr/sys/util.h>
16 :
17 : /* File mode bits */
18 0 : #define ZVFS_MODE_IFMT 0170000
19 0 : #define ZVFS_MODE_UNSPEC 0000000
20 0 : #define ZVFS_MODE_IFIFO 0010000
21 0 : #define ZVFS_MODE_IFCHR 0020000
22 0 : #define ZVFS_MODE_IMSGQ 0030000
23 0 : #define ZVFS_MODE_IFDIR 0040000
24 0 : #define ZVFS_MODE_IFSEM 0050000
25 0 : #define ZVFS_MODE_IFBLK 0060000
26 0 : #define ZVFS_MODE_IFSHM 0070000
27 0 : #define ZVFS_MODE_IFREG 0100000
28 0 : #define ZVFS_MODE_IFLNK 0120000
29 0 : #define ZVFS_MODE_IFSOCK 0140000
30 :
31 0 : #define ZVFS_POLLIN BIT(0)
32 0 : #define ZVFS_POLLPRI BIT(1)
33 0 : #define ZVFS_POLLOUT BIT(2)
34 0 : #define ZVFS_POLLERR BIT(3)
35 0 : #define ZVFS_POLLHUP BIT(4)
36 0 : #define ZVFS_POLLNVAL BIT(5)
37 :
38 : #ifdef __cplusplus
39 : extern "C" {
40 : #endif
41 :
42 : /* FIXME: use k_off_t and k_ssize_t to avoid the POSIX->Zephyr->POSIX dependency cycle */
43 : #ifdef CONFIG_NEWLIB_LIBC
44 : #ifndef _OFF_T_DECLARED
45 : typedef __off_t off_t;
46 : #define _OFF_T_DECLARED
47 : #endif
48 : #ifndef _SSIZE_T_DECLARED
49 : typedef _ssize_t ssize_t;
50 : #define _SSIZE_T_DECLARED
51 : #endif
52 : #endif
53 :
54 : /**
55 : * File descriptor virtual method table.
56 : * Currently all operations beyond read/write/close go thru ioctl method.
57 : */
58 1 : struct fd_op_vtable {
59 : union {
60 0 : ssize_t (*read)(void *obj, void *buf, size_t sz);
61 0 : ssize_t (*read_offs)(void *obj, void *buf, size_t sz, size_t offset);
62 0 : };
63 : union {
64 0 : ssize_t (*write)(void *obj, const void *buf, size_t sz);
65 0 : ssize_t (*write_offs)(void *obj, const void *buf, size_t sz, size_t offset);
66 0 : };
67 : union {
68 0 : int (*close)(void *obj);
69 0 : int (*close2)(void *obj, int fd);
70 0 : };
71 0 : int (*ioctl)(void *obj, unsigned int request, va_list args);
72 : };
73 :
74 : /**
75 : * @brief Reserve file descriptor.
76 : *
77 : * This function allows to reserve a space for file descriptor entry in
78 : * the underlying table, and thus allows caller to fail fast if no free
79 : * descriptor is available. If this function succeeds, zvfs_finalize_fd()
80 : * or zvfs_free_fd() must be called mandatorily.
81 : *
82 : * @return Allocated file descriptor, or -1 in case of error (errno is set)
83 : */
84 1 : int zvfs_reserve_fd(void);
85 :
86 : /**
87 : * @brief Finalize creation of file descriptor, with type.
88 : *
89 : * This function should be called exactly once after zvfs_reserve_fd(), and
90 : * should not be called in any other case.
91 : *
92 : * The difference between this function and @ref zvfs_finalize_fd is that the
93 : * latter does not relay type information of the created file descriptor.
94 : *
95 : * Values permitted for @a mode are one of `ZVFS_MODE_..`.
96 : *
97 : * @param fd File descriptor previously returned by zvfs_reserve_fd()
98 : * @param obj pointer to I/O object structure
99 : * @param vtable pointer to I/O operation implementations for the object
100 : * @param mode File type as specified above.
101 : */
102 1 : void zvfs_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode);
103 :
104 : /**
105 : * @brief Finalize creation of file descriptor.
106 : *
107 : * This function should be called exactly once after zvfs_reserve_fd(), and
108 : * should not be called in any other case.
109 : *
110 : * @param fd File descriptor previously returned by zvfs_reserve_fd()
111 : * @param obj pointer to I/O object structure
112 : * @param vtable pointer to I/O operation implementations for the object
113 : */
114 1 : static inline void zvfs_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable)
115 : {
116 : zvfs_finalize_typed_fd(fd, obj, vtable, ZVFS_MODE_UNSPEC);
117 : }
118 :
119 : /**
120 : * @brief Allocate file descriptor for underlying I/O object.
121 : *
122 : * This function combines operations of zvfs_reserve_fd() and zvfs_finalize_fd()
123 : * in one step, and provided for convenience.
124 : *
125 : * @param obj pointer to I/O object structure
126 : * @param vtable pointer to I/O operation implementations for the object
127 : *
128 : * @return Allocated file descriptor, or -1 in case of error (errno is set)
129 : */
130 1 : int zvfs_alloc_fd(void *obj, const struct fd_op_vtable *vtable);
131 :
132 : /**
133 : * @brief Release reserved file descriptor.
134 : *
135 : * This function may be called once after zvfs_reserve_fd(), and should
136 : * not be called in any other case.
137 : *
138 : * @param fd File descriptor previously returned by zvfs_reserve_fd()
139 : */
140 1 : void zvfs_free_fd(int fd);
141 :
142 : /**
143 : * @brief Get underlying object pointer from file descriptor.
144 : *
145 : * This function is useful for functions other than read/write/ioctl
146 : * to look up underlying I/O object by fd, optionally checking its
147 : * type (using vtable reference). If fd refers to invalid entry,
148 : * NULL will be returned with errno set to EBADF. If fd is valid,
149 : * but vtable param is not NULL and doesn't match object's vtable,
150 : * NULL is returned and errno set to err param.
151 : *
152 : * @param fd File descriptor previously returned by zvfs_reserve_fd()
153 : * @param vtable Expected object vtable or NULL
154 : * @param err errno value to set if object vtable doesn't match
155 : *
156 : * @return Object pointer or NULL, with errno set
157 : */
158 1 : void *zvfs_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err);
159 :
160 : /**
161 : * @brief Get underlying object pointer and vtable pointer from file descriptor.
162 : *
163 : * @param fd File descriptor previously returned by zvfs_reserve_fd()
164 : * @param vtable A pointer to a pointer variable to store the vtable
165 : * @param lock An optional pointer to a pointer variable to store the mutex
166 : * preventing concurrent descriptor access. The lock is not taken,
167 : * it is just returned for the caller to use if necessary. Pass NULL
168 : * if the lock is not needed by the caller.
169 : *
170 : * @return Object pointer or NULL, with errno set
171 : */
172 1 : void *zvfs_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable,
173 : struct k_mutex **lock);
174 :
175 : /**
176 : * @brief Get the mutex and condition variable associated with the given object and vtable.
177 : *
178 : * @param obj Object previously returned by a call to e.g. @ref zvfs_get_fd_obj.
179 : * @param vtable A pointer the vtable associated with @p obj.
180 : * @param lock An optional pointer to a pointer variable to store the mutex
181 : * preventing concurrent descriptor access. The lock is not taken,
182 : * it is just returned for the caller to use if necessary. Pass NULL
183 : * if the lock is not needed by the caller.
184 : * @param cond An optional pointer to a pointer variable to store the condition variable
185 : * to notify waiting threads in the case of concurrent descriptor access. Pass NULL
186 : * if the condition variable is not needed by the caller.
187 : *
188 : * @return `true` on success, `false` otherwise.
189 : */
190 1 : bool zvfs_get_obj_lock_and_cond(void *obj, const struct fd_op_vtable *vtable, struct k_mutex **lock,
191 : struct k_condvar **cond);
192 :
193 : /**
194 : * @brief Call ioctl vmethod on an object using varargs.
195 : *
196 : * We need this helper function because ioctl vmethod is declared to
197 : * take va_list and the only portable way to construct va_list is from
198 : * function's ... parameters.
199 : *
200 : * @param vtable vtable containing ioctl function pointer
201 : * @param obj Object to call ioctl on
202 : * @param request ioctl request number
203 : * @param ... Variadic arguments to ioctl
204 : */
205 1 : static inline int zvfs_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *obj,
206 : unsigned long request, ...)
207 : {
208 : va_list args;
209 : int res;
210 :
211 : va_start(args, request);
212 : res = vtable->ioctl(obj, request, args);
213 : va_end(args);
214 :
215 : return res;
216 : }
217 :
218 0 : struct zvfs_pollfd {
219 0 : int fd;
220 0 : short events;
221 0 : short revents;
222 : };
223 :
224 0 : __syscall int zvfs_poll(struct zvfs_pollfd *fds, int nfds, int poll_timeout);
225 :
226 0 : struct zvfs_fd_set {
227 0 : uint32_t bitset[(CONFIG_ZVFS_OPEN_MAX + 31) / 32];
228 : };
229 :
230 : /** @brief Number of file descriptors which can be added @ref zvfs_fd_set */
231 1 : #define ZVFS_FD_SETSIZE (sizeof(((struct zvfs_fd_set *)0)->bitset) * 8)
232 :
233 0 : void ZVFS_FD_CLR(int fd, struct zvfs_fd_set *fdset);
234 0 : int ZVFS_FD_ISSET(int fd, struct zvfs_fd_set *fdset);
235 0 : void ZVFS_FD_SET(int fd, struct zvfs_fd_set *fdset);
236 0 : void ZVFS_FD_ZERO(struct zvfs_fd_set *fdset);
237 :
238 0 : __syscall int zvfs_select(int nfds, struct zvfs_fd_set *ZRESTRICT readfds,
239 : struct zvfs_fd_set *ZRESTRICT writefds,
240 : struct zvfs_fd_set *ZRESTRICT errorfds,
241 : const struct timespec *ZRESTRICT timeout, const void *ZRESTRICT sigmask);
242 :
243 : /**
244 : * Request codes for fd_op_vtable.ioctl().
245 : *
246 : * Note that these codes are internal Zephyr numbers, for internal
247 : * Zephyr operations (and subject to change without notice, not part
248 : * of "stable ABI"). These are however expected to co-exist with
249 : * "well-known" POSIX/Linux ioctl numbers, and not clash with them.
250 : */
251 0 : enum {
252 : /* Codes below 0x100 are reserved for fcntl() codes. */
253 : ZFD_IOCTL_FSYNC = 0x100,
254 : ZFD_IOCTL_LSEEK,
255 : ZFD_IOCTL_POLL_PREPARE,
256 : ZFD_IOCTL_POLL_UPDATE,
257 : ZFD_IOCTL_POLL_OFFLOAD,
258 : ZFD_IOCTL_SET_LOCK,
259 : ZFD_IOCTL_STAT,
260 : ZFD_IOCTL_TRUNCATE,
261 : ZFD_IOCTL_MMAP,
262 :
263 : /* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */
264 : ZFD_IOCTL_FIONREAD = 0x541B,
265 : ZFD_IOCTL_FIONBIO = 0x5421,
266 : };
267 :
268 : #ifdef __cplusplus
269 : }
270 : #endif
271 :
272 : #include <zephyr/syscalls/fdtable.h>
273 :
274 : #endif /* ZEPHYR_INCLUDE_SYS_FDTABLE_H_ */
|