libusb庫在嵌入式Linux平臺上的移植流程

2020-10-20

關鍵字:libusb在嵌入式上編譯


 

1、why libusb?

 

libusb是一種跨平臺的用C語言實現的開源USB通信庫。簡單來說,任何程序員都可以借用libusb庫封裝出來的接口在應用層高效便捷地開發基於USB通信協議的程序。

 

如果沒有libusb,開發一款使用USB協議通信的程序就必須要下探到驅動層纔行。也許有人會說,既然都做到USB通信這塊了,那幾乎都是涉及到U口設備相關的軟件開發了,這種已經在跟硬件打交道的程序員多多少少都懂點驅動開發知識的,甚至有很多這種軟件的定位本身就是一個驅動程序,所以不引入libusb庫而直接開發一款傳統意義上的驅動程序一點問題也沒有。沒錯,但是請你再考慮的更加深入一點:假設我們就將軟件需求以傳統的驅動程序形式實現出來了,它同時也運行良好,這時突然來了個需求,要求我們將這款軟件兼容另外一個系統平臺,那我們是不是隻能將源碼拷貝出一份副本並修改相關係統調用以適配那個系統,然後還要用它的SDK來重新編譯生成驅動纔行?如此,可以輕易預見當程序需要兼容的平臺多了以後其開發與維護難度是迅速飆升的。而當我們引入了libusb庫以後,這一問題就幾乎不存在了,唯一可能還需要我們做的就是編譯適配不同系統平臺的庫文件出來,但它也只需要敲幾條命令重新編譯而不用修改源碼。這就是libusb的強大的地方,同時這也是目前市面上有很多“免驅”的U口設備的底層技術支撐,其實它們並不是免驅,只是將驅動“打包”進了它們的應用程序裏了而已。

 

據libusb官網發佈的信息,目前爲止其所支持的系統環境有如下幾種:

Linux, macOS, Windows, Windows CE, Android, OpenBSD/NetBSD, Haiku, Solaris.

本篇博文就記錄一下在嵌入式Linux平臺下的移植與使用方式。

 

2、如何在嵌入式平臺集成libusb?

 

libusb庫公開的是源碼形式,自己需要哪個平臺就將源碼拿去用哪個平臺的編譯工具編譯生成動靜態庫來引用。因此,本文所描述的內容僅適合擁有相關嵌入式Linux平臺系統源碼或者至少有那個平臺的編譯鏈工具的同學。

 

有了編譯環境以後將源碼準備好,通過源碼內的 configure 生成Makefile,再編譯與安裝,最後拿到動靜態庫以後就可以去開發自己的應用了。

 

3、獲取

 

libusb源碼直接從官網獲取最原汁原味的即可,其官網地址如下:

https://libusb.info/

官網上有其簡介、幫助文檔以及下載鏈接。

 

目前libusb的源碼是託管到Github上的,其資源網址如下:

https://github.com/libusb/libusb/releases

進去後下載一個最新版本就可以了。

 

筆者這邊以 1.0.23 版本作爲演示,如下圖所示:

 

 

 

4、編譯

 

源碼下載好以後將其解壓至可以編譯的環境,其源碼結構如下圖所示:

 

 

接着檢查一下你的編譯鏈工具,要求相關工具,如gcc的目錄要加載進環境變量中。例如,筆者這邊使用的gcc工具全稱是 msdk-linux-gcc,筆者在 shell 中鍵入 msdk幾個關鍵字後直接以 TAB 鍵就能自動補全完整的工具名。如果你那邊還不可以,將編譯工具目錄加載進PATH中。

 

然後是生成Makefile,使用如下命令即可:

./configure --host=msdk-linux --disable-udev --prefix=/home/.../libusb_install

--host 參數的內容就是指定編譯工具的前綴,筆者的gcc編譯工具全稱是 msdk-linux-gcc,但是在這裏僅需填寫 msdk-linux 就行了。

--disable-udev 則是關閉 udev 的編譯,因爲可能有些環境並沒有安裝 udev 庫,關掉它可以避免編譯報錯,一般也不會對編出來的庫有什麼影響。

--prefix設置的是安裝目錄,如果不指定這個目錄,後面在安裝時默認會將庫文件拷貝至 /usr/lib 目錄下,一般我們可能沒有權限往這個目錄拷貝文件,因此直接指定一個有權限的目錄會方便一點。必須要注意的是這裏要填絕對路徑地址。

另外,你還可以執行命令 ./configure --help 來查閱它所支持的其它配置項。

 

命令執行以後,不出意外的話很快就能看到如下形式的信息:

