全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:5574
推到 Plurk!
推到 Facebook!

請問這一段取得USB Device Handle的程式碼有何問題?

尚未結案
LouisLu
一般會員


發表:7
回覆:8
積分:3
註冊:2005-01-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-02-16 16:30:58 IP:211.79.xxx.xxx 未訂閱
請問各位大大:   可否請各位大大指點不知道我的這一段取得USB Device Handle的程式碼有什麼問題? 我已有定義好GUID_CLASS_ISO為正確的GUID,我想再取得Device Hamdle之後對Device做 DeviceIoControl的動作,但是一直無法成功,似乎是沒有成功取得Device Handle的關係。   煩請各位大大指點迷津...感謝感謝...
HANDLE GetDeviceHandle(BOOL Async)
{
        HANDLE hIsoDev = INVALID_HANDLE_VALUE;
        HDEVINFO                                HardwareDeviceInfo;
        SP_DEVICE_INTERFACE_DATA                DeviceInfoData;
        PSP_DEVICE_INTERFACE_DETAIL_DATA        DeviceDetailData = NULL;
        ULONG                    predictedLength = 0;
        ULONG                    requiredLength = 0;
        ULONG                    i;
        BOOLEAN                  done;             HardwareDeviceInfo = SetupDiGetClassDevs(
                                        &GUID_CLASS_ISO,
                                        NULL, // Define no enumerator (global)
                                        NULL, // Define no
                                        (DIGCF_PRESENT | // Only Devices present
                                        DIGCF_DEVICEINTERFACE)
                                        ); // Function class devices.            done = FALSE;
        DeviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);            for (i=0;!done;i  )
        {
                 if ( SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
                                                 0,                                                                             &GUID_CLASS_ISO,
                                                 i,
                                                 &DeviceInfoData) )
                {
                        SetupDiGetDeviceInterfaceDetail (
                                        HardwareDeviceInfo,
                                        &DeviceInfoData,
                                        NULL, 
                                        0,                                      
      /*其實是有的,不知道之前為什麼會看不見*/&requiredLength, 
                                        NULL); 
                        predictedLength = requiredLength;
                        
                        DeviceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(predictedLength);
                        DeviceDetailData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);                            if( SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo,
                                                            &DeviceInfoData,
                                                            DeviceDetailData,
                                                            predictedLength,
                                                            &requiredLength,
                                                            NULL) )
                        {
                                DWORD FileAttr;                                    if (Async)      FileAttr = FILE_FLAG_OVERLAPPED;
                                else            FileAttr = 0;                                    hIsoDev = CreateFile(DeviceDetailData->DevicePath,
                                                     GENERIC_READ | GENERIC_WRITE,
                                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                     NULL, 
                                                     OPEN_EXISTING, 
                                                     FileAttr, 
                                                     NULL);                             }
                        else
                        {
                                hIsoDev = INVALID_HANDLE_VALUE;
                        }                            free( DeviceDetailData);                            if ( hIsoDev != INVALID_HANDLE_VALUE )
                        {
                                done = TRUE;
                                break;
                        }
                }
                else
                {
                        if (ERROR_NO_MORE_ITEMS == GetLastError())
                        {
                                done = TRUE;
                                break;
                        }
                }
                    SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);            return hIsoDev;
}
. 發表人 - LouisLu 於 2005/02/16 19:59:18
derrenbol1
中階會員


發表:5
回覆:113
積分:93
註冊:2004-12-09

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-02-16 17:18:37 IP:210.202.xxx.xxx 未訂閱
LouisLu : SetupDiGetDeviceInterfaceDetail這個API你必須先給一個變數去存作業 系統給你的大小, 也就是下一行 predictedLength = requiredLength; 為何會這樣寫的關係, 所以你現在這兩個變數都是0, DeviceDetailData 當然沒有空間. 再詳細看一下MSDN關於SetupDiGetDeviceInterfaceDetail 的說明.
LouisLu
一般會員


