首页 > 其他分享 >USB hub检测过程

USB hub检测过程

时间:2023-02-16 12:35:05浏览次数:45  
标签:USB hub 检测 sdcardfs device options usb

一、USB的电气特性

参考链接USB协议

在电气结构上,USB设备与主机的连接也很有讲究:

 

 

主机端的D-和D+数据线各自被串联15KR电阻下拉到地,当没有USB设备插入的时候,这两条数据线就一直呈现低电平状态。

设备端的D-或者D+数据线,串联一个1.5KR的电阻上拉到3.3V,一旦设备插入主机,那么当主机捕捉到自身的D-或者D+被拉到高电平时,就知道有USB设备连接进来了,这样就检测到有外来USB设备接入了。

对于从机设备中到底是D-还是D+串联1.5KR电阻,这个就要有传输协议的模式来决定了,当配置成全速或高速时,就由D+串联电阻;当配置成低速时,就是D-串联电阻了。

简单来说就是快的就连D+,慢的就连D-。

二、USB hub驱动识别过程

1、USB hub检测log

[ 1400.949084] usb 1-1.2: new high-speed USB device number 31 using xhci-hcd
[ 1401.089506] usb 1-1.2: New USB device found, idVendor=1f75, idProduct=0918
[ 1401.096708] usb 1-1.2: New USB device strings: Mfr=0, Product=3, SerialNumber=4
[ 1401.104758] usb 1-1.2: Product: STORAGE DEVICE
[ 1401.109495] usb 1-1.2: SerialNumber: 02071638
[ 1401.130553] usb-storage 1-1.2:1.0: USB Mass Storage device detected
[ 1401.140091] scsi host1: usb-storage 1-1.2:1.0
[ 1402.189010] scsi 1:0:0:0: Direct-Access     Specific STORAGE DEVICE   0009 PQ: 0 ANSI: 4
[ 1402.210918] sd 1:0:0:0: [sdg] Write Protect is off
[ 1402.215912] sd 1:0:0:0: [sdg] Mode Sense: 23 00 00 00
[ 1402.234091]  sdg: sdg1
[ 1403.028002] init: Untracked pid 7638 received signal 15
[ 1403.033724] init: Untracked pid 7638 did not have an associated service entry and will not be reaped
[ 1403.042762] FAT-fs (sdg1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.
[ 1403.098610] sdcardfs version 2.0
[ 1403.101958] sdcardfs: dev_name -> /mnt/media_rw/B67C-36B5
[ 1403.107547] sdcardfs: options -> fsuid=1023,fsgid=1023,mask=6,userid=0,gid=1015
[ 1403.115133] sdcardfs: mnt -> 00000000836b699d
[ 1403.119731] sdcardfs: mounted on top of /mnt/media_rw/B67C-36B5 type vfat
[ 1403.132000] Remount options were mask=18,gid=9997 for vfsmnt 00000000ee1d03d3.
[ 1403.139458] sdcardfs : options - debug:1
[ 1403.143531] sdcardfs : options - gid:9997
[ 1403.147660] sdcardfs : options - mask:18
[ 1403.156331] Remount options were mask=18,gid=9997 for vfsmnt 00000000467b1290.
[ 1403.163787] sdcardfs : options - debug:1
[ 1403.167849] sdcardfs : options - gid:9997
[ 1403.172008] sdcardfs : options - mask:18
[ 1403.180705] Remount options were mask=7,gid=9997 for vfsmnt 0000000076034062.
[ 1403.188041] sdcardfs : options - debug:1
[ 1403.192191] sdcardfs : options - gid:9997
[ 1403.196322] sdcardfs : options - mask:7 

2、驱动代码检测过程过程

 

上一篇博客刚好从平台设备、驱动的匹配分析到 hub_irq 这个函数这里。

static void hub_irq(struct urb *urb)
{
    struct usb_hub *hub = urb->context;
    int status = urb->status;
    unsigned i;
    unsigned long bits;
    switch (status) {
        ....
    case 0:    // 端口的状态发生了变化
        bits = 0;
        for (i = 0; i < urb->actual_length; ++i)
            bits |= ((unsigned long) ((*hub->buffer)[i]))
                    << (i*8);
        hub->event_bits[0] = bits;  // 保存状态改变的信息
        break;
    }

    hub->nerrors = 0;
    /* Something happened, let khubd figure it out */
    kick_khubd(hub);   //  重要函数  唤醒hub线程
resubmit:
    if (hub->quiescing)
        return;
    if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
            && status != -ENODEV && status != -EPERM)
        dev_err (hub->intfdev, "resubmit --> %d\n", status);
}

在 kick_khubd (hub) 中会唤醒执行 wake_up (&khubd_wait) 来唤醒一个程序。那么唤醒的到底是哪个程序呢?

int usb_hub_init(void)
{
    // 这里注册了hub_driver 这个在上一篇博客中提到过
    if (usb_register(&hub_driver) < 0) {
    }
    //  这里创建了一个hub_thread  名字叫"khubd" 
    khubd_task = kthread_run(hub_thread, NULL, "khubd");
    /* Fall through if kernel_thread failed */
    usb_deregister(&hub_driver);
    printk(KERN_ERR "%s: can't start khubd\n", usbcore_name);
    return -1;
}

现在可以看看在 hub_thread 这个线程中做一些什么事?

static int hub_thread(void *__unused)
{
    set_freezable();
    do {
        hub_events();                wait_event_freezable(khubd_wait,!list_empty(&hub_event_list) ||
                kthread_should_stop());
    } while (!kthread_should_stop() || !list_empty(&hub_event_list));
    return 0;
}

  在这个内核线程中主要执行 hub_events (),但是平时应该是休眠状态,直到有事情发生,其他程序中将其唤醒。因此可以说是在 hub_irq 函数中唤醒了 hub_thread,使得 hub_thread 能够执行 hub_events ()

函数。

  当有 usb 设备插入时,主机控制器检测到 hub 端口状态的变化,会执行 hub_irq 函数,然后按照下图的函数调用顺序一路往下执行,实现 usb 设备的识别过程:

  (1)给新设备分配地址

       (2)并将该地址告诉 usb 设备即设置 usb 地址

  (3)发出命令读取描述符

  (4)执行 usb_new_device 和 device_add(向总线上添加 usb 设备) 

  (5)device_add 之后又会执行 usb_device_match 函数和 generic_probe 函数,在 generic_probe 函数中 选择和设置 配置 之后又会执行 device_add(向 usb 总线上添加接口设备)

       (6)device_add 之后又会执行 usb_device_match 函数(这个时候应该就根据 id_table 和自己写的设备驱动进行匹配操作了)和 xx_probe 函数(自己驱动的 probe 函数)。

      

 四、USB hub识别出错检错流程

  • 检测VCC 5V供电是否正常。
  • 检测D+ D-在插入U盘后是否被拉高。
  • 如果上面两个条件满足,说明U盘有被检测到。
  • 加打印分析驱动流程哪块有阻塞。

标签:USB,hub,检测,sdcardfs,device,options,usb
From: https://www.cnblogs.com/yuanqiangfei/p/17126230.html

相关文章