转自:http://www.west263.com

 

USB设备越来越多,而Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题。本文着力从Linux系统下设备驱动的架构,去阐述怎样去使用和配置连同怎样编制USB设备驱动。对于一般用户,能够使我们明晰Linux设备驱动方式,为更好地配置和使用USB设备提供了方便;而对于希望研发Linux系统下USB设备驱动的程式员,提供了初步学习USB驱动架构的机会。

前言

USB 是英文"Universal Serial Bus"的缩写,意为"通用串行总线"。是由Compaq(康柏)DECIBMIntelNEC、微软连同Northern Telecom(北方电讯)等公司于199411月一起提出的,主要目的就是为了解决接口标准太多的弊端。USB使用一个4针插头作为标准插头,并通过这个标准接头,采用菊花瓣形式把任何外设连接起来,他采用串行方式传输数据,现在最大数据传输率为12Mbps, 支持多数据流和多个设备并行操作,允许外设热插拔。

现在USB接口虽然只发展了2代(USB1.0/1.1USB2.0),但是USB综合了一个多平台标准的任何长处 -- 包括降低成本,增加兼容性,可连接大量的外部设备,融合先进的功能和品质。使其逐步成为PC接口标准,进入了高速发展期。

那么对于使用Linux系统,正确支持和配置常见的USB设备,就是其使用必不可少的关键一步。

USB设备越来越多,而Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题。本文着力从Linux系统下设备驱动的架构,去阐述怎样去使用和配置连同怎样编制USB设备驱动。对于一般用户,能够使我们明晰Linux设备驱动方式,为更好地配置和使用USB设备提供了方便;而对于希望研发Linux系统下USB设备驱动的程式员,提供了初步学习USB驱动架构的机会。

前言

USB 是英文"Universal Serial Bus"的缩写,意为"通用串行总线"。是由Compaq(康柏)DECIBMIntelNEC、微软连同Northern Telecom(北方电讯)等公司于199411月一起提出的,主要目的就是为了解决接口标准太多的弊端。USB使用一个4针插头作为标准插头,并通过 这个标准接头,采用菊花瓣形式把任何外设连接起来,他采用串行方式传输数据,现在最大数据传输率为12Mbps, 支持多数据流和多个设备并行操作,允许外设热插拔。

现在USB接口虽然只发展了2代(USB1.0/1.1USB2.0),但是USB综合了一个多平台标准的任何长处 -- 包括降低成本,增加兼容性,可连接大量的外部设备,融合先进的功能和品质。使其逐步成为PC接口标准,进入了高速发展期。

那么对于使用Linux系统,正确支持和配置常见的USB设备,就是其使用必不可少的关键一步。

相关技术基础

模块(驱动程式)

模块(module)是在内核空间运行的程式,实际上是一种目标对象文档,没有链接,不能单独运行,但是能够装载到系统中作为内核的一部分运行,从而能够动态扩充内核的功能。模块最主要的用处就是用来实现设备驱动程式。

Linux下对于一个硬件的驱动,能够有两种方式:直接加载到内核代码中,启动内核时就会驱动此硬件设备。另一种就是以模块方式,编译生成一个.o文档。当应用程式需要时再加载进内核空间运行。所以我们所说的一个硬件的驱动程式,通常指的就是个驱动模块。

设备文档

对于一个设备,他能够在/dev 下面存在一个对应的逻辑设备节点,这个节点以文档的形式存在,但他不是普通意义上的文档,他是设备文档,更确切的说,他是设备节点。这个节点是通过 mknod命令建立的,其中指定了主设备号和次设备号。主设备号表明了某一类设备,一般对应着确定的驱动程式;次设备号一般是区分不同属性,例如不同的使 用方法,不同的位置,不同的操作。这个设备号是从/proc/devices文档中获得的,所以一般是先有驱动程式在内核中,才有设备节点在目录中。这个 设备号(特指主设备号)的主要作用,就是声明设备所使用的驱动程式。驱动程式和设备号是一一对应的,当您打开一个设备文档时,操作系统就已知道这个设备所 对应的驱动程式。

