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