Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2349208
  • 博文数量: 816
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 5010
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-17 17:57
文章分类

全部博文(816)

文章存档

2011年(1)

2008年(815)

分类:

2008-12-17 17:59:54

用 VB 太难了, 用 C++ Builder 6.0 还是很简单的, 我在 BCB 6.0 里面编译通过, 没试过其他版本的 BCB
在 Win98/2000/XP/2003 系统下运行都测试通过了
这里的 WinDDK 版本是 Windows Server 2003 DDK, 可以编 Win98/2000/XP/2003 的驱动程序

#include //用 C++ Builder 6.0 访问 USB 驱动程序 -- Victor Chen
#include
#include
#include "C:/WINDDK/3790/inc/ddk/w2k/usbdi.h"
#include "C:/WINDDK/3790/inc/ddk/w2k/devioctl.h"
#include
//---------------------------------------------------------------------------
// 下面必须为驱动程序的 GUID 值, 这里我乱写的数
DEFINE_GUID(USB_DRIVER_GUID, 0x12345678,0xabcd,0x1122,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00);
//---------------------------------------------------------------------------
HANDLE OpenOneDevice(HDEVINFO hDvcInfo, PSP_INTERFACE_DEVICE_DATA DvcInfoData, char *sDevNameBuf)
{
  HANDLE hOut = INVALID_HANDLE_VALUE;

  ULONG  iReqLen = 0;
  SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, NULL, 0, &iReqLen, NULL);

  ULONG iDevDataLen = iReqLen; //sizeof(SP_FNCLASS_DEVICE_DATA) + 512;
  PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iDevDataLen);

  pDevData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
  if(SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, pDevData, iDevDataLen, &iReqLen, NULL))
   {
     strcpy(sDevNameBuf, pDevData->DevicePath);
     hOut = CreateFile(pDevData->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
   }

  free(pDevData);
  return hOut;
}
//---------------------------------------------------------------------------
HANDLE OpenUsbDevice(const GUID *pGuid, char *sDevNameBuf)
{
  HANDLE hOut = INVALID_HANDLE_VALUE;

  HDEVINFO hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);

  SP_INTERFACE_DEVICE_DATA deviceInfoData;
  deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);

  ULONG nGuessCount = MAXLONG;
  for(ULONG iDevIndex=0; iDevIndex   {
     if(SetupDiEnumDeviceInterfaces(hDevInfo, 0, pGuid, iDevIndex, &deviceInfoData))
      {
        if((hOut=OpenOneDevice(hDevInfo, &deviceInfoData, sDevNameBuf)) != INVALID_HANDLE_VALUE)
          break;
      }
     else if(GetLastError() == ERROR_NO_MORE_ITEMS) //No more items
      {
        break;
      }
   }
  SetupDiDestroyDeviceInfoList(hDevInfo);
  return hOut;
}
//---------------------------------------------------------------------------
bool GetUsbDeviceFileName(const GUID *pGuid, char *sDevNameBuf)
{
  HANDLE hDev = OpenUsbDevice(pGuid, sDevNameBuf);
  if(hDev != INVALID_HANDLE_VALUE)
   {
     CloseHandle(hDev);
     return true;
   }
  return false;
}
//---------------------------------------------------------------------------
HANDLE OpenMyDevice()
{
  char DeviceName[MAXPATH] = "";
  return OpenUsbDevice(&USB_DRIVER_GUID, DeviceName);
}
//---------------------------------------------------------------------------
HANDLE OpenMyDevPipe(const char *PipeName)
{
  char DeviceName[MAXPATH] = "";
  if(GetUsbDeviceFileName(&USB_DRIVER_GUID, DeviceName))
   {
     strcat(DeviceName,"\\");
     strcat(DeviceName,PipeName);
     return CreateFile(DeviceName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
   }
  return INVALID_HANDLE_VALUE;
}
//---------------------------------------------------------------------------

--------------------next---------------------
//---------------------------------------------------------------------------
// 下面必须为驱动程序的 GUID 值, 这里我乱写的数
DEFINE_GUID(USB_DRIVER_GUID, 0x12345678,0xabcd,0x1122,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00);
//---------------------------------------------------------------------------


GUID是甚麼呀
嚮導,引導?
是個參數吧
格式是甚麼樣的呢
怎麼這麼多呢


我是個菜鳥
對硬件一竅不通的
是不是這些信息呀
只是感覺有點像哦
#define DEFAULT_VENDOR_ID         0x067B
#define DEFAULT_PRODUCT_ID        0x2303
#define DEFAULT_INTERFACE_NUM     0
#define DEFAULT_ALTERNATE_SETTING 0
#define DEFAULT_LICENSE_STRING    "6C3CC2BFF76637EC556BF9D50D98F518FD244376.kenneth"

--------------------next---------------------
//如果你想打開一個USB管道,你首先要知道這種USB設備的GUID和管理道名稱,
//獲取句柄以后就可以使用ReadFile/WriteFile進行讀寫了﹗
//以下是代碼,請參考﹗﹗

// filename是管道名稱,如pipe01等
int TForm1::open_file( char *filename)
{

 int successOpened = 0,i;
 int NumOpened;
 HANDLE h;
 NumOpened=OpenAllUsbDevices((LPGUID) &GUID_CLASS_I82930_BULK);
    if(NumOpened<=0)
  return 0;
    for(i=0;i        strcat (outnamebuf[i],"\\");

        strcat (outnamebuf[i],filename);


     h= CreateFile(outnamebuf[i],
                  GENERIC_WRITE | GENERIC_READ,
                  FILE_SHARE_WRITE | FILE_SHARE_READ,
                  NULL,
                  OPEN_EXISTING,
                  0,
                  NULL);
     if (h == INVALID_HANDLE_VALUE) {
   handUsbArray[i]=NULL;
  } else {
    handUsbArray[i]=h;
    successOpened++;
  }
 }
 return successOpened;
}


int TForm1::OpenAllUsbDevices(LPGUID pGuid)     //打開所有的GUID為pGuid的USB器件
{                //輸出名存在outnamebuf中
 ULONG NumberDevices;
 HANDLE hOut = INVALID_HANDLE_VALUE;       //HANDLE Phout[8];
 HDEVINFO                 hardwareDeviceInfo;
 SP_INTERFACE_DEVICE_DATA deviceInfoData;
 ULONG                    i,flag=1,j;
 ULONG       NumDevicesOpened=0;
 BOOLEAN                  done;
 PUSB_DEVICE_DESCRIPTOR   usbDeviceInst;
 PUSB_DEVICE_DESCRIPTOR *UsbDevices = &usbDeviceInst;
 char DeviceName[256]="";         //器件名

 *UsbDevices = NULL;
    UsbDevicesOpened = 0;          //打開器件數置零

 hardwareDeviceInfo = SetupDiGetClassDevs (
  pGuid,
  NULL,             // Define no enumerator (global)
  NULL,             // Define no
  (DIGCF_PRESENT |          // Only Devices present
  DIGCF_INTERFACEDEVICE));        // Function class devices.

 NumberDevices = 4;
 done = FALSE;
 deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
 i=0  ;
 while (!done) {
  NumberDevices *= 2;

  if (*UsbDevices) {
   *UsbDevices =
    (struct _USB_DEVICE_DESCRIPTOR *)realloc (*UsbDevices, (NumberDevices *
sizeof (USB_DEVICE_DESCRIPTOR)));
  } else {
   *UsbDevices = (struct _USB_DEVICE_DESCRIPTOR *)calloc (NumberDevices,
sizeof (USB_DEVICE_DESCRIPTOR));
  }

  if (NULL == *UsbDevices) {
   SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
   return 0 ;
  }

  usbDeviceInst = *UsbDevices + i;

  for (; i < NumberDevices; i++) {
   if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
    0,
    pGuid,
    i,
    &deviceInfoData))
   {
    hOut = OpenOneDevice (hardwareDeviceInfo, &deviceInfoData, DeviceName);
    if ( hOut != INVALID_HANDLE_VALUE )
    {
     handUsbArray[UsbDevicesOpened]=hOut;

     if(!outnamebuf[UsbDevicesOpened])
     {
      return 0;
     }
     for(j=0;j<256;j++)
     {
      *(outnamebuf[UsbDevicesOpened]+j)=*(DeviceName+j);
      *(DeviceName+j)=0;
     }
     UsbDevicesOpened++;
    }
   }
   else
   {
    if(ERROR_NO_MORE_ITEMS == GetLastError())
    {
     done = TRUE;
     break;
    }
   }

  }    //end for
 }       //end while
 SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
 free ( *UsbDevices );
 return UsbDevicesOpened ;

 }

//--------------------------------------------------------------------
//
//
//
//--------------------------------------------------------------------
HANDLE TForm1::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;
    SetupDiGetInterfaceDeviceDetail (
            HardwareDeviceInfo,
            DeviceInfoData,
            NULL,            // probing so no output buffer yet
            0,             // probing so output buffer length of zero
            &requiredLength,
            NULL);        

--------------------next---------------------
    predictedLength = requiredLength;

    functionClassDeviceData =(struct _SP_DEVICE_INTERFACE_DETAIL_DATA_A *)
malloc (predictedLength);
    functionClassDeviceData->cbSize = sizeof
(SP_INTERFACE_DEVICE_DETAIL_DATA);

    if (! SetupDiGetInterfaceDeviceDetail (
               HardwareDeviceInfo,
               DeviceInfoData,
               functionClassDeviceData,
               predictedLength,
               &requiredLength,
               NULL)) {
  free( functionClassDeviceData );
        return INVALID_HANDLE_VALUE;
    }

 strcpy( devName,functionClassDeviceData->DevicePath) ;

    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) {

    }
 free( functionClassDeviceData );
 return hOut;
}


--------------------next---------------------
1.USB 设备硬件部分
  a.这个硬件的标识是用的 Vender ID 和 Product ID, 即“厂家标识”和“产品标识”
  b.这个硬件规定了各个 End Point (端点) 的性质, 读/写 及 类型 (Control/Interrupt/Bulk/Isochronous)
  c.这个硬件的固件里面有 DeviceIoControl 的实现部分, 规定了这个函数的具体参数和动作