發表:7
回覆:8
積分:3
註冊:2005-01-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-02-16 17:41:20 IP:211.79.xxx.xxx 未訂閱
derrenbol1大大您好:   感謝您的耐心回應.. 您的意思是說predictedLength和requiredLength兩個變數都是0是造成無法成功取得Device Handle的原因? 可是我在Debug的時候發現這兩個變數的值皆為83,不是0ㄟ... 還是小弟笨拙,誤會大大的意思了... 請大大明示,多謝..
derrenbol1
中階會員


發表:5
回覆:113
積分:93
註冊:2004-12-09

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-02-16 19:23:04 IP:210.202.xxx.xxx 未訂閱
LouisLu: SetupDiGetDeviceInterfaceDetail這個API主要在取得該裝置的路徑, 而路 徑會放到你所給的參數DeviceDetailData裏面, 然而因為每一個裝置的路徑名稱不一樣, 所以該結構的大小不一定, 故OS希望程式設計者"呼叫兩次", 第一 次你必須給一個DWORD變數的位置於參數5: DWORD RequiredSize = 0; SetupDiGetDeviceInterfaceDetail( DeviceInfoSet, &DeviceInfoData, DeviceDetailData, 0, &RequiredSize, NULL); 於第一次呼叫時DeviceDetailData為NULL, 而OS會將該結構所須的大小放到 RequiredSize裏面, 這樣你才可以用來呼叫malloc去分配空間給DeviceDetailData; 再一次的呼叫, OS就會將"裝置路徑"放到DeviceDetailData裏面了. 你說你predictedLength 及requiredLength的除錯值皆為83, 我想你的除錯 點放錯位罝了, 你是否將斷點放到第二次呼叫之後了呢? 不然你的程式到下 面這一行時: predictedLength = requiredLength; 怎麼看都是0, 因為在上面的程式除了宣告外, 根本沒用到.
LouisLu
一般會員


發表:7
回覆:8
積分:3
註冊:2005-01-31

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-02-16 19:57:56 IP:211.79.xxx.xxx 未訂閱
derrenbol1大大您好:   再次謝謝您的耐心賜教,真的很感激。 剛剛小弟仔細再看了一遍程式,發現其實我的程式碼裡面有這一段敘述,但不知為何在討論區的文章中看不到。 煩請大大救救小弟吧..感謝您..
derrenbol1
中階會員


發表:5
回覆:113
積分:93
註冊:2004-12-09

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-02-16 20:45:18 IP:210.202.xxx.xxx 未訂閱
LouisLu : 那你Port的文章確實怪怪的, 害我以為你的錯誤就是那個, 你有發現 SetupDiEnumDeviceInterfaces也少了個參數嗎? 如果是這樣的話, 那你的程式應該沒有問題才對. 你檢查一下你的GUID 是否"真的"正確. 還有你可以用Regedit.exe來看你所定義的GUID底下真的有 裝置. \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{Your GUID}如果該GUID底下沒裝置的話, 你的程式在列舉裝置時, 會得到NO_MORE_ITEM 這個系統錯誤訊息.
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-02-17 10:07:10 IP:61.66.xxx.xxx 未訂閱
LouisLu你好    你可以參考下面這一個範例 【分享】偵測USB裝置插入哪一個USB Port插槽  http://delphi.ktop.com.tw/topic.php?TOPIC_ID=59211 其中有個問題 但是程式碼中的sizeof(NodeInformation)的長度會算錯 (正確為76,但是我的兩台電腦均為73) 修正方法為 Project->Option->Advanced Compiler->Data Alignment->Byte DeviceDetailData->DevicePath所得到的東西會是下面的形式(舉例) \\?\usb#vid_0123&pid_abcd#6&14e622e5&0&2#{a5dcbf10-6530-11d2-901f-00c04fb951ed} 這樣你就得到Vendor ID, Product ID及OS給的編號(這個是我猜的) 因此你就可以針對特定裝置做控制了
LouisLu
一般會員


