#include #include #include #include #include static DEFINE_LLIST(root_list); static volatile dev_t devid = 0; struct device* __device_add(struct device* parent, void* underlay, char* name_fmt, uint32_t type, va_list args) { struct device* dev = vzalloc(sizeof(struct device)); if (parent) { assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT); } size_t strlen = __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args); dev->dev_id = devid++; dev->name = HSTR(dev->name_val, strlen); dev->parent = parent; dev->underlay = underlay; dev->dev_type = type; hstr_rehash(&dev->name, HSTR_FULL_HASH); llist_append(&root_list, &dev->siblings); return dev; } struct device* device_addseq(struct device* parent, void* underlay, char* name_fmt, ...) { va_list args; va_start(args, name_fmt); struct device* dev = __device_add(parent, underlay, name_fmt, DEV_IFSEQ, args); va_end(args); return dev; } struct device* device_addvol(struct device* parent, void* underlay, char* name_fmt, ...) { va_list args; va_start(args, name_fmt); struct device* dev = __device_add(parent, underlay, name_fmt, DEV_IFVOL, args); va_end(args); return dev; } struct device* device_addcat(struct device* parent, char* name_fmt, ...) { va_list args; va_start(args, name_fmt); struct device* dev = __device_add(parent, NULL, name_fmt, DEV_IFCAT, args); va_end(args); return dev; } struct device* device_getbyid(struct llist_header* devlist, dev_t id) { devlist = devlist ? devlist : &root_list; struct device *pos, *n; llist_for_each(pos, n, devlist, siblings) { if (pos->dev_id == id) { return pos; } } return NULL; } struct device* device_getbyname(struct llist_header* devlist, struct hstr* name) { devlist = devlist ? devlist : &root_list; struct device *pos, *n; llist_for_each(pos, n, devlist, siblings) { if (HSTR_EQ(&pos->name, name)) { return pos; } } return NULL; } void device_remove(struct device* dev) { llist_delete(&dev->siblings); vfree(dev); } struct device* device_getbyoffset(struct llist_header* devlist, int offset) { devlist = devlist ? devlist : &root_list; struct device *pos, *n; int off = 0; llist_for_each(pos, n, devlist, siblings) { if (off++ >= offset) { return pos; } } return NULL; }