diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2023-07-13 10:25:14 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2023-07-13 10:25:14 +0200 |
| commit | 006399dc8d5983037d1ac5a7b9d81a0bdc117143 (patch) | |
| tree | 19afa4ef3624a007ce709b1e3f93e99a6f585645 /mod/src/cyber_device.c | |
| parent | fd89f87ee3d2721155124954dca4156866001562 (diff) | |
| download | dev-cyber-006399dc8d5983037d1ac5a7b9d81a0bdc117143.tar.xz dev-cyber-006399dc8d5983037d1ac5a7b9d81a0bdc117143.zip | |
mod: restructure module layoutHEADmasterfmorgner/re-layout
Diffstat (limited to 'mod/src/cyber_device.c')
| -rw-r--r-- | mod/src/cyber_device.c | 176 |
1 files changed, 134 insertions, 42 deletions
diff --git a/mod/src/cyber_device.c b/mod/src/cyber_device.c index 67b9695..a75a67c 100644 --- a/mod/src/cyber_device.c +++ b/mod/src/cyber_device.c @@ -20,81 +20,173 @@ #include <linux/device.h> #include <linux/kernel.h> +#include <linux/kobject.h> #include <linux/module.h> #include <linux/string.h> +#include <linux/fs.h> -struct cyber_device device = {}; - -/** - * Initialize the sysfs CYBER device class - * - * @return zero on success, non-zero otherwise +/* + * UDEV */ -int cyber_device_init_device_class(void); -/** - * Shutdown the sysfs CYBER device class - */ -void cyber_device_shutdown_device_class(void); +typedef struct device *device_ptr; +typedef struct device const *const_device_ptr; +typedef struct kobj_uevent_env *uevent_env_ptr; +typedef struct kobj_uevent_env const *const_uevent_env_ptr; -/** - * Initialize the CYBER character device - * - * @return zero on success, non-zero otherwise - */ -int cyber_device_init_character_device(void); +static int _handle_uevent(const_device_ptr, uevent_env_ptr environment) +{ + return add_uevent_var(environment, "DEVMODE=%#o", 0666); +} -/** - * Shutdown the CYBER character device +/* + * Device Class */ -void cyber_device_shutdown_character_device(void); -/** - * Initialize the CYBER kernel device - * - * @return zero on success, non-zero otherwise - */ -int cyber_device_init_kernel_device(void); +typedef struct class *class_ptr; +typedef struct class const *const_class_ptr; +typedef struct class_attribute *attribute_ptr; +typedef struct class_attribute const *const_attribute_ptr; -/** - * Shutdown the CYBER kernel device - */ -void cyber_device_shutdown_kernel_device(void); +/// Get the amount of available cyber. +static ssize_t available_show(const_class_ptr, const_attribute_ptr, char * __user output_buffer) +{ + return sprintf(output_buffer, "infinite\n"); +} + +/// Get the storage technology in use. +static ssize_t storage_technology_show(const_class_ptr, const_attribute_ptr, char * __user output_buffer) +{ + return sprintf(output_buffer, "condensed di-hydrogen-monoxide\n"); +} + +static CLASS_ATTR_RO(available); +static CLASS_ATTR_RO(storage_technology); + +static int _init_device_class(cyber_device * device) +{ + int error = 0; + + device->class.name = CLS_NAME; + device->class.dev_uevent = _handle_uevent; + + if((error = class_register(&device->class))) + { + printk(KERN_ALERT DEV_NAME ": Failed to register CYBER device class!\n"); + return error; + } + + if((error = class_create_file(&device->class, &class_attr_available)) || (error = class_create_file(&device->class, &class_attr_storage_technology))) + { + printk(KERN_ALERT DEV_NAME ": Failed to register sysfs CYBER attributes!\n"); + return error; + } + + return 0; +} + +static void _shutdown_device_class(cyber_device * device) +{ + class_unregister(&device->class); +} + +/// Character Device + +typedef struct file_operations *file_operations_ptr; +typedef struct file_operations const *const_file_operations_ptr; + +static int _init_character_device(cyber_device * device, const_file_operations_ptr file_ops) +{ + int error = 0; + + if((error = alloc_chrdev_region(&device->number, 0, 1, DEV_NAME))) + { + printk(KERN_ALERT DEV_NAME ": Failed to allocate character device!\n"); + } + + cdev_init(&device->character, file_ops); + device->character.owner = THIS_MODULE; + device->character.ops = file_ops; + + if((error = cdev_add(&device->character, device->number, 1))) + { + printk(KERN_ALERT DEV_NAME ": Failed to add character device (Error: %d)!\n", error); + } + + return error; +} + +static void _shutdown_character_device(cyber_device * device) +{ + cdev_del(&device->character); + unregister_chrdev_region(device->number, 1); +} + +/// Kernel Device + +static void _close_kernel_device(struct device * device) +{ + printk(KERN_INFO DEV_NAME ": Closing kernel CYBER device\n"); +} + +static int _init_kernel_device(cyber_device * device) +{ + int error = 0; + + device->kernel.class = &device->class; + device->kernel.devt = device->number; + device->kernel.init_name = DEV_NAME; + device->kernel.release = _close_kernel_device; + + if((error = device_register(&device->kernel))) + { + printk(KERN_ALERT DEV_NAME ": Failed to create CYBER device!\n"); + } + + return error; +} + +static void _shutdown_kernel_device(cyber_device * device) +{ + device_unregister(&device->kernel); +} + +/// Device -int cyber_device_init(void) +int cyber_device_init(cyber_device * device, const_file_operations_ptr file_ops) { int error = 0; printk(KERN_INFO DEV_NAME ": Initializing CYBER device\n"); - if((error = cyber_device_init_character_device())) + if((error = _init_character_device(device, file_ops))) { return error; } - if((error = cyber_device_init_device_class())) + if((error = _init_device_class(device))) { - cyber_device_shutdown_character_device(); + _shutdown_character_device(device); return error; } - if((error = cyber_device_init_kernel_device())) + if((error = _init_kernel_device(device))) { - cyber_device_shutdown_character_device(); - cyber_device_shutdown_device_class(); + _shutdown_character_device(device); + _shutdown_device_class(device); return error; } - printk(KERN_INFO DEV_NAME ": New CYBER device with major %d minor %d\n", MAJOR(device.number), MINOR(device.number)); + printk(KERN_INFO DEV_NAME ": New CYBER device with major %d minor %d\n", MAJOR(device->number), MINOR(device->number)); return error; } -void cyber_device_shutdown(void) +void cyber_device_shutdown(cyber_device * device) { printk(KERN_INFO DEV_NAME ": Shutting down CYBER device\n"); - cyber_device_shutdown_kernel_device(); - cyber_device_shutdown_device_class(); - cyber_device_shutdown_character_device(); + _shutdown_kernel_device(device); + _shutdown_device_class(device); + _shutdown_character_device(device); } void cyber_device_release(struct device * device) |
