Windows USB 編程

GUIDhtml

#include <initguid.h> // For DEFINE_GUID算法

// Device Interface GUID.
DEFINE_GUID(GUID_DEVINTERFACE_FOR_D3XX,
            0xd1e8fe6a, 0xab75, 0x4d9e, 0x97, 0xd2, 0x6, 0xfa, 0x22, 0xc7, 0x73, 0x6c);
GUID DeviceGUID[2] = {0};
GUID是經過特定算法產生的一個二進制長度爲128位的數字,在空間上和時間上具備惟一性,保證同一時間不一樣地方產生的數字不一樣。GUID的主要目的是產生徹底惟一的數字。在理想狀況下,任何計算機和計算機集羣都不會生成兩個相同的GUID。隨機生成兩個相同GUID的可能性是很是小的,但並不爲0。
  用了DEFINE_GUID,你可使用在全部源文件中包含同一個頭文件,在頭文件中這樣定義GUID:DEFINE_GUID(CLSID_MyObject,0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
  在沒有包含Initguid.h的地方,DEFINE_GUID宏建立外部引用來使用GUID值,在包含Initguid.h的地方,DEFINE_GUID重定義DEFINE_GUID宏以產生GUID的定義。安全

typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
memcpy()服務器

#include<string.h>
// Open a device handle by GUID
memcpy(&DeviceGUID[0], &GUID_DEVINTERFACE_FOR_D3XX, sizeof(GUID));
函數原型:void memcpy( voiddest, const void *src, size_t n );
函數功能:由src指向地址爲起始地址的連續n個字節的數據複製到以destin指向地址爲起始地址的空間內。
返回值: 函數返回一個指向dest的指針。數據結構

主要目的是,使用GUID惟一標識USB設備,並把打開USB設備的句柄存儲到GUID的數據結構中。多線程

memcmp()app

#include<string.h>
//Compare bytes read with bytes written
memcmp(acWriteBuf, acReadBuf, sizeof(acReadBuf));
函數原型: int memcmp(const void *str1, const void *str2, size_t n)) ;
函數功能:把存儲區 str1 和存儲區 str2 的前 n 個字節進行比較。
返回值: 若是返回值 < 0,則表示 str1 小於 str2。若是返回值 > 0,則表示 str2 小於 str1。若是返回值 = 0,則表示 str1 等於 str2。異步

isprint()async

#include <ctype.h>
if (!isprint(pManufacturer[i]))
    return FALSE;
函數原型:int isprint( int c );
函數功能:檢查所傳的字符是不是可打印的,可打印字符是非控制字符的字符。
返回值: 若是 c 是一個可打印的字符,則該函數返回非零值(true),不然返回 0(false)。
主要目的是,檢驗輸入的參數是否正確。函數

OVERLAPPED

功能做用:Overlapped I/O的設計的目的:取代多線程功能(多線程存在同步機制,線程上下文切換是十分消耗CPU資源的)。Overlapped I/O模型是OS爲你傳遞數據,完成上下文切換,在處理完以後通知你。由程序自己的處理,變爲OS的處理(內部也是用線程處理的)。也就是說程序運行的同時,系統再開闢一個I/O操做的新線程,I/O操做的時間和線程執行其它任務的時間是重疊(OVERLAPPED)的。


// Create the overlapped io event for asynchronous transfer
    OVERLAPPED vOverlappedWrite = {0};
    vOverlappedWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
// Write asynchronously
// When FT_WritePipe is called with overlapped io,
// the function will immediately return with FT_IO_PENDING
    ftStatus = FT_WritePipe(ftHandle, 0x02, acWriteBuf, ulBytesToWrite, &ulBytesWritten, &vOverlappedWrite);
                if (ftStatus == FT_IO_PENDING)
            {
                // Poll until all data requested ulBytesToWrite is sent
                do
                {
                    // FT_GetOverlappedResult will return FT_IO_INCOMPLETE if not yet finish
                    ftStatus = FT_GetOverlappedResult(ftHandle, &vOverlappedWrite, &ulBytesWritten, FALSE);
                    if (ftStatus == FT_IO_INCOMPLETE)
                    {
                        continue;
                    }
                    else if (FT_FAILED(ftStatus))
                    {
                        CloseHandle(vOverlappedWrite.hEvent);
                        FT_Close(ftHandle);
                        return FALSE;
                    }
                    else //if (ftStatus == FT_OK)
                    {
                        // exit now
                        break;
                    }
                }
                while (1);
            }
            // Delete the overlapped io event
            CloseHandle(vOverlappedWrite.hEvent);
