1. 程式人生 > >linux 驅動建立多個裝置

linux 驅動建立多個裝置


linux 驅動中建立一個裝置的例子很多,以下例子是建立多個字元裝置的例子,包括驅動部分和測試部分

驅動部分包括 globalmem.c  Makefile兩個檔案:

globalmem.c file:

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/slab.h>

#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#define GLOBALMEM_SIZE 0x1000 //global memory size 4KB
#define MEM_CLEAR 0x1         //clear all the mem
#define GLOBALMEM_MAJOR 350   //globalmem major number

static struct class* globalmem_class0;
static struct class* globalmem_class1;

static int globalmem_major = GLOBALMEM_MAJOR;

struct globalmem_dev{
    struct cdev cdev; //cdev struct
    unsigned char mem[GLOBALMEM_SIZE]; //global mem
};

struct globalmem_dev* globalmem_devp;

void globalmem_setup_cdev(struct globalmem_dev * dev, int index);

int globalmem_init(void){
    int result;
    dev_t devno = MKDEV(globalmem_major, 0); 

    if(globalmem_major){
        result = register_chrdev_region(devno, 2, "globalmem");
    }else{
        result = alloc_chrdev_region(&devno, 0, 2, "globalmem");
        globalmem_major = MAJOR(devno);
    }   
        if(result < 0){
        return result;
    }

    globalmem_devp = kmalloc(2 * sizeof(struct globalmem_dev), GFP_KERNEL);
    if(!globalmem_devp){
        result = -ENOMEM;
        goto fail_malloc;
    }
    memset(globalmem_devp, 0, 2 * sizeof(struct globalmem_dev));
    globalmem_setup_cdev(&globalmem_devp[0], 0);
    globalmem_setup_cdev(&globalmem_devp[1], 1);

    globalmem_class0 = class_create(THIS_MODULE, "globalmem0"); //create file under /sys/class
    device_create(globalmem_class0, NULL, MKDEV(globalmem_major, 0), NULL, "globalmem_0"); //globalmem_0 is the name under /dev/
    globalmem_class1 = class_create(THIS_MODULE, "globalmem1"); //create file under /sys/class
    device_create(globalmem_class1, NULL, MKDEV(globalmem_major, 1), NULL, "globalmem_1"); //globalmem_1 is the name under /dev/

    return 0;
fail_malloc:
    unregister_chrdev_region(devno, 1);
    return result;
}

void globalmem_exit(void){
    cdev_del(&(globalmem_devp[0].cdev));
    cdev_del(&(globalmem_devp[1].cdev));
    unregister_chrdev_region(MKDEV(globalmem_major, 0), 2); //unregister device
    kfree(globalmem_devp);

    device_destroy(globalmem_class0, MKDEV(globalmem_major, 0));
    class_destroy(globalmem_class0);

    device_destroy(globalmem_class1, MKDEV(globalmem_major, 1));
    class_destroy(globalmem_class1);
}

 static int globalmem_open_0(struct inode* inode, struct file* filp){
    int minor = iminor(inode);
    struct globalmem_dev* dev;
    dev = container_of(inode->i_cdev, struct globalmem_dev, cdev);
    filp->private_data = dev;
    printk(KERN_INFO "in kernel function: %s, minor = %d", __func__, minor);

    return 0;
}

static int globalmem_open_1(struct inode* inode, struct file* filp){
    int minor = iminor(inode);
    struct globalmem_dev* dev;
    dev = container_of(inode->i_cdev, struct globalmem_dev, cdev);
    filp->private_data = dev;
    printk(KERN_INFO "in kernel function: %s, minor = %d", __func__, minor);

    return 0;
}

static ssize_t globalmem_read_0(struct file* filp, char __user * buf, size_t count, loff_t * ppos){
    int ret = 0;
    struct globalmem_dev * dev = filp->private_data;
    printk(KERN_INFO "in kernel function: %s", __func__);
    ret = copy_to_user(buf, dev->mem, count);
    return 0;
}
static ssize_t globalmem_read_1(struct file* filp, char __user * buf, size_t count, loff_t * ppos){
    int ret = 0;
    struct globalmem_dev * dev = filp->private_data;
    printk(KERN_INFO "in kernel function: %s", __func__);
    ret = copy_to_user(buf, dev->mem, count);
    return 0;
}

