blob: f15a437e58615c9c0e16f88b8f09d2f0a4491c1b [file] [log] [blame]
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001/*
2 * uvc_ctrl.c -- USB Video Class driver - Controls
3 *
Laurent Pinchart11fc5ba2010-09-20 06:10:10 -03004 * Copyright (C) 2005-2010
5 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 */
13
14#include <linux/kernel.h>
Laurent Pinchartc0efd232008-06-30 15:04:50 -030015#include <linux/list.h>
16#include <linux/module.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Laurent Pinchartc0efd232008-06-30 15:04:50 -030018#include <linux/uaccess.h>
19#include <linux/usb.h>
20#include <linux/videodev2.h>
21#include <linux/vmalloc.h>
22#include <linux/wait.h>
Arun Sharma600634972011-07-26 16:09:06 -070023#include <linux/atomic.h>
Hans de Goedeb4012002012-04-08 12:59:51 -030024#include <media/v4l2-ctrls.h>
Laurent Pinchartc0efd232008-06-30 15:04:50 -030025
26#include "uvcvideo.h"
27
Laurent Pinchartc0efd232008-06-30 15:04:50 -030028#define UVC_CTRL_DATA_CURRENT 0
29#define UVC_CTRL_DATA_BACKUP 1
Laurent Pinchart59529082010-01-23 06:30:20 -030030#define UVC_CTRL_DATA_MIN 2
31#define UVC_CTRL_DATA_MAX 3
32#define UVC_CTRL_DATA_RES 4
33#define UVC_CTRL_DATA_DEF 5
34#define UVC_CTRL_DATA_LAST 6
Laurent Pinchartc0efd232008-06-30 15:04:50 -030035
36/* ------------------------------------------------------------------------
Laurent Pinchart2c2d2642009-01-03 19:12:40 -030037 * Controls
Laurent Pinchartc0efd232008-06-30 15:04:50 -030038 */
39
40static struct uvc_control_info uvc_ctrls[] = {
41 {
42 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030043 .selector = UVC_PU_BRIGHTNESS_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030044 .index = 0,
45 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -030046 .flags = UVC_CTRL_FLAG_SET_CUR
47 | UVC_CTRL_FLAG_GET_RANGE
48 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030049 },
50 {
51 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030052 .selector = UVC_PU_CONTRAST_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030053 .index = 1,
54 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -030055 .flags = UVC_CTRL_FLAG_SET_CUR
56 | UVC_CTRL_FLAG_GET_RANGE
57 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030058 },
59 {
60 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030061 .selector = UVC_PU_HUE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030062 .index = 2,
63 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -030064 .flags = UVC_CTRL_FLAG_SET_CUR
65 | UVC_CTRL_FLAG_GET_RANGE
66 | UVC_CTRL_FLAG_RESTORE
67 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030068 },
69 {
70 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030071 .selector = UVC_PU_SATURATION_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030072 .index = 3,
73 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -030074 .flags = UVC_CTRL_FLAG_SET_CUR
75 | UVC_CTRL_FLAG_GET_RANGE
76 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030077 },
78 {
79 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030080 .selector = UVC_PU_SHARPNESS_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030081 .index = 4,
82 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -030083 .flags = UVC_CTRL_FLAG_SET_CUR
84 | UVC_CTRL_FLAG_GET_RANGE
85 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030086 },
87 {
88 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030089 .selector = UVC_PU_GAMMA_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030090 .index = 5,
91 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -030092 .flags = UVC_CTRL_FLAG_SET_CUR
93 | UVC_CTRL_FLAG_GET_RANGE
94 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -030095 },
96 {
97 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -030098 .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -030099 .index = 6,
100 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300101 .flags = UVC_CTRL_FLAG_SET_CUR
102 | UVC_CTRL_FLAG_GET_RANGE
103 | UVC_CTRL_FLAG_RESTORE
104 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300105 },
106 {
107 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300108 .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300109 .index = 7,
110 .size = 4,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300111 .flags = UVC_CTRL_FLAG_SET_CUR
112 | UVC_CTRL_FLAG_GET_RANGE
113 | UVC_CTRL_FLAG_RESTORE
114 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300115 },
116 {
117 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300118 .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300119 .index = 8,
120 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300121 .flags = UVC_CTRL_FLAG_SET_CUR
122 | UVC_CTRL_FLAG_GET_RANGE
123 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300124 },
125 {
126 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300127 .selector = UVC_PU_GAIN_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300128 .index = 9,
129 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300130 .flags = UVC_CTRL_FLAG_SET_CUR
131 | UVC_CTRL_FLAG_GET_RANGE
132 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300133 },
134 {
135 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300136 .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300137 .index = 10,
138 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300139 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
140 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300141 },
142 {
143 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300144 .selector = UVC_PU_HUE_AUTO_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300145 .index = 11,
146 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300147 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
148 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300149 },
150 {
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300151 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300152 .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300153 .index = 12,
154 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300155 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
156 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300157 },
158 {
159 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300160 .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300161 .index = 13,
162 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300163 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
164 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300165 },
166 {
167 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300168 .selector = UVC_PU_DIGITAL_MULTIPLIER_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300169 .index = 14,
170 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300171 .flags = UVC_CTRL_FLAG_SET_CUR
172 | UVC_CTRL_FLAG_GET_RANGE
173 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300174 },
175 {
176 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300177 .selector = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300178 .index = 15,
179 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300180 .flags = UVC_CTRL_FLAG_SET_CUR
181 | UVC_CTRL_FLAG_GET_RANGE
182 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300183 },
184 {
185 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300186 .selector = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300187 .index = 16,
188 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300189 .flags = UVC_CTRL_FLAG_GET_CUR,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300190 },
191 {
192 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300193 .selector = UVC_PU_ANALOG_LOCK_STATUS_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300194 .index = 17,
195 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300196 .flags = UVC_CTRL_FLAG_GET_CUR,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300197 },
198 {
199 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300200 .selector = UVC_CT_SCANNING_MODE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300201 .index = 0,
202 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300203 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
204 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300205 },
206 {
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300207 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300208 .selector = UVC_CT_AE_MODE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300209 .index = 1,
210 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300211 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
212 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_GET_RES
213 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300214 },
215 {
216 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300217 .selector = UVC_CT_AE_PRIORITY_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300218 .index = 2,
219 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300220 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
221 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300222 },
223 {
224 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300225 .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300226 .index = 3,
227 .size = 4,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300228 .flags = UVC_CTRL_FLAG_SET_CUR
229 | UVC_CTRL_FLAG_GET_RANGE
230 | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300231 },
232 {
233 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300234 .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300235 .index = 4,
236 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300237 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300238 },
239 {
240 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300241 .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300242 .index = 5,
243 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300244 .flags = UVC_CTRL_FLAG_SET_CUR
245 | UVC_CTRL_FLAG_GET_RANGE
246 | UVC_CTRL_FLAG_RESTORE
247 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300248 },
249 {
250 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300251 .selector = UVC_CT_FOCUS_RELATIVE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300252 .index = 6,
253 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300254 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
255 | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
256 | UVC_CTRL_FLAG_GET_DEF
257 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300258 },
259 {
260 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300261 .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300262 .index = 7,
263 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300264 .flags = UVC_CTRL_FLAG_SET_CUR
265 | UVC_CTRL_FLAG_GET_RANGE
266 | UVC_CTRL_FLAG_RESTORE
267 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300268 },
269 {
270 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300271 .selector = UVC_CT_IRIS_RELATIVE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300272 .index = 8,
273 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300274 .flags = UVC_CTRL_FLAG_SET_CUR
275 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300276 },
277 {
278 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300279 .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300280 .index = 9,
281 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300282 .flags = UVC_CTRL_FLAG_SET_CUR
283 | UVC_CTRL_FLAG_GET_RANGE
284 | UVC_CTRL_FLAG_RESTORE
285 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300286 },
287 {
288 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300289 .selector = UVC_CT_ZOOM_RELATIVE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300290 .index = 10,
291 .size = 3,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300292 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
293 | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
294 | UVC_CTRL_FLAG_GET_DEF
295 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300296 },
297 {
298 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300299 .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300300 .index = 11,
301 .size = 8,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300302 .flags = UVC_CTRL_FLAG_SET_CUR
303 | UVC_CTRL_FLAG_GET_RANGE
304 | UVC_CTRL_FLAG_RESTORE
305 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300306 },
307 {
308 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300309 .selector = UVC_CT_PANTILT_RELATIVE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300310 .index = 12,
311 .size = 4,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300312 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
313 | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
314 | UVC_CTRL_FLAG_GET_DEF
315 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300316 },
317 {
318 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300319 .selector = UVC_CT_ROLL_ABSOLUTE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300320 .index = 13,
321 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300322 .flags = UVC_CTRL_FLAG_SET_CUR
323 | UVC_CTRL_FLAG_GET_RANGE
324 | UVC_CTRL_FLAG_RESTORE
325 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300326 },
327 {
328 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300329 .selector = UVC_CT_ROLL_RELATIVE_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300330 .index = 14,
331 .size = 2,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300332 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
333 | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
334 | UVC_CTRL_FLAG_GET_DEF
335 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300336 },
337 {
338 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300339 .selector = UVC_CT_FOCUS_AUTO_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300340 .index = 17,
341 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300342 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
343 | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300344 },
345 {
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300346 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300347 .selector = UVC_CT_PRIVACY_CONTROL,
Laurent Pinchart5e26d502008-09-22 13:14:59 -0300348 .index = 18,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300349 .size = 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300350 .flags = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
351 | UVC_CTRL_FLAG_RESTORE
352 | UVC_CTRL_FLAG_AUTO_UPDATE,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300353 },
354};
355
356static struct uvc_menu_info power_line_frequency_controls[] = {
357 { 0, "Disabled" },
358 { 1, "50 Hz" },
359 { 2, "60 Hz" },
360};
361
362static struct uvc_menu_info exposure_auto_controls[] = {
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300363 { 2, "Auto Mode" },
Laurent Pinchart90ac5ea2008-07-26 11:42:29 -0300364 { 1, "Manual Mode" },
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300365 { 4, "Shutter Priority Mode" },
366 { 8, "Aperture Priority Mode" },
367};
368
Laurent Pinchart97683522008-12-16 06:46:32 -0300369static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
370 __u8 query, const __u8 *data)
371{
372 __s8 zoom = (__s8)data[0];
373
374 switch (query) {
Laurent Pinchartb482d922009-06-26 11:39:42 -0300375 case UVC_GET_CUR:
Laurent Pinchart97683522008-12-16 06:46:32 -0300376 return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
377
Laurent Pinchartb482d922009-06-26 11:39:42 -0300378 case UVC_GET_MIN:
379 case UVC_GET_MAX:
380 case UVC_GET_RES:
381 case UVC_GET_DEF:
Laurent Pinchart97683522008-12-16 06:46:32 -0300382 default:
383 return data[2];
384 }
385}
386
387static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
388 __s32 value, __u8 *data)
389{
390 data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
Laurent Pinchart2e896132009-11-04 13:11:10 -0300391 data[2] = min((int)abs(value), 0xff);
Laurent Pinchart97683522008-12-16 06:46:32 -0300392}
393
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300394static struct uvc_control_mapping uvc_ctrl_mappings[] = {
395 {
396 .id = V4L2_CID_BRIGHTNESS,
397 .name = "Brightness",
398 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300399 .selector = UVC_PU_BRIGHTNESS_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300400 .size = 16,
401 .offset = 0,
402 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
403 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
404 },
405 {
406 .id = V4L2_CID_CONTRAST,
407 .name = "Contrast",
408 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300409 .selector = UVC_PU_CONTRAST_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300410 .size = 16,
411 .offset = 0,
412 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
413 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
414 },
415 {
416 .id = V4L2_CID_HUE,
417 .name = "Hue",
418 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300419 .selector = UVC_PU_HUE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300420 .size = 16,
421 .offset = 0,
422 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
423 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
424 },
425 {
426 .id = V4L2_CID_SATURATION,
427 .name = "Saturation",
428 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300429 .selector = UVC_PU_SATURATION_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300430 .size = 16,
431 .offset = 0,
432 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
433 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
434 },
435 {
436 .id = V4L2_CID_SHARPNESS,
437 .name = "Sharpness",
438 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300439 .selector = UVC_PU_SHARPNESS_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300440 .size = 16,
441 .offset = 0,
442 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
443 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
444 },
445 {
446 .id = V4L2_CID_GAMMA,
447 .name = "Gamma",
448 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300449 .selector = UVC_PU_GAMMA_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300450 .size = 16,
451 .offset = 0,
452 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
453 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
454 },
455 {
456 .id = V4L2_CID_BACKLIGHT_COMPENSATION,
457 .name = "Backlight Compensation",
458 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300459 .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300460 .size = 16,
461 .offset = 0,
462 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
463 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
464 },
465 {
466 .id = V4L2_CID_GAIN,
467 .name = "Gain",
468 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300469 .selector = UVC_PU_GAIN_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300470 .size = 16,
471 .offset = 0,
472 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
473 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
474 },
475 {
476 .id = V4L2_CID_POWER_LINE_FREQUENCY,
477 .name = "Power Line Frequency",
478 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300479 .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300480 .size = 2,
481 .offset = 0,
482 .v4l2_type = V4L2_CTRL_TYPE_MENU,
483 .data_type = UVC_CTRL_DATA_TYPE_ENUM,
484 .menu_info = power_line_frequency_controls,
485 .menu_count = ARRAY_SIZE(power_line_frequency_controls),
486 },
487 {
488 .id = V4L2_CID_HUE_AUTO,
489 .name = "Hue, Auto",
490 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300491 .selector = UVC_PU_HUE_AUTO_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300492 .size = 1,
493 .offset = 0,
494 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
495 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
496 },
497 {
498 .id = V4L2_CID_EXPOSURE_AUTO,
499 .name = "Exposure, Auto",
500 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300501 .selector = UVC_CT_AE_MODE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300502 .size = 4,
503 .offset = 0,
504 .v4l2_type = V4L2_CTRL_TYPE_MENU,
505 .data_type = UVC_CTRL_DATA_TYPE_BITMASK,
506 .menu_info = exposure_auto_controls,
507 .menu_count = ARRAY_SIZE(exposure_auto_controls),
508 },
509 {
510 .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
511 .name = "Exposure, Auto Priority",
512 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300513 .selector = UVC_CT_AE_PRIORITY_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300514 .size = 1,
515 .offset = 0,
516 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
517 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
518 },
519 {
520 .id = V4L2_CID_EXPOSURE_ABSOLUTE,
521 .name = "Exposure (Absolute)",
522 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300523 .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300524 .size = 32,
525 .offset = 0,
526 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
527 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
528 },
529 {
530 .id = V4L2_CID_AUTO_WHITE_BALANCE,
531 .name = "White Balance Temperature, Auto",
532 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300533 .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300534 .size = 1,
535 .offset = 0,
536 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
537 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
538 },
539 {
540 .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
541 .name = "White Balance Temperature",
542 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300543 .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300544 .size = 16,
545 .offset = 0,
546 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
547 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
548 },
549 {
550 .id = V4L2_CID_AUTO_WHITE_BALANCE,
551 .name = "White Balance Component, Auto",
552 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300553 .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300554 .size = 1,
555 .offset = 0,
556 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
557 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
558 },
559 {
560 .id = V4L2_CID_BLUE_BALANCE,
561 .name = "White Balance Blue Component",
562 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300563 .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300564 .size = 16,
565 .offset = 0,
566 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
567 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
568 },
569 {
570 .id = V4L2_CID_RED_BALANCE,
571 .name = "White Balance Red Component",
572 .entity = UVC_GUID_UVC_PROCESSING,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300573 .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300574 .size = 16,
575 .offset = 16,
576 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
577 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
578 },
579 {
580 .id = V4L2_CID_FOCUS_ABSOLUTE,
581 .name = "Focus (absolute)",
582 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300583 .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300584 .size = 16,
585 .offset = 0,
586 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
587 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
588 },
589 {
590 .id = V4L2_CID_FOCUS_AUTO,
591 .name = "Focus, Auto",
592 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300593 .selector = UVC_CT_FOCUS_AUTO_CONTROL,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300594 .size = 1,
595 .offset = 0,
596 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
597 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
598 },
Laurent Pinchart6df126f2008-12-16 06:44:11 -0300599 {
Laurent Pinchart35a00c42010-01-20 12:13:46 -0300600 .id = V4L2_CID_IRIS_ABSOLUTE,
601 .name = "Iris, Absolute",
602 .entity = UVC_GUID_UVC_CAMERA,
603 .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL,
604 .size = 16,
605 .offset = 0,
606 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
607 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
608 },
609 {
610 .id = V4L2_CID_IRIS_RELATIVE,
611 .name = "Iris, Relative",
612 .entity = UVC_GUID_UVC_CAMERA,
613 .selector = UVC_CT_IRIS_RELATIVE_CONTROL,
614 .size = 8,
615 .offset = 0,
616 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
617 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
618 },
619 {
Laurent Pinchart97683522008-12-16 06:46:32 -0300620 .id = V4L2_CID_ZOOM_ABSOLUTE,
621 .name = "Zoom, Absolute",
622 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300623 .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
Laurent Pinchart97683522008-12-16 06:46:32 -0300624 .size = 16,
625 .offset = 0,
626 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
627 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
628 },
629 {
630 .id = V4L2_CID_ZOOM_CONTINUOUS,
631 .name = "Zoom, Continuous",
632 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300633 .selector = UVC_CT_ZOOM_RELATIVE_CONTROL,
Laurent Pinchart97683522008-12-16 06:46:32 -0300634 .size = 0,
635 .offset = 0,
636 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
637 .data_type = UVC_CTRL_DATA_TYPE_SIGNED,
638 .get = uvc_ctrl_get_zoom,
639 .set = uvc_ctrl_set_zoom,
640 },
641 {
Martin Rublie56be912010-05-19 19:51:56 -0300642 .id = V4L2_CID_PAN_ABSOLUTE,
643 .name = "Pan (Absolute)",
644 .entity = UVC_GUID_UVC_CAMERA,
645 .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
646 .size = 32,
647 .offset = 0,
648 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
649 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
650 },
651 {
652 .id = V4L2_CID_TILT_ABSOLUTE,
653 .name = "Tilt (Absolute)",
654 .entity = UVC_GUID_UVC_CAMERA,
655 .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
656 .size = 32,
657 .offset = 32,
658 .v4l2_type = V4L2_CTRL_TYPE_INTEGER,
659 .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED,
660 },
661 {
Laurent Pinchart6df126f2008-12-16 06:44:11 -0300662 .id = V4L2_CID_PRIVACY,
663 .name = "Privacy",
664 .entity = UVC_GUID_UVC_CAMERA,
Laurent Pinchartb482d922009-06-26 11:39:42 -0300665 .selector = UVC_CT_PRIVACY_CONTROL,
Laurent Pinchart6df126f2008-12-16 06:44:11 -0300666 .size = 1,
667 .offset = 0,
668 .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN,
669 .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN,
670 },
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300671};
672
673/* ------------------------------------------------------------------------
674 * Utility functions
675 */
676
677static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
678{
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300679 return ctrl->uvc_data + id * ctrl->info.size;
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300680}
681
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -0300682static inline int uvc_test_bit(const __u8 *data, int bit)
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300683{
684 return (data[bit >> 3] >> (bit & 7)) & 1;
685}
686
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -0300687static inline void uvc_clear_bit(__u8 *data, int bit)
688{
689 data[bit >> 3] &= ~(1 << (bit & 7));
690}
691
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300692/* Extract the bit string specified by mapping->offset and mapping->size
693 * from the little-endian data stored at 'data' and return the result as
694 * a signed 32bit integer. Sign extension will be performed if the mapping
695 * references a signed data type.
696 */
Laurent Pinchart97683522008-12-16 06:46:32 -0300697static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
698 __u8 query, const __u8 *data)
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300699{
700 int bits = mapping->size;
701 int offset = mapping->offset;
702 __s32 value = 0;
703 __u8 mask;
704
705 data += offset / 8;
706 offset &= 7;
707 mask = ((1LL << bits) - 1) << offset;
708
709 for (; bits > 0; data++) {
710 __u8 byte = *data & mask;
711 value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
712 bits -= 8 - (offset > 0 ? offset : 0);
713 offset -= 8;
714 mask = (1 << bits) - 1;
715 }
716
Laurent Pinchart2c2d2642009-01-03 19:12:40 -0300717 /* Sign-extend the value if needed. */
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300718 if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
719 value |= -(value & (1 << (mapping->size - 1)));
720
721 return value;
722}
723
724/* Set the bit string specified by mapping->offset and mapping->size
725 * in the little-endian data stored at 'data' to the value 'value'.
726 */
Laurent Pinchart97683522008-12-16 06:46:32 -0300727static void uvc_set_le_value(struct uvc_control_mapping *mapping,
728 __s32 value, __u8 *data)
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300729{
730 int bits = mapping->size;
731 int offset = mapping->offset;
732 __u8 mask;
733
Hans de Goede36536392010-05-19 20:15:00 -0300734 /* According to the v4l2 spec, writing any value to a button control
735 * should result in the action belonging to the button control being
736 * triggered. UVC devices however want to see a 1 written -> override
737 * value.
738 */
739 if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON)
740 value = -1;
741
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300742 data += offset / 8;
743 offset &= 7;
744
745 for (; bits > 0; data++) {
746 mask = ((1LL << bits) - 1) << offset;
747 *data = (*data & ~mask) | ((value << offset) & mask);
748 value >>= offset ? offset : 8;
749 bits -= 8 - offset;
750 offset = 0;
751 }
752}
753
754/* ------------------------------------------------------------------------
755 * Terminal and unit management
756 */
757
758static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
759static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA;
760static const __u8 uvc_media_transport_input_guid[16] =
761 UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
762
Laurent Pinchartf9d81df2010-09-17 05:24:13 -0300763static int uvc_entity_match_guid(const struct uvc_entity *entity,
764 const __u8 guid[16])
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300765{
766 switch (UVC_ENTITY_TYPE(entity)) {
Laurent Pinchartb482d922009-06-26 11:39:42 -0300767 case UVC_ITT_CAMERA:
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300768 return memcmp(uvc_camera_guid, guid, 16) == 0;
769
Laurent Pinchartb482d922009-06-26 11:39:42 -0300770 case UVC_ITT_MEDIA_TRANSPORT_INPUT:
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300771 return memcmp(uvc_media_transport_input_guid, guid, 16) == 0;
772
Laurent Pinchartb482d922009-06-26 11:39:42 -0300773 case UVC_VC_PROCESSING_UNIT:
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300774 return memcmp(uvc_processing_guid, guid, 16) == 0;
775
Laurent Pinchartb482d922009-06-26 11:39:42 -0300776 case UVC_VC_EXTENSION_UNIT:
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300777 return memcmp(entity->extension.guidExtensionCode,
778 guid, 16) == 0;
779
780 default:
781 return 0;
782 }
783}
784
785/* ------------------------------------------------------------------------
786 * UVC Controls
787 */
788
789static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
790 struct uvc_control_mapping **mapping, struct uvc_control **control,
791 int next)
792{
793 struct uvc_control *ctrl;
794 struct uvc_control_mapping *map;
795 unsigned int i;
796
797 if (entity == NULL)
798 return;
799
800 for (i = 0; i < entity->ncontrols; ++i) {
801 ctrl = &entity->controls[i];
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300802 if (!ctrl->initialized)
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300803 continue;
804
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300805 list_for_each_entry(map, &ctrl->info.mappings, list) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300806 if ((map->id == v4l2_id) && !next) {
807 *control = ctrl;
808 *mapping = map;
809 return;
810 }
811
812 if ((*mapping == NULL || (*mapping)->id > map->id) &&
813 (map->id > v4l2_id) && next) {
814 *control = ctrl;
815 *mapping = map;
816 }
817 }
818 }
819}
820
Laurent Pinchart23d9f3e2010-11-21 07:58:54 -0300821static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300822 __u32 v4l2_id, struct uvc_control_mapping **mapping)
823{
824 struct uvc_control *ctrl = NULL;
825 struct uvc_entity *entity;
826 int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL;
827
828 *mapping = NULL;
829
830 /* Mask the query flags. */
831 v4l2_id &= V4L2_CTRL_ID_MASK;
832
833 /* Find the control. */
Laurent Pinchart6241d8c2009-11-25 12:00:22 -0300834 list_for_each_entry(entity, &chain->entities, chain) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300835 __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
836 if (ctrl && !next)
837 return ctrl;
838 }
839
840 if (ctrl == NULL && !next)
841 uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n",
842 v4l2_id);
843
844 return ctrl;
845}
846
Laurent Pinchart59529082010-01-23 06:30:20 -0300847static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
848 struct uvc_control *ctrl)
849{
850 int ret;
851
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300852 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
Laurent Pinchart59529082010-01-23 06:30:20 -0300853 ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id,
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300854 chain->dev->intfnum, ctrl->info.selector,
Laurent Pinchart59529082010-01-23 06:30:20 -0300855 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300856 ctrl->info.size);
Laurent Pinchart59529082010-01-23 06:30:20 -0300857 if (ret < 0)
858 return ret;
859 }
860
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300861 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) {
Laurent Pinchart59529082010-01-23 06:30:20 -0300862 ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id,
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300863 chain->dev->intfnum, ctrl->info.selector,
Laurent Pinchart59529082010-01-23 06:30:20 -0300864 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300865 ctrl->info.size);
Laurent Pinchart59529082010-01-23 06:30:20 -0300866 if (ret < 0)
867 return ret;
868 }
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300869 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) {
Laurent Pinchart59529082010-01-23 06:30:20 -0300870 ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300871 chain->dev->intfnum, ctrl->info.selector,
Laurent Pinchart59529082010-01-23 06:30:20 -0300872 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300873 ctrl->info.size);
Laurent Pinchart59529082010-01-23 06:30:20 -0300874 if (ret < 0)
875 return ret;
876 }
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300877 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
Laurent Pinchart59529082010-01-23 06:30:20 -0300878 ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300879 chain->dev->intfnum, ctrl->info.selector,
Laurent Pinchart59529082010-01-23 06:30:20 -0300880 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -0300881 ctrl->info.size);
Laurent Pinchartc4d99f82010-09-30 09:04:03 -0300882 if (ret < 0) {
883 if (UVC_ENTITY_TYPE(ctrl->entity) !=
884 UVC_VC_EXTENSION_UNIT)
885 return ret;
886
887 /* GET_RES is mandatory for XU controls, but some
888 * cameras still choke on it. Ignore errors and set the
889 * resolution value to zero.
890 */
891 uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES,
892 "UVC non compliance - GET_RES failed on "
893 "an XU control. Enabling workaround.\n");
894 memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0,
895 ctrl->info.size);
896 }
Laurent Pinchart59529082010-01-23 06:30:20 -0300897 }
898
899 ctrl->cached = 1;
900 return 0;
901}
902
Hans de Goedecb74d482012-04-08 12:59:50 -0300903static int __uvc_ctrl_get(struct uvc_video_chain *chain,
904 struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
905 s32 *value)
906{
907 struct uvc_menu_info *menu;
908 unsigned int i;
909 int ret;
910
911 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
912 return -EINVAL;
913
914 if (!ctrl->loaded) {
915 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
916 chain->dev->intfnum, ctrl->info.selector,
917 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
918 ctrl->info.size);
919 if (ret < 0)
920 return ret;
921
922 ctrl->loaded = 1;
923 }
924
925 *value = mapping->get(mapping, UVC_GET_CUR,
926 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
927
928 if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
929 menu = mapping->menu_info;
930 for (i = 0; i < mapping->menu_count; ++i, ++menu) {
931 if (menu->value == *value) {
932 *value = i;
933 break;
934 }
935 }
936 }
937
938 return 0;
939}
940
Hans de Goede35f16742012-04-08 12:59:49 -0300941static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
942 struct uvc_control *ctrl,
943 struct uvc_control_mapping *mapping,
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300944 struct v4l2_queryctrl *v4l2_ctrl)
945{
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300946 struct uvc_menu_info *menu;
947 unsigned int i;
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300948
Laurent Pinchart54812c72008-07-17 07:37:37 -0300949 memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300950 v4l2_ctrl->id = mapping->id;
951 v4l2_ctrl->type = mapping->v4l2_type;
Laurent Pinchartd0ebf302009-01-08 14:05:11 -0300952 strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300953 v4l2_ctrl->flags = 0;
954
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300955 if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
Laurent Pincharta90ef692010-04-25 16:23:24 -0300956 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300957 if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300958 v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
959
Laurent Pinchart59529082010-01-23 06:30:20 -0300960 if (!ctrl->cached) {
Hans de Goede35f16742012-04-08 12:59:49 -0300961 int ret = uvc_ctrl_populate_cache(chain, ctrl);
Laurent Pinchartb482d922009-06-26 11:39:42 -0300962 if (ret < 0)
Hans de Goede35f16742012-04-08 12:59:49 -0300963 return ret;
Laurent Pinchart59529082010-01-23 06:30:20 -0300964 }
965
Laurent Pinchart9eb30d22010-11-21 17:08:16 -0300966 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
Laurent Pinchart59529082010-01-23 06:30:20 -0300967 v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF,
968 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300969 }
970
Laurent Pinchart54812c72008-07-17 07:37:37 -0300971 switch (mapping->v4l2_type) {
972 case V4L2_CTRL_TYPE_MENU:
Laurent Pinchartc0efd232008-06-30 15:04:50 -0300973 v4l2_ctrl->minimum = 0;
974 v4l2_ctrl->maximum = mapping->menu_count - 1;
975 v4l2_ctrl->step = 1;
976
977 menu = mapping->menu_info;
978 for (i = 0; i < mapping->menu_count; ++i, ++menu) {
979 if (menu->value == v4l2_ctrl->default_value) {
980 v4l2_ctrl->default_value = i;
981 break;
982 }
983 }
984
Hans de Goede35f16742012-04-08 12:59:49 -0300985 return 0;
Laurent Pinchart54812c72008-07-17 07:37:37 -0300986
987 case V4L2_CTRL_TYPE_BOOLEAN:
988 v4l2_ctrl->minimum = 0;
989 v4l2_ctrl->maximum = 1;
990 v4l2_ctrl->step = 1;
Hans de Goede35f16742012-04-08 12:59:49 -0300991 return 0;
Laurent Pinchart54812c72008-07-17 07:37:37 -0300992
Laurent Pinchartf4eabaf2009-08-06 06:05:40 -0300993 case V4L2_CTRL_TYPE_BUTTON:
994 v4l2_ctrl->minimum = 0;
995 v4l2_ctrl->maximum = 0;
996 v4l2_ctrl->step = 0;
Hans de Goede35f16742012-04-08 12:59:49 -0300997 return 0;
Laurent Pinchartf4eabaf2009-08-06 06:05:40 -0300998
Laurent Pinchart54812c72008-07-17 07:37:37 -0300999 default:
1000 break;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001001 }
1002
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001003 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)
Laurent Pinchart59529082010-01-23 06:30:20 -03001004 v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
1005 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001006
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001007 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
Laurent Pinchart59529082010-01-23 06:30:20 -03001008 v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
1009 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
1010
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001011 if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
Laurent Pinchart59529082010-01-23 06:30:20 -03001012 v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
1013 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
1014
Hans de Goede35f16742012-04-08 12:59:49 -03001015 return 0;
1016}
1017
1018int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
1019 struct v4l2_queryctrl *v4l2_ctrl)
1020{
1021 struct uvc_control *ctrl;
1022 struct uvc_control_mapping *mapping;
1023 int ret;
1024
1025 ret = mutex_lock_interruptible(&chain->ctrl_mutex);
1026 if (ret < 0)
1027 return -ERESTARTSYS;
1028
1029 ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
1030 if (ctrl == NULL) {
1031 ret = -EINVAL;
1032 goto done;
1033 }
1034
1035 ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl);
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001036done:
1037 mutex_unlock(&chain->ctrl_mutex);
1038 return ret;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001039}
1040
Laurent Pinchart23d9f3e2010-11-21 07:58:54 -03001041/*
1042 * Mapping V4L2 controls to UVC controls can be straighforward if done well.
1043 * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
1044 * must be grouped (for instance the Red Balance, Blue Balance and Do White
1045 * Balance V4L2 controls use the White Balance Component UVC control) or
1046 * otherwise translated. The approach we take here is to use a translation
1047 * table for the controls that can be mapped directly, and handle the others
1048 * manually.
1049 */
1050int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
1051 struct v4l2_querymenu *query_menu)
1052{
1053 struct uvc_menu_info *menu_info;
1054 struct uvc_control_mapping *mapping;
1055 struct uvc_control *ctrl;
1056 u32 index = query_menu->index;
1057 u32 id = query_menu->id;
1058 int ret;
1059
1060 memset(query_menu, 0, sizeof(*query_menu));
1061 query_menu->id = id;
1062 query_menu->index = index;
1063
1064 ret = mutex_lock_interruptible(&chain->ctrl_mutex);
1065 if (ret < 0)
1066 return -ERESTARTSYS;
1067
1068 ctrl = uvc_find_control(chain, query_menu->id, &mapping);
1069 if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
1070 ret = -EINVAL;
1071 goto done;
1072 }
1073
1074 if (query_menu->index >= mapping->menu_count) {
1075 ret = -EINVAL;
1076 goto done;
1077 }
1078
1079 menu_info = &mapping->menu_info[query_menu->index];
Laurent Pinchartfc2d5732011-04-30 09:46:11 -03001080
Hans de Goede241fa6e2011-10-11 11:54:26 -03001081 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
1082 (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
Laurent Pinchartfc2d5732011-04-30 09:46:11 -03001083 s32 bitmap;
1084
1085 if (!ctrl->cached) {
1086 ret = uvc_ctrl_populate_cache(chain, ctrl);
1087 if (ret < 0)
1088 goto done;
1089 }
1090
1091 bitmap = mapping->get(mapping, UVC_GET_RES,
1092 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
1093 if (!(bitmap & menu_info->value)) {
1094 ret = -EINVAL;
1095 goto done;
1096 }
1097 }
1098
Laurent Pinchart23d9f3e2010-11-21 07:58:54 -03001099 strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
1100
1101done:
1102 mutex_unlock(&chain->ctrl_mutex);
1103 return ret;
1104}
1105
Hans de Goedeb4012002012-04-08 12:59:51 -03001106/* --------------------------------------------------------------------------
1107 * Ctrl event handling
1108 */
1109
1110static void uvc_ctrl_fill_event(struct uvc_video_chain *chain,
1111 struct v4l2_event *ev,
1112 struct uvc_control *ctrl,
1113 struct uvc_control_mapping *mapping,
1114 s32 value, u32 changes)
1115{
1116 struct v4l2_queryctrl v4l2_ctrl;
1117
1118 __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl);
1119
1120 memset(ev->reserved, 0, sizeof(ev->reserved));
1121 ev->type = V4L2_EVENT_CTRL;
1122 ev->id = v4l2_ctrl.id;
1123 ev->u.ctrl.value = value;
1124 ev->u.ctrl.changes = changes;
1125 ev->u.ctrl.type = v4l2_ctrl.type;
1126 ev->u.ctrl.flags = v4l2_ctrl.flags;
1127 ev->u.ctrl.minimum = v4l2_ctrl.minimum;
1128 ev->u.ctrl.maximum = v4l2_ctrl.maximum;
1129 ev->u.ctrl.step = v4l2_ctrl.step;
1130 ev->u.ctrl.default_value = v4l2_ctrl.default_value;
1131}
1132
1133static void uvc_ctrl_send_event(struct uvc_fh *handle,
1134 struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
1135 s32 value, u32 changes)
1136{
1137 struct v4l2_subscribed_event *sev;
1138 struct v4l2_event ev;
1139
1140 if (list_empty(&mapping->ev_subs))
1141 return;
1142
1143 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, value, changes);
1144
1145 list_for_each_entry(sev, &mapping->ev_subs, node) {
1146 if (sev->fh && (sev->fh != &handle->vfh ||
1147 (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
1148 v4l2_event_queue_fh(sev->fh, &ev);
1149 }
1150}
1151
1152static void uvc_ctrl_send_events(struct uvc_fh *handle,
1153 const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
1154{
1155 struct uvc_control_mapping *mapping;
1156 struct uvc_control *ctrl;
1157 unsigned int i;
1158
1159 for (i = 0; i < xctrls_count; ++i) {
1160 ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
1161 uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
1162 V4L2_EVENT_CTRL_CH_VALUE);
1163 }
1164}
1165
1166static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev)
1167{
1168 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
1169 struct uvc_control_mapping *mapping;
1170 struct uvc_control *ctrl;
1171 int ret;
1172
1173 ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex);
1174 if (ret < 0)
1175 return -ERESTARTSYS;
1176
1177 ctrl = uvc_find_control(handle->chain, sev->id, &mapping);
1178 if (ctrl == NULL) {
1179 ret = -EINVAL;
1180 goto done;
1181 }
1182
1183 list_add_tail(&sev->node, &mapping->ev_subs);
1184 if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) {
1185 struct v4l2_event ev;
1186 u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
1187 s32 val = 0;
1188
1189 if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
1190 changes |= V4L2_EVENT_CTRL_CH_VALUE;
1191
1192 uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
1193 changes);
1194 v4l2_event_queue_fh(sev->fh, &ev);
1195 }
1196
1197done:
1198 mutex_unlock(&handle->chain->ctrl_mutex);
1199 return ret;
1200}
1201
1202static void uvc_ctrl_del_event(struct v4l2_subscribed_event *sev)
1203{
1204 struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
1205
1206 mutex_lock(&handle->chain->ctrl_mutex);
1207 list_del(&sev->node);
1208 mutex_unlock(&handle->chain->ctrl_mutex);
1209}
1210
1211const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops = {
1212 .add = uvc_ctrl_add_event,
1213 .del = uvc_ctrl_del_event,
1214 .replace = v4l2_ctrl_replace,
1215 .merge = v4l2_ctrl_merge,
1216};
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001217
1218/* --------------------------------------------------------------------------
1219 * Control transactions
1220 *
1221 * To make extended set operations as atomic as the hardware allows, controls
1222 * are handled using begin/commit/rollback operations.
1223 *
1224 * At the beginning of a set request, uvc_ctrl_begin should be called to
1225 * initialize the request. This function acquires the control lock.
1226 *
1227 * When setting a control, the new value is stored in the control data field
1228 * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for
1229 * later processing. If the UVC and V4L2 control sizes differ, the current
1230 * value is loaded from the hardware before storing the new value in the data
1231 * field.
1232 *
1233 * After processing all controls in the transaction, uvc_ctrl_commit or
1234 * uvc_ctrl_rollback must be called to apply the pending changes to the
1235 * hardware or revert them. When applying changes, all controls marked as
1236 * dirty will be modified in the UVC device, and the dirty flag will be
1237 * cleared. When reverting controls, the control data field
1238 * UVC_CTRL_DATA_CURRENT is reverted to its previous value
1239 * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
1240 * control lock.
1241 */
Laurent Pinchart8e113592009-07-01 20:24:47 -03001242int uvc_ctrl_begin(struct uvc_video_chain *chain)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001243{
Laurent Pinchart8e113592009-07-01 20:24:47 -03001244 return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001245}
1246
1247static int uvc_ctrl_commit_entity(struct uvc_device *dev,
1248 struct uvc_entity *entity, int rollback)
1249{
1250 struct uvc_control *ctrl;
1251 unsigned int i;
1252 int ret;
1253
1254 if (entity == NULL)
1255 return 0;
1256
1257 for (i = 0; i < entity->ncontrols; ++i) {
1258 ctrl = &entity->controls[i];
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001259 if (!ctrl->initialized)
Laurent Pinchartb1accfa2008-09-27 20:54:02 -03001260 continue;
1261
1262 /* Reset the loaded flag for auto-update controls that were
1263 * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent
1264 * uvc_ctrl_get from using the cached value.
1265 */
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001266 if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE)
Laurent Pinchartb1accfa2008-09-27 20:54:02 -03001267 ctrl->loaded = 0;
1268
1269 if (!ctrl->dirty)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001270 continue;
1271
1272 if (!rollback)
Laurent Pinchartb482d922009-06-26 11:39:42 -03001273 ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id,
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001274 dev->intfnum, ctrl->info.selector,
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001275 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001276 ctrl->info.size);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001277 else
1278 ret = 0;
1279
1280 if (rollback || ret < 0)
1281 memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
1282 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001283 ctrl->info.size);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001284
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001285 ctrl->dirty = 0;
1286
1287 if (ret < 0)
1288 return ret;
1289 }
1290
1291 return 0;
1292}
1293
Hans de Goedeb4012002012-04-08 12:59:51 -03001294int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
1295 const struct v4l2_ext_control *xctrls,
1296 unsigned int xctrls_count)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001297{
Hans de Goedeb4012002012-04-08 12:59:51 -03001298 struct uvc_video_chain *chain = handle->chain;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001299 struct uvc_entity *entity;
1300 int ret = 0;
1301
1302 /* Find the control. */
Laurent Pinchart6241d8c2009-11-25 12:00:22 -03001303 list_for_each_entry(entity, &chain->entities, chain) {
Laurent Pinchart8e113592009-07-01 20:24:47 -03001304 ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001305 if (ret < 0)
1306 goto done;
1307 }
1308
Hans de Goedeb4012002012-04-08 12:59:51 -03001309 if (!rollback)
1310 uvc_ctrl_send_events(handle, xctrls, xctrls_count);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001311done:
Laurent Pinchart8e113592009-07-01 20:24:47 -03001312 mutex_unlock(&chain->ctrl_mutex);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001313 return ret;
1314}
1315
Hans de Goede35f16742012-04-08 12:59:49 -03001316int uvc_ctrl_get(struct uvc_video_chain *chain,
1317 struct v4l2_ext_control *xctrl)
1318{
1319 struct uvc_control *ctrl;
1320 struct uvc_control_mapping *mapping;
1321
1322 ctrl = uvc_find_control(chain, xctrl->id, &mapping);
1323 if (ctrl == NULL)
1324 return -EINVAL;
1325
1326 return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
1327}
1328
Laurent Pinchart8e113592009-07-01 20:24:47 -03001329int uvc_ctrl_set(struct uvc_video_chain *chain,
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001330 struct v4l2_ext_control *xctrl)
1331{
1332 struct uvc_control *ctrl;
1333 struct uvc_control_mapping *mapping;
Laurent Pincharte54532e2010-01-23 07:07:53 -03001334 s32 value;
1335 u32 step;
1336 s32 min;
1337 s32 max;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001338 int ret;
1339
Laurent Pinchart8e113592009-07-01 20:24:47 -03001340 ctrl = uvc_find_control(chain, xctrl->id, &mapping);
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001341 if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001342 return -EINVAL;
1343
Laurent Pincharte54532e2010-01-23 07:07:53 -03001344 /* Clamp out of range values. */
1345 switch (mapping->v4l2_type) {
1346 case V4L2_CTRL_TYPE_INTEGER:
1347 if (!ctrl->cached) {
1348 ret = uvc_ctrl_populate_cache(chain, ctrl);
1349 if (ret < 0)
1350 return ret;
1351 }
1352
1353 min = mapping->get(mapping, UVC_GET_MIN,
1354 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
1355 max = mapping->get(mapping, UVC_GET_MAX,
1356 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
1357 step = mapping->get(mapping, UVC_GET_RES,
1358 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
Laurent Pinchartcf7a50e2010-04-25 16:27:14 -03001359 if (step == 0)
1360 step = 1;
Laurent Pincharte54532e2010-01-23 07:07:53 -03001361
1362 xctrl->value = min + (xctrl->value - min + step/2) / step * step;
1363 xctrl->value = clamp(xctrl->value, min, max);
1364 value = xctrl->value;
1365 break;
1366
1367 case V4L2_CTRL_TYPE_BOOLEAN:
1368 xctrl->value = clamp(xctrl->value, 0, 1);
1369 value = xctrl->value;
1370 break;
1371
1372 case V4L2_CTRL_TYPE_MENU:
1373 if (xctrl->value < 0 || xctrl->value >= mapping->menu_count)
Laurent Pinchart8a4e76c2010-01-21 16:53:11 -03001374 return -ERANGE;
Laurent Pincharte54532e2010-01-23 07:07:53 -03001375 value = mapping->menu_info[xctrl->value].value;
Laurent Pinchartf411f102011-04-30 09:46:11 -03001376
1377 /* Valid menu indices are reported by the GET_RES request for
1378 * UVC controls that support it.
1379 */
Hans de Goede241fa6e2011-10-11 11:54:26 -03001380 if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
1381 (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
Laurent Pinchartf411f102011-04-30 09:46:11 -03001382 if (!ctrl->cached) {
1383 ret = uvc_ctrl_populate_cache(chain, ctrl);
1384 if (ret < 0)
1385 return ret;
1386 }
1387
1388 step = mapping->get(mapping, UVC_GET_RES,
1389 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
1390 if (!(step & value))
1391 return -ERANGE;
1392 }
1393
Laurent Pincharte54532e2010-01-23 07:07:53 -03001394 break;
1395
1396 default:
1397 value = xctrl->value;
1398 break;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001399 }
1400
Laurent Pincharte54532e2010-01-23 07:07:53 -03001401 /* If the mapping doesn't span the whole UVC control, the current value
1402 * needs to be loaded from the device to perform the read-modify-write
1403 * operation.
1404 */
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001405 if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001406 if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001407 memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001408 0, ctrl->info.size);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001409 } else {
Laurent Pinchart8e113592009-07-01 20:24:47 -03001410 ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
1411 ctrl->entity->id, chain->dev->intfnum,
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001412 ctrl->info.selector,
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001413 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001414 ctrl->info.size);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001415 if (ret < 0)
1416 return ret;
1417 }
1418
Laurent Pinchartb1accfa2008-09-27 20:54:02 -03001419 ctrl->loaded = 1;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001420 }
1421
Laurent Pincharte54532e2010-01-23 07:07:53 -03001422 /* Backup the current value in case we need to rollback later. */
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001423 if (!ctrl->dirty) {
1424 memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
1425 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001426 ctrl->info.size);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001427 }
1428
Laurent Pinchart97683522008-12-16 06:46:32 -03001429 mapping->set(mapping, value,
1430 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001431
1432 ctrl->dirty = 1;
1433 ctrl->modified = 1;
1434 return 0;
1435}
1436
1437/* --------------------------------------------------------------------------
1438 * Dynamic controls
1439 */
1440
Laurent Pinchartb5977a52010-10-01 15:39:49 -03001441static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
1442 const struct uvc_control *ctrl, struct uvc_control_info *info)
1443{
1444 struct uvc_ctrl_fixup {
1445 struct usb_device_id id;
1446 u8 entity;
1447 u8 selector;
1448 u8 flags;
1449 };
1450
1451 static const struct uvc_ctrl_fixup fixups[] = {
1452 { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001453 UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
1454 UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
1455 UVC_CTRL_FLAG_AUTO_UPDATE },
Laurent Pinchartb5977a52010-10-01 15:39:49 -03001456 { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001457 UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
1458 UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
1459 UVC_CTRL_FLAG_AUTO_UPDATE },
Laurent Pinchartb5977a52010-10-01 15:39:49 -03001460 { { USB_DEVICE(0x046d, 0x0994) }, 9, 1,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001461 UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
1462 UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
1463 UVC_CTRL_FLAG_AUTO_UPDATE },
Laurent Pinchartb5977a52010-10-01 15:39:49 -03001464 };
1465
1466 unsigned int i;
1467
1468 for (i = 0; i < ARRAY_SIZE(fixups); ++i) {
1469 if (!usb_match_one_id(dev->intf, &fixups[i].id))
1470 continue;
1471
1472 if (fixups[i].entity == ctrl->entity->id &&
1473 fixups[i].selector == info->selector) {
1474 info->flags = fixups[i].flags;
1475 return;
1476 }
1477 }
1478}
1479
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001480/*
1481 * Query control information (size and flags) for XU controls.
1482 */
1483static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
1484 const struct uvc_control *ctrl, struct uvc_control_info *info)
1485{
1486 u8 *data;
1487 int ret;
1488
1489 data = kmalloc(2, GFP_KERNEL);
1490 if (data == NULL)
1491 return -ENOMEM;
1492
1493 memcpy(info->entity, ctrl->entity->extension.guidExtensionCode,
1494 sizeof(info->entity));
1495 info->index = ctrl->index;
1496 info->selector = ctrl->index + 1;
1497
1498 /* Query and verify the control length (GET_LEN) */
1499 ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum,
1500 info->selector, data, 2);
1501 if (ret < 0) {
1502 uvc_trace(UVC_TRACE_CONTROL,
1503 "GET_LEN failed on control %pUl/%u (%d).\n",
1504 info->entity, info->selector, ret);
1505 goto done;
1506 }
1507
1508 info->size = le16_to_cpup((__le16 *)data);
1509
1510 /* Query the control information (GET_INFO) */
1511 ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
1512 info->selector, data, 1);
1513 if (ret < 0) {
1514 uvc_trace(UVC_TRACE_CONTROL,
1515 "GET_INFO failed on control %pUl/%u (%d).\n",
1516 info->entity, info->selector, ret);
1517 goto done;
1518 }
1519
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001520 info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
1521 | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF
1522 | (data[0] & UVC_CONTROL_CAP_GET ?
1523 UVC_CTRL_FLAG_GET_CUR : 0)
1524 | (data[0] & UVC_CONTROL_CAP_SET ?
1525 UVC_CTRL_FLAG_SET_CUR : 0)
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001526 | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001527 UVC_CTRL_FLAG_AUTO_UPDATE : 0);
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001528
Laurent Pinchartb5977a52010-10-01 15:39:49 -03001529 uvc_ctrl_fixup_xu_info(dev, ctrl, info);
1530
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001531 uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
1532 "flags { get %u set %u auto %u }.\n",
1533 info->entity, info->selector, info->size,
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001534 (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0,
1535 (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0,
1536 (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0);
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001537
1538done:
1539 kfree(data);
1540 return ret;
1541}
1542
1543static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
1544 const struct uvc_control_info *info);
1545
1546static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev,
1547 struct uvc_control *ctrl)
1548{
1549 struct uvc_control_info info;
1550 int ret;
1551
1552 if (ctrl->initialized)
1553 return 0;
1554
1555 ret = uvc_ctrl_fill_xu_info(dev, ctrl, &info);
1556 if (ret < 0)
1557 return ret;
1558
1559 ret = uvc_ctrl_add_info(dev, ctrl, &info);
1560 if (ret < 0)
1561 uvc_trace(UVC_TRACE_CONTROL, "Failed to initialize control "
1562 "%pUl/%u on device %s entity %u\n", info.entity,
1563 info.selector, dev->udev->devpath, ctrl->entity->id);
1564
1565 return ret;
1566}
1567
Laurent Pinchart8e113592009-07-01 20:24:47 -03001568int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
Martin Rublife78d182010-10-02 19:10:16 -03001569 struct uvc_xu_control_query *xqry)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001570{
1571 struct uvc_entity *entity;
Martin Rublife78d182010-10-02 19:10:16 -03001572 struct uvc_control *ctrl;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001573 unsigned int i, found = 0;
Martin Rublife78d182010-10-02 19:10:16 -03001574 __u32 reqflags;
1575 __u16 size;
1576 __u8 *data = NULL;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001577 int ret;
1578
1579 /* Find the extension unit. */
Laurent Pinchart6241d8c2009-11-25 12:00:22 -03001580 list_for_each_entry(entity, &chain->entities, chain) {
1581 if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT &&
Martin Rublife78d182010-10-02 19:10:16 -03001582 entity->id == xqry->unit)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001583 break;
1584 }
1585
Martin Rublife78d182010-10-02 19:10:16 -03001586 if (entity->id != xqry->unit) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001587 uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n",
Martin Rublife78d182010-10-02 19:10:16 -03001588 xqry->unit);
1589 return -ENOENT;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001590 }
1591
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001592 /* Find the control and perform delayed initialization if needed. */
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001593 for (i = 0; i < entity->ncontrols; ++i) {
1594 ctrl = &entity->controls[i];
Martin Rublife78d182010-10-02 19:10:16 -03001595 if (ctrl->index == xqry->selector - 1) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001596 found = 1;
1597 break;
1598 }
1599 }
1600
1601 if (!found) {
Laurent Pinchart36bd8832010-01-19 09:06:22 -03001602 uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n",
Martin Rublife78d182010-10-02 19:10:16 -03001603 entity->extension.guidExtensionCode, xqry->selector);
1604 return -ENOENT;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001605 }
1606
Laurent Pinchart8e113592009-07-01 20:24:47 -03001607 if (mutex_lock_interruptible(&chain->ctrl_mutex))
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001608 return -ERESTARTSYS;
1609
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001610 ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl);
1611 if (ret < 0) {
1612 ret = -ENOENT;
1613 goto done;
1614 }
1615
Martin Rublife78d182010-10-02 19:10:16 -03001616 /* Validate the required buffer size and flags for the request */
1617 reqflags = 0;
1618 size = ctrl->info.size;
1619
1620 switch (xqry->query) {
1621 case UVC_GET_CUR:
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001622 reqflags = UVC_CTRL_FLAG_GET_CUR;
Martin Rublife78d182010-10-02 19:10:16 -03001623 break;
1624 case UVC_GET_MIN:
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001625 reqflags = UVC_CTRL_FLAG_GET_MIN;
Martin Rublife78d182010-10-02 19:10:16 -03001626 break;
1627 case UVC_GET_MAX:
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001628 reqflags = UVC_CTRL_FLAG_GET_MAX;
Martin Rublife78d182010-10-02 19:10:16 -03001629 break;
1630 case UVC_GET_DEF:
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001631 reqflags = UVC_CTRL_FLAG_GET_DEF;
Martin Rublife78d182010-10-02 19:10:16 -03001632 break;
1633 case UVC_GET_RES:
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001634 reqflags = UVC_CTRL_FLAG_GET_RES;
Martin Rublife78d182010-10-02 19:10:16 -03001635 break;
1636 case UVC_SET_CUR:
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001637 reqflags = UVC_CTRL_FLAG_SET_CUR;
Martin Rublife78d182010-10-02 19:10:16 -03001638 break;
1639 case UVC_GET_LEN:
1640 size = 2;
1641 break;
1642 case UVC_GET_INFO:
1643 size = 1;
1644 break;
1645 default:
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001646 ret = -EINVAL;
1647 goto done;
1648 }
1649
Martin Rublife78d182010-10-02 19:10:16 -03001650 if (size != xqry->size) {
1651 ret = -ENOBUFS;
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001652 goto done;
1653 }
1654
Martin Rublife78d182010-10-02 19:10:16 -03001655 if (reqflags && !(ctrl->info.flags & reqflags)) {
1656 ret = -EBADRQC;
1657 goto done;
1658 }
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001659
Martin Rublife78d182010-10-02 19:10:16 -03001660 data = kmalloc(size, GFP_KERNEL);
1661 if (data == NULL) {
1662 ret = -ENOMEM;
1663 goto done;
1664 }
1665
1666 if (xqry->query == UVC_SET_CUR &&
1667 copy_from_user(data, xqry->data, size)) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001668 ret = -EFAULT;
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001669 goto done;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001670 }
1671
Martin Rublife78d182010-10-02 19:10:16 -03001672 ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit,
1673 chain->dev->intfnum, xqry->selector, data, size);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001674 if (ret < 0)
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001675 goto done;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001676
Martin Rublife78d182010-10-02 19:10:16 -03001677 if (xqry->query != UVC_SET_CUR &&
1678 copy_to_user(xqry->data, data, size))
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001679 ret = -EFAULT;
Laurent Pinchart27a61c12010-10-02 09:04:53 -03001680done:
Martin Rublife78d182010-10-02 19:10:16 -03001681 kfree(data);
Laurent Pinchart8e113592009-07-01 20:24:47 -03001682 mutex_unlock(&chain->ctrl_mutex);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001683 return ret;
1684}
1685
1686/* --------------------------------------------------------------------------
1687 * Suspend/resume
1688 */
1689
1690/*
1691 * Restore control values after resume, skipping controls that haven't been
1692 * changed.
1693 *
1694 * TODO
1695 * - Don't restore modified controls that are back to their default value.
1696 * - Handle restore order (Auto-Exposure Mode should be restored before
1697 * Exposure Time).
1698 */
1699int uvc_ctrl_resume_device(struct uvc_device *dev)
1700{
1701 struct uvc_control *ctrl;
1702 struct uvc_entity *entity;
1703 unsigned int i;
1704 int ret;
1705
1706 /* Walk the entities list and restore controls when possible. */
1707 list_for_each_entry(entity, &dev->entities, list) {
1708
1709 for (i = 0; i < entity->ncontrols; ++i) {
1710 ctrl = &entity->controls[i];
1711
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001712 if (!ctrl->initialized || !ctrl->modified ||
Laurent Pinchart9eb30d22010-11-21 17:08:16 -03001713 (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001714 continue;
1715
Laurent Pinchart36bd8832010-01-19 09:06:22 -03001716 printk(KERN_INFO "restoring control %pUl/%u/%u\n",
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001717 ctrl->info.entity, ctrl->info.index,
1718 ctrl->info.selector);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001719 ctrl->dirty = 1;
1720 }
1721
1722 ret = uvc_ctrl_commit_entity(dev, entity, 0);
1723 if (ret < 0)
1724 return ret;
1725 }
1726
1727 return 0;
1728}
1729
1730/* --------------------------------------------------------------------------
1731 * Control and mapping handling
1732 */
1733
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001734/*
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001735 * Add control information to a given control.
1736 */
1737static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
1738 const struct uvc_control_info *info)
1739{
1740 int ret = 0;
1741
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001742 memcpy(&ctrl->info, info, sizeof(*info));
1743 INIT_LIST_HEAD(&ctrl->info.mappings);
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001744
1745 /* Allocate an array to save control values (cur, def, max, etc.) */
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001746 ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1,
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001747 GFP_KERNEL);
1748 if (ctrl->uvc_data == NULL) {
1749 ret = -ENOMEM;
1750 goto done;
1751 }
1752
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001753 ctrl->initialized = 1;
1754
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001755 uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001756 "entity %u\n", ctrl->info.entity, ctrl->info.selector,
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001757 dev->udev->devpath, ctrl->entity->id);
1758
1759done:
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001760 if (ret < 0)
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001761 kfree(ctrl->uvc_data);
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001762 return ret;
1763}
1764
1765/*
1766 * Add a control mapping to a given control.
1767 */
1768static int __uvc_ctrl_add_mapping(struct uvc_device *dev,
1769 struct uvc_control *ctrl, const struct uvc_control_mapping *mapping)
1770{
1771 struct uvc_control_mapping *map;
1772 unsigned int size;
1773
1774 /* Most mappings come from static kernel data and need to be duplicated.
1775 * Mappings that come from userspace will be unnecessarily duplicated,
1776 * this could be optimized.
1777 */
1778 map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL);
1779 if (map == NULL)
1780 return -ENOMEM;
1781
Hans de Goedeb4012002012-04-08 12:59:51 -03001782 INIT_LIST_HEAD(&map->ev_subs);
1783
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001784 size = sizeof(*mapping->menu_info) * mapping->menu_count;
1785 map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL);
1786 if (map->menu_info == NULL) {
1787 kfree(map);
1788 return -ENOMEM;
1789 }
1790
1791 if (map->get == NULL)
1792 map->get = uvc_get_le_value;
1793 if (map->set == NULL)
1794 map->set = uvc_set_le_value;
1795
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001796 map->ctrl = &ctrl->info;
1797 list_add_tail(&map->list, &ctrl->info.mappings);
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001798 uvc_trace(UVC_TRACE_CONTROL,
1799 "Adding mapping '%s' to control %pUl/%u.\n",
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001800 map->name, ctrl->info.entity, ctrl->info.selector);
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001801
1802 return 0;
1803}
1804
1805int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
1806 const struct uvc_control_mapping *mapping)
1807{
1808 struct uvc_device *dev = chain->dev;
1809 struct uvc_control_mapping *map;
1810 struct uvc_entity *entity;
1811 struct uvc_control *ctrl;
1812 int found = 0;
Martin Rubli8fb91b32010-09-08 04:15:23 -03001813 int ret;
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001814
1815 if (mapping->id & ~V4L2_CTRL_ID_MASK) {
1816 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control "
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001817 "id 0x%08x is invalid.\n", mapping->name,
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001818 mapping->id);
1819 return -EINVAL;
1820 }
1821
Stephan Lachowskyc0c5e712011-05-31 19:24:21 -03001822 /* Search for the matching (GUID/CS) control on the current chain */
1823 list_for_each_entry(entity, &chain->entities, chain) {
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001824 unsigned int i;
1825
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001826 if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT ||
1827 !uvc_entity_match_guid(entity, mapping->entity))
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001828 continue;
1829
1830 for (i = 0; i < entity->ncontrols; ++i) {
1831 ctrl = &entity->controls[i];
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001832 if (ctrl->index == mapping->selector - 1) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001833 found = 1;
1834 break;
1835 }
1836 }
1837
1838 if (found)
1839 break;
1840 }
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001841 if (!found)
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001842 return -ENOENT;
Laurent Pinchartb30ece52010-06-18 11:31:24 -03001843
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001844 if (mutex_lock_interruptible(&chain->ctrl_mutex))
1845 return -ERESTARTSYS;
Laurent Pinchartb30ece52010-06-18 11:31:24 -03001846
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001847 /* Perform delayed initialization of XU controls */
1848 ret = uvc_ctrl_init_xu_ctrl(dev, ctrl);
1849 if (ret < 0) {
1850 ret = -ENOENT;
1851 goto done;
1852 }
1853
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001854 list_for_each_entry(map, &ctrl->info.mappings, list) {
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001855 if (mapping->id == map->id) {
1856 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "
1857 "control id 0x%08x already exists.\n",
1858 mapping->name, mapping->id);
1859 ret = -EEXIST;
Laurent Pinchartb30ece52010-06-18 11:31:24 -03001860 goto done;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001861 }
1862 }
1863
Martin Rubli8fb91b32010-09-08 04:15:23 -03001864 /* Prevent excess memory consumption */
1865 if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) {
1866 atomic_dec(&dev->nmappings);
1867 uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum "
1868 "mappings count (%u) exceeded.\n", mapping->name,
1869 UVC_MAX_CONTROL_MAPPINGS);
1870 ret = -ENOMEM;
1871 goto done;
1872 }
1873
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001874 ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping);
Martin Rubli8fb91b32010-09-08 04:15:23 -03001875 if (ret < 0)
1876 atomic_dec(&dev->nmappings);
1877
Laurent Pinchartb30ece52010-06-18 11:31:24 -03001878done:
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001879 mutex_unlock(&chain->ctrl_mutex);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001880 return ret;
1881}
1882
1883/*
Laurent Pinchartd732c442009-05-31 17:05:55 -03001884 * Prune an entity of its bogus controls using a blacklist. Bogus controls
1885 * are currently the ones that crash the camera or unconditionally return an
1886 * error when queried.
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001887 */
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001888static void uvc_ctrl_prune_entity(struct uvc_device *dev,
1889 struct uvc_entity *entity)
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001890{
Laurent Pinchartfa341682010-07-23 10:06:08 -03001891 struct uvc_ctrl_blacklist {
Laurent Pinchartd732c442009-05-31 17:05:55 -03001892 struct usb_device_id id;
1893 u8 index;
Laurent Pinchartfa341682010-07-23 10:06:08 -03001894 };
1895
1896 static const struct uvc_ctrl_blacklist processing_blacklist[] = {
Laurent Pinchart9405e3c2010-02-03 06:49:35 -03001897 { { USB_DEVICE(0x13d3, 0x509b) }, 9 }, /* Gain */
Laurent Pinchartd732c442009-05-31 17:05:55 -03001898 { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
1899 { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001900 };
Laurent Pinchartfa341682010-07-23 10:06:08 -03001901 static const struct uvc_ctrl_blacklist camera_blacklist[] = {
1902 { { USB_DEVICE(0x06f8, 0x3005) }, 9 }, /* Zoom, Absolute */
1903 };
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001904
Laurent Pinchartfa341682010-07-23 10:06:08 -03001905 const struct uvc_ctrl_blacklist *blacklist;
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001906 unsigned int size;
Laurent Pinchartfa341682010-07-23 10:06:08 -03001907 unsigned int count;
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001908 unsigned int i;
Laurent Pinchartfa341682010-07-23 10:06:08 -03001909 u8 *controls;
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001910
Laurent Pinchartfa341682010-07-23 10:06:08 -03001911 switch (UVC_ENTITY_TYPE(entity)) {
1912 case UVC_VC_PROCESSING_UNIT:
1913 blacklist = processing_blacklist;
1914 count = ARRAY_SIZE(processing_blacklist);
1915 controls = entity->processing.bmControls;
1916 size = entity->processing.bControlSize;
1917 break;
1918
1919 case UVC_ITT_CAMERA:
1920 blacklist = camera_blacklist;
1921 count = ARRAY_SIZE(camera_blacklist);
1922 controls = entity->camera.bmControls;
1923 size = entity->camera.bControlSize;
1924 break;
1925
1926 default:
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001927 return;
Laurent Pinchartfa341682010-07-23 10:06:08 -03001928 }
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001929
Laurent Pinchartfa341682010-07-23 10:06:08 -03001930 for (i = 0; i < count; ++i) {
Laurent Pinchart385097e2009-12-09 22:31:21 -03001931 if (!usb_match_one_id(dev->intf, &blacklist[i].id))
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001932 continue;
1933
Laurent Pinchartd732c442009-05-31 17:05:55 -03001934 if (blacklist[i].index >= 8 * size ||
1935 !uvc_test_bit(controls, blacklist[i].index))
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001936 continue;
1937
Laurent Pinchartd732c442009-05-31 17:05:55 -03001938 uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
1939 "removing it.\n", entity->id, blacklist[i].index);
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001940
Laurent Pinchartd732c442009-05-31 17:05:55 -03001941 uvc_clear_bit(controls, blacklist[i].index);
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03001942 }
1943}
1944
1945/*
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001946 * Add control information and hardcoded stock control mappings to the given
1947 * device.
1948 */
1949static void uvc_ctrl_init_ctrl(struct uvc_device *dev, struct uvc_control *ctrl)
1950{
1951 const struct uvc_control_info *info = uvc_ctrls;
1952 const struct uvc_control_info *iend = info + ARRAY_SIZE(uvc_ctrls);
1953 const struct uvc_control_mapping *mapping = uvc_ctrl_mappings;
1954 const struct uvc_control_mapping *mend =
1955 mapping + ARRAY_SIZE(uvc_ctrl_mappings);
1956
Laurent Pinchart52c58ad2010-09-29 16:03:03 -03001957 /* XU controls initialization requires querying the device for control
1958 * information. As some buggy UVC devices will crash when queried
1959 * repeatedly in a tight loop, delay XU controls initialization until
1960 * first use.
1961 */
1962 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT)
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001963 return;
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001964
1965 for (; info < iend; ++info) {
1966 if (uvc_entity_match_guid(ctrl->entity, info->entity) &&
1967 ctrl->index == info->index) {
1968 uvc_ctrl_add_info(dev, ctrl, info);
1969 break;
1970 }
1971 }
1972
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001973 if (!ctrl->initialized)
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001974 return;
1975
1976 for (; mapping < mend; ++mapping) {
1977 if (uvc_entity_match_guid(ctrl->entity, mapping->entity) &&
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03001978 ctrl->info.selector == mapping->selector)
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001979 __uvc_ctrl_add_mapping(dev, ctrl, mapping);
1980 }
1981}
1982
1983/*
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001984 * Initialize device controls.
1985 */
1986int uvc_ctrl_init_device(struct uvc_device *dev)
1987{
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001988 struct uvc_entity *entity;
1989 unsigned int i;
1990
1991 /* Walk the entities list and instantiate controls */
1992 list_for_each_entry(entity, &dev->entities, list) {
Laurent Pinchartba2fa992010-09-20 05:53:21 -03001993 struct uvc_control *ctrl;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001994 unsigned int bControlSize = 0, ncontrols = 0;
1995 __u8 *bmControls = NULL;
1996
Laurent Pinchartb482d922009-06-26 11:39:42 -03001997 if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03001998 bmControls = entity->extension.bmControls;
1999 bControlSize = entity->extension.bControlSize;
Laurent Pinchartb482d922009-06-26 11:39:42 -03002000 } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002001 bmControls = entity->processing.bmControls;
2002 bControlSize = entity->processing.bControlSize;
Laurent Pinchartb482d922009-06-26 11:39:42 -03002003 } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) {
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002004 bmControls = entity->camera.bmControls;
2005 bControlSize = entity->camera.bControlSize;
2006 }
2007
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002008 /* Remove bogus/blacklisted controls */
Laurent Pinchartd732c442009-05-31 17:05:55 -03002009 uvc_ctrl_prune_entity(dev, entity);
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03002010
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002011 /* Count supported controls and allocate the controls array */
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002012 for (i = 0; i < bControlSize; ++i)
2013 ncontrols += hweight8(bmControls[i]);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002014 if (ncontrols == 0)
2015 continue;
2016
Thomas Meyerd0d97482011-11-29 17:08:00 -03002017 entity->controls = kcalloc(ncontrols, sizeof(*ctrl),
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002018 GFP_KERNEL);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002019 if (entity->controls == NULL)
2020 return -ENOMEM;
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002021 entity->ncontrols = ncontrols;
2022
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002023 /* Initialize all supported controls */
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002024 ctrl = entity->controls;
2025 for (i = 0; i < bControlSize * 8; ++i) {
Laurent Pinchart2bdd29c2008-12-06 17:43:40 -03002026 if (uvc_test_bit(bmControls, i) == 0)
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002027 continue;
2028
2029 ctrl->entity = entity;
2030 ctrl->index = i;
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002031
2032 uvc_ctrl_init_ctrl(dev, ctrl);
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002033 ctrl++;
2034 }
2035 }
2036
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002037 return 0;
2038}
2039
2040/*
2041 * Cleanup device controls.
2042 */
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002043static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev,
2044 struct uvc_control *ctrl)
2045{
2046 struct uvc_control_mapping *mapping, *nm;
2047
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03002048 list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) {
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002049 list_del(&mapping->list);
2050 kfree(mapping->menu_info);
2051 kfree(mapping);
2052 }
2053}
2054
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002055void uvc_ctrl_cleanup_device(struct uvc_device *dev)
2056{
2057 struct uvc_entity *entity;
2058 unsigned int i;
2059
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002060 /* Free controls and control mappings for all entities. */
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002061 list_for_each_entry(entity, &dev->entities, list) {
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002062 for (i = 0; i < entity->ncontrols; ++i) {
2063 struct uvc_control *ctrl = &entity->controls[i];
2064
Laurent Pinchart071c8bb2010-09-29 16:00:08 -03002065 if (!ctrl->initialized)
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002066 continue;
2067
2068 uvc_ctrl_cleanup_mappings(dev, ctrl);
2069 kfree(ctrl->uvc_data);
Laurent Pinchartba2fa992010-09-20 05:53:21 -03002070 }
Laurent Pinchartc0efd232008-06-30 15:04:50 -03002071
2072 kfree(entity->controls);
2073 }
2074}