1 #include <lunaix/device.h>
3 #include <lunaix/fs/twifs.h>
4 #include <lunaix/ioctl.h>
5 #include <lunaix/mm/valloc.h>
6 #include <lunaix/spike.h>
7 #include <lunaix/syscall.h>
8 #include <lunaix/syscall_utils.h>
9 #include <lunaix/owloysius.h>
11 #include <klibc/strfmt.h>
12 #include <klibc/string.h>
14 static DEFINE_LLIST(root_list);
16 morph_t* device_mobj_root;
19 device_setname_vargs(struct device_meta* dev, char* fmt, va_list args)
21 ksnprintfv(dev->name_val, fmt, DEVICE_NAME_SIZE, args);
22 changeling_setname(dev_mobj(dev), dev->name_val);
26 device_register_generic(struct device_meta* devm, struct devclass* class,
30 morph_t* morphed, *parent;
32 morphed = &devm->mobj;
36 device_setname_vargs(devm, fmt, args);
39 if (class && morph_type_of(morphed, device_morpher))
41 struct device* dev = to_dev(devm);
42 dev->ident = (struct devident) {
43 .fn_grp = class->fn_grp,
44 .unique = DEV_UNIQUE(class->device, class->variant)
48 parent = morphed->parent;
50 changeling_attach(parent, morphed);
57 device_create(struct device* dev, struct device_meta* parent,
58 u32_t type, void* underlay)
60 dev->underlay = underlay;
63 llist_init_head(&dev->potentium);
64 mutex_init(&dev->lock);
65 iopoll_init_evt_q(&dev->pollers);
69 device_alloc(struct device_meta* parent, u32_t type, void* underlay)
71 struct device* dev = vzalloc(sizeof(struct device));
77 device_create(dev, parent, type, underlay);
78 changeling_morph(dev_morph(parent), dev->mobj, NULL, device_morpher);
84 device_alloc_alias(struct device_meta* parent, struct device_meta* aliased)
86 struct device_alias* dev = vzalloc(sizeof(struct device_alias));
93 changeling_ref(dev_mobj(aliased));
94 changeling_morph(dev_morph(parent), dev->mobj, NULL, devalias_morpher);
100 device_alloc_cat(struct device_meta* parent)
102 struct device_cat* dev = vzalloc(sizeof(struct device_cat));
108 changeling_morph(dev_morph(parent), dev->mobj, NULL, devcat_morpher);
114 device_setname(struct device_meta* dev, char* fmt, ...)
119 device_setname_vargs(dev, fmt, args);
125 device_addcat(struct device_meta* parent, char* name_fmt, ...)
128 va_start(args, name_fmt);
130 struct device_cat* dev = device_alloc_cat(parent);
132 device_setname_vargs(dev_meta(dev), name_fmt, args);
133 device_register_generic(dev_meta(dev), NULL, NULL);
140 device_addalias(struct device_meta* parent,
141 struct device_meta* aliased, char* name_fmt, ...)
144 va_start(args, name_fmt);
146 struct device_alias* dev = device_alloc_alias(parent, aliased);
148 device_setname_vargs(dev_meta(dev), name_fmt, args);
149 device_register_generic(dev_meta(dev), NULL, NULL);
156 device_remove(struct device_meta* dev)
158 changeling_isolate(&dev->mobj);
163 device_populate_info(struct device* dev, struct dev_info* devinfo)
165 devinfo->dev_id.group = dev->ident.fn_grp;
166 devinfo->dev_id.unique = dev->ident.unique;
168 if (!devinfo->dev_name.buf) {
172 struct device_def* def = devdef_byident(&dev->ident);
173 size_t buflen = devinfo->dev_name.buf_len;
175 strncpy(devinfo->dev_name.buf, def->name, buflen);
176 devinfo->dev_name.buf[buflen - 1] = 0;
180 resolve_device_morph(void* maybe_dev)
182 struct device_alias* da = NULL;
185 morphed = morphed_ptr(maybe_dev);
187 if (!is_changeling(morphed)) {
191 if (morph_type_of(morphed, device_morpher))
196 if (morph_type_of(morphed, devcat_morpher))
201 while(morph_type_of(morphed, devalias_morpher))
203 da = changeling_reveal(morphed, devalias_morpher);
204 morphed = &da->alias->mobj;
207 return da ? morphed : NULL;
211 device_alert_poller(struct device* dev, int poll_evt)
213 dev->poll_evflags = poll_evt;
214 iopoll_wake_pollers(&dev->pollers);
218 device_chain_loader(struct device_def* def, devdef_ldfn fn)
220 struct device_ldfn_chain* node;
222 node = valloc(sizeof(*node));
225 if (!def->load_chain) {
229 node->chain = def->load_chain;
232 def->load_chain = node;
236 device_chain_load_once(struct device_def* def)
238 struct device_ldfn_chain *node, *next;
244 node = def->load_chain;
245 def->load_chain = NULL;
256 if (def->flags.no_default_realm) {
264 def->create(def, NULL);
268 __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, sc_va_list, _args)
274 convert_valist(&args, _args);
276 if ((errno &= vfs_getfd(fd, &fd_s))) {
280 struct device* dev = resolve_device(fd_s->file->inode->data);
286 if (req == DEVIOIDENT) {
287 struct dev_info* devinfo = va_arg(args, struct dev_info*);
288 device_populate_info(dev, devinfo);
292 if (!dev->ops.exec_cmd) {
297 errno = dev->ops.exec_cmd(dev, req, args);
300 return DO_STATUS_OR_RETURN(errno);
304 __device_subsys_init()
306 device_mobj_root = changeling_spawn(NULL, "devices");
308 owloysius_fetch_init(__device_subsys_init, on_sysconf);