static ssize_t globalmem_write_0(struct file* filp, const char __user * buf, size_t count, loff_t * ppos){
    int ret = 0;
    struct globalmem_dev * dev = filp->private_data;
    ret = copy_from_user(dev->mem, buf, count);
    dev->mem[count] = 0;
    printk(KERN_INFO "in kernel function: %s, content = %s", __func__, dev->mem);
    return 0;
}

static ssize_t globalmem_write_1(struct file* filp, const char __user * buf, size_t count, loff_t * ppos){
    int ret = 0;
    struct globalmem_dev * dev = filp->private_data;
    ret = copy_from_user(dev->mem, buf, count);
    dev->mem[count] = 0;
    printk(KERN_INFO "in kernel function: %s, content = %s", __func__, dev->mem);
    return 0;
}

static loff_t globalmem_llseek_0(struct file* filp, loff_t offset, int orig){
    printk(KERN_INFO "in kernel function: %s", __func__);

    return 0;
}

static loff_t globalmem_llseek_1(struct file* filp, loff_t offset, int orig){
    printk(KERN_INFO "in kernel function: %s", __func__);

    return 0;
}

static long globalmem_ioctl_0(struct file * filp, unsigned int cmd, unsigned long arg){
    struct globalmem_dev * dev = filp->private_data;
    memset(dev->mem, 0, sizeof(dev->mem)/sizeof(dev->mem[0]));
    printk(KERN_INFO "in kernel_function: %s", __func__);

    return 0;
}
static long globalmem_ioctl_1(struct file * filp, unsigned int cmd, unsigned long arg){
    struct globalmem_dev * dev = filp->private_data;
    memset(dev->mem, 0, sizeof(dev->mem)/sizeof(dev->mem[0]));
    printk(KERN_INFO "in kernel_function: %s", __func__);

    return 0;
}

static const struct file_operations globalmem_fops[] = {
    [0] = {
        .owner = THIS_MODULE,
        .open = globalmem_open_0,
        .llseek = globalmem_llseek_0,
        .read = globalmem_read_0,
        .write = globalmem_write_0,
        .compat_ioctl = globalmem_ioctl_0,
    },
    [1] = {
        .owner = THIS_MODULE,
        .open = globalmem_open_1,
        .llseek = globalmem_llseek_1,
        .read = globalmem_read_1,
        .write = globalmem_write_1,
        .compat_ioctl = globalmem_ioctl_1,
    }
};

void globalmem_setup_cdev(struct globalmem_dev* dev, int index){
    int err;
    int devno = MKDEV(globalmem_major, index);
    cdev_init(&dev->cdev, &globalmem_fops[index]);
    dev->cdev.owner = THIS_MODULE;
    err = cdev_add(&dev->cdev, devno, 1);
    if(err)
        printk(KERN_NOTICE "Error %d adding globalmem", err);
}

