• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 failed 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 failed 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;
182     int rc;
183 
184     ctrl.id = qCtrl.id;
185     ctrl.ctrl_class = V4L2_CTRL_ID2CLASS(qCtrl.id);
186     ctrl.type = qCtrl.type;
187     ctrl.minimum = qCtrl.minimum;
188     ctrl.maximum = qCtrl.maximum;
189     ctrl.step = qCtrl.step;
190     ctrl.default_value = qCtrl.default_value;
191     ctrl.flags = qCtrl.flags;
192     ctrl.name = std::string(reinterpret_cast<char*>(qCtrl.name));
193 
194     if (qCtrl.type == V4L2_CTRL_TYPE_CTRL_CLASS) {
195         CAMERA_LOGD("%-14s\n", qCtrl.name);
196         control.push_back(ctrl);
197         return;
198     }
199 
200     rc = V4L2GetCtrl(fd, qCtrl.id, value);
201     if (rc != RC_ERROR) {
202         ctrl.value = value;
203         CAMERA_LOGD("%-14s : id=%08x, type=%d, minimum=%d, maximum=%d\n"
204             "\t\t value = %d, step=%d, default_value=%d\n",
205             qCtrl.name, qCtrl.id, qCtrl.type, qCtrl.minimum, qCtrl.maximum,
206             value, qCtrl.step, qCtrl.default_value);
207     }
208 }
209 
V4L2EnumExtControls(int fd,std::vector<DeviceControl> & control)210 void HosV4L2Control::V4L2EnumExtControls(int fd, std::vector<DeviceControl>& control)
211 {
212     struct v4l2_queryctrl qCtrl = {};
213     DeviceControl ctrl = {};
214     int rc;
215 
216     qCtrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
217     while (!ExtControl(fd, &qCtrl)) {
218         if (qCtrl.flags & V4L2_CTRL_FLAG_DISABLED) {
219             CAMERA_LOGD("V4L2ENUMExtControls flags  V4L2_CTRL_FLAG_DISABLED\n");
220             continue;
221         }
222 
223         V4L2SetValue(fd, control, ctrl, qCtrl);
224 
225         if (qCtrl.type == V4L2_CTRL_TYPE_MENU) {
226             struct v4l2_querymenu menu = {};
227             V4l2Menu menuTemp = {};
228 
229             for (menu.index = qCtrl.minimum;
230                     menu.index <= qCtrl.maximum;
231                     menu.index++) {
232                 menu.id = qCtrl.id;
233                 rc = ioctl(fd, VIDIOC_QUERYMENU, &menu);
234                 if (rc < 0) {
235                     continue;
236                 }
237                 CAMERA_LOGD("\t %d : %s\n", menu.index, menu.name);
238                 menuTemp.index = menu.index;
239                 menuTemp.id = menu.id;
240                 menuTemp.value = menu.value;
241                 menuTemp.name = std::string(reinterpret_cast<char*>(menu.name));
242                 ctrl.menu.push_back(menuTemp);
243             }
244         }
245 
246         control.push_back(ctrl);
247     }
248 }
249 
V4L2GetControl(int fd,std::vector<DeviceControl> & control,unsigned int id)250 int HosV4L2Control::V4L2GetControl(int fd, std::vector<DeviceControl>& control, unsigned int id)
251 {
252     struct v4l2_queryctrl queryCtrl = {};
253     DeviceControl ctrl = {};
254     int rc;
255 
256     queryCtrl.id = id;
257     rc = ioctl(fd, VIDIOC_QUERYCTRL, &queryCtrl);
258     if (rc < 0) {
259         CAMERA_LOGE("V4L2GetControl ioctl error rc %d\n", rc);
260         return RC_ERROR;
261     }
262 
263     if (queryCtrl.flags & V4L2_CTRL_FLAG_DISABLED) {
264         CAMERA_LOGD("V4L2ENUMExtControls flags  V4L2_CTRL_FLAG_DISABLED\n");
265         return RC_OK;
266     }
267 
268     V4L2SetValue(fd, control, ctrl, queryCtrl);
269 
270     if (queryCtrl.type == V4L2_CTRL_TYPE_MENU) {
271         struct v4l2_querymenu menu = {};
272         V4l2Menu mTemp = {};
273 
274         for (menu.index = queryCtrl.minimum;
275                 menu.index <= queryCtrl.maximum;
276                 menu.index++) {
277             menu.id = queryCtrl.id;
278             rc = ioctl(fd, VIDIOC_QUERYMENU, &menu);
279             if (rc < 0) {
280                 continue;
281             }
282             CAMERA_LOGD("\t %d : %s\n", menu.index, menu.name);
283             mTemp.index = menu.index;
284             mTemp.id = menu.id;
285             mTemp.value = menu.value;
286             mTemp.name = std::string(reinterpret_cast<char*>(menu.name));
287             ctrl.menu.push_back(mTemp);
288         }
289     }
290 
291     control.push_back(ctrl);
292 
293     return RC_OK;
294 }
295 
V4L2EnumControls(int fd,std::vector<DeviceControl> & control)296 void HosV4L2Control::V4L2EnumControls(int fd, std::vector<DeviceControl>& control)
297 {
298     int rc;
299     constexpr uint32_t max = V4L2_CID_PRIVATE_BASE + 100;
300 
301     for (unsigned int id = V4L2_CID_BASE; id < V4L2_CID_LASTP1; id++) {
302         rc = V4L2GetControl(fd, control, id);
303             if (rc == RC_ERROR)
304                 break;
305     }
306 
307     for (unsigned int id = V4L2_CID_PRIVATE_BASE; id < max; id++) {
308         rc = V4L2GetControl(fd, control, id);
309             if (rc == RC_ERROR)
310                 break;
311     }
312 }
313 
V4L2GetControls(int fd,std::vector<DeviceControl> & control)314 RetCode HosV4L2Control::V4L2GetControls(int fd, std::vector<DeviceControl>& control)
315 {
316     int rc;
317     struct v4l2_queryctrl qCtrl = {};
318 
319     std::vector<DeviceControl>().swap(control);
320 
321     if (fd < 0) {
322         CAMERA_LOGE("V4L2EnumExtControls fd error\n");
323         return RC_ERROR;
324     }
325 
326     qCtrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
327     rc = ExtControl(fd, &qCtrl);
328     if (rc < 0) {
329         CAMERA_LOGD("V4L2GetControls no support V4L2_CTRL_FLAG_NEXT_CTRL\n");
330         V4L2EnumControls(fd, control);
331     } else {
332         CAMERA_LOGD("V4L2GetControls support V4L2_CTRL_FLAG_NEXT_CTRL\n");
333         V4L2EnumExtControls(fd, control);
334     }
335 
336     return RC_OK;
337 }
338 } // namespace OHOS::Camera
339