/*The drive test code as below*/
#include<stdio.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
int main()
{
int count = 0;
int fd = NULL;
unsigned char buf[100];
unsigned char buf_read[100];
memset(buf_read, 0, 100);
memset(buf, 0, 100);
fd = open("/dev/short_drv0", O_RDWR, S_IRUSR | S_IWUSR);
printf("fd vlaue :%d\n", fd);
printf("input string:");
scanf("%s", buf);
// const char * strTmp = "hello ryan, this is your first linux driver";
// strncpy(buf, strTmp, strlen(strTmp));
count = strlen(buf);
if(count > 100)
count = 100;
count = write(fd, buf, count);
read(fd,buf_read, count);
printf("buf_read: %s\n", buf_read);
close(fd);
return 0;
}
/* Drive souce code as below*/
/*
description: The relationship bewteeen user functions and kernel functions
*/
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include<linux/module.h>
#include <linux/uaccess.h>
#include <linux/semaphore.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/rfkill.h>
#define MAJOR_NUM 249
#define MINOR_NUM 0
static struct class * short_class;
static struct cdev short_cdev;
static dev_t devnum = 0;
static char * modname = "short_drv";
static char * devicename = "short_drv0";
static char * classname = "short_drv_class";
static struct semaphore sem;
static unsigned char kbuf[100] = {0};
static int short_open(struct inode *inode, struct file* pfile)
{
printk(KERN_EMERG " + short_open() \n");
return 0;
}
static int short_release(struct inode* inode, struct file *pfile)
{
printk(KERN_EMERG "-short_rlease() \n");
return 0;
}
ssize_t short_read (struct file *pfile, char *user_buf, size_t len, loff_t *off)
{
int iretval = len;
if(len > 100)
len = 100;
copy_to_user(user_buf, kbuf, len);
return iretval;
}
ssize_t short_write(struct file *pfile, const char *user_buf, size_t len, loff_t *off)
{
int iretval = len;
if(len > 100)
len = 100;
printk("Ryan: %s\n",user_buf);
copy_from_user(kbuf, user_buf, len);
printk("user input string is :%s\n", kbuf);
return iretval;
}
struct file_operations short_fops ={
.open = short_open,
.read = short_read,
.write = short_write,
.release = short_release,
};
static int __init short_drv_init(void)
{
int result = 0;
printk("short_drv_init(void) \n");
printk(KERN_EMERG " + short_drv_init(void) \n");
devnum = MKDEV(MAJOR_NUM,MINOR_NUM); // get device number
result = register_chrdev_region(devnum , 1, modname);
if(result < 0)
{
printk( KERN_EMERG "short_drv_init : can't get major number!\n");
return result;
}
cdev_init(&short_cdev, &short_fops);
short_cdev.owner = THIS_MODULE;
short_cdev.ops = &short_fops;
result = cdev_add(&short_cdev, devnum ,1);
if(result < 0)
{
printk( KERN_EMERG "cdev_add() execute failed!\n");
return result;
}
short_class = class_create(THIS_MODULE, classname);
if(IS_ERR(short_class))
{
printk( KERN_EMERG "Failed at class_create().Please exec [mknod] before operate the device\n");
}
else
{
device_create(short_class, NULL, devnum ,NULL, devicename);
}
sema_init(&sem, 1);
printk( KERN_EMERG "-test_mod_init()!\n");
return 0;
}
static void __exit short_drv_exit(void)
{
printk( KERN_EMERG "+test_mod_exit!\n");
unregister_chrdev_region(devnum, 1);
cdev_del(&short_cdev);
device_destroy(short_class, devnum);
class_destroy(short_class);
printk( KERN_EMERG "-test_mod_exit!\n");
}
module_init(short_drv_init);
module_exit(short_drv_exit);
MODULE_LICENSE("Dual BSD/GPL");
/*The driver makefile*/
ifneq ($(KERNELRELEASE),)
obj-m := short_drv.o
else
KDIR:=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
endif
clean:
rm -f *.o *.ko *.mod.c .short_drv*