如何编写Linux 驱动程序

如何编写Linux 驱动程序,第1张

Linux是Unix *** 作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁, *** 作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的 *** 作要自己来编写,而且调试也不方便。本人这几周来为实验室自行研制的一块多媒体卡编制了驱动程序,获得了一些经验,愿与Linux fans共享

一、Linux device driver 的概念系统调用是 *** 作系统内核和应用程序之间的接口,设备驱动程序是 *** 作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件, 应用程序可以象 *** 作普通文件一样对硬件设备进行 *** 作。设备驱动程序是内核的一部分,它完成以下的功能:

1对设备初始化和释放。

2把数据从内核传送到硬件和从硬件读取数据。

3读取应用程序传送给设备文件的数据和回送应用程序请求的数据。

4检测和处理设备出现的错误。

二、实例剖析我们来写一个最简单的字符设备驱动程序。虽然它什么也不做,但是通过它可以了解Linux的设备驱动程序的工作原理。

linux安装显卡驱动程序:

1、百度输入nvidia or amd 找到官网

2、在官网中找到显卡驱动程序(包括显卡型号、 *** 作系统位数)

3、点击搜索、进入下载页面。但是有时候会出现网页。可能因为31M太大,网页会出现未能响应的情况。所以在点前一个按钮的时候可以选择右键。使用迅雷下载连接

4、复制下载包到linux 目录下面。可以用u盘考,推荐使用winSCP 工具。这个在windows和linux系统直接传送文件还是很好用的。当然还有好用的远程执行linux 命令的工具——putty (1-4步是在windows系统下完成的)

5、linux下切换到命令行页面:init 3 

6、执行安装命令

[root@localhost ~] sh NVIDIA-Linux-x86-1731418-pkg1run,系统d出安装页面 更详细的Linux介绍可以参考书籍《Linux就该这么学》。

一般的驱动程序是不允许应用程序调用的,只有当驱动程序留出这种供外界访问的接口才行,这种接口一般包括read,write,open,ioctl等接口,如果驱动中预留出了这些接口,就可以在应用程序中调用,比如fd=open(设备,参数);或者fd=ioctl(设备,参数);,这样就会调用到这个设备驱动中的open或者ioctl函数。所以一般如果想再应用程序中调试某个驱动程序,常见的方法就是自己建立一个驱动模块,这个模块中预留出对外接口,比如ioctl。然后在你新建的这个驱动模块中完成ioctl函数,如下:

int device_ioctl(fd,argv) {

/ your function; /

}

static struct file_operations device = {

ioctl = device_ioctl //预留外部接口

};

应用程序如下:

ioctl(device,argv);

上面这句就可以完成你的模块中ioctl中的功能。

linux的驱动一般有两种格式,分别为:tar和rpm格式。

rpm安装步骤:

1.将驱动程序文件bcm5700-srcrpm复制到一个临时目录中,并在此目录中运行以下命令:

rpm –ivh bcm5700-srcrpm

2.运行以下命令切换到驱动目录中:

cd /usr/src/redhat/SPECS/

3.此目录中会生成一个名字为bcm5700spec的文件,运行以下命令对驱动程序进行编译:

rpmbuild –bb bcm5700spec (对4xx版本的RPM适用)或 rpm -bb bcm5700spec

4.运行以下命令切换到RPM目录中:

cd /usr/src/redhat/RPMS/i386/

5.运行以下命令安装驱动程序:

rpm –ivh bcm5700-i386rpm (对于Red Hat 72, 73, 21AS和其他包含老版本驱动的系统需要使用--force的参数,强制用新的驱动替换系统自带的老版本驱动)

6.运行以下命令加载驱动模块:

insmod bcm5700

7.运行kudzu命令,系统会自动搜索到硬件,进行配置即可。

或者重新启动系统,启动过程中系统会自动找到硬件,进行相应配置即可。

tar格式安装步骤:

1 将驱动程序压缩文件bcm5700-targz复制到一个临时目录中,并使用以下命令解压缩:

tar xvzf bcm5700-targz

2.构建驱动程序为运行内核可加载模块

cd bcm5700-/src

make

3.加载测试

insmod bcm5700

4.加载驱动程序

make install

5.重新启动系统,启动过程中找到硬件,进行相应配置。

