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