|
驱动程序代码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define MINOR_DEV_NAME "minordev"
#define MINOR_DEV_MAJOR 240
#define MINOR_WRITE_ADDR 0x378
#define MINOR_READ_ADDR 0x379
int minor0_open (struct inode *inode, struct file *filp)
{
printk ("call minor0_open\n");
return 0;
}
ssize_t minor0_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
unsigned char status;
int loop;
for (loop = 0; loop < count; loop++) {
get_user (status, (char *)&buf[loop]);
outb (status, MINOR_WRITE_ADDR);
}
return count;
}
int minor0_release (struct inode *inode, struct file *filp)
{
printk ("call minor0_release\n");
return 0;
}
int minor1_open (struct inode *inode, struct file *filp)
{
printk ("call minor1_open\n");
return 0;
}
ssize_t minor1_read (struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
unsigned char status;
int loop;
for (loop = 0; loop < count; loop++) {
status = inb (MINOR_READ_ADDR);
put_user (status, (char *)&buf[loop]);
}
return count;
}
int minor1_release (struct inode *inode, struct file *filp)
{
printk ("call minor1_release\n");
return 0;
}
struct file_operations minor0_fops = {
.owner = THIS_MODULE,
.write = minor0_write,
.open = minor0_open,
.release = minor0_release,
};
struct file_operations minor1_fops = {
.owner = THIS_MODULE,
.read = minor1_read,
.open = minor1_open,
.release = minor1_release,
};
int minor_open (struct inode *inode, struct file *filp)
{
printk ("call minor_open\n");
switch (MINOR (inode->i_rdev)) {
case 1:
filp->f_op = &minor0_fops;
break;
case 2:
filp->f_op = &minor1_fops;
break;
default :
return -ENXIO;
}
if (filp->f_op && filp->f_op->open)
return filp->f_op->open (inode, filp);
return 0;
}
struct file_operations minor_fops = {
.owner = THIS_MODULE,
.open = minor_open,
};
int minor_init (void)
{
int result;
result = register_chrdev (MINOR_DEV_MAJOR, MINOR_DEV_NAME, &minor_fops);
if (result < 0)
return result;
return 0;
}
void minor_exit (void)
{
unregister_chrdev (MINOR_DEV_MAJOR, MINOR_DEV_NAME);
}
module_init (minor_init);
module_exit (minor_exit);
MODULE_LICENSE ("Dual BSD/GPL");
Makefile 文件:
obj-m := minor_dev.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.ko
rm -rf *.mod.*
rm -rf .*.cmd
rm -rf *.o
测试应用程序:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#define READ_DEVICE_FILENAME "/dev/minor_read"
#define WRITE_DEVICE_FILENAME "/dev/minor_write"
int main()
{
int read_dev;
int write_dev;
char buff [128];
int loop;
read_dev = open (READ_DEVICE_FILENAME, O_RDWR | O_NDELAY);
if (read_dev < 0) {
printf (READ_DEVICE_FILENAME "open error\n");
close (read_dev);
exit (1);
}
write_dev = open (WRITE_DEVICE_FILENAME, O_RDWR | O_NDELAY);
if (write_dev < 0) {
printf (WRITE_DEVICE_FILENAME "open error\n");
close (write_dev);
exit (1);
}
printf ("wait... input\n");
while (1) {
if (read (read_dev, buff, 1) == 1) {
printf ("read data [%02X]\n", buff[0] & 0xFF);
if (!(buff[0] & 0x10)) break;
}
}
printf ("input ok ... \n");
printf ("led flashing ... \n");
for (loop = 0; loop < 5; loop++) {
buff[0] = 0xFF;
write (write_dev, buff, 1);
sleep (1);
buff[0] = 0x00;
write (write_dev, buff, 1);
sleep (1);
}
close (read_dev);
close (write_dev);
return 0;
} |
|