2 #include <lunaix/device.h>
4 #include <lunaix/fs/twifs.h>
5 #include <lunaix/ioctl.h>
6 #include <lunaix/mm/valloc.h>
7 #include <lunaix/spike.h>
8 #include <lunaix/syscall.h>
9 #include <lunaix/syscall_utils.h>
11 #include <usr/lunaix/device.h>
13 #include <klibc/stdio.h>
14 #include <klibc/string.h>
16 static DEFINE_LLIST(root_list);
18 static volatile u32_t devid = 0;
20 struct devclass default_devclass = {};
23 device_prepare(struct device* dev, struct devclass* class)
25 dev->magic = DEV_STRUCT_MAGIC;
26 dev->dev_uid = devid++;
27 dev->class = class ? class : &default_devclass;
29 llist_init_head(&dev->children);
33 device_setname_vargs(struct device* dev, char* fmt, va_list args)
36 __ksprintf_internal(dev->name_val, fmt, DEVICE_NAME_SIZE, args);
38 dev->name = HSTR(dev->name_val, strlen);
40 hstr_rehash(&dev->name, HSTR_FULL_HASH);
44 device_setname(struct device* dev, char* fmt, ...)
49 device_setname_vargs(dev, fmt, args);
55 device_add_vargs(struct device* parent,
59 struct devclass* class,
62 struct device* dev = vzalloc(sizeof(struct device));
64 device_prepare(dev, class);
67 assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
68 llist_append(&parent->children, &dev->siblings);
70 llist_append(&root_list, &dev->siblings);
74 device_setname_vargs(dev, name_fmt, args);
78 dev->underlay = underlay;
85 device_add(struct device* parent,
86 struct devclass* class,
93 va_start(args, name_fmt);
96 device_add_vargs(parent, underlay, name_fmt, type, class, args);
103 device_addsys(struct device* parent,
104 struct devclass* class,
110 va_start(args, name_fmt);
113 device_add_vargs(parent, underlay, name_fmt, DEV_IFSYS, class, args);
120 device_addseq(struct device* parent,
121 struct devclass* class,
127 va_start(args, name_fmt);
130 device_add_vargs(parent, underlay, name_fmt, DEV_IFSEQ, class, args);
137 device_addvol(struct device* parent,
138 struct devclass* class,
144 va_start(args, name_fmt);
147 device_add_vargs(parent, underlay, name_fmt, DEV_IFVOL, class, args);
154 device_addcat(struct device* parent, char* name_fmt, ...)
157 va_start(args, name_fmt);
160 device_add_vargs(parent, NULL, name_fmt, DEV_IFCAT, NULL, args);
167 device_getbyid(struct llist_header* devlist, u32_t id)
169 devlist = devlist ? devlist : &root_list;
170 struct device *pos, *n;
171 llist_for_each(pos, n, devlist, siblings)
173 if (pos->dev_uid == id) {
182 device_getbyhname(struct device* root_dev, struct hstr* name)
184 struct llist_header* devlist = root_dev ? &root_dev->children : &root_list;
185 struct device *pos, *n;
186 llist_for_each(pos, n, devlist, siblings)
188 if (HSTR_EQ(&pos->name, name)) {
197 device_getbyname(struct device* root_dev, const char* name, size_t len)
199 struct hstr hname = HSTR(name, len);
200 hstr_rehash(&hname, HSTR_FULL_HASH);
202 return device_getbyhname(root_dev, &hname);
206 device_remove(struct device* dev)
208 llist_delete(&dev->siblings);
213 device_getbyoffset(struct device* root_dev, int offset)
215 struct llist_header* devlist = root_dev ? &root_dev->children : &root_list;
216 struct device *pos, *n;
218 llist_for_each(pos, n, devlist, siblings)
220 if (off++ >= offset) {
228 device_populate_info(struct device* dev, struct dev_info* devinfo)
230 devinfo->dev_id.meta = dev->class->meta;
231 devinfo->dev_id.device = dev->class->device;
232 devinfo->dev_id.variant = dev->class->variant;
234 if (!devinfo->dev_name.buf) {
238 struct device_def* def = devdef_byclass(dev->class);
239 size_t buflen = devinfo->dev_name.buf_len;
241 strncpy(devinfo->dev_name.buf, def->name, buflen);
242 devinfo->dev_name.buf[buflen - 1] = 0;
245 __DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args)
249 if ((errno &= vfs_getfd(fd, &fd_s))) {
253 struct device* dev = (struct device*)fd_s->file->inode->data;
254 if (dev->magic != DEV_STRUCT_MAGIC) {
259 if (req == DEVIOIDENT) {
260 struct dev_info* devinfo = va_arg(args, struct dev_info*);
261 device_populate_info(dev, devinfo);
265 if (!dev->ops.exec_cmd) {
270 errno &= dev->ops.exec_cmd(dev, req, args);
273 return DO_STATUS_OR_RETURN(errno);