`
javatome
  • 浏览: 844430 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Linux那些事儿之我是U盘(18)冬天来了,春天还会远吗?(二)

 
阅读更多

我们打开unusual_devs.h,随便看一下,发现里边就是很多一个个UNUSUAL_DEV,每一行就是这么一个宏,毫无疑问它对应一种设备,我们从其中挑一个来看,比如挑一个三星的吧,过去在Intel的时候,前辈们会说,若不是当初我们对自己太自信了,这个世界上又怎么有三星的生存空间.说的是上世纪末,Intel决定提高flash产品的价格,Nokia这个大客户不干了,它想找别人,一个叫三星的小公司鬼魅般的出现了,没有人相信这样一个小公司能够满足Nokia,可是,韩国人,韩国人的韧劲不仅仅是体现在足球场上.于是,世界上有了三星,Nokia养活了三星,Intel,flash这一领域失去了一个重要的客户,CEO也为此引咎辞职了.而下面这个设备,正是来自三星的一个flash产品.

711 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/

712 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,

713 "Samsung",

714 "Digimax 410",

715 US_SC_DEVICE, US_PR_DEVICE, NULL,

716 US_FL_FIX_INQUIRY),

Digimax 410,熟悉数码相机的哥们儿大概对三星的这款410万像素3倍光学变焦的产品不会陌生,不过数码相机更新得很快,这款2002年推出的相机如今当然也算是很一般了,市场上卖的话也就1500以下,不过当时刚推出的时候也是30004000元的.ok,我们来看这一行是什么意思.

UNUSUAL_DEV这个宏被定义过两次,当然,#define了之后再下一次#define之前有一个#undef,否则就重复定义了.storage_usb_ids之前,它的定义是

116 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, /

117 vendorName, productName,useProtocol, useTransport, /

118 initFunction, flags) /

119 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }

USB_DEVICE_VER的定义在include/linux/usb.h,

448 /**

449 * USB_DEVICE_VER - macro used to describe a specific usb device with a version range

450 * @vend: the 16 bit USB Vendor ID

451 * @prod: the 16 bit USB Product ID

452 * @lo: the bcdDevice_lo value

453 * @hi: the bcdDevice_hi value

454 *

455 * This macro is used to create a struct usb_device_id that matches a

456 * specific device, with a version range.

457 */

458 #define USB_DEVICE_VER(vend,prod,lo,hi) /

459 .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, .idVendor = (vend), .idProduct = (prod), .bcdDevice_lo = (lo), .bcdDevice_hi = (hi)

所以这行最终出现在storage_usb_ids中的意思就是令match_flags USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,idVendor0x0839,idProduct0x000a,bcdDevice_lo0x0001,bcdDevice_hi0x0001.

而在us_unusal_dev_list这张表之前,UNUSUAL_DEV又被定义为:

168 #undef UNUSUAL_DEV

169 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, /

170 vendor_name, product_name, use_protocol, use_transport, /

171 init_function, Flags) /

172 { /

173 .vendorName = vendor_name, /

174 .productName = product_name, /

175 .useProtocol = use_protocol, /

176 .useTransport = use_transport, /

177 .initFunction = init_function, /

178 .flags = Flags, /

179 }

Ok.这样这个宏的意思又是令vendorName"Samsung",productName"Digimax 410",useProtocolUS_SC_DEVICE, useTransportUS_PR_DEVICE,initFunctionNULL,flagUS_FL_FIX_INQUIRY.

看明白了吗?首先不去管各项的具体含义,至少我们看出来,针对同一个文件,我们使用两次定义UNUSUAL_DEV这个宏的方法,两次利用了它的不同元素,换言之,UNUSUAL_DEV这个宏本来可以设定10个参数,storage_usb_ids中需要使用其中的前4个参数,同时us_unusual_dev_list中需要使用其中的后6个参数,所以在unusual_devs.h中定义的一行起了两个作用.我们注意到不管是storage_usb_ids数组还是us_unusual_dev_list,其中都通过这么一行把unusual_devs.h文件给包含了进来.storage_usb_ids:

121 static struct usb_device_id storage_usb_ids [] = {

122

123 # include "unusual_devs.h"

124 #undef UNUSUAL_DEV

us_unusual_dev_list:

181 static struct us_unusual_dev us_unusual_dev_list[] = {

182 # include "unusual_devs.h"

183 # undef UNUSUAL_DEV

而我们之所以使用两个数组的原因是,storage_usb_ids是提供给usb core,它需要比较driverdevice从而确定设备是被这个driver所支持的,我们只需要比较四项就可以了,因为这四项已经足以确定一个设备了,厂商,产品,序列号.比较这些就够了,us_unusual_dev_list这个数组中的元素是我们接下来的代码要用的,比如它用什么协议,它有什么初始化函数,所以我们使用了两个数组.而我们需要注意的是,这两个数组中元素的顺序是一样的,所以我们从storage_usb_ids中得到的id_index用于us_unusual_dev_list也是可以的,表示的还是同一个设备.而这也就是我们刚才在get_device_info中看到的.

472 struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
473 struct usb_device_id *id = &storage_usb_ids[id_index];

这样,unusual_devid就各取所需了.下面我们将会用到这两个指针.暂且不表.

总结陈词,最后具体解释一下这行为三星这款数码相机写的语句,

1. 关于match_flags,它的值是USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION,这是一个宏,它就告诉usb core,要比较这样几个方面,idVendor,idProduct,bcdDevice_lo,bcdDevice_hi,其中idVendor和下面的vendorName是对应的,idProduct和下面的productName是对应的,业内为每家公司编一个号,这样便于管理,比如三星的编号就是0x0839,那么三星的产品中就会在其设备描述符中idVendor的烙上0x0839.而三星自己的每种产品也会有个编号,Digimax 410对应的编号就是0x000a,bcdDevice_lobcdDevice_hi共同组成一个具体设备的编号(device release number),bcd就意味着这个编号是二进制的格式.

2. vendorNameproductName不用再说了, "Samsung""Digimax 410".

3. useProtocolUS_SC_DEVICE, useTransportUS_PR_DEVICE,这种情况就说明对于这种设备,它属于什么subclass,它使用什么通信协议,得从设备描述符里边去读取,它都写在那里边了.一会我们会看到我们的代码中会如何判断这个的.

4. initFunction等于NULL,这个很有意义的,这个函数就是设备的初始化函数,一般的设备都不需要这个函数,但是有些设备它偏要标新立异,它就告诉你,要用我的设备你必须先做一些初始化,于是它提供了一个函数,initFunction当然是一个函数指针,这里如果不为NULL的话,到时候就会被调用,以后我们会看到代码中对这个指针进行了判断.如果为空不理睬,否则就会执行.比如我们看下面两处,惠普的两个设备,它就提供了一个叫做init_8200e的初始化函数,

63 UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,

64 "HP",

65 "CD-Writer+ 8200e",

66 US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),

67

68 UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,

69 "HP",

70 "CD-Writer+ CD-4e",

71 US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),

5. flag等于US_FL_FIX_INQUIRY,这个flag可以设为很多值,这个flag的存在本身就表示这个设备有些与众不同,因为一般的设备是不用这个flag,有这个flag就表明这个设备可能在某些地方需要进行特殊的处理,所以今后在代码中我们会看到突然跳出一句,判断us->flag等于某个咚咚不,如果等于,就执行一些代码,如果不等于,那就不做任何事情.这个flag的存在也使得我们可以方便处理一些设备的bug,比如正常的设备你问它吃了吗?它就回答吃了.可是不正常的设备可能就会根本不回答,或者回答北京房价真贵!于是对于这种设备,可能我们就需要一些专门的代码来对付.具体到这个US_FL_FIX_INQUIRY,这个flag这么一设置,就表明这个设备在接受到INQUIRY命令的时候会有一些异常的特征,所以以后我们会在代码里看到我们是如何处理它的.设置了这个flag的当然不只是三星的这款相机,别的设备也有可能设置的.

6. 既然明白了unusual_devs.h的作用,那么很显然的一个事情,如果一个厂家推出了一个新的设备,它有一些新的特征,而目前的设备驱动不足以完全支持它,那么厂家首先需要做的事情就是在unusual_devs.h中添加一个UNUSUAL_DEV来定义自己的设备,然后再看是否需要给内核打补丁以及如何打.因此这几年unusual_devs.h这个文件的长度也是慢慢在增长.

分享到:
评论

相关推荐

    Linux那些事儿之我是U盘

    ### Linux中的USB子系统详解——《Linux那些事儿之我是U盘》 #### 一、引言 在现代计算环境中,USB(Universal Serial Bus)已成为连接各种外围设备的标准接口之一。无论是移动存储设备如U盘,还是键盘、鼠标等输入...

    Linux那些事儿

    Linux那些事儿之我是U盘 Linux那些事儿之我是Hub Linux那些事儿之我是USB Core Linux那些事儿之我是UHCI Linux那些事儿之我是EHCI控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是...

    Linux那些事儿之我是USB(第2版)

    ### Linux那些事儿之我是USB(第2版)关键知识点概览 #### 一、书籍概述 - **核心主题**:本书主要围绕Linux内核中的USB子系统展开,深入剖析其工作原理和技术细节。 - **目标读者**:面向Linux初学者、驱动开发者...

    Linux那些事儿1-9合集

    读过《linux那些事儿之我是U盘》的人,都知道其风格,我就不多说了。 导读: linux那些事儿之我是U盘 linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制...

    linux那些事儿之我是USB.zip

    本压缩包文件"linux那些事儿之我是USB.zip"包含了深入理解Linux USB驱动及内核相关知识的九个文档,包括Block层、EHCI主机控制器、HUB、PCI、SCSI硬盘、Sysfs、UHCI、USB core以及U盘。这些文档旨在提供一个系统性的...

    LINUX\Linux那些事儿系列

    3. **Linux那些事儿之我是U盘.pdf**: USB闪存驱动器,通常称为U盘,是常见的便携式存储设备。这部分可能讲述Linux如何识别、挂载和管理U盘,包括使用ums(USB Mass Storage)驱动程序,以及如何处理文件系统的读写...

    Linux那些事儿之全集

    导读.doc Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Hub.pdf Linux那些事儿之我是USB_core.pdf Linux那些事儿之我是U盘.pdf等等 Linux那些事儿系列全在这里了

    Linux那些事儿系列.rar

    》包括《Linux那些事儿之我是Hub》、《Linux那些事儿之我是Sysfs》《Linux那些事儿之我是UHCI》、《Linux那些事儿之我是USB core》、《Linux那些事儿之我是U盘》,令人叹为观止的一个linux系列书籍。只能说,江山代...

    linux 那些事儿全集

    “Linux那些事儿之我是U盘.pdf”将关注通用串行总线(USB)闪存驱动器。这部分会解释Linux如何识别和处理USB闪存设备,包括文件系统的挂载和数据交换过程。 “Linux那些事儿之我是USB Core.pdf”涉及Linux内核的USB...

    linux的那些事儿全集

    Linux那些事儿之我是Block层 Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Hub Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Sysfs ...Linux那些事儿之我是U盘

    linux那些事儿之我是U盘

    ### Linux与USB存储设备——《Linux那些事儿之我是U盘》知识点提炼 #### 引言 本文基于一篇幽默且深入的教程《Linux那些事儿之我是U盘》,该文章通过作者的亲身经历和深入浅出的讲解,介绍了Linux操作系统中USB存储...

Global site tag (gtag.js) - Google Analytics