1 /** @file libuvc_internal.h 2 * @brief Implementation-specific UVC constants and structures. 3 * @cond include_hidden 4 */ 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 <pthread.h> 13 #include <signal.h> 14 #include "utlist.h" 15 16 /** Converts an unaligned four-byte little-endian integer into an int32 */ 17 #define DW_TO_INT(p) ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24)) 18 /** Converts an unaligned two-byte little-endian integer into an int16 */ 19 #define SW_TO_SHORT(p) ((p)[0] | ((p)[1] << 8)) 20 /** Converts an int16 into an unaligned two-byte little-endian integer */ 21 #define SHORT_TO_SW(s, p) \ 22 (p)[0] = (s); \ 23 (p)[1] = (s) >> 8; 24 /** Converts an int32 into an unaligned four-byte little-endian integer */ 25 #define INT_TO_DW(i, p) \ 26 (p)[0] = (i); \ 27 (p)[1] = (i) >> 8; \ 28 (p)[2] = (i) >> 16; \ 29 (p)[3] = (i) >> 24; 30 31 /** Selects the nth item in a doubly linked list. n=-1 selects the last item. */ 32 #define DL_NTH(head, out, n) \ 33 do { \ 34 int dl_nth_i = 0; \ 35 LDECLTYPE(head) dl_nth_p = (head); \ 36 if ((n) < 0) { \ 37 while (dl_nth_p && dl_nth_i > (n)) { \ 38 dl_nth_p = dl_nth_p->prev; \ 39 dl_nth_i--; \ 40 } \ 41 } else { \ 42 while (dl_nth_p && dl_nth_i < (n)) { \ 43 dl_nth_p = dl_nth_p->next; \ 44 dl_nth_i++; \ 45 } \ 46 } \ 47 (out) = dl_nth_p; \ 48 } while (0); 49 50 #ifdef UVC_DEBUGGING 51 #include <libgen.h> 52 #define UVC_DEBUG(format, ...) fprintf(stderr, "[%s:%d/%s] " format "\n", basename(__FILE__), __LINE__, __FUNCTION__, ##__VA_ARGS__) 53 #define UVC_ENTER() fprintf(stderr, "[%s:%d] begin %s\n", basename(__FILE__), __LINE__, __FUNCTION__) 54 #define UVC_EXIT(code) fprintf(stderr, "[%s:%d] end %s (%d)\n", basename(__FILE__), __LINE__, __FUNCTION__, code) 55 #define UVC_EXIT_VOID() fprintf(stderr, "[%s:%d] end %s\n", basename(__FILE__), __LINE__, __FUNCTION__) 56 #else 57 #define UVC_DEBUG(format, ...) 58 #define UVC_ENTER() 59 #define UVC_EXIT_VOID() 60 #define UVC_EXIT(code) 61 #endif 62 63 /* http://stackoverflow.com/questions/19452971/array-size-macro-that-rejects-pointers */ 64 #define IS_INDEXABLE(arg) (sizeof(arg[0])) 65 #define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg))) 66 #define ARRAYSIZE(arr) (sizeof(arr) / (IS_ARRAY(arr) ? sizeof(arr[0]) : 0)) 67 68 /** Video interface subclass code (A.2) */ 69 enum uvc_int_subclass_code { 70 UVC_SC_UNDEFINED = 0x00, 71 UVC_SC_VIDEOCONTROL = 0x01, 72 UVC_SC_VIDEOSTREAMING = 0x02, 73 UVC_SC_VIDEO_INTERFACE_COLLECTION = 0x03 74 }; 75 76 /** Video interface protocol code (A.3) */ 77 enum uvc_int_proto_code { 78 UVC_PC_PROTOCOL_UNDEFINED = 0x00 79 }; 80 81 /** VideoControl interface descriptor subtype (A.5) */ 82 enum uvc_vc_desc_subtype { 83 UVC_VC_DESCRIPTOR_UNDEFINED = 0x00, 84 UVC_VC_HEADER = 0x01, 85 UVC_VC_INPUT_TERMINAL = 0x02, 86 UVC_VC_OUTPUT_TERMINAL = 0x03, 87 UVC_VC_SELECTOR_UNIT = 0x04, 88 UVC_VC_PROCESSING_UNIT = 0x05, 89 UVC_VC_EXTENSION_UNIT = 0x06 90 }; 91 92 /** UVC endpoint descriptor subtype (A.7) */ 93 enum uvc_ep_desc_subtype { 94 UVC_EP_UNDEFINED = 0x00, 95 UVC_EP_GENERAL = 0x01, 96 UVC_EP_ENDPOINT = 0x02, 97 UVC_EP_INTERRUPT = 0x03 98 }; 99 100 /** VideoControl interface control selector (A.9.1) */ 101 enum uvc_vc_ctrl_selector { 102 UVC_VC_CONTROL_UNDEFINED = 0x00, 103 UVC_VC_VIDEO_POWER_MODE_CONTROL = 0x01, 104 UVC_VC_REQUEST_ERROR_CODE_CONTROL = 0x02 105 }; 106 107 /** Terminal control selector (A.9.2) */ 108 enum uvc_term_ctrl_selector { 109 UVC_TE_CONTROL_UNDEFINED = 0x00 110 }; 111 112 /** Selector unit control selector (A.9.3) */ 113 enum uvc_su_ctrl_selector { 114 UVC_SU_CONTROL_UNDEFINED = 0x00, 115 UVC_SU_INPUT_SELECT_CONTROL = 0x01 116 }; 117 118 /** Extension unit control selector (A.9.6) */ 119 enum uvc_xu_ctrl_selector { 120 UVC_XU_CONTROL_UNDEFINED = 0x00 121 }; 122 123 /** VideoStreaming interface control selector (A.9.7) */ 124 enum uvc_vs_ctrl_selector { 125 UVC_VS_CONTROL_UNDEFINED = 0x00, 126 UVC_VS_PROBE_CONTROL = 0x01, 127 UVC_VS_COMMIT_CONTROL = 0x02, 128 UVC_VS_STILL_PROBE_CONTROL = 0x03, 129 UVC_VS_STILL_COMMIT_CONTROL = 0x04, 130 UVC_VS_STILL_IMAGE_TRIGGER_CONTROL = 0x05, 131 UVC_VS_STREAM_ERROR_CODE_CONTROL = 0x06, 132 UVC_VS_GENERATE_KEY_FRAME_CONTROL = 0x07, 133 UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL = 0x08, 134 UVC_VS_SYNC_DELAY_CONTROL = 0x09 135 }; 136 137 /** Status packet type (2.4.2.2) */ 138 enum uvc_status_type { 139 UVC_STATUS_TYPE_CONTROL = 1, 140 UVC_STATUS_TYPE_STREAMING = 2 141 }; 142 143 /** Payload header flags (2.4.3.3) */ 144 #define UVC_STREAM_EOH (1 << 7) 145 #define UVC_STREAM_ERR (1 << 6) 146 #define UVC_STREAM_STI (1 << 5) 147 #define UVC_STREAM_RES (1 << 4) 148 #define UVC_STREAM_SCR (1 << 3) 149 #define UVC_STREAM_PTS (1 << 2) 150 #define UVC_STREAM_EOF (1 << 1) 151 #define UVC_STREAM_FID (1 << 0) 152 153 /** Control capabilities (4.1.2) */ 154 #define UVC_CONTROL_CAP_GET (1 << 0) 155 #define UVC_CONTROL_CAP_SET (1 << 1) 156 #define UVC_CONTROL_CAP_DISABLED (1 << 2) 157 #define UVC_CONTROL_CAP_AUTOUPDATE (1 << 3) 158 #define UVC_CONTROL_CAP_ASYNCHRONOUS (1 << 4) 159 160 struct uvc_streaming_interface; 161 struct uvc_device_info; 162 163 /** VideoStream interface */ 164 typedef struct uvc_streaming_interface { 165 struct uvc_device_info *parent; 166 struct uvc_streaming_interface *prev, *next; 167 /** Interface number */ 168 uint8_t bInterfaceNumber; 169 /** Video formats that this interface provides */ 170 struct uvc_format_desc *format_descs; 171 /** USB endpoint to use when communicating with this interface */ 172 uint8_t bEndpointAddress; 173 uint8_t bTerminalLink; 174 } uvc_streaming_interface_t; 175 176 /** VideoControl interface */ 177 typedef struct uvc_control_interface { 178 struct uvc_device_info *parent; 179 struct uvc_input_terminal *input_term_descs; 180 // struct uvc_output_terminal *output_term_descs; 181 struct uvc_processing_unit *processing_unit_descs; 182 struct uvc_extension_unit *extension_unit_descs; 183 uint16_t bcdUVC; 184 uint8_t bEndpointAddress; 185 /** Interface number */ 186 uint8_t bInterfaceNumber; 187 } uvc_control_interface_t; 188 189 struct uvc_stream_ctrl; 190 191 struct uvc_device { 192 struct uvc_context *ctx; 193 int ref; 194 libusb_device *usb_dev; 195 }; 196 197 typedef struct uvc_device_info { 198 /** Configuration descriptor for USB device */ 199 struct libusb_config_descriptor *config; 200 /** VideoControl interface provided by device */ 201 uvc_control_interface_t ctrl_if; 202 /** VideoStreaming interfaces on the device */ 203 uvc_streaming_interface_t *stream_ifs; 204 205 /* Store the interface for multiple UVCs on a single VID/PID device (Intel RealSense, VF200, e.g) */ 206 int camera_number; 207 } uvc_device_info_t; 208 209 /* 210 set a high number of transfer buffers. This uses a lot of ram, but 211 avoids problems with scheduling delays on slow boards causing missed 212 transfers. A better approach may be to make the transfer thread FIFO 213 scheduled (if we have root). 214 We could/should change this to allow reduce it to, say, 5 by default 215 and then allow the user to change the number of buffers as required. 216 */ 217 #define LIBUVC_XFER_BUF_SIZE (64 * 1024 * 1024) 218 219 struct uvc_stream_handle { 220 struct uvc_device_handle *devh; 221 struct uvc_stream_handle *prev, *next; 222 struct uvc_streaming_interface *stream_if; 223 224 /** if true, stream is running (streaming video to host) */ 225 uint8_t running; 226 /** Current control block */ 227 struct uvc_stream_ctrl cur_ctrl; 228 229 /* listeners may only access hold*, and only when holding a 230 * lock on cb_mutex (probably signaled with cb_cond) */ 231 uint8_t fid; 232 uint32_t seq, hold_seq; 233 uint32_t pts, hold_pts; 234 uint32_t last_scr, hold_last_scr; 235 size_t got_bytes, hold_bytes; 236 uint8_t *outbuf, *holdbuf; 237 pthread_mutex_t cb_mutex; 238 pthread_cond_t cb_cond; 239 pthread_t cb_thread; 240 uint32_t last_polled_seq; 241 uvc_frame_callback_t *user_cb; 242 void *user_ptr; 243 struct libusb_transfer **transfers; // num_transfer_bufs 244 uint8_t **transfer_bufs; // num_transfer_bufs 245 struct uvc_frame frame; 246 uint32_t fourcc; 247 int num_transfer_bufs; 248 }; 249 250 /** Handle on an open UVC device 251 * 252 * @todo move most of this into a uvc_device struct? 253 */ 254 struct uvc_device_handle { 255 struct uvc_device *dev; 256 struct uvc_device_handle *prev, *next; 257 /** Underlying USB device handle */ 258 libusb_device_handle *usb_devh; 259 struct uvc_device_info *info; 260 struct libusb_transfer *status_xfer; 261 uint8_t status_buf[32]; 262 /** Function to call when we receive status updates from the camera */ 263 uvc_status_callback_t *status_cb; 264 void *status_user_ptr; 265 266 uvc_stream_handle_t *streams; 267 /** Whether the camera is an iSight that sends one header per frame */ 268 uint8_t is_isight; 269 }; 270 271 /** Context within which we communicate with devices */ 272 struct uvc_context { 273 /** Underlying context for USB communication */ 274 struct libusb_context *usb_ctx; 275 /** True iff libuvc initialized the underlying USB context */ 276 uint8_t own_usb_ctx; 277 /** List of open devices in this context */ 278 uvc_device_handle_t *open_devices; 279 pthread_t handler_thread; 280 uint8_t kill_handler_thread; 281 }; 282 283 uvc_error_t uvc_query_stream_ctrl( 284 uvc_device_handle_t *devh, 285 uvc_stream_ctrl_t *ctrl, 286 uint8_t probe, 287 enum uvc_req_code req); 288 289 void uvc_start_handler_thread(uvc_context_t *ctx); 290 uvc_error_t uvc_claim_if(uvc_device_handle_t *devh, int idx); 291 uvc_error_t uvc_release_if(uvc_device_handle_t *devh, int idx); 292 293 #endif // !def(LIBUVC_INTERNAL_H) 294 /** @endcond */ 295 296