首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

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

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