原创 Linux那些事儿之我是Hub(12)再向虎山行

2010-7-13 07:05 2972 3 3 分类: MCU/ 嵌入式

徐志摩说:轻轻的我穿衣,正如我轻轻的脱;


后来徐志摩又说:轻轻的我走了,正如我轻轻的来.


hub_events(),没错,胡汉三又回来了.


再一次进入while这个(该)死(的)循环.


第一次来这里的时候,hub_event_list是空的,可是这一次不是了,我们刚刚在kick_khubd()里面才执行了往这个队列里插入的操作,所以我们不会再像第一次一样,从2621行的break跳出循环.相反,我们直接走到2624行,把刚才插入队列的那个节点取出来,存为tmp,然后把tmp从队列里删除掉.(是从队列里删除,不是把tmp本身给删除.)


2627行,list_entry(),这个经典的函数,或者说宏,就像复旦南区食堂的大排,永恒的经典.通过这个宏这里得到的是那个触发hub_events()的hub.然后2628行,同时用局部变量hdev记录hub->hdev.2629行,又得到对应的struct usb_interface和struct device,这下好了,什么都得到了,该付出了吧.


2640行, usb_get_intf(),看仔细了,别和我们当年在usb-storage里面调用的那个usb_get_intfdata()混淆了,这里usb_get_intf只是一个引用计数.是usb core提供的一个函数,以前黑客们推荐用另一个引用计数的函数usb_get_dev(),但在当今世界这样一种现状下,随着一个usb device越来越成为多个interface耦合的情况的出现,struct usb_device实际上已经快淡出历史舞台了,现在在驱动程序里关注的最多的就是interface,而不是device.和usb_get_intf()对应的有另一个函数,叫做usb_put_intf(),很显然,一个是增加引用计数一个减少引用计数.这个函数我们马上就能看到.


