1 /*
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 <sys/types.h>
11 /* FIXME: For native_posix ssize_t, off_t. */
12 #include <zephyr/fs/fs.h>
13 #include <zephyr/sys/mutex.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /**
20  * File descriptor virtual method table.
21  * Currently all operations beyond read/write/close go thru ioctl method.
22  */
23 struct fd_op_vtable {
24 	ssize_t (*read)(void *obj, void *buf, size_t sz);
25 	ssize_t (*write)(void *obj, const void *buf, size_t sz);
26 	int (*close)(void *obj);
27 	int (*ioctl)(void *obj, unsigned int request, va_list args);
28 };
29 
30 /**
31  * @brief Reserve file descriptor.
32  *
33  * This function allows to reserve a space for file descriptor entry in
34  * the underlying table, and thus allows caller to fail fast if no free
35  * descriptor is available. If this function succeeds, z_finalize_fd()
36  * or z_free_fd() must be called mandatorily.
37  *
38  * @return Allocated file descriptor, or -1 in case of error (errno is set)
39  */
40 int z_reserve_fd(void);
41 
42 /**
43  * @brief Finalize creation of file descriptor.
44  *
45  * This function should be called exactly once after z_reserve_fd(), and
46  * should not be called in any other case.
47  *
48  * @param fd File descriptor previously returned by z_reserve_fd()
49  * @param obj pointer to I/O object structure
50  * @param vtable pointer to I/O operation implementations for the object
51  */
52 void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable);
53 
54 /**
55  * @brief Allocate file descriptor for underlying I/O object.
56  *
57  * This function combines operations of z_reserve_fd() and z_finalize_fd()
58  * in one step, and provided for convenience.
59  *
60  * @param obj pointer to I/O object structure
61  * @param vtable pointer to I/O operation implementations for the object
62  *
63  * @return Allocated file descriptor, or -1 in case of error (errno is set)
64  */
65 int z_alloc_fd(void *obj, const struct fd_op_vtable *vtable);
66 
67 /**
68  * @brief Release reserved file descriptor.
69  *
70  * This function may be called once after z_reserve_fd(), and should
71  * not be called in any other case.
72  *
73  * @param fd File descriptor previously returned by z_reserve_fd()
74  */
75 void z_free_fd(int fd);
76 
77 /**
78  * @brief Get underlying object pointer from file descriptor.
79  *
80  * This function is useful for functions other than read/write/ioctl
81  * to look up underlying I/O object by fd, optionally checking its
82  * type (using vtable reference). If fd refers to invalid entry,
83  * NULL will be returned with errno set to EBADF. If fd is valid,
84  * but vtable param is not NULL and doesn't match object's vtable,
85  * NULL is returned and errno set to err param.
86  *
87  * @param fd File descriptor previously returned by z_reserve_fd()
88  * @param vtable Expected object vtable or NULL
89  * @param err errno value to set if object vtable doesn't match
90  *
91  * @return Object pointer or NULL, with errno set
92  */
93 void *z_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err);
94 
95 /**
96  * @brief Get underlying object pointer and vtable pointer from file descriptor.
97  *
98  * @param fd File descriptor previously returned by z_reserve_fd()
99  * @param vtable A pointer to a pointer variable to store the vtable
100  * @param lock An optional pointer to a pointer variable to store the mutex
101  *        preventing concurrent descriptor access. The lock is not taken,
102  *        it is just returned for the caller to use if necessary. Pass NULL
103  *        if the lock is not needed by the caller.
104  *
105  * @return Object pointer or NULL, with errno set
106  */
107 void *z_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable,
108 			      struct k_mutex **lock);
109 
110 /**
111  * @brief Get the mutex and condition variable associated with the given object and vtable.
112  *
113  * @param obj Object previously returned by a call to e.g. @ref z_get_fd_obj.
114  * @param vtable A pointer the vtable associated with @p obj.
115  * @param lock An optional pointer to a pointer variable to store the mutex
116  *        preventing concurrent descriptor access. The lock is not taken,
117  *        it is just returned for the caller to use if necessary. Pass NULL
118  *        if the lock is not needed by the caller.
119  * @param cond An optional pointer to a pointer variable to store the condition variable
120  *        to notify waiting threads in the case of concurrent descriptor access. Pass NULL
121  *        if the condition variable is not needed by the caller.
122  *
123  * @return `true` on success, `false` otherwise.
124  */
125 bool z_get_obj_lock_and_cond(void *obj, const struct fd_op_vtable *vtable, struct k_mutex **lock,
126 			     struct k_condvar **cond);
127 
128 /**
129  * @brief Call ioctl vmethod on an object using varargs.
130  *
131  * We need this helper function because ioctl vmethod is declared to
132  * take va_list and the only portable way to construct va_list is from
133  * function's ... parameters.
134  *
135  * @param vtable vtable containing ioctl function pointer
136  * @param obj Object to call ioctl on
137  * @param request ioctl request number
138  * @param ... Variadic arguments to ioctl
139  */
z_fdtable_call_ioctl(const struct fd_op_vtable * vtable,void * obj,unsigned long request,...)140 static inline int z_fdtable_call_ioctl(const struct fd_op_vtable *vtable, void *obj,
141 				       unsigned long request, ...)
142 {
143 	va_list args;
144 	int res;
145 
146 	va_start(args, request);
147 	res = vtable->ioctl(obj, request, args);
148 	va_end(args);
149 
150 	return res;
151 }
152 
153 /**
154  * Request codes for fd_op_vtable.ioctl().
155  *
156  * Note that these codes are internal Zephyr numbers, for internal
157  * Zephyr operations (and subject to change without notice, not part
158  * of "stable ABI"). These are however expected to co-exist with
159  * "well-known" POSIX/Linux ioctl numbers, and not clash with them.
160  */
161 enum {
162 	/* Codes below 0x100 are reserved for fcntl() codes. */
163 	ZFD_IOCTL_FSYNC = 0x100,
164 	ZFD_IOCTL_LSEEK,
165 	ZFD_IOCTL_POLL_PREPARE,
166 	ZFD_IOCTL_POLL_UPDATE,
167 	ZFD_IOCTL_POLL_OFFLOAD,
168 	ZFD_IOCTL_SET_LOCK,
169 };
170 
171 #ifdef __cplusplus
172 }
173 #endif
174 
175 #endif /* ZEPHYR_INCLUDE_SYS_FDTABLE_H_ */
176