今天需要寫一個類似于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