diff --git a/src/02-driver/dts/.clangd b/src/02-driver/charachter-oriented/.clangd similarity index 100% rename from src/02-driver/dts/.clangd rename to src/02-driver/charachter-oriented/.clangd diff --git a/src/02-driver/dts/Makefile b/src/02-driver/charachter-oriented/Makefile similarity index 57% rename from src/02-driver/dts/Makefile rename to src/02-driver/charachter-oriented/Makefile index 5ea736b..77d73c9 100644 --- a/src/02-driver/dts/Makefile +++ b/src/02-driver/charachter-oriented/Makefile @@ -2,36 +2,21 @@ ifneq ($(KERNELRELEASE),) obj-m += mymodule.o ## name of the generated module -ccflags-y += -Wno-declaration-after-statement -std=gnu11 mymodule-objs := skeleton.o ## list of objects needed for that module # Part executed when called from standard make in module source directory: else +include ../../buildroot_path include ../../kernel_settings PWD := $(shell pwd) -INCL+=-I. -I$(KDIR)/include -I$(KDIR)/arch/arm64/boot/dts -DTB = mydt.dtb -DTS = $(DTB:.dtb=.dts) - -all: dtb boot +all: $(MAKE) -C $(KDIR) M=$(PWD) ARCH=$(CPU) CROSS_COMPILE=$(TOOLS) modules -dtb: $(DTB) -$(DTB) : $(DTS) - ln -s $(KDIR)/arch/arm/boot/dts arm - -cpp $(INCL) -E -P -x assembler-with-cpp $(DTS) | dtc -I dts -O dtb -o $(DTB) - - rm arm - -boot: - mkimage -T script -A arm -C none -d boot.cmd boot.ovl - clean: $(MAKE) -C $(KDIR) M=$(PWD) clean - rm -f *.dtb *.ovl install: $(MAKE) -C $(KDIR) M=$(PWD) INSTALL_MOD_PATH=$(MODPATH) modules_install endif - diff --git a/src/02-driver/dts/boot.cmd b/src/02-driver/charachter-oriented/boot.cmd similarity index 100% rename from src/02-driver/dts/boot.cmd rename to src/02-driver/charachter-oriented/boot.cmd diff --git a/src/02-driver/charachter-oriented/ex2.c b/src/02-driver/charachter-oriented/ex2.c new file mode 100644 index 0000000..e1f5ea9 --- /dev/null +++ b/src/02-driver/charachter-oriented/ex2.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include + +// linux theory: https://linux-kernel-labs.github.io/refs/heads/master/labs/device_drivers.html + +#define MY_MAJOR 42 +#define MY_MAX_MINORS 5 + +#define BUFFER_SIZE 300 + + +struct my_device_data { + struct cdev cdev; + /* my data starts here */ + char buffer[BUFFER_SIZE]; +}; + +struct my_device_data devs; + +// inode: https://www.kernel.org/doc/html/latest/filesystems/ext4/inodes.html +// file: https://docs.kernel.org/filesystems/api-summary.html#c.file + +int skeleton_open(struct inode* i, struct file* f) { + + pr_info("Open file\n"); + + // Get the stuct of my data + struct my_device_data *my_data = container_of(i->i_cdev, struct my_device_data, cdev); + + // point private data on driver data, here this is a char buffer + f->private_data = my_data; + + return 0; +} + +int skeleton_release(struct inode* i, struct file* f) { + + pr_info("Release file\n"); + + return 0; +} + +ssize_t skeleton_read(struct file* f, char* __user buf, size_t count, loff_t* off) { + + pr_info("Read file\n"); + + struct my_device_data *my_data = (struct my_device_data *) f->private_data; + ssize_t len = min(BUFFER_SIZE - ((size_t)*off), count); + + if (len <= 0) { + pr_info("Cannot read data for length: %ld\n", len); + return 0; + } + + + /* read data from my_data->buffer to user buffer */ + if (copy_to_user(buf, my_data->buffer + *off, len)) { + pr_info("Failed to copy to user space buffer\n"); + return -EFAULT; + } + + *off += len; + return len; + +} + +ssize_t skeleton_write(struct file* f, const char* __user buf, size_t count, loff_t* off) { + + pr_info("Write file\n"); + + struct my_device_data *my_data = (struct my_device_data *) f->private_data; + ssize_t len = min(BUFFER_SIZE - ((size_t)*off), count); + + if (len <= 0) { + pr_info("Cannot write data for length: %ld\n", len); + return 0; + } + + + /* read data from user buffer to my_data->buffer */ + if (copy_from_user(my_data->buffer + *off, buf, len)) { + pr_info("Failed to copy from user space buffer\n"); + return -EFAULT; + } + + + *off += len; + return len; +} + + +static struct file_operations skeleton_fops = { + .owner = THIS_MODULE, + .open = skeleton_open, + .read = skeleton_read, + .write = skeleton_write, + .release = skeleton_release, +}; + + +int ex2_init(void) { + pr_info("Load exercice 2\n"); + int ret = register_chrdev_region(MKDEV(MY_MAJOR, 0), MY_MAX_MINORS, "My module"); + + if (ret != 0) { + /* report error */ + pr_info("Module registration error: %d\n", ret); + return ret; + } + + /* initialize devs fields */ + cdev_init(&devs.cdev, &skeleton_fops); + ret = cdev_add(&devs.cdev, MKDEV(MY_MAJOR, 0), 1); + + if (ret != 0) { + /* report error */ + pr_info("cdev add error: %d\n", ret); + return ret; + } + + return ret; +} + +void ex2_exit(void) { + + cdev_del(&devs.cdev); + unregister_chrdev_region(MKDEV(MY_MAJOR, 0), MY_MAX_MINORS); +} diff --git a/src/02-driver/dts/mydt.dts b/src/02-driver/charachter-oriented/mydt.dts similarity index 100% rename from src/02-driver/dts/mydt.dts rename to src/02-driver/charachter-oriented/mydt.dts diff --git a/src/02-driver/charachter-oriented/skeleton.c b/src/02-driver/charachter-oriented/skeleton.c new file mode 100644 index 0000000..0990320 --- /dev/null +++ b/src/02-driver/charachter-oriented/skeleton.c @@ -0,0 +1,38 @@ +#include // needed by all modules +#include // needed for macros +#include // needed for debugging + +#include "ex2.c" + + +static int __init skeleton_init(void) { + int ret = 0; + + pr_info("My module loading...\n"); + pr_info("----------------------\n"); + + ret = ex2_init(); + + pr_info("----------------------\n"); + pr_info("My module is loaded\n"); + + return ret; +} + +static void __exit skeleton_exit(void) { + pr_info("My module unloading...\n"); + pr_info("----------------------\n"); + + ex2_exit(); + + pr_info("----------------------\n"); + pr_info("My module is unloaded\n"); +} + +module_init (skeleton_init); +module_exit (skeleton_exit); + +MODULE_AUTHOR("Fastium "); +MODULE_AUTHOR("Klagarge "); +MODULE_DESCRIPTION ("Module pilot charachter oriented"); +MODULE_LICENSE ("GPL"); diff --git a/src/02-driver/dts/skeleton.c b/src/02-driver/dts/skeleton.c deleted file mode 100644 index d97bdde..0000000 --- a/src/02-driver/dts/skeleton.c +++ /dev/null @@ -1,135 +0,0 @@ -/* skeleton.c */ -#include /* needed for macros */ -#include /* needed for debugging */ -#include /* needed by all modules */ - -#include /* needed for char device driver */ -#include /* needed for device drivers */ -#include /* needed to copy data to/from user */ - -#include /* needed for sysfs handling */ -#include -#include -#include /* needed for sysfs handling */ - -static int skeleton_open(struct inode* i, struct file* f) -{ - pr_info("skeleton : open operation... major:%d, minor:%d\n", - imajor(i), - iminor(i)); - return 0; -} - -static int skeleton_release(struct inode* i, struct file* f) -{ - pr_info("skeleton: release operation...\n"); - return 0; -} - -static ssize_t skeleton_read(struct file* f, - char __user* buf, - size_t count, - loff_t* off) -{ - pr_info("skeleton: read operation... read=%ld\n", count); - return 0; -} - -static ssize_t skeleton_write(struct file* f, - const char __user* buf, - size_t count, - loff_t* off) -{ - pr_info("skeleton: write operation... written=%ld\n", count); - return count; -} - -static struct file_operations fops = { - .owner = THIS_MODULE, - .open = skeleton_open, - .read = skeleton_read, - .write = skeleton_write, - .release = skeleton_release, -}; - -struct miscdevice misc_device = { - .minor = MISC_DYNAMIC_MINOR, - .fops = &fops, - .name = "mydevice", - .mode = 0777, -}; - -int skeleton_probe(struct platform_device* pdev) -{ - pr_info("skeleton - driver probe %llx (%s)- M.m=%d.%d\n", - (unsigned long long)pdev, - pdev->name, - MAJOR(pdev->dev.devt), - MINOR(pdev->dev.devt)); - - // register misc device ... - int ret = misc_register(&misc_device); - - // read device tree attribute - struct device_node* dt_node = pdev->dev.of_node; - const char* prop = 0; - if (dt_node) - ret = of_property_read_string(dt_node, "attribute", &prop); - else - pr_info("mymodule not found!\n"); - if ((prop != 0) && (ret == 0)) - pr_info("attribute=%s (ret=%d)\n", prop, ret); - - return 0; -} -int skeleton_remove(struct platform_device* pdev) -{ - pr_info("skeleton - sysfs driver remove %llx\n", (unsigned long long)pdev); - misc_deregister(&misc_device); - return 0; -} -void skeleton_shutdown(struct platform_device* pdev) -{ - pr_info("skeleton - sysfs driver shutdown %s\n", pdev->name); -} - -struct of_device_id of_skeleton[] = { - { - .compatible = "mydevice", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, of_skeleton); - -static struct platform_driver sysfs_driver = { - .probe = skeleton_probe, - .remove = skeleton_remove, - .shutdown = skeleton_shutdown, - .driver = - { - .name = "mydriver", - .of_match_table = of_match_ptr(of_skeleton), - }, -}; - -static int __init skeleton_init(void) -{ - pr_info("Linux module skeleton loading...\n"); - int status = platform_driver_register(&sysfs_driver); - pr_info("Linux module skeleton loaded\n"); - return status; -} - -static void __exit skeleton_exit(void) -{ - pr_info("Linux module skeleton exiting...\n"); - platform_driver_unregister(&sysfs_driver); - pr_info("Linux module skeleton unloaded\n"); -} - -module_init(skeleton_init); -module_exit(skeleton_exit); - -MODULE_AUTHOR("Daniel Gachet "); -MODULE_DESCRIPTION("Module skeleton"); -MODULE_LICENSE("GPL");