X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/b3b42765712afed5a35c9be5c832f4a06bd85e7a..8b8f49b713d64065775fe538232f8639083601bd:/lunaix-os/kernel/device/device.c?ds=sidebyside diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c index 282f44d..b25a9c2 100644 --- a/lunaix-os/kernel/device/device.c +++ b/lunaix-os/kernel/device/device.c @@ -1,22 +1,52 @@ -#include + #include +#include #include +#include #include #include +#include +#include + +#include +#include static DEFINE_LLIST(root_list); -static volatile dev_t devid = 0; +static volatile u32_t devid = 0; -struct device* -device_add(struct device* parent, - void* underlay, - char* name_fmt, - uint32_t type, - va_list args) +struct devclass default_devclass = {}; + +void +device_setname_vargs(struct device* dev, char* fmt, va_list args) { - struct device* dev = vzalloc(sizeof(struct device)); + size_t strlen = + __ksprintf_internal(dev->name_val, fmt, DEVICE_NAME_SIZE, args); + dev->name = HSTR(dev->name_val, strlen); + + hstr_rehash(&dev->name, HSTR_FULL_HASH); +} + +void +device_register(struct device* dev, struct devclass* class, char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + + if (fmt) { + device_setname_vargs(dev, fmt, args); + } + + if (class) { + dev->ident = (struct devident){ .fn_grp = class->fn_grp, + .unique = DEV_UNIQUE(class->device, + class->variant) }; + } + + dev->dev_uid = devid++; + + struct device* parent = dev->parent; if (parent) { assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT); llist_append(&parent->children, &dev->siblings); @@ -24,45 +54,47 @@ device_add(struct device* parent, llist_append(&root_list, &dev->siblings); } - size_t strlen = - __ksprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args); + va_end(args); +} - dev->dev_id = devid++; - dev->name = HSTR(dev->name_val, strlen); - dev->parent = parent; +void +device_create(struct device* dev, + struct device* parent, + u32_t type, + void* underlay) +{ + dev->magic = DEV_STRUCT_MAGIC; dev->underlay = underlay; dev->dev_type = type; + dev->parent = parent; - hstr_rehash(&dev->name, HSTR_FULL_HASH); llist_init_head(&dev->children); - - return dev; + mutex_init(&dev->lock); } struct device* -device_addseq(struct device* parent, void* underlay, char* name_fmt, ...) +device_alloc(struct device* parent, u32_t type, void* underlay) { - va_list args; - va_start(args, name_fmt); + struct device* dev = vzalloc(sizeof(struct device)); - struct device* dev = - device_add(parent, underlay, name_fmt, DEV_IFSEQ, args); + if (!dev) { + return NULL; + } + + device_create(dev, parent, type, underlay); - va_end(args); return dev; } -struct device* -device_addvol(struct device* parent, void* underlay, char* name_fmt, ...) +void +device_setname(struct device* dev, char* fmt, ...) { va_list args; - va_start(args, name_fmt); + va_start(args, fmt); - struct device* dev = - device_add(parent, underlay, name_fmt, DEV_IFVOL, args); + device_setname_vargs(dev, fmt, args); va_end(args); - return dev; } struct device* @@ -71,20 +103,23 @@ 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); + struct device* dev = device_alloc(parent, DEV_IFCAT, NULL); + + device_setname_vargs(dev, name_fmt, args); + device_register(dev, NULL, NULL); va_end(args); return dev; } struct device* -device_getbyid(struct llist_header* devlist, dev_t id) +device_getbyid(struct llist_header* devlist, u32_t id) { devlist = devlist ? devlist : &root_list; struct device *pos, *n; llist_for_each(pos, n, devlist, siblings) { - if (pos->dev_id == id) { + if (pos->dev_uid == id) { return pos; } } @@ -93,9 +128,9 @@ device_getbyid(struct llist_header* devlist, dev_t id) } struct device* -device_getbyhname(struct llist_header* devlist, struct hstr* name) +device_getbyhname(struct device* root_dev, struct hstr* name) { - devlist = devlist ? devlist : &root_list; + struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; struct device *pos, *n; llist_for_each(pos, n, devlist, siblings) { @@ -108,12 +143,12 @@ device_getbyhname(struct llist_header* devlist, struct hstr* name) } struct device* -device_getbyname(struct llist_header* devlist, const char* name, size_t len) +device_getbyname(struct device* root_dev, const char* name, size_t len) { struct hstr hname = HSTR(name, len); hstr_rehash(&hname, HSTR_FULL_HASH); - return device_getbyhname(devlist, &hname); + return device_getbyhname(root_dev, &hname); } void @@ -124,9 +159,9 @@ device_remove(struct device* dev) } struct device* -device_getbyoffset(struct llist_header* devlist, int offset) +device_getbyoffset(struct device* root_dev, int offset) { - devlist = devlist ? devlist : &root_list; + struct llist_header* devlist = root_dev ? &root_dev->children : &root_list; struct device *pos, *n; int off = 0; llist_for_each(pos, n, devlist, siblings) @@ -136,4 +171,63 @@ device_getbyoffset(struct llist_header* devlist, int offset) } } return NULL; +} + +void +device_populate_info(struct device* dev, struct dev_info* devinfo) +{ + devinfo->dev_id.group = dev->ident.fn_grp; + devinfo->dev_id.unique = dev->ident.unique; + + if (!devinfo->dev_name.buf) { + return; + } + + struct device_def* def = devdef_byident(&dev->ident); + size_t buflen = devinfo->dev_name.buf_len; + + strncpy(devinfo->dev_name.buf, def->name, buflen); + devinfo->dev_name.buf[buflen - 1] = 0; +} + +struct device* +device_cast(void* obj) +{ + struct device* dev = (struct device*)obj; + if (dev && dev->magic == DEV_STRUCT_MAGIC) { + return dev; + } + + return NULL; +} + +__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args) +{ + int errno = -1; + struct v_fd* fd_s; + if ((errno &= vfs_getfd(fd, &fd_s))) { + goto done; + } + + struct device* dev = (struct device*)fd_s->file->inode->data; + if (dev->magic != DEV_STRUCT_MAGIC) { + errno &= ENODEV; + goto done; + } + + if (req == DEVIOIDENT) { + struct dev_info* devinfo = va_arg(args, struct dev_info*); + device_populate_info(dev, devinfo); + errno = 0; + } + + if (!dev->ops.exec_cmd) { + errno &= ENOTSUP; + goto done; + } + + errno &= dev->ops.exec_cmd(dev, req, args); + +done: + return DO_STATUS_OR_RETURN(errno); } \ No newline at end of file