xref: /illumos-gate/usr/src/lib/libxpio/common/libxpio.h (revision fd71220ba0fafcc9cf5ea0785db206f3f31336e7)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2022 Oxide Computer Company
14  */
15 
16 #ifndef _LIBXPIO_H
17 #define	_LIBXPIO_H
18 
19 /*
20  * An evolving, but private, interface to the kernel GPIO and DPIO subsystems
21  * (hence xPIO).
22  */
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 #include <stdint.h>
29 #include <stdbool.h>
30 #include <libdevinfo.h>
31 #include <sys/gpio/dpio.h>
32 
33 typedef enum {
34 	XPIO_ERR_OK = 0,
35 	/*
36 	 * Indicates that there was a memory allocation error. The system error
37 	 * contains the specific errno.
38 	 */
39 	XPIO_ERR_NO_MEM,
40 	/*
41 	 * Indicates that an error occurred while trying to use the devinfo
42 	 * library.
43 	 */
44 	XPIO_ERR_LIBDEVINFO,
45 	/*
46 	 * Indicates that an internal error condition occurred.
47 	 */
48 	XPIO_ERR_INTERNAL,
49 	/*
50 	 * Indicates that the function was given an invalid pointer argument.
51 	 */
52 	XPIO_ERR_BAD_PTR,
53 	/*
54 	 * Indicate that the passed in minor node name was not the right type.
55 	 */
56 	XPIO_ERR_WRONG_MINOR_TYPE,
57 	/*
58 	 * Indicates a failure to open a device file.
59 	 */
60 	XPIO_ERR_OPEN_DEV,
61 	/*
62 	 * Indicates a failure to talk with the kgpio subsystem.
63 	 */
64 	XPIO_ERR_KGPIO,
65 	/*
66 	 * Indicates that the specified GPIO controller does not exist.
67 	 */
68 	XPIO_ERR_BAD_CTRL_NAME,
69 	/*
70 	 * Indicates that the requested GPIO name or number does not exist.
71 	 */
72 	XPIO_ERR_BAD_GPIO_ID,
73 	/*
74 	 * Indicates that there was something wrong with the attributes that
75 	 * were handed in an update. The update structure has additional
76 	 * information.
77 	 */
78 	XPIO_ERR_BAD_UPDATE,
79 	/*
80 	 * Indicates that an attempt to perform an update cannot proceed because
81 	 * the structure has already been used for an update and has error
82 	 * information associated with it.
83 	 */
84 	XPIO_ERR_UPDATE_USED,
85 	/*
86 	 * Indicates that the features that were passed in to create the DPIO
87 	 * included something that was invalid.
88 	 */
89 	XPIO_ERR_BAD_DPIO_FEAT,
90 	/*
91 	 * Indicates that the name of the DPIO was invalid or does not exist.
92 	 */
93 	XPIO_ERR_BAD_DPIO_NAME,
94 	/*
95 	 * Indicates that the name of the GPIO was invalid.
96 	 */
97 	XPIO_ERR_BAD_GPIO_NAME,
98 	/*
99 	 * Indicates that an attempt to lookup something (e.g. a GPIO) did not
100 	 * succeed.
101 	 */
102 	XPIO_ERR_NO_LOOKUP_MATCH
103 } xpio_err_t;
104 
105 typedef enum {
106 	XPIO_ATTR_TYPE_STRING,
107 	XPIO_ATTR_TYPE_UINT32
108 } xpio_attr_type_t;
109 
110 typedef enum {
111 	XPIO_ATTR_PROT_RO,
112 	XPIO_ATTR_PROT_RW
113 } xpio_attr_prot_t;
114 
115 typedef struct xpio xpio_t;
116 typedef struct xpio_ctrl xpio_ctrl_t;
117 typedef struct xpio_ctrl_info xpio_ctrl_info_t;
118 typedef struct xpio_gpio_info xpio_gpio_info_t;
119 typedef struct xpio_gpio_attr xpio_gpio_attr_t;
120 typedef struct xpio_gpio_attr_err xpio_gpio_attr_err_t;
121 typedef struct xpio_gpio_update xpio_gpio_update_t;
122 typedef struct xpio_dpio_info xpio_dpio_info_t;
123 
124 
125 extern xpio_t *xpio_init(void);
126 extern void xpio_fini(xpio_t *);
127 
128 extern xpio_err_t xpio_err(xpio_t *);
129 extern int32_t xpio_syserr(xpio_t *);
130 extern const char *xpio_errmsg(xpio_t *);
131 extern const char *xpio_err2str(xpio_t *, xpio_err_t);
132 
133 /*
134  * Controller Discovery Functions
135  */
136 typedef struct {
137 	di_minor_t xcd_minor;
138 } xpio_ctrl_disc_t;
139 
140 typedef bool (*xpio_ctrl_disc_f)(xpio_t *, xpio_ctrl_disc_t *, void *);
141 extern void xpio_ctrl_discover(xpio_t *, xpio_ctrl_disc_f, void *);
142 
143 extern bool xpio_ctrl_init(xpio_t *, di_minor_t, xpio_ctrl_t **);
144 extern bool xpio_ctrl_init_by_name(xpio_t *, const char *, xpio_ctrl_t **);
145 extern void xpio_ctrl_fini(xpio_ctrl_t *);
146 
147 /*
148  * Get information about a controller. Once obtained, the lifetime is disjoint
149  * from the controller.
150  */
151 extern bool xpio_ctrl_info(xpio_ctrl_t *, xpio_ctrl_info_t **);
152 extern void xpio_ctrl_info_free(xpio_ctrl_info_t *);
153 extern uint32_t xpio_ctrl_info_ngpios(xpio_ctrl_info_t *);
154 extern uint32_t xpio_ctrl_info_ndpios(xpio_ctrl_info_t *);
155 extern const char *xpio_ctrl_info_devpath(xpio_ctrl_info_t *);
156 
157 /*
158  * Ways to translae between human known names to the provider's underlying IDs.
159  * This only searches the specified controller.
160  */
161 extern bool xpio_gpio_lookup_id(xpio_ctrl_t *, const char *, uint32_t *);
162 
163 /*
164  * Snapshot information about a GPIO, walk and understand its attributes. Once
165  * obtained, the lifetime is disjoint from the underlying controller and handle.
166  * Each gpio can be operated on in parallel safely. Attributes are tied to the
167  * corresponding gpio.
168  */
169 extern bool xpio_gpio_info(xpio_ctrl_t *, uint32_t, xpio_gpio_info_t **);
170 extern uint32_t xpio_gpio_id(xpio_gpio_info_t *);
171 extern xpio_gpio_attr_t *xpio_gpio_attr_next(xpio_gpio_info_t *,
172     xpio_gpio_attr_t *);
173 extern xpio_gpio_attr_t *xpio_gpio_attr_find(xpio_gpio_info_t *, const char *);
174 extern const char *xpio_gpio_attr_name(xpio_gpio_info_t *, xpio_gpio_attr_t *);
175 extern xpio_attr_type_t xpio_gpio_attr_type(xpio_gpio_info_t *,
176     xpio_gpio_attr_t *);
177 extern xpio_attr_prot_t xpio_gpio_attr_prot(xpio_gpio_info_t *,
178     xpio_gpio_attr_t *);
179 extern bool xpio_gpio_attr_value_uint32(xpio_gpio_attr_t *, uint32_t *);
180 extern bool xpio_gpio_attr_value_string(xpio_gpio_attr_t *, const char **);
181 extern void xpio_gpio_attr_possible_uint32(xpio_gpio_info_t *,
182     xpio_gpio_attr_t *, uint32_t **, uint_t *);
183 extern void xpio_gpio_attr_possible_string(xpio_gpio_info_t *,
184     xpio_gpio_attr_t *, const char ***, uint_t *);
185 extern bool xpio_gpio_attr_xlate_to_str(xpio_gpio_info_t *, xpio_gpio_attr_t *,
186     char *, size_t);
187 extern bool xpio_gpio_attr_xlate_uint32_to_str(xpio_gpio_info_t *,
188     xpio_gpio_attr_t *, uint32_t, char *, size_t);
189 extern void xpio_gpio_info_free(xpio_gpio_info_t *);
190 
191 /*
192  * The GPIO update data structure is used to track all of the updates that need
193  * to occur to a given GPIO. This structure is tied to the gpio information
194  * because the attributes that a given GPIO has may vary between GPIOs in a
195  * given provider. This update structure can then be given to xpio_gpio_set() to
196  * actually set the information.
197  *
198  * When it comes to error handling and checking here, we only attempt to verify
199  * that an attribute is one that the provider reported to us. We do not attempt
200  * to verify whether it is read-only or not. However, as part of translating
201  * values, we will verify the types. There are two different groups of setting
202  * functions. One is intended for CLI applications which just takes a string and
203  * does all the translation that is necessary as part of setting the attribute.
204  * The other set allows one to specify the types of values themselves.
205  *
206  * To try and provide reasonable error handling, we provide a unique set of
207  * error routines (e.g. these do not require the xpio_t). Finally, as part of
208  * attempting to set a gpio, errors will be returned as something that one can
209  * iterate and determine what wrong with each attribute value to attempt to make
210  * error handling easier.
211  */
212 typedef enum {
213 	/*
214 	 * Indicates that the update was OK.
215 	 */
216 	XPIO_UPDATE_ERR_OK,
217 	/*
218 	 * Indicates that there was an attempt to update a read-only attribute.
219 	 */
220 	XPIO_UPDATE_ERR_RO,
221 	/*
222 	 * Indicates that the attribute's name was unknown to the provider.
223 	 */
224 	XPIO_UPDATE_ERR_UNKNOWN_ATTR,
225 	/*
226 	 * Indicates that the value for a given attribute's type was incorrect.
227 	 */
228 	XPIO_UPDATE_ERR_BAD_TYPE,
229 	/*
230 	 * Indicates that the system didn't know the value in question.
231 	 */
232 	XPIO_UPDATE_ERR_UNKNOWN_VAL,
233 	/*
234 	 * Indicates that the system was unable to translate an attribute value
235 	 * into its underlying type.
236 	 */
237 	XPIO_UPDATE_ERR_CANT_XLATE,
238 	/*
239 	 * Indicates that this was a valid attribute, but it could not be
240 	 * applied.
241 	 */
242 	XPIO_UPDATE_ERR_CANT_APPLY_VAL,
243 	/*
244 	 * Indicates that we ran out of memory processing something.
245 	 */
246 	XPIO_UPDATE_ERR_NO_MEM,
247 	/*
248 	 * Indicates that an internal error occurred in the library.
249 	 */
250 	XPIO_UPDATE_ERR_INTERNAL
251 } xpio_update_err_t;
252 
253 extern bool xpio_gpio_update_init(xpio_t *, xpio_gpio_info_t *,
254     xpio_gpio_update_t **);
255 
256 extern xpio_update_err_t xpio_update_err(xpio_gpio_update_t *);
257 extern int32_t xpio_update_syserr(xpio_gpio_update_t *);
258 extern const char *xpio_update_errmsg(xpio_gpio_update_t *);
259 extern const char *xpio_update_err2str(xpio_gpio_update_t *,
260     xpio_update_err_t);
261 
262 /*
263  * These two routines allow a caller to set an attribute's value directly. There
264  * is no checking on whether the attribute's value is known or valid.
265  */
266 extern bool xpio_gpio_attr_set_str(xpio_gpio_update_t *, xpio_gpio_attr_t *,
267     const char *);
268 extern bool xpio_gpio_attr_set_uint32(xpio_gpio_update_t *, xpio_gpio_attr_t *,
269     uint32_t);
270 /*
271  * The two update functions above assume that you have already determined the
272  * right type. This one performs any translation that might be required to go
273  * from a string to the underlying type and then sets the attribute
274  * appropriately. This will also verify that the value is known to the system,
275  * unlike the ones above.
276  */
277 extern bool xpio_gpio_attr_from_str(xpio_gpio_update_t *,
278     xpio_gpio_attr_t *, const char *);
279 
280 /*
281  * This proceeds to update the GPIO that this update structure is for. After
282  * calling this, if this fails, then one can iterate the update structure for
283  * errors that occurred.
284  */
285 extern bool xpio_gpio_update(xpio_ctrl_t *, xpio_gpio_update_t *);
286 extern xpio_gpio_attr_err_t *xpio_gpio_attr_err_next(xpio_gpio_update_t *,
287     xpio_gpio_attr_err_t *);
288 extern const char *xpio_gpio_attr_err_name(xpio_gpio_attr_err_t *);
289 extern xpio_update_err_t xpio_gpio_attr_err_err(xpio_gpio_attr_err_t *);
290 
291 /*
292  * This tears down the xpio_gpio_update_t, at which point any outstanding
293  * xpio_gpio_attr_err_t's are no longer valid (that is their lifetime is joined
294  * together).
295  */
296 extern void xpio_gpio_update_free(xpio_gpio_update_t *);
297 
298 /*
299  * Create a DPIO from the specified GPIO. The DPIO's supported features are
300  * based on the following bitfield.
301  */
302 typedef enum {
303 	XPIO_DPIO_F_READ	= 1 << 0,
304 	XPIO_DPIO_F_WRITE	= 1 << 1,
305 	XPIO_DPIO_F_KERNEL	= 1 << 2,
306 } xpio_dpio_features_t;
307 
308 extern bool xpio_dpio_create(xpio_ctrl_t *, xpio_gpio_info_t *, const char *,
309     xpio_dpio_features_t);
310 extern bool xpio_dpio_destroy(xpio_ctrl_t *, xpio_gpio_info_t *);
311 
312 /*
313  * DPIO Discovery and Basic Information
314  */
315 typedef struct {
316 	di_minor_t xdd_minor;
317 } xpio_dpio_disc_t;
318 
319 typedef bool (*xpio_dpio_disc_f)(xpio_t *, xpio_dpio_disc_t *, void *);
320 extern void xpio_dpio_discover(xpio_t *, xpio_dpio_disc_f, void *);
321 
322 extern bool xpio_dpio_info(xpio_t *, di_minor_t, xpio_dpio_info_t **);
323 extern const char *xpio_dpio_info_ctrl(xpio_dpio_info_t *);
324 extern const char *xpio_dpio_info_name(xpio_dpio_info_t *);
325 extern uint32_t xpio_dpio_info_gpionum(xpio_dpio_info_t *);
326 extern dpio_caps_t xpio_dpio_info_caps(xpio_dpio_info_t *);
327 extern dpio_flags_t xpio_dpio_info_flags(xpio_dpio_info_t *);
328 extern void xpio_dpio_info_free(xpio_dpio_info_t *);
329 
330 #ifdef __cplusplus
331 }
332 #endif
333 
334 #endif /* _LIBXPIO_H */
335