libusb学习笔记(4)

API说明:

先检查是否支持热插拔。
用 LIBUSB_CAP_HAS_HOTPLUG 参数来调用 libusb_has_capability() 以确认是否支持热插拔。

libusb_context *libusbCtx = NULL;
libusb_init(&libusbCtx);
if(libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)){
    printf("支持热插拔\n");
}
libusb_exit(libusbCtx);

int libusb_hotplug_register_callback(libusb_context *ctx, ...);
注册一个热插拔回调函数。

int libusb_hotplug_register_callback(
    libusb_context *ctx,        // libusb环境上下文
    int             events,     // 触发此回调的热插拔事件
    int             flags,      // 热插拔标志
    int             vendor_id,  // 要匹配的VID,  或设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有。
    int             product_id, // 要匹配的PID,  或设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有。
    int             dev_class,  // 要匹配的class,或设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有。
    libusb_hotplug_callback_fn      cb_fn,          // 回调函数
    void                           *user_data,      // 传输给回调函数的用户数据。
    libusb_hotplug_callback_handle *callback_handle // 用于返回回调句柄。
);

// 触发回调的事件
enum libusb_hotplug_event{
    LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = (1<<0), // 设备已插入,可以使用。
    LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT    = (1<<1)  // 设备已离开,不再可用。
}

// 热插拔标志
enum libusb_hotplug_flag{
    LIBUSB_HOTPLUG_ENUMERATE = (1<<0) // 枚举所有已插入的设备,若匹配也触发回调。
}

// 匹配标志
#define LIBUSB_HOTPLUG_NO_FLAGS   0 // 不使用任何标志
#define LIBUSB_HOTPLUG_MATCH_ANY -1 // 匹配所有

// 回调函数
typedef int (*libusb_hotplug_callback_fn)(
    libusb_context       *ctx,      // libusb环境上下文
    libusb_device        *device,   // 发生事件的设备
    libusb_hotplug_event  event,    // 插入或拔出事件
    void                 *user_data // 用户数据。
);

void libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle);
取消热插拔回调的注册。

void* libusb_hotplug_get_user_data(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle);
获取与热插拔回调关联的用户数据。
用户数据就是 *user_data 参数所指数据。

代码举例:

/*
先检查是否支持热插拔。
    用 LIBUSB_CAP_HAS_HOTPLUG 参数来调用 libusb_has_capability() 以确认是否支持热插拔。
    libusb_context *libusbCtx = NULL;
    libusb_init(&libusbCtx);
    if(libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)){
        printf("支持热插拔\n");
    }
    libusb_exit(libusbCtx);

int libusb_hotplug_register_callback(libusb_context *ctx, ...);
    注册一个热插拔回调函数。

int libusb_hotplug_register_callback(
    libusb_context *ctx,        // libusb环境上下文
    int             events,     // 触发此回调的热插拔事件
    int             flags,      // 热插拔标志
    int             vendor_id,  // 要匹配的VID,  或设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有。
    int             product_id, // 要匹配的PID,  或设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有。
    int             dev_class,  // 要匹配的class,或设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有。
    libusb_hotplug_callback_fn      cb_fn,          // 回调函数
    void                           *user_data,      // 传输给回调函数的用户数据。
    libusb_hotplug_callback_handle *callback_handle // 用于返回回调句柄。
);

// 触发回调的事件
enum libusb_hotplug_event{
    LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = (1<<0), // 设备已插入,可以使用。
    LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT    = (1<<1)  // 设备已离开,不再可用。
}

// 热插拔标志
enum libusb_hotplug_flag{
    LIBUSB_HOTPLUG_ENUMERATE = (1<<0) // 枚举所有已插入的设备,若匹配也触发回调。
}

// 匹配标志
#define LIBUSB_HOTPLUG_NO_FLAGS   0 // 不使用任何标志
#define LIBUSB_HOTPLUG_MATCH_ANY -1 // 匹配所有

// 回调函数
typedef int (*libusb_hotplug_callback_fn)(
    libusb_context       *ctx,      // libusb环境上下文
    libusb_device        *device,   // 发生事件的设备
    libusb_hotplug_event  event,    // 插入或拔出事件
    void                 *user_data // 用户数据。
);

void libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle);
    取消热插拔回调的注册。

void* libusb_hotplug_get_user_data(libusb_context *ctx, libusb_hotplug_callback_handle callback_handle);    
    获取与热插拔回调关联的用户数据。
    用户数据就是 *user_data 参数所指数据。
*/

