【问题标题】:Detecting USB Storage connection using WINAPI使用 WINAPI 检测 USB 存储连接
【发布时间】:2017-03-01 09:02:34
【问题描述】:

我基本上是在尝试检测一个简单的 USB 检测并从中检索某些信息。

对于普通的USB FLASH 驱动器,这样做非常简单,正如大多数 MSDN 示例所示。

HDEVNOTIFY hDevNotify;
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;
hDevNotify = RegisterDeviceNotification(hWnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);

稍后,等待带有DBT_DEVICEARRIVALWM_DEVICECHANGE 消息

我实际上收到了 2 条连续消息:

第一条消息的dbcc_name

\\?\USB#VID_0781&PID_5597#4C530001210518100555#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

第二条消息的dbcc_name

\\?\USBSTOR#Disk&Ven_SanDisk&Prod_Cruzer_Glide_3.0&Rev_1.00#4C530001210518100555&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

从这个,我实际上可以检索到朋友的名字等等。

现在,当我尝试对电话连接执行相同操作时,就会出现问题。

当我使用普通的 USB 数据线插入手机时,我得到了

\\?\USB#VID_18D1&PID_4EE2#00c5c6f0839a25d4#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

SetupDiGetDeviceRegistryPropertySPDRP_DEVICEDESC 返回 USB Composite Device

当我在我的手机上授予文件传输存储权限时,我收到第二条消息:

 \\?\USB#VID_18D1&PID_4EE2#00c5c6f0839a25d4#{a5dcbf10-6530-11d2-901f-00c04fb951ed}

没有友好的名字,使用

SetupDiGetDeviceRegistryProperty(hDevInfo, &spDevInfoData, 
            SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize)

功能。

这里有几个问题:

  1. Windows 如何将其识别为移动设备,甚至在通知栏中显示其名称(Nexus 5x,选择此设备会发生什么)?

  2. 假设我想从中复制某些文件或向其中复制某些文件。如何获取 WriteFile / CreateFile 的设备句柄或设备路径

  3. 为什么GetLogicalDrivesStrings 会为普通的 USB 闪存驱动器检索一个新驱动器(“c:\\\0d:\\\0”),但对移动连接却没有?

