想通過ReadFile()和WriteFile()這兩個介面來訪問usb設備,看檔案說在呼叫這兩個介面前需要先呼叫CreateFile()來獲取handle,而呼叫CreateFile()需要指定portname+端點索引號,問題是,這個portname是如何獲得的?查詢msdn發現需要使用IStiDeviceControl::GetMyDevicePortName()來獲取,頭檔案為:Stiusd.h 。這個介面是在應用層呼叫的嗎?
uj5u.com熱心網友回復:
http://www.docin.com/p-63912601.htmluj5u.com熱心網友回復:
用這個函式試試吧:
// 取我的設備路徑
CString CHidUsbThread::GetMyDevicePath(void)
{
CString path=L"";
CString pszDevicePath[24];
int nCount=0;
//================= 列舉HID設備 =================
HDEVINFO hDevInfoSet;
SP_DEVICE_INTERFACE_DATA ifdata;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
BOOL bResult;
GUID hidGuid;
::HidD_GetHidGuid((LPGUID)&hidGuid); // 取HID設備GUID
// 取得一個該GUID相關的設備資訊集句柄
hDevInfoSet = SetupDiGetClassDevs(&hidGuid, // class GUID
NULL, // 無關鍵字
NULL, // 不指定父視窗句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的設備
// 失敗...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
return path;
}
// 申請設備介面資料空間
pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, 1024);
if(pDetail==NULL)
{
SetupDiDestroyDeviceInfoList(hDevInfoSet); // 清理句柄
return path;
}
pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
bResult = TRUE;
// 設備序號=0,1,2... 逐一測驗設備介面,到失敗為止
while (bResult)
{
ifdata.cbSize = sizeof(ifdata);
// 列舉符合該GUID的設備介面
bResult = ::SetupDiEnumDeviceInterfaces(
hDevInfoSet, // 設備資訊集句柄
NULL, // 不需額外的設備描述
&hidGuid, // GUID
(ULONG)nCount, // 設備資訊集里的設備序號
&ifdata); // 設備介面資訊
if (bResult)
{
// 取得該設備介面的細節(設備路徑)
bResult = SetupDiGetInterfaceDeviceDetail(
hDevInfoSet, // 設備資訊集句柄
&ifdata, // 設備介面資訊
pDetail, // 設備介面細節(設備路徑)
1024, // 輸出緩沖區大小
NULL, // 不需計算輸出緩沖區大小(直接用設定值)
NULL); // 不需額外的設備描述
if (bResult)
{
// 復制設備路徑到輸出緩沖區
pszDevicePath[nCount] = pDetail->DevicePath;
// 調整計數值
nCount++;
}
}
}
//======================= 查找需要的設備 =======================
for(int i=0;i<nCount;i++)
{
if(GetVidAndPid(pszDevicePath[i]))
{
path=pszDevicePath[i];
break;
}
}
return path;
}
uj5u.com熱心網友回復:
沒那么麻煩吧,我現在也在研究USB這塊,HID設備,給你看篇帖子,一起學習http://blog.csdn.net/kevinyujm/article/details/4264506
uj5u.com熱心網友回復:
// 取我的設備路徑
CString CHidUsbThread::GetMyDevicePath(void)
{
CString path=L"";
CString pszDevicePath[24];
int nCount=0;
//================= 列舉HID設備 =================
HDEVINFO hDevInfoSet;
SP_DEVICE_INTERFACE_DATA ifdata;
PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;
BOOL bResult;
GUID hidGuid;
::HidD_GetHidGuid((LPGUID)&hidGuid); // 取HID設備GUID
// 取得一個該GUID相關的設備資訊集句柄
hDevInfoSet = SetupDiGetClassDevs(&hidGuid, // class GUID
NULL, // 無關鍵字
NULL, // 不指定父視窗句柄
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的設備
// 失敗...
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
return path;
}
// 申請設備介面資料空間
pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, 1024);
if(pDetail==NULL)
{
SetupDiDestroyDeviceInfoList(hDevInfoSet); // 清理句柄
return path;
}
pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
bResult = TRUE;
// 設備序號=0,1,2... 逐一測驗設備介面,到失敗為止
while (bResult)
{
ifdata.cbSize = sizeof(ifdata);
// 列舉符合該GUID的設備介面
bResult = ::SetupDiEnumDeviceInterfaces(
hDevInfoSet, // 設備資訊集句柄
NULL, // 不需額外的設備描述
&hidGuid, // GUID
(ULONG)nCount, // 設備資訊集里的設備序號
&ifdata); // 設備介面資訊
if (bResult)
{
// 取得該設備介面的細節(設備路徑)
bResult = SetupDiGetInterfaceDeviceDetail(
hDevInfoSet, // 設備資訊集句柄
&ifdata, // 設備介面資訊
pDetail, // 設備介面細節(設備路徑)
1024, // 輸出緩沖區大小
NULL, // 不需計算輸出緩沖區大小(直接用設定值)
NULL); // 不需額外的設備描述
if (bResult)
{
// 復制設備路徑到輸出緩沖區
pszDevicePath[nCount] = pDetail->DevicePath; ////<<------------這里的Devicepath可以作為Portname來呼叫CreateFile()嗎? 想用這個CreateFile()回傳的handle再來呼叫Readfile和Writefile.
// 調整計數值
nCount++;
}
}
}
//======================= 查找需要的設備 =======================
for(int i=0;i<nCount;i++)
{
if(GetVidAndPid(pszDevicePath[i]))
{
path=pszDevicePath[i];
break;
}
}
return path;
}
uj5u.com熱心網友回復:
主要是看到了下面這個鏈接,所以才會一直想獲取portname然后再呼叫writefilehttp://msdn.microsoft.com/en-us/library/windows/hardware/ff548563%28v=vs.85%29.aspx
uj5u.com熱心網友回復:
謝謝。
但是我的問題是不知道如何確定Createfile()的第1個引數,也就是devicename。
現在可以通過 wxhxj0268的方法獲取 devicename,但是這個devicename和 http://msdn.microsoft.com/en-us/library/windows/hardware/ff548563%28v=vs.85%29.aspx 中提到的portname是一個東西嗎?
uj5u.com熱心網友回復:
先確定什么設備,hid設備用上面的方法。其他的要換設備的guiduj5u.com熱心網友回復:
幫人幫到底,再提供一個函式,它打開設備回傳控制句柄,就是你想知道的Createfile()
// 打開設備獲取句柄
HANDLE CHidUsbThread::OpenDevice(CString devName)
{
HANDLE hOut;
hOut=CreateFile(devName, // 設備路徑
GENERIC_READ|GENERIC_WRITE, // 訪問方式
FILE_SHARE_READ|FILE_SHARE_WRITE, // 共享模式
NULL, // SECURITY_ATTRIBUTES 型別指標
OPEN_EXISTING, // 檔案不存在時回傳失敗
FILE_FLAG_OVERLAPPED, // 以重疊(異步)模式打開
NULL); // 模板檔案句柄
return hOut;
}
uj5u.com熱心網友回復:
GetVidAndPid()的實作呢?
uj5u.com熱心網友回復:
vid和pid你的usb設備是有的,你寫死就行了。一般vid和pid是固定的,當然另外一種方法就是用開源的libusb,你google下就知道了,createfile這種方法其實也還好。uj5u.com熱心網友回復:
不妨使用CxDeviceFind設備查找類http://www.cnblogs.com/EdmundDwyane/p/3187226.html
uj5u.com熱心網友回復:
CreateFile()回傳句柄失敗怎么回事,謝謝大神了?uj5u.com熱心網友回復:
有個libusb庫的,我記得。uj5u.com熱心網友回復:
請問 那么最后,Createfile()的第1個引數,也就是devicename,是不是做過函式回傳的CString,還是其他的什么。
uj5u.com熱心網友回復:
http://www.docin.com/p-63912601.html
謝謝。
但是我的問題是不知道如何確定Createfile()的第1個引數,也就是devicename。
現在可以通過 wxhxj0268的方法獲取 devicename,但是這個devicename和 http://msdn.microsoft.com/en-us/library/windows/hardware/ff548563%28v=vs.85%29.aspx 中提到的portname是一個東西嗎?
請問 那么最后,Createfile()的第1個引數,也就是devicename,是不是做過函式回傳的CString,還是其他的什么。
簡而言之就是:到底哪里應該填什么??
uj5u.com熱心網友回復:
搜“devcon”?uj5u.com熱心網友回復:
http://www.docin.com/p-63912601.html
謝謝。
但是我的問題是不知道如何確定Createfile()的第1個引數,也就是devicename。
現在可以通過 wxhxj0268的方法獲取 devicename,但是這個devicename和 http://msdn.microsoft.com/en-us/library/windows/hardware/ff548563%28v=vs.85%29.aspx 中提到的portname是一個東西嗎?
請問 那么最后,Createfile()的第1個引數,也就是devicename,是不是做過函式回傳的CString,還是其他的什么。
簡而言之就是:到底哪里應該填什么??
對不住啊,我也忘了當時具體填的什么了
uj5u.com熱心網友回復:
http://blog.csdn.net/xust999/article/details/6553302uj5u.com熱心網友回復:
3年過去了,樓主有解決方案么?uj5u.com熱心網友回復:
3年過去了,樓主有解決方案么?
沒有,當時這個東西因為別的事情就放置不做了。我不太熟悉win的平臺,平時都是在linux下干活的,所以對win的一些機制什么的不太熟悉,而且也有抵觸去熟悉的情緒。
uj5u.com熱心網友回復:
搜““USBVIEW””?uj5u.com熱心網友回復:
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的????
uj5u.com熱心網友回復:
尊敬的樓主及所有關心該帖的同道們,雖然該帖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:\
uj5u.com熱心網友回復:
問題延伸,當我們獲取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呢?????
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/62503.html
標籤:硬件/系統
上一篇:VisualStudio C++/C#2015在除錯時如何在Watch視窗顯示WString,LPCWSTRd等UNICODE字串的值?
