1 #include <hal/devtreem.h>
2 #include <lunaix/device.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/syslog.h>
5 #include <lunaix/owloysius.h>
6 #include <lunaix/status.h>
8 #include <klibc/string.h>
12 static DECLARE_HASHTABLE(registry, 32);
13 static struct device_cat* dt_category;
21 #define hash(def) ((unsigned int)__ptr(def))
23 static struct dtm_driver_record*
24 __locate_record(struct device_def* def)
26 struct dtm_driver_record *p, *n;
28 hashtable_hash_foreach(registry, hash(def), p, n, node)
40 __get_patternlet(const char* str, unsigned i, size_t len,
43 fig->optional = (i + 1 < len && str[i + 1] == '?');
54 * A simplified regular expression matcher:
55 * 1. '*' matches any substring including empty string
56 * 2. '?' mark the prefixed character optional (an epsilon transition)
59 __try_match(const char* str, const char* pattern, size_t pat_sz)
61 unsigned j = 0, i = 0;
62 int saved_star = -1, saved_pos = 0;
63 size_t str_sz = strlen(str);
70 __get_patternlet(pattern, j, pat_sz, &p0);
71 __get_patternlet(pattern, j + 1, pat_sz, &p1);
74 j += 1 + !!p0.optional;
83 if (p1.optional || p1.val == c) {
99 j = (unsigned)saved_star;
100 i = (unsigned)saved_pos;
103 return j + 1 >= pat_sz;
106 static struct device_meta*
107 __try_create_categorical(struct dtn_base *p)
111 struct device_meta* parent = NULL;
112 struct device_cat* cat;
114 parent = __try_create_categorical(p->parent);
115 parent = parent ?: dev_meta(dt_category);
117 if (!p->compat.size) {
122 cat = changeling_reveal(p->binded_dev, devcat_morpher);
125 cat = device_addcat(parent, HSTR_VAL(dt_mobj(p)->name));
126 p->binded_dev = dev_mobj(cat);
129 return dev_meta(cat);
133 compat_matched(struct dtm_driver_record* rec, struct dtn_base *base)
136 struct dtm_driver_info *p, *n;
138 list_for_each(p, n, rec->infos.first, node)
140 size_t pat_len = strlen(p->pattern);
141 dtprop_strlst_foreach(compat, &base->compat)
143 if (__try_match(compat, p->pattern, pat_len)) {
153 dtm_try_create_from(struct device_def* def)
157 struct dt_context* dtctx;
158 struct dtm_driver_record* rec;
159 struct dtn_base *p, *n;
161 dtctx = dt_main_context();
163 rec = __locate_record(def);
168 llist_for_each(p, n, &dtctx->nodes, nodes)
170 if (!p->compat.size) {
174 if (!compat_matched(rec, p)) {
178 __try_create_categorical(p);
180 if ((err = def->create(def, dt_mobj(p)))) {
181 name = HSTR_VAL(dt_mobj(p)->name);
182 WARN("failed to bind devtree node %s, err=%d", name, err);
190 dtm_register_entry(struct device_def* def, const char* pattern)
192 struct dtm_driver_info* info;
193 struct dtm_driver_record* record;
195 info = valloc(sizeof(*info));
196 info->pattern = pattern;
198 record = __locate_record(def);
200 record = valloc(sizeof(*record));
202 list_head_init(&record->infos);
204 hashtable_hash_in(registry, &record->node, hash(def));
207 list_add(&record->infos, &info->node);
209 device_chain_loader(def, dtm_try_create_from);
215 hashtable_init(registry);
217 dt_category = device_addcat(NULL, "tree");
219 owloysius_fetch_init(dtm_init, on_sysconf);