-
Notifications
You must be signed in to change notification settings - Fork 54
/
platform-dummy-char.c
112 lines (96 loc) · 3.16 KB
/
platform-dummy-char.c
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
109
110
111
112
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h> /* For platform devices */
#include <linux/cdev.h>
#include <linux/fs.h>
static unsigned int major; /* major number for device */
static struct class *dummy_class;
static struct cdev dummy_cdev;
int dummy_open(struct inode * inode, struct file * filp)
{
pr_info("Someone tried to open me\n");
return 0;
}
int dummy_release(struct inode * inode, struct file * filp)
{
pr_info("Someone closed me\n");
return 0;
}
ssize_t dummy_read (struct file *filp, char __user * buf, size_t count,
loff_t * offset)
{
pr_info("Nothing to read guy\n");
return 0;
}
ssize_t dummy_write(struct file * filp, const char __user * buf, size_t count,
loff_t * offset)
{
pr_info("Can't accept any data guy\n");
return count;
}
struct file_operations dummy_fops = {
open: dummy_open,
release: dummy_release,
read: dummy_read,
write: dummy_write,
};
static int my_pdrv_probe (struct platform_device *pdev)
{
struct device *dummy_device;
int error;
dev_t devt = 0;
/* Get a range of minor numbers (starting with 0) to work with */
error = alloc_chrdev_region(&devt, 0, 1, "dummy_char");
if (error < 0) {
pr_err("Can't get major number\n");
return error;
}
major = MAJOR(devt);
pr_info("dummy_char major number = %d\n",major);
/* Create device class, visible in /sys/class */
dummy_class = class_create(THIS_MODULE, "dummy_char_class");
if (IS_ERR(dummy_class)) {
pr_err("Error creating sdma test module class.\n");
unregister_chrdev_region(MKDEV(major, 0), 1);
return PTR_ERR(dummy_class);
}
/* Initialize the char device and tie a file_operations to it */
cdev_init(&dummy_cdev, &dummy_fops);
dummy_cdev.owner = THIS_MODULE;
/* Now make the device live for the users to access */
cdev_add(&dummy_cdev, devt, 1);
dummy_device = device_create(dummy_class,
&pdev->dev, /* no parent device */
devt, /* associated dev_t */
NULL, /* no additional data */
"dummy_char"); /* device name */
if (IS_ERR(dummy_device)) {
pr_err("Error creating sdma test class device.\n");
class_destroy(dummy_class);
unregister_chrdev_region(devt, 1);
return -1;
}
pr_info("dummy char module loaded\n");
return 0;
}
static int my_pdrv_remove(struct platform_device *pdev)
{
unregister_chrdev_region(MKDEV(major, 0), 1);
device_destroy(dummy_class, MKDEV(major, 0));
cdev_del(&dummy_cdev);
class_destroy(dummy_class);
pr_info("dummy char module Unloaded\n");
return 0;
}
static struct platform_driver mypdrv = {
.probe = my_pdrv_probe,
.remove = my_pdrv_remove,
.driver = {
.name = "platform-dummy-char",
.owner = THIS_MODULE,
},
};
module_platform_driver(mypdrv);
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>");
MODULE_LICENSE("GPL");