简体   繁体   English

使用WINAPI检测USB存储连接

[英]Detecting USB Storage connection using WINAPI

I'm basically trying to detect a simple USB detection and retrieve certain information from it. 我基本上是在尝试检测简单的USB检测并从中检索某些信息。

Doing so, for a regular USB FLASH drive is quite simple, as most of the MSDN samples show. 这样做,如大多数MSDN示例所示,对于常规USB FLASH驱动器来说非常简单。

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);

and later on, wait for a WM_DEVICECHANGE message with DBT_DEVICEARRIVAL 然后再等待带有DBT_DEVICEARRIVALWM_DEVICECHANGE消息

i actually get 2 sequential messages: 我实际上得到2个顺序消息:

dbcc_name of the first message : 第一条消息的dbcc_name

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

dbcc_name of the second message: 第二条消息的dbcc_name

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

From this one, i can actually retrieve the friendaly name and so on. 从这个中,我实际上可以检索出友好名称,依此类推。

Now, my problem occurs when i try to do the same with phone connection. 现在,当我尝试使用电话连接进行相同操作时,会发生我的问题。

When i plug my phone using a regular USB cable, i get 当我使用常规的USB电缆插入手机时,

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

SetupDiGetDeviceRegistryProperty with SPDRP_DEVICEDESC returns USB Composite Device SetupDiGetDeviceRegistryPropertySPDRP_DEVICEDESC返回USB Composite Device

And when i grant file transfer storage permissions on my mobile, i get a second message with: 当我在手机上授予文件传输存储权限时,我收到第二条消息:

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

without a friendly name, using the 没有友好的名字,使用

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

function. 功能。

So couple of questions here: 所以这里有几个问题:

  1. How does windows recognize this as a mobile device, and even shows its name in the notifications bar ( Nexus 5x , Select to choose what happens with this device)? Windows如何将其识别为移动设备,甚至在通知栏中显示其名称( Nexus 5x ,选择以选择此设备会发生什么情况)?

  2. Lets say i would like to copy certain files from or to it. 可以说我想从中复制某些文件。 how do i get device handle or device path for WriteFile / CreateFile 我如何获取WriteFile / CreateFile的设备句柄或设备路径

  3. How come GetLogicalDrivesStrings retrieves a new drive(" c:\\\\\\0d:\\\\\\0 ") for a regular USB flash drive but doesn't do the same for mobile connection? GetLogicalDrivesStrings如何为常规USB闪存驱动器检索新的驱动器(“ c:\\\\\\0d:\\\\\\0 ”),但对于移动连接却不这样做?

Look at the dialog on your phone. 查看手机上的对话框。 You probably picked an option named "MTP". 您可能选择了一个名为“ MTP”的选项。 This is a file sharing protocol. 这是一个文件共享协议。 On the other hand, the USB stick uses a block storage protocol. 另一方面,USB记忆棒使用块存储协议。 That's why you get the USBSTOR announcement. 这就是为什么您会收到USBSTOR公告的原因。

Block storage allows for dumb devices, and requires intelligence on the host (Windows). 块存储允许使用笨拙的设备,并且需要主机(Windows)上的智能。 It's just a few million 512-byte sectors. 它只有几百万个512字节扇区。 Turning that into files is the responsibility of the FAT (or NTFS) driver. 将其转换为文件是FAT(或NTFS)驱动程序的责任。

Since block storage uses the FAT driver, it gets a drive letter just like internal hard disks, and can be accessed via CopyFile . 由于块存储使用FAT驱动程序,因此它就像内部硬盘一样获得驱动器号,并且可以通过CopyFile进行访问。 Since MTP devices aren't managed by the file system, they don't have drive letters. 由于MTP设备不受文件系统管理,因此它们没有驱动器号。

Why do mobile phones use MTP then? 那么为什么手机使用MTP? The big advantage is that MTP allows the phone to be much more in control. 最大的优势是MTP可以让手机掌控更多。 It can decide on a file by file basis whether to show it to the USB host. 它可以逐个文件地决定是否将其显示给USB主机。

(Disclosure: you can do that with FAT as well, but my former employer may still have a patent on that. Search for "Data storage access device patent TomTom" if this matters to you) (公开:您也可以使用FAT 做到这一点,但我的前雇主可能仍对此拥有专利。如果这对您很重要,请搜索“数据存储访问设备专利TomTom”)

when a smartphone is connected it appears at first as a SCSI device. 连接智能手机时,它首先显示为SCSI设备。 then USB protocol supports several attributes (beside vendorID and productID ) from that an operating system can get informations like the device name ( NEXUS 5x ,...) for this especially the attribute fields manufacturer and product USB协议就支持几个属性(除了vendorIDproductID ),操作系统可以从中获取诸如设备名称( NEXUS 5x ,...)之类的信息,尤其是属性字段manufacturerproduct

so windows does not 'know' it is a smartphone 因此Windows不会“知道”它是智能手机

the following is the output of udevadm info -a -p /sys/class/scsi_host/... on linux: 以下是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"

then it depends what function you activate on your smartphone. 那么这取决于您在智能手机上激活的功能。 if you want to activate tethering windows will get notified by the android device and load the RNDIS driver. 如果您想激活网络共享窗口,Android设备会通知您并加载RNDIS驱动程序。 the notification mechanism is a rest of the USB connection 通知机制是USB连接的其余部分

if you want to write or read files from the androids mass storage you have to activate the mass storage option and windows will get notified and 'mount' the android as a file system 如果您想从Android的大容量存储中写入或读取文件,则必须激活大容量存储选项,Windows会收到通知并将android作为文件系统“挂载”

so an android has implemented multiple interfaces / USB device classes in its USB structure and the user has to choose which interface to activate (tethering -> RNDIS, storage -> USB mass storage class,...) 因此,Android在其USB结构中实现了多个接口/ USB设备类,用户必须选择要激活的接口(网络共享-> RNDIS,存储-> USB大容量存储类,...)

this is also the reason why no new drive c:\\\\\\0d:\\\\\\0 appears when you connect the android to windows. 这也是将android连接到Windows时没有新驱动器c:\\\\\\0d:\\\\\\0出现的原因。 At first the android appears as a SCSI device with no specified function (SCSI Target) 最初,Android表现为没有指定功能的SCSI设备(SCSI目标)

For communication with the android in SCSI mode see http://www.stackoverflow.com/questions/3316284/sending-a-specific-scsi-command-to-a-scsi-device-in-windows 要以SCSI模式与android通信,请参阅http://www.stackoverflow.com/questions/3316284/sending-a-specific-scsi-command-to-a-scsi-device-in-windows

if you want to read or write the phones (internal, SD card) activate the mass storage option and you can use the normal USB mass storage interface (like USB memory stick) 如果您想读写手机(内置SD卡),请激活大容量存储选项,然后可以使用普通的USB大容量存储接口(如USB记忆棒)

for getting the dbcc_name maybe see http://www.stackoverflow.com/questions/2208722/how-to-get-friendly-device-name-from-dev-broadcast-deviceinterface-and-device-in 有关获取dbcc_name ,请参见http://www.stackoverflow.com/questions/2208722/how-to-get-friendly-device-name-from-dev-broadcast-deviceinterface-and-device-in

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM