最近在做毕设,一个U盾相关的题目。需要用到USB2.0协议,实现PC和一个硬件平台通信。硬件平台的USB驱动使用内置的函数就可以完成,但PC端的驱动,比较让人头疼,因为没接触过Windows下的驱动开发。通过查找相关的USB资料,发现了libusb可以实现USB的无驱化设计。于是,打算配置相关的库。在网上找到了相关的库文件libusb-win32。我下载的文件是libusb-win32-bin-1.2.6.0.zip。将该文件解压缩,会得到几个文件。

images1

       首先是bin文件夹,该文件夹中的inf-wizard.exe是设备第一次连接PC时,需要通过该应用程序安装一些文件。打开该应用程序,找到自己的设备(通过两个ID确定是哪个设备,我的是0x1122 0x3344),点击下一步,然后保存信息,最后安装。这样当自己编写libusb-win32代码时就可以找到该设备。

images1

       其次是include和lib文件夹,工程配置时需要用到,我是在code::blocks下进行代码的编写。建立好工程后,依次点击Project -> Properties ->Project Build options->Linker settings。然后点击Add添加库,添加lib文件夹下的gcc中(需要根据你的编译器类型选择)的libusb.a。并且 将include文件夹下的libusb0_usb.h头文件复制到工程中。这样就配置成功,接着就可以编写代码了。

images1

       当完成配置工作后,就可以进行代码的编写(需要了解一些基本的USB协议的知识)。对于一个库的使用,其帮助文档是非常重要的,可以去找libusb-win32开发文档

       接下来分析一下使用bulk进行数据传输的代码。

       编写代码时,首先要确定IDVendor和IDProduct,接着要确定bulk端点的输入输出的端口EP_IN和EP_OUT(PC端与USB设备是相反的):

#define IDVendor        0x1122
#define IDProduct       0x3344
#define EP_OUT          0x04
#define EP_IN           0x83
#define MY_CONFIG      0x01
#define MY_INT          0x00
#define BUFFER_SIZE     64            

        接着是初始化,以及查找自己的设备:

struct usb_bus *bus;
struct usb_device *dev;
struct usb_dev_handle *hdev;
int ret = 0;
char buffer2[BUFFER_SIZE] = "USBKEY by libusb-win32";

usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
     for (dev = bus->devices; dev; dev = dev->next) {
               if (dev->descriptor.idVendor == IDVendor 
                   && dev->descriptor.idProduct == IDProduct) {
          /*
                **
                */
      }
   }
}

       通过idVendor和idProduct找到自己的设备之后就可以打开设备,得到一个设备的句柄hdev,通过该句柄就可以进行传输控制等操作了:

hdev = usb_open(dev);
if (hdev == NULL) {
     printf("open error!\n");
     return 1;
}

       要进行数据的传输,必须先调用下面两个函数,进行配置和注册(可以查看帮助文档了解到):

if (usb_set_configuration(hdev, MY_CONFIG) < 0) {
  printf("error setting config #%d: %s", MY_CONFIG, usb_strerror());
  return 1;
}
if (usb_claim_interface(hdev, MY_INT) < 0) {
  printf("error claiming interface #%d:\n%s", MY_INT, usb_strerror());
  return 1;
}

       其中MY_CONFIG和MY_INT分别由descriptor 中的 bConfigurationValue字段和 descriptor 中的bInterfaceNumber(关于这两个字段在USB协议中有介绍)。

       接着就可以使用函数进行bulk端点读写操作:

ret = usb_bulk_write(hdev,EP_OUT,buffer2,BUFFER_SIZE,1000);
if (ret < 0) {
       printf("ret = %d\n",ret);
       printf("write error: %s\n",usb_strerror()); 
} else {
         printf("SED: %d\n",ret);
         printf("SED: %s\n",buffer2);
}
ret = usb_bulk_read(hdev,EP_IN,buffer2,BUFFER_SIZE,1000);
if (ret < 0) {
        printf("ret = %d\n",ret);        
        printf("read error: %s\n",usb_strerror());
} else {        
        printf("REC: %d\n",ret);
        printf("REC: %s\n",buffer2);
}
ret = usb_bulk_read(hdev,EP_IN,buffer2,BUFFER_SIZE,1000);
if (ret < 0) {
         printf("ret = %d\n",ret);         
         printf("read error: %s\n",usb_strerror());
} else {
         printf("REC: %d\n",ret);         
         printf("REC: %s\n",buffer2);
}

       读写结束后关闭设备:

    usb_close(hdev);

       USB硬件设备的部分代码:

unsigned char buffer[BUFFER_SIZE];
USB_Init();
while (1) {
  USB_Bulk_Gets( buffer, 64 );
  USB_Bulk_Puts( buffer, 64 );
  USB_Bulk_Puts( "USBKEY IN A980", 64 );
}

       程序运行结果:

images1