--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/kerneltest/kernel_module.c Tue Feb 12 09:44:55 2008 +0100
@@ -0,0 +1,133 @@
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h>
+
+#include "TestMasterSlave.h"
+#include "console/console.h"
+
+#define minor 0
+
+MODULE_LICENSE("GPL");
+
+static dev_t canftest_dev;
+static struct cdev *canftest_cdev;
+static struct task_struct *thread_start_p, *thread_stop_p;
+static DECLARE_MUTEX (canftest_mutex);
+static int canftest_stopped = 1;
+
+// handler processing write() requests from user-space
+ssize_t canftest_write(struct file *filp, const char __user *buf, size_t count,
+ loff_t *f_pos)
+{
+ int cmd;
+
+ // get integer from user-space
+ if (get_user (cmd, buf))
+ return -EFAULT;
+
+ // process integer as command
+ switch (cmd) {
+ case CMD_START:
+ wake_up_process (thread_start_p);
+ break;
+ case CMD_STOP:
+ if (canftest_stopped) break;
+ wake_up_process (thread_stop_p);
+ break;
+ // ignore new line character
+ case 10:
+ break;
+ default:
+ printk("canftest: bad command %d\n", cmd);
+ break;
+ }
+
+ return count;
+}
+
+// register write() handler
+static struct file_operations canftest_fops = {
+ .owner = THIS_MODULE,
+ .write = canftest_write,
+};
+
+// start TestMasterSlave example
+int thread_start (void* data)
+{
+ int ret=0;
+
+ down_interruptible (&canftest_mutex);
+
+ ret=TestMasterSlave_start();
+
+ // if started
+ if (ret == 0) {
+ canftest_stopped = 0;
+
+ // increment module usage count
+ try_module_get(THIS_MODULE);
+ }
+
+ up (&canftest_mutex);
+
+ return ret;
+}
+
+// finish TestMasterSlave example
+int thread_stop (void* data)
+{
+ down_interruptible (&canftest_mutex);
+
+ TestMasterSlave_stop();
+ canftest_stopped = 1;
+
+ // decrement usage count
+ module_put(THIS_MODULE);
+
+ up (&canftest_mutex);
+
+ return 0;
+}
+
+int init_module(void)
+{
+ int ret, major;
+
+ // get major device number dynamically
+ ret = alloc_chrdev_region(&canftest_dev, minor, 1, DEVICE_NAME);
+ major = MAJOR(canftest_dev);
+ if (ret < 0) {
+ printk(KERN_WARNING "canftest: can't get major %d\n", major);
+ return ret;
+ }
+
+ canftest_cdev = cdev_alloc( );
+ canftest_cdev->owner = THIS_MODULE;
+ canftest_cdev->ops = &canftest_fops;
+
+ // register new character device
+ ret = cdev_add (canftest_cdev, canftest_dev, 1);
+ if (ret) {
+ printk(KERN_WARNING "canftest: error %d adding char device\n", ret);
+ return ret;
+ }
+
+ thread_start_p = kthread_create (thread_start, NULL, "canftest_start");
+ thread_stop_p = kthread_create (thread_stop, NULL, "canftest_stop");
+
+ if (PTR_ERR(thread_start_p) == -ENOMEM || PTR_ERR(thread_stop_p) == -ENOMEM) {
+ printk(KERN_WARNING "canftest: error creating threads\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ // unregister major device number and character device
+ unregister_chrdev_region(canftest_dev, 1);
+ cdev_del(canftest_cdev);
+}