6410之次设备号的作用

一个设备节点的属性有:

设备类型,读写权限,主设备号,次设备号等等。次设备号的作用是什么呢?

举个例子:

假如有两个串口,它们共用一个设备驱动(主设备号),当具体的操作的时候,如何判断操作的是哪一个串口呢?这就使用到了次设备号。


下面给出相关次设备号使用的相关代码:

功能如下:

1.次设备号为0的设备节点功能为操作所有的LED灯

2.测设备号为1,2,3,4分别代表各个单独的LED灯,可以对他们单独进行操作。


代码如下:

#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/pmu.h>
#include <linux/notifier.h>
#include <linux/wait.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/uaccess.h>



struct class *first_dev_class;
//struct device *first_dev;
struct device *led_devs[5];

volatile unsigned long *gpmcon = NULL;
volatile unsigned long *gpmdat = NULL;
int major;
int minor;

static int first_drv_open(struct inode *inode, struct file *file)
{
	printk("first_drv_open!!\n");

	minor = MINOR(inode->i_rdev);

	switch(minor){
		case 0:
		{	//操作leds
			printk("first_drv_open : minor == 0 !!\n");
			*gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12);
			*gpmcon |= (0x1 | 0x1 << 4 | 0x1 << 8 | 0x1 << 12);
			break;
		}
		
		case 1:
		{ 	//操作led1
			printk("first_drv_open : minor == 1 !!\n");
			*gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12);
			*gpmcon |= 0x1;
			break;
		}
		
		
		case 2:
		{
			*gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12);
			*gpmcon |= 0x1 << 4;
			break;
		}
		case 3:
		{
			*gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12);
			*gpmcon |= 0x1 << 8;
			break;
		}
		case 4:
		{
			*gpmcon &= ~(0x3 | 0x3 << 4 | 0x3 << 8 | 0x3 << 12);
			*gpmcon |= 0x1 << 12;
			break;
		}
		
	}
	
	
	return 0;
}

static int first_drv_write(struct file *filp, char __user *buff, 
                                         size_t count, loff_t *offp)
{
	printk("first_drv_write!!\n");
	int val ;
	minor = MINOR(filp->f_dentry->d_inode->i_rdev);

	copy_from_user(&val,buff,count);
	switch(minor){
		case 0:
			{
				printk("first_drv_write minor == 0  !!\n");
				if(val == 1){
					//点灯
					*gpmdat &= ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
				}else if(val == 0){
					//灭灯
					*gpmdat |= (1 << 0 | 1 << 1 | 1 << 2 | 1 << 3);
				}
				break;
			}
		
		case 1:
			{
				printk("first_drv_write minor == 1 !!\n");
				if(val == 1){
					//点灯
					*gpmdat &= ~(1 << 0);
				}else if(val == 0){
					//灭灯
					*gpmdat |= (1 << 0);
				}
				break;			
			}
		
		
		case 2:
			{
				if(val == 1){
					//点灯
					*gpmdat &= ~(1 << 1);
				}else if(val == 0){
					//灭灯
					*gpmdat |= (1 << 1);
				}
				break;
			}
		case 3:
			{
				if(val == 1){
					//点灯
					*gpmdat &= ~(1 << 2);
				}else if(val == 0){
					//灭灯
					*gpmdat |= (1 << 2);
				}
				break;
			}
		case 4:
			{
				if(val == 1){
					//点灯
					*gpmdat &= ~(1 << 3);
				}else if(val == 0){
					//灭灯
					*gpmdat |= (1 << 3);
				}
				break;
			}
		}
	
	return 0;
}

static struct file_operations first_drv_fops = {
    .owner   =   THIS_MODULE,    
    .open    =   first_drv_open,
    .write    =  first_drv_write,
};


static int __init first_drv_init(void)
{
	printk("first_drv_init\n");

	major = register_chrdev(0,"first_drv",&first_drv_fops);
	first_dev_class = class_create(THIS_MODULE, "first_drv_class");
//	first_dev= device_create(first_dev_class, NULL, MKDEV(major,0), NULL, "xyz");
	led_devs[0] = device_create(first_dev_class, NULL, MKDEV(major,0),NULL,"leds");
	for(minor = 1 ; minor < 5 ; minor++){
		led_devs[minor] = device_create(first_dev_class, NULL, MKDEV(major,minor),NULL,"led%d",minor);
	}
	gpmcon = (volatile unsigned long *)ioremap(0x7F008820, 16);
	gpmdat = gpmcon + 1;

//	register_chrdev(111,"first_drv",&first_drv_fops);
	return 0;
}

static void __exit first_drv_exit(void)
{
	printk("first_drv_exit\n");
	
	for(minor = 0 ; minor < 5 ; minor++){
		device_destroy(first_dev_class, MKDEV(major,minor));
	}
//	device_destroy(first_dev_class, MKDEV(major,0));
	class_destroy(first_dev_class);
	unregister_chrdev(major,"first_drv");

	iounmap(gpmcon);
}

module_init(first_drv_init);
module_exit(first_drv_exit);

MODULE_LICENSE("GPL"); 

测试程序:

#include <stdio.h>
#include <fcntl.h>


int main(int argc ,char **argv)
{
	int fd ;
	int val;
	char *filename = argv[1];
	fd = open(filename,O_RDWR);
	if(fd < 0){
		printf("Can not open devices\n");
		return -1;
	}
	if(argc != 3){
		printf("Usage : %s <leds/led1/led2/led3/led4> <on/off> \n",argv[0]);
		return 0;
	}
	if(strcmp(argv[2],"on") == 0){
		val = 1;
	}else{
		val = 0;
	}

	write(fd,&val,4);
	return 0;
}

从上面的驱动程序可以看到,在open,read,write函数中获取次设备号的方法为:

open函数: 通过MINOR(inode->i_rdev);获取
read,write函数: 通过MINOR(filp->f_dentry->d_inode->i_rdev);获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值