1. 程式人生 > >miscdevice混雜裝置驅動

miscdevice混雜裝置驅動

原文地址:http://blog.csdn.net/tong646591/article/details/8301925

定義:字元裝置的一種,它們共享一個主裝置號(10),但次裝置號不同,所有的混雜裝置形成一個連結串列,對裝置訪問時核心根據次裝置號查詢到相應的miscdevice裝置。

例如:觸控式螢幕,LED,按鍵,串列埠。

即:為了節約主裝置號,將某些裝置用連結串列的形式連線在一起,最後通過查詢次裝置區分。這裡用主裝置無法匹配出裝置驅動,只能找到連結串列,再通過次裝置號,才能找到裝置驅動。而之前所學的,一般字元裝置,通過主裝置號,就能找到裝置驅動了。

混雜裝置驅動內建有自動建立裝置節點的程式碼,所以編譯好之後,能自動建立裝置節點。

相關的巨集,定義在 kernel/include/linux/miscdevice.h
[cpp] view plaincopy

    #ifndef _LINUX_MISCDEVICE_H  
    #define _LINUX_MISCDEVICE_H  
    #include <linux/module.h>  
    #include <linux/major.h>  
      
    /*
     *      These allocations are managed by

[email protected] If you use an
     *      entry that is not in assigned your entry may well be moved and
     *      reassigned, or set dynamic if a fixed value is not justified.
     */  
      
    #define PSMOUSE_MINOR           1  
    #define MS_BUSMOUSE_MINOR       2  
    #define ATIXL_BUSMOUSE_MINOR    3  
    /*#define AMIGAMOUSE_MINOR      4       FIXME OBSOLETE */  
    #define ATARIMOUSE_MINOR        5  
    #define SUN_MOUSE_MINOR         6  
    #define APOLLO_MOUSE_MINOR      7  
    #define PC110PAD_MINOR          9  
    /*#define ADB_MOUSE_MINOR       10      FIXME OBSOLETE */  
    #define WATCHDOG_MINOR          130     /* Watchdog timer     */  
    #define TEMP_MINOR              131     /* Temperature Sensor */  
    #define RTC_MINOR               135  
    #define EFI_RTC_MINOR           136     /* EFI Time services */  
    #define SUN_OPENPROM_MINOR      139  
    #define DMAPI_MINOR             140     /* DMAPI */  
    #define NVRAM_MINOR             144  
    #define SGI_MMTIMER             153  
    #define STORE_QUEUE_MINOR       155  
    #define I2O_MINOR               166  
    #define MICROCODE_MINOR         184  
    #define TUN_MINOR               200  
    #define MWAVE_MINOR             219     /* ACP/Mwave Modem */  
    #define MPT_MINOR               220  
    #define MPT2SAS_MINOR           221  
    #define HPET_MINOR              228  
    #define FUSE_MINOR              229  
    #define KVM_MINOR               232  
    #define BTRFS_MINOR             234  
    #define AUTOFS_MINOR            235  
    #define MISC_DYNAMIC_MINOR      255  
      
    struct device;  
      
    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;  
    };  
      
    extern int misc_register(struct miscdevice * misc);  //混雜設備註冊
    extern int misc_deregister(struct miscdevice *misc);  //混雜設備註銷
      
    #define MODULE_ALIAS_MISCDEV(minor)                             \  
            MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR)      \  
            "-" __stringify(minor))  
    #endif  

雜項裝置的核心函式的定義位於:kernel/drivers/char/misc.c

/**
 *  misc_register   -   register a miscellaneous device
 *  @misc: device structure
 *
 *  Register a miscellaneous device with the kernel. If the minor
 *  number is set to %MISC_DYNAMIC_MINOR a minor number is assigned
 *  and placed in the minor field of the structure. For other cases
 *  the minor number requested is used.
 *
 *  The structure passed is linked into the kernel and may not be
 *  destroyed until it has been unregistered.
 *
 *  A zero is returned on success and a negative errno code for
 *  failure.
 */

