使用WINAPI检测USB存储连接

时间:2017-03-01 09:02:35

标签: c++ winapi mobile usb

我基本上试图检测简单的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);

以及稍后,等待WM_DEVICECHANGE消息DBT_DEVICEARRIVAL

我实际上得到了两条连续的消息:

第一条消息的

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}
带有SetupDiGetDeviceRegistryProperty

SPDRP_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. 的设备句柄或设备路径
  4. GetLogicalDrivesStrings如何为常规USB闪存驱动器检索新驱动器(" c:\\\0d:\\\0")但对移动连接不做同样的操作

2 个答案:

答案 0 :(得分:0)

查看手机上的对话框。你可能选择了一个名为" MTP"的选项。这是一个文件共享协议。另一方面,USB记忆棒使用块存储协议。这就是你获得USBSTOR公告的原因。

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

由于块存储使用FAT驱动程序,它会像内部硬盘一样获得驱动器号,并且可以通过CopyFile访问。由于MTP设备不受文件系统管理,因此它们没有驱动器号。

为什么手机会使用MTP呢?最大的优势是MTP可以让手机更加可控。它可以逐个文件地决定是否将其显示给USB主机。

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

答案 1 :(得分:0)

连接智能手机时,它首先显示为SCSI设备。那么USB协议支持几个属性(在vendorIDproductID旁边),操作系统可以获得这样的信息,例如设备名称( NEXUS 5x ,...)属性字段manufacturerproduct

所以Windows不知道它是智能手机

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

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连接的其余部分

如果你想从机器人大容量存储中写入或读取文件,你必须激活大容量存储选项,Windows将收到通知,并将android“挂载”为文件系统

所以android已经在其USB结构中实现了多个接口/ USB设备类,用户必须选择激活哪个接口(网络共享 - > RNDIS,存储 - > USB海量存储类,...)

这也是将android连接到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