rev |
line source |
eleni@0
|
1 #include <asm/uaccess.h>
|
eleni@0
|
2 #include <linux/fs.h>
|
eleni@0
|
3 #include <linux/kernel.h>
|
eleni@0
|
4 #include <linux/module.h>
|
eleni@0
|
5 #include <linux/slab.h>
|
eleni@0
|
6
|
eleni@0
|
7 #define DEV_NAME "ktest"
|
eleni@0
|
8
|
eleni@0
|
9 static int ktest_init(void);
|
eleni@0
|
10 static void ktest_fini(void);
|
eleni@0
|
11
|
eleni@0
|
12 static int ktest_open(struct inode *inode, struct file *file);
|
eleni@0
|
13 static int ktest_release(struct inode *inode, struct file *file);
|
eleni@0
|
14 static ssize_t ktest_read(struct file *file, char *buf, size_t buf_size,
|
eleni@0
|
15 loff_t *offset);
|
eleni@0
|
16
|
eleni@0
|
17 static int dev_num;
|
eleni@0
|
18 static struct file_operations ops = {
|
eleni@0
|
19 .open = ktest_open,
|
eleni@0
|
20 .release = ktest_release,
|
eleni@0
|
21 .read = ktest_read
|
eleni@0
|
22 };
|
eleni@0
|
23 static int hello_counter;
|
eleni@0
|
24
|
eleni@0
|
25 /* macros */
|
eleni@0
|
26
|
eleni@0
|
27 MODULE_LICENSE("GPL");
|
eleni@0
|
28 MODULE_AUTHOR("hikiko");
|
eleni@0
|
29 MODULE_DESCRIPTION("my kernel helloworld");
|
eleni@0
|
30
|
eleni@0
|
31 module_init(ktest_init);
|
eleni@0
|
32 module_exit(ktest_fini);
|
eleni@0
|
33
|
eleni@0
|
34 static int ktest_init(void)
|
eleni@0
|
35 {
|
eleni@0
|
36 hello_counter = 0;
|
eleni@0
|
37
|
eleni@0
|
38 /* register character device */
|
eleni@0
|
39 if((dev_num = register_chrdev(0, DEV_NAME, &ops)) < 0) {
|
eleni@0
|
40 printk(KERN_ALERT "Failed to register character device.\n");
|
eleni@0
|
41 return -1;
|
eleni@0
|
42 }
|
eleni@0
|
43 printk(KERN_INFO "Registered character device. Name: %s number: %d.\n", DEV_NAME, dev_num);
|
eleni@0
|
44 return 0;
|
eleni@0
|
45 }
|
eleni@0
|
46
|
eleni@0
|
47 static void ktest_fini(void)
|
eleni@0
|
48 {
|
eleni@0
|
49 unregister_chrdev(dev_num, DEV_NAME);
|
eleni@0
|
50 printk(KERN_INFO "Unregistered character device. Name: %s number: %d.\n", DEV_NAME, dev_num);
|
eleni@0
|
51 }
|
eleni@0
|
52
|
eleni@0
|
53 static int ktest_open(struct inode *inode, struct file *file)
|
eleni@0
|
54 {
|
eleni@0
|
55 /* 1 device file only => we ignore the params ^ */
|
eleni@0
|
56 try_module_get(THIS_MODULE);
|
eleni@0
|
57 return 0;
|
eleni@0
|
58 }
|
eleni@0
|
59
|
eleni@0
|
60 static int ktest_release(struct inode *inode, struct file *file)
|
eleni@0
|
61 {
|
eleni@0
|
62 module_put(THIS_MODULE);
|
eleni@0
|
63 return 0;
|
eleni@0
|
64 }
|
eleni@0
|
65
|
eleni@0
|
66 static ssize_t ktest_read(struct file *file, char *buf, size_t buf_size,
|
eleni@0
|
67 loff_t *offset)
|
eleni@0
|
68 {
|
eleni@0
|
69 /* buf = userspace buffer,
|
eleni@0
|
70 * kbuf = kernel buffer */
|
eleni@0
|
71
|
eleni@0
|
72 char *kbuf;
|
eleni@0
|
73 int bytes;
|
eleni@0
|
74
|
eleni@0
|
75 if(!(kbuf = kmalloc(buf_size, GFP_KERNEL))) {
|
eleni@0
|
76 printk(KERN_ALERT "Failed to allocate memory.\n");
|
eleni@0
|
77 return -ENOMEM;
|
eleni@0
|
78 }
|
eleni@0
|
79
|
eleni@0
|
80 /* fill kbuf and copy to userspace buf */
|
eleni@0
|
81 bytes = snprintf(kbuf, buf_size, "Hello world, num: %d.\n", ++hello_counter);
|
eleni@0
|
82
|
eleni@0
|
83 if(copy_to_user(buf, kbuf, bytes))
|
eleni@0
|
84 {
|
eleni@0
|
85 kfree(kbuf);
|
eleni@0
|
86 return -EFAULT;
|
eleni@0
|
87 }
|
eleni@0
|
88
|
eleni@0
|
89 kfree(kbuf);
|
eleni@0
|
90 return bytes;
|
eleni@0
|
91 }
|