• 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 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