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