【问题讨论】:

    标签: c++ winapi mobile usb


    【解决方案1】:

    查看手机上的对话框。您可能选择了一个名为“MTP”的选项。这是一个文件共享协议。另一方面,U 盘使用块存储协议。这就是您收到USBSTOR 公告的原因。

    块存储允许使用哑设备,并且需要主机 (Windows) 上的智能。它只是几百万个 512 字节的扇区。将其转换为文件是 FAT(或 NTFS)驱动程序的责任。

    由于块存储使用的是FAT驱动,所以它和内部硬盘一样得到一个盘符,可以通过CopyFile访问。由于 MTP 设备不受文件系统管理,因此它们没有驱动器号。

    那为什么手机要使用MTP呢?最大的优势是 MTP 允许手机更好地控制。它可以逐个文件决定是否显示给USB主机。

    (披露:您也可以使用 FAT 做到这一点,但我的前雇主可能仍然拥有专利。如果这对您很重要,请搜索“数据存储访问设备专利 TomTom”)

    【讨论】:

      【解决方案2】:

      连接智能手机后,它首先显示为 SCSI 设备。那么USB协议支持几个属性(除了vendorIDproductID),操作系统可以从中获取设备名称(NEXUS 5x,...)等信息,尤其是属性字段@ 987654328@ 和product

      所以 windows 不“知道”它是智能手机

      以下是udevadm info -a -p /sys/class/scsi_host/...在linux上的输出:

      looking at device '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3:1.0/host42/scsi_host/host42':
          KERNEL=="host42"
          SUBSYSTEM=="scsi_host"
          DRIVER==""
          ATTR{unique_id}=="0"
          ATTR{host_busy}=="0"
          ATTR{cmd_per_lun}=="1"
          ATTR{can_queue}=="1"
          ATTR{sg_tablesize}=="65535"
          ATTR{sg_prot_tablesize}=="0"
          ATTR{unchecked_isa_dma}=="0"
          ATTR{proc_name}=="usb-storage"
          ATTR{state}=="running"
          ATTR{supported_mode}=="Initiator"
          ATTR{active_mode}=="Initiator"
          ATTR{prot_capabilities}=="0"
          ATTR{prot_guard_type}=="0"
      
        looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3:1.0/host42':
          KERNELS=="host42"
          SUBSYSTEMS=="scsi"
          DRIVERS==""
      
        looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-3/1-3:1.0':
          KERNELS=="1-3:1.0"
          SUBSYSTEMS=="usb"
          DRIVERS=="usb-storage"
          ATTRS{bInterfaceNumber}=="00"
          ATTRS{bAlternateSetting}==" 0"
          ATTRS{bNumEndpoints}=="02"
          ATTRS{bInterfaceClass}=="08"
          ATTRS{bInterfaceSubClass}=="06"
          ATTRS{bInterfaceProtocol}=="50"
          ATTRS{supports_autosuspend}=="1"
          ATTRS{interface}=="Mass Storage"
      
        looking at parent device '/devices/pci0000:00/0000:00:12.2/usb1/1-3':
          KERNELS=="1-3"
          SUBSYSTEMS=="usb"
          DRIVERS=="usb"
          ATTRS{configuration}==""
          ATTRS{bNumInterfaces}==" 1"
          ATTRS{bConfigurationValue}=="1"
          ATTRS{bmAttributes}=="c0"
          ATTRS{bMaxPower}=="500mA"
          ATTRS{urbnum}=="195"
          ATTRS{idVendor}=="feed"
          ATTRS{idProduct}=="2002"
          ATTRS{bcdDevice}=="ffff"
          ATTRS{bDeviceClass}=="00"
          ATTRS{bDeviceSubClass}=="00"
          ATTRS{bDeviceProtocol}=="00"
          ATTRS{bNumConfigurations}=="1"
          ATTRS{bMaxPacketSize0}=="64"
          ATTRS{speed}=="480"
          ATTRS{busnum}=="1"
          ATTRS{devnum}=="34"
          ATTRS{devpath}=="3"
          ATTRS{version}==" 2.00"
          ATTRS{maxchild}=="0"
          ATTRS{quirks}=="0x0"
          ATTRS{avoid_reset_quirk}=="0"
          ATTRS{authorized}=="1"
          ATTRS{manufacturer}=="MediaTek"
          ATTRS{product}=="X5"
          ATTRS{serial}=="0123456789ABCDEF"
      

      那么这取决于您在智能手机上激活的功能。如果您想激活网络共享窗口,Android 设备会通知您并加载 RNDIS 驱动程序。通知机制是 USB 连接的其余部分

      如果您想从 android 的大容量存储中写入或读取文件,您必须激活大容量存储选项,windows 将收到通知并将 android '挂载'为文件系统

      因此,Android 在其 USB 结构中实现了多个接口/USB 设备类,用户必须选择激活哪个接口(网络共享 -> RNDIS,存储 -> USB 大容量存储类,。 ..)

      这也是安卓连接windows时没有出现新驱动c:\\\0d:\\\0的原因。起初,android 显示为没有指定功能的 SCSI 设备(SCSI Target)

      在 SCSI 模式下与 android 的通信参见http://www.stackoverflow.com/questions/3316284/sending-a-specific-scsi-command-to-a-scsi-device-in-windows

      如果您想读取或写入手机(内部、SD 卡),请激活大容量存储选项,您可以使用普通的 USB 大容量存储接口(如 USB 记忆棒)

      要获取dbcc_name,请查看http://www.stackoverflow.com/questions/2208722/how-to-get-friendly-device-name-from-dev-broadcast-deviceinterface-and-device-in

      【讨论】:

      • 但是即使我激活了大容量存储选项,我仍然无法获得LogicalDrive,这样说,使用dbcc_name 调用CreateFile 确实返回了一个有效的句柄,但是然后呢?
      • 不确定如何从那里前进,我确实可以通过设备名称打开一个句柄......但是然后呢?只有在我授予文件传输权限后,才会出现 Nexus 5X 目录中的附加“目录”(内部共享存储)
      • 当您将其设置为大容量存储模式时,Windows 会为您的 android 加载哪个驱动程序?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多