电子大神的日记本,供应链专家的功夫茶盘,在这里记录、分享与共鸣。

登录以开始

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

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

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

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博客,转载请标明出处:

博主
512826028
蓝线技术
15:12:03 UTC+0800 有些文章,可能不全,如果有附件,附件就是这篇文章的完整版。 希望大家多提意见,注意,有些文章表明转载和出处了,不是我的文章。
点击跳转