怎样写linux下的USB设备驱动程序
- 格式:doc
- 大小:93.00 KB
- 文档页数:11
《开发板——Linux配置USBRNDIS》 ⼀台Linux即可充当USB的device端,也可以由另⼀台Linux来充当USB的Host端。
在与以太⽹不同,在USB⽹络⾥各终端不是对等的,即USB Host端和USB Device端的所需要软件和硬件接⼝不⼀样。
Linux充当USB Host Linux开发板当USB Host时,需要安装安装 rndis_host.ko 这个驱动。
│ Prompt: Host for RNDIS and ActiveSync devices (EXPERIMENTAL) ││ Defined at drivers/net/usb/Kconfig:234││ Depends on: NETDEVICES && USB && NET && USB_USBNET && EXPERIMENTAL ││ Location: ││ -> Device Drivers ││ -> Network device support (NETDEVICES [=y]) ││ -> USB Network Adapters ││ -> Multi-purpose USB Networking Framework (USB_USBNET [=m]) │Linux充当USB Device Linux开发板需要安装USB Gadget驱动g_ether.ko 来进⾏通讯。
Symbol: USB_ETH_RNDIS [=n] ││ Prompt: RNDIS support ││ Defined at drivers/usb/gadget/Kconfig:609││ Depends on: && USB_ETH ││ Location: ││ -> Device Drivers ││ -> USB support (USB_SUPPORT [=y]) ││ -> USB Gadget Support (USB_GADGET [=y]) ││ -> USB Gadget Drivers ( [=m]) ││ -> Ethernet Gadget (with CDC Ethernet support) (USB_ETH [=n │ 最终配置选项就是:CONFIG_USB_ETH=y和CONFIG_USB_ETH_RNDIS=y。
USB驱动移植教程一.USB驱动框架在Linux系统中,提供了主机侧和设备侧视角的USB驱动框架,这里,仅仅讲解主机侧角度看到的USB驱动框架。
从主机侧的角度而言,需要编写的USB驱动程序包括主机控制器驱动和设备驱动两类。
USB主机控制器驱动程序控制插入其中的USB设备,而USB设备驱动程序控制该设备如何作为设备与主机通信。
在USB主机控制器驱动和USB设备驱动之间还有一层叫USB核心层。
USB核心负责USB驱动管理和协议处理工作,它通过定义一些数据结构、宏和功能函数,向上为USB设备驱动提供编程接口,向下为USB主机控制器驱动提供编程接口;通过全局变量维护整个系统的USB设备信息,完成设备热插拔控制、总线数据传输控制等。
说了那么多,无图无真相啊~~Linux USB主机侧驱动总体框架二.USB驱动移植步骤1.S5PV210主机控制驱动的移植USB主机控制器有3种规范,UHCI(Universal Host Controller Interface),这种规范主要是Intel、Via芯片公司提供支持PC主板的;OHCI(Open Host Controller Interface),这种规范是微软提出来的,主要应用在非PC系统上的嵌入式领域上的USB芯片;EHCI(Enhanced Host Controller Interface),这种后来为提高USB速度而提出的规范,它支持最高速度为480Mbps。
在《S5PV210_UM_REV1.1》手册上搜索OHCI关键词,会发现下面一段话这表明S5PV210这款CPU支持一个USB主机接口,同时支持EHCI和OHCI这两种规范,支持USB1.1和USB2.0规范,支持最高的外设传输速率为480Mbps。
注意了,它并不支持USB3.0规范的USB设备,所以做测试的时候,千万不要拿USB3.0规范的USB设备去测试。
2.1移植ohci-s5p驱动打开内核目录:driversusbhost,发现Linux系统提供了大量的主机控制器驱动,找遍所有平台,都没有找到ohci-s5p.c源码。
linux libusb热拔插代码-概述说明以及解释1.引言1.1 概述概述部分旨在介绍本篇文章的主题和背景,为读者提供一个全面而简洁的理解。
本文将重点讨论Linux下libusb热拔插的代码实现,为读者提供有关如何在Linux系统中使用libusb库进行热插拔设备的操作的指导。
在这篇文章中,我们将深入探讨libusb的基本概念、原理和使用方法,以及如何使用libusb实现在Linux环境下热插拔设备的连接和断开。
热插拔技术是现代计算机技术中一个非常重要的概念,它允许用户在系统运行时插入和拔出硬件设备,而无需重新启动计算机。
这种灵活性和方便性使得热插拔回应了不断增长的计算需求和多设备管理的需求,使得我们不再受限于固定硬件的配置。
因此,了解和学习如何在Linux系统中使用libusb库实现热插拔设备的连接和断开对于应用开发人员和系统管理员来说是非常重要的。
在本文的后续部分,我们将首先对libusb进行简要介绍,包括其定义、核心功能和主要用途。
然后,我们将重点介绍热插拔技术的背景和原理,解释为什么热插拔设备的连接和断开是一个重要的技术问题,并探讨其对现代计算机系统的影响。
此外,我们将深入研究如何使用libusb库在Linux系统中实现热插拔设备的连接和断开。
我们将详细讨论libusb的主要API和函数,介绍如何编写代码来检测新设备的插入和拔出事件,并动态地与这些设备进行通信。
我们还将解释如何处理设备插入和拔出事件的错误情况,并提供一些实用的编程技巧和建议。
最后,在本文的结论部分,我们将简要总结我们讨论的主要观点和结果,并探讨libusb热插拔代码在未来的发展和应用前景。
我们将强调热插拔技术在计算机系统中的重要性,并指出可能的改进和扩展领域,鼓励读者进一步探索和研究。
通过对libusb热拔插代码的深入讨论和实践,本文旨在帮助读者更好地理解和应用Linux系统中的热插拔技术,为他们在开发和管理计算机系统时提供有价值的指导和建议。
linux usb设备节点产生过程在Linux操作系统中,USB设备节点的生成过程是通过USB核心驱动程序来完成的。
当插入USB设备后,操作系统会检测到新的USB设备并自动加载相应的驱动程序。
下面将详细介绍USB设备节点生成的过程。
1.检测USB设备:当USB设备插入计算机的USB接口时,USB控制器会向主处理器发送中断信号,通知操作系统有新的设备连接。
操作系统通过USB核心驱动程序监听该中断信号,并开始检测新连接的设备。
2.加载USB驱动程序:操作系统会检查存在的USB驱动程序库,并根据USB设备的硬件标识信息(Vendor ID和Product ID)来匹配合适的驱动程序。
如果找到了匹配的驱动程序,操作系统就会加载该驱动程序,以便对USB 设备进行操作。
3.创建设备节点:一旦合适的USB驱动程序被加载,操作系统就会为该USB设备创建设备节点。
设备节点是Linux中与设备交互的接口,通过该节点可以对设备进行读写操作。
每个USB设备在系统中都有一个唯一的设备节点。
4.创建udev规则:udev是Linux内核中的一个设备管理机制,它负责监听系统中设备的插入、移除和属性变化等事件,并根据预定义的规则进行相应的处理。
当系统检测到新的设备时,udev会根据配置文件中的规则来创建设备节点。
这些规则指定了如何命名设备节点、设置设备权限等。
5.设备节点命名:udev会根据其配置文件中的规则为USB设备节点命名。
设备节点的命名通常遵循一定的规则,例如使用/dev/usb开头或者以设备类型为前缀。
这样可以使得设备节点易于识别和管理。
6.设置设备权限:udev还负责为USB设备节点设置权限。
这些权限规定了哪些用户或组可以对设备进行读写操作,以确保系统的安全性。
默认情况下,udev会根据规则设置设备节点的权限,但用户也可以根据需要自行配置设备的权限。
通过以上步骤,USB设备节点在Linux系统中成功生成。
一旦设备节点生成,用户就可以使用相应的命令和API对USB设备进行访问和操作。
⼀⽂搞懂USB设备端驱动框架【转】hello ⼤家好,今天带领⼤家学习⼀下USB 设备端驱动内核版本:4.4.941. Linux USB ⼦系统在介绍设备端驱动前,我们先来看看 Linux USB⼦系统。
这⾥的⼦系统是相对于整个Linux kernel 来说的,⽽⾮单⼀设备。
从整体概括了USB主机端和设备端的通信框架。
Linux kernel 中早已集成了较为完善的USB协议栈,由于其规模庞⼤,包含多个类别的设备驱动,所以Linux系统中的USB协议栈也被称为USB⼦系统。
1.1 主机端主机端,简化抽象三层:各种类设备驱动:mass sotrage, CDC, HID等USB 设备驱动:USB 核⼼处理主机控制器驱动:不同的USB主机控制器(OHCI/EHCI/UHCI),抽象为HDC。
1.2 设备端设备端,也抽象为三层:设备功能驱动:mass sotage , CDC, HID 等,对应主机端的类设备驱动Gadget 设备驱动:中间层,向下直接和UDC通信,建⽴链接;向上提供通⽤接⼝,屏蔽USB请求以及传输细节。
设备控制器驱动:UDC驱动,直接处理USB设备控制器。
2. USB 设备驱动2.1 gadget 驱动框架拆解1我们将USB 设备端驱动拆解⼀下,其驱动框架如下:上⽂提到,Gadget 设备层起着⾄关重要的作⽤。
为上层提供通⽤的驱动框架,与下层UDC通过Gadget Interface 建⽴联系。
其中Compsite Framwork 提供了⼀个通⽤的usb_gadget_driver 模板,包括各种⽅法供上层Function driver 使⽤。
(driver/usb/gadget/compsite.c)从上图我们可以看出,对于USB设备端驱动开发⽽⾔,更多的关注的是Function driver这层。
USB 控制相关过程,内核提供了⼀个中间层帮我们屏蔽掉了。
2.2 gadget 驱动框架拆解2内核版本:Linux Kernel 4.4.94,我们以这个版本进⾏拆解分析4.x 的内核相对于3.x的内核在gadget 驱动上分解的更加完善,显得⽬录结构,层次分明,分⼯合理,更便于理解。
如何在Linux下安裝PL-2303 USB driver※ 安裝前請注意:在安裝Linux Driver時需先安裝下列Library:(1) / usr / bin / wish/ usr / bin / mktemp/ usr / bin / libtcl8.3.so/ usr / bin / libtck8.3.so以及tcl / tk 等相關 library(2) Linux Kerrd RedHat 9.0 verson 2.4.20-8RedHat 9.0 X window verson 3.0一、 要安裝PL-2303須先安裝onetouch-1.2 driver,onetouch-1.2的安裝步驟請參考該份安裝文件。
二、須以root身份登入,並在目錄root底下建立一個存放pl2303.zip此驅動程式的資料夾,可將其命名為pl2303。
[root@localhost root]# mkdir pl2303 <-------此以pl2303為例三、將pl2303.zip拷貝到pl2303資料夾內,此以原pl2303.zip存放於軟碟片中為例:[root@localhost root]# mount /dev/fd0 /mnt/floppy <------掛載fd0(數字0)軟碟機為floppy目錄[root@localhost root]# cd /mnt/floppy <--------先切換到軟式磁碟機[root@localhost floppy]# cp pl2303.zip /root/pl2303四、進入pl2303資料夾,將pl2303.zip解壓縮:[root@localhost pl2303]# unzip pl2303.zip <-------會產生一名為pl2303的資料夾五、使用Vim文字編輯器修改”Makefile”這個檔案:[root@localhost pl2303]# vi MakefileP.S. Vim預設為Normal mode,無法編輯,故須按” I ”鍵以進入Insert mode,方可編輯。
libusb的使⽤教程和例⼦驱动开发向来是内核开发中⼯作量最多的⼀块,随着USB设备的普及,⼤量的USB设备的驱动开发也成为驱动开发者⼿头上做的最多的事情。
本⽂主要介绍 Linux平台下基于libusb的驱动开发,希望能够给从事Linux驱动开发的朋友带来些帮助,更希望能够给其他平台上的⽆驱设计带来些帮助。
⽂章是我在⼯作中使⽤libusb的⼀些总结,难免有错误,如有不当的地⽅,还请指正。
Linux 平台上的usb驱动开发,主要有内核驱动的开发和基于libusb的⽆驱设计。
对于内核驱动的⼤部分设备,诸如带usb接⼝的hid设备,linux本⾝已经⾃带了相关的驱动,我们只要操作设备⽂件便可以完成对设备⼤部分的操作,⽽另外⼀些设备,诸如⾃⼰设计的硬件产品,这些驱动就需要我们驱动⼯程师开发出相关的驱动了。
内核驱动有它的优点,然⽽内核驱动在某些情况下会遇到如下的⼀些问题:1 当使⽤我们产品的客户有2.4内核的平台,同时也有2.6内核的平台,我们要设计的驱动是要兼容两个平台的,就连makefile 我们都要写两个。
2 当我们要把linux移植到嵌⼊平台上,你会发现原先linux⾃带的驱动移过去还挺⼤的,我的内核当然是越⼩越好拉,这样有必要么。
这还不是最郁闷的地⽅,如果嵌⼊平台是客户的,客户要购买你的产品,你突然发现客户设备⾥的系统和你的环境不⼀样,它没有你要的驱动了,你的程序运⾏不了,你会先想:“没关系,我写个内核驱动加载⼀下不就⾏了“。
却发现客户连insmod加载模块的⼯具都没移植,那时你就看看⽼天,说声我怎么那么倒霉啊,客户可不想你动他花了n时间移植的内核哦3 花了些功夫写了个新产品的驱动,挺有成就感啊,代码质量也是相当的有⽔准啊。
正当你沉醉在你的代码中时,客服不断的邮件来了,“客户需要2.6.5内核的驱动,config⽂件我已经发你了” “客户需要双核的 2.6.18-smp 的驱动” “客户的平台是⾃⼰定制的是2.6.12-xxx “ 你恨不得把驱动的源代码给客户,这样省得编译了。
怎样写linux下的USB设备驱动程序 发布时间:2007年11月19日 引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题;本文的目地是使大家了解怎样编制USB设备驱动,为更好地配置和使用USB设备提供方便;对于希望开发Linux系统下USB设备驱动的人员,也可作为进一步学习USB驱动的大体架构进而编写出特殊USB设备的驱动程序。
USB基础知识 USB是英文Universal Serial Bus的缩写,意为通用串行总线。USB最初是为了替代许多不同的低速总线(包括并行、串行和键盘连接)而设计的,它以单一类型的总线连接各种不同的类型的设备。USB的发展已经超越了这些低速的连接方式,它现在可以支持几乎所有可以连接到PC上的设备。最新的USB规范修订了理论上高达480Mbps的高速连接。Linux内核支持两种主要类型的USB驱动程序:宿主系统上的驱动程序和设备上的驱动程序,从宿主的观点来看(一个普通的宿主也就是一个PC机),宿主系统的USB设备驱动程序控制插入其中的USB设备,而USB设备的驱动程序控制该设备如何作为一个USB设备和主机通信。本文将详细介绍运行于PC机上的USB系统是如何运作的。并同时用USB驱动程序的框架程序当例子作详细的说明,我们在此文中不讨论USB器件的驱动程序。
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文件(在2.4以下内核中是用.o作模块文件,我们以2.6的内核为准,以下同)。当应用程序需要时再加载到内核空间运行。所以我们所说的一个硬件的驱动程序,通常指的就是一个驱动模块。 设备文件:对于一个设备,它可以在/dev下面存在一个对应的逻辑设备节点,这个节点以文件的形式存在,但它不是普通意义上的文件,它是设备文件,更确切的说,它是设备节点。这个节点是通过mknod命令建立的,其中指定了主设备号和次设备号。主设备号表明了某一类设备,一般对应着确定的驱动程序;次设 备号一般是区分不同属性,例如不同的使用方法,不同的位置,不同的操作。这个设备号是从/proc/devices文件中获得的,所以一般是先有驱动程序在内核中,才有设备节点在目录中。这个设备号(特指主设备号)的主要作用,就是声明设备所使用的驱动程序。驱动程序和设备号是一一对应的,当你打开一个设备文件时,操作系统就已经知道这个设备所对应的驱动程序。对于一个硬件,Linux是这样来进行驱动的:首先,我们必须提供一个.ko的驱动模块文件。我们要使用这个驱动程序,首先要加载它,我们可以用insmod xxx.ko,这样驱动就会根据自己的类型(字符设备类型或块设备类型,例如鼠标就是字符设备而硬盘就是块设备)向系统注册,注册成功系统会反馈一个主设备号,这个主设备号就是系统对它的唯一标识。驱动就是根据此主设备号来创建一个一般放置在/dev目录下的设备文件。在我们要访问此硬件时,就可以对设备文件通过open、read、write、close等命令进行。而驱动就会接收到相应的read、write操作而根据自己的模块中的相应函数进行操作了。
USB驱动程序实践 了解了上述理论后,我们就可以动手写驱动程序,如果你基本功好,而且写过linux下的硬件驱动,USB的硬件驱动和pci_driver很类似,那么写USB的驱动就比较简单了,如果你只是大体了解了linux的硬件驱动,那也不要紧,因为在linux的内核源码中有一个框架程序可以拿来借用一下,这个框架程序在/usr/src/~(你的内核版本,以下同)/drivers/usb下,文件名为usb-skeleton.c。写一个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, }; struct module *owner :指向该驱动程序的模块所有者的指针。USB核心使用它来正确地对该USB驱动程序进行引用计数,使它不会在不合适的时刻被卸载掉,这个变量应该被设置为THIS_MODULE宏。 const char *name:指向驱动程序名字的指针,在内核的所有USB驱动程序中它必须是唯一的,通常被设置为和驱动程序模块名相同的名字。 int (*probe) (struct usb_interface *intf,const struct usb_device_id *id):这个是指向USB驱动程序中的探测函数的指针。当USB核心认为它有一个接口(usb_interface)可以由该驱动程序处理时,这个函数被调用。 void (disconnect)(struct usb_interface *intf):指向USB驱动程序中的断开函数的指针,当一个USB接口(usb_interface)被从系统中移除或者驱动程序正在从USB核心中卸载时,USB核心将调用这个函数。 const struct usb_device_id *id_table:指向ID设备表的指针,这个表包含了一列该驱动程序可以支持的USB设备,如果没有设置这个变量,USB驱动程序中的探测回调函数就不会被调用。 在这个结构体中还有其它的几个回调函数不是很常用,这里就不一一说明了。以struct usb_driver 指针为参数的usb_register_driver函数调用把struct usb_driver注册到USB核心。一般是在USB驱动程序的模块初始化代码中完成这个工作的: static int __init usb_skel_init(void) { int result;
/* 驱动程序注册到USB子系统中*/ result = usb_register(&skel_driver); if (result) err("usb_register failed. Error number %d", result);
return result; } 当USB驱动程序将要被卸开时,需要把struct usb_driver从内核中注销。通过调用usb_deregister_driver来完成这个工作,当调用发生时,当前绑定到该驱动程序上的任何USB接口都被断开,断开函数将被调用: static void __exit usb_skel_exit(void) { /* 从子系统注销驱动程序 */ usb_deregister(&skel_driver); } 探测和断开:当一个设备被安装而USB核心认为该驱动程序应该处理时,探测函数被调用,探测函数检查传递给它的设备信息,确定驱动程序是否真的适合该设备。当驱动程序因为某种原因不应该控制设备时,断开函数被调用,它可以做一些清理工作。探测回调函数中,USB驱动程序初始化任何可能用于控制USB设备的局部结构体,它还把所需的任何设备相关信息保存到一个局部结构体中,下面是探测函数的部分源