lib: re-use libusb device handle from libuvc

Apparently on Windows a libusb device cannot be
opened twice with different interfaces like on
Linux. Thus, get the libusb device handle from
libuvc.
This commit is contained in:
Steve Markgraf 2024-12-14 18:27:35 +01:00
parent 5d80559044
commit a5375f79cc

View file

@ -412,12 +412,6 @@ int hsdaoh_clear_endpoint_halt(hsdaoh_dev_t *dev)
} }
} }
r = libusb_claim_interface(dev->devh, dev->hid_interface);
if (r < 0) {
fprintf(stderr, "usb_claim_interface hid error %d\n", r);
return r;
}
r = libusb_claim_interface(dev->devh, 1); r = libusb_claim_interface(dev->devh, 1);
if (r < 0) { if (r < 0) {
fprintf(stderr, "usb_claim_interface 1 error %d\n", r); fprintf(stderr, "usb_claim_interface 1 error %d\n", r);
@ -437,8 +431,7 @@ int _hsdaoh_open_uvc_device(hsdaoh_dev_t *dev)
{ {
uvc_error_t r; uvc_error_t r;
/* Initialize UVC context. In theory it should be possible to re-use our /* Initialize UVC context */
* libusb context, but for whatever reason that does not work */
r = uvc_init(&dev->uvc_ctx, NULL); r = uvc_init(&dev->uvc_ctx, NULL);
if (r < 0) { if (r < 0) {
@ -456,10 +449,9 @@ int _hsdaoh_open_uvc_device(hsdaoh_dev_t *dev)
/* Try to open the device: requires exclusive access */ /* Try to open the device: requires exclusive access */
r = uvc_open(dev->uvc_dev, &dev->uvc_devh); r = uvc_open(dev->uvc_dev, &dev->uvc_devh);
if (r < 0) { if (r < 0)
uvc_perror(r, "uvc_open"); /* unable to open device */ uvc_perror(r, "uvc_open"); /* unable to open device */
} }
}
return (int)r; return (int)r;
} }
@ -513,24 +505,31 @@ int hsdaoh_open(hsdaoh_dev_t **out_dev, uint32_t index)
device = NULL; device = NULL;
} }
dev->vid = dd.idVendor;
dev->pid = dd.idProduct;
libusb_free_device_list(list, 1);
libusb_exit(dev->ctx);
if (!device) { if (!device) {
r = -1; r = -1;
goto err; goto err;
} }
dev->vid = dd.idVendor; r = _hsdaoh_open_uvc_device(dev);
dev->pid = dd.idProduct;
r = libusb_open(device, &dev->devh);
libusb_free_device_list(list, 1);
if (r < 0) { if (r < 0) {
fprintf(stderr, "usb_open error %d\n", r); if (r == LIBUSB_ERROR_ACCESS)
if(r == LIBUSB_ERROR_ACCESS)
fprintf(stderr, "Please fix the device permissions, e.g. " fprintf(stderr, "Please fix the device permissions, e.g. "
"by installing the udev rules file\n"); "by installing the udev rules file\n");
goto err; goto err;
} }
dev->devh = uvc_get_libusb_handle(dev->uvc_devh);
if (!dev->devh) {
fprintf(stderr, "Failed to get libusb device handle\n");
goto err;
}
dev->hid_interface = 4; dev->hid_interface = 4;
if (libusb_kernel_driver_active(dev->devh, dev->hid_interface) == 1) { if (libusb_kernel_driver_active(dev->devh, dev->hid_interface) == 1) {
@ -541,12 +540,15 @@ int hsdaoh_open(hsdaoh_dev_t **out_dev, uint32_t index)
} }
} }
r = libusb_claim_interface(dev->devh, dev->hid_interface);
if (r < 0) {
fprintf(stderr, "usb_claim_interface hid error %d\n", r);
return r;
}
if (hsdaoh_clear_endpoint_halt(dev) < 0) if (hsdaoh_clear_endpoint_halt(dev) < 0)
goto err; goto err;
_hsdaoh_open_uvc_device(dev);
//dev->rate = DEFAULT_SAMPLERATE; //dev->rate = DEFAULT_SAMPLERATE;
dev->dev_lost = 0; dev->dev_lost = 0;
@ -555,12 +557,8 @@ found:
return 0; return 0;
err: err:
if (dev) { if (dev)
if (dev->ctx)
libusb_exit(dev->ctx);
free(dev); free(dev);
}
return r; return r;
} }
@ -573,11 +571,6 @@ int hsdaoh_close(hsdaoh_dev_t *dev)
if (HSDAOH_INACTIVE != dev->async_status) if (HSDAOH_INACTIVE != dev->async_status)
uvc_stop_streaming(dev->uvc_devh); uvc_stop_streaming(dev->uvc_devh);
uvc_close(dev->uvc_devh);
uvc_unref_device(dev->uvc_dev);
uvc_exit(dev->uvc_ctx);
libusb_release_interface(dev->devh, dev->hid_interface); libusb_release_interface(dev->devh, dev->hid_interface);
//TODO: only re-attach kernel driver if it was attached previously //TODO: only re-attach kernel driver if it was attached previously
@ -586,8 +579,10 @@ int hsdaoh_close(hsdaoh_dev_t *dev)
else else
fprintf(stderr, "Reattaching kernel driver failed!\n"); fprintf(stderr, "Reattaching kernel driver failed!\n");
libusb_close(dev->devh); uvc_close(dev->uvc_devh);
libusb_exit(dev->ctx); uvc_unref_device(dev->uvc_dev);
uvc_exit(dev->uvc_ctx);
free(dev); free(dev);
return 0; return 0;
@ -782,12 +777,5 @@ int hsdaoh_stop_stream(hsdaoh_dev_t *dev)
return 0; return 0;
} }
/* if called while in pending state, change the state forcefully */
#if 0
if (HSDAOH_INACTIVE != dev->async_status) {
dev->async_status = HSDAOH_INACTIVE;
return 0;
}
#endif
return -2; return -2;
} }