checking for linux/netlink.h... yes
checking poll.h usability... yes
checking poll.h presence... yes
checking for poll.h... yes
checking sys/timerfd.h usability... yes
checking sys/timerfd.h presence... yes
checking for sys/timerfd.h... yes
checking whether TFD_NONBLOCK is declared... yes
checking whether TFD_CLOEXEC is declared... yes
checking whether to use timerfd for timing... yes
checking for pipe2... yes
checking for struct timespec... yes
checking sys/time.h usability... yes
checking sys/time.h presence... yes
checking for sys/time.h... yes
checking for sigaction... yes
checking whether CC supports -std=gnu99... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating libusb-1.0.pc
config.status: creating Makefile
config.status: creating libusb/Makefile
config.status: creating examples/Makefile
config.status: creating tests/Makefile
config.status: creating doc/Makefile
config.status: creating doc/doxygen.cfg
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands

這就表示配置已經成功,Makefile已經自動生成了。不放心的話可以查找一下Makefile的情況,筆者這邊的Makefile查找結果如下:

$ find -type f -name Makefile
./examples/Makefile
./tests/Makefile
./Makefile
./libusb/Makefile
./doc/Makefile

 

如果您很不幸在執行這條命令的時候遇到了如下報錯:

checking whether we are using the GNU C++ compiler... yes
checking whether msdk-linux-g++ accepts -g... yes
checking dependency style of msdk-linux-g++... gcc3
checking build system type... x86_64-pc-linux-gnu
checking host system type... Invalid configuration `msdk-linux': machine `msdk' not recognized
configure: error: /bin/sh ./config.sub msdk-linux failed

不用慌,這並不是什麼大問題,只是libusb覺得它暫時不支持你的編譯工具而已,我們只需要放過這塊的條件判斷即可。打開源碼根目錄下的 config.sub 文件,在約第 246 行的位置仿照已有的case分支添加你的編譯鏈信息,如下圖所示:

 

再次執行,就能成功的了。

 

有了Makefile就可以編譯了,編譯直接在源碼根目錄下執行以下命令:

make

稍等片刻,便可見到如下形式的打印:

core.c:2370: warning: zero-length gnu_printf format string
  CC       libusb_1_0_la-descriptor.lo
descriptor.c: In function 'libusb_get_device_descriptor':
descriptor.c:546: warning: zero-length gnu_printf format string
  CC       libusb_1_0_la-hotplug.lo
  CC       libusb_1_0_la-io.lo
io.c: In function 'disarm_timerfd':
io.c:1333: warning: zero-length gnu_printf format string
io.c: In function 'libusb_interrupt_event_handler':
io.c:1915: warning: zero-length gnu_printf format string
  CC       libusb_1_0_la-strerror.lo
  CC       libusb_1_0_la-sync.lo
  CC       os/libusb_1_0_la-poll_posix.lo
  CC       os/libusb_1_0_la-threads_posix.lo
  CC       os/libusb_1_0_la-linux_usbfs.lo
  CC       os/libusb_1_0_la-linux_netlink.lo
  CCLD     libusb-1.0.la
make[2]: Leaving directory `/home/C3/yongfa.yang/others/iroute/code/rtl819x/users/tmp_deleteme/libusb-1.0.23/libusb'
Making all in doc
make[2]: Entering directory `/home/C3/yongfa.yang/others/iroute/code/rtl819x/users/tmp_deleteme/libusb-1.0.23/doc'
make[2]: Nothing to be done for `all'.
make[2]: Leaving directory `/home/C3/yongfa.yang/others/iroute/code/rtl819x/users/tmp_deleteme/libusb-1.0.23/doc'
make[2]: Entering directory `/home/C3/yongfa.yang/others/iroute/code/rtl819x/users/tmp_deleteme/libusb-1.0.23'
make[2]: Leaving directory `/home/C3/yongfa.yang/others/iroute/code/rtl819x/users/tmp_deleteme/libusb-1.0.23'
make[1]: Leaving directory `/home/C3/yongfa.yang/others/iroute/code/rtl819x/users/tmp_deleteme/libusb-1.0.23'

一般來說,只要能正常結束編譯命令就代表成功了。

 

同時,在 libusb/.libs/ 目錄下也能見到編譯生成出來的庫文件,如下圖所示:

 

 

最後,再執行安裝命令,直接在源碼根目錄下執行:

make install

如果命令能不報錯退出,則表示安裝成功。此時去到你先前指定的安裝目錄,會發現多了兩個目錄,如下圖所示:

 

這裏面就放着相關頭文件以及動靜態庫文件了。

 

如此,便完成了整個編譯過程。

 

5、開發

 

在得到上一步編譯生成的庫文件和頭文件以後即可直接拿去供自己的應用開發使用了。

 

關於應用libusb庫以及簡單的使用示例,筆者將會在另一篇博文中記述。如有需要請閱讀筆者的另一篇博文。

 


 

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