/*
** 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 <utils/Log.h>
#include <utils/threads.h>
#include <fcntl.h>
#include <sys/mman.h>
/* include QCamera Hardware Interface Header*/
#include "QualcommCamera.h"
#include "QualcommCameraHardware.h"
//#include <camera/CameraHardwareInterface.h>
extern "C" {
#include <sys/time.h>
}
/* 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<IMemory> 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<IMemory>& 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<IMemory>& 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