diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..87061e0 --- /dev/null +++ b/Android.mk @@ -0,0 +1,23 @@ +LOCAL_PATH := $(call my-dir) +LIBCAMERA_BUILD := nexus +include $(call all-subdir-makefiles) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE := camera.$(TARGET_BOARD_PLATFORM) +LOCAL_SRC_FILES := cameraHal.cpp +LOCAL_PRELINK_MODULE := false +CAMERA_LIB := camera-inc + +ifeq ($(LIBCAMERA_BUILD),nexus) +CAMERA_LIB := camera-nexus +endif + +TARGET_GLOBAL_LD_DIRS += -L$(LOCAL_PATH) -l${CAMERA_LIB} +LOCAL_SHARED_LIBRARIES := liblog libdl libutils libcamera_client libbinder libcutils libhardware +LOCAL_C_INCLUDES := frameworks/base/services/ frameworks/base/include +LOCAL_C_INCLUDES += hardware/libhardware/include/ hardware/libhardware/modules/gralloc/ + +include $(BUILD_SHARED_LIBRARY) diff --git a/CameraHardwareInterface.h b/CameraHardwareInterface.h new file mode 100644 index 0000000..18b2294 --- /dev/null +++ b/CameraHardwareInterface.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2010, Code Aurora Forum. All rights reserved. + * + * 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. + */ + +#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H +#define ANDROID_HARDWARE_CAMERA_HARDWARE_INTERFACE_H + +#include +#include +#include +#include +#include + +namespace android { + +class Overlay; + +/** + * The size of image for display. + */ +typedef struct image_rect_struct +{ + uint32_t width; /* Image width */ + uint32_t height; /* Image height */ +} image_rect_type; + + +typedef void (*notify_callback)(int32_t msgType, + int32_t ext1, + int32_t ext2, + void* user); + +typedef void (*data_callback)(int32_t msgType, + const sp& dataPtr, + void* user); + +typedef void (*data_callback_timestamp)(nsecs_t timestamp, + int32_t msgType, + const sp& dataPtr, + void* user); + +/** + * CameraHardwareInterface.h defines the interface to the + * camera hardware abstraction layer, used for setting and getting + * parameters, live previewing, and taking pictures. + * + * It is a referenced counted interface with RefBase as its base class. + * CameraService calls openCameraHardware() to retrieve a strong pointer to the + * instance of this interface and may be called multiple times. The + * following steps describe a typical sequence: + * + * -# After CameraService calls openCameraHardware(), getParameters() and + * setParameters() are used to initialize the camera instance. + * CameraService calls getPreviewHeap() to establish access to the + * preview heap so it can be registered with SurfaceFlinger for + * efficient display updating while in preview mode. + * -# startPreview() is called. The camera instance then periodically + * sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time + * a new preview frame is available. If data callback code needs to use + * this memory after returning, it must copy the data. + * + * Prior to taking a picture, CameraService calls autofocus(). When auto + * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification, + * which informs the application whether focusing was successful. The camera instance + * only sends this message once and it is up to the application to call autoFocus() + * again if refocusing is desired. + * + * CameraService calls takePicture() to request the camera instance take a + * picture. At this point, if a shutter, postview, raw, and/or compressed callback + * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME, + * any memory provided in a data callback must be copied if it's needed after returning. + */ +class CameraHardwareInterface : public virtual RefBase { +public: + virtual ~CameraHardwareInterface() { } + + /** Return the IMemoryHeap for the preview image heap */ + virtual sp getPreviewHeap() const = 0; + + /** Return the IMemoryHeap for the raw image heap */ + virtual sp getRawHeap() const = 0; + + /** Set the notification and data callbacks */ + virtual void setCallbacks(notify_callback notify_cb, + data_callback data_cb, + data_callback_timestamp data_cb_timestamp, + void* user) = 0; + + /** + * The following three functions all take a msgtype, + * which is a bitmask of the messages defined in + * include/ui/Camera.h + */ + + /** + * Enable a message, or set of messages. + */ + virtual void enableMsgType(int32_t msgType) = 0; + + /** + * Disable a message, or a set of messages. + */ + virtual void disableMsgType(int32_t msgType) = 0; + + /** + * Query whether a message, or a set of messages, is enabled. + * Note that this is operates as an AND, if any of the messages + * queried are off, this will return false. + */ + virtual bool msgTypeEnabled(int32_t msgType) = 0; + + /** + * Start preview mode. + */ + virtual status_t startPreview() = 0; + +#ifdef USE_GETBUFFERINFO + /** + * Query the recording buffer information from HAL. + * This is needed because the opencore expects the buffer + * information before starting the recording. + */ + virtual status_t getBufferInfo(sp& Frame, size_t *alignedSize) = 0; +#endif + + /** + * Only used if overlays are used for camera preview. + */ + virtual bool useOverlay() {return false;} + virtual status_t setOverlay(const sp &overlay) {return BAD_VALUE;} + + /** + * Stop a previously started preview. + */ + virtual void stopPreview() = 0; + + /** + * Returns true if preview is enabled. + */ + virtual bool previewEnabled() = 0; + + /** + * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME + * message is sent with the corresponding frame. Every record frame must be released + * by calling releaseRecordingFrame(). + */ + virtual status_t startRecording() = 0; + + /** + * Stop a previously started recording. + */ + virtual void stopRecording() = 0; + + /** + * Returns true if recording is enabled. + */ + virtual bool recordingEnabled() = 0; + + /** + * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + */ + virtual void releaseRecordingFrame(const sp& mem) = 0; + + /** + * Start auto focus, the notification callback routine is called + * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() + * will be called again if another auto focus is needed. + */ + virtual status_t autoFocus() = 0; + + /** + * Cancels auto-focus function. If the auto-focus is still in progress, + * this function will cancel it. Whether the auto-focus is in progress + * or not, this function will return the focus position to the default. + * If the camera does not support auto-focus, this is a no-op. + */ + virtual status_t cancelAutoFocus() = 0; + + /** + * Take a picture. + */ + virtual status_t takePicture() = 0; + + /** + * Cancel a picture that was started with takePicture. Calling this + * method when no picture is being taken is a no-op. + */ + virtual status_t cancelPicture() = 0; + + /** + * Set the camera parameters. This returns BAD_VALUE if any parameter is + * invalid or not supported. */ + virtual status_t setParameters(const CameraParameters& params) = 0; + + /** Return the camera parameters. */ + virtual CameraParameters getParameters() const = 0; + + /** + * Send command to camera driver. + */ + virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0; + + /** + * Release the hardware resources owned by this object. Note that this is + * *not* done in the destructor. + */ + virtual void release() = 0; + + /** + * Dump state of the camera hardware + */ + virtual status_t dump(int fd, const Vector& args) const = 0; + +}; + +/** + * The functions need to be provided by the camera HAL. + * + * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo() + * and openCameraHardware() is 0 to N-1. + */ +extern "C" int HAL_getNumberOfCameras(); +extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo); +/* HAL should return NULL if it fails to open camera hardware. */ +extern "C" sp HAL_openCameraHardware(int cameraId); + +}; // namespace android + +#endif diff --git a/cameraHal.cpp b/cameraHal.cpp new file mode 100644 index 0000000..efbd43a --- /dev/null +++ b/cameraHal.cpp @@ -0,0 +1,630 @@ +/* + * Copyright (C) 2012, Raviprasad V Mummidi. + * + * 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 "CameraHAL" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NO_ERROR 0 +//#define LOGV LOGD + +struct qcom_mdp_rect { + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; +}; + +struct qcom_mdp_img { + uint32_t width; + int32_t height; + int32_t format; + int32_t offset; + int memory_id; /* The file descriptor */ +}; + +struct qcom_mdp_blit_req { + struct qcom_mdp_img src; + struct qcom_mdp_img dst; + struct qcom_mdp_rect src_rect; + struct qcom_mdp_rect dst_rect; + uint32_t alpha; + uint32_t transp_mask; + uint32_t flags; +}; + +struct blitreq { + unsigned int count; + struct qcom_mdp_blit_req req; +}; + +/* Prototypes and extern functions. */ +extern "C" android::sp openCameraHardware(int id); +int qcamera_device_open(const hw_module_t* module, const char* name, + hw_device_t** device); +int CameraHAL_GetNum_Cameras(void); +int CameraHAL_GetCam_Info(int camera_id, struct camera_info *info); + +/* Global variables. */ +camera_notify_callback origNotify_cb = NULL; +camera_data_callback origData_cb = NULL; +camera_data_timestamp_callback origDataTS_cb = NULL; +camera_request_memory origCamReqMemory = NULL; + +android::String8 g_str; +android::CameraParameters camSettings; +preview_stream_ops_t *mWindow = NULL; +android::sp qCamera; + +static hw_module_methods_t camera_module_methods = { + open: qcamera_device_open +}; + +camera_module_t HAL_MODULE_INFO_SYM = { + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: CAMERA_HARDWARE_MODULE_ID, + name: "Camera HAL for ICS", + author: "Raviprasad V Mummidi", + methods: &camera_module_methods, + dso: NULL, + reserved: {0}, + }, + get_number_of_cameras: CameraHAL_GetNum_Cameras, + get_camera_info: CameraHAL_GetCam_Info, +}; + +/* HAL helper functions. */ +void +CameraHAL_NotifyCb(int32_t msg_type, int32_t ext1, + int32_t ext2, void *user) +{ + LOGV("CameraHAL_NotifyCb: msg_type:%d ext1:%d ext2:%d user:%p\n", + msg_type, ext1, ext2, user); + if (origNotify_cb != NULL) { + origNotify_cb(msg_type, ext1, ext2, user); + } +} + +void +CameraHAL_CopyBuffers_Hw(int srcFd, int destFd, + size_t srcOffset, size_t destOffset, + int srcFormat, int destFormat, + int x, int y, int w, int h) +{ + struct blitreq blit; + int fb_fd = open("/dev/graphics/fb0", O_RDWR); + + if (fb_fd < 0) { + LOGD("CameraHAL_CopyBuffers_Hw: Error opening /dev/graphics/fb0\n"); + return; + } + + LOGV("CameraHAL_CopyBuffers_Hw: srcFD:%d destFD:%d srcOffset:%#x" + " destOffset:%#x x:%d y:%d w:%d h:%d\n", srcFd, destFd, srcOffset, + dstOffset, x, y, w, h); + + memset(&blit, 0, sizeof(blit)); + blit.count = 1; + + blit.req.flags = 0; + blit.req.alpha = 0xff; + blit.req.transp_mask = 0xffffffff; + + blit.req.src.width = w; + blit.req.src.height = h; + blit.req.src.offset = srcOffset; + blit.req.src.memory_id = srcFd; + blit.req.src.format = srcFormat; + + blit.req.dst.width = w; + blit.req.dst.height = h; + blit.req.dst.offset = destOffset; + blit.req.dst.memory_id = destFd; + blit.req.dst.format = destFormat; + + blit.req.src_rect.x = blit.req.dst_rect.x = x; + blit.req.src_rect.y = blit.req.dst_rect.y = y; + blit.req.src_rect.w = blit.req.dst_rect.w = w; + blit.req.src_rect.h = blit.req.dst_rect.h = h; + + if (ioctl(fb_fd, MSMFB_BLIT, &blit)) { + LOGE("CameraHAL_CopyBuffers_Hw: MSMFB_BLIT failed = %d %s\n", + errno, strerror(errno)); + } + close(fb_fd); +} + +void +CameraHAL_HandlePreviewData(const android::sp& dataPtr, + preview_stream_ops_t *mWindow, + camera_request_memory getMemory, + int32_t previewWidth, int32_t previewHeight) +{ + if (mWindow != NULL && getMemory != NULL) { + ssize_t offset; + size_t size; + int32_t previewFormat = MDP_Y_CBCR_H2V2; + int32_t destFormat = MDP_RGBA_8888; + + android::status_t retVal; + android::sp mHeap = dataPtr->getMemory(&offset, + &size); + + LOGV("CameraHAL_HandlePreviewData: previewWidth:%d previewHeight:%d " + "offset:%#x size:%#x base:%p\n", previewWidth, previewHeight, + (unsigned)offset, size, mHeap != NULL ? mHeap->base() : 0); + + retVal = mWindow->set_buffers_geometry(mWindow, + previewWidth, previewHeight, + HAL_PIXEL_FORMAT_RGBA_8888); + if (retVal == NO_ERROR) { + int32_t stride; + buffer_handle_t *bufHandle = NULL; + + retVal = mWindow->dequeue_buffer(mWindow, &bufHandle, &stride); + if (retVal == NO_ERROR) { + retVal = mWindow->lock_buffer(mWindow, bufHandle); + if (retVal == NO_ERROR) { + private_handle_t const *privHandle = + reinterpret_cast(*bufHandle); + CameraHAL_CopyBuffers_Hw(mHeap->getHeapID(), privHandle->fd, + offset, privHandle->offset, + previewFormat, destFormat, + 0, 0, previewWidth, previewHeight); + mWindow->enqueue_buffer(mWindow, bufHandle); + } else { + LOGE("CameraHAL_HandlePreviewData: ERROR locking the buffer\n"); + mWindow->cancel_buffer(mWindow, bufHandle); + } + } else { + LOGE("CameraHAL_HandlePreviewData: ERROR dequeueing the buffer\n"); + } + } + } +} + +camera_memory_t * +CameraHAL_GenClientData(const android::sp &dataPtr, + camera_request_memory reqClientMemory, + void *user) +{ + ssize_t offset; + size_t size; + camera_memory_t *clientData = NULL; + android::sp mHeap = dataPtr->getMemory(&offset, &size); + + LOGV("CameraHAL_GenClientData: offset:%#x size:%#x base:%p\n", + (unsigned)offset, size, mHeap != NULL ? mHeap->base() : 0); + + clientData = reqClientMemory(-1, size, 1, user); + if (clientData != NULL) { + memcpy(clientData->data, (char *)(mHeap->base()) + offset, size); + } else { + LOGV("CameraHAL_GenClientData: ERROR allocating memory from client\n"); + } + return clientData; +} + +void +CameraHAL_DataCb(int32_t msg_type, const android::sp& dataPtr, + void *user) +{ + LOGV("CameraHAL_DataCb: msg_type:%d user:%p\n", msg_type, user); + if (msg_type == CAMERA_MSG_PREVIEW_FRAME) { + int32_t previewWidth, previewHeight; + android::CameraParameters hwParameters = qCamera->getParameters(); + hwParameters.getPreviewSize(&previewWidth, &previewHeight); + CameraHAL_HandlePreviewData(dataPtr, mWindow, origCamReqMemory, + previewWidth, previewHeight); + } else if (origData_cb != NULL && origCamReqMemory != NULL) { + camera_memory_t *clientData = CameraHAL_GenClientData(dataPtr, + origCamReqMemory, user); + if (clientData != NULL) { + LOGV("CameraHAL_DataCb: Posting data to client\n"); + origData_cb(msg_type, clientData, 0, NULL, user); + } + } +} + +void +CameraHAL_DataTSCb(nsecs_t timestamp, int32_t msg_type, + const android::sp& dataPtr, void *user) +{ + LOGD("CameraHAL_DataTSCb: timestamp:%lld msg_type:%d user:%p\n", + timestamp /1000, msg_type, user); + + if (origDataTS_cb != NULL && origCamReqMemory != NULL) { + camera_memory_t *clientData = CameraHAL_GenClientData(dataPtr, + origCamReqMemory, user); + if (clientData != NULL) { + LOGV("CameraHAL_DataTSCb: Posting data to client timestamp:%lld\n", + systemTime()); + origDataTS_cb(timestamp, msg_type, clientData, 0, user); + qCamera->releaseRecordingFrame(dataPtr); + } else { + LOGD("CameraHAL_DataTSCb: ERROR allocating memory from client\n"); + } + } +} + +int +CameraHAL_GetNum_Cameras(void) +{ + LOGE("CameraHAL_GetNum_Cameras:\n"); + return 1; +} + +int +CameraHAL_GetCam_Info(int camera_id, struct camera_info *info) +{ + LOGV("CameraHAL_GetCam_Info:\n"); + info->facing = CAMERA_FACING_BACK; + info->orientation = 90; + return NO_ERROR; +} + +void +CameraHAL_FixupParams(android::CameraParameters &settings) +{ + const char *preview_sizes = + "1280x720,800x480,768x432,720x480,640x480,576x432,480x320,384x288,352x288,320x240,240x160,176x144"; + const char *video_sizes = + "1280x720,800x480,720x480,640x480,352x288,320x240,176x144"; + const char *preferred_size = "640x480"; + const char *preview_frame_rates = "30,27,24,15"; + const char *preferred_frame_rate = "15"; + + settings.set(android::CameraParameters::KEY_VIDEO_FRAME_FORMAT, + android::CameraParameters::PIXEL_FORMAT_YUV420SP); + + if (!settings.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES)) { + settings.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, + preview_sizes); + } + + if (!settings.get(android::CameraParameters::KEY_SUPPORTED_VIDEO_SIZES)) { + settings.set(android::CameraParameters::KEY_SUPPORTED_VIDEO_SIZES, + video_sizes); + } + + if (!settings.get(android::CameraParameters::KEY_VIDEO_SIZE)) { + settings.set(android::CameraParameters::KEY_VIDEO_SIZE, preferred_size); + } + + if (!settings.get(android::CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO)) { + settings.set(android::CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, + preferred_size); + } + + if (!settings.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)) { + settings.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, + preview_frame_rates); + } + + if (!settings.get(android::CameraParameters::KEY_PREVIEW_FRAME_RATE)) { + settings.set(android::CameraParameters::KEY_PREVIEW_FRAME_RATE, + preferred_frame_rate); + } +} + +/* Hardware Camera interface handlers. */ +int +qcamera_set_preview_window(struct camera_device * device, + struct preview_stream_ops *window) +{ + LOGV("qcamera_set_preview_window : Window :%p\n", window); + if (device == NULL) { + LOGE("qcamera_set_preview_window : Invalid device.\n"); + return -EINVAL; + } else { + LOGV("qcamera_set_preview_window : window :%p\n", window); + mWindow = window; + return 0; + } +} + +void +qcamera_set_callbacks(struct camera_device * device, + camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, void *user) +{ + LOGV("qcamera_set_callbacks: notify_cb: %p, data_cb: %p " + "data_cb_timestamp: %p, get_memory: %p, user :%p", + notify_cb, data_cb, data_cb_timestamp, get_memory, user); + + origNotify_cb = notify_cb; + origData_cb = data_cb; + origDataTS_cb = data_cb_timestamp; + origCamReqMemory = get_memory; + qCamera->setCallbacks(CameraHAL_NotifyCb, CameraHAL_DataCb, + CameraHAL_DataTSCb, user); +} + +void +qcamera_enable_msg_type(struct camera_device * device, int32_t msg_type) +{ + LOGV("qcamera_enable_msg_type: msg_type:%d\n", msg_type); + qCamera->enableMsgType(msg_type); +} + +void +qcamera_disable_msg_type(struct camera_device * device, int32_t msg_type) +{ + LOGV("qcamera_disable_msg_type: msg_type:%d\n", msg_type); + qCamera->disableMsgType(msg_type); +} + +int +qcamera_msg_type_enabled(struct camera_device * device, int32_t msg_type) +{ + LOGV("qcamera_msg_type_enabled: msg_type:%d\n", msg_type); + return qCamera->msgTypeEnabled(msg_type); +} + +int +qcamera_start_preview(struct camera_device * device) +{ + LOGV("qcamera_start_preview: Enabling CAMERA_MSG_PREVIEW_FRAME\n"); + + /* TODO: Remove hack. */ + qCamera->enableMsgType(CAMERA_MSG_PREVIEW_FRAME); + return qCamera->startPreview(); +} + +void +qcamera_stop_preview(struct camera_device * device) +{ + LOGV("qcamera_stop_preview:\n"); + + /* TODO: Remove hack. */ + qCamera->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); + return qCamera->stopPreview(); +} + +int +qcamera_preview_enabled(struct camera_device * device) +{ + LOGV("qcamera_preview_enabled:\n"); + return qCamera->previewEnabled() ? 1 : 0; +} + +int +qcamera_store_meta_data_in_buffers(struct camera_device * device, int enable) +{ + LOGV("qcamera_store_meta_data_in_buffers:\n"); + return NO_ERROR; +} + +int +qcamera_start_recording(struct camera_device * device) +{ + LOGV("qcamera_start_recording\n"); + + /* TODO: Remove hack. */ + qCamera->enableMsgType(CAMERA_MSG_VIDEO_FRAME); + qCamera->startRecording(); + return NO_ERROR; +} + +void +qcamera_stop_recording(struct camera_device * device) +{ + LOGV("qcamera_stop_recording:\n"); + + /* TODO: Remove hack. */ + qCamera->disableMsgType(CAMERA_MSG_VIDEO_FRAME); + qCamera->stopRecording(); +} + +int +qcamera_recording_enabled(struct camera_device * device) +{ + LOGV("qcamera_recording_enabled:\n"); + return (int)qCamera->recordingEnabled(); +} + +void +qcamera_release_recording_frame(struct camera_device * device, + const void *opaque) +{ + /* + * We release the frame immediately in CameraHAL_DataTSCb after making a + * copy. So, this is just a NOP. + */ + LOGV("qcamera_release_recording_frame: opaque:%p\n", opaque); +} + +int +qcamera_auto_focus(struct camera_device * device) +{ + LOGV("qcamera_auto_focus:\n"); + qCamera->autoFocus(); + return NO_ERROR; +} + +int +qcamera_cancel_auto_focus(struct camera_device * device) +{ + LOGV("qcamera_cancel_auto_focus:\n"); + qCamera->cancelAutoFocus(); + return NO_ERROR; +} + +int +qcamera_take_picture(struct camera_device * device) +{ + LOGV("qcamera_take_picture:\n"); + + /* TODO: Remove hack. */ + qCamera->enableMsgType(CAMERA_MSG_SHUTTER | + CAMERA_MSG_POSTVIEW_FRAME | + CAMERA_MSG_RAW_IMAGE | + CAMERA_MSG_COMPRESSED_IMAGE); + + qCamera->takePicture(); + return NO_ERROR; +} + +int +qcamera_cancel_picture(struct camera_device * device) +{ + LOGV("camera_cancel_picture:\n"); + qCamera->cancelPicture(); + return NO_ERROR; +} + +int +qcamera_set_parameters(struct camera_device * device, const char *params) +{ + LOGV("qcamera_set_parameters: %s\n", params); + g_str = android::String8(params); + camSettings.unflatten(g_str); + qCamera->setParameters(camSettings); + return NO_ERROR; +} + +char* +qcamera_get_parameters(struct camera_device * device) +{ + char *rc = NULL; + LOGV("qcamera_get_parameters\n"); + camSettings = qCamera->getParameters(); + LOGV("qcamera_get_parameters: after calling qCamera->getParameters()\n"); + CameraHAL_FixupParams(camSettings); + g_str = camSettings.flatten(); + rc = strdup((char *)g_str.string()); + LOGV("camera_get_parameters: returning rc:%p :%s\n", + rc, (rc != NULL) ? rc : "EMPTY STRING"); + return rc; +} + +void +qcamera_put_parameters(struct camera_device *device, char *params) +{ + LOGV("qcamera_put_parameters: params:%p %s", params, params); + free(params); +} + + +int +qcamera_send_command(struct camera_device * device, int32_t cmd, + int32_t arg0, int32_t arg1) +{ + LOGV("qcamera_send_command: cmd:%d arg0:%d arg1:%d\n", + cmd, arg0, arg1); + return NO_ERROR; +} + +void +qcamera_release(struct camera_device * device) +{ + LOGV("camera_release:\n"); + qCamera->release(); +} + +int +qcamera_dump(struct camera_device * device, int fd) +{ + LOGV("qcamera_dump:\n"); + android::Vector args; + return qCamera->dump(fd, args); +} + +int +camera_device_close(hw_device_t* device) +{ + int rc = -EINVAL; + LOGD("camera_device_close\n"); + camera_device_t *cameraDev = (camera_device_t *)device; + if (cameraDev) { + camera_device_ops_t *camera_ops = cameraDev->ops; + if (camera_ops) { + if (qCamera != NULL) { + qCamera.clear(); + } + free(camera_ops); + } + free(cameraDev); + rc = NO_ERROR; + } + return rc; +} + +int +qcamera_device_open(const hw_module_t* module, const char* name, + hw_device_t** device) +{ + + int cameraId = atoi(name); + + LOGD("qcamera_device_open: name:%s device:%p cameraId:%d\n", + name, device, cameraId); + + qCamera = openCameraHardware(cameraId); + camera_device_t* camera_device = NULL; + camera_device_ops_t* camera_ops = NULL; + + camera_device = (camera_device_t*)malloc(sizeof(*camera_device)); + camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops)); + memset(camera_device, 0, sizeof(*camera_device)); + memset(camera_ops, 0, sizeof(*camera_ops)); + + camera_device->common.tag = HARDWARE_DEVICE_TAG; + camera_device->common.version = 0; + camera_device->common.module = (hw_module_t *)(module); + camera_device->common.close = camera_device_close; + camera_device->ops = camera_ops; + + camera_ops->set_preview_window = qcamera_set_preview_window; + camera_ops->set_callbacks = qcamera_set_callbacks; + camera_ops->enable_msg_type = qcamera_enable_msg_type; + camera_ops->disable_msg_type = qcamera_disable_msg_type; + camera_ops->msg_type_enabled = qcamera_msg_type_enabled; + camera_ops->start_preview = qcamera_start_preview; + camera_ops->stop_preview = qcamera_stop_preview; + camera_ops->preview_enabled = qcamera_preview_enabled; + camera_ops->store_meta_data_in_buffers = qcamera_store_meta_data_in_buffers; + camera_ops->start_recording = qcamera_start_recording; + camera_ops->stop_recording = qcamera_stop_recording; + camera_ops->recording_enabled = qcamera_recording_enabled; + camera_ops->release_recording_frame = qcamera_release_recording_frame; + camera_ops->auto_focus = qcamera_auto_focus; + camera_ops->cancel_auto_focus = qcamera_cancel_auto_focus; + camera_ops->take_picture = qcamera_take_picture; + camera_ops->cancel_picture = qcamera_cancel_picture; + + camera_ops->set_parameters = qcamera_set_parameters; + camera_ops->get_parameters = qcamera_get_parameters; + camera_ops->put_parameters = qcamera_put_parameters; + camera_ops->send_command = qcamera_send_command; + camera_ops->release = qcamera_release; + camera_ops->dump = qcamera_dump; + + *device = &camera_device->common; + return NO_ERROR; +} diff --git a/libcamera-nexus.so b/libcamera-nexus.so new file mode 100644 index 0000000..71432a9 Binary files /dev/null and b/libcamera-nexus.so differ