4 #ifdef RS_USE_LIBUVC_BACKEND 17 static void check(
const char * call,
uvc_error_t status)
19 if (status < 0)
throw std::runtime_error(to_string() << call <<
"(...) returned " <<
uvc_strerror(status));
21 #define CALL_UVC(name, ...) check(#name, name(__VA_ARGS__)) 26 libusb_context * usb_context;
30 check(
"uvc_init",
uvc_init(&ctx,
nullptr));
32 int status = libusb_init(&usb_context);
33 if (status < 0)
throw std::runtime_error(to_string() <<
"libusb_init(...) returned " << libusb_error_name(status));
37 libusb_exit(usb_context);
52 this->channel_data_callback = callback;
55 static void poll_interrupts(libusb_device_handle *handle,
const std::vector<subdevice *> &
subdevices, uint16_t
timeout)
57 static const unsigned short interrupt_buf_size = 0x400;
58 uint8_t
buffer[interrupt_buf_size];
62 int res = libusb_interrupt_transfer(handle, 0x84, buffer, interrupt_buf_size, &num_bytes, timeout);
66 for (
auto & sub : subdevices)
67 if (sub->channel_data_callback)
68 sub->channel_data_callback(buffer, num_bytes);
72 if (res == LIBUSB_ERROR_TIMEOUT)
75 throw std::runtime_error(to_string() <<
"USB Interrupt end-point error " << libusb_strerror((libusb_error)res));
83 const std::shared_ptr<context> parent;
87 std::vector<int> claimed_interfaces;
89 std::thread data_channel_thread;
90 volatile bool data_stop;
93 std::shared_ptr<device> aux_device;
95 libusb_device_handle * usb_handle;
97 device(std::shared_ptr<context> parent,
uvc_device_t * uvcdevice) : parent(parent), uvcdevice(uvcdevice), usb_handle()
109 for(
auto interface_number : claimed_interfaces)
111 int status = libusb_release_interface(get_subdevice(0).handle->usb_devh, interface_number);
112 if(status < 0)
LOG_ERROR(
"libusb_release_interface(...) returned " << libusb_error_name(status));
115 for(
auto & sub : subdevices)
if(sub.handle)
uvc_close(sub.handle);
119 subdevice & get_subdevice(
int subdevice_index)
121 if (subdevice_index >= subdevices.size()) subdevices.resize(subdevice_index + 1);
123 if (subdevice_index == 3 && aux_device)
125 auto& sub = aux_device->get_subdevice(0);
126 subdevices[subdevice_index] = sub;
130 if (!subdevices[subdevice_index].handle) check(
"uvc_open2",
uvc_open2(uvcdevice, &subdevices[subdevice_index].handle, subdevice_index));
131 return subdevices[subdevice_index];
137 std::vector<subdevice *> data_channel_subs;
138 for (
auto & sub : subdevices)
140 if (sub.channel_data_callback)
142 data_channel_subs.push_back(&sub);
147 if (claimed_interfaces.size())
149 data_channel_thread = std::thread([
this, data_channel_subs]()
154 subdevice::poll_interrupts(this->usb_handle, data_channel_subs, 100);
162 if (data_channel_thread.joinable())
165 data_channel_thread.join();
175 int get_vendor_id(
const device & device) {
return device.vid; }
180 std::string usb_port = std::to_string(libusb_get_bus_number(device.uvcdevice->usb_dev)) +
"-" +
181 std::to_string(libusb_get_port_number(device.uvcdevice->usb_dev));
187 int status =
uvc_get_ctrl(const_cast<device &>(dev).get_subdevice(xu.subdevice).handle, xu.unit, ctrl, data, len,
UVC_GET_CUR);
188 if(status < 0)
throw std::runtime_error(to_string() <<
"uvc_get_ctrl(...) returned " << libusb_error_name(status));
191 void set_control(device & device,
const extension_unit & xu, uint8_t ctrl,
void * data,
int len)
193 int status =
uvc_set_ctrl(device.get_subdevice(xu.subdevice).handle, xu.unit, ctrl,
data,
len);
194 if(status < 0)
throw std::runtime_error(to_string() <<
"uvc_set_ctrl(...) returned " << libusb_error_name(status));
197 void claim_interface(device & device,
const guid & interface_guid,
int interface_number)
199 libusb_device_handle* dev_h =
nullptr;
203 dev_h = device.usb_handle;
207 dev_h = device.get_subdevice(0).handle->usb_devh;
209 int status = libusb_claim_interface(dev_h, interface_number);
210 if (status < 0)
throw std::runtime_error(to_string() <<
"libusb_claim_interface(...) returned " << libusb_error_name(status));
211 device.claimed_interfaces.push_back(interface_number);
214 void claim_aux_interface(device & device,
const guid & interface_guid,
int interface_number)
219 void bulk_transfer(device & device,
unsigned char endpoint,
void * data,
int length,
int *actual_length,
unsigned int timeout)
222 libusb_device_handle* dev_h =
nullptr;
226 dev_h = device.usb_handle;
230 dev_h = device.get_subdevice(0).handle->usb_devh;
233 int status = libusb_bulk_transfer(dev_h, endpoint, (
unsigned char *)data, length, actual_length, timeout);
235 if (status < 0)
throw std::runtime_error(to_string() <<
"libusb_bulk_transfer(...) returned " << libusb_error_name(status));
241 auto & sub = device.get_subdevice(subdevice_index);
242 check(
"get_stream_ctrl_format_size",
uvc_get_stream_ctrl_format_size(sub.handle, &sub.ctrl, reinterpret_cast<
const big_endian<uint32_t> &>(fourcc), width, height, fps));
243 sub.callback = callback;
248 device.subdevices[subdevice_index].set_data_channel_cfg(callback);
253 for(
auto i = 0; i < device.subdevices.size(); i++)
255 auto& sub = device.get_subdevice(i);
258 #if defined (ENABLE_DEBUG_SPAM) 264 reinterpret_cast<subdevice *>(user)->callback(frame->data, []{});
265 }, &sub, 0, num_transfer_bufs));
273 for(
auto & sub : device.subdevices)
283 device.start_data_acquisition();
288 device.stop_data_acquisition();
294 unsigned char buffer[4];
295 if(
sizeof(T)==1) buffer[0] =
value;
296 if(
sizeof(T)==2) SHORT_TO_SW(value, buffer);
297 if(
sizeof(T)==4) INT_TO_DW(value, buffer);
298 int status = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET,
UVC_SET_CUR, control << 8, unit << 8 | (subdevice * 2), buffer,
sizeof(T), 0);
299 if(status < 0)
throw std::runtime_error(to_string() <<
"libusb_control_transfer(...) returned " << libusb_error_name(status));
300 if(status !=
sizeof(T))
throw std::runtime_error(
"insufficient data written to usb");
303 template<
class T>
int get_pu(
uvc_device_handle_t * devh,
int subdevice, uint8_t unit, uint8_t control,
int uvc_get_thing)
306 unsigned char buffer[4];
307 int status = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, uvc_get_thing, control << 8, unit << 8 | (subdevice * 2), buffer,
sizeof(T), 0);
308 if(status < 0)
throw std::runtime_error(to_string() <<
"libusb_control_transfer(...) returned " << libusb_error_name(status));
309 if(status !=
sizeof(T))
throw std::runtime_error(
"insufficient data read from usb");
310 if(
sizeof(T)==1)
return buffer[0];
311 if(
sizeof(T)==2)
return SW_TO_SHORT(buffer);
312 if(
sizeof(T)==4)
return DW_TO_INT(buffer);
314 template<
class T>
void get_pu_range(
uvc_device_handle_t * devh,
int subdevice, uint8_t unit, uint8_t control,
int * min,
int * max,
int * step,
int * def)
324 auto handle =
const_cast<uvc::device &
>(device).get_subdevice(subdevice).handle;
325 int ct_unit = 0, pu_unit = 0;
343 default:
throw std::logic_error(
"invalid option");
347 void get_extension_control_range(
const device & device,
const extension_unit & xu,
char control,
int * min,
int * max,
int * step,
int * def)
349 throw std::logic_error(
"get_extension_control_range(...) is not implemented for this backend");
354 auto handle = device.get_subdevice(subdevice).handle;
355 int ct_unit = 0, pu_unit = 0;
374 assert(subdevice == 3);
377 default:
throw std::logic_error(
"invalid option");
383 auto handle =
const_cast<uvc::device &
>(device).get_subdevice(subdevice).handle;
384 int ct_unit = 0, pu_unit = 0;
403 default:
throw std::logic_error(
"invalid option");
413 return std::make_shared<context>();
421 std::vector<std::shared_ptr<device>>
query_devices(std::shared_ptr<context> context)
423 std::vector<std::shared_ptr<device>> devices;
427 for (
auto it = list; *it; ++it)
430 auto dev = std::make_shared<device>(context, *it);
432 devices.push_back(dev);
434 catch (std::runtime_error &
e)
440 std::shared_ptr<device>
fisheye =
nullptr;
442 for (
auto& dev : devices)
450 for (
auto& dev : devices)
452 dev->aux_device = fisheye;
std::shared_ptr< context > create_context()
uvc_error_t uvc_init(uvc_context_t **pctx, struct libusb_context *usb_ctx)
Initializes the UVC context.
void get_pu_control_range(const device &device, int subdevice, rs_option option, int *min, int *max, int *step, int *def)
uvc_error_t uvc_get_device_list(uvc_context_t *ctx, uvc_device_t ***list)
Get a list of the UVC devices attached to the system.
const uvc_input_terminal_t * uvc_get_input_terminals(uvc_device_handle_t *devh)
Get input terminal descriptors for the open device.
enum uvc_error uvc_error_t
void claim_aux_interface(device &device, const guid &interface_guid, int interface_number)
int uvc_set_ctrl(uvc_device_handle_t *devh, uint8_t unit, uint8_t ctrl, void *data, int len)
Perform a SET_CUR request to a terminal or unit.
void set_subdevice_mode(device &device, int subdevice_index, int width, int height, uint32_t fourcc, int fps, video_channel_callback callback)
GLint GLint GLsizei GLsizei height
struct uvc_processing_unit * next
void uvc_stop_streaming(uvc_device_handle_t *devh)
Stop streaming videoCloses all streams, ends threads and cancels pollers.
bool is_device_connected(device &device, int vid, int pid)
uvc_error_t uvc_start_streaming(uvc_device_handle_t *devh, uvc_stream_ctrl_t *ctrl, uvc_frame_callback_t *cb, void *user_ptr, uint8_t flags, int num_transfer_buffers)
const uint16_t VID_INTEL_CAMERA
GLsizei const GLchar *const * string
static const int REQ_TYPE_GET
struct uvc_device uvc_device_t
rs_option
Defines general configuration controls.
GLbitfield GLuint64 timeout
void uvc_free_device_list(uvc_device_t **list, uint8_t unref_devices)
Frees a list of device structures created with uvc_get_device_list.
std::string get_usb_port_id(const device &device)
void uvc_free_device_descriptor(uvc_device_descriptor_t *desc)
Frees a device descriptor created with uvc_get_device_descriptor.
const uint16_t ZR300_FISHEYE_PID
std::function< void(const unsigned char *data, const int size)> data_channel_callback
void set_subdevice_data_channel_handler(device &device, int subdevice_index, data_channel_callback callback)
void start_streaming(device &device, int num_transfer_bufs)
void start_data_acquisition(device &device)
void get_extension_control_range(const device &device, const extension_unit &xu, char control, int *min, int *max, int *step, int *def)
void uvc_unref_device(uvc_device_t *dev)
Decrement the reference count for a device device.
Implementation-specific UVC constants and structures.
const char * uvc_strerror(uvc_error_t err)
Return a string explaining an error in the UVC driver.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * data
void stop_streaming(device &device)
uint8_t uvc_get_bus_number(uvc_device_t *dev)
Get the number of the bus to which the device is attached.
uvc_error_t uvc_get_stream_ctrl_format_size(uvc_device_handle_t *devh, uvc_stream_ctrl_t *ctrl, uint32_t fourcc, int width, int height, int fps)
GLsizei const GLfloat * value
const uint16_t ZR300_CX3_PID
void uvc_close(uvc_device_handle_t *devh)
Close a device.
void claim_interface(device &device, const guid &interface_guid, int interface_number)
int get_pu_control(const device &device, int subdevice, rs_option option)
int get_product_id(const device &device)
void bulk_transfer(device &device, unsigned char endpoint, void *data, int length, int *actual_length, unsigned int timeout)
uvc_error_t uvc_open2(uvc_device_t *dev, uvc_device_handle_t **devh, int camera_number)
Open a UVC device, specifying the camera number, zero-based.
GLint GLint GLsizei width
void set_control(device &device, const extension_unit &xu, uint8_t ctrl, void *data, int len)
uint8_t uvc_get_device_address(uvc_device_t *dev)
Get the number assigned to the device within its bus.
int uvc_get_ctrl(uvc_device_handle_t *devh, uint8_t unit, uint8_t ctrl, void *data, int len, enum uvc_req_code req_code)
Perform a GET_* request from an extension unit.
void uvc_print_stream_ctrl(uvc_stream_ctrl_t *ctrl, FILE *stream)
Print the values in a stream control block.
struct uvc_context uvc_context_t
std::vector< std::shared_ptr< device > > query_devices(std::shared_ptr< context > context)
GLuint GLsizei GLsizei * length
void set_pu_control(device &device, int subdevice, rs_option option, int value)
const uvc_processing_unit_t * uvc_get_processing_units(uvc_device_handle_t *devh)
Get processing unit descriptors for the open device.
uvc_error_t uvc_get_device_descriptor(uvc_device_t *dev, uvc_device_descriptor_t **desc)
Get a descriptor that contains the general information about a deviceFree *desc with uvc_free_device_...
void uvc_exit(uvc_context_t *ctx)
Closes the UVC context, shutting down any active cameras.
struct uvc_device_handle uvc_device_handle_t
void get_control(const device &device, const extension_unit &xu, uint8_t ctrl, void *data, int len)
void stop_data_acquisition(device &device)
static const int REQ_TYPE_SET
std::function< void(const void *frame, std::function< void()> continuation)> video_channel_callback
int get_vendor_id(const device &device)