1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18
19 #include <jni.h>
20 #include <fstream>
21 #include <iostream>
22 #include <utility>
23 #include <vector>
24
25 #include <glob.h>
26 #include <linux/usb/g_uvc.h>
27 #include <linux/usb/video.h>
28 #include <sys/epoll.h>
29 #include <sys/inotify.h>
30 #include <sys/mman.h>
31
32 #include <DeviceAsWebcamNative.h>
33 #include <SdkFrameProvider.h>
34 #include <UVCProvider.h>
35 #include <Utils.h>
36 #include <log/log.h>
37
38 constexpr int MAX_EVENTS = 10;
39 constexpr uint32_t NUM_BUFFERS_ALLOC = 4;
40 constexpr uint32_t USB_PAYLOAD_TRANSFER_SIZE = 3072;
41 constexpr char kDeviceGlobPattern[] = "/dev/video*";
42
43 // Taken from UVC UAPI. The kernel handles mapping these back to actual USB interfaces set up by the
44 // UVC gadget function.
45 constexpr uint32_t CONTROL_INTERFACE_IDX = 0;
46 constexpr uint32_t STREAMING_INTERFACE_IDX = 1;
47
48 constexpr uint32_t FRAME_INTERVAL_NUM = 10'000'000;
49
50 namespace android {
51 namespace webcam {
52
init()53 Status EpollW::init() {
54 int fd = epoll_create1(EPOLL_CLOEXEC);
55 if (fd < 0) {
56 ALOGE("%s epoll_create failed: %s", __FUNCTION__, strerror(errno));
57 return Status::ERROR;
58 }
59 mEpollFd.reset(fd);
60 return Status::OK;
61 }
62
add(int fd,uint32_t eventsIn)63 Status EpollW::add(int fd, uint32_t eventsIn) {
64 struct epoll_event event {};
65 event.data.fd = fd;
66 event.events = eventsIn;
67 if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &event) != 0) {
68 ALOGE("%s Epoll_ctl ADD failed %s \n", __FUNCTION__, strerror(errno));
69 return Status::ERROR;
70 }
71 return Status::OK;
72 }
73
modify(int fd,uint32_t newEvents)74 Status EpollW::modify(int fd, uint32_t newEvents) {
75 struct epoll_event event {};
76 event.data.fd = fd;
77 event.events = newEvents;
78 // TODO(b/267794640): Could we use CTL_MOD instead with UVC, reliably.
79 if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_DEL, fd, &event) != 0) {
80 ALOGE("%s Epoll_ctl DEL failed %s \n", __FUNCTION__, strerror(errno));
81 return Status::ERROR;
82 }
83 if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &event) != 0) {
84 ALOGE("%s Epoll_ctl ADD failed %s \n", __FUNCTION__, strerror(errno));
85 return Status::ERROR;
86 }
87 return Status::OK;
88 }
89
remove(int fd)90 Status EpollW::remove(int fd) {
91 struct epoll_event event {};
92 if (epoll_ctl(mEpollFd.get(), EPOLL_CTL_DEL, fd, &event) != 0) {
93 ALOGE("%s Epoll_ctl DEL failed %s \n", __FUNCTION__, strerror(errno));
94 return Status::ERROR;
95 }
96 return Status::OK;
97 }
98
waitForEvents()99 Events EpollW::waitForEvents() {
100 struct epoll_event events[MAX_EVENTS];
101 Events eventsVec;
102 int nFds = epoll_wait(mEpollFd.get(), events, MAX_EVENTS, /*msWait for 15 fps*/ 66);
103
104 if (nFds < 0) {
105 ALOGE("%s nFds was < 0 %s", __FUNCTION__, strerror(errno));
106 return eventsVec;
107 }
108 for (int i = 0; i < nFds; i++) {
109 eventsVec.emplace_back(events[i]);
110 }
111 return eventsVec;
112 }
113
openV4L2DeviceAndSubscribe(const std::string & videoNode)114 Status UVCProvider::UVCDevice::openV4L2DeviceAndSubscribe(const std::string& videoNode) {
115 struct v4l2_capability cap {};
116 int fd = open(videoNode.c_str(), O_RDWR);
117 if (fd < 0) {
118 ALOGE("%s Couldn't open V4L2 device %s err: %d fd %d, err str %s", __FUNCTION__,
119 videoNode.c_str(), errno, fd, strerror(errno));
120 return Status::ERROR;
121 }
122
123 ALOGI("%s Start to listen to device fd %d", __FUNCTION__, fd);
124 mUVCFd.reset(fd);
125
126 // Set up inotify to watch for V4L2 node removal before before setting up anything else.
127 int inotifyFd = inotify_init();
128 if (inotifyFd < 0) {
129 ALOGE("%s: Couldn't create an inotify fd. Error(%d): %s", __FUNCTION__,
130 errno, strerror(errno));
131 return Status::ERROR;
132 }
133 mINotifyFd.reset(inotifyFd);
134 // Watch for IN_ATTRIB which is returned on link/unlink among other things.
135 // As the videoNode is already linked, this should only be called during unlink.
136 // NOTE: We don't watch for IN_DELETE_SELF because it isn't triggered when the
137 // V4L2 node is removed.
138 int ret = inotify_add_watch(inotifyFd, videoNode.c_str(), IN_ATTRIB);
139 if (ret < 0) {
140 ALOGE("%s: Couldn't add watch for %s. Error(%d): %s", __FUNCTION__, videoNode.c_str(),
141 errno, strerror(errno));
142 return Status::ERROR;
143 }
144
145 memset(&cap, 0, sizeof(cap));
146
147 if (ioctl(mUVCFd.get(), VIDIOC_QUERYCAP, &cap) < 0) {
148 ALOGE("%s Couldn't get V4L2 device capabilities fd %d", __FUNCTION__, mUVCFd.get());
149 return Status::ERROR;
150 }
151
152 // Check that it is indeed a video output device
153 if (!(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
154 ALOGE("%s V4L2 device capabilities don't contain video output, caps: %zu", __FUNCTION__,
155 (size_t)cap.capabilities);
156 return Status::ERROR;
157 }
158
159 mUVCProperties = parseUvcProperties();
160
161 // Subscribe to events
162 struct v4l2_event_subscription subscription {};
163 std::vector<unsigned long> events = {UVC_EVENT_SETUP, UVC_EVENT_DATA, UVC_EVENT_STREAMON,
164 UVC_EVENT_STREAMOFF, UVC_EVENT_DISCONNECT};
165
166 for (auto event : events) {
167 subscription.type = event;
168 if (ioctl(mUVCFd.get(), VIDIOC_SUBSCRIBE_EVENT, &subscription) < 0) {
169 ALOGE("%s Couldn't subscribe to V4L2 event %lu error %s", __FUNCTION__, event,
170 strerror(errno));
171 return Status::ERROR;
172 }
173 }
174 return Status::OK;
175 }
176
isVideoOutputDevice(const char * dev)177 static bool isVideoOutputDevice(const char* dev) {
178 base::unique_fd fd(open(dev, O_RDWR));
179 if (fd.get() < 0) {
180 ALOGW("%s Opening V4L2 node %s failed %s", __FUNCTION__, dev, strerror(errno));
181 return false;
182 }
183
184 struct v4l2_capability capability {};
185 int ret = ioctl(fd.get(), VIDIOC_QUERYCAP, &capability);
186 if (ret < 0) {
187 ALOGV("%s v4l2 QUERYCAP %s failed %s", __FUNCTION__, dev, strerror(errno));
188 return false;
189 }
190
191 if (capability.device_caps & V4L2_CAP_VIDEO_OUTPUT) {
192 ALOGI("%s device %s supports VIDEO_OUTPUT", __FUNCTION__, dev);
193 return true;
194 }
195 ALOGV("%s device %s does not support VIDEO_OUTPUT", __FUNCTION__, dev);
196 return false;
197 }
198
getFrameIntervals(ConfigFrame * frame,ConfigFormat * format)199 void UVCProvider::UVCDevice::getFrameIntervals(ConfigFrame* frame, ConfigFormat* format) {
200 uint32_t index = 0;
201 while (true) {
202 struct v4l2_frmivalenum intervalDesc {};
203 intervalDesc.index = index;
204 intervalDesc.pixel_format = format->fcc;
205 intervalDesc.width = frame->width;
206 intervalDesc.height = frame->height;
207 int ret = ioctl(mUVCFd.get(), VIDIOC_ENUM_FRAMEINTERVALS, &intervalDesc);
208 if (ret != 0) {
209 return;
210 }
211 if (intervalDesc.index != index) {
212 ALOGE("%s V4L2 api returned different index %u from expected %u", __FUNCTION__,
213 intervalDesc.index, index);
214 }
215 uint32_t ival = 0;
216 switch (intervalDesc.type) {
217 case V4L2_FRMIVAL_TYPE_DISCRETE:
218 ival = (intervalDesc.discrete.numerator * FRAME_INTERVAL_NUM) /
219 intervalDesc.discrete.denominator;
220 break;
221 case V4L2_FRMIVAL_TYPE_STEPWISE:
222 // We only take the min here
223 ival = intervalDesc.stepwise.min.numerator / intervalDesc.stepwise.min.denominator;
224 break;
225 default:
226 ALOGE("%s frame type %u invalid", __FUNCTION__, intervalDesc.type);
227 break;
228 }
229 frame->intervals.emplace_back(ival);
230 index++;
231 }
232 }
233
getFormatFrames(ConfigFormat * format)234 void UVCProvider::UVCDevice::getFormatFrames(ConfigFormat* format) {
235 uint32_t index = 0;
236 while (true) {
237 struct v4l2_frmsizeenum frameDesc {};
238 frameDesc.index = index;
239 frameDesc.pixel_format = format->fcc;
240 ALOGI("Getting frames for format index %u", index);
241 int ret = ioctl(mUVCFd.get(), VIDIOC_ENUM_FRAMESIZES, &frameDesc);
242 if (ret != 0) {
243 return;
244 }
245 if (frameDesc.index != index) {
246 ALOGE("%s V4L2 api returned different index %u from expected %u", __FUNCTION__,
247 frameDesc.index, index);
248 }
249 ConfigFrame configFrame{};
250 configFrame.index = index;
251 switch (frameDesc.type) {
252 case V4L2_FRMSIZE_TYPE_DISCRETE:
253 configFrame.width = frameDesc.discrete.width;
254 configFrame.height = frameDesc.discrete.height;
255 break;
256 case V4L2_FRMSIZE_TYPE_STEPWISE:
257 // We only take the min here
258 configFrame.width = frameDesc.stepwise.min_width;
259 configFrame.height = frameDesc.stepwise.min_height;
260 break;
261 default:
262 ALOGE("%s frame type %u invalid", __FUNCTION__, frameDesc.type);
263 break;
264 }
265 getFrameIntervals(&configFrame, format);
266 format->frames.emplace_back(configFrame);
267 index++;
268 }
269 }
270
getFormats()271 std::vector<ConfigFormat> UVCProvider::UVCDevice::getFormats() {
272 std::vector<ConfigFormat> retVal;
273 for (uint32_t index = 0; true; ++index) {
274 ALOGI("Getting formats for index %u", index);
275 struct v4l2_fmtdesc formatDesc {};
276 formatDesc.index = index;
277 formatDesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
278 int ret = ioctl(mUVCFd.get(), VIDIOC_ENUM_FMT, &formatDesc);
279 if (ret != 0) {
280 return retVal;
281 }
282 if (formatDesc.index != index) {
283 ALOGE("%s V4L2 api returned different index %u from expected %u", __FUNCTION__,
284 formatDesc.index, index);
285 }
286
287 ConfigFormat configFormat{};
288 configFormat.formatIndex = formatDesc.index; // TODO: Double check with jchowdhary@
289 configFormat.fcc = formatDesc.pixelformat;
290 getFormatFrames(&configFormat);
291 retVal.emplace_back(configFormat);
292 }
293 }
294
parseUvcProperties()295 std::shared_ptr<UVCProperties> UVCProvider::UVCDevice::parseUvcProperties() {
296 std::shared_ptr<UVCProperties> ret = std::make_shared<UVCProperties>();
297 ret->videoNode = mVideoNode;
298 ret->streaming.formats = getFormats();
299 ret->controlInterfaceNumber = CONTROL_INTERFACE_IDX;
300 ret->streaming.interfaceNumber = STREAMING_INTERFACE_IDX;
301 return ret;
302 }
303
UVCDevice(std::weak_ptr<UVCProvider> parent,const std::unordered_set<std::string> & ignoredNodes)304 UVCProvider::UVCDevice::UVCDevice(std::weak_ptr<UVCProvider> parent,
305 const std::unordered_set<std::string>& ignoredNodes) {
306 mParent = std::move(parent);
307
308 // Initialize probe and commit controls with default values
309 FormatTriplet defaultFormatTriplet(/*formatIndex*/ 1, /*frameSizeIndex*/ 1,
310 /*frameInterval*/ 0);
311
312 mVideoNode = getVideoNode(ignoredNodes);
313
314 if (mVideoNode.empty()) {
315 ALOGE("%s: mVideoNode is empty, what ?", __FUNCTION__);
316 return;
317 }
318
319 if (openV4L2DeviceAndSubscribe(mVideoNode) != Status::OK) {
320 ALOGE("%s: Unable to open and subscribe to V4l2 node %s ?", __FUNCTION__,
321 mVideoNode.c_str());
322 return;
323 }
324 setStreamingControl(&mCommit, &defaultFormatTriplet);
325 mInited = true;
326 }
327
closeUVCFd()328 void UVCProvider::UVCDevice::closeUVCFd() {
329 mINotifyFd.reset(); // No need to inotify_rm_watch as closing the fd frees up resources
330
331 if (mUVCFd.get() >= 0) {
332 struct v4l2_event_subscription subscription {};
333 subscription.type = V4L2_EVENT_ALL;
334
335 if (ioctl(mUVCFd.get(), VIDIOC_UNSUBSCRIBE_EVENT, subscription) < 0) {
336 ALOGE("%s Couldn't unsubscribe from V4L2 events error %s", __FUNCTION__,
337 strerror(errno));
338 }
339 }
340 mUVCFd.reset();
341 }
342
getVideoNode(const std::unordered_set<std::string> & ignoredNodes)343 std::string UVCProvider::getVideoNode(const std::unordered_set<std::string>& ignoredNodes) {
344 std::string devNode;
345 ALOGV("%s start scanning for existing V4L2 OUTPUT devices", __FUNCTION__);
346 glob_t globRes;
347 glob(kDeviceGlobPattern, /*flags*/ 0, /*error_callback*/ nullptr, &globRes);
348 for (unsigned int i = 0; i < globRes.gl_pathc; ++i) {
349 auto& node = globRes.gl_pathv[i];
350 ALOGV("%s file: %s", __FUNCTION__, node);
351
352 // Skip if the node should be ignored
353 if (ignoredNodes.find(node) != ignoredNodes.end()) { continue; }
354
355 if (isVideoOutputDevice(node)) {
356 devNode = globRes.gl_pathv[i];
357 break;
358 }
359 }
360 globfree(&globRes);
361 return devNode;
362 }
363
isInited() const364 bool UVCProvider::UVCDevice::isInited() const {
365 return mInited;
366 }
367
processSetupControlEvent(const struct usb_ctrlrequest * control,struct uvc_request_data * resp)368 void UVCProvider::UVCDevice::processSetupControlEvent(const struct usb_ctrlrequest* control,
369 struct uvc_request_data* resp) {
370 // TODO(b/267794640): Support control requests
371 resp->data[0] = 0x3;
372 resp->length = control->wLength;
373 }
374
processSetupStreamingEvent(const struct usb_ctrlrequest * request,struct uvc_request_data * response)375 void UVCProvider::UVCDevice::processSetupStreamingEvent(const struct usb_ctrlrequest* request,
376 struct uvc_request_data* response) {
377 uint8_t requestType = request->bRequest;
378 uint8_t controlSelect = request->wValue >> 8;
379 if (controlSelect != UVC_VS_PROBE_CONTROL && controlSelect != UVC_VS_COMMIT_CONTROL) {
380 ALOGE("%s: control select %u is invalid", __FUNCTION__, controlSelect);
381 return;
382 }
383
384 struct uvc_streaming_control* ctrl =
385 reinterpret_cast<struct uvc_streaming_control*>(response->data);
386 response->length = sizeof(struct uvc_streaming_control);
387 FormatTriplet maxFormatTriplet(/*formatIndex*/ UINT8_MAX,
388 /*frameSizeIndex*/ UINT8_MAX,
389 /*frameInterval*/ UINT32_MAX);
390 FormatTriplet defaultFormatTriplet(/*formatIndex*/ 1, /*frameSizeIndex*/ 1,
391 /*frameInterval*/ 0);
392
393 switch (requestType) {
394 case UVC_SET_CUR:
395 mCurrentControlState = controlSelect;
396 // UVC 1.5 spec section 4.3.1
397 response->length = 48;
398 break;
399 case UVC_GET_CUR:
400 if (controlSelect == UVC_VS_PROBE_CONTROL) {
401 memcpy(ctrl, &mProbe, sizeof(struct uvc_streaming_control));
402 } else {
403 memcpy(ctrl, &mCommit, sizeof(struct uvc_streaming_control));
404 }
405 break;
406 case UVC_GET_MAX:
407 setStreamingControl(ctrl, &maxFormatTriplet);
408 break;
409 case UVC_GET_MIN:
410 case UVC_GET_DEF:
411 setStreamingControl(ctrl, &defaultFormatTriplet);
412 break;
413 case UVC_GET_RES:
414 memset(ctrl, 0, sizeof(struct uvc_streaming_control));
415 break;
416 case UVC_GET_LEN:
417 response->data[0] = 0x00;
418 // UVC 1.5 spec section 4.3.1
419 response->data[0] = 0x30;
420 response->length = 2;
421 break;
422 case UVC_GET_INFO:
423 // UVC 1.5 Spec Section 4.1.2 "Get Request"
424 response->data[0] = 0x3;
425 response->length = 1;
426 break;
427 default:
428 ALOGE("%s requestType %u not supported", __FUNCTION__, requestType);
429 break;
430 }
431 }
432
processSetupClassEvent(const struct usb_ctrlrequest * request,struct uvc_request_data * response)433 void UVCProvider::UVCDevice::processSetupClassEvent(const struct usb_ctrlrequest* request,
434 struct uvc_request_data* response) {
435 uint8_t interface = request->wIndex & 0xff;
436 ALOGV("%s: Interface %u", __FUNCTION__, interface);
437
438 if ((request->bRequestType & USB_RECIP_MASK) != USB_RECIP_INTERFACE) {
439 ALOGE("Invalid bRequestType byte %u", request->bRequestType);
440 return;
441 }
442
443 if (interface == mUVCProperties->controlInterfaceNumber) {
444 processSetupControlEvent(request, response);
445 } else if (interface == mUVCProperties->streaming.interfaceNumber) {
446 processSetupStreamingEvent(request, response);
447 }
448 }
449
processSetupEvent(const struct usb_ctrlrequest * request,struct uvc_request_data * response)450 void UVCProvider::UVCDevice::processSetupEvent(const struct usb_ctrlrequest* request,
451 struct uvc_request_data* response) {
452 uint8_t type = request->bRequestType;
453 uint8_t requestCode = request->bRequest;
454 uint16_t length = request->wLength;
455 uint16_t index = request->wIndex;
456 uint16_t value = request->wValue;
457 ALOGV("%s: type %u requestCode %u length %u index %u value %u", __FUNCTION__, type, requestCode,
458 length, index, value);
459 switch (type & USB_TYPE_MASK) {
460 case USB_TYPE_STANDARD:
461 ALOGW("USB_TYPE_STANDARD request not being handled");
462 break;
463 case USB_TYPE_CLASS:
464 processSetupClassEvent(request, response);
465 break;
466 default:
467 ALOGE("%s: Unknown request type %u", __FUNCTION__, type);
468 }
469 }
470
setStreamingControl(struct uvc_streaming_control * streamingControl,const FormatTriplet * req)471 void UVCProvider::UVCDevice::setStreamingControl(struct uvc_streaming_control* streamingControl,
472 const FormatTriplet* req) {
473 // frame and format index start from 1.
474 uint8_t chosenFormatIndex = req->formatIndex > mUVCProperties->streaming.formats.size()
475 ? mUVCProperties->streaming.formats.size()
476 : req->formatIndex;
477 if (chosenFormatIndex <= 0) {
478 return;
479 }
480 const ConfigFormat& chosenFormat = mUVCProperties->streaming.formats[chosenFormatIndex - 1];
481 uint8_t chosenFrameIndex = req->frameSizeIndex > chosenFormat.frames.size()
482 ? chosenFormat.frames.size()
483 : req->frameSizeIndex;
484 if (chosenFrameIndex <= 0) {
485 return;
486 }
487 ALOGV("%s: chosenFormatIndex %d chosenFrameIndex: %d", __FUNCTION__, chosenFormatIndex,
488 chosenFrameIndex);
489 const ConfigFrame& chosenFrame = chosenFormat.frames[chosenFrameIndex - 1];
490 uint32_t reqFrameInterval = req->frameInterval;
491 bool largerFound = false;
492 // Choose the first frame interval >= requested. Frame intervals are expected to be in
493 // ascending order.
494 for (auto frameInterval : chosenFrame.intervals) {
495 if (reqFrameInterval <= frameInterval) {
496 reqFrameInterval = frameInterval;
497 largerFound = true;
498 break;
499 }
500 }
501 if (!largerFound) {
502 reqFrameInterval = chosenFrame.intervals[chosenFrame.intervals.size() - 1];
503 }
504 memset(streamingControl, 0, sizeof(*streamingControl));
505
506 // TODO((b/267794640): Add documentation for magic numbers used here and elsewhere.
507 streamingControl->bmHint = 1;
508 streamingControl->bmFramingInfo = 3;
509 streamingControl->bPreferedVersion = 1;
510 streamingControl->bMaxVersion = 1;
511
512 streamingControl->bFormatIndex = chosenFormatIndex;
513 streamingControl->bFrameIndex = chosenFrameIndex;
514 streamingControl->dwFrameInterval = reqFrameInterval;
515 streamingControl->dwMaxPayloadTransferSize = USB_PAYLOAD_TRANSFER_SIZE;
516 switch (chosenFormat.fcc) {
517 case V4L2_PIX_FMT_YUYV:
518 case V4L2_PIX_FMT_MJPEG:
519 streamingControl->dwMaxVideoFrameSize = chosenFrame.width * chosenFrame.height * 2;
520 break;
521 default:
522 ALOGE("%s Video format is not YUYV or MJPEG ??", __FUNCTION__);
523 }
524 }
525
commitControls()526 void UVCProvider::UVCDevice::commitControls() {
527 const ConfigFormat& commitFormat = mUVCProperties->streaming.formats[mCommit.bFormatIndex - 1];
528 const ConfigFrame& commitFrame = commitFormat.frames[mCommit.bFrameIndex - 1];
529 mFps = FRAME_INTERVAL_NUM / mCommit.dwFrameInterval;
530
531 memset(&mV4l2Format, 0, sizeof(mV4l2Format));
532 mV4l2Format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
533 mV4l2Format.fmt.pix.width = commitFrame.width;
534 mV4l2Format.fmt.pix.height = commitFrame.height;
535 mV4l2Format.fmt.pix.pixelformat = commitFormat.fcc;
536 mV4l2Format.fmt.pix.field = V4L2_FIELD_ANY;
537 mV4l2Format.fmt.pix.sizeimage = mCommit.dwMaxVideoFrameSize;
538
539 // Call ioctl VIDIOC_S_FMT which may change the fields in mV4l2Format
540 if (ioctl(mUVCFd.get(), VIDIOC_S_FMT, &mV4l2Format) < 0) {
541 ALOGE("%s Unable to set pixel format with the uvc gadget driver: %s", __FUNCTION__,
542 strerror(errno));
543 return;
544 }
545 ALOGV("%s controls committed frame width %u, height %u, format %u, sizeimage %u"
546 " frame rate %u mjpeg fourcc %u",
547 __FUNCTION__, mV4l2Format.fmt.pix.width, mV4l2Format.fmt.pix.height,
548 mV4l2Format.fmt.pix.pixelformat, mV4l2Format.fmt.pix.sizeimage, mFps, V4L2_PIX_FMT_MJPEG);
549 }
550
processDataEvent(const struct uvc_request_data * data)551 void UVCProvider::UVCDevice::processDataEvent(const struct uvc_request_data* data) {
552 const struct uvc_streaming_control* controlReq =
553 reinterpret_cast<const struct uvc_streaming_control*>(&data->data);
554
555 FormatTriplet triplet(controlReq->bFormatIndex, controlReq->bFrameIndex,
556 controlReq->dwFrameInterval);
557
558 switch (mCurrentControlState) {
559 case UVC_VS_PROBE_CONTROL:
560 setStreamingControl(&mProbe, &triplet);
561 break;
562 case UVC_VS_COMMIT_CONTROL:
563 setStreamingControl(&mCommit, &triplet);
564 commitControls();
565 break;
566 default:
567 ALOGE("mCurrentControlState is UNDEFINED");
568 break;
569 }
570 }
571
mapBuffer(uint32_t i)572 std::shared_ptr<Buffer> UVCProvider::UVCDevice::mapBuffer(uint32_t i) {
573 struct v4l2_buffer buffer {};
574
575 buffer.index = i;
576 buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
577 buffer.memory = V4L2_MEMORY_MMAP;
578
579 if (ioctl(mUVCFd.get(), VIDIOC_QUERYBUF, &buffer) < 0) {
580 ALOGE("%s: Unable to query V4L2 buffer index %u from gadget driver: %s", __FUNCTION__, i,
581 strerror(errno));
582 return nullptr;
583 }
584
585 void* mem = mmap(/*addr*/ nullptr, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
586 mUVCFd.get(), buffer.m.offset);
587 if (mem == MAP_FAILED) {
588 ALOGE("%s: Unable to map V4L2 buffer index %u from gadget driver: %s", __FUNCTION__, i,
589 strerror(errno));
590 return nullptr;
591 }
592 ALOGV("%s: Allocated and mapped buffer at %p of size %u", __FUNCTION__, mem, buffer.length);
593 return std::make_shared<V4L2Buffer>(mem, &buffer);
594 }
595
allocateAndMapBuffers(std::shared_ptr<Buffer> * consumerBuffer,std::vector<std::shared_ptr<Buffer>> * producerBuffers)596 Status UVCProvider::UVCDevice::allocateAndMapBuffers(
597 std::shared_ptr<Buffer>* consumerBuffer,
598 std::vector<std::shared_ptr<Buffer>>* producerBuffers) {
599 if (consumerBuffer == nullptr || producerBuffers == nullptr) {
600 ALOGE("%s: ConsumerBuffer / producerBuffers are null", __FUNCTION__);
601 return Status::ERROR;
602 }
603 *consumerBuffer = nullptr;
604 producerBuffers->clear();
605 struct v4l2_requestbuffers requestBuffers {};
606
607 requestBuffers.count = NUM_BUFFERS_ALLOC;
608 requestBuffers.memory = V4L2_MEMORY_MMAP;
609 requestBuffers.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
610
611 // Request the driver to allocate buffers
612 if (ioctl(mUVCFd.get(), VIDIOC_REQBUFS, &requestBuffers) < 0) {
613 ALOGE("%s: Unable to request V4L2 buffers from gadget driver: %s", __FUNCTION__,
614 strerror(errno));
615 return Status::ERROR;
616 }
617
618 if (requestBuffers.count != NUM_BUFFERS_ALLOC) {
619 ALOGE("%s: Gadget driver could only allocate %u buffers instead of %u", __FUNCTION__,
620 requestBuffers.count, NUM_BUFFERS_ALLOC);
621 // TODO: We should probably be freeing buffers here
622 return Status::ERROR;
623 }
624
625 // First buffer is consumer buffer
626 *consumerBuffer = mapBuffer(0);
627 if (*consumerBuffer == nullptr) {
628 ALOGE("%s: Mapping consumer buffer failed", __FUNCTION__);
629 return Status::ERROR;
630 }
631
632 // The rest are producer buffers
633 for (uint32_t i = 1; i < NUM_BUFFERS_ALLOC; i++) {
634 std::shared_ptr<Buffer> buffer = mapBuffer(i);
635 if (buffer == nullptr) {
636 ALOGE("%s: Mapping producer buffer index %u failed", __FUNCTION__, i);
637 *consumerBuffer = nullptr;
638 producerBuffers->clear();
639 return Status::ERROR;
640 }
641 producerBuffers->push_back(buffer);
642 }
643 return Status::OK;
644 }
645
unmapBuffer(std::shared_ptr<Buffer> & buffer)646 Status UVCProvider::UVCDevice::unmapBuffer(std::shared_ptr<Buffer>& buffer) {
647 if (buffer->getMem() != nullptr) {
648 if (munmap(buffer->getMem(), buffer->getLength()) < 0) {
649 ALOGE("%s: munmap failed for buffer with pointer %p", __FUNCTION__, buffer->getMem());
650 return Status::ERROR;
651 }
652 }
653 return Status::OK;
654 }
655
destroyBuffers(std::shared_ptr<Buffer> & consumerBuffer,std::vector<std::shared_ptr<Buffer>> & producerBuffers)656 void UVCProvider::UVCDevice::destroyBuffers(std::shared_ptr<Buffer>& consumerBuffer,
657 std::vector<std::shared_ptr<Buffer>>& producerBuffers) {
658 if (unmapBuffer(consumerBuffer) != Status::OK) {
659 ALOGE("%s: Failed to unmap consumer buffer, continuing producer buffer cleanup anyway",
660 __FUNCTION__);
661 }
662 for (auto& buf : producerBuffers) {
663 if (unmapBuffer(buf) != Status::OK) {
664 ALOGE("%s: Failed to unmap producer buffer, continuing buffer cleanup anyway",
665 __FUNCTION__);
666 }
667 }
668 struct v4l2_requestbuffers zeroRequest {};
669 zeroRequest.count = 0;
670 zeroRequest.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
671 zeroRequest.memory = V4L2_MEMORY_MMAP;
672
673 if (ioctl(mUVCFd.get(), VIDIOC_REQBUFS, &zeroRequest) < 0) {
674 ALOGE("%s: request to free buffers from uvc gadget driver failed %s", __FUNCTION__,
675 strerror(errno));
676 }
677 }
678
getFrameAndQueueBufferToGadgetDriver(bool firstBuffer)679 Status UVCProvider::UVCDevice::getFrameAndQueueBufferToGadgetDriver(bool firstBuffer) {
680 // If first buffer, also call the STREAMON ioctl on uvc device
681 ALOGV("%s: E", __FUNCTION__);
682 if (firstBuffer) {
683 int type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
684 if (ioctl(mUVCFd.get(), VIDIOC_STREAMON, &type) < 0) {
685 ALOGE("%s: VIDIOC_STREAMON failed %s", __FUNCTION__, strerror(errno));
686 return Status::ERROR;
687 }
688 }
689 Buffer* buffer = mBufferManager->getFilledBufferAndSwap();
690 struct v4l2_buffer v4L2Buffer = *(static_cast<V4L2Buffer*>(buffer)->getV4L2Buffer());
691 ALOGV("%s: got buffer, queueing it with index %u", __FUNCTION__, v4L2Buffer.index);
692
693 if (ioctl(mUVCFd.get(), VIDIOC_QBUF, &v4L2Buffer) < 0) {
694 ALOGE("%s: VIDIOC_QBUF failed on gadget driver: %s", __FUNCTION__, strerror(errno));
695 return Status::ERROR;
696 }
697 ALOGV("%s: X", __FUNCTION__);
698 return Status::OK;
699 }
700
processStreamOffEvent()701 void UVCProvider::UVCDevice::processStreamOffEvent() {
702 int type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
703 if (ioctl(mUVCFd.get(), VIDIOC_STREAMOFF, &type) < 0) {
704 ALOGE("%s: uvc gadget driver request to switch stream off failed %s", __FUNCTION__,
705 strerror(errno));
706 return;
707 }
708
709 mFrameProvider.reset();
710 mBufferManager.reset();
711 memset(&mCommit, 0, sizeof(mCommit));
712 memset(&mProbe, 0, sizeof(mProbe));
713 memset(&mV4l2Format, 0, sizeof(mV4l2Format));
714 mFps = 0;
715 }
716
processStreamOnEvent()717 void UVCProvider::UVCDevice::processStreamOnEvent() {
718 // Allocate V4L2 and map buffers for circulation between camera and UVCDevice
719 mBufferManager = std::make_shared<BufferManager>(this);
720 CameraConfig config;
721 config.width = mV4l2Format.fmt.pix.width;
722 config.height = mV4l2Format.fmt.pix.height;
723 config.fcc = mV4l2Format.fmt.pix.pixelformat;
724 config.fps = mFps;
725
726 mFrameProvider = std::make_shared<SdkFrameProvider>(mBufferManager, config);
727 mFrameProvider->setStreamConfig();
728 mFrameProvider->startStreaming();
729
730 // Queue first buffer to start the stream
731 if (getFrameAndQueueBufferToGadgetDriver(true) != Status::OK) {
732 ALOGE("%s: Queueing first buffer to gadget driver failed, stream not started",
733 __FUNCTION__);
734 return;
735 }
736 auto parent = mParent.lock();
737 parent->watchStreamEvent();
738 }
739
~UVCProvider()740 UVCProvider::~UVCProvider() {
741 if (mUVCListenerThread.joinable()) {
742 mListenToUVCFds = false;
743 mUVCListenerThread.join();
744 }
745
746 if (mUVCDevice) {
747 if (mUVCDevice->getUVCFd() >= 0) {
748 mEpollW.remove(mUVCDevice->getUVCFd());
749 }
750 if (mUVCDevice->getINotifyFd() >= 0) {
751 mEpollW.remove(mUVCDevice->getINotifyFd());
752 }
753 }
754 mUVCDevice = nullptr;
755 }
756
init()757 Status UVCProvider::init() {
758 // TODO: What in the world?
759 return mEpollW.init();
760 }
761
processStreamEvent()762 void UVCProvider::UVCDevice::processStreamEvent() {
763 // Dequeue producer buffer
764 struct v4l2_buffer v4L2Buffer {};
765 v4L2Buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
766 v4L2Buffer.memory = V4L2_MEMORY_MMAP;
767
768 if (ioctl(mUVCFd.get(), VIDIOC_DQBUF, &v4L2Buffer) < 0) {
769 ALOGE("%s: VIDIOC_DQBUF failed %s", __FUNCTION__, strerror(errno));
770 return;
771 }
772 // Get camera frame and queue it to gadget driver
773 if (getFrameAndQueueBufferToGadgetDriver() != Status::OK) {
774 return;
775 }
776 }
encodeImage(AHardwareBuffer * buffer,long timestamp,int rotation)777 Status UVCProvider::UVCDevice::encodeImage(AHardwareBuffer* buffer, long timestamp, int rotation) {
778 if (mFrameProvider == nullptr) {
779 ALOGE("%s: encodeImage called but there is no frame provider active", __FUNCTION__);
780 return Status::ERROR;
781 }
782 return mFrameProvider->encodeImage(buffer, timestamp, rotation);
783 }
784
processUVCEvent()785 void UVCProvider::processUVCEvent() {
786 struct v4l2_event event {};
787 int deviceFd = mUVCDevice->getUVCFd();
788
789 if (ioctl(deviceFd, VIDIOC_DQEVENT, &event) < 0) {
790 ALOGE("%s Failed to dequeue V4L2 event : %s", __FUNCTION__, strerror(errno));
791 return;
792 }
793 struct uvc_event* uvcEvent = reinterpret_cast<struct uvc_event*>(&event.u.data);
794 struct uvc_request_data uvcResponse {};
795 switch (event.type) {
796 case UVC_EVENT_CONNECT:
797 return;
798 case UVC_EVENT_DISCONNECT:
799 ALOGI("%s Disconnect event", __FUNCTION__);
800 stopService();
801 return;
802 case UVC_EVENT_SETUP:
803 ALOGV(" %s: Setup event ", __FUNCTION__);
804 mUVCDevice->processSetupEvent(&(uvcEvent->req), &uvcResponse);
805 break;
806 case UVC_EVENT_DATA:
807 ALOGV(" %s: Data event", __FUNCTION__);
808 mUVCDevice->processDataEvent(&(uvcEvent->data));
809 return;
810 case UVC_EVENT_STREAMON:
811 ALOGI("%s STREAMON event", __FUNCTION__);
812 mUVCDevice->processStreamOnEvent();
813 return;
814 case UVC_EVENT_STREAMOFF:
815 ALOGI("%s STREAMOFF event", __FUNCTION__);
816 mUVCDevice->processStreamOffEvent();
817 mEpollW.modify(mUVCDevice->getUVCFd(), EPOLLPRI);
818 return;
819 default:
820 ALOGI(" UVC Event unsupported %u", event.type);
821 break;
822 }
823
824 if (ioctl(deviceFd, UVCIOC_SEND_RESPONSE, &uvcResponse) < 0) {
825 ALOGE("%s Unable to send response to uvc gadget driver %s", __FUNCTION__, strerror(errno));
826 return;
827 }
828 }
829
830 // TODO: seems unnecessary
watchStreamEvent()831 void UVCProvider::watchStreamEvent() {
832 mEpollW.modify(mUVCDevice->getUVCFd(), EPOLLPRI | EPOLLOUT);
833 }
834
ListenToUVCFds()835 void UVCProvider::ListenToUVCFds() {
836 // For UVC events
837 ALOGI("%s Start to listen to device fd %d and inotify_fd %d", __FUNCTION__,
838 mUVCDevice->getUVCFd(), mUVCDevice->getINotifyFd());
839
840 // Listen to inotify events for node removal
841 mEpollW.add(mUVCDevice->getINotifyFd(), EPOLLIN);
842 // Listen to V4L2 events
843 mEpollW.add(mUVCDevice->getUVCFd(), EPOLLPRI);
844 // For stream events : dequeue and queue buffers
845 while (mListenToUVCFds) {
846 Events events = mEpollW.waitForEvents();
847 for (auto event : events) {
848 if (mUVCDevice->getINotifyFd() == event.data.fd && (event.events & EPOLLIN)) {
849 // File system event on the V4L2 node
850 if (processINotifyEvent()) {
851 break; // Stop handling current events if the service was stopped.
852 }
853 } else {
854 // V4L2 event
855 // Priority event might come with regular events, so one event could have both
856 if (event.events & EPOLLPRI) {
857 processUVCEvent();
858 }
859
860 if (event.events & EPOLLOUT) {
861 if (mUVCDevice != nullptr) {
862 mUVCDevice->processStreamEvent();
863 } else {
864 ALOGW("mUVCDevice is null we've disconnected");
865 }
866 } else if (!(event.events & EPOLLPRI)) {
867 ALOGW("Which event fd is %d ? event %u", event.data.fd, event.events);
868 }
869 }
870 }
871 }
872 }
873
processINotifyEvent()874 bool UVCProvider::processINotifyEvent() {
875 // minimum size to read one event fully
876 ALOGV("%s: Processing inotify event", __FUNCTION__);
877 constexpr size_t BUF_SIZE = sizeof(struct inotify_event) + NAME_MAX + 1;
878 char buf[BUF_SIZE];
879 int len = 0;
880 while ((len = read(mUVCDevice->getINotifyFd(), buf, BUF_SIZE)) >= 0) {
881 for (int i = 0; i < len;) {
882 struct inotify_event* event = reinterpret_cast<inotify_event*>(&buf[i]);
883 i += sizeof(struct inotify_event) + event->len;
884
885 ALOGV("%s: Read inotify_event: wd(%d); mask(%u); cookie(%u); len(%u); name(%s)",
886 __FUNCTION__, event->wd, event->mask, event->cookie, event->cookie,
887 &event->name[0]);
888
889 // Make sure the V4L2 node is actually removed before stopping service.
890 if ((event->mask & IN_ATTRIB) && access(mUVCDevice->getCurrentVideoNode(), F_OK)) {
891 // V4L2 node unlinked. Stop service as "UVC_EVENT_DISCONNECT" won't be coming in
892 // anymore.
893 ALOGW("%s: V4L2 node removed without UVC_EVENT_DISCONNECT. Stopping Service.",
894 __FUNCTION__);
895 stopService();
896 return true;
897 }
898 }
899 }
900 ALOGV("%s: Could not read from inotify_fd(%d). Error(%d): %s", __FUNCTION__,
901 mUVCDevice->getINotifyFd(), errno, strerror(errno));
902 return false;
903 }
904
encodeImage(AHardwareBuffer * buffer,long timestamp,int rotation)905 int UVCProvider::encodeImage(AHardwareBuffer* buffer, long timestamp, int rotation) {
906 if (mUVCDevice == nullptr) {
907 ALOGE("%s: Request to encode Image without UVCDevice Running.", __FUNCTION__);
908 return -1;
909 }
910 return mUVCDevice->encodeImage(buffer, timestamp, rotation) == Status::OK ? 0 : -1;
911 }
912
startUVCListenerThread()913 void UVCProvider::startUVCListenerThread() {
914 mListenToUVCFds = true;
915 mUVCListenerThread =
916 DeviceAsWebcamNative::createJniAttachedThread(&UVCProvider::ListenToUVCFds, this);
917 ALOGI("Started new UVCListenerThread");
918 }
919
stopAndWaitForUVCListenerThread()920 void UVCProvider::stopAndWaitForUVCListenerThread() {
921 // This thread stays alive till onDestroy is called.
922 if (mUVCListenerThread.joinable()) {
923 mListenToUVCFds = false;
924 mUVCListenerThread.join();
925 }
926 }
927
startService(const std::unordered_set<std::string> & ignoredNodes)928 Status UVCProvider::startService(const std::unordered_set<std::string>& ignoredNodes) {
929 // Resets old state for epoll since this is a new start for the service.
930 mEpollW.init();
931 if (mUVCDevice != nullptr) {
932 mUVCDevice->closeUVCFd();
933 }
934 mUVCDevice = std::make_shared<UVCDevice>(shared_from_this(), ignoredNodes);
935 if (!mUVCDevice->isInited()) {
936 return Status::ERROR;
937 }
938 stopAndWaitForUVCListenerThread(); // Just in case it is already running
939 startUVCListenerThread();
940 return Status::OK;
941 }
942
stopService()943 void UVCProvider::stopService() {
944 // TODO: Try removing this
945 mUVCDevice->processStreamOffEvent();
946 mEpollW.remove(mUVCDevice->getUVCFd());
947 mEpollW.remove(mUVCDevice->getINotifyFd());
948 // Signal the service to stop.
949 // UVC Provider will get destructed when the Java Service is destroyed.
950 DeviceAsWebcamServiceManager::kInstance->stopService();
951 mUVCDevice = nullptr;
952 mListenToUVCFds = false;
953 }
954
955 } // namespace webcam
956 } // namespace android
957