-Linux character driver example on 3.19.0-43-generic -


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
 
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
 
static DEFINE_MUTEX(mutexIoctl);
//Mutex for unlocked_ioctl
 
static unsigned char* chpBuf = NULL;
//Device buffer pointer
 
static int memOpen(struct inode *inp, struct file *fp);
static int memRel(struct inode *inp, struct file *fp);
static ssize_t memRead(struct file *fp, unsigned char *chpOut, size_t sztCount, loff_t *loftPos);
static ssize_t memWrite(struct file *fp, const unsigned char __user *chpIn, size_t sztCount, loff_t *loftPos);
static long memIoctl(struct file *fp, unsigned int iNum, unsigned long iParam);
//Device callback functions
 
static struct file_operations fileOpers;
static bool bFlag = false;
//Custom device mutex
 
static int __init kernmodule_init(void)
{
    void *vpErr;
    //Error pointer
    
    fileOpers.read = memRead;
    fileOpers.write = memWrite;
    fileOpers.open = memOpen;
    fileOpers.release = memRel;
    fileOpers.unlocked_ioctl = memIoctl;
    //Allocate callback functions
 
    if(register_chrdev(200"kernmodule", &fileOpers) < 0)
        return -EIO;
    //Register character device (major = 200, device name = kernmodule)
 
    chpBuf = kmalloc(32, GFP_USER);
    if(IS_ERR(vpErr = chpBuf))
        return -ENOMEM;
    memset(chpBuf, 032);
    //Allocate memory area for device buffer
 
}
 
static void __exit kernmodule_exit(void)
{
       unregister_chrdev(200"kernmodule");
       //Unregister character device
 
       if(chpBuf)
        kfree(chpBuf);
}
 
static int memOpen(struct inode *inp, struct file *fp){
    //Device file open
    if(bFlag)
        return -EBUSY;
    bFlag = true;
    return 0;
}
 
static int memRel(struct inode *inp, struct file *fp){
    //Device file release
    bFlag = false;
    return 0;
}
 
static ssize_t memRead(struct file *fp, unsigned char __user *chpOut, size_t sztCount, loff_t *loftPos){
    //read() from device file
    if(sztCount > 32)
        return -1;
    if(bFlag)
        copy_to_user(chpOut, chpBuf, sztCount);
    return sztCount;
}
 
static ssize_t memWrite(struct file *fp, const unsigned char __user *chpIn, size_t sztCount, loff_t *loftPos){
    //write() to device file
    if(sztCount > 32)
        return -1;
    if(bFlag)
        copy_from_user(chpBuf, chpIn, sztCount);
    return sztCount;
 
static long memIoctl(struct file *fp, unsigned int uiNum, unsigned long ulParam)
{
    int iIter = 0;
    mutex_lock(&mutexIoctl);
    //ioctl Routine(User-level application can access with ioctl() function)
    mutex_unlock(&mutexIoctl);
    return 0;
}
//unlocked_ioctl : normal ioctl was deprecated
 
module_init(kernmodule_init);
module_exit(kernmodule_exit);
 
 
cs
Posted by RevDev
,