SCSI 设备

SCSI 是有别于IDE的一个电脑标准接口。现在大部分平板式扫描仪、CD-R刻录机、MO光磁盘机等渐渐趋向使用SCSI接口,加之SCSI又能提供一个高速传 送通道,所以,接触到SCSI设备的用户会越来越多。Linux支持很多种的SCSI设备,例如:SCSI硬盘、SCSI光驱、SCSI磁带机。更重要的 是,Linux提供了IDE设备对SCSI的模拟(ide-scsi.o模块),我们通常会就把IDE光驱模拟为SCSI光驱进行访问。因为在Linux 中很多软件都只能操作SCSI光驱。例如大多数刻录软件、一些媒体播放软件。通常我们的USB存储设备,也模拟为SCSI硬盘而进行访问。

Linux硬件驱动架构

对于一个硬件,Linux 是这样来进行驱动的:首先,我们必须提供一个.o的驱动模块文档(这里我们只说明模块方式,其实内核方式是类似的)。我们要使用这个驱动程式,首先要加载 运行他(insmod *.o)。这样驱动就会根据自己的类型(字符设备类型或块设备类型,例如鼠标就是字符设备而硬盘就是块设备)向系统注册,注册成功系统会反馈一个主设备 号,这个主设备号就是系统对他的唯一标识(例如硬盘块设备在/proc/devices中显示的主设备号为3 ,我们用ls -l /dev/had看到的主设备就肯定是3)。驱动就是根据此主设备号来创建一个一般放置在/dev目录下的设备文档(mknod命令用来创建他,他必须用 主设备号这个参数)。在我们要访问此硬件时,就能够对设备文档通过openreadwrite等命令进行。而驱动就会接收到相应的read write操作而根据自己的模块中的相应函数进行了。

其中更有几个比较有关系的东西:一个是/lib /modules/2.4.XX目录,他下面就是针对当前内核版本的模块。只要您的模块依赖关系正确(能够通过depmod配置),您就能够通过 modprobe 命令加载而无需知道具体模块文档位置。 另一个是/etc/modules.conf文档,他定义了一些常用设备的别名。系统就能够在需要此设备支持时,正确寻找驱动模块。例如alias eth0 e100,就代表第一块网卡的驱动模块为e100.o。他们的关系图如下:

配置USB设备

内核中配置.

要启用 Linux USB 支持,首先进入"USB support"节并启用"Support for USB"选项(对应模块为usbcore.o)。尽管这个步骤相当直观明了,但接下来的 Linux USB 配置步骤则会让人感到糊涂。特别地,现在需要选择用于系统的正确 USB 主控制器驱动程式。选项是"EHCI" (对应模块为ehci-hcd.o)、"UHCI" (对应模块为usb-uhci.o)、"UHCI (alternate driver)""OHCI" (对应模块为usb-ohci.o)。这是许多人对 Linux USB 开始感到困惑的地方。

要理解"EHCI"及其同类是什么,首先要知道每块支持插入 USB 设备的主板或 PCI 卡都需要有 USB 主控制器芯片组。这个特别的芯片组和插入系统的 USB 设备进行相互操作,并负责处理允许 USB 设备和系统其他部分通信所必需的任何低层次细节。

Linux USB 驱动程式有三种不同的 USB 主控制器选项是因为在主板和 PCI 卡上有三种不同类型的 USB 芯片。"EHCI"驱动程式设计成为实现新的高速 USB 2.0 协议的芯片提供支持。"OHCI"驱动程式用来为非 PC 系统上的(连同带有 SiS ALi 芯片组的 PC 主板上的)USB 芯片提供支持。"UHCI"驱动程式用来为大多数其他 PC 主板(包括 Intel Via)上的 USB 实现提供支持。只需选择和希望启用的 USB 支持的类型对应的"?HCI"驱动程式即可。如有疑惑,为保险起见,能够启用"EHCI""UHCI" (两者中任选一种,他们之间没有明显的区别)和"OHCI"。( 赵明注:根据文档,EHCI已包含了UHCIOHCI,但现在就我个人的测试,单独加EHCI是不行的,通常我的做法是根据主板类型加载UHCIOHCI后,再加载EHCI这样才能够支持USB2.0设备)。

