/* * Copyright (c) 2021 by Allwinnertech Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "CameraHALv3_4" #include "v4l2_camera_hal.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "camera_config.h" #include "v4l2_camera.h" /* * This file serves as the entry point to the HAL. It is modified from the * example default HAL available in hardware/libhardware/modules/camera. * It contains the module structure and functions used by the framework * to load and interface to this HAL, as well as the handles to the individual * camera devices. */ namespace v4l2_camera_hal { // Default global camera hal. static V4L2CameraHAL gCameraHAL; V4L2CameraHAL::V4L2CameraHAL() : mCameras(), mCallbacks(NULL) { HAL_LOG_ENTER(); // Find /dev/video* nodes. // Fix stream is not manager now. int ret; std::string node; // Test each for V4L2 support and uniqueness. int id = 0; int i = 0; char dev_node[16]; sprintf(dev_node, "/dev/video%d", i); ret = access(dev_node, F_OK); if (ret == 0) { HAL_LOGV("Found video node %s.", dev_node); } else { HAL_LOGE("Cannot found video node %s. %s", dev_node, strerror(errno)); } hal_merge_stream_flag = false; char * s_value; int pic_width = 0; int pic_height = 0; std::string tmp; std::vector s_data; // id == 0 camera facing back; // id == 1 camera facing front; int MAX_NUM_OF_CAMERAS = CCameraConfig::numberOfCamera(); for (id = 0; id config = std::make_shared(cameraId); if (config == 0) { HAL_LOGW("create CCameraConfig failed"); } else { config->initParameters(); config->dumpParameters(); } mCameraConfig.push_back(config); s_value = config->supportPictureSizeValue(); std::string st1 = s_value; std::stringstream input(st1); while (getline(input, tmp, ',')) { s_data.push_back(tmp); } for(auto s : s_data) { sscanf(s.c_str(), "%dx%d", &pic_width,&pic_height); if(pic_width * pic_height > 4000*3000) { hal_merge_stream_flag = true; } } V4L2Camera* cam(V4L2Camera::NewV4L2Camera(id, config, hal_merge_stream_flag)); if (cam) { mCameras.push_back(cam); } else { HAL_LOGE("Failed to initialize camera at %s.", dev_node); } mCameraConfig.push_back(config); if (getSingleCameraId() == 0) break; } } V4L2CameraHAL::~V4L2CameraHAL() { HAL_LOG_ENTER(); int MAX_NUM_OF_CAMERAS = CCameraConfig::numberOfCamera(); for (int n = 0; n < MAX_NUM_OF_CAMERAS; n++) { if (mCameraConfig[n] != NULL) { // delete mCameraConfig[n]; mCameraConfig[n] = NULL; } if (getSingleCameraId() == 0) break; } } int V4L2CameraHAL::getNumberOfCameras() { HAL_LOGV("returns %zu", mCameras.size()); return mCameras.size(); } int V4L2CameraHAL::getCameraInfo(int id, camera_info_t* info) { HAL_LOG_ENTER(); if (id < 0 || id >= static_cast(mCameras.size())) { return -EINVAL; } // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged. return mCameras[id]->getInfo(info); } int V4L2CameraHAL::setCallbacks(const camera_module_callbacks_t* callbacks) { HAL_LOG_ENTER(); mCallbacks = callbacks; return 0; } void V4L2CameraHAL::getVendorTagOps(vendor_tag_ops_t* UNUSED(ops)) { HAL_LOG_ENTER(); // No vendor ops for this HAL. From : // "leave ops unchanged if no vendor tags are defined." } int V4L2CameraHAL::openLegacy(const hw_module_t* /*module*/, const char* /*id*/, uint32_t /*halVersion*/, hw_device_t** /*device*/) { HAL_LOG_ENTER(); // Not supported. return -ENOSYS; } int V4L2CameraHAL::setTorchMode(const char* camera_id, bool enabled) { HAL_LOG_ENTER(); // TODO(b/29158098): HAL is required to respond appropriately if // the desired camera actually does support flash. int retVal = 0; int cam_id = std::atoi(camera_id); if (mCameraConfig[cam_id] != NULL) { if (!mCameraConfig[cam_id]->supportFlashMode()) { return -ENOSYS; } } HAL_LOGD("enabled:%d cam_id:%d", enabled, cam_id); if (cam_id == 1 && mCallbacks != NULL) { HAL_LOGV("no flash!cam_id:%d", cam_id); mCallbacks->torch_mode_status_change(mCallbacks, camera_id, TORCH_MODE_STATUS_NOT_AVAILABLE); } else { if (enabled) { retVal = mCameras[cam_id]->setFlashTorchMode(enabled); if (mCallbacks != NULL && !retVal) { mCallbacks->torch_mode_status_change(mCallbacks, camera_id, TORCH_MODE_STATUS_AVAILABLE_ON); } } else { retVal = mCameras[cam_id]->setFlashTorchMode(enabled); if (mCallbacks != NULL && !retVal) { mCallbacks->torch_mode_status_change(mCallbacks, camera_id, TORCH_MODE_STATUS_AVAILABLE_OFF); } } } return retVal; } int V4L2CameraHAL::openDevice(const hw_module_t* module, const char* name, hw_device_t** device) { HAL_LOG_ENTER(); if (module != &HAL_MODULE_INFO_SYM.common) { HAL_LOGE( "Invalid module %p expected %p", module, &HAL_MODULE_INFO_SYM.common); return -EINVAL; } int id; if (!android::base::ParseInt(name, &id, 0, getNumberOfCameras() - 1)) { return -EINVAL; } if (mCameraConfig[id]->supportCameraMulplex()) { if (mCameras[id]->isBusy()) { return -EUSERS; } } else { uint32_t id_tmp; for (id_tmp = 0; id_tmp < mCameras.size(); id_tmp++) { if (mCameras[id_tmp]->isBusy()) { return -EUSERS; } } } if (mCallbacks != NULL) { const char* camera_id = "0"; setTorchMode(camera_id, false); mCameras[0]->closeFlashTorch(); } // TODO(b/29185945): Hotplugging: return -EINVAL if unplugged. return mCameras[id]->openDevice(module, device); } /* * The framework calls the following wrappers, which in turn * call the corresponding methods of the global HAL object. */ static int get_number_of_cameras() { return gCameraHAL.getNumberOfCameras(); } static int get_camera_info(int id, struct camera_info* info) { return gCameraHAL.getCameraInfo(id, info); } static int set_callbacks(const camera_module_callbacks_t* callbacks) { return gCameraHAL.setCallbacks(callbacks); } static void get_vendor_tag_ops(vendor_tag_ops_t* ops) { return gCameraHAL.getVendorTagOps(ops); } static int open_legacy(const hw_module_t* module, const char* id, uint32_t halVersion, hw_device_t** device) { return gCameraHAL.openLegacy(module, id, halVersion, device); } static int set_torch_mode(const char* camera_id, bool enabled) { return gCameraHAL.setTorchMode(camera_id, enabled); } static int open_dev(const hw_module_t* module, const char* name, hw_device_t** device) { return gCameraHAL.openDevice(module, name, device); } } // namespace v4l2_camera_hal static hw_module_methods_t v4l2_module_methods = { .open = v4l2_camera_hal::open_dev}; camera_module_t HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = { .common = { .tag = HARDWARE_MODULE_TAG, .module_api_version = CAMERA_MODULE_API_VERSION_2_4, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = CAMERA_HARDWARE_MODULE_ID, .name = "V4L2 Camera HAL v3", .author = "ZJW", .methods = &v4l2_module_methods, .dso = nullptr, .reserved = {0}, }, .get_number_of_cameras = v4l2_camera_hal::get_number_of_cameras, .get_camera_info = v4l2_camera_hal::get_camera_info, .set_callbacks = v4l2_camera_hal::set_callbacks, .get_vendor_tag_ops = v4l2_camera_hal::get_vendor_tag_ops, .open_legacy = v4l2_camera_hal::open_legacy, .set_torch_mode = v4l2_camera_hal::set_torch_mode, .init = nullptr, .reserved = {nullptr, nullptr}};