天天看點

usb應用程式

今天需要寫一個類似于DNW的USB下載下傳工具,用來與EBOOT通信傳輸CE的鏡像檔案,從網上找來的DNW源碼編譯生成的DNW無法檢測到USB已經連接配接,分析應該是通過USB驅動的GUID打開裝置導緻的問題,于是想查找secusb2.sys的GUID是多少,找到下邊這篇文章,第2節有相關資訊,通過此方法找到GUID後修改源檔案已經能夠檢查到USB連接配接OK。

作者:skdev

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-5ae3f3ea6e77

DEFINE_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);

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;

}

BOOL GetUsbDeviceFileName( LPGUID pGuid, char *outNameBuf)

{

       HANDLE hDev = OpenUsbDevice( pGuid, outNameBuf );

       if ( hDev != INVALID_HANDLE_VALUE )

       {

              CloseHandle( hDev );

              return TRUE;

       }

       return FALSE;

}

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;

}

int   GetUsbPath(char *path)

{

       if ( !GetUsbDeviceFileName((LPGUID) &GUID_CLASS_I82930_BULK,path) )

       {

              return 0;

       }

       return 1;

}

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;

}

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.aspx

本文來自CSDN部落格,轉載請标明出處:http://blog.csdn.net/Veabol/archive/2010/01/12/5181404.aspx