#include 
#include 
#include 
#include 
#include "libusb.h"

static char* getLocalTimeString(void){
    static char buffer[32];
    struct tm localDate;
    time_t second = time(NULL);
    localtime_r(&second, &localDate);
    strftime(buffer, 30, "<%H:%M:%S>", &localDate);
    return buffer;
}

// 热插拔回调函数
static int hotplugCallback(
    libusb_context       *libusbCtx, 
    libusb_device        *dev, 
    libusb_hotplug_event  event, 
    void                 *userData
){
    uint8_t bus = libusb_get_bus_number(dev);
    uint8_t addr = libusb_get_device_address(dev);
    struct libusb_device_descriptor deviceDescriptor;
    memset(&deviceDescriptor, 0, sizeof(struct libusb_device_descriptor));
    libusb_get_device_descriptor(dev, &deviceDescriptor);
    
    // '+'表示插入,'-'表示拔出。
    printf("%s %c /dev/bus/usb/%03u/%03u %04x:%04x usb%u.%u class:%02x\n", 
        getLocalTimeString(), 
        (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED ? '+' : '-'),
        bus, addr, 
        deviceDescriptor.idVendor, 
        deviceDescriptor.idProduct, 
        (deviceDescriptor.bcdUSB & 0x0f00) >> 8, 
        (deviceDescriptor.bcdUSB & 0x00f0) >> 4, 
        deviceDescriptor.bDeviceClass
    );
    
    return 0;
}

int main(int argc, char* argv[]){
    // 设置等待事件的次数
    int eventCount = 30;
    if(argc >= 2){
        eventCount = atoi(argv[1]);
        if(eventCount >= 10000) eventCount = 10000;
        else if(eventCount < 1) eventCount = 1;
    }
    
    // 初始化libusb环境上下文
    libusb_context *libusbCtx = NULL;
    int errCode = libusb_init(&libusbCtx);
    if(errCode) return -1;
    
    // 检查是否支持热插拔
    if(libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)){
        printf("支持热插拔\n");
    }else{
        printf("不支持热插拔\n");
        libusb_exit(libusbCtx);
        return -2;
    }
    
    // 注册热插拔回调函数
    libusb_hotplug_callback_handle callbackHandle = 0;
    errCode = libusb_hotplug_register_callback(
        libusbCtx,                            // 环境上下文
        LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | // 插入事件
        LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,     // 拔出事件
        LIBUSB_HOTPLUG_ENUMERATE,             // 枚举已插入的设备
        LIBUSB_HOTPLUG_MATCH_ANY,             // 匹配所有VID
        LIBUSB_HOTPLUG_MATCH_ANY,             // 匹配所有PID
        LIBUSB_HOTPLUG_MATCH_ANY,             // 匹配所有CLass
        hotplugCallback,                      // 回调函数
        NULL,                                 // 调用回调函数时传递给回调函数的用户数据
        &callbackHandle                       // 返回回调句柄
    );
    if(errCode){
        printf("注册热插拔回调函数失败\n");
        libusb_exit(libusbCtx);
        return -3;
    }
    
    // 等待事件?
    while(eventCount-- > 0){
        libusb_handle_events_completed(libusbCtx, NULL);
    }
    
    // 取消热插拔回调
    libusb_hotplug_deregister_callback(libusbCtx, callbackHandle);
    libusb_exit(libusbCtx);
    return 0;
}
INCLUDE=-I/usr/include/libusb-1.0/
LIBDIR=-L/usr/lib/x86_64-linux-gnu/ -lusb-1.0

