`
dato0123
  • 浏览: 910979 次
文章分类
社区版块
存档分类
最新评论

Linux那些事儿之我是Hub(18)八大重量级函数闪亮登场(二)

 
阅读更多

第二个函数,usb_set_device_state(),鉴于网友潜水潜到二零零八提出drivers/usb/core/hub.c出镜频率过于的高,为避免被人成为新时期祥林嫂,经支部开会决定,从此以后凡是出自drivers/usb/core/hub.c这个文件的函数将不再做介绍其来源,这个就当是默认的位置.

1041 /**

1042 * usb_set_device_state - change a device's current state (usbcore, hcds)

1043 * @udev: pointer to device whose state should be changed

1044 * @new_state: new state value to be stored

1045 *

1046 * udev->state is _not_ fully protected by the device lock. Although

1047 * most transitions are made only while holding the lock, the state can

1048 * can change to USB_STATE_NOTATTACHED at almost any time. This

1049 * is so that devices can be marked as disconnected as soon as possible,

1050 * without having to wait for any semaphores to be released. As a result,

1051 * all changes to any device's state must be protected by the

1052 * device_state_lock spinlock.

1053 *

1054 * Once a device has been added to the device tree, all changes to its state

1055 * should be made using this routine. The state should _not_ be set directly.

1056 *

1057 * If udev->state is already USB_STATE_NOTATTACHED then no change is made.

1058 * Otherwise udev->state is set to new_state, and if new_state is

1059 * USB_STATE_NOTATTACHED then all of udev's descendants' states are also set

1060 * to USB_STATE_NOTATTACHED.

1061 */

1062 void usb_set_device_state(struct usb_device *udev,

1063 enum usb_device_state new_state)

1064 {

1065 unsigned long flags;

1066

1067 spin_lock_irqsave(&device_state_lock, flags);

1068 if (udev->state == USB_STATE_NOTATTACHED)

1069 ; /* do nothing */

1070 else if (new_state != USB_STATE_NOTATTACHED) {

1071

1072 /* root hub wakeup capabilities are managed out-of-band

1073 * and may involve silicon errata ... ignore them here.

1074 */

1075 if (udev->parent) {

1076 if (udev->state == USB_STATE_SUSPENDED

1077 || new_state == USB_STATE_SUSPENDED)

1078 ; /* No change to wakeup settings */

1079 else if (new_state == USB_STATE_CONFIGURED)

1080 device_init_wakeup(&udev->dev,

1081 (udev->actconfig->desc.bmAttributes

1082 & USB_CONFIG_ATT_WAKEUP));

1083 else

1084 device_init_wakeup(&udev->dev, 0);

1085 }

1086 udev->state = new_state;

1087 } else

1088 recursively_mark_NOTATTACHED(udev);

1089 spin_unlock_irqrestore(&device_state_lock, flags);

1090 }

天可怜见,这个函数不是很长,问题是,这个函数里面又调用了别的函数.

USB_STATE_NOTATTACHED,就是啥也没有,基本上就是说设备已经断开了,这种情况当然啥也不用做.

咱们刚才在usb_alloc_dev设置了等于USB_STATE_ATTACHED,所以继续,new_state,结合实参看一下,传递的是USB_STATE_POWERED,Root Hub另有管理方式,我们这里首先就处理非Root Hub的情况,如果原来就是USB_STATE_SUSPENDED,现还设置USB_STATE_SUSPENDED,那么当然什么也不用做.如果新的状态要被设置为USB_STATE_CONFIGURED,那么调用device_init_wakeup(),初始化唤醒方面的东西,您要是和我一样,对电源管理不感兴趣,那么估计这里您不会被唤醒,您会进入睡眠.不过人在江湖,身不由己,如果能够退出江湖,我们都想退出,然而,任我行说过,有人的地方就有江湖,人就是江湖,你怎么退出?我们又如何退出呢?既然不能退出,那么只好硬着头皮前进.

要认识device_init_wakeup()首先需要知道两个概念,can_wakeupshould_wakeup.这两个家伙从哪里钻出来的?struct device结构体,里面有这么一个成员, struct dev_pm_info power,来看看struct dev_pm_info,来自include/linux/pm.h:

265 struct dev_pm_info {

266 pm_message_t power_state;

267 unsigned can_wakeup:1;

268 #ifdef CONFIG_PM

269 unsigned should_wakeup:1;

270 pm_message_t prev_state;

271 void * saved_state;

272 struct device * pm_parent;

273 struct list_head entry;

274 #endif

275 };

这些都是电源管理部分的核心数据结构,显然我们没有必要深入研究,只是需要知道,can_wakeup1表明一个设备可以被唤醒,设备驱动为了支持Linux中的电源管理,有责任调用device_init_wakeup()来初始化can_wakeup.should_wakeup则是在设备的电源状态发生变化的时候被device_may_wakeup()用来测试,测试它该不该变化.因此can_wakeup表明的是一种能力,should_wakeup表明的是有了这种能力以后去不去做某件事,就好比我们吵架的时候经常说,不是我打不过你,而是我不想打你.打得过是一种能力,但是有这种能力不一定就会去真的打,还得衡量该不该打.

我们给device_init_wakeup()传递的参数是这个设备以及配置描述符中的bmAttributes&USB_CONFIG_ATT_WAKEUP,这是因为,USB spec中规定了,bmAttributes,D5表明的就是一个USB设备是否具有被唤醒的能力.如下图所示:

<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 252.75pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:/DOCUME~1/JASON_~1/LOCALS~1/Temp/msohtml1/01/clip_image001.emz"></imagedata></shape>

USB_CONFIG_ATT_WAKEUP被定义为1<<5,所以这里比较的就是D5是否为1,1就是说:”我能”.

1083这个else就是说,如果设备将要被设置的新状态又不是USB_STATE_CONFIGUERD,那么就执行这里的device_init_wakeup,这里第二个参数传递的是0,就是说先不打开这个设备的wakeup能力.咱们这个上下文就是这种情况,咱们刚刚才说到,咱们的新状态就是USB_STATE_POWERED.

直到1086,才正式把咱们的状态设置为新的这个状态,对于我们这个上下文,那就是USB_STATE_POWERED.

1087行这里又是一个else,那么很显然这个else的意思就是原来的状态不是USB_STATE_NOTATTACHED而现在要设置成USB_STATE_NOTATTACHED.这又是一个递归函数.其作用就是其名字中所说的那样,递归的把各设备都设置成NOTATTACHED状态.

1028 static void recursively_mark_NOTATTACHED(struct usb_device *udev)

1029 {

1030 int i;

1031

1032 for (i = 0; i < udev->maxchild; ++i) {

1033 if (udev->children[i])

1034 recursively_mark_NOTATTACHED(udev->children[i]);

1035 }

1036 if (udev->state == USB_STATE_SUSPENDED)

1037 udev->discon_suspended = 1;

1038 udev->state = USB_STATE_NOTATTACHED;

1039 }

这段代码真的是太简单了,属于教科书般的递归函数的经典例子.就是每一个设备遍历自己的子节点,一个个调用recursively_mark_NOTATTACHED()函数把其state设置为USB_STATE_NOTATTACHED.如果设备的状态处于USB_STATE_SUSPENDED,那么设置udev->discon_suspended1,struct usb_device中的一个成员,unsigned discon_suspended,含义很明显,表征Disconnected while suspended.这里这么一设置,暂时我们还不知道有什么用,不过到时候我们就会在电源管理部分的代码里看到判断这个flag,很显然设置了这个flag就会阻止suspend相关的代码被调用,咱们走着瞧.

Ok,第二个函数就这么轻轻松松搞定!

分享到:
评论

相关推荐

    Linux那些事儿之我是Hub

    Linux那些事儿之我是Hub,是前面Linux那些事之我是U盘,usb等的姐妹篇

    Linux那些事儿之我是HUB.pdf

    非常不错的一本书,LinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinux

    Linux那些事儿

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

    Linux那些事儿1-9合集

    linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Block层 linux那些事儿...

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

    Linux那些事儿第二版我是Hub一章,比较第一版修正了一些错误,增加了电源管理部分的分析,推荐阅读

    linux那些事儿之我是USB(包括第一版和第二版完整文字)

    本文件包括第一第二完成版,第二版基于2.6.22内核,对USB子系统的大部分源代码逐行进行分析,系统地阐释了Linux内核中USB子系统是如何运转的,子系统内部的各个模块之间是如何互相协作、配合的。本次改版修改了第1版...

    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那些事儿之我是USB(第2版).pdf

    本书基于2.6.22内核,对USB子系统的大部分源代码逐行进行分析,系统地阐释了Linux内核中USB子系统是如何运转的,子系统内部的各个模块之间是如何互相协作、配合的。本次改版修改了第1版中出现的错误,增加了一个附录...

    linux的那些事儿全集

    Linux那些事儿之我是Block层 ...Linux那些事儿之我是Hub Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Sysfs Linux那些事儿之我是UHCI Linux那些事儿之我是USB core Linux那些事儿之我是U盘

    linux那些事儿(EHCI Block SCSI Sysfs PCI USB U 盘 UHCI Hub)

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

    linux那些事全集

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

    Linux那些事儿系列

    本人整理的fudan_abc的专栏中以完结的文章,在此向原作者表示感谢,给...内容包括:linux那些事儿之我是U盘,linux那些事儿之我是USB,linux那些事儿之我是HUB,linux那些事儿之我是UHCI,linux那些事儿之我是Sysfs。

    Linux那些事儿之我是XXX全集.rar

    Linux那些事儿之我是XXX全集 包含USB core U盘 UHCI PCI SCSI硬盘 Block Hub EHCI 。 想学驱动的童鞋,不妨看看。该书主要是进行源代码的分析

    Linux那些事儿.rar

    包括:Linux那些Linux那些事儿之我是SCSI硬盘,Linux那些事儿之我是Block层,Linux那些事儿之我是EHCI主机控制器,Linux那些事儿之我是HUB,Linux那些事儿之我是PCI,Linux那些事儿之我是Sysfs,Linux那些事儿之我是...

    Linux那些事儿 系列之2 Block+EHCI+PCI+SCSI

    Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是PCI.pdf Linux那些事儿之我是SCSI硬盘.pdf 注: 之前有人已经上传了《Linux那些事儿 系列》,其已经包含了:hub,sysfs...

    linux那些事儿之我是USB.zip

    里面包含Linux那些事的九个文档,Block层,ECHI主机控制,HUB,PCI,SCSI硬盘,Sysfs,UHCI,USB+core,U盘等九个文档,内容详细,而且全面都有书签,适合系统学习!

    Linux那些事系列

    Linux那些事儿之我是Hub Linux那些事儿之我是Sysfs Linux那些事儿之我是UHCI Linux那些事儿之我是USB core Linux那些事儿之我是U盘 Linux那些事之我是HUB1

Global site tag (gtag.js) - Google Analytics