參考地址:http://oss.org.cn/kernel-book/ldd3/ch09s03.html
13腳接led的正輸入,25腳接led的負極
驅動代碼:
parport_drv.c
#include
#include
#include
#include
#include
#include
#include
#include"parport_drv.h"
#define Drv_major 240
#define Drv_name "parport_drv"
#define Drv_read_addr 0x379
#define Drv_write_addr 0x378
int parport_open(struct inode *inode, struct file *filp)
{
printk(KERN_ALERT "open the parport_dev\n");
return 0;
}
ssize_t parport_write(struct file *filp, const char *buf, size_t count, loff_t *f_ops)
{
unsigned char status;
int loop;
for(loop = 0; loop < count; loop++)
{
get_user(status, (char *)buf);
outb(status, Drv_write_addr);
}
return count;
}
ssize_t parport_read(struct file *filp, char *buf, size_t count, loff_t *f_ops)
{
unsigned char status;
int loop;
for(loop = 0; loop < count; loop++)
{
status = inb(Drv_read_addr);
put_user(status, (char *) &buf[loop]);
}
return count;
}
long parport_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int loop;
struct dat data;
switch(cmd)
{
case PARPORT_WRITE:
// outb(status, Drv_write_addr);
copy_from_user(&data, (struct dat *)arg, sizeof(data));
printk(KERN_ALERT "out put %d\n",data.loop);
for(loop = 0; loop < data.loop; loop ++)
{
printk(KERN_ALERT "the %dth loop, write %d\n",loop,data.buf[loop]);
outb(data.buf[loop], Drv_write_addr);
wmb();
}
break;
case PARPORT_CLOSE:
outb(0x00, Drv_write_addr);
wmb();
break;
}
return 0;
}
int parport_release(struct inode *inode, struct file *filp)
{
printk(KERN_ALERT "close the module parport_dev\n");
return 0;
}
struct file_operations parport_fops = {
.owner = THIS_MODULE,
.write = parport_write,
.read = parport_read,
.open = parport_open,
.unlocked_ioctl = parport_ioctl,
.release= parport_release,
};
int parport_init(void)
{
int result;
result = register_chrdev(Drv_major, Drv_name, &parport_fops);
if(result < 0)
return result;
printk(KERN_ALERT "hello the module parport_dev\n");
return 0;
}
void parport_exit(void)
{
printk(KERN_ALERT "exit the module parport_drv\n");
unregister_chrdev(Drv_major, Drv_name);
}
module_init(parport_init);
module_exit(parport_exit);
parport_drv.h
#ifndef _PARPORT_DRV_H
#define _PARPORT_DRV_H
#define PARPORT_WRITE 1
#define PARPORT_CLOSE 2
struct dat{
int loop;
unsigned char *buf;
};
#endif
測試代碼par_test.c
#include
#include
#include
#include
#include
#include "parport_drv.h"
#define DEVICE_NAME "/dev/parport_dev"
int main()
{
int fd;
char buf[128];
int loop;
fd = open(DEVICE_NAME, O_RDWR | O_NDELAY);
if(fd < 0)
{
perror("open device");
exit(1);
}
else
{
// printf("waiting for input ...\n");
//
// while(1)
// {
// if(read(fd, buf, 1) == 1)
// {
// printf("read data [%2X]\n", buf[0] & 0xFF);
// if(!(buf[0] & 0x10))
// break;
// }
// sleep(1);
// }
// printf("input ok ... \n");
// printf("led begins to flash ... \n");
// for(loop = 0; loop < 5; loop++)
// {
// buf[0] = 0xff;
// write(fd, buf, 1);
// sleep(1);
// buf[0] = 0x00;
// write(fd, buf, 1);
// sleep(1);
// }
int i;
int arg=0x99;
unsigned char buf[255];
struct dat da;
da.loop = 4;
da.buf = (unsigned char *)malloc(5 * sizeof(unsigned char));
for(i = 0;i< da.loop; i++)
da.buf[i] = i*2+1;
for(i=0;i<da.loop;i++)
printf("test:%d\n", da.buf[i]);
ioctl(fd, PARPORT_WRITE,&da);
sleep(1);
ioctl(fd, PARPORT_CLOSE);
sleep(1);
close(fd);
}
return 0;
}
1 load_rdwrdev#!/bin/sh
insmod parport_drv.ko
mknod /dev/parport_dev c 240 0
2 unload_rdwrdev#!/bin/sh
rmmod parport_drv.ko
rm /dev/parport_dev