1 /* 2 * Copyright 2009, Google Inc. 3 * Author: lexnikitin (at) google.com (Alexey Nikitin) 4 * 5 * V4LLookup provides basic functionality to work with V2L2 devices in Linux 6 * The functionality is implemented as a class with virtual methods for 7 * the purpose of unit testing. 8 */ 9 #include "talk/session/phone/v4llookup.h" 10 11 #include <errno.h> 12 #include <fcntl.h> 13 #include <linux/types.h> 14 #include <linux/videodev2.h> 15 #include <sys/ioctl.h> 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 19 #include <cstring> 20 21 #include "talk/base/logging.h" 22 23 namespace cricket { 24 25 V4LLookup *V4LLookup::v4l_lookup_ = new V4LLookup(); 26 27 bool V4LLookup::CheckIsV4L2Device(const std::string& device_path) { 28 // check device major/minor numbers are in the range for video devices. 29 struct stat s; 30 31 if (lstat(device_path.c_str(), &s) != 0 || !S_ISCHR(s.st_mode)) return false; 32 33 int video_fd = -1; 34 bool is_v4l2 = false; 35 36 // check major/minur device numbers are in range for video device 37 if (major(s.st_rdev) == 81) { 38 dev_t num = minor(s.st_rdev); 39 if (num <= 63 && num >= 0) { 40 video_fd = ::open(device_path.c_str(), O_RDONLY | O_NONBLOCK); 41 if ((video_fd >= 0) || (errno == EBUSY)) { 42 ::v4l2_capability video_caps; 43 memset(&video_caps, 0, sizeof(video_caps)); 44 45 if ((errno == EBUSY) || 46 (::ioctl(video_fd, VIDIOC_QUERYCAP, &video_caps) >= 0 && 47 (video_caps.capabilities & V4L2_CAP_VIDEO_CAPTURE))) { 48 LOG(LS_INFO) << "Found V4L2 capture device " << device_path; 49 50 is_v4l2 = true; 51 } else { 52 LOG(LS_ERROR) << "VIDIOC_QUERYCAP failed for " << device_path; 53 } 54 } else { 55 LOG(LS_ERROR) << "Failed to open " << device_path; 56 } 57 } 58 } 59 60 if (video_fd >= 0) 61 ::close(video_fd); 62 63 return is_v4l2; 64 } 65 66 }; // namespace cricket 67