]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - examples/kerneltest/kernel_module.c
kerneltest updated for the new api
[CanFestival-3.git] / examples / kerneltest / kernel_module.c
1 #include <linux/module.h>
2 #include <linux/kthread.h>
3 #include <linux/fs.h>
4 #include <linux/cdev.h>
5 #include <asm/uaccess.h>
6
7 #include "TestMasterSlave.h"
8 #include "console/console.h"
9
10 #define minor 0
11
12 MODULE_LICENSE("GPL");
13
14 static dev_t canftest_dev;
15 static struct cdev *canftest_cdev;
16 static struct task_struct *thread_start_p, *thread_stop_p;
17 static DECLARE_MUTEX (canftest_mutex);
18 static int canftest_stopped = 1;
19
20 int thread_start (void* data);
21 int thread_stop (void* data);
22
23 // handler processing write() requests from user-space
24 ssize_t canftest_write(struct file *filp, const char __user *buf, size_t count,
25                        loff_t *f_pos)
26 {
27         int cmd;
28
29         // get integer from user-space
30         if (get_user (cmd, buf))
31                 return -EFAULT;
32
33         // process integer as command
34         switch (cmd) {
35                 case CMD_START:
36                         if (!canftest_stopped) break;
37                         thread_start_p = kthread_create (thread_start, NULL, "canftest_start");
38
39                         if (PTR_ERR(thread_start_p) == -ENOMEM) {
40                                 printk(KERN_WARNING "canftest: error creating start thread\n");
41                                 return -ENOMEM;
42                         }
43
44                         wake_up_process (thread_start_p);
45                         break;
46
47                 case CMD_STOP:
48                         if (canftest_stopped) break;
49                         thread_stop_p = kthread_create (thread_stop, NULL, "canftest_stop");
50
51                         if (PTR_ERR(thread_stop_p) == -ENOMEM) {
52                                 printk(KERN_WARNING "canftest: error creating stop thread\n");
53                                 return -ENOMEM;
54                         }
55
56                         wake_up_process (thread_stop_p);
57                         break;
58
59                 // ignore new line character
60                 case 10:
61                         break;
62
63                 default:
64                         printk("canftest: bad command %d\n", cmd);
65                         break;
66         }
67         
68         return count;
69 }
70
71 // register write() handler
72 static struct file_operations canftest_fops = {
73         .owner =    THIS_MODULE,
74         .write =    canftest_write,
75 };
76
77 // start TestMasterSlave example
78 int thread_start (void* data)
79 {
80         int ret=0;
81         
82         down_interruptible (&canftest_mutex);
83         
84         ret=TestMasterSlave_start();
85
86         // if started
87         if (ret == 0) {
88                 canftest_stopped = 0;
89
90                 // increment module usage count
91                 try_module_get(THIS_MODULE);
92         }
93         
94         up (&canftest_mutex);
95
96         return ret;
97 }
98
99 // finish TestMasterSlave example
100 int thread_stop (void* data)
101 {
102         down_interruptible (&canftest_mutex);
103
104         TestMasterSlave_stop();
105         canftest_stopped = 1;
106
107         // decrement usage count
108         module_put(THIS_MODULE);
109         
110         up (&canftest_mutex);
111
112         return 0;
113 }
114
115 int init_module(void)
116 {
117         int ret, major;
118
119         // get major device number dynamically
120         ret = alloc_chrdev_region(&canftest_dev, minor, 1, DEVICE_NAME);
121         major = MAJOR(canftest_dev);
122         if (ret < 0) {
123                 printk(KERN_WARNING "canftest: can't get major %d\n", major);
124                 return ret;
125         }
126         
127         canftest_cdev = cdev_alloc( );
128         canftest_cdev->owner = THIS_MODULE;
129         canftest_cdev->ops = &canftest_fops;
130         
131         // register new character device
132         ret = cdev_add (canftest_cdev, canftest_dev, 1);
133         if (ret) {
134                 printk(KERN_WARNING "canftest: error %d adding char device\n", ret);
135                 return ret;
136         }
137
138         return 0;
139 }
140
141 void cleanup_module(void)
142 {
143         // unregister major device number and character device
144         unregister_chrdev_region(canftest_dev, 1);
145         cdev_del(canftest_cdev);
146 }