或者直接运行kudzu命令,系统会自动搜索到硬件,进行配置即可。

USB驱动程序基础

在动手写USB驱动程序这前,让我们先看看写的USB驱动程序在内核中的结构,如下图:

 

USB驱动程序存在于不同的内核子系统和USB硬件控制器之间,USB核心为USB驱动程序提供了一个用于访问和控制USB硬件的接口,而不必考虑系统当前存在的各种不同类型的USB硬件控制器。USB是一个非常复杂的设备,linux内核为我们提供了一个称为USB的核心的子系统来处理大部分的复杂性,USB设备包括配置(configuration)、接口(interface)和端点(endpoint),USB设备绑定到接口上,而不是整个USB设备。如下图所示:

 

USB通信最基本的形式是通过端点(USB端点分中断、批量、等时、控制四种,每种用途不同),USB端点只能往一个方向传送数据,从主机到设备或者从设备到主机,端点可以看作是单向的管道(pipe)。所以我们可以这样认为:设备通常具有一个或者更多的配置,配置经常具有一个或者更多的接口,接口通常具有一个或者更多的设置,接口没有或具有一个以上的端点。驱动程序把驱动程序对象注册到USB子系统中,稍后再使用制造商和设备标识来判断是否已经安装了硬件。USB核心使用一个列表(是一个包含制造商ID和设备号ID的一个结构体)来判断对于一个设备该使用哪一个驱动程序,热插拨脚本使用它来确定当一个特定的设备插入到系统时该自动装载哪一个驱动程序。

上面我们简要说明了驱动程序的基本理论,在写一个设备驱动程序之前,我们还要了解以下两个概念:模块和设备文件。

模块:是在内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能独立运行,但是可以装载到系统中作为内核的一部分运行,从而可以动态扩充内核的功能。模块最主要的用处就是用来实现设备驱动程序。Linux下对于一个硬件的驱动,可以有两种方式:直接加载到内核代码中,启动内核时就会驱动此硬件设备。另一种就是以模块方式,编译生成一个ko文件(在24以下内核中是用o作模块文件,我们以26的内核为准,以下同)。当应用程序需要时再加载到内核空间运行。所以我们所说的一个硬件的驱动程序,通常指的就是一个驱动模块。

设备文件:对于一个设备,它可以在/dev下面存在一个对应的逻辑设备节点,这个节点以文件的形式存在,但它不是普通意义上的文件,它是设备文件,更确切的说,它是设备节点。这个节点是通过mknod命令建立的,其中指定了主设备号和次设备号。主设备号表明了某一类设备,一般对应着确定的驱动程序;次设备号一般是区分不同属性,例如不同的使用方法,不同的位置,不同的 *** 作。这个设备号是从/proc/devices文件中获得的,所以一般是先有驱动程序在内核中,才有设备节点在目录中。这个设备号(特指主设备号)的主要作用,就是声明设备所使用的驱动程序。驱动程序和设备号是一一对应的,当你打开一个设备文件时, *** 作系统就已经知道这个设备所对应的驱动程序。对于一个硬件,Linux是这样来进行驱动的:首先,我们必须提供一个ko的驱动模块文件。我们要使用这个驱动程序,首先要加载它,我们可以用insmod

xxxko,这样驱动就会根据自己的类型(字符设备类型或块设备类型,例如鼠标就是字符设备而硬盘就是块设备)向系统注册,注册成功系统会反馈一个主设备号,这个主设备号就是系统对它的唯一标识。驱动就是根据此主设备号来创建一个一般放置在/dev目录下的设备文件。在我们要访问此硬件时,就可以对设备文件通过open、read、write、close等命令进行。而驱动就会接收到相应的read、write *** 作而根据自己的模块中的相应函数进行 *** 作了。

USB驱动程序实践

了解了上述理论后,我们就可以动手写驱动程序,如果你基本功好,而且写过linux下的硬件驱动,USB的硬件驱动和pci_driver很类似,那么写USB的驱动就比较简单了,如果你只是大体了解了linux的硬件驱动,那也不要紧,因为在linux的内核源码中有一个框架程序可以拿来借用一下,这个框架程序在/usr/src/~(你的内核版本,以下同)/drivers/usb下,文件名为usb-skeletonc。写一个USB的驱动程序最基本的要做四件事:驱动程序要支持的设备、注册USB驱动程序、探测和断开、提交和控制urb(USB请求块)(当然也可以不用urb来传输数据,下文我们会说到)。