2.USB 设备驱动
①硬件接口
  a.需要识别 Vender ID 和 Product ID
  b.对每个 EndPoint 的每个 I/O 分配一个 Pipe, 并且起一个名字作为软件接口
  c.做 DeviceIoControl 的接口
②软件接口
  a.GUID, 驱动程序的标识, 每个驱动程序使用不同的 GUID, GUID 是识别驱动的, 与硬件无关 (驱动程序升级版本 GUID 不能修改)
  b.硬件接口里面的 b: Pipe 名字是软件接口, 这个 Pipe 名字纯粹由驱动定义的, 和硬件无关, 升级驱动不能改 Pipe 的名字
  c.硬件接口里面的 c 的各个参数也是软件的接口, 这些参数是由硬件带来的, 不是驱动规定的, 当然也可以在驱动里面转义, 隐藏设备的真实情况
③这个驱动程序是用 WinDDK 编译的, 可以用文本编辑器或其他开发工具的编辑器编程序代码, 然后调用 WinDDK 编译

3.读写 USB 口的程序
①与驱动的接口
  a.利用驱动程序里面的 GUID 找出设备的文件名, 用 CreateFile 函数打开设备。我前面的程序里面的 OpenUsbDevice 就是这个作用
  b.通过 a.得到的设备文件名和驱动程序里面的 Pipe 名打开 Pipe, 访问这个 Pipe 对应的 USB 端点 (读写数据)
  c.使用 a.的 CreateFile 得到的句柄, 通过 DeviceIoControl 实现设备规定的动作
