1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "v4l2_control.h"
17
18 namespace OHOS::Camera {
HosV4L2Control()19 HosV4L2Control::HosV4L2Control() {}
~HosV4L2Control()20 HosV4L2Control::~HosV4L2Control() {}
21
V4L2SetCtrls(int fd,std::vector<DeviceControl> & control,const int numControls)22 RetCode HosV4L2Control::V4L2SetCtrls (int fd, std::vector<DeviceControl>& control, const int numControls)
23 {
24 int ret;
25 int count = 0;
26
27 if (numControls != control.size()) {
28 CAMERA_LOGE("HosV4L2Control::V4L2SetCtrls numControls != control.size()\n");
29 return RC_ERROR;
30 }
31
32 struct v4l2_ext_control cList[numControls];
33 for (auto itr = control.begin(); itr != control.end(); itr++) {
34 if (itr->flags & V4L2_CTRL_FLAG_READ_ONLY) {
35 continue;
36 }
37
38 if (count <= numControls) {
39 cList[count].value = itr->value;
40 count++;
41 }
42 auto itrNext = itr + 1;
43 if (itrNext == control.end() || itr->ctrl_class != itrNext->ctrl_class) {
44 struct v4l2_ext_controls ctrls = {};
45 ctrls.ctrl_class = itr->ctrl_class;
46 ctrls.count = count;
47 ctrls.controls = cList;
48 ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls);
49 if (ret) {
50 CAMERA_LOGE("HosV4L2Control::VIDIOC_S_EXT_CTRLS set faile try to VIDIOC_S_CTRL\n");
51 struct v4l2_control ctrl;
52
53 for (int i = 0; count > 0; i++, count--) {
54 ctrl.id = cList[i].id;
55 ctrl.value = cList[i].value;
56 ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
57 if (ret) {
58 CAMERA_LOGE("HosV4L2Control::V4L2SetCtrls VIDIOC_S_CTRL error i = %d\n", i);
59 continue;
60 }
61 }
62 }
63
64 count = 0;
65 }
66 }
67
68 return RC_OK;
69 }
70
V4L2GetCtrls(int fd,std::vector<DeviceControl> & control,const int numControls)71 RetCode HosV4L2Control::V4L2GetCtrls (int fd, std::vector<DeviceControl>& control, const int numControls)
72 {
73 int ret;
74 int count = 0;
75 auto iter = control.begin();
76
77 if (numControls != control.size()) {
78 CAMERA_LOGE("HosV4L2Control::V4L2GetCtrls numControls != control.size()\n");
79 return RC_ERROR;
80 }
81
82 struct v4l2_ext_control cList[numControls];
83 for (auto itr = control.begin(); itr != control.end(); itr++) {
84 if (itr->flags & V4L2_CTRL_FLAG_WRITE_ONLY) {
85 continue;
86 }
87 if (count <= numControls) {
88 cList[count].id = itr->id;
89 count++;
90 }
91
92 auto itrNext = itr + 1;
93 if (itrNext == control.end() || itr->ctrl_class != itrNext->ctrl_class) {
94 struct v4l2_ext_controls ctrls = {};
95 ctrls.ctrl_class = itr->ctrl_class;
96 ctrls.count = count;
97 ctrls.controls = cList;
98 ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, &ctrls);
99 if (ret) {
100 CAMERA_LOGE("HosV4L2Control::VIDIOC_G_EXT_CTRLS set faile try to VIDIOC_S_CTRL\n");
101 struct v4l2_control ctrl;
102 for (int i = 0; count > 0; i++, count--) {
103 ctrl.id = cList[i].id;
104 ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
105 if (ret) {
106 continue;
107 }
108
109 iter->value = ctrl.value;
110 iter++;
111 }
112 } else {
113 for (int i = 0; count > 0; i++, count--) {
114 iter->value = cList[i].value;
115 iter++;
116 }
117 }
118
119 count = 0;
120 }
121 }
122
123 return RC_OK;
124 }
125
V4L2GetCtrl(int fd,unsigned int id,int & value)126 RetCode HosV4L2Control::V4L2GetCtrl(int fd, unsigned int id, int& value)
127 {
128 int rc = 0;
129 struct v4l2_control ctrl;
130
131 ctrl.id = id;
132
133 rc = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
134 if (rc < 0) {
135 CAMERA_LOGE("HosV4L2Control::V4L2GetCtrl error rc = %d", rc);
136 return RC_ERROR;
137 }
138
139 value = ctrl.value;
140
141 return RC_OK;
142 }
143
V4L2SetCtrl(int fd,unsigned int id,int value)144 RetCode HosV4L2Control::V4L2SetCtrl(int fd, unsigned int id, int value)
145 {
146 struct v4l2_control ctrl;
147 int rc;
148
149 CAMERA_LOGD("HosV4L2Control::V4L2SetCtrl value = %d\n", value);
150
151 ctrl.id = id;
152 ctrl.value = value;
153
154 rc = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
155 if (rc < 0) {
156 CAMERA_LOGE("HosV4L2Control::V4L2SetCtrl error rc = %d", rc);
157 return RC_ERROR;
158 }
159
160 return RC_OK;
161 }
162
ExtControl(int fd,struct v4l2_queryctrl * ctrl)163 int HosV4L2Control::ExtControl(int fd, struct v4l2_queryctrl *ctrl)
164 {
165 int ret = 0;
166
167 if (ctrl == nullptr) {
168 CAMERA_LOGE("HosV4L2Control::ExtControl ctrl == nullptr");
169 return -1;
170 }
171
172 ctrl->id |= V4L2_CTRL_FLAG_NEXT_CTRL;
173 ret = ioctl(fd, VIDIOC_QUERYCTRL, ctrl);
174
175 return ret;
176 }
177
V4L2SetValue(int fd,std::vector<DeviceControl> & control,DeviceControl & ctrl,v4l2_queryctrl & qCtrl)178 void HosV4L2Control::V4L2SetValue(int fd, std::vector<DeviceControl>& control,
179 DeviceControl& ctrl, v4l2_queryctrl& qCtrl)
180 {
181 int value, rc;
182
183 ctrl.id = qCtrl.id;
184 ctrl.ctrl_class = V4L2_CTRL_ID2CLASS(qCtrl.id);
185 ctrl.type = qCtrl.type;
186 ctrl.minimum = qCtrl.minimum;
187 ctrl.maximum = qCtrl.maximum;
188 ctrl.step = qCtrl.step;
189 ctrl.default_value = qCtrl.default_value;
190 ctrl.flags = qCtrl.flags;
191 ctrl.name = std::string((char*)qCtrl.name);
192
193 if (qCtrl.type == V4L2_CTRL_TYPE_CTRL_CLASS) {
194 CAMERA_LOGD("%-14s\n", qCtrl.name);
195 control.push_back(ctrl);
196 return;
197 }
198
199 rc = V4L2GetCtrl(fd, qCtrl.id, value);
200 if (rc != RC_ERROR) {
201 ctrl.value = value;
202 CAMERA_LOGD("%-14s : id=%08x, type=%d, minimum=%d, maximum=%d\n"
203 "\t\t value = %d, step=%d, default_value=%d\n",
204 qCtrl.name, qCtrl.id, qCtrl.type, qCtrl.minimum, qCtrl.maximum,
205 value, qCtrl.step, qCtrl.default_value);
206 }
207 }
208
V4L2EnumExtControls(int fd,std::vector<DeviceControl> & control)209 void HosV4L2Control::V4L2EnumExtControls(int fd, std::vector<DeviceControl>& control)
210 {
211 struct v4l2_queryctrl qCtrl = {};
212 DeviceControl ctrl = {};
213 int rc;
214
215 qCtrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
216 while (!ExtControl(fd, &qCtrl)) {
217 if (qCtrl.flags & V4L2_CTRL_FLAG_DISABLED) {
218 CAMERA_LOGD("V4L2ENUMExtControls flags V4L2_CTRL_FLAG_DISABLED\n");
219 continue;
220 }
221
222 V4L2SetValue(fd, control, ctrl, qCtrl);
223
224 if (qCtrl.type == V4L2_CTRL_TYPE_MENU) {
225 struct v4l2_querymenu menu = {};
226 V4l2Menu menuTemp = {};
227
228 for (menu.index = qCtrl.minimum;
229 menu.index <= qCtrl.maximum;
230 menu.index++) {
231 menu.id = qCtrl.id;
232 rc = ioctl(fd, VIDIOC_QUERYMENU, &menu);
233 if (rc < 0) {
234 continue;
235 }
236 CAMERA_LOGD("\t %d : %s\n", menu.index, menu.name);
237 menuTemp.index = menu.index;
238 menuTemp.id = menu.id;
239 menuTemp.value = menu.value;
240 menuTemp.name = std::string((char*)menu.name);
241 ctrl.menu.push_back(menuTemp);
242 }
243 }
244
245 control.push_back(ctrl);
246 }
247 }
248
V4L2GetControl(int fd,std::vector<DeviceControl> & control,unsigned int id)249 int HosV4L2Control::V4L2GetControl(int fd, std::vector<DeviceControl>& control, unsigned int id)
250 {
251 struct v4l2_queryctrl queryCtrl = {};
252 DeviceControl ctrl = {};
253 int rc;
254
255 queryCtrl.id = id;
256 rc = ioctl(fd, VIDIOC_QUERYCTRL, &queryCtrl);
257 if (rc < 0) {
258 CAMERA_LOGE("V4L2GetControl ioctl error rc %d\n", rc);
259 return RC_ERROR;
260 }
261
262 if (queryCtrl.flags & V4L2_CTRL_FLAG_DISABLED) {
263 CAMERA_LOGD("V4L2ENUMExtControls flags V4L2_CTRL_FLAG_DISABLED\n");
264 return RC_OK;
265 }
266
267 V4L2SetValue(fd, control, ctrl, queryCtrl);
268
269 if (queryCtrl.type == V4L2_CTRL_TYPE_MENU) {
270 struct v4l2_querymenu menu = {};
271 V4l2Menu mTemp = {};
272
273 for (menu.index = queryCtrl.minimum;
274 menu.index <= queryCtrl.maximum;
275 menu.index++) {
276 menu.id = queryCtrl.id;
277 rc = ioctl(fd, VIDIOC_QUERYMENU, &menu);
278 if (rc < 0) {
279 continue;
280 }
281 CAMERA_LOGD("\t %d : %s\n", menu.index, menu.name);
282 mTemp.index = menu.index;
283 mTemp.id = menu.id;
284 mTemp.value = menu.value;
285 mTemp.name = std::string((char*)menu.name);
286 ctrl.menu.push_back(mTemp);
287 }
288 }
289
290 control.push_back(ctrl);
291
292 return RC_OK;
293 }
294
V4L2EnumControls(int fd,std::vector<DeviceControl> & control)295 void HosV4L2Control::V4L2EnumControls(int fd, std::vector<DeviceControl>& control)
296 {
297 int rc;
298 constexpr uint32_t max = V4L2_CID_PRIVATE_BASE + 100;
299
300 for (unsigned int id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; id++) {
301 rc = V4L2GetControl(fd, control, id);
302 if (rc == RC_ERROR)
303 break;
304 }
305
306 for (unsigned int id = V4L2_CID_PRIVATE_BASE; id < max; id++) {
307 rc = V4L2GetControl(fd, control, id);
308 if (rc == RC_ERROR)
309 break;
310 }
311 }
312
V4L2GetControls(int fd,std::vector<DeviceControl> & control)313 RetCode HosV4L2Control::V4L2GetControls(int fd, std::vector<DeviceControl>& control)
314 {
315 int rc;
316 struct v4l2_queryctrl qCtrl = {};
317
318 std::vector<DeviceControl>().swap(control);
319
320 if (fd < 0) {
321 CAMERA_LOGE("V4L2EnumExtControls fd error\n");
322 return RC_ERROR;
323 }
324
325 qCtrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
326 rc = ExtControl(fd, &qCtrl);
327 if (rc < 0) {
328 CAMERA_LOGD("V4L2GetControls no support V4L2_CTRL_FLAG_NEXT_CTRL\n");
329 V4L2EnumControls(fd, control);
330 } else {
331 CAMERA_LOGD("V4L2GetControls support V4L2_CTRL_FLAG_NEXT_CTRL\n");
332 V4L2EnumExtControls(fd, control);
333 }
334
335 return RC_OK;
336 }
337 } // namespace OHOS::Camera
338