驱动程序支持的设备:有一个结构体struct

usb_device_id,这个结构体提供了一列不同类型的该驱动程序支持的USB设备,对于一个只控制一个特定的USB设备的驱动程序来说,struct

usb_device_id表被定义为:

/ 驱动程序支持的设备列表 /

static struct usb_device_id

skel_table [] = {

    { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID)

},

    { }                    / 终止入口 /

};

MODULE_DEVICE_TABLE (usb,

skel_table);

对于PC驱动程序,MODULE_DEVICE_TABLE是必需的,而且usb必需为该宏的第一个值,而USB_SKEL_VENDOR_ID和USB_SKEL_PRODUCT_ID就是这个特殊设备的制造商和产品的ID了,我们在程序中把定义的值改为我们这款USB的,如:

/

定义制造商和产品的ID号 /

#define USB_SKEL_VENDOR_ID    0x1234

#define

USB_SKEL_PRODUCT_ID   

0x2345

这两个值可以通过命令lsusb,当然你得先把USB设备先插到主机上了。或者查看厂商的USB设备的手册也能得到,在我机器上运行lsusb是这样的结果:

Bus

004 Device 001: ID 0000:0000 

Bus 003 Device 002: ID 1234:2345  Abc  Corp

Bus 002 Device 001: ID 0000:0000 

Bus 001 Device 001: ID

0000:0000

得到这两个值后把它定义到程序里就可以了。

注册USB驱动程序:所有的USB驱动程序都必须创建的结构体是struct

usb_driver。这个结构体必须由USB驱动程序来填写,包括许多回调函数和变量,它们向USB核心代码描述USB驱动程序。创建一个有效的struct

usb_driver结构体,只须要初始化五个字段就可以了,在框架程序中是这样的:

static struct usb_driver skel_driver

= {

    owner =    THIS_MODULE,

    name =        "skeleton",

   

probe =    skel_probe,

    disconnect =    skel_disconnect,

   

id_table =    skel_table,

};

由于你的问题太长我只好转载别人的手打的太累不好意思~~~

Linux是Unix作系统的一种变种,在Linux下编写驱动程序的原理和

思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的

区别在Linux环境下设计驱动程序,思想简洁,作方便,功芤埠芮看但是

支持函数少,只能依赖kernel中的函数,有些常用的作要自己来编写,而且调

试也不方便本人这几周来为实验室自行研制的一块多媒体卡编制了驱动程序,

获得了一些经验,愿与Linux fans共享,有不当之处,请予指正

以下的一些文字主要来源于khg,johnsonm的Write linux device driver,

Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关

device driver的一些资料 这些资料有的已经过时,有的还有一些错误,我依

据自己的试验结果进行了修正

一 Linux device driver 的概念

系统调用是作系统内核和应用程序之间的接口,设备驱动程序是作系统

内核和机器硬件之间的接口设备驱动程序为应用程序屏蔽了硬件的细节,这样

在应用程序看来,硬件设备只是一个设备文件, 应用程序可以象作普通文件

一样对硬件设备进行作设备驱动程序是内核的一部分,它完成以下的功能:

1对设备初始化和释放

2把数据从内核传送到硬件和从硬件读取数据

3读取应用程序传送给设备文件的数据和回送应用程序请求的数据

4检测和处理设备出现的错误

在Linux作系统下有两类主要的设备文件类型,一种是字符设备,另一种是

块设备字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际

的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,

当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际

的I/O作块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间

来等待

已经提到,用户进程是通过设备文件来与实际的硬件打交道每个设备文件都

都有其文件属性(c/b),表示是字符设备还蔤强樯璞另外每个文件都有两个设

备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个

设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分

他们设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号

一致,否则用户进程将无法访问到驱动程序

最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是

抢先式调度也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他

的工作如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就

是漫长的fsck//hehe

(请看下节,实例剖析)

读/写时,它首先察看缓冲区的内容,如果缓冲区的数据

如何编写Linux作系统下的设备驱动程序

Roy G

二实例剖析

我们来写一个最简单的字符设备驱动程序虽然它什么也不做,但是通过它

