1. 程式人生 > 實用技巧 >舊版本原始碼usbip的移植

舊版本原始碼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> "