最近项目用到了libusb,作为小菜鸟,简单总结一下,方便大家使用,其实对usb还是听感兴趣的,下此有机会把usb协议也去拜读一下,然后把usb驱动再学习学习。
libusb编译说明:
1、去官网下载libusb-1.0.23
2、tar -xvf libusb-1.0.23.tar.bz2
3、./configure --disable-udev --build=x86_64 --host=arm-linux --prefix=/home/cjj/mytoy/libusb-out CC=arm-linux-gcc --enable-udev
–build自己PC机本地编译环境,–host生成到哪个目录,CC要用到哪个平台上面,注意配置自己交叉编译器
4、编译过程中难免出错,sudo apt-get install libusb-dev,sudo apt-get install libusb-1.0-0-dev, sudo apt-get install autoconf, sudo apt-get install libtool, sudo apt-get install xsltproc
这一大串我都不信还报错
5、make && make install
会生成两个目录:一个是头文件,另一个是库,这里我使用的是静态库
cjj@cjj-MyThink:~/mytoy/libusb-debug$ ls include/libusb-1.0/libusb.h
include/libusb-1.0/libusb.h
cjj@cjj-MyThink:~/mytoy/libusb-debug/lib$ ls
libusb-1.0.a libusb-1.0.la libusb-1.0.so libusb-1.0.so.0 libusb-1.0.so.0.2.0 pkgconfig
编译方式链接本地静态库:
cjj@cjj-MyThink:~/mytoy/libusb-debug$ cat build.sh
gcc -o usb_test usbtest.c -I./include/libusb-1.0/ -L./lib -lusb-1.0 -lpthread
libusb接口介绍:
此处注释一下原作者的地址,写的不错,这里我引用一下
https://blog.csdn.net/wince_lover/article/details/70337809
本文介绍几个实例中需要用到的:
int libusb_init(libusb_context **ctx); | 该函数进行libusb的初始化,必须最先调用。ctx通常设置NULL。返回值:0成功,非0 失败 |
---|---|
void libusb_exit(libusb_context *ctx); | 和libusb_init成对使用,释放相应的资源。ctx通常设置NULL |
int libusb_has_capability(uint32_t capability); | 功能说明:判断当前的库是否支持某项功能 参数说明:capability的取值范围在 enum libusb_capability中定义。LIBUSB_CAP_HAS_CAPABILITY libus库的 API是否有效,该项通常总是返回1 LIBUSB_CAP_HAS_HOTPLUG 是否支持热插拔 LIBUSB_CAP_HAS_HID_ACCESS 是否支持访问HID设备,而不需要用户干预 |
ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, libusb_device ***list); | 获取当前的设备列表, 返回值:0成功,非0 失败 |
int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle,dev libusb_device的指针); | 通过libusb_device的指针打开一个USB设备,并返回设备句柄libusb_device_handle的指针,返回值:0成功,非0 失败 |
void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); | 函数功能:关闭 libusb_open或者libusb_open_device_with_vid_pid打开的设备 参数说明:dev_handle 调用libusb_open或者libusb_open_device_with_vid_pid返回的设备句柄libusb_device_handle的指针 返回值:无 |
int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, struct libusb_device_descriptor *desc); | 函数功能:获取USB设备的设备描述符 参数说明:dev libusb_device的指针,是要读取的设备 desc 设备描述符的指针,用来带回设备描述符的结构 注意:这个函数是将设备描述符的结构拷贝到desc指向的地址 |
int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index, struct libusb_config_descriptor **config); | 获取指定设备的配置描述符 dev libusb_device的指针,是要读取的设备 config_index 配置描述符的索引(一个USB设备可能有多个配置) config 配置描述符的指针,用来带回设备描述符 |
int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev,int interface_number); | 确定指定接口的内核驱动程序是否已经激活。如果一个内核驱动程序是激活的,libusb_claim_interface调用的会失败 返回值:1 已经激活,非1 没有激活 |
int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev,int interface_number); | 函数功能:卸载指定接口的内核驱动程序。如果一个内核驱动程序是激活的,必须先调用这个函数,再调用libusb_claim_interface 返回值:0 成功,非0失败 |
int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev, int interface_number); | 加载指定接口的内核驱动 返回值:0 成功,非0失败 |
废话不多说,下面实例主要实现的功能是通过libusb去卸载U盘,再加载U盘
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#include <libusb-1.0/libusb.h>
int get_configuration(libusb_device* dev, struct libusb_config_descriptor *config)
{
int ret = 0;
ret = libusb_get_config_descriptor(dev, 0, &config);
return ret;
}
void usb_handler(void *dev_handler)
{
libusb_device_handle *dev = (libusb_device_handle *)dev_handler;
int c = getchar();
printf("-------getchar is %d------\n", c);
libusb_attach_kernel_driver(dev, 0);
}
static int KernelDriverDetached = 0; /* set to 1 kernel driver detached */
static int dump_altsetting(libusb_device_handle *dev, const struct libusb_interface_descriptor *interface)
{
// char cls[128], subcls[128], proto[128];
// char *ifstr;
// get_class_string(cls, sizeof(cls), interface->bInterfaceClass);
// get_subclass_string(subcls, sizeof(subcls), interface->bInterfaceClass, interface->bInterfaceSubClass);
// get_protocol_string(proto, sizeof(proto), interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bInterfaceProtocol);
// ifstr = get_dev_string(dev, interface->iInterface);
printf(" Interface Descriptor:\n"
" bLength %5u\n"
" bDescriptorType %5u\n"
" bInterfaceNumber %5u\n"
" bAlternateSetting %5u\n"
" bNumEndpoints %5u\n"
" bInterfaceClass %5u\n"
" bInterfaceSubClass %5u\n"
" bInterfaceProtocol %5u\n",
interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber,
interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass,
interface->bInterfaceSubClass,interface->bInterfaceProtocol);
if (interface->bInterfaceClass == 8) {
fprintf(stdout, "this is a big Mass-storage\n");
if (libusb_kernel_driver_active(dev, 0) > 0) {
if (libusb_detach_kernel_driver(dev, 0) == 0) {
KernelDriverDetached = 1;
fprintf(stdout, "Mass-storage detach success\n");
pthread_t pid;
pthread_create(&pid, NULL, (void *)usb_handler, (void *)dev); /* 此处从中端获取一个字符,然后去重新挂载U盘 */
} else {
fprintf(stdout, "Mass-storage detach fail\n");
return -1;
}
}
}
// free(ifstr);
return 0;
}
static void dump_interface(libusb_device_handle *dev, const struct libusb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
dump_altsetting(dev, &interface->altsetting[i]);
}
static int list_devices(libusb_context *ctx)
{
libusb_device **list;
struct libusb_device_descriptor desc; /* device descriptor */
struct libusb_config_descriptor* conf; /* config descriptor */
libusb_device_handle * handle = NULL;
int config= 0;
int ret;
int status;
ssize_t num_devs, i, j, k;
status = 1; /* 1 device not found, 0 device found */
num_devs = libusb_get_device_list(ctx, &list); /* Traverse the current number of USB devices and return the number of devices */
if (num_devs < 0)
goto error;
for (i = 0; i < num_devs; ++i) {
libusb_device *dev = list[i];
libusb_open(dev,&handle); /* get the usb-device handle */
//libusb_get_configuration(handle,&config); /* 之前调试某些平台这里会出现断错误 */
uint8_t bnum = libusb_get_bus_number(dev);
uint8_t dnum = libusb_get_device_address(dev);
libusb_get_device_descriptor(dev, &desc);
status = 0;
printf("device:%04x:%04x\n",desc.idVendor,desc.idProduct);
printf("bDeviceSubClass = %5u\n",desc.bDeviceSubClass);
printf("bDeviceClass = %5u\n",desc.bDeviceClass);
printf("bDeviceProtocol = %5u\n",desc.bDeviceProtocol);
for( j = 0; j < desc.bNumConfigurations; ++j) {
ret = libusb_get_config_descriptor(dev, j, &conf);
if (ret) {
fprintf(stderr, "Couldn't get configuration "
"descriptor %lu, some information will "
"be missing\n", j);
} else {
printf("bNumberInterfaces = %5u\n",conf->bNumInterfaces);
printf("bConfigurationValue = %5u\n",conf->bConfigurationValue);
for (k = 0 ; k < conf->bNumInterfaces ; k++)
dump_interface(handle, &conf->interface[k]);
libusb_free_config_descriptor(conf);
}
}
}
libusb_free_device_list(list, 0);
error:
return status;
}
int main(int argc, char *args[])
{
int err = 0;
libusb_context *ctx;
err = libusb_init(&ctx);
if (err) {
fprintf(stderr, "unable to initialize libusb: %i\n", err);
return EXIT_FAILURE;
}
list_devices(ctx);
while(1)
sleep(1);
return 0;
}