舊版本原始碼usbip的移植
前言
-
由於工作需要usb透傳功能,所以記錄下移植usbip過程中遇到的難題和解決辦法,可以給自己以後的移植工作做個參考,也可以給正在移植usbip的困惑者給點幫助。
-
這裡先玩玩usbip的功能,後續部落格再對usbip的原理進行解析
概述
-
usbip是一種利用乙太網,將usb裝置(鍵鼠、U盤等)共享到另一端網路驅動,提供了USB透傳的功能(類似於USB延長線)
-
usbip剛開始是一個獨立的專案(http://usbip.sourceforge.net),後來合併到linux分支下
-
舊版本Linux原始碼中在drivers/staging/usbip,使用者測試原始碼在該目錄下的userspace/目錄下
-
新版本Linux原始碼中在drivers/usb/usbip,使用者測試原始碼在tools/usb/usbip下
-
對於windows下,也有類似的開源專案,可能Windows上的用途會比較廣,github路徑為:https://github.com/cezanne/usbip-win
-
移植工作
準備工作
-
材料: Ubuntu12.04、 3352板子(核心原始碼3.2.0)、 交叉編譯工具(這裡是TI原始碼6.0.0中的4.7.3交叉編譯工具)
-
虛擬機器和3352板子需要先ping通,百度上很多文章有講到,這裡不多說
3352移植(遇見的問題在下邊彙總)
-
編譯驅動:
-
可以選擇編進核心或者編成模組,在原始碼根目錄執行make menuconfig,在 Device Drivers ---> [*] Staging drivers ---> --- Staging drivers 下進行選擇
-
編進核心的話將新核心映象燒寫到板子上,編成模組則有usbip-core.ko,usbip-host.ko和vhci-hcd.ko,insmod到板子上
-
-
編譯使用者測試原始碼:
- 事先安裝一些依賴檔案
sudo apt-get install autoconf automake libtool libudev-dev libsysfs-dev
-
進入使用者測試程式目錄userspace/下,執行./autogen.sh,生成configure
-
接下來執行經典“三部曲”:./configure、make和make install, 重點需要對configure的引數進行配置正確,不然會出現很多問題,我自己參考ti寫了一個配置指令碼build.sh(結尾有ti指令碼的內容),執行./build.sh
#!/bin/sh # build the CDVS Test Model # with full optimizations and multithreading: export CFLAGS=" -march=armv7-a -marm -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 --sysroot=/home/book/sysroots/armv7ahf-vfp-neon-3.2-oe-linux-gnueabi" export LDFLAGS=' --sysroot=/home/book/sysroots/armv7ahf-vfp-neon-3.2-oe-linux-gnueabi' export CPATH="/home/book/sysroots/armv7ahf-vfp-neon-3.2-oe-linux-gnueabi/usr/include" export PATH="$PATH:/home/book/sysroots/armv7ahf-vfp-neon-3.2-oe-linux-gnueabi/usr/bin:/home/book/sysroots/i686-arago-linux/usr/bin" mkdir -p build CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ LD=arm-linux-gnueabihf-ld AR=arm-linux-gnueabihf-ar AS=arm-linux-gnueabihf-as NM=arm-linux-gnueabihf-nm STRIP= RANLIB=arm-linux-gnueabihf-strip OBJDUMP=arm-linux-gnueabihf-objdump ./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf --build=i686-linux --with-libtool-sysroot=/home/book/sysroots/armv7ahf-vfp-neon-3.2-oe-linux-gnueabi --prefix=$HOME/usbip_build # build all binaries make # install all binaries in $HOME/bin (no need of admin priviledges) make install
- 交叉編譯工具的詳細資訊
[email protected]:~$ arm-linux-gnueabihf-gcc -v Using built-in specs. COLLECT_GCC=/home/book/sysroots/i686-arago-linux/usr/bin/arm-linux-gnueabihf-gcc COLLECT_LTO_WRAPPER=/home/book/sysroots/i686-arago-linux/usr/bin/../libexec/gcc/arm-linux-gnueabihf/4.7.3/lto-wrapper Target: arm-linux-gnueabihf Configured with: /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/src/gcc-linaro-4.7-2013.03/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf --prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/install --with-sysroot=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/install/arm-linux-gnueabihf/libc --enable-languages=c,c++,fortran --enable-multilib --with-arch=armv7-a --with-tune=cortex-a9 --with-fpu=vfpv3-d16 --with-float=hard --with-pkgversion='crosstool-NG linaro-1.13.1-4.7-2013.03-20130313 - Linaro GCC 2013.03' --with-bugurl=https://bugs.launchpad.net/gcc-linaro --enable-__cxa_atexit --enable-libmudflap --enable-libgomp --enable-libssp --with-gmp=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-mpfr=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-mpc=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-ppl=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-cloog=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-libelf=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static --with-host-libstdcxx='-L/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/.build/arm-linux-gnueabihf/build/static/lib -lpwl' --enable-threads=posix --disable-libstdcxx-pch --enable-linker-build-id --enable-gold --with-local-prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-linux/install/arm-linux-gnueabihf/libc --enable-c99 --enable-long-long --with-mode=thumb Thread model: posix gcc version 4.7.3 20130226 (prerelease) (crosstool-NG linaro-1.13.1-4.7-2013.03-20130313 - Linaro GCC 2013.03)
-
指令碼說明:
-
首先是CFLAGS,該選項為C編譯器選項,裡邊定義的變數為後續configure需要用到的,-march選項是交叉編譯工具中選項--with-arch的值armv7-a;選項-marm指定arm指令集; 選項-mthumb-interwork是生成的目標檔案允許在ARM和Thumb之間交叉呼叫; -mfloat-abi對應交叉編譯工具選項--with-float的值hard; 選項-mfpu是CPU型別編譯器,根據自己需求選擇; 選項-mtune指定的是目標處理器的名稱,這裡3352板子是cortex-a8; 由於ti的交叉編譯工具是將執行檔案和庫檔案分開,因此需要特別指定庫檔案根目錄,即設定引數--sysroot,該選項是指定邏輯目錄,在這裡是/home/book/sysroots/armv7ahf-vfp-neon-3.2-oe-linux-gnueabi。(重點是選項-match、-mtune和--sysroot,其他的選項視實際情況指定)
-
常用的CPU型別編譯器選項
-
LDFLAGS新增庫搜尋目錄,CPATH新增標頭檔案搜尋目錄,PATH新增交叉編譯工具的執行目錄
-
--target和--host指定目標機的執行環境,這裡為arm-linux-gnueabihf, --build選項是指定在哪裡編譯該環境,這裡是Ubuntu12.04,為i686(命令uname -a可以檢視),--prefix指定編譯後的安裝目錄
-
到這裡配置結束,之後make、 make install 完成編譯和安裝,一般都不會正常的結束,出現的問題在後邊進行彙總
-
-
編譯成功後在配置時選項prefix的指定目錄下有相應檔案,將整個檔案打包到3352開發板上,進入sbin目錄下執行檔案,若出現連結不到庫檔案的情況,將usbip目錄中的lib路徑加到/etc/ld.so.conf中,執行ldconfig即可
Ubuntu12.04上的編譯
-
Ubuntu12.04本機上已經有usbip驅動了(目錄:/lib/modules/`uname -r`/kernel/drivers/staging/usbip),所以不用自己編譯成模組
-
對於想自己手動編譯核心的話,進入usbip/目錄,將Makefile修改後編譯即可
KERN_DIR = /usr/src/linux-headers-3.5.0-25-generic/ #原始碼目錄
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.ordes
ccflags-y := -DDEBUG
obj-m += usbip-core.o
usbip-core-y := usbip_common.o usbip_event.o
obj-m += vhci-hcd.o
vhci-hcd-y := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o
obj-m += usbip-host.o
usbip-host-y := stub_dev.o stub_main.o stub_rx.o stub_tx.o
-
編譯使用者測試原始碼:
-
由於Ubuntu12.04的版本比較舊,如果直接執行
sudo apt-get install usbip
來安裝usbip的話,可能會出現版本不相容的情況,因此需要手動安裝 -
安裝對應板子核心版本的原始碼(3.2.0),並執行初始化配置
sudo apt-get install linux-source-3.2.0 sudo tar -xjvf /usr/src/linux-source-3.2.0/linux-source-3.2.0.tar.bz2 cd linux-source-3.2.0/drivers/staging/usbip/userspace sudo ./autogen.sh
- 接下來就是配置和安裝了,但有個注意點,就是
./configure
後會產生一個config.h檔案,裡邊包含了一些版本的資訊,需要對版本資訊進行確認,在3352板子上執行usbip version
可以查到資訊,我這裡是usbip (usbip-utils 1.1.1),因此不需要改
-
動,如果網路兩邊的版本不一致,可能會出現“usbip: debug: usbip_network.c:149:[usbip_net_recv_op_common] version mismatch: 262 273”通訊不了的情況
* 配置和安裝
```shell
# sudo sed -i 's%USBIP_VERSION 0x00000111%USBIP_VERSION 0x00000106%g' config.h (這裡示範:1.1.1版本改為1.0.6,不需要改動的可以跳過)
# sudo ./configure --prefix=/usr --sysconfdir=/etc
# sudo make install
```
* 載入模組
```shell
modprobe -l |grep usbip
sudo modprobe -a usbip-core usbip-host vhci-hcd
```
* 需要進行開機設定的可以寫入/etc/modules
```shell
# sudo vim /etc/modules
#+++++++++++++++++++++++++++++++++++++++++
usbip-core
usbip-host
vhci-hcd
#+++++++++++++++++++++++++++++++++++++++++
```
測試例子
說明
- 服務端是插入Usb裝置的一端,而客戶端是獲取usb裝置資訊的一端,例如,在服務端插入USB滑鼠,當客戶端和服務端連線後,就可以在服務端上操作客戶端桌面,類似遠端連線
Server
-
服務端需要插入的模組是usbip-core.ko和usbip-host.ko
-
命令解析
usbipd -D #啟動後臺守護程序
usbip list -l #羅列插入的usb裝置,注意busid(2-1.1)
- busid 2-1.1 (046d:c077)
Logitech, Inc. : M105 Optical Mouse (046d:c077)
usbip bind -b 2-1.1 #繫結裝置
usbip: info: bind device on busid 2-1.1: complete
usbip unbind -b 2-1.1 #解綁裝置
usbip: info: unbind device on busid 2-1.1: complete
client
-
客戶端需要插入的模組是usbip-core.ko和vhci-hcd.ko
-
命令解析
#usbip list –r <server端ip地址>
usbip list -r 192.168.202.150
#usbip attach -r <server端ip地址> -b <busid>
usbip attach -r 192.168.202.150 -b 2-1.1
#usbip detach-p <port>
usbip detach -p 0
測試結果
-
在服務端3352板子上插入USB裝置,可以對客戶端的Ubuntu進行操作,換做U盤時出現Ubuntu識別到掛接,但找不到掛載點(猜想是虛擬機器VM的問題),暫時沒解決
-
在服務端Ubuntu上掛接U盤,在客戶端3352板子上可以看到掛接的目錄和檔案內容
缺陷
- 將服務端的USB裝置拔插,需要重新執行連線命令才能使用,熱拔插支援不是很好
問題彙總
執行./autogen.sh時出現 Missing /usr/include/sysfs/libsysfs.h
-
缺少相關的庫,執行
sudo apt-get install libsysfs-dev
-
對於標頭檔案的缺失,由於標頭檔案的名字是以lib開頭的,可以大膽猜測是缺少某些庫,百度下就會有
configure配置時出現的錯誤
-
configure執行不成功時會把錯誤資訊保留在config.log檔案中
-
對於找不到一些類似於.o、-lc連結不上的情況,看下configure時連結庫路徑有沒有出錯
-
pkg-config版本太老的問題,執行
sudo apt-get install pkg-config
更新pkg配置,並且將PATH環境變數中將自己新增的部分放在系統變數的後邊
執行時出現cannot open "/usr/share/hwdata/usb.ids", No such file or directory
-
這個沒影響的,只是用於識別裝置驅動的名稱
-
解決辦法:將Ubuntu12.04相應位置的usb.ids複製到開發板相應位置上即可
連線時出現error: recv op_common
-
出現這個問題一般就是斷連的情況
-
檢查客戶端是否繫結成功,再執行下繫結裝置的命令,確定是否繫結成功
-
檢查USB硬體上是否鬆動,執行多次羅列裝置的命令,看看是否會出現經常查不到當前USB裝置的情況(我自己的USB裝置硬體就是鬆動,多次查詢後就找不到裝置)
連線時出現error:sorry, it's a bug!
- 這個在移植過程中只碰到過一次,猜想是庫檔案的問題,可能要考慮重新編譯使用者測試程式
Ti的參考指令碼
-
Ti的東西有很多是可以學習的,不妨去看看Ti的SDK
-
環境初始化指令碼
SDK_PATH="/home/aspeed/ti-sdk-am335x-evm-06.00.00.00/linux-devkit"
if [ -z "$ZSH_NAME" ] && [ "x$0" = "x./environment-setup" ]; then
echo "Error: This script needs to be sourced. Please run as \". ./environment-setup\""
exit 1
else
if [ -n "$BASH_SOURCE" ]; then
SDK_PATH="`dirname $BASH_SOURCE`"
fi
SDK_PATH=`readlink -f "$SDK_PATH"`
export SDK_PATH
fi
export SDK_SYS=i686-arago-linux
export TARGET_SYS=armv7ahf-vfp-neon-3.2-oe-linux-gnueabi
export TOOLCHAIN_SYS=arm-linux-gnueabihf
export TOOLCHAIN_PREFIX=$TOOLCHAIN_SYS-
export SDK_PATH_NATIVE=$SDK_PATH/sysroots/$SDK_SYS
export SDK_PATH_TARGET=$SDK_PATH/sysroots/$TARGET_SYS
export PATH=$SDK_PATH_NATIVE/usr/bin:$PATH
export CPATH=$SDK_PATH_TARGET/usr/include:$CPATH
export PKG_CONFIG_SYSROOT_DIR=$SDK_PATH_TARGET
export PKG_CONFIG_PATH=$SDK_PATH_TARGET/usr/lib/pkgconfig
export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
export CONFIG_SITE=$SDK_PATH/site-config-$TARGET_SYS
export CC=${TOOLCHAIN_PREFIX}gcc
export CXX=${TOOLCHAIN_PREFIX}g++
export GDB=${TOOLCHAIN_PREFIX}gdb
export CPP="${TOOLCHAIN_PREFIX}gcc -E"
export NM=${TOOLCHAIN_PREFIX}nm
export AS=${TOOLCHAIN_PREFIX}as
export AR=${TOOLCHAIN_PREFIX}ar
export RANLIB=${TOOLCHAIN_PREFIX}ranlib
export OBJCOPY=${TOOLCHAIN_PREFIX}objcopy
export OBJDUMP=${TOOLCHAIN_PREFIX}objdump
export STRIP=${TOOLCHAIN_PREFIX}strip
export CONFIGURE_FLAGS="--target=$TARGET_SYS --host=$TARGET_SYS --build=i686-linux --with-libtool-sysroot=$SDK_PATH_TARGET"
export CPPFLAGS=" -march=armv7-a -marm -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 --sysroot=$SDK_PATH_TARGET"
export CFLAGS="$CPPFLAGS"
export CXXFLAGS="$CPPFLAGS"
export LDFLAGS=" --sysroot=$SDK_PATH_TARGET"
export OECORE_NATIVE_SYSROOT=$SDK_PATH_NATIVE
export OECORE_TARGET_SYSROOT=$SDK_PATH_TARGET
export OECORE_ACLOCAL_OPTS="-I $SDK_PATH_NATIVE/usr/share/aclocal"
export OECORE_DISTRO_VERSION="2013.05"
export OECORE_SDK_VERSION="2013.05"
export OE_QMAKE_CFLAGS="$CFLAGS"
export OE_QMAKE_CXXFLAGS="$CXXFLAGS"
export OE_QMAKE_LDFLAGS="$LDFLAGS"
export OE_QMAKE_CC=$CC
export OE_QMAKE_CXX=$CXX
export OE_QMAKE_LINK=$CXX
export OE_QMAKE_AR=$AR
export OE_QMAKE_LIBDIR_QT=$SDK_PATH_TARGET/usr/lib
export OE_QMAKE_INCDIR_QT=$SDK_PATH_TARGET/usr/include/qtopia
export OE_QMAKE_MOC=$SDK_PATH_NATIVE/usr/bin/moc4
export OE_QMAKE_UIC=$SDK_PATH_NATIVE/usr/bin/uic4
export OE_QMAKE_UIC3=$SDK_PATH_NATIVE/usr/bin/uic34
export OE_QMAKE_RCC=$SDK_PATH_NATIVE/usr/bin/rcc4
export OE_QMAKE_QDBUSCPP2XML=$SDK_PATH_NATIVE/usr/bin/qdbuscpp2xml4
export OE_QMAKE_QDBUSXML2CPP=$SDK_PATH_NATIVE/usr/bin/qdbusxml2cpp4
export OE_QMAKE_QT_CONFIG=$SDK_PATH_TARGET/usr/share/qtopia/mkspecs/qconfig.pri
export OE_QMAKE_STRIP="echo"
export QMAKESPEC=$SDK_PATH_TARGET/usr/share/qtopia/mkspecs/linux-g++
#export PS1="\[\e[32;1m\][linux-devkit]\[\e[0m\]:\w> "