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_dev.h"
17 #include <sys/prctl.h>
18 
19 namespace OHOS::Camera {
20 std::map<std::string, std::string> HosV4L2Dev::deviceMatch = HosV4L2Dev::CreateDevMap();
21 std::map<std::string, int> HosV4L2Dev::fdMatch = HosV4L2Dev::CreateFdMap();
22 std::mutex HosV4L2Dev::deviceFdLock_ = {};
23 
24 static constexpr uint32_t WATING_TIME = 1000 * 100;
25 
HosV4L2Dev()26 HosV4L2Dev::HosV4L2Dev() {}
~HosV4L2Dev()27 HosV4L2Dev::~HosV4L2Dev() {}
28 
GetCurrentFd(const std::string & cameraID)29 int HosV4L2Dev::GetCurrentFd(const std::string& cameraID)
30 {
31     auto itr = HosV4L2Dev::fdMatch.find(cameraID);
32     if (itr == HosV4L2Dev::fdMatch.end()) {
33         CAMERA_LOGE("error: GetCurrentFd no camera fd\n");
34         return RCERRORFD;
35     }
36 
37     return itr->second;
38 }
39 
start(const std::string & cameraID)40 RetCode HosV4L2Dev::start(const std::string& cameraID)
41 {
42     std::string devName;
43     int fd;
44 
45     CAMERA_LOGI("HosV4L2Dev::start enter %{public}s\n", cameraID.c_str());
46 
47     if (myFileFormat_ == nullptr) {
48         myFileFormat_ = std::make_shared<HosFileFormat>();
49         if (myFileFormat_ == nullptr) {
50             CAMERA_LOGE("error: InitMatch: myFileFormat_ make_shared is NULL\n");
51             return RC_ERROR;
52         }
53     }
54 
55     auto itr = HosV4L2Dev::deviceMatch.find(cameraID);
56     if (itr == HosV4L2Dev::deviceMatch.end()) {
57         CAMERA_LOGE("error:find V4L2 devname fail\n");
58         return RC_ERROR;
59     }
60     devName = itr->second;
61 
62     fd = myFileFormat_->V4L2OpenDevice(devName);
63     if (fd < 0) {
64         CAMERA_LOGE("error:myFileFormat_->V4L2OpenDevice fail fd == %{public}d\n", fd);
65         return RC_ERROR;
66     }
67 
68     bufferType_ = static_cast<enum v4l2_buf_type>(myFileFormat_->V4L2SearchBufType(fd));
69     if (bufferType_ == V4L2_BUF_TYPE_PRIVATE) {
70         CAMERA_LOGE("error:myFileFormat_->V4L2SearchBufType bufferType_ == 0\n");
71         return RC_ERROR;
72     }
73 
74     std::lock_guard<std::mutex> l(HosV4L2Dev::deviceFdLock_);
75     HosV4L2Dev::fdMatch.insert(std::make_pair(cameraID, fd));
76     CAMERA_LOGI("HosV4L2Dev::start out cameraID:%{public}s, devName:%{public}s\n", cameraID.c_str(), devName.c_str());
77     return RC_OK;
78 }
79 
stop(const std::string & cameraID)80 RetCode HosV4L2Dev::stop(const std::string& cameraID)
81 {
82     int fd;
83 
84     CAMERA_LOGI("HosV4L2Dev::stop enter %{public}s\n", cameraID.c_str());
85 
86     if (myFileFormat_ == nullptr) {
87         CAMERA_LOGE("HosV4L2Dev::stop myFileFormat_ == nullptr\n");
88         return RC_ERROR;
89     }
90 
91     auto itr = HosV4L2Dev::fdMatch.find(cameraID);
92     if (itr == HosV4L2Dev::fdMatch.end()) {
93         CAMERA_LOGE("HosV4L2Dev::stop GetCurrentFd error\n");
94         return RC_ERROR;
95     }
96 
97     fd = itr->second;
98     if (fd < 0) {
99         CAMERA_LOGE("HosV4L2Dev::stop fd error = %d\n", fd);
100         return RC_ERROR;
101     }
102 
103     myFileFormat_->V4L2CloseDevice(fd);
104 
105     std::lock_guard<std::mutex> l(HosV4L2Dev::deviceFdLock_);
106     HosV4L2Dev::fdMatch.erase(itr);
107     CAMERA_LOGI("HosV4L2Dev::stop out %{public}s\n", cameraID.c_str());
108     return RC_OK;
109 }
110 
Init(const std::vector<std::string> & cameraIDs)111 RetCode HosV4L2Dev::Init(const std::vector<std::string>& cameraIDs)
112 {
113     CAMERA_LOGI("HosV4L2Dev::Init enter\n");
114     auto myFileFormat = std::make_shared<HosFileFormat>();
115     if (myFileFormat == nullptr) {
116         CAMERA_LOGE("error: InitMatch: myFileFormat_ make_shared is NULL\n");
117         return RC_ERROR;
118     }
119 
120     myFileFormat->V4L2MatchDevice(cameraIDs);
121     CAMERA_LOGI("HosV4L2Dev::Init out\n");
122     return RC_OK;
123 }
124 
ReqBuffers(const std::string & cameraID,unsigned int buffCont)125 RetCode HosV4L2Dev::ReqBuffers(const std::string& cameraID, unsigned int buffCont)
126 {
127     int rc, fd;
128     CAMERA_LOGI("HosV4L2Dev::ReqBuffers enters %{public}s\n", cameraID.c_str());
129     fd = GetCurrentFd(cameraID);
130     if (fd < 0) {
131         CAMERA_LOGE("error: ReqBuffers: GetCurrentFd error\n");
132         return RC_ERROR;
133     }
134 
135     if (myBuffers_ == nullptr) {
136         myBuffers_ = HosV4L2Buffers::CreateHosV4L2Buffers(memoryType_, bufferType_);
137         if (myBuffers_ == nullptr) {
138             CAMERA_LOGE("error: Creatbuffer: myBuffers_ make_shared is NULL\n");
139             return RC_ERROR;
140         }
141     }
142 
143     rc = myBuffers_->V4L2ReqBuffers(fd, buffCont);
144     if (rc == RC_ERROR) {
145         CAMERA_LOGE("error: Creatbuffer: V4L2ReqBuffers error\n");
146         return RC_ERROR;
147     }
148     CAMERA_LOGI("HosV4L2Dev::ReqBuffers exit %{public}s\n", cameraID.c_str());
149     return RC_OK;
150 }
151 
CreatBuffer(const std::string & cameraID,const std::shared_ptr<FrameSpec> & frameSpec)152 RetCode HosV4L2Dev::CreatBuffer(const std::string& cameraID, const std::shared_ptr<FrameSpec>& frameSpec)
153 {
154     int rc, fd;
155     CAMERA_LOGI("HosV4L2Dev::CreatBuffer in %{public}s\n", cameraID.c_str());
156     fd = GetCurrentFd(cameraID);
157     if (fd < 0) {
158         CAMERA_LOGE("error: ReqBuffers: GetCurrentFd error\n");
159         return RC_ERROR;
160     }
161 
162     if (frameSpec == nullptr || myBuffers_ == nullptr) {
163         CAMERA_LOGE("error: Creatbuffer frameSpec or myBuffers_ is NULL\n");
164         return RC_ERROR;
165     }
166 
167     CAMERA_LOGI("Creatbuffer frameSpec->buffer index == %d\n", frameSpec->buffer_->GetIndex());
168 
169     rc = myBuffers_->V4L2AllocBuffer(fd, frameSpec);
170     if (rc == RC_ERROR) {
171         CAMERA_LOGE("error: Creatbuffer: V4L2AllocBuffer error\n");
172         return RC_ERROR;
173     }
174 
175     rc = myBuffers_->V4L2QueueBuffer(fd, frameSpec);
176     if (rc == RC_ERROR) {
177         CAMERA_LOGE("error: Creatbuffer: V4L2QueueBuffer error\n");
178         return RC_ERROR;
179     }
180     CAMERA_LOGI("HosV4L2Dev::CreatBuffer out %{public}s\n", cameraID.c_str());
181     return RC_OK;
182 }
183 
QueueBuffer(const std::string & cameraID,const std::shared_ptr<FrameSpec> & frameSpec)184 RetCode HosV4L2Dev::QueueBuffer(const std::string& cameraID, const std::shared_ptr<FrameSpec>& frameSpec)
185 {
186     int rc, fd;
187     CAMERA_LOGI("HosV4L2Dev::QueueBuffer in %{public}s\n", cameraID.c_str());
188     fd = GetCurrentFd(cameraID);
189     if (fd < 0) {
190         CAMERA_LOGE("QueueBuffer: GetCurrentFd error\n");
191         return RC_ERROR;
192     }
193 
194     if (frameSpec == nullptr || myBuffers_ == nullptr) {
195         CAMERA_LOGE(" QueueBuffer frameSpec or myBuffers_ is NULL\n");
196         return RC_ERROR;
197     }
198 
199     rc = myBuffers_->V4L2QueueBuffer(fd, frameSpec);
200     if (rc == RC_ERROR) {
201         CAMERA_LOGE("QueueBuffer: V4L2QueueBuffer error\n");
202         return RC_ERROR;
203     }
204     CAMERA_LOGI("HosV4L2Dev::QueueBuffer out %{public}s\n", cameraID.c_str());
205     return RC_OK;
206 }
207 
ReleaseBuffers(const std::string & cameraID)208 RetCode HosV4L2Dev::ReleaseBuffers(const std::string& cameraID)
209 {
210     int fd;
211     int rc = 0;
212     CAMERA_LOGI("HosV4L2Dev::ReleaseBuffers in %{public}s\n", cameraID.c_str());
213     if (myBuffers_ == nullptr) {
214         CAMERA_LOGE("ReleaseBuffers myBuffers_ is NULL\n");
215         return RC_ERROR;
216     }
217 
218     fd = GetCurrentFd(cameraID);
219     if (fd < 0) {
220         CAMERA_LOGE("ReleaseBuffers: GetCurrentFd error\n");
221         return RC_ERROR;
222     }
223 
224     rc = myBuffers_->V4L2ReleaseBuffers(fd);
225     if (rc == RC_ERROR) {
226         CAMERA_LOGE("ReleaseBuffers: V4L2ReleaseBuffers error\n");
227         return RC_ERROR;
228     }
229     CAMERA_LOGI("HosV4L2Dev::ReleaseBuffers out %{public}s\n", cameraID.c_str());
230     return RC_OK;
231 }
232 
dequeueBuffers()233 void HosV4L2Dev::dequeueBuffers()
234 {
235     int nfds;
236     int rc;
237     struct epoll_event events[MAXSTREAMCOUNT];
238     nfds = epoll_wait(epollFd_, events, MAXSTREAMCOUNT, -1);
239     CAMERA_LOGI("loopBuffers: epoll_wait rc = %{public}d streamNumber_ == %{public}d\n", nfds, streamNumber_);
240 
241     for (int n = 0; nfds > 0; ++n, --nfds) {
242         if ((events[n].events & EPOLLIN) && (events[n].data.fd != eventFd_)) {
243             CHECK_IF_PTR_NULL_RETURN_VOID(myBuffers_);
244             rc = myBuffers_->V4L2DequeueBuffer(events[n].data.fd);
245             if (rc == RC_ERROR) {
246                 continue;
247             }
248         } else {
249             CAMERA_LOGI("loopBuffers: epoll invalid events = 0x%{public}x or eventFd exit = %{public}d\n",
250                 events[n].events, (events[n].data.fd == eventFd_));
251             usleep(WATING_TIME);
252         }
253     }
254 }
255 
loopBuffers()256 void HosV4L2Dev::loopBuffers()
257 {
258     CAMERA_LOGI("!!! loopBuffers enter, streamNumber_=%{public}d\n", streamNumber_);
259     prctl(PR_SET_NAME, "v4l2_loopbuffer");
260 
261     while (true) {
262         {
263             std::lock_guard<std::mutex> l(streamLock_);
264             if (streamNumber_ <= 0) {
265                 break;
266             }
267         }
268         dequeueBuffers();
269     }
270     CAMERA_LOGI("!!! loopBuffers exit, streamNumber_=%{public}d\n", streamNumber_);
271 }
272 
CreateEpoll(int fd,const unsigned int streamNumber)273 RetCode HosV4L2Dev::CreateEpoll(int fd, const unsigned int streamNumber)
274 {
275     struct epoll_event epollevent = {};
276     CAMERA_LOGI("CreateEpoll enter, fd=%{public}d\n", fd);
277     if (streamNumber == 0) {
278         epollFd_ = epoll_create(MAXSTREAMCOUNT);
279         if (epollFd_ < 0) {
280             CAMERA_LOGE("V4L2 StartStream create_epoll failed\n");
281             return RC_ERROR;
282         }
283         epollevent.events = EPOLLIN;
284         epollevent.data.fd = fd;
285         int ret = epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &epollevent);
286         if (ret < 0) {
287             CAMERA_LOGE("add fd=%{public}d to epoll failed, ret=%{public}d, errno=%{public}d", fd, ret, errno);
288         }
289 
290         std::lock_guard<std::mutex> l(epollLock_);
291         epollEvent_.push_back(epollevent);
292 
293         eventFd_ = eventfd(0, 0);
294         epollevent = {};
295         epollevent.events = EPOLLIN;
296         epollevent.data.fd = eventFd_;
297         ret = epoll_ctl(epollFd_, EPOLL_CTL_ADD, eventFd_, &epollevent);
298         if (ret < 0) {
299             CAMERA_LOGE("add eventFd_=%{public}d to epoll failed, ret=%{public}d, errno=%{public}d",
300                 eventFd_, ret, errno);
301             return RC_ERROR;
302         }
303     } else {
304         epollevent.events = EPOLLIN;
305         epollevent.data.fd = fd;
306 
307         std::lock_guard<std::mutex> l(epollLock_);
308         epollEvent_.push_back(epollevent);
309 
310         int ret = epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &epollevent);
311         if (ret < 0) {
312             CAMERA_LOGE("add fd = %{public}d to epoll failed, ret=%{public}d, errno=%{public}d", fd, ret, errno);
313             return RC_ERROR;
314         }
315     }
316     CAMERA_LOGI("CreateEpoll out, fd=%{public}d\n", fd);
317     return RC_OK;
318 }
319 
EraseEpoll(int fd)320 void HosV4L2Dev::EraseEpoll(int fd)
321 {
322     CAMERA_LOGI("EraseEpoll enter, fd = %{public}d\n", fd);
323     auto itr = std::find_if(epollEvent_.begin(), epollEvent_.end(), [fd](const epoll_event& event) {
324         if (event.data.fd == fd) {
325             return true;
326         } else {
327             return false;
328         }
329     });
330     if (itr != epollEvent_.end()) {
331         struct epoll_event event = *itr;
332         int ret = epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, &event);
333         if (ret < 0) {
334             CAMERA_LOGE("del fd=%{public}d to epoll failed, ret=%{public}d, errno=%{public}d", fd, ret, errno);
335         }
336         std::lock_guard<std::mutex> l(epollLock_);
337         epollEvent_.erase(itr);
338     }
339     CAMERA_LOGI("EraseEpoll out, fd = %{public}d\n", fd);
340 }
341 
StartStream(const std::string & cameraID)342 RetCode HosV4L2Dev::StartStream(const std::string& cameraID)
343 {
344     int rc, fd;
345     CAMERA_LOGI("StartStream enter, cameraID = %{public}s\n", cameraID.c_str());
346     fd = GetCurrentFd(cameraID);
347     if (fd < 0) {
348         CAMERA_LOGE("error: ReqBuffers: GetCurrentFd error\n");
349         return RC_ERROR;
350     }
351 
352     if (myStreams_ == nullptr) {
353         myStreams_ = std::make_shared<HosV4L2Streams>(bufferType_);
354         if (myStreams_ == nullptr) {
355             CAMERA_LOGE("error: StartStream: myStreams_ make_shared is NULL\n");
356             return RC_ERROR;
357         }
358     }
359 
360     rc = myStreams_->V4L2StreamOn(fd);
361     if (rc == RC_ERROR) {
362         CAMERA_LOGE("error: StartStream: V4L2StreamOn error\n");
363         return RC_ERROR;
364     }
365 
366     rc = CreateEpoll(fd, streamNumber_);
367     if (rc == RC_ERROR) {
368         CAMERA_LOGE("StartStream: CreateEpoll error\n");
369         return RC_ERROR;
370     }
371 
372     if (streamNumber_ == 0) {
373         streamNumber_++;
374         CAMERA_LOGE("go start thread loopBuffers, streamNumber_=%{public}d\n", streamNumber_);
375         streamThread_ = new (std::nothrow) std::thread([this] {this->loopBuffers();});
376         if (streamThread_ == nullptr) {
377             CAMERA_LOGE("V4L2 StartStream start thread failed\n");
378             streamNumber_--;
379             return RC_ERROR;
380         }
381     }
382     CAMERA_LOGI("StartStream out, cameraID = %{public}s\n", cameraID.c_str());
383     return RC_OK;
384 }
385 
StopStream(const std::string & cameraID)386 RetCode HosV4L2Dev::StopStream(const std::string& cameraID)
387 {
388     CAMERA_LOGI("StartStream enter, cameraID = %{public}s\n", cameraID.c_str());
389     if (myStreams_ == nullptr || streamThread_ == nullptr) {
390         CAMERA_LOGE("error: StopStream: myStreams_ or streamThread_ is nullptr");
391         return RC_ERROR;
392     }
393 
394     int fd = GetCurrentFd(cameraID);
395     if (fd < 0) {
396         CAMERA_LOGE("error: StopStream: GetCurrentFd error\n");
397         return RC_ERROR;
398     }
399 
400     unsigned int streamNum = 0;
401     {
402         std::lock_guard<std::mutex> l(streamLock_);
403         streamNum = --streamNumber_;
404         CAMERA_LOGI("HosV4L2Dev::StopStream streamNumber_ = %{public}d\n", streamNumber_);
405     }
406 
407     if (streamNum == 0) {
408         CAMERA_LOGI("waiting loopBuffers stop\n");
409         uint64_t one = 1;
410         ssize_t ret = write(eventFd_, &one, sizeof(one));
411         if (ret != sizeof(one)) {
412             CAMERA_LOGE("HosV4L2Dev::StopStream write fd: %{public}d, failed, ret = %{public}zd\n", eventFd_, ret);
413         }
414         streamThread_->join();
415         close(eventFd_);
416         CAMERA_LOGI("waiting loopBuffers exit\n");
417     }
418 
419     if (myStreams_->V4L2StreamOff(fd) == RC_ERROR) {
420         CAMERA_LOGE("error: StopStream: V4L2StreamOn error\n");
421         return RC_ERROR;
422     }
423 
424     EraseEpoll(fd);
425     {
426         std::lock_guard<std::mutex> l(streamLock_);
427         if (streamNumber_ == 0) {
428             close(epollFd_);
429             delete streamThread_;
430             streamThread_ = nullptr;
431         }
432     }
433     CAMERA_LOGI("StartStream out, cameraID = %{public}s\n", cameraID.c_str());
434     return RC_OK;
435 }
436 
SetCtrlByCondition(int32_t fd,AdapterCmd command,const int * args,int & rc,std::shared_ptr<HosV4L2Control> myControl_)437 void SetCtrlByCondition(int32_t fd, AdapterCmd command, const int* args,
438     int &rc, std::shared_ptr<HosV4L2Control> myControl_)
439 {
440     switch (command) {
441         case CMD_EXPOSURE_MODE:
442             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_EXPOSURE_AUTO, *args);
443             break;
444         case CMD_AE_EXPOTIME:
445             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_EXPOSURE_ABSOLUTE, *args);
446             break;
447         case CMD_EXPOSURE_COMPENSATION:
448             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_EXPOSURE, *args);
449             break;
450         case CMD_AWB_MODE:
451             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, *args);
452             break;
453         case CMD_AE_LOCK:
454         case CMD_EXPOSURE_LOCK:
455         case CMD_FOCUS_LOCK:
456         case CMD_AWB_LOCK:
457             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_3A_LOCK, *args);
458             break;
459         case CMD_FOCUS_AUTO:
460             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_FOCUS_AUTO, *args);
461             break;
462         case CMD_FOCUS_ABSOLUTE:
463             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_FOCUS_ABSOLUTE, *args);
464             break;
465         case CMD_AUTO_FOCUS_START:
466             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_AUTO_FOCUS_START, *args);
467             break;
468         case CMD_AUTO_FOCUS_STOP:
469             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_AUTO_FOCUS_STOP, *args);
470             break;
471         case CMD_METER_MODE:
472             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_EXPOSURE_METERING, *args);
473             break;
474         case CMD_FLASH_MODE:
475             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_FLASH_LED_MODE, *args);
476             break;
477         case CMD_AE_EXPO:
478             rc = myControl_->V4L2SetCtrl(fd, V4L2_CID_BRIGHTNESS, *args);
479             break;
480         default:
481             break;
482     }
483 }
484 
UpdateSetting(const std::string & cameraID,AdapterCmd command,const int * args)485 RetCode HosV4L2Dev::UpdateSetting(const std::string& cameraID, AdapterCmd command, const int* args)
486 {
487     CAMERA_LOGI("UpdateSetting enter, cameraID = %{public}s\n", cameraID.c_str());
488     int32_t fd;
489     int rc = 0;
490     if (args == nullptr) {
491         CAMERA_LOGE("HosV4L2Dev::UpdateSetting: args is NULL\n");
492         return RC_ERROR;
493     }
494     if (myControl_ == nullptr) {
495         myControl_ = std::make_shared<HosV4L2Control>();
496         if (myControl_ == nullptr) {
497             CAMERA_LOGE("HosV4L2Dev::UpdateSetting: myControl_ make_shared is NULL\n");
498             return RC_ERROR;
499         }
500     }
501     fd = GetCurrentFd(cameraID);
502     if (fd < 0) {
503         CAMERA_LOGE("UpdateSetting: GetCurrentFd error\n");
504         return RC_ERROR;
505     }
506     SetCtrlByCondition(fd, command, args, rc, myControl_);
507     if (rc != RC_OK) {
508         return RC_ERROR;
509     }
510     CAMERA_LOGI("UpdateSetting out, cameraID = %{public}s\n", cameraID.c_str());
511     return RC_OK;
512 }
513 
QuerySetting(const std::string & cameraID,unsigned int command,int * args)514 RetCode HosV4L2Dev::QuerySetting(const std::string& cameraID, unsigned int command, int* args)
515 {
516     int32_t fd;
517     int32_t value = 0;
518     int rc = 0;
519     CAMERA_LOGI("QuerySetting enter, cameraID = %{public}s\n", cameraID.c_str());
520     if (args == nullptr) {
521         CAMERA_LOGE("HosV4L2Dev::QuerySetting: args is NULL\n");
522         return RC_ERROR;
523     }
524 
525     if (myControl_ == nullptr) {
526         myControl_ = std::make_shared<HosV4L2Control>();
527         if (myControl_ == nullptr) {
528             CAMERA_LOGE("HosV4L2Dev::QuerySetting: myControl_ make_shared is NULL\n");
529             return RC_ERROR;
530         }
531     }
532 
533     fd = GetCurrentFd(cameraID);
534     if (fd < 0) {
535         CAMERA_LOGE("QuerySetting: GetCurrentFd error\n");
536         return RC_ERROR;
537     }
538 
539     rc = myControl_->V4L2GetCtrl(fd, command, value);
540     if (rc != RC_OK) {
541         return RC_ERROR;
542     }
543 
544     *(reinterpret_cast<int32_t*>(args)) = value;
545     CAMERA_LOGI("QuerySetting out, cameraID = %{public}s\n", cameraID.c_str());
546     return RC_OK;
547 }
548 
GetNumberCtrls(const std::string & cameraID,std::vector<DeviceControl> & control)549 RetCode HosV4L2Dev::GetNumberCtrls(const std::string& cameraID, std::vector<DeviceControl>& control)
550 {
551     int32_t fd;
552     CAMERA_LOGI("GetNumberCtrls enter, cameraID = %{public}s\n", cameraID.c_str());
553     if (myControl_ == nullptr) {
554         myControl_ = std::make_shared<HosV4L2Control>();
555         if (myControl_ == nullptr) {
556             CAMERA_LOGE("HosV4L2Dev::GetNumberCtrls: myControl_ make_shared is NULL\n");
557             return RC_ERROR;
558         }
559     }
560 
561     fd = GetCurrentFd(cameraID);
562     if (fd < 0) {
563         CAMERA_LOGE("GetNumberCtrls: GetCurrentFd error\n");
564         return RC_ERROR;
565     }
566 
567     return myControl_->V4L2GetCtrls(fd, control, control.size());
568 }
569 
SetNumberCtrls(const std::string & cameraID,std::vector<DeviceControl> & control)570 RetCode HosV4L2Dev::SetNumberCtrls(const std::string& cameraID, std::vector<DeviceControl>& control)
571 {
572     int32_t fd;
573     CAMERA_LOGI("SetNumberCtrls enter, cameraID = %{public}s\n", cameraID.c_str());
574     if (myControl_ == nullptr) {
575         myControl_ = std::make_shared<HosV4L2Control>();
576         if (myControl_ == nullptr) {
577             CAMERA_LOGE("HosV4L2Dev::SetNumberCtrls: myControl_ make_shared is NULL\n");
578             return RC_ERROR;
579         }
580     }
581 
582     fd = GetCurrentFd(cameraID);
583     if (fd < 0) {
584         CAMERA_LOGE("SetNumberCtrls: GetCurrentFd error\n");
585         return RC_ERROR;
586     }
587 
588     return myControl_->V4L2SetCtrls(fd, control, control.size());
589 }
590 
GetControls(const std::string & cameraID,std::vector<DeviceControl> & control)591 RetCode HosV4L2Dev::GetControls(const std::string& cameraID, std::vector<DeviceControl>& control)
592 {
593     int fd, rc;
594     CAMERA_LOGI("GetControls enter, cameraID = %{public}s\n", cameraID.c_str());
595     if (myControl_ == nullptr) {
596         myControl_ = std::make_shared<HosV4L2Control>();
597         if (myControl_ == nullptr) {
598             CAMERA_LOGE("HosV4L2Dev::GetControls: myControl_ make_shared is NULL\n");
599             return RC_ERROR;
600         }
601     }
602 
603     fd = GetCurrentFd(cameraID);
604     if (fd < 0) {
605         CAMERA_LOGE("GetControls: GetCurrentFd error\n");
606         return RC_ERROR;
607     }
608 
609     rc = myControl_->V4L2GetControls(fd, control);
610     if (rc == RC_ERROR) {
611         CAMERA_LOGE("myControl_->V4L2GetControls fail\n");
612         return RC_ERROR;
613     }
614     CAMERA_LOGI("GetControls out, cameraID = %{public}s\n", cameraID.c_str());
615     return RC_OK;
616 }
617 
GetFmtDescs(const std::string & cameraID,std::vector<DeviceFormat> & fmtDesc)618 RetCode HosV4L2Dev::GetFmtDescs(const std::string& cameraID, std::vector<DeviceFormat>& fmtDesc)
619 {
620     int fd, rc;
621     CAMERA_LOGI("GetFmtDescs enter, cameraID = %{public}s\n", cameraID.c_str());
622     if (myFileFormat_ == nullptr) {
623         CAMERA_LOGE("GetFmtDescs: myFileFormat_ == nullptr\n");
624         return RC_ERROR;
625     }
626 
627     fd = GetCurrentFd(cameraID);
628     if (fd < 0) {
629         CAMERA_LOGE("GetFmtDescs: GetCurrentFd error\n");
630         return RC_ERROR;
631     }
632 
633     rc = myFileFormat_->V4L2GetFmtDescs(fd, fmtDesc);
634     if (rc == RC_ERROR) {
635         CAMERA_LOGE("myFileFormat_->V4L2GetFmtDescs fail\n");
636         return RC_ERROR;
637     }
638     CAMERA_LOGI("GetFmtDescs out, cameraID = %{public}s\n", cameraID.c_str());
639     return RC_OK;
640 }
641 
ConfigFps(const int fd,DeviceFormat & format,V4l2FmtCmd command)642 RetCode HosV4L2Dev::ConfigFps(const int fd, DeviceFormat& format, V4l2FmtCmd command)
643 {
644     RetCode rc = RC_OK;
645     CAMERA_LOGI("ConfigFps enter, fd = %{public}d\n", fd);
646     if (myStreams_ == nullptr) {
647         myStreams_ = std::make_shared<HosV4L2Streams>(bufferType_);
648         if (myStreams_ == nullptr) {
649             CAMERA_LOGE("error: ConfigSys: myStreams_ make_shared is nullptr\n");
650             return RC_ERROR;
651         }
652     }
653 
654     if (command == CMD_V4L2_SET_FPS) {
655         rc = myStreams_->V4L2StreamFPSSet(fd, format);
656     } else {
657         rc = myStreams_->V4L2StreamFPSGet(fd, format);
658     }
659 
660     if (rc != RC_OK) {
661         CAMERA_LOGE("ConfigFps CMD %d fail\n", command);
662     }
663     CAMERA_LOGI("ConfigFps out, fd = %{public}d\n", fd);
664     return rc;
665 }
666 
ConfigSys(const std::string & cameraID,V4l2FmtCmd command,DeviceFormat & format)667 RetCode HosV4L2Dev::ConfigSys(const std::string& cameraID, V4l2FmtCmd command, DeviceFormat& format)
668 {
669     int fd;
670     RetCode rc = RC_OK;
671     CAMERA_LOGI("ConfigSys enter, cameraID = %{public}s\n", cameraID.c_str());
672     if (myFileFormat_ == nullptr) {
673         CAMERA_LOGE("GetFmtDescs: ConfigSys == nullptr\n");
674         return RC_ERROR;
675     }
676 
677     fd = GetCurrentFd(cameraID);
678     if (fd < 0) {
679         CAMERA_LOGE("ConfigSys: GetCurrentFd error\n");
680         return RC_ERROR;
681     }
682 
683     switch (command) {
684         case CMD_V4L2_GET_FORMAT:
685             rc = myFileFormat_->V4L2GetFmt(fd, format);
686             break;
687 
688         case CMD_V4L2_SET_FORMAT:
689             rc = myFileFormat_->V4L2SetFmt(fd, format);
690             break;
691 
692         case CMD_V4L2_GET_CROPCAP:
693             rc = myFileFormat_->V4L2GetCropCap(fd, format);
694             break;
695 
696         case CMD_V4L2_GET_CROP:
697             rc = myFileFormat_->V4L2GetCrop(fd, format);
698             break;
699 
700         case CMD_V4L2_SET_CROP:
701             rc = myFileFormat_->V4L2SetCrop(fd, format);
702             break;
703 
704         case CMD_V4L2_SET_FPS:
705         case CMD_V4L2_GET_FPS:
706             rc = ConfigFps(fd, format, command);
707             break;
708 
709         default:
710             CAMERA_LOGE("HosV4L2Dev::ConfigSys unknown command\n");
711             break;
712     }
713 
714     if (rc != RC_OK) {
715         CAMERA_LOGE("ConfigSys CMD %d fail\n", command);
716     }
717 
718     return rc;
719 }
720 
SetV4L2DevCallback(BufCallback cb)721 RetCode HosV4L2Dev::SetV4L2DevCallback(BufCallback cb)
722 {
723     if (cb == nullptr) {
724         CAMERA_LOGE("HosV4L2Dev::SetCallback is null");
725         return RC_ERROR;
726     }
727     if (myBuffers_ == nullptr) {
728         CAMERA_LOGE("SetCallback myBuffers_ is NULL\n");
729         return RC_ERROR;
730     }
731 
732     myBuffers_->SetV4L2BuffersCallback(cb);
733 
734     return RC_OK;
735 }
Flush(const std::string & cameraID)736 RetCode HosV4L2Dev::Flush(const std::string& cameraID)
737 {
738     int rc, fd;
739     CAMERA_LOGI("Flush enter, cameraID = %{public}s\n", cameraID.c_str());
740     fd = GetCurrentFd(cameraID);
741     if (fd < 0) {
742         CAMERA_LOGE("HosV4L2Dev::Flush: GetCurrentFd error\n");
743         return RC_ERROR;
744     }
745 
746     if (myBuffers_ == nullptr) {
747         CAMERA_LOGE(" HosV4L2Dev::Flush myBuffers_ is NULL\n");
748         return RC_ERROR;
749     }
750 
751     rc = myBuffers_->Flush(fd);
752     if (rc == RC_ERROR) {
753         CAMERA_LOGE("HosV4L2Dev::Flush: error\n");
754         return RC_ERROR;
755     }
756     CAMERA_LOGI("Flush out, cameraID = %{public}s\n", cameraID.c_str());
757     return RC_OK;
758 }
759 
SetMemoryType(uint8_t & memType)760 void HosV4L2Dev::SetMemoryType(uint8_t &memType)
761 {
762     CAMERA_LOGI("func[HosV4L2Dev::%{public}s] memType[%{public}d]", __func__, memType);
763     if (memType == V4L2_MEMORY_MMAP) {
764         memoryType_ = V4L2_MEMORY_MMAP;
765     } else if (memType == V4L2_MEMORY_DMABUF) {
766         memoryType_ = V4L2_MEMORY_DMABUF;
767     }
768 }
769 } // namespace OHOS::Camera
770