可以了解Linux的设备驱动程序的工作原理把下面的C代码输入机器,你就会

获得一个真正的设备驱动程序不过我的kernel是2034,在低版本的kernel

上可能会出现问题,我还没测试过//xixi

#define __NO_VERSION__

#include

#include

char kernel_version [] = UTS_RELEASE;

这一段定义了一些版本信息,虽然用处不是很大,但也必不可少Johnsonm说所

有的驱动程序的开头都要包含,但我看倒是未必

由于用户进程是通过设备文件同硬件打交道,对设备文件的作方式不外乎就

是一些系统调用,如 open,read,write,close, 注意,不是fopen, fread,

但是如何把系统调用和驱动程序关联起来呢这需要了解一个非常关键的数据

结构:

struct file_operations {

int (seek) (struct inode ,struct file , off_t ,int);

int (read) (struct inode ,struct file , char ,int);

int (write) (struct inode ,struct file , off_t ,int);

int (readdir) (struct inode ,struct file , struct dirent ,int);

int (select) (struct inode ,struct file , int ,select_table );

int (ioctl) (struct inode ,struct file , unsined int ,unsigned long

int (mmap) (struct inode ,struct file , struct vm_area_struct );

int (open) (struct inode ,struct file );

int (release) (struct inode ,struct file );

int (fsync) (struct inode ,struct file );

int (fasync) (struct inode ,struct file ,int);

int (check_media_change) (struct inode ,struct file );

int (revalidate) (dev_t dev);

}

这个结构的每一个成员的名字都对应着一个系统调用用户进程利用系统调用

在对设备文件进行诸如read/write作时,系统调用通过设备文件的主设备号

找到相应的设备驱动程序,然后读取这个数据结构相应的函数指针,接着把控制

权交给该函数这是linux的设备驱动程序工作的基本原理既然是这样,则编写

设备驱动程序的主要工作就是编写子函数,并填充file_operations的各个域

相当简单,不是吗

下面就开始写子程序

#include

#include

#include

#include

#include

unsigned int test_major = 0;

static int read_test(struct inode node,struct file file,

char buf,int count)

{

int left;

if (verify_area(VERIFY_WRITE,buf,count) == -EFAULT )

return -EFAULT;

for(left = count left > 0 left--)

{

__put_user(1,buf,1);

buf++;

}

return count;

}

这个函数是为read调用准备的当调用read时,read_test()被调用,它把用户的

缓冲区全部写1

buf 是read调用的一个参数它是用户进程空间的一个地址但是在read_test

被调用时,系统进入核心态所以不能使用buf这个地址,必须用__put_user(),

这是kernel提供的一个函数,用于向用户传送数据另外还有很多类似功能的

函数请参考在向用户空间拷贝数据之前,必须验证buf是否可用

这就用到函数verify_area

static int write_tibet(struct inode inode,struct file file,

const char buf,int count)

{

return count;

}

static int open_tibet(struct inode inode,struct file file )

{

MOD_INC_USE_COUNT;

return 0;

} static void release_tibet(struct inode inode,struct file file )

{

MOD_DEC_USE_COUNT;

}

这几个函数都是空作实际调用发生时什么也不做,他们仅仅为下面的结构

提供函数指针。

struct file_operations test_fops = {

NULL,

read_test,

write_test,

NULL, / test_readdir /

NULL,

NULL, / test_ioctl /

NULL, / test_mmap /

open_test,

release_test, NULL, / test_fsync /

NULL, / test_fasync /

/ nothing more, fill with NULLs /

};

设备驱动程序的主体可以说是写好了。现在要把驱动程序嵌入内核。驱动程序

可以按照两种方式编译。一种是编译进kernel,另一种是编译成模块(modules),

如果编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能

动态的卸载,不利于调试,所以推荐使用模块方式。

int init_module(void)

{

int result;

result = register_chrdev(0, "test", &test_fops);

if (result < 0) {

printk(KERN_INFO "test: can't get major number ");

return result;

}

if (test_major == 0) test_major = result; / dynamic /

return 0;

}

在用insmod命令将编译好的模块调入内存时,init_module 函数被调用。在

这里,init_module只做了一件事,就是向系统的字符设备表登记了一个字符

设备。register_chrdev需要三个参数,参数一是希望获得的设备号,如果是

零的话,系统将选择一个没有被占用的设备号返回。参数二是设备文件名,

参数三用来登记驱动程序实际执行作的函数的指针。

如果登记成功,返回设备的主设备号,不成功,返回一个负值。

void cleanup_module(void)

{

unregister_chrdev(test_major, "test");

}

在用rmmod卸载模块时,cleanup_module函数被调用,它释放字符设备test

在系统字符设备表中占有的表项。

一个极其简单的字符设备可以说写好了,文件名就叫testc吧。

下面编译

$ gcc -O2 -DMODULE -D__KERNEL__ -c testc

得到文件testo就是一个设备驱动程序。

如果设备驱动程序有多个文件,把每个文件按上面的命令行编译,然后

ld -r file1o file2o -o modulename

驱动程序已经编译好了,现在把它安装到系统中去。

$ insmod -f testo

如果安装成功,在/proc/devices文件中就可以看到设备test,

并可以看到它的主设备号,。

要卸载的话,运行

$ rmmod test

下一步要创建设备文件。

mknod /dev/test c major minor

c 是指字符设备,major是主设备号,就是在/proc/devices里看到的。

用shell命令

$ cat /proc/devices | awk "\$2=="test" {print \$1}"

就可以获得主设备号,可以把上面的命令行加入你的shell script中去。

minor是从设备号,设置成0就可以了。

我们现在可以通过设备文件来访问我们的驱动程序。写一个小小的测试程序。

#include

#include

#include

#include

main()

{

int testdev;

int i;

char buf[10];

testdev = open("/dev/test",O_RDWR);

if ( testdev == -1 )

{

printf("Cann't open file ");

exit(0);

}

read(testdev,buf,10);

for (i = 0; i < 10;i++)

printf("%d ",buf);

close(testdev);

}

编译运行,看看是不是打印出全1 ?

以上只是一个简单的演示。真正实用的驱动程序要复杂的多,要处理如中断,

DMA,I/O port等问题。这些才是真正的难点。请看下节,实际情况的处理。

如何编写Linux作系统下的设备驱动程序

Roy G

三 设备驱动程序中的一些具体问题。

1 I/O Port

和硬件打交道离不开I/O Port,老的ISA设备经常是占用实际的I/O端口,

在linux下,作系统没有对I/O口屏蔽,也就是说,任何驱动程序都可以

对任意的I/O口作,这样就很容易引起混乱。每个驱动程序应该自己避免

误用端口。

有两个重要的kernel函数可以保证驱动程序做到这一点。

1)check_region(int io_port, int off_set)

