/* ** Copyright (c) 2011 The Linux Foundation. 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. */ /*#error uncomment this for compiler test!*/ //#define ALOG_NDEBUG 0 #define ALOG_NIDEBUG 0 #define LOG_TAG "QualcommCamera" #include #include #include #include /* include QCamera Hardware Interface Header*/ #include "QualcommCamera.h" #include "QualcommCameraHardware.h" //#include extern "C" { #include } /* HAL function implementation goes here*/ /** * 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. */ static hw_module_methods_t camera_module_methods = { open: camera_device_open, }; static hw_module_t camera_common = { tag: HARDWARE_MODULE_TAG, version_major: 0, version_minor: 01, id: CAMERA_HARDWARE_MODULE_ID, name: "Qcamera", author:"Qcom", methods: &camera_module_methods, dso: NULL, //reserved[0]: 0, }; camera_module_t HAL_MODULE_INFO_SYM = { common: camera_common, get_number_of_cameras: get_number_of_cameras, get_camera_info: get_camera_info, }; camera_device_ops_t camera_ops = { set_preview_window: android::set_preview_window, set_callbacks: android::set_callbacks, enable_msg_type: android::enable_msg_type, disable_msg_type: android::disable_msg_type, msg_type_enabled: android::msg_type_enabled, start_preview: android::start_preview, stop_preview: android::stop_preview, preview_enabled: android::preview_enabled, store_meta_data_in_buffers: android::store_meta_data_in_buffers, start_recording: android::start_recording, stop_recording: android::stop_recording, recording_enabled: android::recording_enabled, release_recording_frame: android::release_recording_frame, auto_focus: android::auto_focus, cancel_auto_focus: android::cancel_auto_focus, take_picture: android::take_picture, cancel_picture: android::cancel_picture, set_parameters: android::set_parameters, get_parameters: android::get_parameters, put_parameters: android::put_parameters, send_command: android::send_command, release: android::release, dump: android::dump, }; namespace android { typedef struct { QualcommCameraHardware *hardware; int camera_released; QCameraParameters parameters; #if 1 camera_notify_callback notify_cb; camera_data_callback data_cb; camera_data_timestamp_callback data_cb_timestamp; camera_request_memory get_memory; void *user_data; #endif } camera_hardware_t; typedef struct { camera_memory_t mem; int32_t msgType; sp dataPtr; void* user; unsigned int index; } q_cam_memory_t; static void camera_release_memory(struct camera_memory *mem) { } void cam_notify_callback(int32_t msgType, int32_t ext1, int32_t ext2, void* user) { ALOGV("Q%s: E", __func__); camera_device * device = (camera_device *)user; if(device) { camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal) { camera_notify_callback notify_cb = camHal->notify_cb; void *user_data = camHal->user_data; if(notify_cb) { notify_cb(msgType, ext1, ext2, user_data); } } } } camera_memory_t* get_mem(int fd,size_t buf_size, unsigned int num_bufs, void *user) { ALOGV("Q%s: E", __func__); camera_device * device = (camera_device *)user; if(device) { camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal) { camera_request_memory getmem_cb = camHal->get_memory; void *user_data = camHal->user_data; if(getmem_cb) { return getmem_cb(fd, buf_size, num_bufs, user_data); } } } return NULL; } #if 0 void native_send_data_callback(int32_t msgType, camera_memory_t * framebuffer, void* user) { ALOGE("Q%s: E", __func__); static unsigned int counter = 0; #if 0 camera_device * device = (camera_device *)user; if(device) { camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal) { camera_data_callback data_cb = camHal->data_cb; void *user_data = camHal->user_data; if(data_cb) { q_cam_memory_t *qmem = (q_cam_memory_t *)malloc(sizeof(q_cam_memory_t)); if (qmem) { qmem->dataPtr = dataPtr; qmem->mem.data = (void *)((int)dataPtr->pointer() + dataPtr->offset()); qmem->mem.handle = NULL; //(void *)dataPtr->getHeapID(); qmem->mem.size = dataPtr->size( ); qmem->mem.release = camera_release_memory; qmem->msgType = msgType; qmem->index = counter; #endif data_cb(msgType, framebuffer, counter, NULL, user); counter++; #if 0 } else { ALOGE("%s: out of memory", __func__); } #endif // } // } // } } #endif static void cam_data_callback(int32_t msgType, const sp& dataPtr, void* user) { ALOGV("Q%s: E", __func__); static unsigned int counter = 0; camera_device * device = (camera_device *)user; if(device) { camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal) { camera_data_callback data_cb = camHal->data_cb; void *user_data = camHal->user_data; if(data_cb) { q_cam_memory_t *qmem = (q_cam_memory_t *)malloc(sizeof(q_cam_memory_t)); if (qmem) { qmem->dataPtr = dataPtr; qmem->mem.data = (void *)((int)dataPtr->pointer() + dataPtr->offset()); qmem->mem.handle = NULL; //(void *)dataPtr->getHeapID(); qmem->mem.size = dataPtr->size( ); qmem->mem.release = camera_release_memory; qmem->msgType = msgType; qmem->index = counter; counter++; data_cb(msgType, (camera_memory_t *)qmem, counter, NULL, user_data); } else { ALOGE("%s: out of memory", __func__); } } } } } static void cam_data_callback_timestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr, void* user) { ALOGV("Q%s: E", __func__); static unsigned int counter = 0; camera_device * device = (camera_device *)user; if(device) { camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal) { camera_data_timestamp_callback data_cb_timestamp = camHal->data_cb_timestamp; void *user_data = camHal->user_data; if(data_cb_timestamp) { q_cam_memory_t *qmem = (q_cam_memory_t *)malloc(sizeof(q_cam_memory_t)); if (qmem) { qmem->dataPtr = dataPtr; qmem->mem.data = (void *)((int)dataPtr->pointer() + dataPtr->offset()); qmem->mem.handle = NULL; //(void *)dataPtr->getHeapID(); qmem->mem.size = dataPtr->size( ); qmem->mem.release = camera_release_memory; qmem->msgType = msgType; qmem->index = counter; counter++; data_cb_timestamp(timestamp, msgType, (camera_memory_t *)qmem, counter, user_data); } else { ALOGE("%s: out of memory", __func__); } } } } } QualcommCameraHardware * util_get_Hal_obj( struct camera_device * device) { QualcommCameraHardware* hardware = NULL; if(device && device->priv){ camera_hardware_t *camHal = (camera_hardware_t *)device->priv; hardware = camHal->hardware; } return hardware; } void close_Hal_obj( struct camera_device * device) { ALOGV("%s: E", __func__); QualcommCameraHardware* hardware = NULL; if(device && device->priv){ camera_hardware_t *camHal = (camera_hardware_t *)device->priv; ALOGI("%s: clear hw", __func__); hardware = camHal->hardware; delete hardware; } ALOGV("%s: X", __func__); } QCameraParameters* util_get_HAL_parameter( struct camera_device * device) { QCameraParameters *param = NULL; if(device && device->priv){ camera_hardware_t *camHal = (camera_hardware_t *)device->priv; param = &(camHal->parameters); } return param; } extern "C" int get_number_of_cameras() { /* try to query every time we get the call!*/ ALOGV("Q%s: E", __func__); return android::HAL_getNumberOfCameras( ); } extern "C" int get_camera_info(int camera_id, struct camera_info *info) { int rc = -1; ALOGV("Q%s: E", __func__); if(info) { struct CameraInfo camInfo; memset(&camInfo, -1, sizeof (struct CameraInfo)); HAL_getCameraInfo(camera_id, &camInfo); if (camInfo.facing >= 0) { rc = 0; info->facing = camInfo.facing; info->orientation = camInfo.orientation; } } ALOGV("Q%s: X", __func__); return rc; } /* HAL should return NULL if it fails to open camera hardware. */ extern "C" int camera_device_open( const struct hw_module_t* module, const char* id, struct hw_device_t** hw_device) { ALOGV("Q%s: E", __func__); int rc = -1; camera_device *device = NULL; if(module && id && hw_device) { int cameraId = atoi(id); if (!strcmp(module->name, camera_common.name)) { device = (camera_device *)malloc(sizeof (struct camera_device)); if(device) { camera_hardware_t *camHal = (camera_hardware_t *) malloc(sizeof (camera_hardware_t)); if(camHal) { memset(camHal, 0, sizeof (camera_hardware_t)); camHal->hardware = HAL_openCameraHardware(cameraId); if (camHal->hardware != NULL) { /*To Do: populate camHal*/ device->common.close = close_camera_device; device->ops = &camera_ops; device->priv = (void *)camHal; rc = 0; } else { free(camHal); free (device); device = NULL; } } else { free (device); device = NULL; } } } } *hw_device = (hw_device_t*)device; return rc; } extern "C" int close_camera_device( hw_device_t *hw_dev) { ALOGV("Q%s: device =%p E", __func__, hw_dev); int rc = -1; camera_device_t *device = (camera_device_t *)hw_dev; if(device) { camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal ) { //if(!camHal->camera_released) { QualcommCameraHardware* hardware = util_get_Hal_obj( device); if(hardware != NULL) { if(camHal->camera_released != true) hardware->release( ); //hardware.clear( ); } //} close_Hal_obj(device); free(device->priv); device->priv = NULL; } free(device); rc = 0; } return rc; } int set_preview_window(struct camera_device * device, struct preview_stream_ops *window) { ALOGV("Q%s: E window = %p", __func__, window); int rc = -1; QualcommCameraHardware *hardware = util_get_Hal_obj(device); if(hardware != NULL) { rc = hardware->set_PreviewWindow((void *)window); } return rc; } void 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) { ALOGV("Q%s: E", __func__); QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ camera_hardware_t *camHal = (camera_hardware_t *)device->priv; if(camHal) { camera_notify_callback cam_nt_cb; camera_data_callback cam_dt_cb; camera_data_timestamp_callback cam_dt_timestamp_cb; camHal->notify_cb = notify_cb; camHal->data_cb = data_cb; camHal->data_cb_timestamp = data_cb_timestamp; camHal->user_data = user; camHal->get_memory = get_memory; #if 0 if(notify_cb) { cam_nt_cb = cam_notify_callback; } else { cam_nt_cb = NULL; } if(data_cb) { cam_dt_cb = cam_data_callback; } else { cam_dt_cb = NULL; } if(data_cb_timestamp) { cam_dt_timestamp_cb = cam_data_callback_timestamp; } else { cam_dt_timestamp_cb = NULL; } #endif ALOGV("cam_nt_cb =%p,cam_dt_cb=%p,cam_dt_timestamp_cb=%p", cam_nt_cb, cam_dt_cb, cam_dt_timestamp_cb); hardware->setCallbacks(notify_cb,data_cb,data_cb_timestamp,get_memory, user); } } } void enable_msg_type(struct camera_device * device, int32_t msg_type) { QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ hardware->enableMsgType(msg_type); } } void disable_msg_type(struct camera_device * device, int32_t msg_type) { QualcommCameraHardware * hardware = util_get_Hal_obj(device); ALOGV("Q%s: E", __func__); if(hardware != NULL){ hardware->disableMsgType(msg_type); } } int msg_type_enabled(struct camera_device * device, int32_t msg_type) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->msgTypeEnabled(msg_type); } return rc; } int start_preview(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->startPreview( ); } ALOGV("Q%s: X", __func__); return rc; } void stop_preview(struct camera_device * device) { ALOGV("Q%s: E", __func__); QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ hardware->stopPreview( ); } } int preview_enabled(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware* hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->previewEnabled( ); } return rc; } int store_meta_data_in_buffers(struct camera_device * device, int enable) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->storeMetaDataInBuffers( enable); } return rc; } int start_recording(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->startRecording( ); } return rc; } void stop_recording(struct camera_device * device) { ALOGV("Q%s: E", __func__); QualcommCameraHardware* hardware = util_get_Hal_obj(device); if(hardware != NULL){ hardware->stopRecording( ); } } int recording_enabled(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->recordingEnabled( ); } return rc; } void release_recording_frame(struct camera_device * device, const void *opaque) { ALOGV("Q%s: E", __func__); QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ hardware->releaseRecordingFrame( opaque); } } int auto_focus(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->autoFocus( ); } return rc; } int cancel_auto_focus(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->cancelAutoFocus( ); } return rc; } int take_picture(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->takePicture( ); } return rc; } int cancel_picture(struct camera_device * device) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->cancelPicture( ); } return rc; } QCameraParameters g_param; String8 g_str; int set_parameters(struct camera_device * device, const char *parms) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL && parms){ // = util_get_HAL_parameter(device); g_str = String8(parms); g_param.unflatten(g_str); rc = hardware->setParameters( g_param ); } return rc; } char* get_parameters(struct camera_device * device) { ALOGV("Q%s: E", __func__); char* rc = NULL; QCameraParameters param; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ g_param = hardware->getParameters( ); g_str = g_param.flatten( ); rc = (char *)g_str.string( ); if (!rc) { ALOGE("get_parameters: NULL string"); } else { //ALOGE("get_parameters: %s", rc); } } ALOGV("get_parameters X"); return rc; } void put_parameters(struct camera_device * device, char *parm) { ALOGV("Q%s: E", __func__); QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ if(hardware != NULL){ //rc = hardware->putParameters(parm ); } } ALOGV("put_parameters X"); } int send_command(struct camera_device * device, int32_t cmd, int32_t arg1, int32_t arg2) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ rc = hardware->sendCommand( cmd, arg1, arg2); } return rc; } void release(struct camera_device * device) { ALOGV("Q%s: E", __func__); QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ camera_hardware_t *camHal = (camera_hardware_t *)device->priv; hardware->release( ); camHal->camera_released = true; } } int dump(struct camera_device * device, int fd) { ALOGV("Q%s: E", __func__); int rc = -1; QualcommCameraHardware * hardware = util_get_Hal_obj(device); if(hardware != NULL){ //rc = hardware->dump( fd ); rc = 0; } return rc; } }; // namespace android