USB應用程式開發

來源:互聯網
上載者:User
 

1 前言USB開發跟其他檔案裝置(如串口)開發一樣,痛點是找到該USB裝置的路徑,本文以DDK裡src/usb/bulkusb例子為參考,闡述一個非HID的USB調試器軟體的開發過程。2 裝置GUID一般裝置會有兩個GUID, 一個為Class GUID, 在INF檔案中,另一個為Device GUID,在SYS檔案中。 CreateFile使用的是SYS中的GUID,想得到它有兩個辦法: 1 跟裝置的提供者索要。 2在註冊表裡找,一般在:HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Control/DeviceClasses/3 裝置路徑根據裝置GUID,枚舉所有USB HOST,找匹配的USB裝置,然後擷取其路徑。3.1 標頭檔 usbport.h#define WINVER 0x0500#include <windows.h>#include <setupapi.h>#include <basetyps.h>#include <usbdi.h>#include <initguid.h>#include <stdio.h> #pragma comment(lib,"setupapi.lib")#pragma comment(lib,"hid.lib")#pragma comment(lib,"comctl32.lib") #ifndef BULKUSBH_INC#define BULKUSBH_INC #define BULKUSB_IOCTL_INDEX 0x0000  #define IOCTL_BULKUSB_GET_CONFIG_DESCRIPTOR     CTL_CODE(FILE_DEVICE_UNKNOWN, /                                                   BULKUSB_IOCTL_INDEX,/                                                   METHOD_BUFFERED, /                                                   FILE_ANY_ACCESS)                                                   #define IOCTL_BULKUSB_RESET_DEVICE   CTL_CODE(FILE_DEVICE_UNKNOWN, /                                                   BULKUSB_IOCTL_INDEX+1,/                                                   METHOD_BUFFERED, /                                                   FILE_ANY_ACCESS)                                                                                                                 #define IOCTL_BULKUSB_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, /                                                   BULKUSB_IOCTL_INDEX+2,/                                                   METHOD_BUFFERED, /                                                   FILE_ANY_ACCESS)             extern HANDLE            open_file(char *filename);extern int               GetUsbPath(char *path);extern int               WriteUsb(HANDLE hUsb,char *Outbuff, int len);extern int               ReadUsb(HANDLE hUsb,BYTE inbuff[],DWORD &nBytesRead,int nToRead);3.2 源檔案 usbport.cpp#include "usbport.h" //8a3bf75d-83c7-440e-8276-5ae3f3ea6e77DEFINE_GUID(GUID_CLASS_I82930_BULK,0x8a3bf75d, 0x83c7, 0x440e,0x82, 0x76, 0x5a, 0xe3, 0xf3, 0xea, 0x6e, 0x77); BOOL            GetUsbDeviceFileName( LPGUID pGuid, char *outNameBuf);HANDLE        OpenUsbDevice( LPGUID pGuid, char *outNameBuf);HANDLE        OpenOneDevice (HDEVINFO HardwareDeviceInfo, PSP_INTERFACE_DEVICE_DATA   DeviceInfoData,char *devName);int                  GetUsbPath(char *path);int                  WriteUsb(HANDLE hUsb,char *Outbuff, int len);int                  ReadUsb(HANDLE hUsb,BYTE inbuff[], DWORD &nBytesRead,int nToRead); /*名稱:open_file 功能:開啟USB裝置 參數:filename 定義為”PIPE00” pipe name for bulk input pipe on our test board ,”PIPE01” pipe name for bulk output pipe on our test board。PIPE00 和 PIPE01 是參考src/usb/bulkusb,我實際在用時這兩個效果一樣,為了避免USB異常引起的死機,我檔案開啟採用非阻塞模式。*/HANDLE open_file( char *filename){        int success = 1;       HANDLE h;       char completeDeviceName[256] = ""; //generated from the GUID registered by the driver itself        if ( !GetUsbDeviceFileName((LPGUID) &GUID_CLASS_I82930_BULK,completeDeviceName) )       {              //NOISY(("Failed to GetUsbDeviceFileName/n", GetLastError()));              return INVALID_HANDLE_VALUE;       }     strcat (completeDeviceName,       "//");                          strcat (completeDeviceName,       filename);                                           //printf("completeDeviceName = (%s)/n", completeDeviceName);        h = CreateFile(completeDeviceName,              GENERIC_WRITE | GENERIC_READ,              FILE_SHARE_WRITE | FILE_SHARE_READ,              NULL,              OPEN_EXISTING,              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,              NULL);        if (h == INVALID_HANDLE_VALUE) {              //NOISY(("Failed to open (%s) = %d", completeDeviceName, GetLastError()));              success = 0;       } else {                     //NOISY(("Opened successfully./n"));    }                    return h;}/*名稱:GetUsbDeviceFileName 功能:擷取USB裝置路徑 參數:pGUID 返回:outNameBuf USB裝置路徑*/BOOL GetUsbDeviceFileName( LPGUID pGuid, char *outNameBuf){       HANDLE hDev = OpenUsbDevice( pGuid, outNameBuf );       if ( hDev != INVALID_HANDLE_VALUE )       {              CloseHandle( hDev );              return TRUE;       }       return FALSE; }/*名稱:OpenUsbDevice 功能:擷取USB裝置路徑 參數:pGUID 裝置GUID 返回:outNameBuf USB裝置路徑*/HANDLE OpenUsbDevice( LPGUID pGuid, char *outNameBuf){   ULONG NumberDevices;   HANDLE hOut = INVALID_HANDLE_VALUE;   HDEVINFO                 hardwareDeviceInfo;   SP_INTERFACE_DEVICE_DATA deviceInfoData;   ULONG                    i;   BOOLEAN                  done;   PUSB_DEVICE_DESCRIPTOR   usbDeviceInst;   PUSB_DEVICE_DESCRIPTOR   *UsbDevices = &usbDeviceInst;    *UsbDevices = NULL;   NumberDevices = 0;    //   // Open a handle to the plug and play dev node.   // SetupDiGetClassDevs() returns a device information set that contains info on all   // installed devices of a specified class.   //   hardwareDeviceInfo = SetupDiGetClassDevs (                           pGuid,                           NULL, // Define no enumerator (global)                           NULL, // Define no                           (DIGCF_PRESENT | // Only Devices present                            DIGCF_INTERFACEDEVICE)); // Function class devices.    //   // Take a wild guess at the number of devices we have;   // Be prepared to realloc and retry if there are more than we guessed   //   NumberDevices = 4;   done = FALSE;   deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);    i=0;   while (!done)    {      NumberDevices *= 2;       if (*UsbDevices)         {         *UsbDevices = (PUSB_DEVICE_DESCRIPTOR)realloc (*UsbDevices, (NumberDevices * sizeof (USB_DEVICE_DESCRIPTOR)));      }         else         {         *UsbDevices = (PUSB_DEVICE_DESCRIPTOR)calloc (NumberDevices, sizeof (USB_DEVICE_DESCRIPTOR));      }       if (NULL == *UsbDevices)         {          // SetupDiDestroyDeviceInfoList destroys a device information set         // and frees all associated memory.          SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);         return INVALID_HANDLE_VALUE;      }       usbDeviceInst = *UsbDevices + i;       for (; i < NumberDevices; i++)         {          // SetupDiEnumDeviceInterfaces() returns information about device interfaces         // exposed by one or more devices. Each call returns information about one interface;         // the routine can be called repeatedly to get information about several interfaces         // exposed by one or more devices.          if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,                                         0, // We don't care about specific PDOs                                                                       pGuid,                                         i,                                         &deviceInfoData)) {             hOut = OpenOneDevice (hardwareDeviceInfo, &deviceInfoData, outNameBuf);                     if ( hOut != INVALID_HANDLE_VALUE )                      {               done = TRUE;               break;                     }         }                else                {            if (ERROR_NO_MORE_ITEMS == GetLastError())                      {               done = TRUE;               break;            }         }      }   }    NumberDevices = i;    // SetupDiDestroyDeviceInfoList() destroys a device information set   // and frees all associated memory.    SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);   free ( *UsbDevices );   return hOut;}HANDLE OpenOneDevice (    IN       HDEVINFO                    HardwareDeviceInfo,    IN       PSP_INTERFACE_DEVICE_DATA   DeviceInfoData,       IN          char *devName    ){    PSP_INTERFACE_DEVICE_DETAIL_DATA     functionClassDeviceData = NULL;    ULONG                                predictedLength = 0;    ULONG                                requiredLength = 0;       HANDLE                                                        hOut = INVALID_HANDLE_VALUE;     //    // allocate a function class device data structure to receive the    // goods about this particular device.    //    SetupDiGetInterfaceDeviceDetail (            HardwareDeviceInfo,            DeviceInfoData,            NULL, // probing so no output buffer yet            0, // probing so output buffer length of zero            &requiredLength,            NULL); // not interested in the specific dev-node      predictedLength = requiredLength;    // sizeof (SP_FNCLASS_DEVICE_DATA) + 512;     functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc (predictedLength);    functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA);     //    // Retrieve the information from Plug and Play.    //    if (! SetupDiGetInterfaceDeviceDetail (               HardwareDeviceInfo,               DeviceInfoData,               functionClassDeviceData,               predictedLength,               &requiredLength,               NULL)) {              free( functionClassDeviceData );        return INVALID_HANDLE_VALUE;    }        strcpy( devName,functionClassDeviceData->DevicePath) ;       //printf( "Attempting to open %s/n", devName );     hOut = CreateFile (                  functionClassDeviceData->DevicePath,                  GENERIC_READ | GENERIC_WRITE,                  FILE_SHARE_READ | FILE_SHARE_WRITE,                  NULL, // no SECURITY_ATTRIBUTES structure                  OPEN_EXISTING, // No special create flags                  0, // No special attributes                  NULL); // No template file     if (INVALID_HANDLE_VALUE == hOut)        {              //printf( "FAILED to open %s/n", devName );    }       free( functionClassDeviceData );       return hOut;}/*名稱:GetUsbPath 功能:返回USB裝置路徑 參數:pGUID 返回:path 路徑*/int   GetUsbPath(char *path){       if ( !GetUsbDeviceFileName((LPGUID) &GUID_CLASS_I82930_BULK,path) )       {              return 0;       }       return 1;}/*名稱:WriteUsb 功能:向USB寫資料 參數:hUsb USB控制代碼,Outbut 資料指標,len 資料長度*/int WriteUsb(HANDLE hUsb,char *Outbuff, int len){    DWORD nBytesWrite,endtime,lrc;    static OVERLAPPED ol;    DWORD dwErrorMask,dwError;    COMSTAT comstat;       if(hUsb==NULL)              return 0;    ol.Offset=0; //裝置使用指定0                ol.OffsetHigh=0; //裝置使用指定0    ol.hEvent=NULL;   //標識事件為非訊號狀態,資料傳送完成時,它將被設為訊號狀態       ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);        if(!WriteFile(hUsb,Outbuff,len,&nBytesWrite,&ol))     {       //出錯資訊處理--------------------------------        if((lrc=GetLastError())==ERROR_IO_PENDING)        {           endtime=GetTickCount()+1000;            while(!GetOverlappedResult(hUsb,&ol,&nBytesWrite,FALSE))            {                   dwError=GetLastError();                if(GetTickCount()>endtime)                {                        MessageBox(NULL,"寫串口時間過長,目前串口發送緩衝區中的資料數目為空白",NULL,NULL);                    break;                }                if(dwError=ERROR_IO_INCOMPLETE)                     continue;          //未完全讀完時的正常返回結果                else                {                    //    發生錯誤,嘗試恢複!                                        break;                }            }        }        //-------------------------------------------------//              }           CloseHandle(ol.hEvent);    FlushFileBuffers(hUsb);        return 1;}/*名稱:ReadUsb 功能:讀取USB裝置發來的資料 參數:hUsb USB控制代碼,nToRead讀取的長度 返回:inbuff 讀到的資料,nBytesRead 讀到的長度*/int ReadUsb(HANDLE hUsb,BYTE inbuff[], DWORD &nBytesRead,int nToRead){    DWORD lrc;                                 ///縱向冗餘校正    DWORD endtime;                            /////////jiesuo    static OVERLAPPED ol;    int ReadNumber=0;        int numCount=0 ;                             //控制讀取的數目    DWORD dwErrorMask;             DWORD dwEvtMask=0 ;        DWORD      ntoread;       int          ReadTime;     ReadTime=2000;    ntoread=nToRead;       ol.Offset=0;                            ///相對檔案開始的位元組位移量    ol.OffsetHigh=0;                        ///開始傳送資料的位元組位移量的高位字,管道和通訊時調用進程可忽略。    ol.hEvent=NULL;                         ///標識事件,資料傳送完成時設為訊號狀態    ol.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);     if(!ReadFile(hUsb,inbuff,ntoread,&nBytesRead,&ol))    {            if((lrc=GetLastError())==ERROR_IO_PENDING)        {            ///////////////////            endtime=GetTickCount()+ReadTime;//GetTickCount()取回系統開始至此所用的時間(毫秒)            while(!GetOverlappedResult(hUsb,&ol,&nBytesRead,FALSE))//該函數取回重疊操作的結果            {                if(GetTickCount()>endtime)                    break;            }            }            }            CloseHandle(ol.hEvent);    return 1;     }4 編譯前提開發USB程式,需要下載Microsotft的DDK(DRIVER DEVELOP KIT)庫,該庫的配置請參考http://blog.csdn.net/skdev/archive/2007/01/26/1494635.aspx5 效果 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.