这个函数察看系统的I/O表,看是否有别的驱动程序占用某一段I/O口。

参数1:io端口的基地址,

参数2:io端口占用的范围。

返回值:0 没有占用, 非0,已经被占用。

2)request_region(int io_port, int off_set,char devname)

如果这段I/O端口没有被占用,在我们的驱动程序中就可以使用它。在使用

之前,必须向系统登记,以防止被其他程序占用。登记后,在/proc/ioports

文件中可以看到你登记的io口。

参数1:io端口的基地址。

参数2:io端口占用的范围。

参数3:使用这段io地址的设备名。

在对I/O口登记后,就可以放心地用inb(), outb()之类的函来访问了。

在一些pci设备中,I/O端口被映射到一段内存中去,要访问这些端口就相当

于访问一段内存。经常性的,我们要获得一块内存的物理地址。在dos环境下,

(之所以不说是dos作系统是因为我认为DOS根本就不是一个作系统,它实

在是太简单,太不安全了)只要用段:偏移就可以了。在window95中,95ddk

提供了一个vmm 调用 _MapLinearToPhys,用以把线性地址转化为物理地址。但

在Linux中是怎样做的呢?

2 内存作

在设备驱动程序中动态开辟内存,不是用malloc,而是kmalloc,或者用

get_free_pages直接申请页。释放内存用的是kfree,或free_pages 请注意,

kmalloc等函数返回的是物理地址!而malloc等返回的是线性地址!关于

kmalloc返回的是物理地址这一点本人有点不太明白:既然从线性地址到物理

地址的转换是由386cpu硬件完成的,那样汇编指令的作数应该是线性地址,