module_init(globalmem_init);
module_exit(globalmem_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("XXX");
MODULE_DESCRIPTION("Global mem test");
                                                                                                                                         1,1           Top

Makefile file:

mymodule-objs := globalmem.o
obj-m := globalmem.o
PWD:=$(shell pwd)
KERNEL_DIR=/sziauto/android_src/m6_lch_1280x800/svn_m6_jb42_0403/branches/branches-LCH/out/target/product/T37lchaudi/obj/KERNEL_OBJ/
CROSS_COMPILE=/sziauto/android_src/m6_lch_1280x800/svn_m6_jb42_0403/branches/branches-LCH/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin
PWD:=$(shell pwd)
all:
    make ARCH=arm $(CROSS_COMPILE) -C $(KERNEL_DIR) M=$(PWD) modules
clean:
    rm -rf *.o modules.order *.ko Module.symvers *.mod.c

測試部分包括 Android.mk  driver_test.c

driver_test.c :

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BUFFER_LEN 100

int main(int argc, char* argv[]){
    int fd = -1; 
    char cmd = 0;
    char param[BUFFER_LEN] = {0};
    char content[BUFFER_LEN] = {0};
    const char* PATH0 = "/dev/globalmem_0";
    const char* PATH1 = "/dev/globalmem_1";

    while(1){
        printf("\n");
        printf("type o|O to open file\n");
        printf("type r|R to exec read\n");
        printf("type w|W to exec write\n");
        printf("type i|I to exec ioctl\n");
        printf("type q|Q to quit\n");
        printf("input your cmd: ");
        memset(param, 0, sizeof(param)/sizeof(param[0]));
        fgets(param, BUFFER_LEN, stdin);        
        if(param[0] == 'o' || param[0] == 'O'){
            printf("input the path you want to open\n");
            printf("type 0 to open /dev/globalmem_0, 1 to open /dev/globalmem_1:");
            memset(param, 0, sizeof(param)/sizeof(param[0]));
            fgets(param, BUFFER_LEN, stdin);
            if(param[0] == '0'){
                if(fd > 0){ 
                    close(fd);
                }
                fd = open(PATH0, O_RDWR);
            }else if(param[0] == '1'){
                if(fd > 0){
                    close(fd);
                }
                fd = open(PATH1, O_RDWR);
            }
        }else if(param[0] == 'r' || param[0] == 'R'){
            read(fd, content, BUFFER_LEN);
            printf("\ncontent read from kernel is: %s\n", content);
        }else if(param[0] == 'w' || param[0] == 'W'){
            printf("exec write cmd\n");
            memset(param, 0, sizeof(param)/sizeof(param[0]));
            printf("input your write content: ");
            fgets(param, BUFFER_LEN, stdin);
            write(fd, param, strlen(param));
        }else if(param[0] == 'i' || param[0] == 'I'){
            printf("exec ioctl cmd\n");
            ioctl(fd, 1, NULL);
        }else if(param[0] == 'q' || param[0] == 'Q'){
            printf("will quit...\n");
            close(fd);
            fd = -1;
            break;
        }
    }

    return 0;
}

Android.mk

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
	driver_test.c



LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := driver_test

include $(BUILD_EXECUTABLE)


相關推薦

linux 驅動建立裝置

linux 驅動中建立一個裝置的例子很多,以下例子是建立多個字元裝置的例子,包括驅動部分和測試部分 驅動部分包括 globalmem.c  Makefile兩個檔案: globalmem.c file: #include <linux/module.h>

linux驅動支援裝置

1.註冊裝置 insmod driverName.ko //主要是呼叫xxx_init()函式向chrdev中註冊裝置號(代表一類裝置),和將要使用的裝置數量 // xxx_init()中利用函式結構體,file_operations初始化cdev,然後把cdev和註冊的

程式碼:編寫一個簡單的字元裝置驅動——建立同類型裝置

編寫同類型多個裝置字元驅動應注意一下幾個問題: 1、申請裝置號alloc_chrdev_region時須指定次裝置號範圍; 2、動態分配裝置空間時同時分配NUM個裝置的空間; 3、根據次裝置號和統一的主裝置號生成針對單個裝置的devno,然後完成cdev_add註冊; 4、

一個驅動支援裝置再usb子系統、input子系統、platform、iic子系統 中的實現

platform 你寫的驅動你應該知道它適用與哪些裝置吧,如果你想支援一個裝置,那麼你就構造一個 usb_device_id (USB)、i2c_device_id (IIC)、platform_device_id(Platform)放到對應驅動的id_

ZYNQ Linux驅動開發——第一字元裝置驅動

硬體平臺:XCZ7020 CLG484-1 完全適配Zedboard 開發環境:Widows下Vivado 2016.2 、 SDK2016.2 、 Linux機器:debin 目的:操作板載的LED燈LD9,受PS部分的MIO7控制 linux裝置驅

一個驅動程式對應裝置

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/cdev.h> #in

Linux中通過fork()同時建立程序

1、使用系統呼叫fork()建立三個子程序;2、各個子程序顯示和輸出一些提示資訊和自己的程序識別符號;3、父程序顯示自己的程序ID和一些提示資訊,然後呼叫waitpid()等待多個子程序結束,並在子程序結束後顯示輸出提示資訊表示程式結束。#include <stdio.

Linux中apache建立虛擬主機(訪問站點目錄)

因為公司公用一臺開發機,apache服務是公用的,全域性的document是預設的,不便於改動,只能建立虛擬機器主機及埠來通過http訪問自己的站點目錄。 進入etc/httpd/httpd.conf配置檔案: 1.加入listen埠:     Listen 81 2

linux——alsa中音效卡裝置時開啟某一指定音效卡的PCM裝置

前言   最近除錯板子上的3個ADAU1761音訊介面,使用pocketsphinx語音庫呼叫alsa庫的API介面開啟指定的Mic進行錄入語音時出現異常,預設情況只能開啟第一個ADAU1761音訊介面,想開啟第二個或第三個ADAU1761音訊介面時卻出現錯誤

Windows驅動開發WDM (11)- 裝置物件(同一個驅動

通常在WDM驅動的AddDevice裡面只會呼叫一次IoCreateDevice建立一個裝置物件。其實我們也可以呼叫多次IoCreateDevice來建立多個裝置物件。當驅動呼叫IoCreateDevice成功後,驅動物件DriverObject的DeviceObject指

linux驅動開發之一真正的裝置驅動需要一些什麼元素(裝置號,操作方法)

1,需要一個裝置號(重點看下面的程式碼) 因為核心中有很多的裝置驅動,所以需要一個裝置號id來進行區分 裝置號分成兩個部分: 主裝置號:某一

TCP server 為什麽一個端口可以建立連接?

tab 建立 傳輸 grep not ide 技術分享 什麽 circle https://segmentfault.com/q/1010000003101541 如果是tcp client用同一個本地端口去連不同的兩個服務器ip,連第二個時就會提示端口已被占用。但服務

Linux下nginx+Tomcat負載均衡的實現

java 負載 均衡 bootstra 火墻 瀏覽器 startup 顯示 tomcat的配置 由於項目需要,共創建了10個Tomcat端,由nginx負責轉發。9個Tomcat端口分別是8080,11000,12000,13000,14000,15000,16000,17

Linux下SVN+Tomcat自動部署

mod .html 部署 update語句 hooks 參考 eba bsp auth 項目中都是jsp開發,所以用到Tomcat。 在我文章中也寫過多個Tomcat 的部署,具體可以參考:http://www.cnblogs.com/magmell/p/7045193.h

如何將Linux系統的目錄及文件備份並壓縮到一個文件,以方面保持和傳遞?

如何將linux系統的多個目錄及文件備份並壓縮到一個文件 以方面保持和傳遞? 1.備份Linux系統  window系統在運行狀態下,我們是無法將文件拷貝出來的,那麽在Linux下呢?她的文件結構式一種樹型結構。而且在系統運行的時候我們可以進行打包所有系統文件。特別要說的在Linux的root賬戶具備

Exchange Server 2016管理系列課件45.DAG部署之建立DAG組

Exchange Server 郵件服務器 DAG管理 多DAG管理 方式方法是一樣的,比如我建了三個DAG組,對應的有三個DAG的計算機名稱。每個DAG群集都對應有自己的IP到故障轉移群集管理器中,可以看到DAG相關的群集資源。註意:群集管理器裏面的東西看看可以,但是不建議在群集管理器中隨意

Tomcat建立應用(Web Server),主機,站點的方法

-h 制作 ctp 變量 details real def fonts lin https://blog.csdn.net/chungle2011/article/details/52317433 http://piperzero.iteye.com/blog/147577

linux nginx配置網站

vhost host 編輯 dir OS nginx 文件夾 CA nginx配置 1.把網站配置在hom目錄下,需要建立wwwroot目錄 1.在nginx.conf 增加inlcude代碼,然後創建一個vhost,最後配置個xxx.com.conf //編輯n

Linux 下 svn 項目多用戶分配

usr osi 匿名 win 註意 () 禁止訪問 缺省值 管理 安裝步驟如下: 1、yum install subversion 2、輸入rpm -ql subversion查看安裝位置,如下圖: 輸入 svn –help可以查看svn的使用方法 需求 開發

Linux上配置tomcat的配置修改(修改tomcat配置)

1、修改環境變數      #vi  /etc/profile ####### 工程1 tomcat1####### export CATALINA_BASE=/data/server/tomcat export CATALINA_HOME=$CA