In my Zephyr DTS binding I have a node with a given compatibility, let's call it my_compatibilty
, with an optional property of type phandles
, let's call it things
, allowed to have up to two elements. In my driver code I can build up an array of the leaves of this tree; for instance, I can make an array of the values of a string entry flibble
within things
, or NULL
if not present, for all compatible nodes with:
#define GET_THINGS_LIST(i, name) {DT_PROP_BY_PHANDLE_IDX_OR(i, things, 0, name, NULL), \
DT_PROP_BY_PHANDLE_IDX_OR(i, things, 1, name, NULL)},
static const char *const leafValueFlibble[][2] = {
DT_FOREACH_STATUS_OKAY_VARGS(my_compatibilty, GET_THINGS_LIST, flibble)
};
This is now easy to manage, a nice ordered list I can work with from C.
HOWEVER, I now need flibble
to be a phandle
-type property. How do I extend the macrobatics above so that I can still get at the leaves of the tree, i.e. for all compatible nodes, create arrays of the values of the named properties within flibble
(or NULL
/-1
/some-known-value
if not present to keep the order)?
Based on the question and comments, the solution would require a few macros:
#define DEFAULT_VALUE { .bingInt = 0, .bingString = NULL, },
// This node might have a flibble, if it does, follow it to get bingInt and bingString from the pointed to node
#define HANDLE_FLIBBLE(node) \
COND_CODE_1(DT_NODE_HAS_PROP(node, flibble), \
({ .bingInt = DT_PROP_BY_PHANDLE(node, flibble, bingInt), \
.bingString = DT_PROP_BY_PHANDLE(node, flibble, bingString), },), \
(DEFAULT_VALUE))
// This node might have things, if it does, follow it to the flibble
#define HANDLE_MY_COMPAT(node) { \
COND_CODE_1(DT_PROP_HAS_IDX(node, thing, 0), \
(HANDLE_FLIBBLE(DT_PHANDLE_BY_IDX(node, thing, 0))), \
(DEFAULT_VALUE)) \
COND_CODE_1(DT_PROP_HAS_IDX(node, thing, 1), \
(HANDLE_FLIBBLE(DT_PHANDLE_BY_IDX(node, thing, 1))), \
(DEFAULT_VALUE)) \
},
struct flibbles {
int bingInt;
const char *bingString;
};
// Define the array using HANDLE_MY_COMPAT
const struct flibbles leafFlibbles[][2] = {
DT_FOREACH_STATUS_OKAY(my_compatibilty, HANDLE_MY_COMPAT)
};