int misc_register(struct miscdevice * misc)
{
    struct miscdevice *c;
    dev_t dev;
    int err = 0;

    INIT_LIST_HEAD(&misc->list);

    mutex_lock(&misc_mtx);
    list_for_each_entry(c, &misc_list, list) {
        if (c->minor == misc->minor) {
            mutex_unlock(&misc_mtx);
            return -EBUSY;
        }
    }

    if (misc->minor == MISC_DYNAMIC_MINOR) {     //#define MISC_DYNAMIC_MINOR 255
        int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);    //#define DYNAMIC_MINORS 64 /* like dynamic majors */
        if (i >= DYNAMIC_MINORS) {
            mutex_unlock(&misc_mtx);
            return -EBUSY;
        }
        misc->minor = DYNAMIC_MINORS - i - 1;
        set_bit(i, misc_minors);
    }

//獲得裝置號

    dev = MKDEV(MISC_MAJOR, misc->minor);     //#define MISC_MAJOR  10    // 在 kernel/include/linux/major.h   中定義。

    misc->this_device = device_create(misc_class, misc->parent, dev, misc, "%s", misc->name);//說明了混雜裝置驅動內部有自動裝置驅動,可自動

//建立裝置節點
    if (IS_ERR(misc->this_device)) {
        int i = DYNAMIC_MINORS - misc->minor - 1;
        if (i < DYNAMIC_MINORS && i >= 0)
            clear_bit(i, misc_minors);
        err = PTR_ERR(misc->this_device);
        goto out;
    }

    /*
     * Add it to the front, so that later devices can "override"
     * earlier defaults
     */
    list_add(&misc->list, &misc_list);
 out:
    mutex_unlock(&misc_mtx);
    return err;
}

/**
 *  misc_deregister - unregister a miscellaneous device
 *  @misc: device to unregister
 *
 *  Unregister a miscellaneous device that was previously
 *  successfully registered with misc_register(). Success
 *  is indicated by a zero return, a negative errno code
 *  indicates an error.
 */

