1. 程式人生 > 實用技巧 >《驅動學習 —— 雜項裝置》

《驅動學習 —— 雜項裝置》

1.雜項裝置

  雜項裝置,本質上就是字元裝置驅動,只不過是一個特殊一點的。雜項裝置的主裝置號,被固定在 10,通過次裝置號進行區分裝置。雜項設備註冊之後,在 /dev/ 目錄下就有 name 裝置節點,在 /sys/clas/misc 下面,也會自動生成的類資訊,因此,一定程度上,比標準的的字元裝置驅動簡單了。

2.雜項裝置的註冊與登出

註冊:

int misc_register(struct miscdevice * misc)

  

登出:

int misc_deregister(struct miscdevice *misc)

  可以看到,基本就是圍繞著miscdevice結構體。

struct miscdevice  { 
    int minor; 
    const char *name;      // 名字 
    const struct file_operations *fops;  // 檔案操作結構體 
    struct list_head list; 
    struct device *parent; 
    struct device *this_device; 
    const char *nodename; 
    mode_t mode; 
};

  結構體中,name 是註冊的名字,以後將會在 /dev 目錄下,進行顯示的 name,裡面最主要的是 struct file_operations ,在註冊雜項裝置的時候,字元裝置的結構體與雜項裝置進行繫結,minor 為 MISC_DYNAMIC_MINOR 的時候,miscdevice 核心層會自動尋找一個空閒的次裝置號。

3.雜項裝置驅動編寫流程

struct const file_operations xxxx_fops = {
    .unlock_ioctl = xxx_ioctl,
     xxxx
};

    struct miscdevice xxx_dev = {

    .minor = MISC_DYNAMIC_MINOR,

    .name = “xxx”,

    .fops = xxxx_fops
};

static int __init xxx_init()
{
    return misc_register(&xxx_dev );
}

void __exit xxx_exit()
{
    return misc_deregister(&xxx_dev) ;
}

  當呼叫 misc_register(&xxx_dev ); 的時候,會在 misc_open 的幫助下,實現將 xxx_dev 成為 file 的private_data,也就是 系統會幫助我們實現 file->private_data = xxx_dev。

4.例項

#include <linux/init.h>
#include <linux/module.h>

/*驅動註冊的標頭檔案,包含驅動的結構體和註冊和解除安裝的函式*/
#include <linux/platform_device.h>
/*註冊雜項裝置標頭檔案*/
#include <linux/miscdevice.h>
/*註冊裝置節點的檔案結構體*/
#include <linux/fs.h>

#define DRIVER_NAME "hello_ctl"
#define DEVICE_NAME "hello_ctl123"
MODULE_LICENSE("Dual BSD/GPL");


static long hello_ioctl( struct file *files, unsigned int cmd, unsigned long arg){

	
	printk("cmd is %d,arg is %d\n",cmd,arg);
	return 0;
}

static int hello_release(struct inode *inode, struct file *file){
	printk(KERN_EMERG "hello release\n");
	return 0;
}

static int hello_open(struct inode *inode, struct file *file){
	printk(KERN_EMERG "hello open\n");
	return 0;
}

static struct file_operations hello_ops = {
	.owner = THIS_MODULE,
	.open = hello_open,
	.release = hello_release,
	.unlocked_ioctl = hello_ioctl,
};

static  struct miscdevice hello_dev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVICE_NAME,
	.fops = &hello_ops,
};


static int hello_probe(struct platform_device *pdv){
	
	printk(KERN_EMERG "\tinitialized\n");
	misc_register(&hello_dev);
	
	return 0;
}

static int hello_remove(struct platform_device *pdv){
	
	printk(KERN_EMERG "\tremove\n");
	misc_deregister(&hello_dev);
	return 0;
}

static void hello_shutdown(struct platform_device *pdv){
	
	;
}

static int hello_suspend(struct platform_device *pdv,pm_message_t pmt){
	
	return 0;
}

static int hello_resume(struct platform_device *pdv){
	
	return 0;
}

struct platform_driver hello_driver = {
	.probe = hello_probe,
	.remove = hello_remove,
	.shutdown = hello_shutdown,
	.suspend = hello_suspend,
	.resume = hello_resume,
	.driver = {
		.name = DRIVER_NAME,
		.owner = THIS_MODULE,
	}
};


static int hello_init(void)
{
	int DriverState;
	
	printk(KERN_EMERG "HELLO WORLD enter!\n");
	DriverState = platform_driver_register(&hello_driver);
	
	printk(KERN_EMERG "\tDriverState is %d\n",DriverState);
	return 0;
}


static void hello_exit(void)
{
	printk(KERN_EMERG "HELLO WORLD exit!\n");
	
	platform_driver_unregister(&hello_driver);	
}

module_init(hello_init);
module_exit(hello_exit);