發表:7
回覆:8
積分:3
註冊:2005-01-31

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-02-17 10:15:29 IP:211.79.xxx.xxx 未訂閱
感謝derrenbol1大大和blk5743大大:    我在VC中用這一段程式是沒有問題的,而且我的GUID是從VC程式中copy過來的,所以應該是不會有問題。 會不會是在BCB中使用這些DDK的function要有哪些設定或是include檔需要修改呢? 以下是小弟的一些include和define,不知道是不是有問題,請各位大大指點迷津。    還有一個問題,小弟不懂為何各位大大都會 #include "stdafx.h"。 那是什麼作用呢?內容為何呢?    
#include 
#pragma hdrstop    #include "Unit1.h"    #include 
#include 
#include 
#include 
#include     #define ISOUSB_IOCTL_INDEX              0x0000    #define IOCTL_ISOUSB_START_ISO_STREAM  CTL_CODE
               (FILE_DEVICE_UNKNOWN,    \                                                 
                ISOUSB_IOCTL_INDEX   4,  \  //這一行又不見了
                  METHOD_BUFFERED,         \  //這一行又不見了
                  FILE_ANY_ACCESS)            //這一行又不見了
發表人 - LouisLu 於 2005/02/17 10:51:53
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-02-17 13:09:11 IP:61.66.xxx.xxx 未訂閱
引言: 還有一個問題,小弟不懂為何各位大大都會 #include "stdafx.h"。
以下是我之前在別的站看到的 ================================================================ 簡單來說,stdafx.h 和 precompile header 有關。如果你在編譯器環境設定不使用 procompile header 的話,就可以不要理會 stdafx.h/.cpp 這東西。不過對編譯大型的程式來說,使用 precompile header 編譯會比較省時間(precompile header 把常用到的又不常變動的 library source 先預先編譯,就像先預先做成 .lib 一樣,不過 source 有變,precompile header 可以更新) quote: --------------------------------------------------------------------- 原發表者是 Tom 簡單來講,它就是將一些原本我們應該要一個一個 include 的標頭檔, 全部寫在 stdafx.h 內,這樣一來,寫大型的程式就會比較方便! 是不是這樣呢? 還有,這應該只有在用 VC 來寫視窗程式時才會用到吧! 在寫 console 程式時,有沒有可能使用到! 謝謝! --------------------------------------------------------------------- precompile header 和你把所有的標頭檔集中在一個 header 再分別 include 到其他 .cpp 檔是不一樣的。 有些編譯環境讓你指定 precompile header 是哪一個後,你不需要把 precompile header 一一 include 到 .cpp 檔案裡,而編譯環境也只有在 precompile header 裡的內容有變動時才會再編譯出 precompile header output 檔,這和把一個集大成的巨大 header 拿來到處掛上 .cpp 檔是不一樣的。 寫 console mode 時有沒有可能用到 precompile header 是看你,你也可以把常用到的 Standard C Library 的一部份(如 STL)先弄到 precompile header 裡來增加編譯的效率。你不想使用也可以,在 project 設定下可以取消 precompile header 的使用。
LouisLu
一般會員


發表:7
回覆:8
積分:3
註冊:2005-01-31

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-02-17 14:06:32 IP:211.79.xxx.xxx 未訂閱
重複按到 不知道如何刪除此篇 Sorry 發表人 - LouisLu 於 2005/02/17 14:11:25
LouisLu
一般會員


發表:7
回覆:8
積分:3
註冊:2005-01-31

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-02-17 14:07:05 IP:211.79.xxx.xxx 未訂閱
謝謝derrenbol1大大的耐心指導,小弟獲益良多。    也謝謝blk5743大大的指導 Project->Option->Advanced Compiler->Data Alignment->Byte 果然成功地解決我的問題。    萬分感激兩位大大,謝謝你們 
系統時間:2024-05-05 0:55:49
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!