Home | History | Annotate | Download | only in 3_4
      1 /*
      2  * Copyright 2016 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 // Modified from hardware/libhardware/modules/camera/CameraHAL.cpp
     18 
     19 //#define LOG_NDEBUG 0
     20 #define LOG_TAG "V4L2CameraHAL"
     21 
     22 #include "v4l2_camera_hal.h"
     23 
     24 #include <dirent.h>
     25 #include <fcntl.h>
     26 #include <linux/videodev2.h>
     27 #include <sys/ioctl.h>
     28 #include <sys/stat.h>
     29 #include <sys/types.h>
     30 #include <unistd.h>
     31 
     32 #include <algorithm>
     33 #include <cstdlib>
     34 #include <unordered_set>
     35 
     36 #include <android-base/parseint.h>
     37 
     38 #include "common.h"
     39 #include "v4l2_camera.h"
     40 
     41 /*
     42  * This file serves as the entry point to the HAL. It is modified from the
     43  * example default HAL available in hardware/libhardware/modules/camera.
     44  * It contains the module structure and functions used by the framework
     45  * to load and interface to this HAL, as well as the handles to the individual
     46  * camera devices.
     47  */
     48 
     49 namespace v4l2_camera_hal {
     50 
     51 // Default global camera hal.
     52 static V4L2CameraHAL gCameraHAL;
     53 
     54 V4L2CameraHAL::V4L2CameraHAL() : mCameras(), mCallbacks(NULL) {
     55   HAL_LOG_ENTER();
     56   // Adds all available V4L2 devices.
     57   // List /dev nodes.
     58   DIR* dir = opendir("/dev");
     59   if (dir == NULL) {
     60     HAL_LOGE("Failed to open /dev");
     61     return;
     62   }
     63   // Find /dev/video* nodes.
     64   dirent* ent;
     65   std::vector<std::string> nodes;
     66   while ((ent = readdir(dir))) {
     67     std::string desired = "video";
     68     size_t len = desired.size();
     69     if (strncmp(desired.c_str(), ent->d_name, len) == 0) {
     70       if (strlen(ent->d_name) > len && isdigit(ent->d_name[len])) {
     71         // ent is a numbered video node.
     72         nodes.push_back(std::string("/dev/") + ent->d_name);
     73         HAL_LOGV("Found video node %s.", nodes.back().c_str());
     74       }
     75     }
     76   }
     77   // Test each for V4L2 support and uniqueness.
     78   std::unordered_set<std::string> buses;
     79   std::string bus;
     80   v4l2_capability cap;
     81   int fd;
     82   int id = 0;
     83   for (const auto& node : nodes) {
     84     // Open the node.
     85     fd = TEMP_FAILURE_RETRY(open(node.c_str(), O_RDWR));
     86     if (fd < 0) {
     87       HAL_LOGE("failed to open %s (%s).", node.c_str(), strerror(errno));
     88       continue;
     89     }
     90     // Read V4L2 capabilities.
     91     if (TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_QUERYCAP, &cap)) != 0) {
     92       HAL_LOGE(
     93           "VIDIOC_QUERYCAP on %s fail: %s.", node.c_str(), strerror(errno));
     94     } else if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
     95       HAL_LOGE("%s is not a V4L2 video capture device.", node.c_str());
     96     } else {
     97       // If the node is unique, add a camera for it.
     98       bus = reinterpret_cast<char*>(cap.bus_info);
     99       if (buses.insert(bus).second) {
    100         HAL_LOGV("Found unique bus at %s.", node.c_str());
    101         std::unique_ptr<V4L2Camera> cam(V4L2Camera::NewV4L2Camera(id++, node));
    102         if (cam) {
    103           mCameras.push_back(std::move(cam));
    104         } else {
    105           HAL_LOGE("Failed to initialize camera at %s.", node.c_str());
    106         }
    107       }
    108     }
    109     close(fd);
    110   }
    111 }
    112 
    113 V4L2CameraHAL::~V4L2CameraHAL() {
    114   HAL_LOG_ENTER();
    115 }
    116 
    117 int V4L2CameraHAL::getNumberOfCameras() {
    118   HAL_LOGV("returns %zu", mCameras.size());
    119   return mCameras.size();
    120 }
    121 
    122 int V4L2CameraHAL::getCameraInfo(int id, camera_info_t* info) {
    123   HAL_LOG_ENTER();
    124   if (id < 0 || static_cast<size_t>(id) >= mCameras.size()) {
    125     return -EINVAL;
    126   }
    127   // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged.
    128   return mCameras[id]->getInfo(info);
    129 }
    130 
    131 int V4L2CameraHAL::setCallbacks(const camera_module_callbacks_t* callbacks) {
    132   HAL_LOG_ENTER();
    133   mCallbacks = callbacks;
    134   return 0;
    135 }
    136 
    137 void V4L2CameraHAL::getVendorTagOps(vendor_tag_ops_t* /*ops*/) {
    138   HAL_LOG_ENTER();
    139   // No vendor ops for this HAL. From <hardware/camera_common.h>:
    140   // "leave ops unchanged if no vendor tags are defined."
    141 }
    142 
    143 int V4L2CameraHAL::openLegacy(const hw_module_t* /*module*/,
    144                               const char* /*id*/,
    145                               uint32_t /*halVersion*/,
    146                               hw_device_t** /*device*/) {
    147   HAL_LOG_ENTER();
    148   // Not supported.
    149   return -ENOSYS;
    150 }
    151 
    152 int V4L2CameraHAL::setTorchMode(const char* /*camera_id*/, bool /*enabled*/) {
    153   HAL_LOG_ENTER();
    154   // TODO(b/29158098): HAL is required to respond appropriately if
    155   // the desired camera actually does support flash.
    156   return -ENOSYS;
    157 }
    158 
    159 int V4L2CameraHAL::openDevice(const hw_module_t* module,
    160                               const char* name,
    161                               hw_device_t** device) {
    162   HAL_LOG_ENTER();
    163 
    164   if (module != &HAL_MODULE_INFO_SYM.common) {
    165     HAL_LOGE(
    166         "Invalid module %p expected %p", module, &HAL_MODULE_INFO_SYM.common);
    167     return -EINVAL;
    168   }
    169 
    170   int id;
    171   if (!android::base::ParseInt(name, &id, 0, getNumberOfCameras() - 1)) {
    172     return -EINVAL;
    173   }
    174   // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged.
    175   return mCameras[id]->openDevice(module, device);
    176 }
    177 
    178 /*
    179  * The framework calls the following wrappers, which in turn
    180  * call the corresponding methods of the global HAL object.
    181  */
    182 
    183 static int get_number_of_cameras() {
    184   return gCameraHAL.getNumberOfCameras();
    185 }
    186 
    187 static int get_camera_info(int id, struct camera_info* info) {
    188   return gCameraHAL.getCameraInfo(id, info);
    189 }
    190 
    191 static int set_callbacks(const camera_module_callbacks_t* callbacks) {
    192   return gCameraHAL.setCallbacks(callbacks);
    193 }
    194 
    195 static void get_vendor_tag_ops(vendor_tag_ops_t* ops) {
    196   return gCameraHAL.getVendorTagOps(ops);
    197 }
    198 
    199 static int open_legacy(const hw_module_t* module,
    200                        const char* id,
    201                        uint32_t halVersion,
    202                        hw_device_t** device) {
    203   return gCameraHAL.openLegacy(module, id, halVersion, device);
    204 }
    205 
    206 static int set_torch_mode(const char* camera_id, bool enabled) {
    207   return gCameraHAL.setTorchMode(camera_id, enabled);
    208 }
    209 
    210 static int open_dev(const hw_module_t* module,
    211                     const char* name,
    212                     hw_device_t** device) {
    213   return gCameraHAL.openDevice(module, name, device);
    214 }
    215 
    216 }  // namespace v4l2_camera_hal
    217 
    218 static hw_module_methods_t v4l2_module_methods = {
    219     .open = v4l2_camera_hal::open_dev};
    220 
    221 camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
    222     .common =
    223         {
    224             .tag = HARDWARE_MODULE_TAG,
    225             .module_api_version = CAMERA_MODULE_API_VERSION_2_4,
    226             .hal_api_version = HARDWARE_HAL_API_VERSION,
    227             .id = CAMERA_HARDWARE_MODULE_ID,
    228             .name = "V4L2 Camera HAL v3",
    229             .author = "The Android Open Source Project",
    230             .methods = &v4l2_module_methods,
    231             .dso = nullptr,
    232             .reserved = {0},
    233         },
    234     .get_number_of_cameras = v4l2_camera_hal::get_number_of_cameras,
    235     .get_camera_info = v4l2_camera_hal::get_camera_info,
    236     .set_callbacks = v4l2_camera_hal::set_callbacks,
    237     .get_vendor_tag_ops = v4l2_camera_hal::get_vendor_tag_ops,
    238     .open_legacy = v4l2_camera_hal::open_legacy,
    239     .set_torch_mode = v4l2_camera_hal::set_torch_mode,
    240     .init = nullptr,
    241     .get_physical_camera_info = nullptr,
    242     .reserved = {nullptr, nullptr}};
    243