启用了"USB support"和适当的"?HCI"USB 主控制器驱动程式后,使 USB 启动并运行只需再进行几个步骤。应该启用"Preliminary USB device filesystem",然后确保启用任何特定于将和 Linux 一起使用的实际 USB 外围设备的驱动程式。例如,为了启用对 USB 游戏控制器的支持,我启用了"USB Human Interface Device (full HID) support"。我还启用了主"Input core support" 节下的"Input core support""Joystick support"

一旦用新的已启用 USB 的内核重新引导后,若/proc/bus/usb下没有相应USB设备信息,应输入以下命令将 USB 设备文档系统手动挂装到 /proc/bus/usb

 

# mount -t usbdevfs none /proc/bus/usb

 

为了在系统引导时自动挂装 USB 设备文档系统,请将下面一行添加到 /etc/fstab 中的 /proc 挂装行之后:

none /proc/bus/usb usbdevfs defaults 0 0

 

模块的配置方法.

在很多时候,我们的USB设备驱动并不包含在内核中。其实我们只要根据他所需要使用的模块,逐一加载。就能够使他启作用。

首先要确保在内核编译时以模块方式选择了相应支持。这样我们就应该能够在/lib/modules/2.4.XX目录看到相应.o文档。在加载模块时,我们只需要运行modprobe xxx.o就能够了(modprobe主要加载系统已通过depmod登记过的模块,insmod一般是针对具体.o文档进行加载)

对应USB设备下面一些模块是关键的。

usbcore.o

要支持usb所需要的最基础模块

usb-uhci.o

(已提过)

usb-ohci.o

(已提过)

uhci.o

另一个uhci驱动程式,我也不知道有什么用,一般不要加载,会死机的

ehci-hcd.o

(已提过 usb2.0

hid.o

USB人机界面设备,像鼠标呀、键盘呀都需要

usb-storage.o

USB存储设备,U盘等用到

相关模块

ide-disk.o

IDE硬盘

ide-scsi.o

IDE设备模拟SCSI接口

scsi_mod.o

SCSI支持

注意kernel config其中一项:

 

         Probe all LUNs on each SCSI device

 

最好选上,要不某些同时支持多个口的读卡器只能显示一个。若模块方式就要带参数安装或提前在/etc/modules.conf中加入以下项,来支持多个LUN

 

         add options scsi_mod max_scsi_luns=9 

 

 

sd_mod.o

SCSI硬盘

sr_mod.o

SCSI光盘

sg.o

SCSI通用支持(在某些探测U盘、SCSI探测中会用到)

常见USB设备及其配置

Linux 2.4的内核中已支持不下20种设备。他支持几乎任何的通用设备如键盘、鼠标、modem、打印机等,并不断地添加厂商新的设备象数码相机、MP3、网卡等。下面就是几个最常见设备的介绍和使用方法:

USB鼠标:

键盘和鼠标属于低速的输入设备,对于已为用户认可的PS/2 接口,USB键盘和USB鼠标似乎并没有太多更优越的地方。现在的大部分鼠标采用了PS/2接口,但是USB接口的鼠标也越来越多,两者相比,各有优势: 一般来说,USB的鼠标接口的带宽大于PS/2鼠标,也就是说在同样的时间内,USB鼠标扫描次数就要多于PS/2鼠标,这样在定位上USB鼠标就更为精 确;同时USB接口鼠标的默认采样率也比较高,达到125HZ,而PS/2接口的鼠标仅有40HZWindows 9x/Me)或是60HZWindows NT/2000)。

对于USB设备您当然必须先插入相应的USB控制器模块:usb-uhci.ousb-ohci.o

 

         modprobe usb-uhci

 

USB鼠标为了使其正常工作,您必须先插入模块usbmouse.omousedev.o

 

         modprobe usbmouse

         modprobe mousedev

 