②有关需要的资料
  a.Vender ID, Product ID 和 GUID 一般在驱动程序的 .inf 文件里面能看到, 如果找不到就需要和厂家联系
  b.Pipe 的名字是驱动程序规定的, 需要有驱动程序的资料才能知道
  c.DeviceIoControl 的参数需要有驱动程序的资料或者硬件资料才能知道
③这个程序一般用 C/C++ 直接编写, 如果使用其他语言(VB/PB等)需要调用 C/C++ 编的 DLL

--------------------next---------------------
标题   如何根据驱动程序及其安装文件来访问该设备呢(Visual C++ or C++ Builder均可以)     kingcaiyao [原作]  


 First of all,我要讲一下Windows对每检测到一个新设备的处理过程:
1.首先Windows将各种设备分成不同的设备类,比如说USB Storage存储类设备,而这些类设备都有一个GUID,它们位于注册表中HKEY_LOCAL_MACHINE\ControlSet001\Control\Class下,在这个键下你看到的以128位长度结点名称为结点都是设备类。
2.当检测到一个新设备时,Windows OS就会到KEY_LOCAL_MACHINE\ControlSet001下去搜索,如果此类设备已经注册,那么就此子键下增加一个子键,这个子键的名称是顺序递增的,如果当前该类设备中最大子键名称为0005,那么新设备的就是0006,0000,0001等就是设备的序列号。如果发现这个设备没有注册,那么OS就会以该设备对应的驱动程序安装文件.inf中的ClassGuid为名称来创建一个键,并将此被检测到的设备的序列号为0,在该键下创建一个子键,并且命名为0000来存储该设备的相关信息,之所以命名为0000,因为该设备是该类设备的第一个。
3.有些设备,如我们常用的COM1,COM2,当我们要访问它时可以用CreateFile("COM1"。。。)就可以打开串口,这里的COM1,COM2是符号名,有些设备也用到了符号名,比如说有些USB设备虚拟成一个COM口,如COM3,COM4,COM5等,在程序中我们只需要对COM3,COM4,COM5进行访问,就相当对该设备进行访问。
在没有符号名的情况下,我们如何根据设备驱动程序以及设备安装文件.inf来对设备进行访问呢?我们可以这样:
1.首先,我们在这个设备的符号名中找到设备类的ClassGuid,这是一定可以找到的。
2.然后我们到HKEY_LOCAL_MACHINE\ControlSet001\Control\Class下去找这个设备类,在找到后,我们再找它的子键,找到该设备对应的序列号,如它到底是0000还是0001,在得到这两个数据即ClassGuid和设备序列号后,就好办了。
下面我写一段代码,用来访问我机器上的一USB设备,并在listbox中列出当前机器上此设备类下的所有设备。

