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