前面我们贴hub_events()只贴到2641行,现在继续贴,贴完这个粉恐怖的函数.


   2642


   2643                 /* Lock the device, then check to see if we were


   2644                  * disconnected while waiting for the lock to succeed. */


   2645                 if (locktree(hdev) < 0) {


   2646                         usb_put_intf(intf);


   2647                         continue;


   2648                 }


   2649                 if (hub != usb_get_intfdata(intf))


   2650                         goto loop;


   2651


   2652                 /* If the hub has died, clean up after it */


   2653                 if (hdev->state == USB_STATE_NOTATTACHED) {


   2654                         hub->error = -ENODEV;


   2655                         hub_pre_reset(intf);


   2656                         goto loop;


   2657                 }


   2658


   2659                 /* Autoresume */


   2660                 ret = usb_autopm_get_interface(intf);


   2661                 if (ret) {


   2662                         dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);


   2663                         goto loop;


   2664                 }


   2665


   2666                 /* If this is an inactive hub, do nothing */


   2667                 if (hub->quiescing)


   2668                         goto loop_autopm;


   2669


   2670                 if (hub->error) {


   2671                         dev_dbg (hub_dev, "resetting for error %d\n",


   2672                                 hub->error);


   2673


   2674                         ret = usb_reset_composite_device(hdev, intf);


   2675                         if (ret) {


   2676                                 dev_dbg (hub_dev,


   2677                                         "error resetting hub: %d\n", ret);


   2678                                 goto loop_autopm;


   2679                         }


   2680


   2681                         hub->nerrors = 0;


   2682                         hub->error = 0;


   2683                 }


   2684


   2685                 /* deal with port status changes */


   2686                 for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {


   2687                         if (test_bit(i, hub->busy_bits))


   2688                                 continue;


   2689                         connect_change = test_bit(i, hub->change_bits);


   2690                         if (!test_and_clear_bit(i, hub->event_bits) &&


   2691                                         !connect_change && !hub->activating)


   2692                                 continue;


   2693


   2694                         ret = hub_port_status(hub, i,


   2695                                         &portstatus, &portchange);


   2696                         if (ret < 0)


   2697                                 continue;


   2698


   2699                         if (hub->activating && !hdev->children[i-1] &&


   2700                                         (portstatus &


   2701                                                 USB_PORT_STAT_CONNECTION))


   2702                                 connect_change = 1;


   2703


   2704                         if (portchange & USB_PORT_STAT_C_CONNECTION) {


   2705                                 clear_port_feature(hdev, i,


   2706                                         USB_PORT_FEAT_C_CONNECTION);


   2707                                 connect_change = 1;


   2708                         }


   2709


   2710                         if (portchange & USB_PORT_STAT_C_ENABLE) {


   2711                                 if (!connect_change)


   2712                                         dev_dbg (hub_dev,


   2713                                                 "port %d enable change, "


   2714                                                 "status %08x\n",


   2715                                                 i, portstatus);


   2716                                 clear_port_feature(hdev, i,


   2717                                         USB_PORT_FEAT_C_ENABLE);


   2718


   2719                                 /*


   2720                                  * EM interference sometimes causes badly


   2721                                  * shielded USB devices to be shutdown by


   2722                                  * the hub, this hack enables them again.


   2723                                  * Works at least with mouse driver.


   2724                                  */


   2725                                 if (!(portstatus & USB_PORT_STAT_ENABLE)


   2726                                     && !connect_change


   2727                                     && hdev->children[i-1]) {


   2728                                         dev_err (hub_dev,


   2729                                             "port %i "


   2730                                             "disabled by hub (EMI?), "


   2731                                             "re-enabling...\n",


   2732                                                 i);


   2733                                         connect_change = 1;


   2734                                 }


   2735                         }


   2736


   2737                         if (portchange & USB_PORT_STAT_C_SUSPEND) {


   2738                                 clear_port_feature(hdev, i,


   2739                                         USB_PORT_FEAT_C_SUSPEND);


   2740                                 if (hdev->children[i-1]) {


   2741                                         ret = remote_wakeup(hdev->


   2742                                                         children[i-1]);


   2743                                         if (ret < 0)


   2744                                                 connect_change = 1;


   2745                                 } else {


   2746                                         ret = -ENODEV;


   2747                                         hub_port_disable(hub, i, 1);


   2748                                 }


   2749                                 dev_dbg (hub_dev,


   2750                                         "resume on port %d, status %d\n",


   2751                                         i, ret);


   2752                         }


   2753


   2754                         if (portchange & USB_PORT_STAT_C_OVERCURRENT) {


   2755                                 dev_err (hub_dev,


   2756                                         "over-current change on port %d\n",


   2757                                         i);


   2758                                 clear_port_feature(hdev, i,


   2759                                         USB_PORT_FEAT_C_OVER_CURRENT);


   2760                                 hub_power_on(hub);


   2761                         }


   2762


   2763                         if (portchange & USB_PORT_STAT_C_RESET) {


   2764                                 dev_dbg (hub_dev,


   2765                                         "reset change on port %d\n",


   2766                                         i);


   2767                                 clear_port_feature(hdev, i,


   2768                                         USB_PORT_FEAT_C_RESET);


   2769                         }


   2770


   2771                         if (connect_change)


   2772                                 hub_port_connect_change(hub, i,


   2773                                                 portstatus, portchange);


   2774                 } /* end for i */


   2775


   2776                 /* deal with hub status changes */


   2777                 if (test_and_clear_bit(0, hub->event_bits) == 0)


   2778                         ;       /* do nothing */


   2779                 else if (hub_hub_status(hub, &hubstatus, &hubchange) < 0)


   2780                         dev_err (hub_dev, "get_hub_status failed\n");


   2781                 else {


   2782                         if (hubchange & HUB_CHANGE_LOCAL_POWER) {


   2783                                 dev_dbg (hub_dev, "power change\n");


   2784                                 clear_hub_feature(hdev, C_HUB_LOCAL_POWER);


   2785                                 if (hubstatus & HUB_STATUS_LOCAL_POWER)


   2786                                         /* FIXME: Is this always true? */


   2787                                         hub->limited_power = 0;


   2788                                 else


   2789                                         hub->limited_power = 1;


   2790                         }


   2791                         if (hubchange & HUB_CHANGE_OVERCURRENT) {


   2792                                 dev_dbg (hub_dev, "overcurrent change\n");


   2793                                 msleep(500);    /* Cool down */


   2794                                 clear_hub_feature(hdev, C_HUB_OVER_CURRENT);


   2795                                 hub_power_on(hub);


   2796                         }


   2797                 }


   2798


   2799                 hub->activating = 0;


   2800


   2801                 /* If this is a root hub, tell the HCD it's okay to


   2802                  * re-enable port-change interrupts now. */


   2803                 if (!hdev->parent && !hub->busy_bits[0])


   2804                         usb_enable_root_hub_irq(hdev->bus);


   2805


   2806 loop_autopm:


   2807                 /* Allow autosuspend if we're not going to run again */


   2808                 if (list_empty(&hub->event_list))


   2809                         usb_autopm_enable(intf);


   2810 loop:


   2811                 usb_unlock_device(hdev);


   2812                 usb_put_intf(intf);


   2813


   2814         } /* end while (1) */


   2815 }


我真想诚恳的问候一下写代码的人的女性长辈.当裴多菲说:"若为自由故,两者皆可抛",我懂得了作为人的价值;当鲁迅说:"不在沉默中爆发,就在沉默中灭亡",我懂得人应具有反抗精神;当白朗宁说:"拿走爱,世界将变成一座坟墓",我懂得了为他人奉献爱心的重要;当简爱说:"我们是平等的,我不是无感情的机器",我懂得了作为女性的自尊;当我看到这段代码,我却完全不懂写代码的人为什么总要写一些恐怖的函数出来.一定要吓唬吓唬我他们就开心么?我是复旦的,不是厦(吓)大的.


 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fudan_abc/archive/2007/08/25/1759101.aspx

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /3 下一条