Ubuntu下识别usb设备接入,使用libusb库;采用热插拔识别设备接入,并获取设备序列号。
1. 下载编译libusb库
安装依赖项
sudo apt install -y make dh-autoreconf
sudo apt install -y libudev-dev
编译后得到libusb-1.0.a与libusb-1.0.so, libusb.h
2. 程序基本流程
初始化libusb:在main函数中,首先调用libusb_init初始化libusb上下文。
检查热插拔支持:通过libusb_has_capability检查系统是否支持热插拔功能。
注册回调函数:
使用libusb_hotplug_register_callback注册设备接入回调函数hotplug_callback。
同样使用该函数注册设备移除回调函数hotplug_callback_detach。
事件循环:在while循环中,调用libusb_handle_events_timeout_completed处理libusb事件,超时5ms。注意不要使用libusb_handle_events,该接口会阻塞线程;
标准的示例处理设备如下所示,不过实际测试发现仅第一次接入设备能读取到设备序列后,后续就无法获取;猜测是设备重复插拔系统响应不过来,在设备接入时增加延时处理后热插拔OK!流程详见代码。
- 设备接入处理(
hotplug_callback):- 获取设备描述符。
- 关闭之前打开的设备句柄(如果有)。
- 打开新接入的设备。
- 获取设备的序列号。
- 配置设备接口,启用自动分离内核驱动,并尝试声明接口。
- 设备移除处理(
hotplug_callback_detach):- 获取设备描述符。
- 关闭打开的设备句柄(如果有)
#include "libusb.h"
#include <stdio.h>
#include <sys/time.h>
#include <bits/types.h>
#include <unistd.h>
int delaycnt = 0, iSerialNumber = 0;
libusb_device_handle *handle = NULL;
libusb_device *attach_dev = NULL;
#define DEVICE_VID 0x1FC9
#define DEVICE_PID 0x0188
static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
delaycnt = 100;
attach_dev = dev;
return 0;
}
static int LIBUSB_CALL hotplug_callback_detach(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
struct libusb_device_descriptor desc;
int rc;
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS == rc) {
printf ("Device detached: %04x:%04x\n", desc.idVendor, desc.idProduct);
} else {
printf ("Device detached\n");
fprintf (stderr, "Error getting device descriptor: %s\n",
libusb_strerror((enum libusb_error)rc));
}
if (handle) {
libusb_close (handle);
handle = NULL;
}
attach_dev = NULL;
printf("attatch_dev NULL\n");
return 0;
}
int main(void)
{
libusb_hotplug_callback_handle hp[2];
int rc;
libusb_context *ctx;
struct libusb_device_descriptor desc;
rc = libusb_init(&ctx);
if (LIBUSB_SUCCESS != rc)
{
printf ("failed to initialise libusb: %s\n",
libusb_strerror((enum libusb_error)rc));
return -1;
}
libusb_set_option(ctx, LIBUSB_OPTION_NO_DEVICE_DISCOVERY, 1);
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf ("Hotplug capabilities are not supported on this platform\n");
libusb_exit (NULL);
return -1;
}
rc = libusb_hotplug_register_callback (ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 1, DEVICE_VID,
DEVICE_PID, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, NULL, &hp[0]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 0\n");
libusb_exit (NULL);
return -1;
}
rc = libusb_hotplug_register_callback (ctx, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 1, DEVICE_VID,
DEVICE_PID,LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback_detach, NULL, &hp[1]);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error registering callback 1\n");
libusb_exit (NULL);
return -1;
}
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 5000;
while (1) {
fflush(stdout);
rc= libusb_handle_events_timeout_completed(ctx,&tv,NULL);
if(rc!=LIBUSB_SUCCESS){
printf("[lib_usb] libusb_handle_events error: %s\n", libusb_error_name(rc));
}
//device attached, delayed
if(delaycnt > 0) {
delaycnt--;
if(delaycnt == 0) {
printf("main thread get serial: %X\n", (int)attach_dev);
rc = libusb_open (attach_dev, &handle);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "No access to device: %s\n",
libusb_strerror((enum libusb_error)rc));
}
else {
printf("libusb open sucess\n");
rc = libusb_get_device_descriptor(libusb_get_device(handle), &desc);
if (LIBUSB_SUCCESS == rc) {
printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
}
else {
printf ("Device attached: error getting device descriptor:%s\n", libusb_strerror((enum libusb_error)rc));
}
char serial[256] = {0};
libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
(uint8_t*)serial, sizeof(serial));
printf("device serial: %s, serialNumber:%d\n", serial, desc.iSerialNumber);
// 每次打开设备时配置接口
libusb_set_auto_detach_kernel_driver(handle, 1);//启用自动模式
int r = libusb_claim_interface(handle, 0);
if(r != LIBUSB_SUCCESS){
printf("libusb_claim_interface failed:%s\n", libusb_error_name(r));
}
if(r == LIBUSB_ERROR_BUSY) {
printf("lhandle detach\n");
libusb_detach_kernel_driver(handle, 0); //手动立即解除绑定
libusb_claim_interface(handle, 0);
}
}
}
}
}
if (handle) {
libusb_close (handle);
}
libusb_exit (NULL);
return 0;
}
运行日志如下:
main thread get serial: 35DACAE0
libusb open sucess
Device attached: 1fc9:0188
device serial: YU123456, serialNumber:3
Device detached: 1fc9:0188
attatch_dev NULL
main thread get serial: 48002460
libusb open sucess
Device attached: 1fc9:0188
device serial: YU123456, serialNumber:3
Device detached: 1fc9:0188
attatch_dev NULL
main thread get serial: 480037B0
libusb open sucess
Device attached: 1fc9:0188
device serial: YU123456, serialNumber:3


9114

被折叠的 条评论
为什么被折叠?



