Embedded 版 (精华区)
发信人: Zinux (Linux技工), 信区: Embedded_system
标 题: 驱动程序
发信站: 哈工大紫丁香 (2001年10月26日18:43:34 星期五), 站内信件
发信人: clown (梧桐叶), 信区: UKP
标 题: 驱动程序
发信站: UNIX编程 (2001年10月26日11:31:00 星期五), 站内信件
//dev.c
//the driver of the virtual character device /dev/vir_chr_dev
#define MODULE
#define __KERNEL__
//#define EXPORT_SYMTAB
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#define DEV_MAJOR 61
#define DEV_MINOR 0
#define DEV_NAME "vir_chr_dev"
//#mknod /dev/vir_chr_dev c 61 0
static int read_busy;
static int write_busy;
#define MAX_SIZE 32
struct vir_buf {
int size;
char buf[MAX_SIZE];
struct vir_buf *next;
};
extern struct vir_buf *rd_head, *wr_head;
//static DECLARE_WAIT_QUEUE_HEAD(vir_queue);
ssize_t read_vir(struct file *, char *, size_t, loff_t *);
ssize_t write_vir(struct file *, const char *, size_t, loff_t *);
int open_vir(struct inode *inode, struct file *file);
int release_vir(struct inode *inode, struct file *file);
int release_vir(struct inode *inode, struct file *file);
struct file_operations virtual_fops = {
THIS_MODULE,
NULL,
read_vir,
write_vir,
NULL,
NULL,
NULL,
NULL,
open_vir,
NULL,
release_vir,
NULL,
NULL,
NULL,
NULL,
NULL
};
extern int driver_loaded; file://a flag to see wether the device driver
is
loaded.
loaded.
extern int ker_read();
extern int ker_write();
int init_module(void)
{
int res;
printk("<1>Installing the virtual deviec\n");
if((res = register_chrdev(DEV_MAJOR, DEV_NAME, &virtual_fops)) <
0) {
printk("<1>can't get major %d\n", DEV_MAJOR);
return res;
}
read_busy = 0;
write_busy = 0;
driver_loaded = 1;
printk("<1>Install succeed\n");
return 0;
}
void cleanup_module()
{
int res;
printk("<1>Unstalling the virtual device\n");
printk("<1>Unstalling the virtual device\n");
if((res = unregister_chrdev(DEV_MAJOR, DEV_NAME)) < 0) {
printk("<1>can't unintall the device, major %d\n", DEV_MAJOR);
return;
}
printk("<1>Unstall succeed\n");
return;
}
int open_vir(struct inode *inode, struct file *file)
{
if(MINOR(inode->i_rdev) != 0) {
printk("<1>open error\n");
return -ENODEV;
}
if((file->f_flags & O_ACCMODE) == O_RDONLY) {
if(read_busy) {
printk("<1>open error, open device more than once\n");
return -EBUSY;
} else {
printk("<1>open device for reading\n");
read_busy++;
MOD_INC_USE_COUNT;
MOD_INC_USE_COUNT;
return 0;
}
} else if((file->f_flags & O_ACCMODE) == O_WRONLY) {
if(write_busy) {
printk("<1>write error, write more than once\n");
return -EBUSY;
} else {
printk("<1>open device for writing\n");
write_busy++;
MOD_INC_USE_COUNT;
return 0;
}
} else
return -ENXIO;
}
int release_vir(struct inode *inode, struct file *file)
{
if(MINOR(inode->i_rdev) != 0) {
printk("<1>close error\n");
return -ENODEV;
return -ENODEV;
}
if((file->f_flags & O_ACCMODE) == O_RDONLY) {
printk("<1>close device for reading\n");
read_busy = 0;
} else if((file->f_flags & O_ACCMODE) == O_WRONLY) {
printk("<1>close device for writing\n");
write_busy = 0;
}
MOD_DEC_USE_COUNT;
return 0;
}
ssize_t read_vir(struct file *file, char *buf, size_t count, loff_t
*off)
{
int len;
unsigned long flags;
struct vir_buf *p;
save_flags(flags);
cli();
if(rd_head == NULL) {
//interruptible_sleep_on(&vir_queue);
//interruptible_sleep_on(&vir_queue);
//the function provided by ker.o
if(ker_write() < 0) {
printk("<1>ker_write error\n");
restore_flags(flags);
return -EFAULT;
}
}
len = count < rd_head->size ? count : rd_head->size;
if(copy_to_user(buf, rd_head->buf, len) != 0) {
printk("<1>copy_to_user error\n");
restore_flags(flags);
return -EFAULT;
}
printk("<1>kernel->application: %s\n", rd_head->buf);
p = rd_head;
rd_head = rd_head->next;
*off += len;
kfree(p);
restore_flags(flags);
return len;
}
}
ssize_t write_vir(struct file *file, const char *buf, size_t count,
loff_t
*off)
{
int len;
unsigned long flags;
struct vir_buf *p, *q;
len = count < MAX_SIZE ? count : MAX_SIZE;
if((p = kmalloc(sizeof(struct vir_buf), GFP_ATOMIC)) == NULL) {
printk("<1>kmalloc error\n");
return -ENOMEM;
}
/*
if(access_ok(VERIFY_READ, buf, sizeof(buf)) == 0) {
printk("<1>the memory in application layer can't read\n");
return -EFAULT;
}
*/
save_flags(flags);
cli();
if(copy_from_user(p->buf, buf, len) != 0) {
printk("<1>copy_from_user error\n");
printk("<1>copy_from_user error\n");
kfree(p);
restore_flags(flags);
return -EFAULT;
}
p->size = len;
p->next = NULL;
if(wr_head == NULL)
wr_head = p;
else {
q = wr_head;
while(q->next != NULL)
q = q->next;
q->next = p;
}
*off += len;
printk("<1>application->kernel: %s\n", wr_head->buf);
restore_flags(flags);
//call the ker.o function to read the buffer
if(ker_read() < 0) {
printk("<1>ker_read error\n");
return -EFAULT;
}
return len;
}
--
puke!
技工而已
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.152]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:2.361毫秒