结束了get_device_info,我们继续沿着storage_probe一步一步走下去.为了保持原汁原味,我们贴代码的原则是一个函数的每一行都贴出来.get_device_info是962行,我们已经贴过,所以下面从963行开始了.
963
964 #ifdef CONFIG_USB_STORAGE_SDDR09
965 if (us->protocol == US_PR_EUSB_SDDR09 ||
966 us->protocol == US_PR_DPCM_USB) {
967 /* set the configuration -- STALL is an acceptable response here */
968 if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
969 US_DEBUGP("active config #%d != 1 ??/n", us->pusb_dev
970 ->actconfig->desc.bConfigurationValue);
971 goto BadDevice;
972 }
973 result = usb_reset_configuration(us->pusb_dev);
974
975 US_DEBUGP("Result of usb_reset_configuration is %d/n", result);
976 if (result == -EPIPE) {
977 US_DEBUGP("-- stall on control interface/n");
978 } else if (result != 0) {
979 /* it's not a stall, but another error -- time to bail */
980 US_DEBUGP("-- Unknown error. Rejecting device/n");
981 goto BadDevice;
982 }
983 }
984 #endif
看到这段代码,我笑了.因为#ifdef CONFIG_USB_STORAGE_SDDR09说明这段代码跟我们无关.关于这些编译选项我们前面已然提过,第六感告诉我们这个选项是针对某种特殊产品的,对于这种特殊的产品,它在某些方面有它自己的要求,所以它会有它特殊的代码.具体到这个选项,我们看一下drivers/usb/storage/Kconfig文件,这个文件里边介绍了该目录下每一个编译选项的作用.
99 config USB_STORAGE_SDDR09
100 bool "SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)"
101 depends on USB_STORAGE && EXPERIMENTAL
102 help
103 Say Y here to include additional code to support the Sandisk SDDR-09
104 SmartMedia reader in the USB Mass Storage driver.
105 Also works for the Microtech Zio! SmartMedia reader.
可以看到,如果要支持Sandisk SDDR-09 SmartMedia的读卡器,那你就打开这个编译选项吧.Sandisk是公司名,玩数码的人对这家公司不会陌生,中文名叫晟碟,这是一家全球最大的闪存数据存储产品供应商.而SmartMedia(简称SM)卡通常用于数码相机中,也曾一度被用于MP3中,它也是一种flash memory存储卡.不过如今市面上很少有SM卡了,因为其兼容性不好.眼下用得比较多的应该是CF卡(Compact Flash)了.而读卡器就是用来把卡里边的数据读出来,使用USB接口,从原理上来看和U盘也是差不多. (顺便介绍一下,U盘和存储卡的区别吧,我们所讲的U盘,就是可以直接读写的存储器,而存储卡需要外部设备才能进行访问,如手机的闪存卡,数码相机的闪存卡等就只是一张卡,电脑不能直接对其进行访问,这就需要一种叫"读卡器"的外部设备进行识别,存储卡有多种,如XD、CF、SD、SM等等,有些读卡器具有"多合一"的功能,可以对不同的闪存卡进行读写.而我们这段代码里以及接下来的代码中每一个条件编译开关显然对应的是一种读卡器.她们属于不同的厂商的不同的产品.)
继续,这就是我们前面提到过的三个函数.get_transport,get_protocol,get_pipes.一旦结束了这三个函数,我们就将进入本故事的高潮部分.而在这之前,我们只能一个一个来看.好在这几个函数虽然不短,但是真正有用的信息只有一点点,所以可以很快的看完.
985
986 /* Get the transport, protocol, and pipe settings */
987 result = get_transport(us);
988 if (result)
989 goto BadDevice;
990 result = get_protocol(us);
991 if (result)
992 goto BadDevice;
993 result = get_pipes(us);
994 if (result)
995 goto BadDevice;
第一个,get_transport(us),
549 /* Get the transport settings */
550 static int get_transport(struct us_data *us)
551 {
552 switch (us->protocol) {
553 case US_PR_CB:
554 us->transport_name = "Control/Bulk";
555 us->transport = usb_stor_CB_transport;
556 us->transport_reset = usb_stor_CB_reset;
557 us->max_lun = 7;
558 break;
559
560 case US_PR_CBI:
561 us->transport_name = "Control/Bulk/Interrupt";
562 us->transport = usb_stor_CBI_transport;
563 us->transport_reset = usb_stor_CB_reset;
564 us->max_lun = 7;
565 break;
566
567 case US_PR_BULK:
568 us->transport_name = "Bulk";
569 us->transport = usb_stor_Bulk_transport;
570 us->transport_reset = usb_stor_Bulk_reset;
571 break;
572
573 #ifdef CONFIG_USB_STORAGE_HP8200e
574 case US_PR_SCM_ATAPI:
575 us->transport_name = "SCM/ATAPI";
576 us->transport = hp8200e_transport;
577 us->transport_reset = usb_stor_CB_reset;
578 us->max_lun = 1;
579 break;
580 #endif
581
582 #ifdef CONFIG_USB_STORAGE_SDDR09
583 case US_PR_EUSB_SDDR09:
584 us->transport_name = "EUSB/SDDR09";
585 us->transport = sddr09_transport;
586 us->transport_reset = usb_stor_CB_reset;
587 us->max_lun = 0;
588 break;
589 #endif
590
591 #ifdef CONFIG_USB_STORAGE_SDDR55
592 case US_PR_SDDR55:
593 us->transport_name = "SDDR55";
594 us->transport = sddr55_transport;
595 us->transport_reset = sddr55_reset;
596 us->max_lun = 0;
597 break;
598 #endif
599
600 #ifdef CONFIG_USB_STORAGE_DPCM
601 case US_PR_DPCM_USB:
602 us->transport_name = "Control/Bulk-EUSB/SDDR09";
603 us->transport = dpcm_transport;
604 us->transport_reset = usb_stor_CB_reset;
605 us->max_lun = 1;
606 break;
607 #endif
608
609 #ifdef CONFIG_USB_STORAGE_FREECOM
610 case US_PR_FREECOM:
611 us->transport_name = "Freecom";
612 us->transport = freecom_transport;
613 us->transport_reset = usb_stor_freecom_reset;
614 us->max_lun = 0;
615 break;
616 #endif
617
618 #ifdef CONFIG_USB_STORAGE_DATAFAB
619 case US_PR_DATAFAB:
620 us->transport_name = "Datafab Bulk-Only";
621 us->transport = datafab_transport;
622 us->transport_reset = usb_stor_Bulk_reset;
623 us->max_lun = 1;
624 break;
625 #endif
626
627 #ifdef CONFIG_USB_STORAGE_JUMPSHOT
628 case US_PR_JUMPSHOT:
629 us->transport_name = "Lexar Jumpshot Control/Bulk";
630 us->transport = jumpshot_transport;
631 us->transport_reset = usb_stor_Bulk_reset;
632 us->max_lun = 1;
633 break;
634 #endif
635
636 default:
637 return -EIO;
638 }
639 US_DEBUGP("Transport: %s/n", us->transport_name);
640
641 /* fix for single-lun devices */
642 if (us->flags & US_FL_SINGLE_LUN)
643 us->max_lun = 0;
644 return 0;
645 }
咋一看,这么长一段,用长沙话讲,这叫非洲老头子跳高—吓(黑)老子一跳.(长沙话”黑”和”吓”一个音)不过明眼人一看,就知道了,主要就是一个switch,选择语句,语法上来说很简单,谭浩强大哥的书里边介绍的很清楚.所以我们看懂这段代码不难,只是,我想说的是,虽然这里做出一个选择不难,但是不同选择就意味着后来整个故事会有千差万别的结局,当鸟儿选择在两翼上系上黄金,就意味着它放弃展翅高飞;选择云天搏击,就意味着放弃身外的负累.所以,此处,我们需要仔细的看清楚我们究竟选择了怎样一条路.很显然,前面我们已经说过,对于U盘,spec规定了,它就属于Bulk-only的传输方式,即它的us->protocol就是US_PR_BULK.这是我们刚刚在get_device_info中确定下来的.于是,在整个switch段落中,我们所执行的只是US_PR_BULK这一段,即,
us的transport_name被赋值为”Bulk”,transport被赋值为usb_stor_Bulk_transport,transport_reset被赋值为usb_stor_Bulk_reset.其中我们最需要记住的是,us的成员transport和transport_reset是两个函数指针.程序员们把这个称作钩子.这两个赋值我们需要牢记,日后我们定会用到它们的,因为这正是我们真正的数据传输的时候调用的冬冬.关于usb_stor_Bulk_*的这两个函数,咱们到时候调用了再来看.现在只需知道,日后我们一定会回过来看这个赋值的.
573行到634行,不用多说了,这里就全是与各种特定产品相关的一些编译开关,它们有些自己定义一些传输函数,有些则共用那些通用的函数.
641行,判断us->flags,还记得我们在讲unusual_devs.h文件的时候说的那个flags吧,这里第一次用上了.有些设备设置了US_FL_SINGLE_LUN这么一个flag,就表明它是只有一个LUN的.像这样的设备挺多的,随便从unusual_devs.h中抓一个出来:
338 UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
339 "Sony",
340 "Memorystick MSAC-US1",
341 US_SC_DEVICE, US_PR_DEVICE, NULL,
342 US_FL_SINGLE_LUN ),
比如这个Sony的Memorystick.中文名叫记忆棒,大小就跟箭牌口香糖似的,也是一种存储芯片,是Sony公司推出的,广泛用于Sony的各种数码产品中.比如数码相机,数码摄影机.
有人问了,啥是LUN啊?logical unit number.通常在谈到scsi设备的时候不可避免的要说起LUN.关于LUN,曾几何时,一位来自Novell(SUSE)的参与开发Linux内核中usb子系统的工程师这样对我说,一个lun就是一个device中的一个drive.换言之,usb中引入lun的目的在于,举例来说,有些读卡器可以有多个插槽,比如就是两个,其中一个支持CF卡,另一个支持SD卡,那么这种情况要区分这两个插槽里的冬冬,就得引入lun这么一个词.这叫逻辑单元.很显然,像U盘这样简单的设备其LUN必然是一个.有时候,人们常把U盘中一个分区当作一个LUN,这样说可能对小学三年级以下的朋友是可以接受的,但是作为一个成年人,不应该这么理解.
知道了LUN以后,自然就可以知道US_FL_SINGLE_LUN是干嘛了,这个flag的意义很明显,直截了当的告诉你,我这个设备只有一个LUN,它不支持多个LUN.而max_lun又是什么意思?us中的成员max_lun等于一个设备所支持的最大的lun号.即如果一个设备支持四个LUNs,那么这四个LUN的编号就是0,1,2,3,而max_lun就是3.如果一个设备不用支持多个LUN,那么它的max_lun就是0.所以这里max_lun就是设为了0.
另外一个需要注意的地方是,比较一下各个case语句,发现, US_PR_BULK和别的case不一样,别的case下面都设置了us->max_lun,而对应于Bulk-Only协议的这个case,它没有设置us->max_lun,这是为何?别急,后来我们会专门有一个函数去读取这个值的,之所以不设,是因为这个值由设备说了算,必须向设备查询,这是Bulk-Only协议规定的.所以我们之后会遇见usb_stor_Bulk_max_lun()函数,它将负责获取这个max lun.而我依然要声明一次,这个函数对我们U盘是没啥意义的,咱们这个值肯定是0.
至此,get_transport()也结束了,和get_device_info一样.我们目前所看到的这些函数都不得不面对现实,对它们来说,凋谢是最终的结果,盛开只是一个过程...而对我们来说,要到达终点,那么和这些函数狭路相逢,终不能幸免.然而,不管这部分代码有多么重要,也不过是我们整个长途旅程中,来去匆匆的转机站,无论停留多久,始终要离去坐另一班机.
分享到:
相关推荐
- **冬天来了,春天还会远吗? (一至五)**:这一系列章节似乎探讨了面对挑战时的积极态度。 - **通往春天的管道**:可能涉及到了数据传输的原理和技术细节。 - **传说中的URB**:URB即USB Request Block,详细介绍了...
刘嘉怡.中期检查.doc
内容概要:本文详细介绍了如何使用COMSOL Multiphysics进行热电效应仿真的全过程。首先解释了热电效应的基本概念及其应用场景,如手机充电发烫、吹风机温度升高等。接着,通过具体实例展示了如何在COMSOL中建立热电模型,包括选择合适的物理场(焦耳热和热电效应)、设定材料属性(电导率、导热系数、塞贝克系数)、绘制几何形状以及设置边界条件。文中还提供了详细的MATLAB代码片段用于自动化建模流程,涵盖求解器配置、网格划分、后处理等方面的技术细节。此外,作者分享了一些常见问题的解决方案,如求解器不收敛、网格畸变等。 适合人群:对热电效应感兴趣的科研人员、工程技术人员及高校学生,尤其适用于有一定COMSOL和MATLAB基础的学习者。 使用场景及目标:帮助读者掌握热电效应的基本原理和COMSOL仿真技能,能够独立完成从模型构建到结果分析的完整流程。目标是提高热电转换系统的效率,优化设计参数,探索新材料的应用潜力。 其他说明:文章不仅提供了理论指导,还包括大量实战经验和技术技巧,有助于解决实际建模过程中遇到的问题。
内容概要:本文深入探讨了汽车内外饰模具设计的关键要素,涵盖分型面设计、斜顶和滑块的应用、模架选择以及顶出系统的配置。针对每个部分,不仅提供了理论指导,还辅以Python、MATLAB等编程语言的实际代码示例,帮助理解和实施具体设计方案。例如,分型面设计强调了如何根据产品结构和外观要求确定最佳分型面位置;斜顶和滑块部分讨论了不同类型及其应用场景;模架和顶出系统则关注于结构稳定性和顶出效果的优化。 适合人群:从事汽车模具设计的专业人士,尤其是希望深入了解内外饰模具设计细节的新手设计师和技术人员。 使用场景及目标:适用于汽车内外饰模具设计项目,旨在提高模具设计的精度和效率,减少试错成本,确保产品质量。通过学习本文提供的技术和实践经验,能够更好地应对实际工作中遇到的各种挑战。 其他说明:文中提到的代码示例和经验公式均来源于实际工程案例,具有较高的参考价值。同时,作者还分享了许多宝贵的行业经验和技巧,有助于读者快速掌握模具设计的核心技能。
python3.10以上 可安装pyside6(类似pyqt),具体安装操作步骤
内容概要:DeepSeek AI是由杭州深度求索人工智能基础技术研究有限公司于2025年1月20日发布的深度探索AI技术。它具有多模态能力、多语言支持、长上下文理解、领域垂直优化、开源特性等多项技术突破,支
IIS配置phpweb服务器所需VC_redist.x64.rar
云南移动5G-A网业战略发展探讨 -创新领航,千帆竞发,共同迈入5G-A新时代.pptx
本文描述了如何使用C#基于OpenCvSharpe实现模版匹配功能,其中实现了下功能: 1、图像加载; 2、模版加载、绘制、保存功能; 3、模版匹配功能。
内容概要:本文档汇集了CSci 235软件设计与分析II课程中关于数据结构的面试题,由Stewart Weiss教授整理。文档涵盖了广泛的数据结构主题,包括但不限于链表(如单链表、双向链表、循环链表)、二叉树(如二叉搜索树、最小高度二叉搜索树)、栈、队列等。每个问题都旨在考察求职者对不同数据结构的理解及其应用场景。例如,选择合适的数据结构实现手机通讯录功能,或设计支持撤销功能的文本编辑器。此外,文档还探讨了复杂度分析(Big-O表示法),以及如何优化特定操作的时间复杂度。最后,文档提供了额外的学习资源链接,帮助求职者进一步准备面试。 适合人群:计算机科学专业的学生或有志于从事软件开发工作的求职者,特别是那些希望在技术面试中表现优异的人士。 使用场景及目标:①理解并掌握常见数据结构的基本概念和特性;②学会根据不同场景选择最合适的数据结构;③掌握常见数据结构操作的时间复杂度分析;④为技术面试做充分准备,提高面试成功率。 其他说明:文档中的问题不仅限于理论知识,还包括实际编码练习,建议读者在学习过程中动手实践,以加深理解和记忆。同时,文档提供的额外资源链接可以作为扩展阅读材料,帮助读者更全面地掌握相关知识。
Matlab领域上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作
帆软本地打印插件FinePrint 8.0版本,适用于FineReport8
内容概要:本文介绍了密歇根大学EECS 461课程——嵌入式控制系统的核心内容及其发展背景。课程旨在教授学生嵌入式控制系统的理论与实践,包括传感器和执行器接口、实时性能和安全要求、混合行为系统、分布式控制网络等方面的知识。文中特别强调了现代汽车作为嵌入式控制系统的典型应用,从1977年到2019年间,汽车技术经历了从模拟控制到微处理器控制的巨大变革,如今的汽车具备了更高效、更环保、更安全的特点。课程还涵盖了S32K144微控制器的开发环境、实验室练习(如数字I/O、PWM信号生成、虚拟墙模拟等)以及自动代码生成工具的使用。 适合人群:具备一定编程基础,特别是对嵌入式系统感兴趣的本科生和研究生,尤其是电气工程、计算机科学专业的高年级学生或硕士生。 使用场景及目标:①了解嵌入式控制系统的基本概念和发展历程;②掌握嵌入式控制系统的设计方法和技术手段,如实时操作系统、中断处理、网络通信协议(CAN)等;③通过实际项目操作,熟悉嵌入式硬件平台和开发工具链的应用。 其他说明:随着汽车行业向智能化、自动化方向发展,对于能够开发复杂嵌入式软件的人才需求日益增长。EECS 461不仅为学生提供了扎实的技术训练,也为他们未来的职业发展打下了坚实的基础。此外,课程还反映了跨学科教育的重要性,鼓励学生打破传统学术界限,培养解决实际问题的能力。
内容概要:本文详细介绍了如何利用C#与Halcon联合编程构建高效的视觉几何定位与测量框架。主要内容涵盖模板创建与匹配、圆测量、数据持久化以及图像采集等方面的技术细节。首先,通过创建形状模板并进行匹配,实现了工件的精确定位。接着,针对圆形物体的测量,提出了动态ROI绘制、亚像素边缘提取和稳健圆拟合的方法。此外,还讨论了模板管理和图像采集的最佳实践,确保系统的稳定性和高效性。最后,强调了Halcon对象的内存管理和错误处理机制,提供了实用的优化建议。 适合人群:具备一定编程基础,尤其是对C#和Halcon有一定了解的研发人员和技术爱好者。 使用场景及目标:适用于工业生产线上的自动化检测设备开发,旨在提高工件定位和尺寸测量的精度与效率。主要目标是帮助开发者掌握C#与Halcon联合编程的具体实现方法,从而构建稳定可靠的视觉检测系统。 其他说明:文中提供了大量实战代码片段和调试技巧,有助于读者快速理解和应用相关技术。同时,作者分享了许多实际项目中的经验和教训,使读者能够避开常见陷阱,提升开发效率。
内容概要:本文深入探讨了DeepSeek AI的独特优势及其在全球AI领域的影响力。DeepSeek由中国深度求索公司开发,自2025年1月20日发布以来,凭借其卓越的性能和独特优势迅速吸引了全球关注。其核心优势包括:1) 极致成本效率,如低成本训练和高效推理;2) 强大的推理能力,涵盖多领域表现优异
php连接sqlserver之VC_redist.x64.exe
内容概要:本文详细介绍了利用Matlab/Simulink进行异步电动机交流调速系统的仿真实验,主要探讨了两种控制方式:恒压频比(V/F)开环控制和转差频率闭环控制。文中不仅提供了具体的数学模型和代码片段,还展示了不同控制方式下的仿真结果对比,包括转速响应、电流波形和谐波含量等方面的表现。此外,文章深入讲解了SVPWM(空间矢量脉宽调制)的应用,强调了其相对于传统SPWM的优势,并给出了详细的参数调整技巧和注意事项。 适合人群:从事电机控制系统设计的研究人员和技术人员,尤其是对Matlab/Simulink有一定基础并希望深入了解异步电动机调速系统的人群。 使用场景及目标:适用于需要进行电机控制算法开发和优化的场合,旨在帮助读者掌握异步电动机调速的基本原理和具体实现方法,提高仿真的准确性和效率。 其他说明:文章通过丰富的实例和图表,生动地展示了各种控制策略的特点和效果,有助于读者更好地理解和应用相关理论。同时,文中提供的调试技巧对于解决实际工程中的常见问题非常有帮助。
内容概要:本文详细介绍了如何利用Matlab进行电动汽车等速工况续驶里程的仿真。首先解释了等速工况的概念及其重要性,接着展示了具体的参数设定,如车辆质量、风阻系数、电池容量等。然后深入探讨了核心算法,包括阻力计算、功率需求、能量消耗以及SOC(剩余电量)的变化过程。文中特别强调了一些常见的陷阱和注意事项,如单位换算错误、电机效率的动态变化等。最后,通过可视化工具展示了仿真结果,并讨论了可能的改进方向,如引入NEDC工况循环和其他动态因素。 适合人群:新能源汽车专业的学生、研究人员以及对电动汽车仿真感兴趣的工程师。 使用场景及目标:①帮助理解和掌握电动汽车等速工况续驶里程仿真的原理和方法;②提供详细的代码实现和注释,便于学习和修改;③用于课程设计、毕业设计或其他研究项目。 其他说明:本文不仅提供了完整的Matlab代码,还包括详细的参数说明和常见问题解析,确保使用者能够顺利运行并理解整个仿真过程。同时,作者还分享了许多实践经验,有助于提高仿真的准确性和实用性。
【定稿】桂林电子科技大学第七届大学生思政课社会实践优秀成果展示活动实施方案 (1).zip
内容概要:本文详细介绍了使用Maxwell 16.0和ANSYS 2020进行直线感应电机瞬态磁场仿真的方法和技术要点。首先强调了建模前的准备工作,包括初级线圈布置、次级导体材料选择、气隙宽度等参数的确定。然后针对Maxwell 16.0用户,讲解了坐标系的选择(笛卡尔坐标系)、初级绕组绘制、运动参数设置、网格剖分优化以及边界条件的正确配置。对于ANSYS 2020用户,则着重讲述了如何利用Maxwell模块建立模型并在Mechanical中进行电磁力耦合分析,包括参数化扫描设置、气隙厚度扫描、磁密云图动态更新等技巧。此外,文中还分享了许多实用的经验和注意事项,如避免常见的参数设置错误、提高仿真精度的方法、处理推力波动等问题的具体措施。 适合人群:从事电机设计与仿真的工程师、研究人员,尤其是有一定Maxwell和ANSYS使用基础的技术人员。 使用场景及目标:帮助用户掌握直线感应电机瞬态磁场仿真的全流程,确保仿真结果的准确性,提升工作效率。具体应用场景包括但不限于新电机设计验证、现有电机性能优化、故障诊断等。 其他说明:文中提供了大量具体的命令和脚本示例,便于读者直接应用到实际工作中。同时,作者结合自身丰富的实践经验,给出了许多宝贵的建议和警示,有助于读者避开常见陷阱,顺利完成仿真任务。