若您把HID input layer支持和input core 支持也作为模块方式安装,那么启动hid模块和input模块也是必要的。

         modprobe hid

         modprobe input

 

USB键盘:

一般的,我们现在使用的键盘大多是PS/2 的,USB键盘还比较少见,但是下来的发展,键盘将向USB接口靠拢。使用USB键盘基本上没有太多的需要,只需在主板的BIOS设定对USB键盘的支 持,就能够在各系统中完全无障碍的使用,而且更能够真正做到在即插即用和热插拔使用,并能提供两个USB连接埠:让您能够轻易地直接将具备USB接头的装 置接在您的键盘上,而非电脑的后面。

同样您当然必须先插入相应的USB控制器模块:usb-uhci.ousb-ohci.o

 

         modprobe usb-uhci

 

然后您还必须插入键盘模块usbkbd.o,连同keybdev.o,这样usb键盘才能够正常工作。此时,运行的系统命令:

 

modprobe usbkbd

modprobe keybdev

 

同样若您把HID input layer支持和input core 支持也作为模块方式安装,那么启动hid模块和input模块也是必要的。

U盘和USB读卡器:

数码存储设备现在对我们来说已是相当普遍的了。CF卡、SD卡、Memory Stick等存储卡已遍及我们的身边,通常,他们的读卡器都是USB接口的。另外,很多MP3、数码相机也都是USB接口和电脑进行数据传递。更我们的U盘、USB硬盘,作为移动存储设备,已成为我们的必须装备。

Linux下这些设备通常都是以一种叫做usb-storage的方式进行驱动。要使用他们必须加载此模块

 

         modprobe usb-storage

 

当然,usbcore.o usb-uhci.ousb-ohci也肯定是不可缺少的。另外,若您系统中SCSI支持也是模块方式,那么下面的模块也要加载

         modprobe scsi_mod

         modprobe sd_mod

 

在加载完这些模块后,我们插入U盘或存储卡,就会发现系统中多了一个SCSI硬盘,通过正确地mount他,就能够使用了(SCSI硬盘一般为/dev/sd?,可参照文章后面的常见问题解答)。

 

         mount /dev/sda1 /mnt

 

Linux支持的其他USB设备。

MODEM--(比较常见)

网络设备

摄像头--(比较常见)例如ov511.o

联机线--能够让您的两台电脑用USB线实现网络功能。usbnet.o

显示器--(我没见过)

游戏杆

电视盒--(比较常见)

手写板--(比较常见)

扫描仪--(比较常见)

刻录机--(比较常见)

打印机--(比较常见)

注意:

上面所说的每个驱动模块,并不是都要手动加载,有很多系统会在启动或您的应用需要时自动加载的,写明这些模块,是便于您在不能够使用USB设备时,能够自行检查。只要用lsmod确保以上模块已被系统加载,您的设备就应该能够正常工作了。当然注意有些模块已以内核方式在kernel启动时存在了(这些模块文档在/lib/modules/2.4.XX中是很难找到的)。

最常遇见的USB问题

  1. USB设备的系统安装完redhat 7.3启动死机问题

USB 设备,当您刚装完redhat 7.3第一次启动时,总会死掉。主要原因是Linux在安装时探测到有usb-uhciehci-hcd两个控制器,但在启动时,加载完usb- uhci再加载ehci-hcd就会有冲突。分析认为redhat7.3系统内核在支持USB2.0标准上存在问题。在其他版本的Linux中均不存在此 问题。

解决办法:在lilogrub启动时用命令行传递参数init=/sbin/init。这样在启动后就不运行其他服务而直接启动shell。然后运行 mount -o remount,rw / 使/ 可写,init直接启动的系统默认只mount /为只读

然后vi /etc/modules.config文档

删除alias usb-controller1 ehci-hcd一行。或前面加#注释掉

然后mount -o remount,ro / 使/ 只读,避免直接关机破坏文档系统

然后就能够按Ctrl-Alt-Delete直接重启了