extern "C"
{
#include "setupapi.h"
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   //First of all,I will enumurate all the devices under the specified deviceclass
   HKEY m_hKey,m_hSubKey;
   long m_lResult=0;//using for return value
   int m_nKeyIndex=0,m_nValueIndex=0;
   char cKeyName[255],cValue[255];
   unsigned char pbData[255];
   BOOL bOutter=TRUE,bInter=TRUE;
   char *cRoot="SYSTEM\\ControlSet001\\Control\\Class\\{4D36E96D-E325-11CE-BFC1-08002BE10318}";
   AnsiString m_sAttached("");
   m_lResult=::RegOpenKeyEx(HKEY_LOCAL_MACHINE,cRoot,0,KEY_ALL_ACCESS,&m_hKey);
   if(m_lResult!=ERROR_SUCCESS) return FALSE;
   //Enum Keys
   while(bOutter){
   m_lResult=::RegEnumKey(m_hKey,m_nKeyIndex,cKeyName,255);
   bInter=TRUE;
   if(m_lResult!=ERROR_SUCCESS) bOutter=FALSE;
   else{
   m_lResult=::RegOpenKeyEx(m_hKey,cKeyName,0,KEY_ALL_ACCESS,&m_hSubKey);
   if(m_lResult!=ERROR_SUCCESS){
   ::RegCloseKey(m_hKey);
   return FALSE;}
   while(bInter){
   unsigned long m_nDataSize=255;
   unsigned long m_nValueNameSize=255;
   unsigned long m_nType;
   m_lResult=::RegEnumValue(m_hSubKey,m_nValueIndex,cValue,&m_nValueNameSize,0,&m_nType,pbData,&m_nDataSize);
   if(m_lResult!=ERROR_SUCCESS)  bInter=FALSE;
    else{
     if(!strcmp(cValue,"AttachedTo")){
      m_sAttached=(AnsiString)(char*)pbData;
     }
     if(!strcmp(cValue,"DriverDesc")){
      m_lstDevice->Items->Add((AnsiString)(char*)pbData+"  "+m_sAttached);
     }
     m_nValueIndex++;
    }
   }
   m_nValueIndex=0;
   m_nKeyIndex++;
   
  }
 }
 ::RegCloseKey(m_hKey);
 ::RegCloseKey(m_hSubKey);
   
  file://Next/ Step,I will access one of the device.I know its device serialno:0001
  DWORD ReqLength;
  DWORD Flags=DIGCF_PRESENT|DIGCF_DEVICEINTERFACE;
  GUID CardGuid={4D36E96D-E325-11CE-BFC1-08002BE10318};
  HANDLE hCard=0;
  PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceDetailData;
     SP_DEVICE_INTERFACE_DATA        DeviceInterfaceData;
     DeviceInterfaceData.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
     hCard=SetupDiGetClassDevs(&CardGuid,NULL,NULL,Flags);
     if(hCard==INVALID_HANDLE_VALUE){
     ::MessageBox(0,"Invalid Parameters!","Error",MB_OK|MB_ICONERROR);
         return;}
     BOOL status=SetupDiEnumDeviceInterfaces(hCard,NULL,&CardGuid,Index,&DeviceInterfaceData,&ReqLength,
 NULL);//Index即设备的序号,这里的Index为1.
 if(!status){
  ::MessageBox(0,"Failed to enumurate the specified
 device!","Error",MB_OK+MB_ICONERROR);
         ::CloseHandle(hCard);
         return;}
 SetupDiGetInterfaceDeviceDetail(hCard,&DeviceInterfaceData,NULL,0,&ReqLength,NULL);
 DeviceDetailData=(PSP_INTERFACE_DEVICE_DETAIL_DATA)new char[ReqLength];
 if(DeviceDetailData){
  ::MessageBox("ERROR NOT ENOUGH MEMORY!","Error",MB_OK+MB_ICONERROR);
         ::CloseHandle(hCard);
         return;}
         status=SetupDiGetInterfaceDeviceDetail(hCard,&DeviceInterfaceData,DeviceDetailD

--------------------next---------------------
我用的是CY7C68013芯片,想用其自带的驱动(我还不会写驱动:)),不知道如何解决以上问题,我用Overlaped试过好像不行,可能我的程序有错。我的程序的要求是这样的:我和三方进行通讯,分别用串口、网口、usb,我的程序每秒分别主动读取usb口、串口中的数据,然后将其处理后的部分数据用网口发送出去,串口和usb口的数据不定长,且数据量很大,usb口每秒最多会有256KB的数据,也有可能没有数据,请问我在程序中如何处理,(读usb时我曾经开过线程,太占Cpu资源,另外当串口收数据时,读usb数据时很慢,这也导致对方发过来的数据大量丢包,而且对方不发usb数据时又会导致进程死锁),哎,这么多问题,我该怎么办呢?能不能知道FIFO中有数据而且知道有多少数据,然后再去读?

--------------------next---------------------

阅读(1993) | 评论(0) | 转发(0) |
0

上一篇:C++爱好者

下一篇:C++爱好者 - 网友留言

给主人留下些什么吧!~~