examples/kerneltest/kernel_module.c
author etisserant
Fri, 25 Apr 2008 12:18:23 +0200
changeset 448 732c33c2d8a7
parent 391 7802a7d5584f
child 467 40efa79d27dd
permissions -rw-r--r--
CAN over Serial link (TTY) interface, with serial hub software. Thanks to James Steward.
391
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     1
#include <linux/module.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     2
#include <linux/kthread.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     3
#include <linux/fs.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     4
#include <linux/cdev.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     5
#include <asm/uaccess.h>
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     6
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     7
#include "TestMasterSlave.h"
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     8
#include "console/console.h"
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
     9
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    10
#define minor 0
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    11
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    12
MODULE_LICENSE("GPL");
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    13
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    14
static dev_t canftest_dev;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    15
static struct cdev *canftest_cdev;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    16
static struct task_struct *thread_start_p, *thread_stop_p;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    17
static DECLARE_MUTEX (canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    18
static int canftest_stopped = 1;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    19
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    20
// handler processing write() requests from user-space
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    21
ssize_t canftest_write(struct file *filp, const char __user *buf, size_t count,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    22
		       loff_t *f_pos)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    23
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    24
	int cmd;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    25
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    26
	// get integer from user-space
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    27
	if (get_user (cmd, buf))
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    28
		return -EFAULT;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    29
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    30
	// process integer as command
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    31
	switch (cmd) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    32
		case CMD_START:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    33
			wake_up_process (thread_start_p);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    34
			break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    35
		case CMD_STOP:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    36
			if (canftest_stopped) break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    37
			wake_up_process (thread_stop_p);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    38
			break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    39
		// ignore new line character
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    40
		case 10:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    41
			break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    42
		default:
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    43
			printk("canftest: bad command %d\n", cmd);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    44
			break;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    45
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    46
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    47
	return count;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    48
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    49
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    50
// register write() handler
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    51
static struct file_operations canftest_fops = {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    52
	.owner =    THIS_MODULE,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    53
	.write =    canftest_write,
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    54
};
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    55
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    56
// start TestMasterSlave example
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    57
int thread_start (void* data)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    58
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    59
	int ret=0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    60
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    61
	down_interruptible (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    62
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    63
	ret=TestMasterSlave_start();
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    64
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    65
	// if started
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    66
	if (ret == 0) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    67
		canftest_stopped = 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    68
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    69
		// increment module usage count
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    70
		try_module_get(THIS_MODULE);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    71
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    72
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    73
	up (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    74
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    75
	return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    76
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    77
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    78
// finish TestMasterSlave example
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    79
int thread_stop (void* data)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    80
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    81
	down_interruptible (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    82
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    83
	TestMasterSlave_stop();
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    84
	canftest_stopped = 1;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    85
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    86
	// decrement usage count
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    87
	module_put(THIS_MODULE);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    88
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    89
	up (&canftest_mutex);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    90
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    91
	return 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    92
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    93
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    94
int init_module(void)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    95
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    96
	int ret, major;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    97
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    98
	// get major device number dynamically
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
    99
	ret = alloc_chrdev_region(&canftest_dev, minor, 1, DEVICE_NAME);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   100
	major = MAJOR(canftest_dev);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   101
	if (ret < 0) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   102
		printk(KERN_WARNING "canftest: can't get major %d\n", major);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   103
		return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   104
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   105
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   106
	canftest_cdev = cdev_alloc( );
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   107
	canftest_cdev->owner = THIS_MODULE;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   108
	canftest_cdev->ops = &canftest_fops;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   109
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   110
	// register new character device
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   111
	ret = cdev_add (canftest_cdev, canftest_dev, 1);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   112
	if (ret) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   113
		printk(KERN_WARNING "canftest: error %d adding char device\n", ret);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   114
		return ret;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   115
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   116
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   117
	thread_start_p = kthread_create (thread_start, NULL, "canftest_start");
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   118
	thread_stop_p = kthread_create (thread_stop, NULL, "canftest_stop");
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   119
	
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   120
	if (PTR_ERR(thread_start_p) == -ENOMEM || PTR_ERR(thread_stop_p) == -ENOMEM) {
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   121
		printk(KERN_WARNING "canftest: error creating threads\n");
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   122
		return -ENOMEM;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   123
	}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   124
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   125
	return 0;
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   126
}
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   127
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   128
void cleanup_module(void)
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   129
{
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   130
	// unregister major device number and character device
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   131
	unregister_chrdev_region(canftest_dev, 1);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   132
	cdev_del(canftest_cdev);
7802a7d5584f Accepted Vladimir Chren linux kernelspace port patch.
etisserant
parents:
diff changeset
   133
}