旧版本源码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
-
交叉编译工具的详细信息
book@www.100ask.org:~$ 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”通讯不了的情况 -
配置和安装
# 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
-
加载模块
modprobe -l |grep usbip sudo modprobe -a usbip-core usbip-host vhci-hcd
-
需要进行开机设定的可以写入/etc/modules
# 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开头的,可以大胆猜测是缺少某些库,百度下就会有
-
如果安装后还出现找不到的情况,检查对应路径文件是否存在,存在则用sudo增加权限
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> "