1 /*********************************************************************
2 * add some functions unsupported on original libuvc library
3 * and fixed some issues
4 * Copyright (C) 2014-2015 saki@serenegiant All rights reserved.
5 *********************************************************************/
6 /*********************************************************************
7 * Software License Agreement (BSD License)
9 * Copyright (C) 2010-2012 Ken Tossell
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
16 * * Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * * Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials provided
21 * with the distribution.
22 * * Neither the name of the author nor other contributors may be
23 * used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 *********************************************************************/
40 * @defgroup ctrl Video capture and processing controls
41 * @brief Functions for manipulating device settings and stream parameters
43 * The `uvc_get_*` and `uvc_set_*` functions are used to read and write the settings associated
44 * with the device's input, processing and output units.
47 #include "libuvc/libuvc.h"
48 #include "libuvc/libuvc_internal.h"
50 static const int REQ_TYPE_SET = 0x21;
51 static const int REQ_TYPE_GET = 0xa1;
53 #define CTRL_TIMEOUT_MILLIS 0
55 /***** GENERIC CONTROLS *****/
57 * @brief Get the length of a control on a terminal or unit.
59 * @param devh UVC device handle
60 * @param unit Unit or Terminal ID; obtain this from the uvc_extension_unit_t describing the extension unit
61 * @param ctrl Vendor-specific control number to query
62 * @return On success, the length of the control as reported by the device. Otherwise,
63 * a uvc_error_t error describing the error encountered.
66 int uvc_get_ctrl_len(uvc_device_handle_t *devh, uint8_t unit, uint8_t ctrl) {
69 int ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, UVC_GET_LEN,
71 unit << 8, // FIXME this will work wrong, invalid wIndex value
72 buf, 2, CTRL_TIMEOUT_MILLIS);
74 if (UNLIKELY(ret < 0))
77 return (unsigned short) SW_TO_SHORT(buf);
81 * @brief Perform a GET_* request from an extension unit.
83 * @param devh UVC device handle
84 * @param unit Unit ID; obtain this from the uvc_extension_unit_t describing the extension unit
85 * @param ctrl Control number to query
86 * @param data Data buffer to be filled by the device
87 * @param len Size of data buffer
88 * @param req_code GET_* request to execute
89 * @return On success, the number of bytes actually transferred. Otherwise,
90 * a uvc_error_t error describing the error encountered.
93 int uvc_get_ctrl(uvc_device_handle_t *devh, uint8_t unit, uint8_t ctrl,
94 void *data, int len, enum uvc_req_code req_code) {
95 return libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
97 unit << 8, // FIXME this will work wrong, invalid wIndex value
98 data, len, CTRL_TIMEOUT_MILLIS);
102 * @brief Perform a SET_CUR request to a terminal or unit.
104 * @param devh UVC device handle
105 * @param unit Unit or Terminal ID
106 * @param ctrl Control number to set
107 * @param data Data buffer to be sent to the device
108 * @param len Size of data buffer
109 * @return On success, the number of bytes actually transferred. Otherwise,
110 * a uvc_error_t error describing the error encountered.
113 int uvc_set_ctrl(uvc_device_handle_t *devh, uint8_t unit, uint8_t ctrl,
114 void *data, int len) {
115 return libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
117 unit << 8, // FIXME this will work wrong, invalid wIndex value
118 data, len, CTRL_TIMEOUT_MILLIS);
121 /***** INTERFACE CONTROLS *****/
122 /** VC Request Error Code Control (UVC 4.2.1.2) */ // XXX added saki
123 uvc_error_t uvc_vc_get_error_code(uvc_device_handle_t *devh,
124 uvc_vc_error_code_control_t *error_code, enum uvc_req_code req_code) {
125 uint8_t error_char = 0;
126 uvc_error_t ret = UVC_SUCCESS;
128 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
129 UVC_VC_REQUEST_ERROR_CODE_CONTROL << 8,
130 devh->info->ctrl_if.bInterfaceNumber, // XXX saki
131 &error_char, sizeof(error_char), CTRL_TIMEOUT_MILLIS);
133 if (LIKELY(ret == 1)) {
134 *error_code = error_char;
141 /** VS Request Error Code Control */ // XXX added saki
142 uvc_error_t uvc_vs_get_error_code(uvc_device_handle_t *devh,
143 uvc_vs_error_code_control_t *error_code, enum uvc_req_code req_code) {
144 uint8_t error_char = 0;
145 uvc_error_t ret = UVC_SUCCESS;
147 #if 0 // This code may cause hang-up on some combinations of device and camera and temporary disabled.
148 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
149 UVC_VS_STREAM_ERROR_CODE_CONTROL << 8,
150 devh->info->stream_ifs->bInterfaceNumber, // XXX is this OK?
151 &error_char, sizeof(error_char), CTRL_TIMEOUT_MILLIS);
153 if (LIKELY(ret == 1)) {
154 *error_code = error_char;
164 uvc_error_t uvc_get_power_mode(uvc_device_handle_t *devh,
165 enum uvc_device_power_mode *mode, enum uvc_req_code req_code) {
166 uint8_t mode_char = 0;
169 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
170 UVC_VC_VIDEO_POWER_MODE_CONTROL << 8,
171 devh->info->ctrl_if.bInterfaceNumber, // XXX saki
172 &mode_char, sizeof(mode_char), CTRL_TIMEOUT_MILLIS);
174 if (LIKELY(ret == 1)) {
182 uvc_error_t uvc_set_power_mode(uvc_device_handle_t *devh,
183 enum uvc_device_power_mode mode) {
184 uint8_t mode_char = mode;
187 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
188 UVC_VC_VIDEO_POWER_MODE_CONTROL << 8,
189 devh->info->ctrl_if.bInterfaceNumber, // XXX saki
190 &mode_char, sizeof(mode_char), CTRL_TIMEOUT_MILLIS);
192 if (LIKELY(ret == 1))
198 /***** CAMERA TERMINAL CONTROLS *****/
199 uvc_error_t uvc_get_ae_mode(uvc_device_handle_t *devh, uint8_t *mode,
200 enum uvc_req_code req_code) {
204 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
205 UVC_CT_AE_MODE_CONTROL << 8,
206 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
207 devh->info->ctrl_if.input_term_descs->request,
208 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
210 if (LIKELY(ret == sizeof(data))) {
218 uvc_error_t uvc_set_ae_mode(uvc_device_handle_t *devh, uint8_t mode) {
224 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
225 UVC_CT_AE_MODE_CONTROL << 8,
226 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
227 devh->info->ctrl_if.input_term_descs->request,
228 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
230 if (LIKELY(ret == sizeof(data)))
236 //----------------------------------------------------------------------
237 uvc_error_t uvc_get_ae_priority(uvc_device_handle_t *devh, uint8_t *priority,
238 enum uvc_req_code req_code) {
242 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
243 UVC_CT_AE_PRIORITY_CONTROL << 8,
244 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
245 devh->info->ctrl_if.input_term_descs->request,
246 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
248 if (LIKELY(ret == sizeof(data))) {
256 uvc_error_t uvc_set_ae_priority(uvc_device_handle_t *devh, uint8_t priority) {
262 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
263 UVC_CT_AE_PRIORITY_CONTROL << 8,
264 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
265 devh->info->ctrl_if.input_term_descs->request,
266 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
268 if (LIKELY(ret == sizeof(data)))
274 //----------------------------------------------------------------------
275 uvc_error_t uvc_get_exposure_abs(uvc_device_handle_t *devh, int *time,
276 enum uvc_req_code req_code) {
280 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
281 UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL << 8,
282 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
283 devh->info->ctrl_if.input_term_descs->request,
284 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
286 if (LIKELY(ret == sizeof(data))) {
287 *time = DW_TO_INT(data);
294 uvc_error_t uvc_set_exposure_abs(uvc_device_handle_t *devh, int time) {
298 INT_TO_DW(time, data);
300 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
301 UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL << 8,
302 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
303 devh->info->ctrl_if.input_term_descs->request,
304 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
306 if (LIKELY(ret == sizeof(data)))
312 uvc_error_t uvc_get_exposure_rel(uvc_device_handle_t *devh, int *step,
313 enum uvc_req_code req_code) {
317 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
318 UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL << 8,
319 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
320 devh->info->ctrl_if.input_term_descs->request,
321 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
323 if (LIKELY(ret == sizeof(data))) {
331 uvc_error_t uvc_set_exposure_rel(uvc_device_handle_t *devh, int step) {
337 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
338 UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL << 8,
339 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
340 devh->info->ctrl_if.input_term_descs->request,
341 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
343 if (LIKELY(ret == sizeof(data)))
349 //----------------------------------------------------------------------
350 uvc_error_t uvc_get_scanning_mode(uvc_device_handle_t *devh, uint8_t *mode,
351 enum uvc_req_code req_code) {
355 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
356 UVC_CT_SCANNING_MODE_CONTROL << 8,
357 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
358 devh->info->ctrl_if.input_term_descs->request,
359 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
361 if (LIKELY(ret == sizeof(data))) {
369 uvc_error_t uvc_set_scanning_mode(uvc_device_handle_t *devh, uint8_t mode) {
375 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
376 UVC_CT_SCANNING_MODE_CONTROL << 8,
377 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
378 devh->info->ctrl_if.input_term_descs->request,
379 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
381 if (LIKELY(ret == sizeof(data)))
387 //----------------------------------------------------------------------
388 uvc_error_t uvc_get_focus_auto(uvc_device_handle_t *devh, uint8_t *autofocus,
389 enum uvc_req_code req_code) {
393 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
394 UVC_CT_FOCUS_AUTO_CONTROL << 8,
395 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
396 devh->info->ctrl_if.input_term_descs->request,
397 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
399 if (LIKELY(ret == sizeof(data))) {
400 *autofocus = data[0];
407 uvc_error_t uvc_set_focus_auto(uvc_device_handle_t *devh, uint8_t autofocus) {
413 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
414 UVC_CT_FOCUS_AUTO_CONTROL << 8,
415 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
416 devh->info->ctrl_if.input_term_descs->request,
417 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
419 if (LIKELY(ret == sizeof(data)))
425 //----------------------------------------------------------------------
426 uvc_error_t uvc_get_focus_abs(uvc_device_handle_t *devh, short *focus,
427 enum uvc_req_code req_code) {
431 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
432 UVC_CT_FOCUS_ABSOLUTE_CONTROL << 8,
433 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
434 devh->info->ctrl_if.input_term_descs->request,
435 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
437 if (LIKELY(ret == sizeof(data))) {
438 *focus = SW_TO_SHORT(data);
445 uvc_error_t uvc_set_focus_abs(uvc_device_handle_t *devh, short focus) {
449 SHORT_TO_SW(focus, data);
451 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
452 UVC_CT_FOCUS_ABSOLUTE_CONTROL << 8,
453 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
454 devh->info->ctrl_if.input_term_descs->request,
455 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
457 if (LIKELY(ret == sizeof(data)))
463 uvc_error_t uvc_get_focus_rel(uvc_device_handle_t *devh, int8_t *focus, uint8_t *speed,
464 enum uvc_req_code req_code) {
468 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
469 UVC_CT_FOCUS_RELATIVE_CONTROL << 8,
470 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
471 devh->info->ctrl_if.input_term_descs->request,
472 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
474 if (LIKELY(ret == sizeof(data))) {
483 uvc_error_t uvc_set_focus_rel(uvc_device_handle_t *devh, int8_t focus, uint8_t speed) {
490 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
491 UVC_CT_FOCUS_RELATIVE_CONTROL << 8,
492 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
493 devh->info->ctrl_if.input_term_descs->request,
494 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
496 if (LIKELY(ret == sizeof(data)))
502 //----------------------------------------------------------------------
503 uvc_error_t uvc_get_iris_abs(uvc_device_handle_t *devh, uint16_t *iris,
504 enum uvc_req_code req_code) {
508 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
509 UVC_CT_FOCUS_ABSOLUTE_CONTROL << 8,
510 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
511 devh->info->ctrl_if.input_term_descs->request,
512 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
514 if (LIKELY(ret == sizeof(data))) {
515 *iris = SW_TO_SHORT(data);
522 uvc_error_t uvc_set_iris_abs(uvc_device_handle_t *devh, uint16_t iris) {
526 SHORT_TO_SW(iris, data);
528 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
529 UVC_CT_FOCUS_ABSOLUTE_CONTROL << 8,
530 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
531 devh->info->ctrl_if.input_term_descs->request,
532 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
534 if (LIKELY(ret == sizeof(data)))
540 uvc_error_t uvc_get_iris_rel(uvc_device_handle_t *devh, uint8_t *iris,
541 enum uvc_req_code req_code) {
545 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
546 UVC_CT_FOCUS_RELATIVE_CONTROL << 8,
547 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
548 devh->info->ctrl_if.input_term_descs->request,
549 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
551 if (LIKELY(ret == sizeof(data))) {
559 uvc_error_t uvc_set_iris_rel(uvc_device_handle_t *devh, uint8_t iris) {
565 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
566 UVC_CT_FOCUS_RELATIVE_CONTROL << 8,
567 // 1 << 8, /* = fixed ID(00) and wrong VideoControl interface descriptor subtype(UVC_VC_HEADER) on original libuvc */
568 devh->info->ctrl_if.input_term_descs->request,
569 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
571 if (LIKELY(ret == sizeof(data)))
577 //----------------------------------------------------------------------
578 uvc_error_t uvc_get_zoom_abs(uvc_device_handle_t *devh, uint16_t *zoom,
579 enum uvc_req_code req_code) {
583 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
584 UVC_CT_ZOOM_ABSOLUTE_CONTROL << 8,
585 devh->info->ctrl_if.input_term_descs->request,
586 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
588 if (LIKELY(ret == sizeof(data))) {
589 *zoom = SW_TO_SHORT(data);
596 uvc_error_t uvc_set_zoom_abs(uvc_device_handle_t *devh, uint16_t zoom) {
600 SHORT_TO_SW(zoom, data);
602 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
603 UVC_CT_ZOOM_ABSOLUTE_CONTROL << 8,
604 devh->info->ctrl_if.input_term_descs->request,
605 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
607 if (LIKELY(ret == sizeof(data)))
613 uvc_error_t uvc_get_zoom_rel(uvc_device_handle_t *devh, int8_t *zoom, uint8_t *isdigital, uint8_t *speed,
614 enum uvc_req_code req_code) {
618 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
619 UVC_CT_ZOOM_RELATIVE_CONTROL << 8,
620 devh->info->ctrl_if.input_term_descs->request,
621 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
623 if (LIKELY(ret == sizeof(data))) {
625 *isdigital = data[1];
633 uvc_error_t uvc_set_zoom_rel(uvc_device_handle_t *devh, int8_t zoom, uint8_t isdigital, uint8_t speed) {
641 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
642 UVC_CT_ZOOM_RELATIVE_CONTROL << 8,
643 devh->info->ctrl_if.input_term_descs->request,
644 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
646 if (LIKELY(ret == sizeof(data)))
652 //----------------------------------------------------------------------
653 uvc_error_t uvc_get_pantilt_abs(uvc_device_handle_t *devh, int32_t *pan, int32_t *tilt,
654 enum uvc_req_code req_code) {
659 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
660 UVC_CT_PANTILT_ABSOLUTE_CONTROL << 8,
661 devh->info->ctrl_if.input_term_descs->request,
662 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
664 if (LIKELY(ret == sizeof(data))) {
665 *pan = DW_TO_INT(data);
666 *tilt = DW_TO_INT(data + 4);
673 uvc_error_t uvc_set_pantilt_abs(uvc_device_handle_t *devh, int32_t pan, int32_t tilt) {
677 INT_TO_DW(pan, data);
678 INT_TO_DW(tilt, data + 4);
680 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
681 UVC_CT_PANTILT_ABSOLUTE_CONTROL << 8,
682 devh->info->ctrl_if.input_term_descs->request,
683 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
685 if (LIKELY(ret == sizeof(data)))
691 uvc_error_t uvc_get_pantilt_rel(uvc_device_handle_t *devh,
692 int8_t *pan_rel, uint8_t *pan_speed,
693 int8_t* tilt_rel, uint8_t* tilt_speed,
694 enum uvc_req_code req_code) {
699 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
700 UVC_CT_PANTILT_RELATIVE_CONTROL << 8,
701 devh->info->ctrl_if.input_term_descs->request,
702 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
704 if (LIKELY(ret == sizeof(data))) {
706 *pan_speed = data[1];
708 *tilt_speed = data[3];
715 uvc_error_t uvc_set_pantilt_rel(uvc_device_handle_t *devh,
716 int8_t pan_rel, uint8_t pan_speed,
717 int8_t tilt_rel, uint8_t tilt_speed) {
725 data[3] = tilt_speed;
727 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
728 UVC_CT_PANTILT_RELATIVE_CONTROL << 8,
729 devh->info->ctrl_if.input_term_descs->request,
730 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
732 if (LIKELY(ret == sizeof(data)))
738 uvc_error_t uvc_get_roll_abs(uvc_device_handle_t *devh, int16_t *roll,
739 enum uvc_req_code req_code) {
744 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
745 UVC_CT_ROLL_ABSOLUTE_CONTROL << 8,
746 devh->info->ctrl_if.input_term_descs->request,
747 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
749 if (LIKELY(ret == sizeof(data))) {
750 *roll = SW_TO_SHORT(data + 0);
757 uvc_error_t uvc_set_roll_abs(uvc_device_handle_t *devh, int16_t roll) {
762 SHORT_TO_SW(roll, data + 0);
764 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
765 UVC_CT_ROLL_ABSOLUTE_CONTROL << 8,
766 devh->info->ctrl_if.input_term_descs->request,
767 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
769 if (LIKELY(ret == sizeof(data)))
776 * @brief Reads the ROLL_RELATIVE control.
777 * @param devh UVC device handle
778 * @param[out] roll_rel TODO
779 * @param[out] speed TODO
780 * @param req_code UVC_GET_* request to execute
782 uvc_error_t uvc_get_roll_rel(uvc_device_handle_t *devh, int8_t *roll_rel, uint8_t *speed,
783 enum uvc_req_code req_code) {
788 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
789 UVC_CT_ROLL_RELATIVE_CONTROL << 8,
790 devh->info->ctrl_if.input_term_descs->request,
791 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
793 if (LIKELY(ret == sizeof(data))) {
804 * @brief Sets the ROLL_RELATIVE control.
805 * @param devh UVC device handle
806 * @param roll_rel TODO
809 uvc_error_t uvc_set_roll_rel(uvc_device_handle_t *devh, int8_t roll_rel, uint8_t speed) {
817 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
818 UVC_CT_ROLL_RELATIVE_CONTROL << 8,
819 devh->info->ctrl_if.input_term_descs->request,
820 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
822 if (LIKELY(ret == sizeof(data)))
829 * @brief Reads the PRIVACY control.
830 * @param devh UVC device handle
831 * @param[out] privacy TODO
832 * @param req_code UVC_GET_* request to execute
834 uvc_error_t uvc_get_privacy(uvc_device_handle_t *devh, uint8_t *privacy,
835 enum uvc_req_code req_code) {
840 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
841 UVC_CT_PRIVACY_CONTROL << 8,
842 devh->info->ctrl_if.input_term_descs->request,
843 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
845 if (LIKELY(ret == sizeof(data))) {
855 * @brief Sets the PRIVACY control.
856 * @param devh UVC device handle
857 * @param privacy TODO
859 uvc_error_t uvc_set_privacy(uvc_device_handle_t *devh, uint8_t privacy) {
866 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
867 UVC_CT_PRIVACY_CONTROL << 8,
868 devh->info->ctrl_if.input_term_descs->request,
869 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
871 if (LIKELY(ret == sizeof(data)))
878 * @brief Reads the DIGITAL_WINDOW control.
879 * @param devh UVC device handle
880 * @param[out] window_top TODO
881 * @param[out] window_left TODO
882 * @param[out] window_bottom TODO
883 * @param[out] window_right TODO
884 * @param[out] num_steps TODO
885 * @param[out] num_steps_units TODO
886 * @param req_code UVC_GET_* request to execute
888 uvc_error_t uvc_get_digital_window(uvc_device_handle_t *devh,
889 uint16_t *window_top, uint16_t *window_left,
890 uint16_t *window_bottom, uint16_t *window_right,
891 uint16_t *num_steps, uint16_t *num_steps_units,
892 enum uvc_req_code req_code) {
897 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
898 UVC_CT_DIGITAL_WINDOW_CONTROL << 8,
899 devh->info->ctrl_if.input_term_descs->request,
900 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
902 if (LIKELY(ret == sizeof(data))) {
903 *window_top = SW_TO_SHORT(data + 0);
904 *window_left = SW_TO_SHORT(data + 2);
905 *window_bottom = SW_TO_SHORT(data + 4);
906 *window_right = SW_TO_SHORT(data + 6);
907 *num_steps = SW_TO_SHORT(data + 8);
908 *num_steps_units = SW_TO_SHORT(data + 10);
917 * @brief Sets the DIGITAL_WINDOW control.
918 * @param devh UVC device handle
919 * @param window_top TODO
920 * @param window_left TODO
921 * @param window_bottom TODO
922 * @param window_right TODO
923 * @param num_steps TODO
924 * @param num_steps_units TODO
926 uvc_error_t uvc_set_digital_window(uvc_device_handle_t *devh,
927 uint16_t window_top, uint16_t window_left,
928 uint16_t window_bottom, uint16_t window_right,
929 uint16_t num_steps, uint16_t num_steps_units) {
934 SHORT_TO_SW(window_top, data + 0);
935 SHORT_TO_SW(window_left, data + 2);
936 SHORT_TO_SW(window_bottom, data + 4);
937 SHORT_TO_SW(window_right, data + 6);
938 SHORT_TO_SW(num_steps, data + 8);
939 SHORT_TO_SW(num_steps_units, data + 10);
941 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
942 UVC_CT_DIGITAL_WINDOW_CONTROL << 8,
943 devh->info->ctrl_if.input_term_descs->request,
944 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
946 if (LIKELY(ret == sizeof(data)))
953 * @brief Reads the REGION_OF_INTEREST control.
954 * @param devh UVC device handle
955 * @param[out] roi_top TODO
956 * @param[out] roi_left TODO
957 * @param[out] roi_bottom TODO
958 * @param[out] roi_right TODO
959 * @param[out] auto_controls TODO
960 * @param req_code UVC_GET_* request to execute
962 uvc_error_t uvc_get_digital_roi(uvc_device_handle_t *devh,
963 uint16_t *roi_top, uint16_t *roi_left,
964 uint16_t* roi_bottom, uint16_t *roi_right, uint16_t *auto_controls,
965 enum uvc_req_code req_code) {
970 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
971 UVC_CT_REGION_OF_INTEREST_CONTROL << 8,
972 devh->info->ctrl_if.input_term_descs->request,
973 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
975 if (LIKELY(ret == sizeof(data))) {
976 *roi_top = SW_TO_SHORT(data + 0);
977 *roi_left = SW_TO_SHORT(data + 2);
978 *roi_bottom = SW_TO_SHORT(data + 4);
979 *roi_right = SW_TO_SHORT(data + 6);
980 *auto_controls = SW_TO_SHORT(data + 8);
989 * @brief Sets the REGION_OF_INTEREST control.
990 * @param devh UVC device handle
991 * @param roi_top TODO
992 * @param roi_left TODO
993 * @param roi_bottom TODO
994 * @param roi_right TODO
995 * @param auto_controls TODO
997 uvc_error_t uvc_set_digital_roi(uvc_device_handle_t *devh,
998 uint16_t roi_top, uint16_t roi_left,
999 uint16_t roi_bottom, uint16_t roi_right, uint16_t auto_controls) {
1004 SHORT_TO_SW(roi_top, data + 0);
1005 SHORT_TO_SW(roi_left, data + 2);
1006 SHORT_TO_SW(roi_bottom, data + 4);
1007 SHORT_TO_SW(roi_right, data + 6);
1008 SHORT_TO_SW(auto_controls, data + 8);
1010 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1011 UVC_CT_REGION_OF_INTEREST_CONTROL << 8,
1012 devh->info->ctrl_if.input_term_descs->request,
1013 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1015 if (LIKELY(ret == sizeof(data)))
1021 /***** SELECTOR UNIT CONTROLS *****/
1023 /** @todo input_select */
1025 /***** PROCESSING UNIT CONTROLS *****/
1026 uvc_error_t uvc_get_backlight_compensation(uvc_device_handle_t *devh, short *comp,
1027 enum uvc_req_code req_code) {
1031 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1032 UVC_PU_BACKLIGHT_COMPENSATION_CONTROL << 8,
1033 devh->info->ctrl_if.processing_unit_descs->request,
1034 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1036 if (LIKELY(ret == sizeof(data))) {
1037 *comp = SW_TO_SHORT(data);
1042 RETURN(-1, uvc_error_t);
1045 uvc_error_t uvc_set_backlight_compensation(uvc_device_handle_t *devh, short comp) {
1049 SHORT_TO_SW(comp, data);
1051 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1052 UVC_PU_BACKLIGHT_COMPENSATION_CONTROL << 8,
1053 devh->info->ctrl_if.processing_unit_descs->request,
1054 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1056 if (LIKELY(ret == sizeof(data)))
1062 uvc_error_t uvc_get_brightness(uvc_device_handle_t *devh, short *brightness,
1063 enum uvc_req_code req_code) {
1067 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1068 UVC_PU_BRIGHTNESS_CONTROL << 8,
1069 devh->info->ctrl_if.processing_unit_descs->request,
1070 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1072 if (LIKELY(ret == sizeof(data))) {
1073 *brightness = SW_TO_SHORT(data);
1078 RETURN(-1, uvc_error_t);
1081 uvc_error_t uvc_set_brightness(uvc_device_handle_t *devh, short brightness) {
1085 SHORT_TO_SW(brightness, data);
1087 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1088 UVC_PU_BRIGHTNESS_CONTROL << 8,
1089 devh->info->ctrl_if.processing_unit_descs->request,
1090 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1092 if (LIKELY(ret == sizeof(data)))
1098 uvc_error_t uvc_get_contrast(uvc_device_handle_t *devh, uint16_t *contrast,
1099 enum uvc_req_code req_code) {
1103 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1104 UVC_PU_CONTRAST_CONTROL << 8,
1105 devh->info->ctrl_if.processing_unit_descs->request,
1106 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1108 if (LIKELY(ret == sizeof(data))) {
1109 *contrast = SW_TO_SHORT(data);
1114 RETURN(-1, uvc_error_t);
1117 uvc_error_t uvc_set_contrast(uvc_device_handle_t *devh, uint16_t contrast) {
1121 SHORT_TO_SW(contrast, data);
1123 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1124 UVC_PU_CONTRAST_CONTROL << 8,
1125 devh->info->ctrl_if.processing_unit_descs->request,
1126 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1128 if (LIKELY(ret == sizeof(data)))
1134 uvc_error_t uvc_get_contrast_auto(uvc_device_handle_t *devh, uint8_t *autoContrast,
1135 enum uvc_req_code req_code) {
1139 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1140 UVC_PU_CONTRAST_AUTO_CONTROL << 8,
1141 devh->info->ctrl_if.processing_unit_descs->request,
1142 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1144 if (LIKELY(ret == sizeof(data))) {
1145 *autoContrast = data[0];
1150 RETURN(-1, uvc_error_t);
1153 uvc_error_t uvc_set_contrast_auto(uvc_device_handle_t *devh, uint8_t autoContrast) {
1157 data[0] = autoContrast ? 1 : 0;
1159 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1160 UVC_PU_CONTRAST_AUTO_CONTROL << 8,
1161 devh->info->ctrl_if.processing_unit_descs->request,
1162 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1164 if (LIKELY(ret == sizeof(data)))
1170 uvc_error_t uvc_get_gain(uvc_device_handle_t *devh, uint16_t *gain,
1171 enum uvc_req_code req_code) {
1175 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1176 UVC_PU_GAIN_CONTROL << 8,
1177 devh->info->ctrl_if.processing_unit_descs->request,
1178 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1180 if (LIKELY(ret == sizeof(data))) {
1181 *gain = SW_TO_SHORT(data);
1186 RETURN(-1, uvc_error_t);
1189 uvc_error_t uvc_set_gain(uvc_device_handle_t *devh, uint16_t gain) {
1193 SHORT_TO_SW(gain, data);
1195 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1196 UVC_PU_GAIN_CONTROL << 8,
1197 devh->info->ctrl_if.processing_unit_descs->request,
1198 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1200 if (LIKELY(ret == sizeof(data)))
1206 uvc_error_t uvc_get_powerline_freqency(uvc_device_handle_t *devh, uint8_t *freq,
1207 enum uvc_req_code req_code) {
1211 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1212 UVC_PU_POWER_LINE_FREQUENCY_CONTROL << 8,
1213 devh->info->ctrl_if.processing_unit_descs->request,
1214 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1216 if (LIKELY(ret == sizeof(data))) {
1222 RETURN(-1, uvc_error_t);
1225 uvc_error_t uvc_set_powerline_freqency(uvc_device_handle_t *devh, uint8_t freq) {
1229 // XXX AUTO(0x03) is only available for UVC1.5.
1230 if ( ((freq & 0xff) == 0xff)
1231 || (((freq & 0x03) == 0x03) && (devh->info->ctrl_if.bcdUVC < 0x0150)) ) {
1233 ret = uvc_get_powerline_freqency(devh, &freq, UVC_GET_DEF);
1234 if (UNLIKELY(ret)) {
1235 LOGE("failed to uvc_get_powerline_freqency:err=%d", ret);
1240 data[0] = freq & 0x03;
1242 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1243 UVC_PU_POWER_LINE_FREQUENCY_CONTROL << 8,
1244 devh->info->ctrl_if.processing_unit_descs->request,
1245 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1247 if (LIKELY(ret == sizeof(data)))
1253 uvc_error_t uvc_get_hue(uvc_device_handle_t *devh, short *hue,
1254 enum uvc_req_code req_code) {
1258 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1259 UVC_PU_HUE_CONTROL << 8,
1260 devh->info->ctrl_if.processing_unit_descs->request,
1261 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1263 if (LIKELY(ret == sizeof(data))) {
1264 *hue = SW_TO_SHORT(data);
1269 RETURN(-1, uvc_error_t);
1272 uvc_error_t uvc_set_hue(uvc_device_handle_t *devh, short hue) {
1276 SHORT_TO_SW(hue, data);
1278 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1279 UVC_PU_HUE_CONTROL << 8,
1280 devh->info->ctrl_if.processing_unit_descs->request,
1281 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1283 if (LIKELY(ret == sizeof(data)))
1289 uvc_error_t uvc_get_hue_auto(uvc_device_handle_t *devh, uint8_t *autoHue,
1290 enum uvc_req_code req_code) {
1294 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1295 UVC_PU_HUE_AUTO_CONTROL << 8,
1296 devh->info->ctrl_if.processing_unit_descs->request,
1297 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1299 if (LIKELY(ret == sizeof(data))) {
1305 RETURN(-1, uvc_error_t);
1308 uvc_error_t uvc_set_hue_auto(uvc_device_handle_t *devh, uint8_t autoHue) {
1312 data[0] = autoHue ? 1 : 0;
1314 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1315 UVC_PU_HUE_AUTO_CONTROL << 8,
1316 devh->info->ctrl_if.processing_unit_descs->request,
1317 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1319 if (LIKELY(ret == sizeof(data)))
1325 uvc_error_t uvc_get_saturation(uvc_device_handle_t *devh, uint16_t *saturation,
1326 enum uvc_req_code req_code) {
1330 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1331 UVC_PU_SATURATION_CONTROL << 8,
1332 devh->info->ctrl_if.processing_unit_descs->request,
1333 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1335 if (LIKELY(ret == sizeof(data))) {
1336 *saturation = SW_TO_SHORT(data);
1341 RETURN(-1, uvc_error_t);
1344 uvc_error_t uvc_set_saturation(uvc_device_handle_t *devh, uint16_t saturation) {
1348 SHORT_TO_SW(saturation, data);
1350 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1351 UVC_PU_SATURATION_CONTROL << 8,
1352 devh->info->ctrl_if.processing_unit_descs->request,
1353 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1355 if (LIKELY(ret == sizeof(data)))
1361 uvc_error_t uvc_get_sharpness(uvc_device_handle_t *devh, uint16_t *sharpness,
1362 enum uvc_req_code req_code) {
1366 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1367 UVC_PU_SHARPNESS_CONTROL << 8,
1368 devh->info->ctrl_if.processing_unit_descs->request,
1369 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1371 if (LIKELY(ret == sizeof(data))) {
1372 *sharpness = SW_TO_SHORT(data);
1377 RETURN(-1, uvc_error_t);
1380 uvc_error_t uvc_set_sharpness(uvc_device_handle_t *devh, uint16_t sharpness) {
1384 SHORT_TO_SW(sharpness, data);
1386 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1387 UVC_PU_SHARPNESS_CONTROL << 8,
1388 devh->info->ctrl_if.processing_unit_descs->request,
1389 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1391 if (LIKELY(ret == sizeof(data)))
1397 uvc_error_t uvc_get_gamma(uvc_device_handle_t *devh, uint16_t *gamma,
1398 enum uvc_req_code req_code) {
1402 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1403 UVC_PU_GAMMA_CONTROL << 8,
1404 devh->info->ctrl_if.processing_unit_descs->request,
1405 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1407 if (LIKELY(ret == sizeof(data))) {
1408 *gamma = SW_TO_SHORT(data);
1413 RETURN(-1, uvc_error_t);
1416 uvc_error_t uvc_set_gamma(uvc_device_handle_t *devh, uint16_t gamma) {
1420 SHORT_TO_SW(gamma, data);
1422 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1423 UVC_PU_GAMMA_CONTROL << 8,
1424 devh->info->ctrl_if.processing_unit_descs->request,
1425 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1427 if (LIKELY(ret == sizeof(data)))
1433 uvc_error_t uvc_get_white_balance_temperature(uvc_device_handle_t *devh, uint16_t *wb_temperature,
1434 enum uvc_req_code req_code) {
1438 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1439 UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL << 8,
1440 devh->info->ctrl_if.processing_unit_descs->request,
1441 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1443 if (LIKELY(ret == sizeof(data))) {
1444 *wb_temperature = SW_TO_SHORT(data);
1449 RETURN(-1, uvc_error_t);
1452 uvc_error_t uvc_set_white_balance_temperature(uvc_device_handle_t *devh, uint16_t wb_temperature) {
1456 SHORT_TO_SW(wb_temperature, data);
1458 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1459 UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL << 8,
1460 devh->info->ctrl_if.processing_unit_descs->request,
1461 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1463 if (LIKELY(ret == sizeof(data)))
1469 uvc_error_t uvc_get_white_balance_temperature_auto(uvc_device_handle_t *devh, uint8_t *autoWbTemp,
1470 enum uvc_req_code req_code) {
1474 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1475 UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL << 8,
1476 devh->info->ctrl_if.processing_unit_descs->request,
1477 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1479 if (LIKELY(ret == sizeof(data))) {
1480 *autoWbTemp = data[0];
1485 RETURN(-1, uvc_error_t);
1488 uvc_error_t uvc_set_white_balance_temperature_auto(uvc_device_handle_t *devh, uint8_t autoWbTemp) {
1492 data[0] = autoWbTemp ? 1 : 0;
1494 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1495 UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL << 8,
1496 devh->info->ctrl_if.processing_unit_descs->request,
1497 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1499 if (LIKELY(ret == sizeof(data)))
1505 uvc_error_t uvc_get_white_balance_component(uvc_device_handle_t *devh, uint32_t *wb_compo,
1506 enum uvc_req_code req_code) {
1510 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1511 UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL << 8,
1512 devh->info->ctrl_if.processing_unit_descs->request,
1513 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1515 if (LIKELY(ret == sizeof(data))) {
1516 *wb_compo = DW_TO_INT(data);
1521 RETURN(-1, uvc_error_t);
1524 uvc_error_t uvc_set_white_balance_component(uvc_device_handle_t *devh, uint32_t wb_compo) {
1528 INT_TO_DW(wb_compo, data);
1530 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1531 UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL << 8,
1532 devh->info->ctrl_if.processing_unit_descs->request,
1533 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1535 if (LIKELY(ret == sizeof(data)))
1541 uvc_error_t uvc_get_white_balance_component_auto(uvc_device_handle_t *devh, uint8_t *autoWbCompo,
1542 enum uvc_req_code req_code) {
1546 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1547 UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL << 8,
1548 devh->info->ctrl_if.processing_unit_descs->request,
1549 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1551 if (LIKELY(ret == sizeof(data))) {
1552 *autoWbCompo = data[0];
1557 RETURN(-1, uvc_error_t);
1560 uvc_error_t uvc_set_white_balance_component_auto(uvc_device_handle_t *devh, uint8_t autoWbCompo) {
1564 data[0] = autoWbCompo ? 1 : 0;
1566 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1567 UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL << 8,
1568 devh->info->ctrl_if.processing_unit_descs->request,
1569 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1571 if (LIKELY(ret == sizeof(data)))
1577 uvc_error_t uvc_get_digital_multiplier(uvc_device_handle_t *devh, uint16_t *multiplier,
1578 enum uvc_req_code req_code) {
1582 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1583 UVC_PU_DIGITAL_MULTIPLIER_CONTROL << 8,
1584 devh->info->ctrl_if.processing_unit_descs->request,
1585 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1587 if (LIKELY(ret == sizeof(data))) {
1588 *multiplier = SW_TO_SHORT(data);
1593 RETURN(-1, uvc_error_t);
1596 uvc_error_t uvc_set_digital_multiplier(uvc_device_handle_t *devh, uint16_t multiplier) {
1600 SHORT_TO_SW(multiplier, data);
1602 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1603 UVC_PU_DIGITAL_MULTIPLIER_CONTROL << 8,
1604 devh->info->ctrl_if.processing_unit_descs->request,
1605 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1607 if (LIKELY(ret == sizeof(data)))
1613 uvc_error_t uvc_get_digital_multiplier_limit(uvc_device_handle_t *devh, uint16_t *limit,
1614 enum uvc_req_code req_code) {
1618 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1619 UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL << 8,
1620 devh->info->ctrl_if.processing_unit_descs->request,
1621 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1623 if (LIKELY(ret == sizeof(data))) {
1624 *limit = SW_TO_SHORT(data);
1629 RETURN(-1, uvc_error_t);
1632 uvc_error_t uvc_set_digital_multiplier_limit(uvc_device_handle_t *devh, uint16_t limit) {
1636 SHORT_TO_SW(limit, data);
1638 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1639 UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL << 8,
1640 devh->info->ctrl_if.processing_unit_descs->request,
1641 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1643 if (LIKELY(ret == sizeof(data)))
1649 uvc_error_t uvc_get_analog_video_standard(uvc_device_handle_t *devh, uint8_t *standard,
1650 enum uvc_req_code req_code) {
1654 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1655 UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL << 8,
1656 devh->info->ctrl_if.processing_unit_descs->request,
1657 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1659 if (LIKELY(ret == sizeof(data))) {
1660 *standard = data[0];
1665 RETURN(-1, uvc_error_t);
1668 uvc_error_t uvc_set_analog_video_standard(uvc_device_handle_t *devh, uint8_t standard) {
1674 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1675 UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL << 8,
1676 devh->info->ctrl_if.processing_unit_descs->request,
1677 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1679 if (LIKELY(ret == sizeof(data)))
1685 uvc_error_t uvc_get_analog_video_lockstate(uvc_device_handle_t *devh, uint8_t *lock_state,
1686 enum uvc_req_code req_code) {
1690 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_GET, req_code,
1691 UVC_PU_ANALOG_LOCK_STATUS_CONTROL << 8,
1692 devh->info->ctrl_if.processing_unit_descs->request,
1693 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1695 if (LIKELY(ret == sizeof(data))) {
1696 *lock_state = data[0];
1701 RETURN(-1, uvc_error_t);
1704 uvc_error_t uvc_set_analog_video_lockstate(uvc_device_handle_t *devh, uint8_t lock_state) {
1708 data[0] = lock_state;
1710 ret = libusb_control_transfer(devh->usb_devh, REQ_TYPE_SET, UVC_SET_CUR,
1711 UVC_PU_ANALOG_LOCK_STATUS_CONTROL << 8,
1712 devh->info->ctrl_if.processing_unit_descs->request,
1713 data, sizeof(data), CTRL_TIMEOUT_MILLIS);
1715 if (LIKELY(ret == sizeof(data)))