diff --git a/kernel/kmod.c b/kernel/kmod.c index ab812ef4046c2068180645606d92eb90f41b6d33..75443bcd4dfb9dc99a9378c6e36024c61ac45b47 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -1,29 +1,37 @@ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fs.h> +#include "../common/include/data.h" +#include "../common/include/message.h" #include <linux/cdev.h> -#include <linux/vmalloc.h> -#include <linux/uaccess.h> +#include <linux/crc32.h> +#include <linux/delay.h> +#include <linux/fs.h> +#include <linux/gpio.h> #include <linux/hrtimer.h> +#include <linux/kernel.h> #include <linux/kthread.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/crc32.h> -#include "../common/include/message.h" +#include <linux/module.h> +#include <linux/uaccess.h> +#include <linux/vmalloc.h> #define DEVICE_NAME "amogus" #define CLASS_NAME "amogus_class" #define SLOTS 4 -#define SLOT_INTERVAL_NS 250000 +#define SLOT_INTERVAL_NS 1000000 -#define GPIO_PIN 12 +#define MAX_VALUES 16 + +#define GPIO_PIN 575 static int major_number; -static struct class* class = NULL; +static struct class *class = NULL; static struct cdev mycdev; -static message_t* message; +typedef struct packet { + data_t data; + uint32_t crc; +} packet_t; + +static packet_t *packet; static struct hrtimer timer; static ktime_t interval; @@ -35,193 +43,221 @@ static atomic_t wake_counter = ATOMIC_INIT(0); static int slot = 0; -typedef struct packet { - message_t data; - uint32_t crc; -} packet_t; +static int device_open(struct inode *inode, struct file *file) { return 0; } -static int device_open(struct inode *inode, struct file *file) -{ - return 0; -} +static int device_release(struct inode *inode, struct file *file) { return 0; } -static int device_release(struct inode *inode, struct file *file) -{ - return 0; +static uint32_t calculate_crc32(const data_t *data) { + uint32_t crc = crc32(0, (void *)&data->sensor_id, sizeof(uint8_t)); + crc = crc32(crc, (void *)&data->count, sizeof(uint8_t)); + crc = crc32(crc, (void *)&data->values, sizeof(message_t) * data->count); + return crc; } -static ssize_t device_write(struct file *filp, const char *input, - size_t length, loff_t *offset) -{ - if(length != sizeof(message_t)) { - printk(KERN_ALERT "lkm: Tried to write more bytes than allowed\n"); - return -EFAULT; - } +static ssize_t device_write(struct file *filp, const char *input, size_t length, + loff_t *offset) { + if (length != sizeof(data_t)) { + printk(KERN_ALERT "lkm: Tried to write more bytes than allowed\n"); + return -EFAULT; + } - if (copy_from_user((void*)message, input, length)) { - return -EFAULT; - } + if (((data_t *)input)->count >= MAX_VALUES) { + printk(KERN_ALERT "lkm: Tried to write more messages than allowed\n"); + return -EFAULT; + } + + if (copy_from_user((void *)&(packet->data.sensor_id), + (void *)&(((data_t *)input)->sensor_id), + sizeof(uint8_t))) { + return -EFAULT; + } - printk(KERN_INFO "lkm: received write of size %zu\n", length); + if (copy_from_user((void *)&(packet->data.count), + (void *)&(((data_t *)input)->count), sizeof(uint8_t))) { + return -EFAULT; + } - return length; + if (copy_from_user((void *)packet->data.values, + (void *)((data_t *)input)->values, + sizeof(message_t) * packet->data.count)) { + return -EFAULT; + } + + packet->crc = calculate_crc32(&packet->data); + + printk(KERN_INFO "lkm: received write of size %zu\n", length); + + return length; } static const struct file_operations fops = { - .write = device_write, - .open = device_open, - .release = device_release -}; + .write = device_write, .open = device_open, .release = device_release}; static enum hrtimer_restart timer_callback(struct hrtimer *timer) { - atomic_inc(&wake_counter); - wake_up_interruptible(&wq); + atomic_inc(&wake_counter); + wake_up_interruptible(&wq); - hrtimer_forward_now(timer, interval); - return HRTIMER_RESTART; + hrtimer_forward_now(timer, interval); + return HRTIMER_RESTART; } static void send_bit(uint8_t bit) { - gpio_set_value(GPIO_PIN, bit); - udelay(1); + gpio_set_value(GPIO_PIN, bit); + udelay(1); } static void send_byte(uint8_t byte) { - send_bit(0); + send_bit(0); - for (int i = 0; i < 8; i++) { - int bit = (byte >> (7 - i)) & 1; - send_bit(bit); - } + for (int i = 0; i < 8; i++) { + int bit = (byte >> (7 - i)) & 1; + send_bit(bit); + } - send_bit(1); + send_bit(1); } -static void send_data(const void *data, size_t length) { - const uint8_t *bytes = (const uint8_t*)data; +static void send_data(const packet_t *packet) { + send_byte(packet->data.sensor_id); + send_byte(packet->data.count); - for (size_t i = 0; i < length; i++) { - send_byte(bytes[i]); - } -} - -static uint32_t calculate_crc32(const void *data, size_t length){ - return crc32(0, data, length); -} + uint8_t *bytes = (uint8_t *)packet->data.values; -static int timed_thread_fn(void *args) { - while (!kthread_should_stop()) { - wait_event_interruptible(wq, atomic_read(&wake_counter) > 0); - atomic_dec(&wake_counter); + for (size_t i = 0; i < sizeof(message_t) * packet->data.count; i++) { + send_byte(bytes[i]); + } - if (slot == 0) { - packet_t packet; + bytes = (uint8_t *)&packet->crc; - packet.data = *message; - packet.crc = calculate_crc32(&packet.data, sizeof(&packet.data)); + for (size_t i = 0; i < sizeof(uint32_t); i++) { + send_byte(bytes[i]); + } +} - send_data(&packet, sizeof(packet)); - } +static int timed_thread_fn(void *args) { + while (!kthread_should_stop()) { + wait_event_interruptible(wq, atomic_read(&wake_counter) > 0); + atomic_dec(&wake_counter); - slot = (slot + 1) % SLOTS; + if (slot == 0) { + send_data(packet); } - return 0; -} + slot = (slot + 1) % SLOTS; + } -static int __init lkm_init(void) -{ - dev_t dev; + return 0; +} - message = (message_t*)vmalloc(sizeof(message_t)); +static int __init lkm_init(void) { + dev_t dev; - if(message == NULL) { - return -1; - } + packet = (packet_t *)vmalloc(sizeof(packet_t)); - // Dynamically allocate major number - if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) { - vfree(message); - printk(KERN_ALERT "Failed to allocate major number\n"); - return -1; - } - major_number = MAJOR(dev); - - class = class_create(CLASS_NAME); - if (IS_ERR(class)) { - vfree(message); - unregister_chrdev_region(MKDEV(major_number, 0), 1); - printk(KERN_ALERT "Failed to create device class\n"); - return PTR_ERR(class); - } + if (packet == NULL) { + return -EFAULT; + } - if (device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME) == NULL) { - vfree(message); - class_destroy(class); - unregister_chrdev_region(MKDEV(major_number, 0), 1); - printk(KERN_ALERT "Failed to create device\n"); - return -1; - } + packet->data.sensor_id = 0x7C; + packet->data.count = 0; - cdev_init(&mycdev, &fops); - if (cdev_add(&mycdev, MKDEV(major_number, 0), 1) < 0) { - vfree(message); - device_destroy(class, MKDEV(major_number, 0)); - class_destroy(class); - unregister_chrdev_region(MKDEV(major_number, 0), 1); - printk(KERN_ALERT "Failed to add character device\n"); - return -1; - } + packet->data.values = (message_t *)vmalloc(sizeof(message_t) * MAX_VALUES); - printk(KERN_INFO "lkm: device created successfully\n"); + if (packet->data.values == NULL) { + vfree(packet); + return -EFAULT; + } - if (gpio_request(GPIO_PIN, "GPIO_PIN") < 0) { - vfree(message); - cdev_del(&mycdev); - device_destroy(class, MKDEV(major_number, 0)); - class_destroy(class); - unregister_chrdev_region(MKDEV(major_number, 0), 1); - printk(KERN_ALERT "Failed to request GPIO pin\n"); - return -1; - } - gpio_direction_output(GPIO_PIN, 1); - - timed_thread = kthread_run(timed_thread_fn, NULL, "timed_thread"); - if (IS_ERR(timed_thread)) { - vfree(message); - cdev_del(&mycdev); - device_destroy(class, MKDEV(major_number, 0)); - class_destroy(class); - unregister_chrdev_region(MKDEV(major_number, 0), 1); - printk(KERN_ALERT "Failed to create timed thread\n"); - return -1; - } + // Dynamically allocate major number + if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) { + vfree(packet->data.values); + vfree(packet); + printk(KERN_ALERT "Failed to allocate major number\n"); + return -1; + } + major_number = MAJOR(dev); - interval = ktime_set(0, SLOT_INTERVAL_NS); - hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - timer.function = timer_callback; - hrtimer_start(&timer, interval, HRTIMER_MODE_REL); + class = class_create(CLASS_NAME); + if (IS_ERR(class)) { + vfree(packet->data.values); + vfree(packet); + unregister_chrdev_region(MKDEV(major_number, 0), 1); + printk(KERN_ALERT "Failed to create device class\n"); + return PTR_ERR(class); + } + + if (device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME) == + NULL) { + vfree(packet->data.values); + vfree(packet); + class_destroy(class); + unregister_chrdev_region(MKDEV(major_number, 0), 1); + printk(KERN_ALERT "Failed to create device\n"); + return -1; + } + + cdev_init(&mycdev, &fops); + if (cdev_add(&mycdev, MKDEV(major_number, 0), 1) < 0) { + vfree(packet->data.values); + vfree(packet); + device_destroy(class, MKDEV(major_number, 0)); + class_destroy(class); + unregister_chrdev_region(MKDEV(major_number, 0), 1); + printk(KERN_ALERT "Failed to add character device\n"); + return -1; + } - return 0; -} + printk(KERN_INFO "lkm: device created successfully\n"); -static void __exit lkm_exit(void) -{ - vfree(message); + if (gpio_request(GPIO_PIN, "GPIO_PIN") < 0) { + vfree(packet->data.values); + vfree(packet); + cdev_del(&mycdev); + device_destroy(class, MKDEV(major_number, 0)); + class_destroy(class); + unregister_chrdev_region(MKDEV(major_number, 0), 1); + printk(KERN_ALERT "Failed to request GPIO pin\n"); + return -1; + } + gpio_direction_output(GPIO_PIN, 1); + + timed_thread = kthread_run(timed_thread_fn, NULL, "timed_thread"); + if (IS_ERR(timed_thread)) { + vfree(packet->data.values); + vfree(packet); cdev_del(&mycdev); device_destroy(class, MKDEV(major_number, 0)); class_destroy(class); unregister_chrdev_region(MKDEV(major_number, 0), 1); - printk(KERN_INFO "lkm: device removed successfully\n"); + printk(KERN_ALERT "Failed to create timed thread\n"); + return -1; + } - gpio_set_value(GPIO_PIN, 0); - gpio_free(GPIO_PIN); + interval = ktime_set(0, SLOT_INTERVAL_NS); + hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + timer.function = timer_callback; + hrtimer_start(&timer, interval, HRTIMER_MODE_REL); - if(timed_thread) { - kthread_stop(timed_thread); - } + return 0; +} + +static void __exit lkm_exit(void) { + vfree(packet->data.values); + vfree(packet); + cdev_del(&mycdev); + device_destroy(class, MKDEV(major_number, 0)); + class_destroy(class); + unregister_chrdev_region(MKDEV(major_number, 0), 1); + printk(KERN_INFO "lkm: device removed successfully\n"); + + gpio_set_value(GPIO_PIN, 0); + gpio_free(GPIO_PIN); + + if (timed_thread) { + kthread_stop(timed_thread); + } - hrtimer_cancel(&timer); + hrtimer_cancel(&timer); } module_init(lkm_init);