Intel® RealSense™ Cross Platform API
Intel Realsense Cross-platform API
libuvc_internal.h
Go to the documentation of this file.
1 
5 #ifndef LIBUVC_INTERNAL_H
6 #define LIBUVC_INTERNAL_H
7 
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdint.h>
13 #include <thread>
14 #include <mutex>
15 #include <condition_variable>
16 #include <signal.h>
17 #include "../third-party/libusb/libusb/libusb.h"
18 #include "utlist.h"
19 
21 #define DW_TO_INT(p) ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
22 
23 #define SW_TO_SHORT(p) ((p)[0] | ((p)[1] << 8))
24 
25 #define QW_TO_QUAD(p) ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24) | \
26  ((p)[4] << 32) |((p)[5] << 40) |((p)[6] << 48) |((p)[7] << 56))
27 
29 #define SHORT_TO_SW(s, p) \
30  (p)[0] = (s); \
31  (p)[1] = (s) >> 8;
32 
33 #define INT_TO_DW(i, p) \
34  (p)[0] = (i); \
35  (p)[1] = (i) >> 8; \
36  (p)[2] = (i) >> 16; \
37  (p)[3] = (i) >> 24;
38 
40 #define QUAD_TO_QW(i, p) \
41  (p)[0] = (i); \
42  (p)[1] = (i) >> 8; \
43  (p)[2] = (i) >> 16; \
44  (p)[3] = (i) >> 24; \
45  (p)[4] = (i) >> 32; \
46  (p)[5] = (i) >> 40; \
47  (p)[6] = (i) >> 48; \
48  (p)[7] = (i) >> 56; \
49 
50 
51 #define DL_NTH(head, out, n) \
52  do { \
53  int dl_nth_i = 0; \
54  LDECLTYPE(head) dl_nth_p = (head); \
55  if ((n) < 0) { \
56  while (dl_nth_p && dl_nth_i > (n)) { \
57  dl_nth_p = dl_nth_p->prev; \
58  dl_nth_i--; \
59  } \
60  } else { \
61  while (dl_nth_p && dl_nth_i < (n)) { \
62  dl_nth_p = dl_nth_p->next; \
63  dl_nth_i++; \
64  } \
65  } \
66  (out) = dl_nth_p; \
67  } while (0);
68 
69 #ifdef UVC_DEBUGGING
70 #include <libgen.h>
71 #define UVC_DEBUG(format, ...) fprintf(stderr, "[%s:%d/%s] " format "\n", basename(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__)
72 #define UVC_ENTER() fprintf(stderr, "[%s:%d] begin %s\n", basename(__FILE__), __LINE__, __FUNCTION__)
73 #define UVC_EXIT(code) fprintf(stderr, "[%s:%d] end %s (%d)\n", basename(__FILE__), __LINE__, __FUNCTION__, code)
74 #define UVC_EXIT_VOID() fprintf(stderr, "[%s:%d] end %s\n", basename(__FILE__), __LINE__, __FUNCTION__)
75 #else
76 #define UVC_DEBUG(format, ...)
77 #define UVC_ENTER()
78 #define UVC_EXIT_VOID()
79 #define UVC_EXIT(code)
80 #endif
81 
82 /* http://stackoverflow.com/questions/19452971/array-size-macro-that-rejects-pointers */
83 #define IS_INDEXABLE(arg) (sizeof(arg[0]))
84 #define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
85 #define ARRAYSIZE(arr) (sizeof(arr) / (IS_ARRAY(arr) ? sizeof(arr[0]) : 0))
86 
88 enum uvc_int_subclass_code {
89  UVC_SC_UNDEFINED = 0x00,
90  UVC_SC_VIDEOCONTROL = 0x01,
91  UVC_SC_VIDEOSTREAMING = 0x02,
92  UVC_SC_VIDEO_INTERFACE_COLLECTION = 0x03
93 };
94 
96 enum uvc_int_proto_code {
97  UVC_PC_PROTOCOL_UNDEFINED = 0x00
98 };
99 
101 enum uvc_vc_desc_subtype {
102  UVC_VC_DESCRIPTOR_UNDEFINED = 0x00,
103  UVC_VC_HEADER = 0x01,
104  UVC_VC_INPUT_TERMINAL = 0x02,
105  UVC_VC_OUTPUT_TERMINAL = 0x03,
106  UVC_VC_SELECTOR_UNIT = 0x04,
107  UVC_VC_PROCESSING_UNIT = 0x05,
108  UVC_VC_EXTENSION_UNIT = 0x06
109 };
110 
112 enum uvc_ep_desc_subtype {
113  UVC_EP_UNDEFINED = 0x00,
114  UVC_EP_GENERAL = 0x01,
115  UVC_EP_ENDPOINT = 0x02,
116  UVC_EP_INTERRUPT = 0x03
117 };
118 
120 enum uvc_vc_ctrl_selector {
121  UVC_VC_CONTROL_UNDEFINED = 0x00,
122  UVC_VC_VIDEO_POWER_MODE_CONTROL = 0x01,
123  UVC_VC_REQUEST_ERROR_CODE_CONTROL = 0x02
124 };
125 
127 enum uvc_term_ctrl_selector {
128  UVC_TE_CONTROL_UNDEFINED = 0x00
129 };
130 
132 enum uvc_su_ctrl_selector {
133  UVC_SU_CONTROL_UNDEFINED = 0x00,
134  UVC_SU_INPUT_SELECT_CONTROL = 0x01
135 };
136 
138 enum uvc_xu_ctrl_selector {
139  UVC_XU_CONTROL_UNDEFINED = 0x00
140 };
141 
143 enum uvc_vs_ctrl_selector {
144  UVC_VS_CONTROL_UNDEFINED = 0x00,
145  UVC_VS_PROBE_CONTROL = 0x01,
146  UVC_VS_COMMIT_CONTROL = 0x02,
147  UVC_VS_STILL_PROBE_CONTROL = 0x03,
148  UVC_VS_STILL_COMMIT_CONTROL = 0x04,
149  UVC_VS_STILL_IMAGE_TRIGGER_CONTROL = 0x05,
150  UVC_VS_STREAM_ERROR_CODE_CONTROL = 0x06,
151  UVC_VS_GENERATE_KEY_FRAME_CONTROL = 0x07,
152  UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL = 0x08,
153  UVC_VS_SYNC_DELAY_CONTROL = 0x09
154 };
155 
157 enum uvc_status_type {
158  UVC_STATUS_TYPE_CONTROL = 1,
159  UVC_STATUS_TYPE_STREAMING = 2
160 };
161 
163 #define UVC_STREAM_EOH (1 << 7)
164 #define UVC_STREAM_ERR (1 << 6)
165 #define UVC_STREAM_STI (1 << 5)
166 #define UVC_STREAM_RES (1 << 4)
167 #define UVC_STREAM_SCR (1 << 3)
168 #define UVC_STREAM_PTS (1 << 2)
169 #define UVC_STREAM_EOF (1 << 1)
170 #define UVC_STREAM_FID (1 << 0)
171 
173 #define UVC_CONTROL_CAP_GET (1 << 0)
174 #define UVC_CONTROL_CAP_SET (1 << 1)
175 #define UVC_CONTROL_CAP_DISABLED (1 << 2)
176 #define UVC_CONTROL_CAP_AUTOUPDATE (1 << 3)
177 #define UVC_CONTROL_CAP_ASYNCHRONOUS (1 << 4)
178 
179 struct uvc_streaming_interface;
180 struct uvc_device_info;
181 
183 typedef struct uvc_streaming_interface {
184  struct uvc_device_info *parent;
185  struct uvc_streaming_interface *prev, *next;
187  uint8_t bInterfaceNumber;
189  struct uvc_format_desc *format_descs;
191  uint8_t bEndpointAddress;
192  uint8_t bTerminalLink;
193 } uvc_streaming_interface_t;
194 
196 typedef struct uvc_control_interface {
197  struct uvc_device_info *parent;
198  struct uvc_input_terminal *input_term_descs;
199  // struct uvc_output_terminal *output_term_descs;
200  struct uvc_selector_unit *selector_unit_descs;
201  struct uvc_processing_unit *processing_unit_descs;
202  struct uvc_extension_unit *extension_unit_descs;
203  uint16_t bcdUVC;
204  uint32_t dwClockFrequency;
205  uint8_t bEndpointAddress;
207  uint8_t bInterfaceNumber;
208 } uvc_control_interface_t;
209 
210 struct uvc_stream_ctrl;
211 
212 struct uvc_device {
213  struct uvc_context *ctx;
214  int ref;
215  libusb_device *usb_dev;
216  int interface;
217 };
218 
219 typedef struct uvc_device_info {
221  struct libusb_config_descriptor *config;
223  uvc_control_interface_t ctrl_if;
225  uvc_streaming_interface_t *stream_ifs;
227  int camera_number;
228 } uvc_device_info_t;
229 
230 /*
231  set a high number of transfer buffers. This uses a lot of ram, but
232  avoids problems with scheduling delays on slow boards causing missed
233  transfers. A better approach may be to make the transfer thread FIFO
234  scheduled (if we have root).
235  We could/should change this to allow reduce it to, say, 5 by default
236  and then allow the user to change the number of buffers as required.
237  */
238 #define LIBUVC_NUM_TRANSFER_BUFS 1
239 
240 #define LIBUVC_XFER_BUF_SIZE ( 16 * 1024 * 1024 )
241 
242 struct uvc_stream_handle {
243  struct uvc_device_handle *devh;
244  struct uvc_stream_handle *prev, *next;
245  struct uvc_streaming_interface *stream_if;
246 
248  uint8_t running;
250  struct uvc_stream_ctrl cur_ctrl;
251 
252  /* listeners may only access hold*, and only when holding a
253  * lock on cb_mutex (probably signaled with cb_cond) */
254  uint8_t fid;
255  uint32_t seq, hold_seq;
256  uint32_t pts, hold_pts;
257  uint32_t last_scr, hold_last_scr;
258  uint8_t *metadata_buf;
259  size_t metadata_bytes,metadata_size;
260  size_t got_bytes, hold_bytes;
261  uint8_t *outbuf, *holdbuf;
262  std::mutex cb_mutex;
263  std::condition_variable cb_cond;
264  std::thread cb_thread;
265  uint32_t last_polled_seq;
266  uvc_frame_callback_t *user_cb;
267  void *user_ptr;
268  struct libusb_transfer *transfers[LIBUVC_NUM_TRANSFER_BUFS];
269  uint8_t *transfer_bufs[LIBUVC_NUM_TRANSFER_BUFS];
270  struct uvc_frame frame;
272 };
273 
278 struct uvc_device_handle {
279  struct uvc_device *dev;
280  struct uvc_device_handle *prev, *next;
282  libusb_device_handle *usb_devh;
283  struct uvc_device_info *info;
284  struct libusb_transfer *status_xfer;
285  uint8_t status_buf[32];
287  uvc_status_callback_t *status_cb;
288  void *status_user_ptr;
290  uvc_button_callback_t *button_cb;
291  void *button_user_ptr;
292 
293  uvc_stream_handle_t *streams;
295  uint8_t is_isight;
296 };
297 
299 struct uvc_context {
301  struct libusb_context *usb_ctx;
303  uint8_t own_usb_ctx;
305  uvc_device_handle_t *open_devices;
306  std::thread handler_thread;
307  int kill_handler_thread;
308 };
309 
310 uvc_error_t uvc_query_stream_ctrl(
311  uvc_device_handle_t *devh,
312  uvc_stream_ctrl_t *ctrl,
313  uint8_t probe,
314  enum uvc_req_code req);
315 
316 void uvc_start_handler_thread(uvc_context_t *ctx);
317 uvc_error_t uvc_claim_if(uvc_device_handle_t *devh, int idx);
318 uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx);
319 
320 #endif // !def(LIBUVC_INTERNAL_H)
321 
void() uvc_status_callback_t(enum uvc_status_class status_class, int event, int selector, enum uvc_status_attribute status_attribute, void *data, size_t data_len, void *user_ptr)
Definition: libuvc.h:389
uvc_req_code
Definition: libuvc.h:197
Definition: libuvc.h:326
void() uvc_button_callback_t(int button, int state, void *user_ptr)
Definition: libuvc.h:399
enum uvc_error uvc_error_t
Definition: libuvc.h:356
Definition: libuvc.h:165
void() uvc_frame_callback_t(struct uvc_frame *frame, void *user_ptr)
Definition: libuvc.h:461
struct uvc_stream_handle uvc_stream_handle_t
Definition: libuvc.h:323
enum uvc_frame_format frame_format
Definition: libuvc.h:439
struct uvc_context uvc_context_t
Definition: libuvc.h:300
Definition: libuvc.h:363
Definition: libuvc.h:345
struct uvc_device_handle uvc_device_handle_t
Definition: libuvc.h:315
Definition: libuvc.h:466
uvc_frame_format
Definition: libuvc.h:65
Definition: libuvc.h:425