相关代码在资源中下载。
主设备号标识设备对应的驱动程序;而次设备号则用来标识同一类设备中的某个唯一的设备。
利用到的函数及结构在上面几节中都有说出,在此不再叙述。
驱动设备:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/poll.h>
#include <asm/hardirq.h>
/*不同的linux版本,同文件会有所不同*/
static int major;
/*定义类*/
static struct class *first_class;
/*类下定义一个设备*/
static struct device *first_dev[4];
volatile int long *GPBCON = NULL;
volatile int long *GPBDAT = NULL;
int myfirst_led_open(struct inode *inode, struct file *file)
{
*GPBCON &= ~((3<<10) | (3<<12) | (3<<14) | (3<<16));
*GPBCON |= (1<<10) | (1<<12) | (1<<14) | (1<<16);
*GPBDAT = 0x1e0;
return 0;
}
ssize_t myfirst_led_write(struct file *file, const char __user *user_buffer,
size_t count, loff_t *ppos)
{
int minor;
int val;
/*得到用户空间的数据*/
copy_from_user(&val,user_buffer,count);
/*获取次设备号*/
minor = MINOR(file->f_dentry->d_inode->i_rdev);
switch (minor){
case 0:
*GPBDAT = 0x1e0;
*GPBDAT &= (val<<5)&(0x1e0);
break;
case 1:
*GPBDAT = 0x1e0;
*GPBDAT &= (val<<6)&(0x1e0);
break;
case 2:
*GPBDAT = 0x1e0;
*GPBDAT &= (val<<7)&(0x1e0);
break;
case 3:
*GPBDAT = 0x1e0;
*GPBDAT &= (val<<8)&(0x1e0);
break;
default:
break;
}
return count;
}
/*定义file_operations结构*/
static struct file_operations myfirst_fops = {
.owner = THIS_MODULE,
.write = myfirst_led_write,
.open = myfirst_led_open,
};
static int myfirst_init(void)
{
int i;
/*注册*/
major = register_chrdev(0,"first_led_minor",&myfirst_fops);
/*物理地址映射到虚拟地址*/
GPBCON = (volatile int long *)ioremap(0x56000010,16);
GPBDAT = GPBCON + 1;
/*创建类*/
first_class = class_create(THIS_MODULE,"first_led_minor");
for(i=0;i<4;i++)
{ /*创建设备*/
first_dev[i] =
device_create(first_class,NULL,MKDEV(major,i),NULL,"led%d",i);
}
return 0;
}
static void myfirst_exit(void)
{
int i;
/*注销*/
unregister_chrdev(major,"first_led_minor");
/*注销虚拟地址*/
iounmap(GPBCON);
for(i=0;i<4;i++)
/*注销设备*/
device_unregister(first_dev[i]);
/*销毁定义的类*/
class_destroy(first_class);
}
MODULE_LICENSE("GPL");
module_init(myfirst_init);
module_exit(myfirst_exit);
应用程序:
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
int main(int argc ,char **argv){
int val;
char *p;
int fd;
if(argc != 3){
printf("USAGE:file <dev> <on|off>");
}
p = argv[1];
fd = open(p,O_RDWR);
if(fd < 0)
printf("can't open!");
if(strcmp(argv[2],"on") == 0 )
val = 0;
else
val = 1;
write(fd,&val,1);
return 0;
}
下面就是检测驱动程序是否正确了,由于led中处于亮的状态,可以用off进行检测。