all: 
    gcc -o test1.exe test1.c $(INCLUDE) $(LIBDIR) -Wall
    gcc -o test2.exe test2.c $(INCLUDE) $(LIBDIR) -Wall
    gcc -o test3.exe test3.c $(INCLUDE) $(LIBDIR) -Wall
    gcc -o test4.exe test4.c $(INCLUDE) $(LIBDIR) -Wall

运行结果:

test@test-PC:~/TMP/libusb$ ./test4.exe 
支持热插拔
<14:56:07> + /dev/bus/usb/002/001 1d6b:0003 usb3.1 class:09
<14:56:07> + /dev/bus/usb/001/003 1c4f:0002 usb1.1 class:00
<14:56:07> + /dev/bus/usb/001/036 05e3:0610 usb2.1 class:09
<14:56:07> + /dev/bus/usb/001/004 093a:2510 usb2.0 class:00
<14:56:07> + /dev/bus/usb/001/001 1d6b:0002 usb2.0 class:09
<14:56:28> - /dev/bus/usb/001/036 05e3:0610 usb2.1 class:09
<14:56:29> + /dev/bus/usb/001/049 05e3:0610 usb2.1 class:09
<14:56:30> + /dev/bus/usb/001/050 0781:5567 usb2.0 class:00
<14:56:42> - /dev/bus/usb/001/004 093a:2510 usb2.0 class:00
<14:56:43> + /dev/bus/usb/001/051 093a:2510 usb2.0 class:00
<14:56:44> + /dev/bus/usb/001/052 096e:0209 usb1.1 class:00
<14:56:49> - /dev/bus/usb/001/052 096e:0209 usb1.1 class:00
<14:56:49> + /dev/bus/usb/001/053 058f:6387 usb2.0 class:00
<14:56:52> + /dev/bus/usb/001/054 096e:0209 usb1.1 class:00
<14:56:53> - /dev/bus/usb/001/050 0781:5567 usb2.0 class:00
<14:56:57> + /dev/bus/usb/001/055 0781:5567 usb2.0 class:00
<14:57:00> - /dev/bus/usb/001/053 058f:6387 usb2.0 class:00
<14:57:04> + /dev/bus/usb/001/056 058f:6387 usb2.0 class:00
<14:57:13> - /dev/bus/usb/001/054 096e:0209 usb1.1 class:00
<14:57:15> - /dev/bus/usb/001/055 0781:5567 usb2.0 class:00
<14:57:18> - /dev/bus/usb/001/056 058f:6387 usb2.0 class:00
<14:57:23> + /dev/bus/usb/001/057 0000:3825 usb1.1 class:00
<14:57:36> - /dev/bus/usb/001/057 0000:3825 usb1.1 class:00
<14:58:07> - /dev/bus/usb/001/051 093a:2510 usb2.0 class:00
<14:58:07> - /dev/bus/usb/001/049 05e3:0610 usb2.1 class:09
<14:58:11> + /dev/bus/usb/001/058 093a:2510 usb2.0 class:00
<14:59:11> + /dev/bus/usb/001/059 05e3:0610 usb2.1 class:09
<14:59:11> + /dev/bus/usb/001/060 096e:0209 usb1.1 class:00
<14:59:20> + /dev/bus/usb/001/061 0781:5567 usb2.0 class:00
<14:59:26> - /dev/bus/usb/001/060 096e:0209 usb1.1 class:00
<14:59:27> + /dev/bus/usb/001/062 096e:0209 usb1.1 class:00
<14:59:28> + /dev/bus/usb/001/063 096e:0209 usb1.1 class:00
<14:59:44> - /dev/bus/usb/001/063 096e:0209 usb1.1 class:00
<14:59:44> - /dev/bus/usb/001/062 096e:0209 usb1.1 class:00
<14:59:45> - /dev/bus/usb/001/061 0781:5567 usb2.0 class:00
test@test-PC:~/TMP/libusb$ 

你可能感兴趣的:(libusb学习笔记(4))