Skip to content

Instantly share code, notes, and snippets.

@vbarboza
Created February 27, 2019 13:11
Show Gist options
  • Save vbarboza/3b5840b617038e2171ee2c78dfd66df4 to your computer and use it in GitHub Desktop.
Save vbarboza/3b5840b617038e2171ee2c78dfd66df4 to your computer and use it in GitHub Desktop.
Exploring Beagle Bone character device example.
#include <linux/init.h> // Macros used to mark up functions e.g. __init __exit
#include <linux/module.h> // Core header for loading LKMs into the kernel
#include <linux/device.h> // Header to support the kernel Driver Model
#include <linux/kernel.h> // Contains types, macros, functions for the kernel
#include <linux/fs.h> // Header for the Linux file system support
#include <linux/uaccess.h> // Required for the copy to user function
#define DEVICE_NAME "ebbchar" ///< The device will appear at /dev/ebbchar using this value
#define CLASS_NAME "ebb" ///< The device class -- this is a character device driver
MODULE_LICENSE("GPL"); ///< The license type -- this affects available functionality
MODULE_AUTHOR("Derek Molloy"); ///< The author -- visible when you use modinfo
MODULE_DESCRIPTION("A simple Linux char driver for the BBB"); ///< The description -- see modinfo
MODULE_VERSION("0.1"); ///< A version number to inform users
static int majorNumber; ///< Stores the device number -- determined automatically
static char message[256] = {0}; ///< Memory for the string that is passed from userspace
static short size_of_message; ///< Used to remember the size of the string stored
static int numberOpens = 0; ///< Counts the number of times the device is opened
static struct class* ebbcharClass = NULL; ///< The device-driver class struct pointer
static struct device* ebbcharDevice = NULL; ///< The device-driver device struct pointer
// The prototype functions for the character driver -- must come before the struct definition
static int dev_open(struct inode *, struct file *);
static int dev_release(struct inode *, struct file *);
static ssize_t dev_read(struct file *, char *, size_t, loff_t *);
static ssize_t dev_write(struct file *, const char *, size_t, loff_t *);
static struct file_operations fops =
{
.open = dev_open,
.read = dev_read,
.write = dev_write,
.release = dev_release,
};
static int __init ebbchar_init(void){
printk(KERN_INFO "EBBChar: Initializing the EBBChar LKM\n");
// Try to dynamically allocate a major number for the device -- more difficult but worth it
majorNumber = register_chrdev(0, DEVICE_NAME, &fops);
printk(KERN_INFO "EBBChar: registered correctly with major number %d\n", majorNumber);
// Register the device class
ebbcharClass = class_create(THIS_MODULE, CLASS_NAME);
printk(KERN_INFO "EBBChar: device class registered correctly\n");
// Register the device driver
ebbcharDevice = device_create(ebbcharClass, NULL, MKDEV(majorNumber, 0), NULL, DEVICE_NAME);
printk(KERN_INFO "EBBChar: device class created correctly\n"); // Made it! device was initialized
return 0;
}
static void __exit ebbchar_exit(void){
device_destroy(ebbcharClass, MKDEV(majorNumber, 0)); // remove the device
class_unregister(ebbcharClass); // unregister the device class
class_destroy(ebbcharClass); // remove the device class
unregister_chrdev(majorNumber, DEVICE_NAME); // unregister the major number
printk(KERN_INFO "EBBChar: Goodbye from the LKM!\n");
}
static int dev_open(struct inode *inodep, struct file *filep){
numberOpens++;
printk(KERN_INFO "EBBChar: Device has been opened %d time(s)\n", numberOpens);
return 0;
}
static ssize_t dev_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
int error_count = 0;
error_count = copy_to_user(buffer, message, size_of_message);
}
static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
sprintf(message, "%s(%zu letters)", buffer, len); // appending received string with its length
size_of_message = strlen(message); // store the length of the stored message
printk(KERN_INFO "EBBChar: Received %zu characters from the user\n", len);
return len;
}
static int dev_release(struct inode *inodep, struct file *filep){
printk(KERN_INFO "EBBChar: Device successfully closed\n");
return 0;
}
module_init(ebbchar_init);
module_exit(ebbchar_exit);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment