10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2009 Google Inc. 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Author: lexnikitin@google.com (Alexey Nikitin) 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * V4LLookup provides basic functionality to work with V2L2 devices in Linux 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * The functionality is implemented as a class with virtual methods for 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * the purpose of unit testing. 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/devices/v4llookup.h" 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <errno.h> 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <fcntl.h> 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <linux/types.h> 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <linux/videodev2.h> 15b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org#include <string.h> 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <sys/ioctl.h> 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <sys/stat.h> 18cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include <sys/types.h> 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <unistd.h> 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 212a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h" 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket { 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgV4LLookup *V4LLookup::v4l_lookup_ = NULL; 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool V4LLookup::CheckIsV4L2Device(const std::string& device_path) { 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // check device major/minor numbers are in the range for video devices. 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org struct stat s; 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (lstat(device_path.c_str(), &s) != 0 || !S_ISCHR(s.st_mode)) return false; 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int video_fd = -1; 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_v4l2 = false; 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // check major/minur device numbers are in range for video device 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (major(s.st_rdev) == 81) { 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org dev_t num = minor(s.st_rdev); 390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (num <= 63) { 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_fd = ::open(device_path.c_str(), O_RDONLY | O_NONBLOCK); 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if ((video_fd >= 0) || (errno == EBUSY)) { 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ::v4l2_capability video_caps; 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org memset(&video_caps, 0, sizeof(video_caps)); 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if ((errno == EBUSY) || 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (::ioctl(video_fd, VIDIOC_QUERYCAP, &video_caps) >= 0 && 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (video_caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))) { 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Found V4L2 capture device " << device_path; 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_v4l2 = true; 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 5270022fa5eb218ec690774cc4a74558699a79600asergeyu@chromium.org LOG_ERRNO(LS_ERROR) << "VIDIOC_QUERYCAP failed for " << device_path; 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 5570022fa5eb218ec690774cc4a74558699a79600asergeyu@chromium.org LOG_ERRNO(LS_ERROR) << "Failed to open " << device_path; 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video_fd >= 0) 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ::close(video_fd); 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return is_v4l2; 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; // namespace cricket 67