Libusb-win32編程方法

Libusb-win32編程方法
Libusb-win32使用主要是兩個方面,一個是編寫程序的時候調用Libusb-win32提供的API函數,另一個是編譯的時候要調用相應的庫文件;進入C:\Users\sun\Desktop\libusb-win32-bin-1.2.6.0\lib,可以看到Libusb-win32根據不同的編譯方法提供了不同的庫文件,可根據自己的編譯環境調用相應的庫文件;
這裏寫圖片描述
一、首先說明庫文件調用方法,本人使用的是QT軟件,編譯語言是c和c++,編譯器爲GCC,調用庫的方法如下:(windows下QT安裝和配置在另一篇文檔裏介紹)
將C:\Users\sun\Desktop\libusb-win32-bin-1.2.6.0\lib\gcc文件夾下的libusb.a文件拷貝到工程目錄文件夾下,打開工程文件,在文件里加上LIBS += ../libusb.a,添加庫文件,庫文件的路徑要寫對,否則調用不成功
這裏寫圖片描述
二、編寫程序
首先將C:\Users\sun\Desktop\libusb-win32-bin-1.2.6.0\include中的lusb0_usb.h添加到項目中;
編寫程序有個流程,這方面網上很多介紹資料,下面簡單介紹下;
在C:\Users\sun\Desktop\libusb-win32-bin-1.2.6.0\examples文件夾下面有個bulk.c文件,裏面涉及到了usb四種通信方式的控制傳輸和批量傳輸,其他兩種傳輸方法類似,可自行研究。

1.首先調用下面三個函數:
usb_init(); /* initialize the library */
usb_find_busses(); /* find all busses */
usb_find_devices(); /* find all connected devices */
這三個函數是所有操作前就必須調用的,用來初始化庫,遍歷總線和設備;
2.打開設備;
調用了下面的函數,這個函數要自己實現,不是庫文件裏的,功能是遍歷所有的總線和設備,根據VID和PID識別到自己的設備,然後調用usb_open庫函數,打開該設備,返回一個設備句柄,用來下面的讀寫操作;

usb_dev_handle *open_dev(void)
{
    struct usb_bus *bus;
    struct usb_device *dev;

    for (bus = usb_get_busses(); bus; bus = bus->next)
    {
        for (dev = bus->devices; dev; dev = dev->next)
        {
            if (dev->descriptor.idVendor == MY_VID
                    && dev->descriptor.idProduct == MY_PID)
            {
                return usb_open(dev);
            }
        }
    }
    return NULL;
}

3.根據從機的驅動來做相應的初始化操作,一般是設置從機的配置和接口(從機功能單元有配置,接口,端口,端口是最小單位,是用來發送和接收數據的功能單元,資料很多,不詳細介紹)
(1)調用int usb_set_configuration(usb_dev_handle *dev, int configuration);函數進行從設備的配置,需要從設別的支持,如果從設備只有一個配置或者使用者使用默認設置,在從設備初始化的過程中,設置設備的配置可以省略;返回值小於0表示配置失敗;
(2)調用int usb_claim_interface(usb_dev_handle *dev, int interface);來配置接口,這一步一般都是要的,返回值小於0表示配置失敗;

上面的初始化操作只是用戶調用libusb-win32時的初始化流程,像讀取設備信息這類操作電腦已經幫我們完成,
初始化設備完成,我們就可以調用相應的庫函數對設備進行讀寫和控制操作了;
Bulk.c中給出了控制傳輸和批量傳輸例子,其中批量傳輸給了同步和非同步兩種方式,控制傳輸代碼如下:
ret = usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
14, /* set/get test */
1, /* test type */
MY_INTF, /* interface id */
tmp, 1, 1000);
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);

這有兩個地方需要注意,
1.批量傳輸的斷點分輸出端點和輸入端點,使用的時候不可以搞混,想查看自己設備有哪些端點還有端點信息,可以通過C:\Users\sun\Desktop\libusb-win32-bin-1.2.6.0\bin\x86目錄下面的testlibusb-win.exe獲得,(這是32位機下的,64位機可在相應目錄下找到該文件):
這裏寫圖片描述
這裏寫圖片描述
上圖中圖示部分爲端點號,一個輸出端點,一個輸入端點,根據從設備確定;
2.第二個要注意的地方是,usb批量傳輸時,如果傳輸的數據小於從設備設置的端點緩存大小,則每次傳輸的數據都應該是8的整數倍,如果發送數據的大小不是8的整數倍,最後的字節收到的時候會有錯誤;
而且傳輸的數據都應該以字符’\0’結束,字符串的話默認後面都有’\0’,如果是其他數據,則要認爲的加上’\0’;
異步傳輸代碼如下:

/*
* Read/Write using async transfer functions.
*
* NOTE: This function waits for the transfer to complete essentially making
* it a sync transfer function so it only serves as an example of how one might
* implement async transfers into thier own code.
*/
static int transfer_bulk_async(usb_dev_handle *dev,
                               int ep,
                               char *bytes,
                               int size,
                               int timeout)
{
    // Each async transfer requires it's own context. A transfer
    // context can be re-used.  When no longer needed they must be
    // freed with usb_free_async().
    //
    void* async_context = NULL;
    int ret;

    // Setup the async transfer.  This only needs to be done once
    // for multiple submit/reaps. (more below)
    //
    ret = usb_bulk_setup_async(dev, &async_context, ep);
    if (ret < 0)
    {
        printf("error usb_bulk_setup_async:\n%s\n", usb_strerror());
        goto Done;
    }

    // Submit this transfer.  This function returns immediately and the
    // transfer is on it's way to the device.
    //
    ret = usb_submit_async(async_context, bytes, size);
    if (ret < 0)
    {
        printf("error usb_submit_async:\n%s\n", usb_strerror());
        usb_free_async(&async_context);
        goto Done;
    }

    // Wait for the transfer to complete.  If it doesn't complete in the
    // specified time it is cancelled.  see also usb_reap_async_nocancel().
    //
    ret = usb_reap_async(async_context, timeout);

    // Free the context.
    usb_free_async(&async_context);

Done:
    return ret;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章