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