6 #include <libubox/uapi.h>
11 static struct avl_tree devices;
13 static void API_CTOR dev_init(void)
15 avl_init(&devices, avl_strcmp, false, NULL);
18 static void free_simple_device(struct device *dev)
24 static void broadcast_device_event(struct device *dev, enum device_event ev)
26 struct device_user *dep, *tmp;
28 list_for_each_entry_safe(dep, tmp, &dev->users, list) {
36 static int set_device_state(struct device *dev, bool state)
46 int claim_device(struct device *dev)
50 DPRINTF("claim device %s, new refcount: %d\n", dev->ifname, dev->active + 1);
51 if (++dev->active != 1)
54 broadcast_device_event(dev, DEV_EVENT_SETUP);
55 ret = dev->set_state(dev, true);
57 broadcast_device_event(dev, DEV_EVENT_UP);
64 void release_device(struct device *dev)
67 DPRINTF("release device %s, new refcount: %d\n", dev->ifname, dev->active);
68 assert(dev->active >= 0);
73 broadcast_device_event(dev, DEV_EVENT_TEARDOWN);
74 dev->set_state(dev, false);
75 broadcast_device_event(dev, DEV_EVENT_DOWN);
78 int check_device_state(struct device *dev)
80 if (!dev->type->check_state)
83 return dev->type->check_state(dev);
86 void init_virtual_device(struct device *dev, const struct device_type *type, const char *name)
92 strncpy(dev->ifname, name, IFNAMSIZ);
94 fprintf(stderr, "Initialize device '%s'\n", dev->ifname);
95 INIT_LIST_HEAD(&dev->users);
99 int init_device(struct device *dev, const struct device_type *type, const char *ifname)
103 init_virtual_device(dev, type, ifname);
106 dev->set_state = set_device_state;
108 dev->avl.key = dev->ifname;
110 ret = avl_insert(&devices, &dev->avl);
114 check_device_state(dev);
119 struct device *get_device(const char *name, bool create)
121 static const struct device_type simple_type = {
123 .check_state = system_if_check,
124 .free = free_simple_device,
129 if (strchr(name, '.'))
130 return get_vlan_device_chain(name, create);
132 dev = avl_find_element(&devices, name, dev, avl);
139 dev = calloc(1, sizeof(*dev));
140 init_device(dev, &simple_type, name);
145 void cleanup_device(struct device *dev)
147 struct device_user *dep, *tmp;
149 fprintf(stderr, "Clean up device '%s'\n", dev->ifname);
150 list_for_each_entry_safe(dep, tmp, &dev->users, list) {
154 dep->cb(dep, DEV_EVENT_REMOVE);
158 avl_delete(&devices, &dev->avl);
161 void set_device_present(struct device *dev, bool state)
163 if (dev->present == state)
166 DPRINTF("Device '%s' %s present\n", dev->ifname, state ? "is now" : "is no longer" );
167 dev->present = state;
168 broadcast_device_event(dev, state ? DEV_EVENT_ADD : DEV_EVENT_REMOVE);
171 void add_device_user(struct device_user *dep, struct device *dev)
174 list_add(&dep->list, &dev->users);
175 if (dep->cb && dev->present) {
176 dep->cb(dep, DEV_EVENT_ADD);
178 dep->cb(dep, DEV_EVENT_UP);
182 void remove_device_user(struct device_user *dep)
184 struct device *dev = dep->dev;
186 list_del(&dep->list);
188 if (list_empty(&dev->users)) {
189 /* all references have gone away, remove this device */
197 cleanup_devices(void)
199 struct device *dev, *tmp;
201 avl_for_each_element_safe(&devices, dev, avl, tmp) {
202 if (!list_empty(&dev->users))