關鍵詞: libusb, bulk批量傳輸, 上位機軟體.

公司的一個專案中負責USB驅動SDK設計, 做一個USB上位機軟體, 要求使用的傳輸方式是bulk傳輸. 以前從沒接觸過這方面的東西, 可以說完全是個外行, 到現在為止搞了將近一個月, 總算出來了那麼一點成果. 在這裡, 總結分享一下.

~>USB上位機程式的編寫

      1.下載libusb-win32的專案原始碼(libusb-win32-bin-1.2.6.0), 裡面包含.lib庫和.h標頭檔案, 以及inf-wizard.exe和testlibusb-win.exe.

  1. 在PC端插上USB裝置後, 執行inf-wizard.exe, 即可自動生成.inf 驅動檔案, 不用自己編寫驅動, 就可完成驅動的安裝.
  2. 執行testlibusb-win.exe, 即可檢視裝置的資訊, 包括: VID/PID,以及各種描述符, 端點地址Endpoint Address, 最大包的大小MaxPacketSize.
  3. 程式程式碼中加入 : #include "lusb0_usb.h"       以及      #pragma comment(lib, "libusb.lib")          //即可呼叫libusb的函式
  1. 函式的呼叫過程.

          1) 呼叫 void usb_init(void); 進行初始化

          2) 呼叫usb_find_busses、usb_find_devices和usb_get_busses這三個函式,獲得已找到的USB匯流排序列;然後通過連結串列遍歷所有的USB裝置,根據已知的要開啟USB裝置的ID(VID/PID),找到相應的USB裝置.

          3) 呼叫usb_open函式開啟該USB裝置

          4) usb_set_configuration(m_dev_handle, 1)   //設定配置 

        intint usb_claim_interface(usb_dev_handle *dev, int interface);   

         註冊與作業系統通訊的介面,這個函式必須被呼叫,因為只有註冊介面,才能做相應的操作。

          5)與USB裝置進行通訊。使用函式

        int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);//批量寫入

        int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);//批量讀取

           從USB裝置讀取(接收)資料或向其寫入(傳送)資料。

          6) int usb_release_interface(usb_dev_handle *dev, int interface);

          登出被usb_claim_interface函式呼叫後的介面,釋放資源,和usb_claim_interface對應使用。

          8)  int usb_close(usb_dev_handle *dev);

          與usb_open相對應,關閉裝置,是必須呼叫的, 返回0成功,<0 失敗。

附上最簡單的win32控制檯程式的程式碼:(配合Bus Hound執行起來更直觀).

#include <stdio.h> 
#include <string.h> 
#include <iostream>
#include "conio.h"
#include "lusb0_usb.h"
#pragma comment(lib, "libusb.lib")

#define m_dev_VID	0x1483        /* Vendor ID of the m_dev         */ 
#define m_dev_PID	0x5751        /* Product ID of the m_dev        */ 
#define EP1_OUT_SIZE	63	      //可根據裝置修改大小
#define EP1_IN_SIZE	63

int main(int argc, char *argv[]) 
{  
        struct usb_device * m_dev = NULL; 
        struct usb_dev_handle *m_dev_handle; 
        char str[64];
	memset(str,0,sizeof(str));

        usb_init(); 
        usb_find_busses(); 
        usb_find_devices(); 
        
	struct usb_bus *bus; 
        for(bus = usb_get_busses(); bus; bus = bus->next) 
        { 
                struct usb_device *dev; 
                for(dev = bus->devices; dev; dev = dev->next) 
                { 
                        if(dev->descriptor.idVendor == m_dev_VID && dev->descriptor.idProduct == m_dev_PID) 
                        m_dev=dev; 
                } 
        } 
        if(!m_dev) 
        { 
                printf("m_dev not found\n"); 
                return 1; 
        } 
  
        m_dev_handle = usb_open(m_dev); 
        if(!m_dev_handle) 
        { 
			printf("Could not open m_dev\n"); 
			return 1; 
        } 
  
        printf("裝置開啟成功!\n"); 
        if(usb_set_configuration(m_dev_handle, 1) < 0) 
        { 
                printf("Could not set configuration\n"); 
                usb_close(m_dev_handle); 
                return 1; 
        } 

        if(usb_claim_interface(m_dev_handle, 0) < 0) //claim_interface 0 註冊與作業系統通訊的介面 0
        { 
                printf("Could not claim interface\n"); 
                usb_close(m_dev_handle); 
                return 1; 
        } 

 
	//-----獲取端點的地址-----------------------------
	int ep = m_dev->config->interface->altsetting->endpoint->bEndpointAddress;
	int EP_IN = 0;
	int EP_OUT = 0;
	if (ep > 0x0f)
	{
		EP_IN = ep;
		EP_OUT = ep - 0x80;
	}
	else
	{
		EP_OUT = ep;
		EP_IN = ep + 0x80;
	}
		
	printf("EP_IN: 0x%02x , EP_OUT: 0x%02x \n", EP_IN, EP_OUT);
	//------------------------------------------------------------
		
	char WriteTestData[2048] = {0};
	char ReadTestData[2048] = {0};
	for(int i = 0; i< 2048; i++)
	{
		WriteTestData[i] = i;
	}
		
		//端點1寫入資料
        int ret; 
	ret = usb_bulk_write(m_dev_handle, EP_OUT, WriteTestData, EP1_OUT_SIZE, 500);
	if(ret != EP1_OUT_SIZE)
	{
		printf("端點1寫入資料失敗! %d\n", ret);
		return 1;
	}
	else
	{
		printf("端點1寫入資料成功!\n");
	}

	//端點1讀取資料
	ret = usb_bulk_read(m_dev_handle, EP_IN, ReadTestData, EP1_IN_SIZE, 500);
	if(ret != EP1_IN_SIZE)
	{
		printf("端點1讀取資料失敗! %d\n", ret);
		return 1;
	}
	else
	{
		printf("端點1讀取資料成功!\n");
		for (int i = 0; i < EP1_IN_SIZE; i++)
		{
			printf("%02X ", ReadTestData[i]);
			if(((i + 1) % 16) == 0)
			{
				printf("\n");
			}
		}
		printf("\n");
	}


	/**************************************************************************/

        usb_release_interface(m_dev_handle, 0);		//登出介面,釋放資源,和usb_claim_interface搭配使用。
        usb_close(m_dev_handle); 
        printf("\n裝置關閉\n"); 

        return 0; 
} 



附上:我用VC++編寫的上位機測試Demo.