目录
零、前言
一、libusb交叉编译
1.0 前言
1.1 交叉编译
二、usbutils交叉编译
2.0 前言
2.1 交叉编译
三、libudev交叉编译
3.0 前言
3.1 交叉编译
3.2 错误处理-没找到usbutils
3.3 错误处理-没找到pci.ids (pci.ids not found)
3.3.0 前言
3.3.1 查找pci.ids
3.3.2 继续编译
3.4 错误处理-没找到gperf (gperf not found)
3.5 编译并安装
四、eudev交叉编译
4.0 前言
4.1 交叉编译
五、测试代码
5.1 usb测试代码
5.2 编译脚本Makefile
5.3 运行结果
零、前言
alientek@ubuntu16:~/linuxProject/v4l2_test/usb_callback_test$ make
arm-linux-gnueabihf-gcc -o usb_callback_test usb_callback_test.c -lpthread -lusb-1.0 -I/home/alientek/tools/libusb-1.0.26/build/include -L/home/alientek/tools/libusb-1.0.26/build/lib
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.9.4/../../../../arm-linux-gnueabihf/bin/ld: warning: libudev.so.1, needed by /home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so, not found (try using -rpath or -rpath-link)
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_monitor_filter_add_match_subsystem_devtype@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_monitor_enable_receiving@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_enumerate_scan_devices@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_new@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_device_get_devnode@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_enumerate_new@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_list_entry_get_name@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_enumerate_add_match_subsystem@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_device_get_sysname@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_enumerate_get_list_entry@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_enumerate_add_match_property@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_device_new_from_syspath@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_monitor_new_from_netlink@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_monitor_receive_device@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_device_unref@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_enumerate_unref@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_monitor_get_fd@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_list_entry_get_next@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_monitor_unref@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_unref@LIBUDEV_183’未定义的引用
/home/alientek/tools/libusb-1.0.26/build/lib/libusb-1.0.so:对‘udev_device_get_action@LIBUDEV_183’未定义的引用
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'usb_callback_test' failed
make: *** [usb_callback_test] Error 1
一、libusb交叉编译
1.0 前言
1.1 交叉编译
sudo apt-get install libtool
unzip libusb-1.0.26.zip
cd libusb-1.0.26
mkdir build
./autogen.sh
./configure CC={编译器目录} --host=arm-linux-gnueabihf --prefix=$PWD/build
make
make install #安装在build目录下
编译时需要指定头文件路径/home/alientek/tools/libusb-1.0.26/build/include
库文件路径/home/alientek/tools/libusb-1.0.26/build/lib
二、usbutils交叉编译
2.0 前言
2.1 交叉编译
#unzip
cd usbutils-005
mkdir build
./configure CC={编译器目录} --host=arm-linux-gnueabihf --prefix=$PWD/build
make
make install
三、libudev交叉编译
3.0 前言
3.1 交叉编译
#unzip
cd udev-182
mkdir build
./configure CC={编译器目录} --host=arm-linux-gnueabihf --prefix=$PWD/build
make
make install
环境没有问题的话,能够一次编译成功,如下所示。但实际上会缺少部分文件,详情根据3.2以后章节查看。
3.2 错误处理-没找到usbutils
如果configure配置失败,出现没找到usbutils错误,需要检查是否usbutils安装出现问题
通过查看上面打印信息可以看到使用的pkg-config路径为/opt/fsl-imx-x11/4.1.15-2.1.0/目录下。通过下面指令找到实际存放的pkgconfig路径
cd /opt/fsl-imx-x11/4.1.15-2.1.0/ #根据提示信息自行修改
find ./ -name "pkgconfig" #得到路径/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/lib/pkgconfig
将usbutils-005目录下交叉编译生成的文件放到上述pkgconfig目录下
cp {usbutils-005}/build/share/pkgconfig/usbutils.pc /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/lib/pkgconfig
完成上述操作后,再次配置udev-182
./configure --host=arm-linux-gnueabihf --prefix=$PWD/build #配置udev交叉编译
提示如下错误:
3.3 错误处理-没找到pci.ids (pci.ids not found)
3.3.0 前言
参考: 交叉编译 udev 库_pci.ids not found_huihuiwith的博客-CSDN博客
3.3.1 查找pci.ids
使用参考连接中的whereis pci.ids无法找到有效地址。这里使用find指令查找:sudo find / -name "pci.ids"
找到两个路径。疑问:我们需要是的交叉编译,可以直接只是x86的ids吗?
3.3.2 继续编译
指定pci路径地址,再次配置
./configure --host=arm-linux-gnueabihf --prefix=$PWD/build --with-pci-ids-path=/usr/share/misc/pci.ids
提示gperf not found
3.4 错误处理-没找到gperf (gperf not found)
参考: configure: error: gperf is needed_tool gperf is required._柳鲲鹏的博客-CSDN博客
通过apt安装gperf:
sudo apt install gperf
再次配置即可成功
3.5 编译并安装
make
make install
注:本人在进行make过程中,出现了/bin/grep: /usr/lib/libglib-2.0.la: No such file or director等问题。根据其他人的博文内容,udev已经很久没有更新,而且也有eudev作为更好的替代品。因此后面修改使用eudev进行交叉编译。
四、eudev交叉编译
4.0 前言
参考: 海思Hi3536交叉编译eudev和libusb库_eudev 3.2.9编译_mkelehk的博客-CSDN博客
eudev版本:3.2.11 ( Archived eudev tarballs (gentoo.org))
4.1 交叉编译
sudo apt install gperf
#解压
cd eudev-3.2.11
mkdir build
./configure --host=arm-linux-gnueabihf --prefix=$PWD/build --disable-blkid --disable-kmod
make
make install
将交叉编译的头文件、动态库文件放到交叉工具链中
cd {eudev目录}/build
cp bin/udevadm ~/linux/nfs/rootfs-alientek/bin/
sudo cp lib/* /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/lib/
sudo cp include/* /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/include/
五、测试代码
5.1 usb测试代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libudev.h>
#include <sys/select.h>
// 打印设备信息
void print_device_info(struct udev_device *dev) {
// 获取设备信息
const char *devpath = udev_device_get_devpath(dev);
const char *subsystem = udev_device_get_subsystem(dev);
const char *devtype = udev_device_get_devtype(dev);
const char *syspath = udev_device_get_syspath(dev);
const char *sysname = udev_device_get_sysname(dev);
const char *sysnum = udev_device_get_sysnum(dev);
const char *devnode = udev_device_get_devnode(dev);
// 打印设备信息
printf("Device info:\n");
printf(" devpath : %s\n", devpath );
printf(" subsystem : %s\n", subsystem);
printf(" devtype : %s\n", devtype );
printf(" syspath : %s\n", syspath );
printf(" sysname : %s\n", sysname );
printf(" sysnum : %s\n", sysnum );
printf(" devnode : %s\n", devnode );
printf("\n");
}
// 遍历USB设备
void enumerate_usb_devices(struct udev *udev) {
// 创建枚举器
struct udev_enumerate *enumerate = udev_enumerate_new(udev);
// 设置匹配条件
udev_enumerate_add_match_subsystem(enumerate, "usb");
// 扫描设备
udev_enumerate_scan_devices(enumerate);
// 获取设备列表
struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
struct udev_list_entry *dev_list_entry;
// 遍历设备列表
udev_list_entry_foreach(dev_list_entry, devices) {
// 获取设备路径
const char *path = udev_list_entry_get_name(dev_list_entry);
// 创建设备对象
struct udev_device *dev = udev_device_new_from_syspath(udev, path);
if (dev) {
// 打印设备信息
print_device_info(dev);
// 释放设备对象
udev_device_unref(dev);
}
}
// 释放枚举器
udev_enumerate_unref(enumerate);
}
int main() {
// 创建一个udev对象
struct udev *udev = udev_new();
if (!udev) {
// 创建失败
fprintf(stderr, "Failed to create udev context\n");
return 1;
}
// 枚举所有USB设备并打印它们的信息
enumerate_usb_devices(udev);
// 创建udev monitor对象,并设置要监听的设备类型为usb
struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(monitor, "usb", NULL);
// 启用udev monitor接收事件
udev_monitor_enable_receiving(monitor);
// 获取monitor的文件描述符
int fd = udev_monitor_get_fd(monitor);
fd_set fds;
// 进入循环,等待事件发生
while (1) {
// 清空文件描述符集合并将monitor的文件描述符添加到集合中
FD_ZERO(&fds);
FD_SET(fd, &fds);
// 调用select函数等待文件描述符就绪
int ret = select(fd + 1, &fds, NULL, NULL, NULL);
if (ret > 0 && FD_ISSET(fd, &fds)) {
// 从monitor中接收一个事件对象
struct udev_device *dev = udev_monitor_receive_device(monitor);
if (dev) {
// 获取事件动作(add或remove)
const char *action = udev_device_get_action(dev);
if (strcmp(action, "add") == 0) {
// 如果是add事件,打印提示信息并枚举所有USB设备
printf("USB device added\n");
// enumerate_usb_devices(udev);
}
else if (strcmp(action, "remove") == 0) {
// 如果是remove事件,打印提示信息即可
printf("USB device removed\n");
}
// 释放事件对象
udev_device_unref(dev);
}
}
}
// 关闭monitor和udev对象
udev_monitor_unref(monitor);
udev_unref(udev);
return 0;
}
5.2 编译脚本Makefile
CROSS=arm-linux-gnueabihf-
CC = $(CROSS)gcc
CFLAGS = -Wall -Wextra -pedantic -std=c99 \
-lpthread -lusb-1.0 -ludev \
-I/home/alientek/tools/libusb-1.0.26/build/include \
-I/home/alientek/tools/eudev-3.2.11/build/include
LDFLAGS = -L/home/alientek/tools/libusb-1.0.26/build/lib \
-L/home/alientek/tools/eudev-3.2.11/build/lib
TARGET = usb_callback_test
OBJS = $(TARGET).o
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
cp -f ${TARGET} ~/linux/nfs/rootfs-alientek/
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(OBJS) $(TARGET)
5.3 运行结果