驱动程序同样也不能直接使用物理地址而是线性地址。但是事实上kmalloc

返回的确实是物理地址,而且也可以直接通过它访问实际的RAM,我想这样可

以由两种解释,一种是在核心态禁止分页,但是这好像不太现实;另一种是

linux的页目录和页表项设计得正好使得物理地址等同于线性地址。我的想法

不知对不对,还请高手指教。

言归正传,要注意kmalloc最大只能开辟128k-16,16个字节是被页描述符

结构占用了。kmalloc用法参见khg

内存映射的I/O口,寄存器或者是硬件设备的RAM(如显存)一般占用F0000000

以上的地址空间。在驱动程序中不能直接访问,要通过kernel函数vremap获得

重新映射以后的地址。

另外,很多硬件需要一块比较大的连续内存用作DMA传送。这块内存需要一直

驻留在内存,不能被交换到文件中去。但是kmalloc最多只能开辟128k的内存。

这可以通过牺牲一些系统内存的方法来解决。

具体做法是:比如说你的机器由32M的内存,在liloconf的启动参数中加上

mem=30M,这样linux就认为你的机器只有30M的内存,剩下的2M内存在vremap

之后就可以为DMA所用了。

请记住,用vremap映射后的内存,不用时应用unremap释放,否则会浪费页表。

3 中断处理

同处理I/O端口一样,要使用一个中断,必须先向系统登记。

int request_irq(unsigned int irq ,

void(handle)(int,void ,struct pt_regs ),

unsigned int long flags,

const char device);

irq: 是要申请的中断。

handle:中断处理函数指针。

flags:SA_INTERRUPT 请求一个快速中断,0 正常中断。

device:设备名。

如果登记成功,返回0,这时在/proc/interrupts文件中可以看你请求的

中断。

4一些常见的问题。

对硬件作,有时时序很重要。但是如果用C语言写一些低级的硬件作

的话,gcc往往会对你的程序进行优化,这样时序就错掉了。如果用汇编写呢,

gcc同样会对汇编代码进行优化,除非你用volatile关键字修饰。最保险的

办法是禁止优化。这当然只能对一部分你自己编写的代码。如果对所有的代码

都不优化,你会发现驱动程序根本无法装载。这是因为在编译驱动程序时要

用到gcc的一些扩展特性,而这些扩展特性必须在加了优化选项之后才能体现

出来。

关于kernel的调试工具,我现在还没有发现有合适的。有谁知道请告诉我,

不胜感激。我一直都在printk打印调试信息,倒也还凑合。

关于设备驱动程序还有很多内容,如等待/唤醒机制,块设备的编写等。

我还不是很明白,不敢乱说。

在Linux kernel源码目录中driver/usb/usb-skeletonc为我们提供了一个最基础的USB驱动程序。我们称为USB骨架。通过它我们仅需要修改极少的部分,就可以完成一个USB设备的驱动。我们的USB驱动开发也是从她开始的。

那些linux下不支持的USB设备几乎都是生产厂商特定的产品。如果生产厂商在他们的产品中使用自己定义的协议,他们就需要为此设备创建特定的驱动程序。当然我们知道,有些生产厂商公开他们的USB协议,并帮助Linux驱动程序的开发,然而有些生产厂商却根本不公开他们的USB协议。因为每一个不同的协议都会产生一个新的驱动程序,所以就有了这个通用的USB驱动骨架程序, 它是以pci 骨架为模板的。

如果你准备写一个linux驱动程序,首先要熟悉USB协议规范。USB主页上有它的帮助。一些比较典型的驱动可以在上面发现,同时还介绍了USB urbs的概念,而这个是usb驱动程序中最基本的。

Linux USB 驱动程序需要做的第一件事情就是在Linux USB 子系统里注册,并提供一些相关信息,例如这个驱动程序支持哪种设备,当被支持的设备从系统插入或拔出时,会有哪些动作。所有这些信息都传送到USB 子系统中。

楼主如果想学习如何使用Linux系统,可以百度《Linux就该这么学》,里面有详细的介绍。

以上就是关于如何编写Linux 驱动程序全部的内容,包括:如何编写Linux 驱动程序、在Linux上怎样安装显卡驱动、Linux应用程序如何调用驱动程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9977574.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存