int misc_deregister(struct miscdevice *misc)
{
    int i = DYNAMIC_MINORS - misc->minor - 1;

    if (list_empty(&misc->list))
        return -EINVAL;

    mutex_lock(&misc_mtx);
    list_del(&misc->list);
    device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
    if (i < DYNAMIC_MINORS && i >= 0)
        clear_bit(i, misc_minors);


EXPORT_SYMBOL(misc_register);
EXPORT_SYMBOL(misc_deregister);

 

static char *misc_devnode(struct device *dev, mode_t *mode)
{
    struct miscdevice *c = dev_get_drvdata(dev);

    if (mode && c->mode)
        *mode = c->mode;
    if (c->nodename)
        return kstrdup(c->nodename, GFP_KERNEL);
    return NULL;
}

 

static int __init misc_init(void)
{
    int err;

#ifdef CONFIG_PROC_FS
    proc_create("misc", 0, NULL, &misc_proc_fops);
#endif
    misc_class = class_create(THIS_MODULE, "misc");
    err = PTR_ERR(misc_class);
    if (IS_ERR(misc_class))
        goto fail_remove;

    err = -EIO;
    if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
        goto fail_printk;
    misc_class->devnode = misc_devnode;
    return 0;

fail_printk:
    printk("unable to get major %d for misc devices\n", MISC_MAJOR);
    class_destroy(misc_class);
fail_remove:
    remove_proc_entry("misc", NULL);
    return err;

}

subsys_initcall(misc_init);

以下是建立自動裝置節點相關程式碼

 "kernel/drivers/base/core.c"

struct device *device_create(struct class *class, struct device *parent,  dev_t devt, void *drvdata, const char *fmt, ...)
{
    va_list vargs;
    struct device *dev;

    va_start(vargs, fmt);
    dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
    va_end(vargs);
    return dev;
}
EXPORT_SYMBOL_GPL(device_create);

static int __match_devt(struct device *dev, void *data)
{
    dev_t *devt = data;

    return dev->devt == *devt;
}

/**
 * device_destroy - removes a device that was created with device_create()
 * @class: pointer to the struct class that this device was registered with
 * @devt: the dev_t of the device that was previously registered
 *
 * This call unregisters and cleans up a device that was created with a
 * call to device_create().
 */
void device_destroy(struct class *class, dev_t devt)
{
    struct device *dev;

    dev = class_find_device(class, NULL, &devt, __match_devt);
    if (dev) {
        put_device(dev);
        device_unregister(dev);
    }
}
EXPORT_SYMBOL_GPL(device_destroy);

相關推薦

miscdevice混雜裝置驅動

原文地址:http://blog.csdn.net/tong646591/article/details/8301925 定義:字元裝置的一種,它們共享一個主裝置號(10),但次裝置號不同,所有的混雜裝置形成一個連結串列,對裝置訪問時核心根據次裝置號查詢到相應的miscd

平臺裝置驅動混雜裝置驅動

1. 平臺裝置驅動 在linux2.6以後的裝置驅動模型中,只關心裝置、驅動和匯流排這三個實體,匯流排將裝置驅動繫結。在向系統註冊一個裝置時會由匯流排匹配對應的驅動,相反當向系統註冊一個驅動時由匯流排匹配出對應的裝置。 在linux裝置和驅動通常要掛接在某條總線上,對於II

Linux核心混雜裝置驅動

1.linux核心混雜裝置驅動 1.1混雜裝置驅動特點: 本質上還是一類字元裝置,在驅動軟體上,混雜裝置的主裝置號已經由核心指定主裝置號為10; 各個混雜裝置個體通過次裝置號來區分;1.2linux核心描述混雜裝置的資料結構 struct miscdevice { int

linux misc混雜裝置驅動 .

一. misc結構體 struct miscdevice { int minor; //次裝置號 const char *name; //裝置名 const struct file_operations *fops; //操作函式集 struct list_head list; //連結串列

linux驅動修煉之道-混雜裝置

Linux驅動中把無法歸類的五花八門的裝置定義為混雜裝置(用miscdevice結構體表述)。miscdevice共享一個主裝置號MISC_MAJOR(即10),但次裝置號不同。 所有的miscdevice裝置形成了一個連結串列,對裝置訪問時核心根據次裝置號查詢對應的mi

linux裝置驅動開發學習--記憶體和IO訪問

一 I/O 埠 1. 讀寫位元組埠(8 位寬) unsigned inb(unsigned port); void outb(unsigned char byte, unsigned port); 2. 讀寫字埠(16 位寬) unsigned inw(unsigne

字元裝置驅動程式的三種寫法

驅動工程師如何去寫驅動程式? 要看原理圖。確定如何去操作硬體。 對於點亮led燈來說,確定引腳,檢視晶片手冊,確定如何去操作引腳,要設定哪些暫存器,如何設定這些暫存器才可以讓這個引腳輸出高電平或者低電平。 寫驅動程式 驅動程式起封裝作用,如何封裝。應用程式要操作硬體需要o

linux裝置驅動模型 - regmap

1. regmap介紹 regmap主要是為了方便操作暫存器而設計的,它將所有模組的暫存器(包括soc上模組的暫存器和外圍裝置的暫存器等) 抽象出來,用一套統一介面來操作暫存器 比如,如果要操作i2c裝置的暫存器,那麼就要呼叫i2c_transfer介面,要操作spi裝置的暫存

linux裝置驅動模型 - device/bus/driver

在linux驅動模型中,為了便於管理各種裝置,我們把不同裝置分別掛在他們對應的總線上,裝置對應的驅動程式也在總線上找,這樣就提出了deivce-bus-driver的模型,硬體上有許多裝置匯流排,那麼我們就在裝置模型上抽象出bus概念,相應的device就代表裝置,driver表示驅動,

linux裝置驅動模型 - sys/kobject

1. sysfs 1.1 sysfs檔案系統註冊 在系統啟動時會註冊sysfs檔案系統 (fs/sysfs/mount.c) int __init sysfs_init(void) { int err; sysfs_root = kernfs_creat

linux裝置驅動模型 - 驅動框架

linux驅動模型框架如圖所示: 1. kernfs 驅動最終是提供給使用者層使用,那麼其中的介面就是通過kernfs檔案系統來註冊,kernfs是一個通用的核心虛擬檔案系統 2. sysfs/kobject sysfs是裝置驅動檔案系統,裝置之間的各種關係會在在/

linux裝置驅動(3)I2C驅動

i2c驅動程式的核心是建立i2c_driver結構體 /* This is the driver that will be inserted */ static struct i2c_driver at24cxx_driver = { .driver = { .name

裝置驅動之二

一、將塊裝置新增到系統 register_blkdev並沒有真正將裝置新增到系統中,想要將裝置新增到系統中,需要使用如下API: void blk_register_region(dev_t devt, unsigned long range, struct module *module,

裝置驅動程式之一

一、塊裝置概述 linux支援的兩種重要的裝置型別分別是字元裝置和塊裝置,塊裝置可以隨機地以固定大小的塊傳送資料。與字元裝置相比,塊裝置有以下幾個特殊之處: 塊裝置可以從資料的任何位置進行訪問 塊資料總是以固定長度進行傳輸,即便請求的這是一個位元組 對塊裝置的訪問有大量的快

《linux裝置驅動開發》,基於最新的linux 4.0核心-----筆記

第二章 Linux 的核心結構及構建 ---->這一章是自己總結的 1、核心結構(主要是下面這幾個部分) 系統呼叫介面<–>System call interface 程序管理<------>Process manag

裝置驅動程式》--Jonathan corbet,Alessandro rubini & Greg kroah-hartman

第二章 構造和執行模組 2.1核心模組與應用程式的對比 1、應用程式可以是C的庫函式,而驅動程式只能使用linux核心原始碼中的函式,而不能使用C的庫函式。 2、應用程式是有main函式的;而驅動程式沒有main函式 3、驅動程式有自己的入口和出口;而應用程式

linux裝置驅動 按鍵幾種寫法總結

對於基礎按鍵的驅動,有如下幾種寫法: (1)查詢 所謂查詢方法,主要描述應用程式會在while(1)裡面一直read,如果沒有資料會導致阻塞,佔用CPU;這種方法是最差的。   (2)中斷 中斷配合休眠會避免查詢法佔用CPU的缺點。 應用程式和查詢法沒有什麼區別, 但是驅動裡面的read

光碟安裝win7系統顯示缺少所需的cd dvd驅動器裝置驅動程式

注意:必須用內建光碟機才會好使。 這樣的問題是由於安裝版映象中不帶USB3.0驅動,安裝介質插到USB3.0介面導致。可以換到USB2.0的介面或是把USB3.0介面的裝置拔掉。 如果上面方法不行,則用下面方法: 1、首先進入BIOS,在BIOS中-Config-USB-USB3.0

WDF開發USB裝置驅動教程(1)

PDF下載地址(1.2版):連結地址 CY001開發板討論帖:連結地址 注:本文件新版本已出,請在部落格中查詢,或下載PDF全文文件。   連結地址WDF開發USB裝置驅動教程 by 張佩   文件說明     &

linux 裝置驅動 nand驅動框架

nand 裝置驅動(一)架構 使用mini2440 - nand 1. nand硬體 1.1 資源 LDATD0~7資料線和地址線是複用的,都是8位 既可以傳輸資料(命令或者資料), 也可以傳送地址訊號 訊號說明: CLE: 命令鎖存, 高表示cmd ALE: 地址鎖存, 高表示地址