或许,您有更简单的办法:换USB键盘和鼠标为PS2接口,启动后修改/etc/modules.config文档。

  1. 我们已知道U盘在

Linux中会模拟为SCSI设备去访问,可怎么知道他对应那个SCSI设备呢?

方法1: 推测。通常您第一次插入一个SCSI设备,他就是sda,第二个就是sdb以此类推。您启动Linux插入一个U盘,就试试sda,换了一个就可能是 sdb。这里注意两个特例:1)您用的是联想U盘,他可能存在两个设备区(一个用于加密或启动电脑),这样就可能一次用掉两个sdasdb,换个U盘就 是sdcsdd2) 联想数码电脑中,可能已有了六合一读卡器。他同样也是USB存储设备。他会占掉一个或两个SCSI设备号。

方法2:看信息。其实,只要您提前把usb-storage.oscsi_mod.osd_mod.o模块加载(直接在kernel中也能够)了,在您插入和拔出U盘时,系统会自动打出信息如下:

 

SCSI device sda: 60928 512-byte hdwr sectors ( 31 MB )

sda: Write Protect is on

根据此信息,您就知道他在sda上了。当然,可能您的系统信息级别比较高,上述信息可能没有打出,这时候您只要tail /var/log/messages就能够看到了。

方法3:同样,cat /proc/partitions也能够看到分区信息,其中sd?就是U盘所对应的了。若根本没有sd设备,就要检查您的SCSI模块和usb-storage模块是否正确加载了。

  1. 在使用U盘或存储卡时,我该mount /dev/sda还是/dev/sda1呢?

这是个历史遗留问题。存储卡最初尺寸很小,很多厂商在使用时,就直接使用存储,不含有分区表信息。而随着存储卡尺寸的不断扩大,他也就引入了类似硬盘分区的概念。例如/dev /hda您能够分成主分区hda1hda2扩展分区hda3,然后把扩展分区hda3又分为逻辑分区hda5hda6hda7等。这样,通常的U盘 就被分成一个分区sda1,类似把硬盘整个分区分成一个主分区hda1。实际上,我们完万能够通过fdisk /dev/sda对存储卡进行完全类似硬盘的分区方式分成sda1sda2甚至逻辑分区sda5sda6。实际上,对USB硬盘现在您的确需要这样,因为他通常都是多少G的容量。而且通常,他里面就是笔记本硬盘。

一个好玩的问题。您在Linux 下用fdisk /dev/sda U盘进行了多分区,这时候到windows下,您会发现怎么找,怎么格式化,U盘都只能找到第一个分区大小尺寸,而且使用看不出任何问题。这主要是 windows驱动对U盘都只支持一个分区的缘故。您是不是能够利用他来进行一些文档的隐藏和保护?您是不是能够和某些人没玩过Linux的人开些玩笑: 您的U盘容量变小了J

现在较多的数码设备也和windows 相同,是把任何U盘容量分为一个,所以在对待U盘的时候,通常您mount的是sda1。但对于某些特别的数码设备格式化的U盘或存储卡(现在我发现的是 一款联想的支持模拟USB软盘的U盘和我的一个数码相机),您就要mount /dev/sda。因为他根本就没分区表(若mount /dev/sda1通常的效果是死掉)。其实,这些信息,只要您注意了/proc/partitions文档,都应该注意到的。

  1. 每次插入U盘,都要寻找对应设备文档名,都要手动mount,我能不能做到象windows那样插入就能够使用呢。

当然能够,但是您需要做一些工作。我这里只提供一些信息帮助您去尝试完成配置:Linux 内核提供了一种叫hotplug支持的东西,他能够让您系统在PCI设备、USB等设备插拔时做一些事情。而automount 功能能够使您的软驱、光盘等设备的分区自动挂载和自动卸载。您甚至能够在KDE桌面中创建相应的图标,方便您操作。具体配置方法就要您自己去尝试了。反正 我使用Linux已麻木了,不就是敲一行命令嘛

 

文章整理:西部数码
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