程序解讀:
  由於 FT_WritePipe()是同步阻塞操做,若是要作到異步寫操做,就要用到 vOverlapped parameter。
  CreateEvent() 建立事件對象,指定該內核對象是自動重置的(FALSE)。而且指定該內核對象起始狀態是未通知狀態的(FALSE)。
  當 FT_WritePipe() 用 overlapped IO 調用時,會當即返回 FT_IO_PENDING 。
  進入循環的做用是判斷寫操做是否完成。經過 FT_GetOverlappedResult() 檢測寫操做是否完成,若未完成則返回 FT_IO_INCOMPLETE ;寫操做線程繼續,同時檢測線程檢測。
  最後關閉事件對象。
  你能夠這樣認爲重疊IO,如今你已經進入一個服務器/客戶機環境,請不要混淆概念,這裏的服務器是指操做系統,而客戶機是指你的程序(它進行IO操做),是當你進行IO操做(send,recv,writefile,readfile….)時你發送一個IO請求給服務器(操做系統),由服務器來完成你須要的操做,而後你什麼事都沒有了(有點像開闢新線程),當服務器完成IO請求時它會通知你,固然在這期間你能夠作任何事,一個經常使用的技巧是在發送重疊IO請求後,程序在一個循環中一邊調用PeekMessage,TranslateMessage和DispatchMessage更新界面,同時調用 GetOverlappedResult等待服務器完成IO操做,更高效一點的作法是使用IO完成例程來處理服務器(操做系統)返回的結果,但並非每一個支持重疊IO操做的函數都支持完成例程如TransmitFile函數.

OVERLAPPED 數據結構:

typedef struct _OVERLAPPED {
  DWORD Internal; //一般被保留,當GetOverlappedResult()傳回False而且GatLastError()並不是傳回ERROR_IO_PENDINO時,該狀態置爲系統定的狀態。
  DWORD InternalHigh; //一般被保留,當GetOverlappedResult()傳回False時,爲被傳輸數據的長度。
  DWORD Offset; //指定文件的位置,從該位置傳送數據,文件位置是相對文件開始處的字節偏移量。調用 ReadFile或WriteFile函數以前調用進程設置這個成員,讀寫命名管道及通訊設備時調用進程忽略這個成員;
  DWORD OffsetHigh; //指定開始傳送數據的字節偏移量的高位字,讀寫命名管道及通訊設備時調用進程忽略這個成員;
  HANDLE hEvent; //標識事件,數據傳送完成時把它設爲信號狀態,調用ReadFil,eWriteFile,ConnectNamedPipe TransactNamedPipe函數前,調用進程設置這個成員. 相關函數CreateEvent ResetEvent GetOverlappedResult WaitForSingleObject CWinThread GetLastError
} OVERLAPPED, *LPOVERLAPPED;
CreateEvent 數據結構:

HANDLE CreateEvent(
PSECURITY_ATTRIBUTES psa,
BOOL bManualReset,
BOOL bInitialState,
PCTSTR pszName);
第一個參數:是安全描述符,設爲NULL表示使用默認的安全描述符,而且子進程沒法繼承返回的句柄。
  第二個參數:指定了該內核對象是人工重置(傳遞TRUE)的仍是自動重置(傳遞FALSE)的。
  第三個參數:指定了該內核對象起始狀態是已通知(傳遞TRUE)仍是未通知狀態(FALSE)。
  第四個參數:爲要建立的事件內核對象起一個名字,若是傳遞NULL,則建立一個「匿名」的事件內核對象。若是不傳遞NULL,且系統中已經存在該名字的事件內核對象,則不建立新的事件內核對象而是打開這個已經存在的,返回它的句柄。
  該函數若是成功,返回事件內核對象的句柄,這樣就能夠操縱它了。若是失敗,返回NULL。

事件內核對象(hEvent):
  事件內核對象最一般的用途是:讓一個線程執行初始化工做,而後觸發另外一個線程,讓它執行剩餘的工做,一開始的時候咱們將事件初始化爲未觸發狀態,而後當線程完成初始化工做的時候觸發事件。
  一個事件內核對象的觸發表示一個操做已經完成。有兩種類型的事件內核對象:手動重置事件和自動重置事件。
當一個手動重置對象被觸發的時候,正在等待該事件的全部線程都將變成可調度狀態。而當一個自動重置事件被觸發時,只有一個正在等待該事件的線程會變成可調度狀態。
  對同一個文件handle,系統有多個異步操做時(一邊讀文件頭,一邊寫文件尾, 有一個完成,就會有信號,不能區分是那種操做。),爲每一個進行中的overlapped調用GetOverlappedResult是很差的做法。

SetEvent設置事件爲觸發狀態,ResetEvent設置事件爲未觸發狀態。

句柄必定要關閉,經過CloseHandle。

C++ 中_In_ 和_out_

__ In__ 代表定義的變量或參數是做爲輸入,即須要給這個參數賦值,傳遞給某個函數去執行;

__ out__ 代表定義的變量或參數是做爲輸出,即須要給該參數一個地址,函數內部往這個地址寫數據;

//////////////////////////////////////////////////////////////////
// Setting of chip configuration ( enables/disables streaming mode )
//////////////////////////////////////////////////////////////////
BOOL StartStreamPipe(
        FT_HANDLE ftHandle,
// _In_ : it's macro definition, need assign a value to parameter
           _In_  UCHAR a_ucPipeID,
           _In_  ULONG a_ulStreamSize
    )
{
    return FT_SetStreamPipe(ftHandle,
            FALSE,
            FALSE,
            a_ucPipeID,
            a_ulStreamSize
    ) == FT_OK ? TRUE : FALSE;
}

 

https://www.cnblogs.com/leon19870907/archive/2011/09/23/2186291.html

https://www.jianshu.com/p/3afc1eb5bd32

https://www.jianshu.com/p/cf8e7df5ff09

https://www.jianshu.com/p/2a6e22194cd3

相關文章
相關標籤/搜索