問題由來:
https://bbs.csdn.net/topics/390907217?page=1#post-403471959
這位兄弟在很多年前使用USB時有個問題:用CreateFile()打開usb設備時,如何填寫devicepath這個值?
他的描述為:
想通過ReadFile()和WriteFile()這兩個介面來訪問usb設備,看檔案說在呼叫這兩個介面前需要先呼叫CreateFile()來獲取handle,而呼叫CreateFile()需要指定portname+端點索引號,問題是,這個portname是如何獲得的?查詢msdn發現需要使用IStiDeviceControl::GetMyDevicePortName()來獲取,頭檔案為:Stiusd.h 。這個介面是在應用層呼叫的嗎?
我看了很多回復,都沒有說到關鍵點上去,尤其是那些不負責任的人胡亂貼一些代碼根本就運行不了。垃圾!
此前本人并沒有涉及WINDOW下的USB編程,USB是老玩意了吧!但為啥沒有成熟的回復呢? 為了解決這個問題,本人做了一些研究,最終解決了問題,由于在那個帖子中回復只能回復5次,所以我這里集中把解決問題的經歷寫在這里:
先正面回答問題:CreateFile函式用到的devicepath就是通過設備GUID獲取的devicepath,這個設備GUID是具體到如果有子設備的話是子設備的設備GUID,當獲取到具有子設備GUID的devicepath時就可以直接使用,無需再找什么portname+端點索引號,或許根據具體設備的GUID獲取設備的devicepath就包含所謂的“portname+端點索引號"了吧(這個我沒弄清楚),以下是我的心路歷程,認真看完應該可以解決問題。
為了便于問題解決,強烈建議下載 工具軟體 UsbTreeView 和 BusHound
4年過去了,樓主及其他人有解決方案么?
我的計算機上有個U盤,盤符是H, 利用 UsbTreeView 知道該U盤 VID= 0x090c, pid= 0x1000,
利用 GUID_DEVINTERFACE_USB_DEVICE 這個GUID 結合 VID= 0x090c, pid= 0x1000
以及以下幾個主要函式 SetupDiGetClassDevs,SetupDiEnumDeviceInterfaces,SetupDiGetDeviceInterfaceDetail 獲取 設備路徑DevicePath為 "\\\\?\\usb#vid_090c&pid_1000#5&8b518d6&0&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"; (注意,這個字串中某些數字會變動,可能跟插的不同USB口有關),
利用這個DevicePath 執行 CreateFile函式并配置相應的引數能夠獲取句柄,但是獲取的句柄與使用 strDeviceName = "\\\\.\\H:"; 這個字串(盤符名)獲取的句柄值是不一樣的,后續利用DeviceIoControl來讀寫設備結果也是不同的,用前一種方法獲得的句柄讀寫失敗,后一種直接利用盤符獲取的句柄執行DeviceIoControl就可以成功讀取資料。 不知道什么原因!!!!!!
另外,當使用 GUID_DEVINTERFACE_USB_DEVICE 這個GUID 時 , HidD_GetAttributes 函式不能使用,我這里測驗這個函式只能用于HID設備。
我的問題是一個普通非U盤設備如何獲取類似"\\\\.\\H:"這樣的“檔案”名來提供給CreateFile的????
尊敬的樓主及所有關心該帖的同道們,雖然該帖4年過去了,但是仍有人關注和關心這個帖子,不能不讓人不感動!
入正題,上一個回復中提到的Device Path我利用工具 UsbTreeView,查看發現有兩處一處與我用函式獲取的相同,另一個為:
\\?\usbstor#disk&ven_usb&prod_flash_disk&rev_1100#6&ef43437&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b},
這一次我用這個代入CreateFile函式獲取句柄,雖然與用"\\\\.\\H:"獲得的句柄值不同,但后續也能成功讀取。
我驚訝發現這個DevicePath是 Child Device 1 的DevicePath !!!!
那么我現在初步回答樓主的問題(用CreateFile()打開usb設備時,如何填寫devicepath這個值? ),通常利用我上一個回復里的方法可以獲取devicepath,如果沒有子設備,那么就直接用這個devicepath配合CreateFile獲取句柄,如果有子設備,暫時我還沒有辦法自己獲取其子設備的devicepath, 但利用工具UsbTreeView可以查到,(UsbTreeView這個工具可以在網上下載到),希望能夠幫到你。
問題: 如何通過編程獲取子設備的devicepath?
以下是利用UsbTreeView獲取的U盤部分資訊描述
+++++++++++++++++ Device Information ++++++++++++++++++
Device Description : USB 大容量存盤設備
Device Path : \\?\usb#vid_090c&pid_1000#5&8b518d6&0&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
Device ID : USB\VID_090C&PID_1000\5&8B518D6&0&3
Hardware IDs : USB\VID_090C&PID_1000&REV_1100 USB\VID_090C&PID_1000
Driver KeyName : {36fc9e60-c465-11cf-8056-444553540000}\0070 (GUID_DEVCLASS_USB)
Driver : system32\DRIVERS\USBSTOR.SYS (Version: 6.1.7600.16385 Date: 2009-07-14)
Driver Inf : C:\Windows\inf\usbstor.inf
Legacy BusType : PNPBus
Class : USB
Class GUID : {36fc9e60-c465-11cf-8056-444553540000} (GUID_DEVCLASS_USB)
Interface GUID : {a5dcbf10-6530-11d2-901f-00c04fb951ed} (GUID_DEVINTERFACE_USB_DEVICE)
Service : USBSTOR
Enumerator : USB
Location Info : Port_#0003.Hub_#0001
Location IDs : PCIROOT(0)#PCI(1400)#USBROOT(0)#USB(3)
Container ID : {b577a458-b617-11e8-a8c8-28e3472d3289}
Manufacturer Info : 兼容 USB 存盤設備
Capabilities : 0xC4 (Removable, RawDeviceOK, SurpriseRemovalOK)
Status : 0x0180600A (DN_DRIVER_LOADED, DN_STARTED, DN_DISABLEABLE, DN_REMOVABLE, DN_NT_ENUMERATOR, DN_NT_DRIVER)
Problem Code : 0
Address : 3
Power State : D0 (supported: D0, D3, wake from D0)
Child Device 1 : USB Flash Disk USB Device (磁盤驅動器) (Disk1)
DevicePath : \\?\usbstor#disk&ven_usb&prod_flash_disk&rev_1100#6&ef43437&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
Device ID : USBSTOR\DISK&VEN_USB&PROD_FLASH_DISK&REV_1100\6&EF43437&0
Class : DiskDrive
Volume : \\?\Volume{b577a45b-b617-11e8-a8c8-28e3472d3289}\
Kernel Name : \Device\HarddiskVolume7
Mountpoint : H:\
---------------------------
問題延伸,當我們獲取Child Device 的DevicePath后把U盤插入另外一個USB口發現這個DevicePath是變得例如我這里兩次不同USB口獲取的值為:
strDeviceName = "\\\\?\\usbstor#disk&ven_usb&prod_flash_disk&rev_1100#6&ef43437&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
strDeviceName = "\\\\?\\usbstor#disk&ven_usb&prod_flash_disk&rev_1100#6&b867c1f&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
所以我們迫切需要編程自動獲取該值。
如何編程獲取Child Device 的DevicePath呢?????
問題進一步解決:
上回書說到利用UsbTreeView可以獲取Child Device的DevicePath,但如果更換USB口這個DevicePath會改變,所以如果這樣的程式交給客戶用顯然不行的,我們最終要擺脫UsbTreeView,要讓程式自我自動查找到Child Device的DevicePath,那為什之前找到的總是父設備的DevicePath呢?
重新研究了一下 父設備與子設備的DevicePath猛然發現,父設備與子設備的GUID不同
父設備DevicePath = "\\\\?\\usb#vid_090c&pid_1000#5&8b518d6&0&3#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"
//子設備DevicePath = "\\\\?\\usbstor#disk&ven_usb&prod_flash_disk&rev_1100#6&b867c1f&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}";
想到之前用一通函式SetupDiGetClassDevs,SetupDiEnumDeviceInterfaces,SetupDiGetDeviceInterfaceDetail 獲取設備路徑DevicePath時用的
GUID 不就是DevicePath后面“尾巴”么???靈光一閃,說時遲那時快,趕緊把程式頭部的GUID換成子設備的GUID,嘗試一下,
就是把 父設備 Interface GUID : {a5dcbf10-6530-11d2-901f-00c04fb951ed}
換成子設備 Interface GUID :{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
也就是在代碼里把它們寫成結構體形式為:
static GUID GUID_DEVINTERFACE_USB_DEVICE ={ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };//父
變為
static GUID GUID_DEVINTERFACE_USB_DEVICE ={ 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } };//子
使用子設備的GUID重新查找!果不其然!!!找到了!!!!
不過還是出了點小問題:
程式找到了兩個,我這里的情況列舉如下:
\\?\scsi#disk&ven_hgst&prod_hts541010a9e6800#4&f50782b&0&040000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
\\?\usbstor#disk&ven_usb&prod_flash_disk&rev_1100#6&b867c1f&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
后一個就是我要的東西,前一個不知道是什么,不過我直接用“usb”字串比對把前一個或略掉,留下后一個解決當前專案。
給所有朋友留一個問題:
前一個\\?\scsi#disk&ven_hgst&prod_hts541010a9e6800#4&f50782b&0&040000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 是什么東西?干嘛用的呢?
uj5u.com熱心網友回復:
百度搜“devcon”uj5u.com熱心網友回復:
感謝大佬 ,這幾天查了一堆資料,都看不太懂 ,看到這篇突然茅舍頓開uj5u.com熱心網友回復:
?這個很難?
DEFINE_GUID( GUID_DEVINTERFACE_USB_DEVICE, 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, \
0xC0, 0x4F, 0xB9, 0x51, 0xED ); // USB specific GUIDs
DEFINE_GUID(GUID_DEVINTERFACE_DISK, 0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b); // ioctlguid
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/45372.html
標籤:硬件/系統
上一篇:顏色漸變的三角形 用mfc
