examples/kerneltest/kernel_module.c
changeset 391 7802a7d5584f
child 467 40efa79d27dd
equal deleted inserted replaced
390:31dc4ec8710c 391:7802a7d5584f
       
     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 }