Skip to content

Instantly share code, notes, and snippets.

@sandeepbhuyan
Forked from itrobotics/chrdev.c
Created June 7, 2018 16:36
Show Gist options
  • Save sandeepbhuyan/f31daae41ed951e38abaf2a0c9faa7fa to your computer and use it in GitHub Desktop.
Save sandeepbhuyan/f31daae41ed951e38abaf2a0c9faa7fa to your computer and use it in GitHub Desktop.
a simple char device example for linux module
/*******************************************************************************
* Copyright (c) 2015 Song Yang @ ittraining
*
* All rights reserved.
* This program is free to use, but the ban on selling behavior.
* Modify the program must keep all the original text description.
*
* 保留所有權利。
* 本程式可任意使用,但是禁止販售行為。
* 修改程式時必須保留所有原有文字說明。
*
* Email: [email protected]
* Blog : http://blog.ittraining.com.tw
*******************************************************************************/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#define MY_MAJOR 200
#define MY_MINOR 0
#define MY_DEV_COUNT 2
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ITtraining.com.tw");
MODULE_DESCRIPTION("A Simple GPIO Device Driver module for RaspPi");
static int my_open( struct inode *, struct file * );
static ssize_t my_read( struct file * , char * , size_t, loff_t *);
static ssize_t my_write(struct file * , const char * , size_t, loff_t *);
static int my_close(struct inode *, struct file * );
struct file_operations my_fops = {
read : my_read,
write : my_write,
open : my_open,
release : my_close,
owner : THIS_MODULE
};
struct cdev my_cdev;
static char *msg = NULL;
/*
* INIT_MODULE -- MODULE START --
* */
int init_module(void)
{
// -- initial the device number
dev_t devno;
unsigned int count = MY_DEV_COUNT;
int err;
devno = MKDEV(MY_MAJOR, MY_MINOR);
register_chrdev_region(devno, count , "mydev");
// -- initial the char device
cdev_init(&my_cdev, &my_fops);
my_cdev.owner = THIS_MODULE;
err = cdev_add(&my_cdev, devno, count);
// -- check error of adding char device
if (err < 0)
{
printk("Device Add Error\n");
return -1;
}
printk("Hello World. This is my first char dev.\n");
printk("'mknod /dev/mydev_0 c %d 0'.\n", MY_MAJOR);
printk("'mknod /dev/mydev_1 c %d 1'.\n", MY_MAJOR);
msg = (char *)kmalloc(32, GFP_KERNEL);
if (msg !=NULL)
printk("malloc allocator address: 0x%p\n", msg);
return 0;
}
/*
* CLEANUP_MODULE -- MODULE END --
* */
void cleanup_module(void)
{
dev_t devno;
printk("Goodbye\n");
if (msg){
/* release the malloc */
kfree(msg);
}
// -- release the char device
devno = MKDEV(MY_MAJOR, MY_MINOR);
unregister_chrdev_region(devno, MY_DEV_COUNT);
cdev_del(&my_cdev);
}
/*
* file operation: OPEN
* */
static int my_open(struct inode *inod, struct file *fil)
{
int major;
int minor;
major = imajor(inod);
minor = iminor(inod);
printk("\n*****Some body is opening me at major %d minor %d*****\n",major, minor);
return 0;
}
/*
* file operation: READ
* */
static ssize_t my_read(struct file *filp, char *buff, size_t len, loff_t *off)
{
int major, minor;
short count;
major = MAJOR(filp->f_dentry->d_inode->i_rdev);
minor = MINOR(filp->f_dentry->d_inode->i_rdev);
printk("FILE OPERATION READ:%d:%d\n", major, minor);
switch(minor){
case 0:
strcpy(msg,"DATA FROM MOUDLE: minor : 0");
break;
case 1:
strcpy(msg,"DATA FROM MOUDLE: minor : 1");
break;
default:
len = 0;
}
count = copy_to_user( buff, msg, len);
return 0;
}
/*
* file operation: WRITE
* */
static ssize_t my_write(struct file *filp, const char *buff, size_t len, loff_t *off)
{
int major,minor;
short count;
memset(msg, 0, 32);
major = MAJOR(filp->f_dentry->d_inode->i_rdev);
minor = MINOR(filp->f_dentry->d_inode->i_rdev);
// -- copy the string from the user space program which open and write this device
count = copy_from_user( msg, buff, len );
printk("FILE OPERATION WRITE:%d:%d\n",major,minor);
printk("msg: %s", msg);
return len;
}
/*
* file operation : CLOSE
* */
static int my_close(struct inode *inod, struct file *fil)
{
int minor;
minor = MINOR(fil->f_dentry->d_inode->i_rdev);
printk("*****Some body is closing me at major %d*****\n",minor);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment