`
djsl6071
  • 浏览: 593390 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

Linux环境下USB的原理、驱动和配置

阅读更多

本文由CSDN 特别约稿,作者为北京中科红旗软件技术有限公司 嵌入式工程师 梁国军

转自: http://news.csdn.net/n/20071015/109592.html


        随着生活水平的提高,人们对USB设备的使用也越来越多,鉴于Linux在硬件配置上尚不能全部即插即用,因此关于Linux如何配置和使用,成为困扰我们的一大问题。

<!----><o:p> </o:p>

什么是USB<o:p></o:p>

USB是英文Universal Serial Bus的缩写,意为通用串行总线。USB最初是为了替代许多不同的低速总线(包括并行、串行和键盘连接)而设计的,它以单一类型的总线连接各种不同的类型的设备。USB的发展已经超越了这些低速的连接方式,它现在可以支持几乎所有可以连接到PC上的设备。最新的USB规范修订了理论上高达480Mbps的高速连接。Linux内核支持两种主要类型的USB驱动程序:宿主系统上的驱动程序和设备上的驱动程序,从宿主的观点来看(一个普通的宿主也就是一个PC机),宿主系统的USB设备驱动程序控制插入其中的USB设备,而USB设备的驱动程序控制该设备如何作为一个USB设备和主机通信。<o:p></o:p>

<o:p> </o:p>

USB的具体构成<o:p></o:p>

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

<o:p> </o:p>

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

<o:p> </o:p>

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

<o:p> </o:p>

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

<o:p> </o:p>

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

<o:p> </o:p>

设备文件:对于一个设备,它可以在/dev下面存在一个对应的逻辑设备节点,这个节点以文件的形式存在,但它不是普通意义上的文件,它是设备文件,更确切的说,它是设备节点。这个节点是通过mknod命令建立的,其中指定了主设备号和次设备号。主设备号表明了某一类设备,一般对应着确定的驱动程序;次设备号一般是区分不同属性,例如不同的使用方法,不同的位置,不同的操作。这个设备号是从/proc/devices文件中获得的,所以一般是先有驱动程序在内核中,才有设备节点在目录中。这个设备号(特指主设备号)的主要作用,就是声明设备所使用的驱动程序。驱动程序和设备号是一一对应的,当你打开一个设备文件时,操作系统就已经知道这个设备所对应的驱动程序。对于一个硬件,Linux是这样来进行驱动的:首先,我们必须提供一个.ko的驱动模块文件。我们要使用这个驱动程序,首先要加载它,我们可以用insmod xxx.ko,这样驱动就会根据自己的类型(字符设备类型或块设备类型,例如鼠标就是字符设备而硬盘就是块设备)向系统注册,注册成功系统会反馈一个主设备号,这个主设备号就是系统对它的唯一标识。驱动就是根据此主设备号来创建一个一般放置在/dev目录下的设备文件。在我们要访问此硬件时,就可以对设备文件通过openreadwriteclose等命令进行。而驱动就会接收到相应的readwrite操作而根据自己的模块中的相应函数进行操作了。<o:p></o:p>

<o:p> </o:p>

USB驱动程序如何应用<o:p></o:p>

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

<o:p> </o:p>

驱动程序支持的设备:有一个结构体struct usb_device_id,这个结构体提供了一列不同类型的该驱动程序支持的USB设备,对于一个只控制一个特定的USB设备的驱动程序来说,struct usb_device_id表被定义为:<o:p></o:p>

/* 驱动程序支持的设备列表 */<o:p></o:p>

static struct usb_device_id skel_table [] = {<o:p></o:p>

       { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },<o:p></o:p>

       { }                               /* 终止入口 */<o:p></o:p>

};<o:p></o:p>

MODULE_DEVICE_TABLE (usb, skel_table);<o:p></o:p>

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

/* 定义制造商和产品的ID */<o:p></o:p>

#define USB_SKEL_VENDOR_ID       0x1234<o:p></o:p>

#define USB_SKEL_PRODUCT_ID     0x2345<o:p></o:p>

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

Bus 004 Device 001: ID 0000:0000  <o:p></o:p>

Bus 003 Device 002: ID 1234:2345  Abc  Corp. <o:p></o:p>

Bus 002 Device 001: ID 0000:0000  <o:p></o:p>

Bus 001 Device 001: ID 0000:0000<o:p></o:p>

得到这两个值后把它定义到程序里就可以了。<o:p></o:p>

<o:p> </o:p>

注册USB驱动程序:所有的USB驱动程序都必须创建的结构体是struct usb_driver。这个结构体必须由USB驱动程序来填写,包括许多回调函数和变量,它们向USB核心代码描述USB驱动程序。创建一个有效的struct usb_driver结构体,只须要初始化五个字段就可以了,在框架程序中是这样的:<o:p></o:p>

static struct usb_driver skel_driver = {<o:p></o:p>

       .owner = THIS_MODULE,<o:p></o:p>

       .name =          "skeleton",<o:p></o:p>

       .probe =  skel_probe,<o:p></o:p>

       .disconnect =  skel_disconnect,<o:p></o:p>

       .id_table =      skel_table,<o:p></o:p>

};<o:p></o:p>

struct module *owner :指向该驱动程序的模块所有者的批针。USB核心使用它来正确地对该USB驱动程序进行引用计数,使它不会在不合适的时刻被卸载掉,这个变量应该被设置为THIS_MODULE宏。<o:p></o:p>

const char *name:指向驱动程序名字的指针,在内核的所有USB驱动程序中它必须是唯一的,通常被设置为和驱动程序模块名相同的名字。<o:p></o:p>

int (*probe) (struct usb_interface *intf,const struct usb_device_id *id):这个是指向USB驱动程序中的探测函数的指针。当USB核心认为它有一个接口(usb_interface)可以由该驱动程序处理时,这个函数被调用。<o:p></o:p>

void (disconnect)(struct usb_interface *intf):指向USB驱动程序中的断开函数的指针,当一个USB接口(usb_interface)被从系统中移除或者驱动程序正在从USB核心中卸载时,USB核心将调用这个函数。<o:p></o:p>

const struct usb_device_id *id_table:指向ID设备表的指针,这个表包含了一列该驱动程序可以支持的USB设备,如果没有设置这个变量,USB驱动程序中的探测回调函数就不会被调用。<o:p></o:p>

在这个结构体中还有其它的几个回调函数不是很常用,这里就不一一说明了。以struct usb_driver 指针为参数的usb_register_driver函数调用把struct usb_driver注册到USB核心。一般是在USB驱动程序的模块初始化代码中完成这个工作的:<o:p></o:p>

static int __init usb_skel_init(void)<o:p></o:p>

{<o:p></o:p>

       int result;<o:p></o:p>

<o:p> </o:p>

       /* 驱动程序注册到USB子系统中*/<o:p></o:p>

       result = usb_register(&skel_driver);<o:p></o:p>

       if (result)<o:p></o:p>

              err("usb_register failed. Error number %d", result);<o:p></o:p>

<o:p> </o:p>

       return result;<o:p></o:p>

}<o:p></o:p>

USB驱动程序将要被卸开时,需要把struct usb_driver从内核中注销。通过调用usb_deregister_driver来完成这个工作,当调用发生时,当前绑定到该驱动程序上的任何USB接口都被断开,断开函数将被调用:<o:p></o:p>

static void __exit usb_skel_exit(void)<o:p></o:p>

{<o:p></o:p>

       /* 从子系统注销驱动程序 */<o:p></o:p>

       usb_deregister(&skel_driver);<o:p></o:p>

}<o:p></o:p>

<o:p> </o:p>

探测和断开:当一个设备被安装而USB核心认为该驱动程序应该处理时,探测函数被调用,探测函数检查传递给它的设备信息,确定驱动程序是否真的适合该设备。当驱动程序因为某种原因不应该控制设备时,断开函数被调用,它可以做一些清理工作。探测回调函数中,USB驱动程序初始化任何可能用于控制USB设备的局部结构体,它还把所需的任何设备相关信息保存到一个局部结构体中,下面是探测函数的部分源码,我们加以分析。<o:p></o:p>

<o:p> </o:p>

       /* 设置端点信息 */<o:p></o:p>

       /* 只使用第一个批量IN和批量OUT端点 */<o:p></o:p>

       iface_desc = interface->cur_altsetting;<o:p></o:p>

       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {<o:p></o:p>

              endpoint = &iface_desc->endpoint[i].desc;<o:p></o:p>

<o:p> </o:p>

              if (!dev->bulk_in_endpointAddr &&<o:p></o:p>

                  (endpoint->bEndpointAddress & USB_DIR_IN) &&<o:p></o:p>

                  ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)<o:p></o:p>

                                   == USB_ENDPOINT_XFER_BULK)) {<o:p></o:p>

                     /* 找到一个批量IN端点 */<o:p></o:p>

                     buffer_size = endpoint->wMaxPacketSize;<o:p></o:p>

                     dev->bulk_in_size = buffer_size;<o:p></o:p>

                     dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;<o:p></o:p>

                     dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);<o:p></o:p>

                     if (!dev->bulk_in_buffer) {<o:p></o:p>

                            err("Could not allocate bulk_in_buffer");<o:p></o:p>

                            goto error;<o:p></o:p>

                     }<o:p></o:p>

              }<o:p></o:p>

<o:p> </o:p>

              if (!dev->bulk_out_endpointAddr &&<o:p></o:p>

                  !(endpoint->bEndpointAddress & USB_DIR_IN) &&<o:p></o:p>

                  ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)<o:p></o:p>

                                   == USB_ENDPOINT_XFER_BULK)) {<o:p></o:p>

                     /* 找到一个批量OUT端点 */<o:p></o:p>

                     dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;<o:p></o:p>

              }<o:p></o:p>

       }<o:p></o:p>

       if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {<o:p></o:p>

              err("Could not find both bulk-in and bulk-out endpoints");<o:p></o:p>

              goto error;<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

在探测函数里,这个循环首先访问该接口中存在的每一个端点,给该端点一个局部指针以便以后访问:<o:p></o:p>

<o:p> </o:p>

for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {<o:p></o:p>

              endpoint = &iface_desc->endpoint[i].desc;<o:p></o:p>

<o:p> </o:p>

在一轮探测过后,我们就有了一个端点,在还没有发现批量IN类型的端点时,探测该端点方向是否为IN,这可以通过检查USB_DIR_IN是否包含在bEndpointAddress端点变量有确定,如果是的话,我们在探测该端点类型是否为批量,先用USB_ENDPOINT_XFERTYPE_MASK位掩来取bmAttributes变量的值,然后探测它是否和USB_ENDPOINT_XFER_BULK值匹配:<o:p></o:p>

<o:p> </o:p>

              if (!dev->bulk_out_endpointAddr &&<o:p></o:p>

                  !(endpoint->bEndpointAddress & USB_DIR_IN) &&<o:p></o:p>

                  ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)<o:p></o:p>

                                   == USB_ENDPOINT_XFER_BULK))<o:p></o:p>

<o:p> </o:p>

如果所有这些探测都通过了,驱动程序就知道它已经发现了正确的端点类型,可以把该端点的相关信息保存到一个局部结构体中以便稍后用它来和端点进行通信:<o:p></o:p>

<o:p> </o:p>

                     /* 找到一个批量IN类型的端点 */<o:p></o:p>

                     buffer_size = endpoint->wMaxPacketSize;<o:p></o:p>

                     dev->bulk_in_size = buffer_size;<o:p></o:p>

                     dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;<o:p></o:p>

                     dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);<o:p></o:p>

                     if (!dev->bulk_in_buffer) {<o:p></o:p>

                            err("Could not allocate bulk_in_buffer");<o:p></o:p>

                            goto error;<o:p></o:p>

                     }<o:p></o:p>

<o:p> </o:p>

因为USB驱动程序要在设备的生命周期的稍后时间获取和接口相关联的局部数据结构体,所以调用了usb_set_intfdata函数,把它保存到struct usb_interface结构体中以便后面的访问<o:p></o:p>

<o:p> </o:p>

       /* 把数据指针保存到这个接口设备中 */<o:p></o:p>

       usb_set_intfdata(interface, dev);<o:p></o:p>

<o:p> </o:p>

我们以后调用usb_set_intfdata函数来获取数据。当这一切都完成后,USB驱动程序必须在探测函数中调用usb_register_dev函数来把该设备注册到USB核心里:<o:p></o:p>

<o:p> </o:p>

       /* 注册设备到USB核心 */<o:p></o:p>

       retval = usb_register_dev(interface, &skel_class);<o:p></o:p>

       if (retval) {<o:p></o:p>

              /* 有些情况下是不允许注册驱动程序的 */<o:p></o:p>

              err("Not able to get a minor for this device.");<o:p></o:p>

              usb_set_intfdata(interface, NULL);<o:p></o:p>

              goto error;<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

当一个USB设备被断开时,和该设备相关联的所有资源都应该被尽可能的清理掉,在此时,如果已在在探测函数中调用了注册函数来为该USB设备分配了一个次设备号话,必须调用usb_deregister_dev函数来把次设备号交还给USB核心。在断开函数中,从接口获取之前调用usb_set_intfdata设置的任何数据也是很重要的。然后设置struct usb_interface结构体中的数据指针为NULL,以防任何不适当的对该数据的错误访问。<o:p></o:p>

<o:p> </o:p>

在探测函数中会对每一个接口进行一次探测,所以我们在写USB驱动程序的时候,只要做好第一个端点,其它的端点就会自动完成探测。在探测函数中我们要注意的是在内核中用结构体struct usb_host_endpoint来描述USB端点,这个结构体在另一个名为struct usb_endpoint_descriptor的结构体中包含了真正的端点信息,struct usb_endpoint_descriptor结构体包含了所有的USB特定的数据,该结构体中我们要关心的几个字段是:<o:p></o:p>

<o:p> </o:p>

bEndpointAddress:这个是特定的USB地址,可以结合USB_DIR_INUSB_DIR_OUT来使用,以确定该端点的数据是传向设备还是主机。<o:p></o:p>

<o:p> </o:p>

bmAttributes:这个是端点的类型,这个值可以结合位掩码USB_ENDPOINT_XFERTYPE_MASK来使用,以确定此端点的类型是USB_ENDPOINT_XFER_ISOC(等时)、USB_ENDPOINT_XFER_BULK(批量)、USB_ENDPOINT_XFER_INT的哪一种。<o:p></o:p>

wMaxPacketSize:这个是端点一次可以处理的最大字节数,驱动程序可以发送数量大于此值的数据到端点,在实际传输中,数据量如果大于此值会被分割。<o:p></o:p>

<o:p> </o:p>

bInterval:这个值只有在端点类型是中断类型时才起作用,它是端点中断请求的间隔时间,以毫秒为单位。<o:p></o:p>

<o:p> </o:p>

提交和控制urb:当驱动程序有数据要发送到USB设备时(大多数情况是在驱动程序的写函数中),要分配一个urb来把数据传输给设备:<o:p></o:p>

<o:p> </o:p>

       /* 创建一个urb,并且给它分配一个缓存*/<o:p></o:p>

       urb = usb_alloc_urb(0, GFP_KERNEL);<o:p></o:p>

       if (!urb) {<o:p></o:p>

              retval = -ENOMEM;<o:p></o:p>

              goto error;<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

urb被成功分配后,还要创建一个DMA缓冲区来以高效的方式发送数据到设备,传递给驱动程序的数据要复制到这块缓冲中去:<o:p></o:p>

<o:p> </o:p>

       buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);<o:p></o:p>

       if (!buf) {<o:p></o:p>

              retval = -ENOMEM;<o:p></o:p>

              goto error;<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

       if (copy_from_user(buf, user_buffer, count)) {<o:p></o:p>

              retval = -EFAULT;<o:p></o:p>

              goto error;<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

当数据从用户空间正确复制到局部缓冲区后,urb必须在可以被提交给USB核心之前被正确初始化:<o:p></o:p>

<o:p> </o:p>

       /* 初始化urb */<o:p></o:p>

       usb_fill_bulk_urb(urb, dev->udev,<o:p></o:p>

                       usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),<o:p></o:p>

                       buf, count, skel_write_bulk_callback, dev);<o:p></o:p>

       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;<o:p></o:p>

<o:p> </o:p>

然后urb就可以被提交给USB核心以传输到设备了:<o:p></o:p>

<o:p> </o:p>

       /* 把数据从批量OUT端口发出 */<o:p></o:p>

       retval = usb_submit_urb(urb, GFP_KERNEL);<o:p></o:p>

       if (retval) {<o:p></o:p>

              err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);<o:p></o:p>

              goto error;<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

urb被成功传输到USB设备之后,urb回调函数将被USB核心调用,在我们的例子中,我们初始化urb,使它指向skel_write_bulk_callback函数,以下就是该函数:<o:p></o:p>

<o:p> </o:p>

static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)<o:p></o:p>

{<o:p></o:p>

       struct usb_skel *dev;<o:p></o:p>

<o:p> </o:p>

       dev = (struct usb_skel *)urb->context;<o:p></o:p>

<o:p> </o:p>

       if (urb->status && <o:p></o:p>

           !(urb->status == -ENOENT || <o:p></o:p>

             urb->status == -ECONNRESET ||<o:p></o:p>

             urb->status == -ESHUTDOWN)) {<o:p></o:p>

              dbg("%s - nonzero write bulk status received: %d",<o:p></o:p>

                  __FUNCTION__, urb->status);<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

       /* 释放已分配的缓冲区 */<o:p></o:p>

       usb_buffer_free(urb->dev, urb->transfer_buffer_length, <o:p></o:p>

           

分享到:
评论

相关推荐

    Linux下关于USB Gadget驱动框架简介

    在本文中,我们将深入探讨Linux下的USB Gadget驱动框架,了解其工作原理、应用以及如何配置。 USB Gadget驱动框架是Linux内核的一部分,它为开发者提供了一种抽象的接口,以便于构建和管理USB设备功能。这个框架将...

    linux USB cdc 子类 驱动 合集

    首先,我们来深入了解一下Linux USB CDC驱动的工作原理。CDC是一种标准,允许不同的USB设备通过一个统一的接口与主机通信。它定义了多个子类,如抽象控制模型(ACM)、网络控制模型(NCM)等,以适应不同的通信需求...

    linux下的fusb302驱动源码

    此外,了解Linux设备模型和USB子系统的概念也有助于深入理解驱动的工作原理。 总之,fusb302驱动源码是实现Linux系统与FUSB302芯片通信的基础,它使得USB PD快充功能能够在Linux环境中正常工作。通过研究源码,...

    linux USB摄像头驱动

    本文将深入探讨Linux环境下USB摄像头驱动的相关知识点,特别是针对标题中提及的gspcav1-20071224驱动。 一、Linux驱动程序基础 Linux驱动程序是内核的一部分,它负责管理硬件设备,为上层应用提供统一的接口。在...

    基于Linux环境下USB设备驱动移植的研究.pdf

    【Linux USB驱动移植】在Linux环境下,针对USB设备的驱动移植是一项重要的系统开发工作,尤其在嵌入式系统和桌面系统领域。Linux操作系统以其开源、免费的特性,为开发者提供了丰富的资源和高度的灵活性。USB...

    Linux usb gadget 驱动

    ### Linux USB Gadget 驱动详解 #### 一、概述与应用场景 **Linux USB Gadget** 驱动是一种特殊的驱动程序,用于使运行Linux的设备能够作为USB从设备工作。这种驱动允许Linux设备模拟各种USB设备角色,如U盘、键盘...

    嵌入式Linux下USB摄像头驱动程序的开发

    本文将详细介绍一款基于台湾凌越TP6800视频主控芯片的USB摄像头,在嵌入式Linux环境下开发驱动程序的过程,以及一般USB设备驱动程序开发的基本流程和方法。 #### 嵌入式Linux环境及其特点 嵌入式Linux开发平台凭借...

    Linux_USB.rar_USB LINUX_linux usb_linux usb驱动_usb_usb linux

    在提供的压缩包文件中,"Linux环境下USB的原理、驱动和配置.mht"可能包含更详细的理论介绍和技术指南,而"www.pudn.com.txt"可能是下载来源或附加信息。读者可以通过阅读这些资料,进一步提升对Linux USB的理解和...

    linux中的usb驱动

    通过学习以上知识,你可以深入了解Linux USB驱动的工作原理,从而编写自己的USB设备驱动。此外,阅读Linux内核源码和参考文档,参与开源社区,也是提高技能的有效途径。在实际项目中,理解设备特性和正确使用内核...

    Linux下USB驱动程序的设计与实现

    ### Linux下USB驱动程序的设计与实现 ...通过以上步骤,我们不仅了解了USB总线的基本概念和结构,还掌握了Linux下USB驱动程序的设计原理和实现方法。这对于进一步开发复杂的应用场景或嵌入式系统来说是非常宝贵的。

    如何实现Linux下的U盘(USB Mass Storage)驱动 v0.6

    本文档详细介绍了如何在Linux环境下编写USB Mass Storage Class (MSC) 驱动程序。USB Mass Storage 设备是常见的外设之一,如U盘、移动硬盘等,它们基于通用串行总线 (USB) 进行数据传输。了解并掌握如何在Linux操作...

    Linux系统下USB设备驱动程序的开发

    本文将深入探讨Linux环境下USB设备驱动的原理、开发流程以及具体实现。 首先,理解USB设备驱动的工作原理至关重要。USB驱动分为用户空间驱动(用户模式驱动)和内核空间驱动(内核模式驱动)。内核空间驱动负责与...

    usb.rar_USB驱动_linux usb_linux usb驱动_usb_usb 驱动

    "usb.txt"文件可能是关于USB驱动开发的文本教程或代码示例,可以帮助你了解如何在Linux环境下与USB设备交互,包括如何编写内核模块、如何注册和卸载驱动、如何处理中断和批量传输等。 总之,理解并掌握USB驱动在...

    Linux ARM下的USB驱动开发.pdf

    本文介绍了嵌入式Linux下的USB驱动开发原理,并阐述了在Linux下的Z228 USB驱动程序的具体实现。文章首先介绍了USB的发展历史和特点,然后讨论了USB驱动程序的编写技术。 USB是一种新的接口标准,自1994年由Compaq、...

    嵌入式Linux下指纹采集模块USB接口驱动程序的设计实现.pdf

    在嵌入式Linux环境下,设计和实现指纹采集模块的USB接口驱动程序是一项关键的技术任务,尤其对于需要在恶劣工业环境中稳定运行的系统来说。本文详细介绍了这一过程,并着重讨论了CMOS光电式指纹采集模块的USB接口...

    嵌入式全套视频-7-(LINUX USB系统)(USB驱动程序开发).rar

    总的来说,这个压缩包提供的内容对想要深入理解Linux环境下的USB系统和驱动开发的工程师来说非常有价值。通过学习,你可以了解USB设备的工作原理,掌握如何与USB设备通信,以及如何为新的USB设备编写驱动程序。这...

    嵌入式Linux中USB摄像头驱动的研究.pdf

    本文介绍了嵌入式Linux系统中USB摄像头驱动程序的开发和应用,涵盖了USB设备驱动程序的基本原理、USB主机驱动程序的组成、USB摄像头驱动程序的实现和应用等方面的内容,为嵌入式Linux系统开发和应用提供了有价值的...

    Linux_Usb_driver.rar_USB LINUX_USB驱动 linux_linux usb_usb driver_

    学习和理解Linux下的USB驱动开发,不仅可以帮助开发者创建自定义的USB设备驱动,还能提升对Linux内核工作原理的理解,对于从事嵌入式系统、物联网(IoT)设备开发的工程师尤其重要。通过深入学习这份资料,开发者可以...

    LINUX USB键盘驱动源码

    在Linux操作系统中,USB设备的驱动程序是操作系统与硬件之间的重要桥梁,负责处理硬件的输入输出请求。...通过研究提供的源码和文档,开发者可以深入了解Linux内核的工作原理,并具备开发其他USB设备驱动的能力。

Global site tag (gtag.js) - Google Analytics