refactor: add user space printf.
[lunaix-os.git] / lunaix-os / kernel / device / device.c
1 #include <klibc/stdio.h>
2 #include <lunaix/device.h>
3 #include <lunaix/fs/twifs.h>
4 #include <lunaix/mm/valloc.h>
5 #include <lunaix/spike.h>
6
7 static DEFINE_LLIST(root_list);
8
9 static volatile dev_t devid = 0;
10
11 struct device*
12 device_add(struct device* parent,
13            void* underlay,
14            char* name_fmt,
15            uint32_t type,
16            va_list args)
17 {
18     struct device* dev = vzalloc(sizeof(struct device));
19
20     if (parent) {
21         assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
22     }
23
24     size_t strlen =
25       __ksprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
26
27     dev->dev_id = devid++;
28     dev->name = HSTR(dev->name_val, strlen);
29     dev->parent = parent;
30     dev->underlay = underlay;
31     dev->dev_type = type;
32
33     hstr_rehash(&dev->name, HSTR_FULL_HASH);
34     llist_append(&root_list, &dev->siblings);
35
36     return dev;
37 }
38
39 struct device*
40 device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
41 {
42     va_list args;
43     va_start(args, name_fmt);
44
45     struct device* dev =
46       device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
47
48     va_end(args);
49     return dev;
50 }
51
52 struct device*
53 device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
54 {
55     va_list args;
56     va_start(args, name_fmt);
57
58     struct device* dev =
59       device_add(parent, underlay, name_fmt, DEV_IFVOL, args);
60
61     va_end(args);
62     return dev;
63 }
64
65 struct device*
66 device_addcat(struct device* parent, char* name_fmt, ...)
67 {
68     va_list args;
69     va_start(args, name_fmt);
70
71     struct device* dev = device_add(parent, NULL, name_fmt, DEV_IFCAT, args);
72
73     va_end(args);
74     return dev;
75 }
76
77 struct device*
78 device_getbyid(struct llist_header* devlist, dev_t id)
79 {
80     devlist = devlist ? devlist : &root_list;
81     struct device *pos, *n;
82     llist_for_each(pos, n, devlist, siblings)
83     {
84         if (pos->dev_id == id) {
85             return pos;
86         }
87     }
88
89     return NULL;
90 }
91
92 struct device*
93 device_getbyhname(struct llist_header* devlist, struct hstr* name)
94 {
95     devlist = devlist ? devlist : &root_list;
96     struct device *pos, *n;
97     llist_for_each(pos, n, devlist, siblings)
98     {
99         if (HSTR_EQ(&pos->name, name)) {
100             return pos;
101         }
102     }
103
104     return NULL;
105 }
106
107 struct device*
108 device_getbyname(struct llist_header* devlist, const char* name, size_t len)
109 {
110     struct hstr hname = HSTR(name, len);
111     hstr_rehash(&hname, HSTR_FULL_HASH);
112
113     return device_getbyhname(devlist, &hname);
114 }
115
116 void
117 device_remove(struct device* dev)
118 {
119     llist_delete(&dev->siblings);
120     vfree(dev);
121 }
122
123 struct device*
124 device_getbyoffset(struct llist_header* devlist, int offset)
125 {
126     devlist = devlist ? devlist : &root_list;
127     struct device *pos, *n;
128     int off = 0;
129     llist_for_each(pos, n, devlist, siblings)
130     {
131         if (off++ >= offset) {
132             return pos;
133         }
134     }
135     return NULL;
136 }