Skip to content
Snippets Groups Projects
Commit e7e1aa6b authored by David Maul's avatar David Maul :crab:
Browse files

feat: buffer messages in userspace and improve message handling in kernel module

parent d4413e6a
No related branches found
No related tags found
No related merge requests found
#include <linux/module.h> #include "../common/include/data.h"
#include <linux/kernel.h> #include "../common/include/message.h"
#include <linux/fs.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include <linux/vmalloc.h> #include <linux/crc32.h>
#include <linux/uaccess.h> #include <linux/delay.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/hrtimer.h> #include <linux/hrtimer.h>
#include <linux/kernel.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/gpio.h> #include <linux/module.h>
#include <linux/delay.h> #include <linux/uaccess.h>
#include <linux/crc32.h> #include <linux/vmalloc.h>
#include "../common/include/message.h"
#define DEVICE_NAME "amogus" #define DEVICE_NAME "amogus"
#define CLASS_NAME "amogus_class" #define CLASS_NAME "amogus_class"
#define SLOTS 4 #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 int major_number;
static struct class *class = NULL; static struct class *class = NULL;
static struct cdev mycdev; 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 struct hrtimer timer;
static ktime_t interval; static ktime_t interval;
...@@ -35,43 +43,55 @@ static atomic_t wake_counter = ATOMIC_INIT(0); ...@@ -35,43 +43,55 @@ static atomic_t wake_counter = ATOMIC_INIT(0);
static int slot = 0; static int slot = 0;
typedef struct packet { static int device_open(struct inode *inode, struct file *file) { return 0; }
message_t data;
uint32_t crc;
} packet_t;
static int device_open(struct inode *inode, struct file *file) static int device_release(struct inode *inode, struct file *file) { return 0; }
{
return 0;
}
static int device_release(struct inode *inode, struct file *file) static uint32_t calculate_crc32(const data_t *data) {
{ uint32_t crc = crc32(0, (void *)&data->sensor_id, sizeof(uint8_t));
return 0; 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, static ssize_t device_write(struct file *filp, const char *input, size_t length,
size_t length, loff_t *offset) loff_t *offset) {
{ if (length != sizeof(data_t)) {
if(length != sizeof(message_t)) {
printk(KERN_ALERT "lkm: Tried to write more bytes than allowed\n"); printk(KERN_ALERT "lkm: Tried to write more bytes than allowed\n");
return -EFAULT; return -EFAULT;
} }
if (copy_from_user((void*)message, input, length)) { if (((data_t *)input)->count >= MAX_VALUES) {
printk(KERN_ALERT "lkm: Tried to write more messages than allowed\n");
return -EFAULT; return -EFAULT;
} }
if (copy_from_user((void *)&(packet->data.sensor_id),
(void *)&(((data_t *)input)->sensor_id),
sizeof(uint8_t))) {
return -EFAULT;
}
if (copy_from_user((void *)&(packet->data.count),
(void *)&(((data_t *)input)->count), sizeof(uint8_t))) {
return -EFAULT;
}
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); printk(KERN_INFO "lkm: received write of size %zu\n", length);
return length; return length;
} }
static const struct file_operations fops = { static const struct file_operations fops = {
.write = device_write, .write = device_write, .open = device_open, .release = device_release};
.open = device_open,
.release = device_release
};
static enum hrtimer_restart timer_callback(struct hrtimer *timer) { static enum hrtimer_restart timer_callback(struct hrtimer *timer) {
atomic_inc(&wake_counter); atomic_inc(&wake_counter);
...@@ -97,16 +117,21 @@ static void send_byte(uint8_t byte) { ...@@ -97,16 +117,21 @@ static void send_byte(uint8_t byte) {
send_bit(1); send_bit(1);
} }
static void send_data(const void *data, size_t length) { static void send_data(const packet_t *packet) {
const uint8_t *bytes = (const uint8_t*)data; send_byte(packet->data.sensor_id);
send_byte(packet->data.count);
uint8_t *bytes = (uint8_t *)packet->data.values;
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < sizeof(message_t) * packet->data.count; i++) {
send_byte(bytes[i]); send_byte(bytes[i]);
} }
}
static uint32_t calculate_crc32(const void *data, size_t length){ bytes = (uint8_t *)&packet->crc;
return crc32(0, data, length);
for (size_t i = 0; i < sizeof(uint32_t); i++) {
send_byte(bytes[i]);
}
} }
static int timed_thread_fn(void *args) { static int timed_thread_fn(void *args) {
...@@ -115,12 +140,7 @@ static int timed_thread_fn(void *args) { ...@@ -115,12 +140,7 @@ static int timed_thread_fn(void *args) {
atomic_dec(&wake_counter); atomic_dec(&wake_counter);
if (slot == 0) { if (slot == 0) {
packet_t packet; send_data(packet);
packet.data = *message;
packet.crc = calculate_crc32(&packet.data, sizeof(&packet.data));
send_data(&packet, sizeof(packet));
} }
slot = (slot + 1) % SLOTS; slot = (slot + 1) % SLOTS;
...@@ -129,19 +149,29 @@ static int timed_thread_fn(void *args) { ...@@ -129,19 +149,29 @@ static int timed_thread_fn(void *args) {
return 0; return 0;
} }
static int __init lkm_init(void) static int __init lkm_init(void) {
{
dev_t dev; dev_t dev;
message = (message_t*)vmalloc(sizeof(message_t)); packet = (packet_t *)vmalloc(sizeof(packet_t));
if(message == NULL) { if (packet == NULL) {
return -1; return -EFAULT;
}
packet->data.sensor_id = 0x7C;
packet->data.count = 0;
packet->data.values = (message_t *)vmalloc(sizeof(message_t) * MAX_VALUES);
if (packet->data.values == NULL) {
vfree(packet);
return -EFAULT;
} }
// Dynamically allocate major number // Dynamically allocate major number
if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) { if (alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME) < 0) {
vfree(message); vfree(packet->data.values);
vfree(packet);
printk(KERN_ALERT "Failed to allocate major number\n"); printk(KERN_ALERT "Failed to allocate major number\n");
return -1; return -1;
} }
...@@ -149,14 +179,17 @@ static int __init lkm_init(void) ...@@ -149,14 +179,17 @@ static int __init lkm_init(void)
class = class_create(CLASS_NAME); class = class_create(CLASS_NAME);
if (IS_ERR(class)) { if (IS_ERR(class)) {
vfree(message); vfree(packet->data.values);
vfree(packet);
unregister_chrdev_region(MKDEV(major_number, 0), 1); unregister_chrdev_region(MKDEV(major_number, 0), 1);
printk(KERN_ALERT "Failed to create device class\n"); printk(KERN_ALERT "Failed to create device class\n");
return PTR_ERR(class); return PTR_ERR(class);
} }
if (device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME) == NULL) { if (device_create(class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME) ==
vfree(message); NULL) {
vfree(packet->data.values);
vfree(packet);
class_destroy(class); class_destroy(class);
unregister_chrdev_region(MKDEV(major_number, 0), 1); unregister_chrdev_region(MKDEV(major_number, 0), 1);
printk(KERN_ALERT "Failed to create device\n"); printk(KERN_ALERT "Failed to create device\n");
...@@ -165,7 +198,8 @@ static int __init lkm_init(void) ...@@ -165,7 +198,8 @@ static int __init lkm_init(void)
cdev_init(&mycdev, &fops); cdev_init(&mycdev, &fops);
if (cdev_add(&mycdev, MKDEV(major_number, 0), 1) < 0) { if (cdev_add(&mycdev, MKDEV(major_number, 0), 1) < 0) {
vfree(message); vfree(packet->data.values);
vfree(packet);
device_destroy(class, MKDEV(major_number, 0)); device_destroy(class, MKDEV(major_number, 0));
class_destroy(class); class_destroy(class);
unregister_chrdev_region(MKDEV(major_number, 0), 1); unregister_chrdev_region(MKDEV(major_number, 0), 1);
...@@ -176,7 +210,8 @@ static int __init lkm_init(void) ...@@ -176,7 +210,8 @@ static int __init lkm_init(void)
printk(KERN_INFO "lkm: device created successfully\n"); printk(KERN_INFO "lkm: device created successfully\n");
if (gpio_request(GPIO_PIN, "GPIO_PIN") < 0) { if (gpio_request(GPIO_PIN, "GPIO_PIN") < 0) {
vfree(message); vfree(packet->data.values);
vfree(packet);
cdev_del(&mycdev); cdev_del(&mycdev);
device_destroy(class, MKDEV(major_number, 0)); device_destroy(class, MKDEV(major_number, 0));
class_destroy(class); class_destroy(class);
...@@ -188,7 +223,8 @@ static int __init lkm_init(void) ...@@ -188,7 +223,8 @@ static int __init lkm_init(void)
timed_thread = kthread_run(timed_thread_fn, NULL, "timed_thread"); timed_thread = kthread_run(timed_thread_fn, NULL, "timed_thread");
if (IS_ERR(timed_thread)) { if (IS_ERR(timed_thread)) {
vfree(message); vfree(packet->data.values);
vfree(packet);
cdev_del(&mycdev); cdev_del(&mycdev);
device_destroy(class, MKDEV(major_number, 0)); device_destroy(class, MKDEV(major_number, 0));
class_destroy(class); class_destroy(class);
...@@ -205,9 +241,9 @@ static int __init lkm_init(void) ...@@ -205,9 +241,9 @@ static int __init lkm_init(void)
return 0; return 0;
} }
static void __exit lkm_exit(void) static void __exit lkm_exit(void) {
{ vfree(packet->data.values);
vfree(message); vfree(packet);
cdev_del(&mycdev); cdev_del(&mycdev);
device_destroy(class, MKDEV(major_number, 0)); device_destroy(class, MKDEV(major_number, 0));
class_destroy(class); class_destroy(class);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment