|
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 // handler processing write() requests from user-space |
|
21 ssize_t canftest_write(struct file *filp, const char __user *buf, size_t count, |
|
22 loff_t *f_pos) |
|
23 { |
|
24 int cmd; |
|
25 |
|
26 // get integer from user-space |
|
27 if (get_user (cmd, buf)) |
|
28 return -EFAULT; |
|
29 |
|
30 // process integer as command |
|
31 switch (cmd) { |
|
32 case CMD_START: |
|
33 wake_up_process (thread_start_p); |
|
34 break; |
|
35 case CMD_STOP: |
|
36 if (canftest_stopped) break; |
|
37 wake_up_process (thread_stop_p); |
|
38 break; |
|
39 // ignore new line character |
|
40 case 10: |
|
41 break; |
|
42 default: |
|
43 printk("canftest: bad command %d\n", cmd); |
|
44 break; |
|
45 } |
|
46 |
|
47 return count; |
|
48 } |
|
49 |
|
50 // register write() handler |
|
51 static struct file_operations canftest_fops = { |
|
52 .owner = THIS_MODULE, |
|
53 .write = canftest_write, |
|
54 }; |
|
55 |
|
56 // start TestMasterSlave example |
|
57 int thread_start (void* data) |
|
58 { |
|
59 int ret=0; |
|
60 |
|
61 down_interruptible (&canftest_mutex); |
|
62 |
|
63 ret=TestMasterSlave_start(); |
|
64 |
|
65 // if started |
|
66 if (ret == 0) { |
|
67 canftest_stopped = 0; |
|
68 |
|
69 // increment module usage count |
|
70 try_module_get(THIS_MODULE); |
|
71 } |
|
72 |
|
73 up (&canftest_mutex); |
|
74 |
|
75 return ret; |
|
76 } |
|
77 |
|
78 // finish TestMasterSlave example |
|
79 int thread_stop (void* data) |
|
80 { |
|
81 down_interruptible (&canftest_mutex); |
|
82 |
|
83 TestMasterSlave_stop(); |
|
84 canftest_stopped = 1; |
|
85 |
|
86 // decrement usage count |
|
87 module_put(THIS_MODULE); |
|
88 |
|
89 up (&canftest_mutex); |
|
90 |
|
91 return 0; |
|
92 } |
|
93 |
|
94 int init_module(void) |
|
95 { |
|
96 int ret, major; |
|
97 |
|
98 // get major device number dynamically |
|
99 ret = alloc_chrdev_region(&canftest_dev, minor, 1, DEVICE_NAME); |
|
100 major = MAJOR(canftest_dev); |
|
101 if (ret < 0) { |
|
102 printk(KERN_WARNING "canftest: can't get major %d\n", major); |
|
103 return ret; |
|
104 } |
|
105 |
|
106 canftest_cdev = cdev_alloc( ); |
|
107 canftest_cdev->owner = THIS_MODULE; |
|
108 canftest_cdev->ops = &canftest_fops; |
|
109 |
|
110 // register new character device |
|
111 ret = cdev_add (canftest_cdev, canftest_dev, 1); |
|
112 if (ret) { |
|
113 printk(KERN_WARNING "canftest: error %d adding char device\n", ret); |
|
114 return ret; |
|
115 } |
|
116 |
|
117 thread_start_p = kthread_create (thread_start, NULL, "canftest_start"); |
|
118 thread_stop_p = kthread_create (thread_stop, NULL, "canftest_stop"); |
|
119 |
|
120 if (PTR_ERR(thread_start_p) == -ENOMEM || PTR_ERR(thread_stop_p) == -ENOMEM) { |
|
121 printk(KERN_WARNING "canftest: error creating threads\n"); |
|
122 return -ENOMEM; |
|
123 } |
|
124 |
|
125 return 0; |
|
126 } |
|
127 |
|
128 void cleanup_module(void) |
|
129 { |
|
130 // unregister major device number and character device |
|
131 unregister_chrdev_region(canftest_dev, 1); |
|
132 cdev_del(canftest_cdev); |
|
133 } |