有的時候我們需要通過HUB接多個完全一樣的UVC設備,即每個設備的VID和PID等信息是完全一樣的,libuvc和libusb原生就支持同vidpid設備,?且libuvc提供了查找多個設備的接口uvc_find_devices,?我們就來實現一個小的Demo進行測試。
代碼見:https://github.com/qinyunti/uvc_demo.git
代碼詳見test_samevidpid.c
test_samevidpid_main中
先初始化上下文
? ? res =?uvc_init(&ctx,?NULL);?? ??if?(res 0) {? ? ? ??uvc_perror(res,?"uvc_init");? ? ? ??return?res;? ? }?printf("UVC initialized\r\n");
和最后的退出釋放對應
? ? uvc_exit(ctx);? ??printf("UVC exited");
然后是查找設備,這里使用uvc_find_devices查找指定VID和PID的多個設備SN為空不指定。
這里傳入&devs是uvc_device_t ***類型
devs是uvc_device_t **類型,所以函數調用后返回之devs指向的是多個
uvc_device_t *的設備列表。即每一個devs[i]都是一個uvc_device_t *的設備。
?res =?uvc_find_devices(? ? ? ? ctx, &devs,? ? ? ??0x1993,?0x0101,?NULL);?? ??if(devs ==?NULL){? ? ? ??uvc_exit(ctx);? ? ? ??printf("no device founded");? ? }
計算有多少個設備
? ??for(int?i=0; ; i++){? ? ? ??if(devs[i] !=?NULL){? ? ? ? ? ? dev_num++;? ? ? ? }else{? ? ? ? ? ??break;? ? ? ? }}
和解引用設備對應
? ? ? ??for(int?i=0; i? ? ? ? {? ? ? ? ? ? uvc_unref_device(devs[i]);? ? ? ? }
然后是循環打開多個uvc設備和啟動流
? ??if?(res 0)? ? {? ? ? ??uvc_perror(res,?"uvc_find_devices");? ? }? ??else? ? {? ? ? ??printf("Device found\r\n");? ? ? ??for(int?i=0; i? ? ? ? {? ? ? ? ? ? res =?uvc_open(devs[i], &devh[i]);? ? ? ? ? ??if?(res 0)? ? ? ? ? ? {? ? ? ? ? ? ? ??uvc_perror(res,?"uvc_open");? ? ? ? ? ? }? ? ? ? ? ??else? ? ? ? ? ? {? ? ? ? ? ? ? ??printf("Device opened %d\r\n",dev_num);?? ? ? ? ? ? ? ??uvc_print_diag(devh[i], stderr);?? ? ? ? ? ? ? ? res =?uvc_get_stream_ctrl_format_size(? ? ? ? ? ? ? ? ? ? devh[i], &ctrl[i], UVC_FRAME_FORMAT_MJPEG,?1280,?720,?0? ? ? ? ? ? ? ? ? ? );?? ? ? ? ? ? ? ??uvc_print_stream_ctrl(&ctrl[i], stderr);?? ? ? ? ? ? ? ??if?(res 0)? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ??uvc_perror(res,?"get_mode");? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ??else? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? res =?uvc_start_streaming(devh[i], &ctrl[i], cb, (void*)i,?0);?? ? ? ? ? ? ? ? ? ??if?(res 0)? ? ? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ??uvc_perror(res,?"start_streaming");? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ??else? ? ? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ??printf("Streaming for 10 seconds...");? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }
執行10S
Sleep(10000);
和停止流對應
? ? ? ??for(int?i=0; i? ? ? ? {? ? ? ? ? ? uvc_stop_streaming(devh[i]);? ? ? ? ? ??printf("Done streaming %d.\r\n",i);? ? ? ? }
和關閉uvc設備對應
? ? ? ??for(int?i=0; i? ? ? ? {? ? ? ? ? ? uvc_unref_device(devs[i]);? ? ? ? }
回調函數中
static?void?cb(uvc_frame_t?*frame,?void?*ptr)?{? ??uvc_frame_t?*bgr;? ??uvc_error_t?ret;?? ??printf("callback! length = %zu, ptr = %p\n", frame->data_bytes, ptr);?? ? bgr =?uvc_allocate_frame(frame->width * frame->height *?3);? ??if?(!bgr) {? ? ? ??printf("unable to allocate bgr frame!");? ? ? ??return;? ? }?? ??/* 格式解析 */? ? ret =?uvc_any2bgr(frame, bgr);? ??if?(ret) {? ? ? ??uvc_perror(ret,?"uvc_any2bgr");? ? ? ??uvc_free_frame(bgr);? ? ? ??return;? ? }? ??// 顯示等操作? ??uvc_free_frame(bgr);}
我們通過ptr參數區分是哪一個設備,打印如下
printf("callback! length = %zu, ptr = %p\n", frame->data_bytes, ptr);
使用HUB接入兩個一樣的UVC設備,
注意參照readme修改PID和VID,重新編譯

使用build/Desktop_Qt_6_6_1_MinGW_64_bit-Debug/debug/uvc.exe測試
可以看到回調打印如下,兩個設備都工作OK。

Libusb和libuvc都原生支持同cidpid的多設備,使用uvc_find_devices可以打開多個設備,不過注意傳入參數是三級指針,使用時需要注意。