/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//#define ALOG_NDEBUG 0
#define ALOG_NIDEBUG 0
#define LOG_TAG "QCameraUsbParm"
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/String16.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <cutils/properties.h>
#include <math.h>
#if HAVE_ANDROID_OS
#include <linux/android_pmem.h>
#endif
#include <linux/ioctl.h>
#include <camera/QCameraParameters.h>
#include <media/mediarecorder.h>
#include <gralloc_priv.h>
#include "linux/msm_mdp.h"
#include <linux/fb.h>
#include <limits.h>
extern "C" {
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/system_properties.h>
#include <sys/time.h>
#include <stdlib.h>
#include <linux/msm_ion.h>
#include <camera.h>
#include <cam_fifo.h>
#include <jpege.h>
} // extern "C"
#include "QCameraHWI.h"
#include "QualcommUsbCamera.h"
#include "QCameraUsbPriv.h"
#include "QCameraUsbParm.h"
namespace android {
/********************************************************************/
static const str_map preview_formats[] = {
{QCameraParameters::PIXEL_FORMAT_YUV420SP, HAL_PIXEL_FORMAT_YCrCb_420_SP},
};
static const preview_format_info_t preview_format_info_list[] = {
{HAL_PIXEL_FORMAT_YV12, CAMERA_YUV_420_YV12, CAMERA_PAD_TO_WORD, 3}
};
static struct camera_size_type previewSizes[] = {
{ 1920, 1088}, //1080p
{ 1280, 720}, // 720P,
{ 640, 480}, // VGA
{ 512, 384},
{ 480, 320},
{ 320, 240}, // QVGA
};
// All fps ranges which can be supported. This list will be filtered according
// to the min and max fps supported by hardware
// this list must be sorted first by max_fps and then min_fps
// fps values are multiplied by 1000
static android::FPSRange prevFpsRanges[] = {
android::FPSRange(5000, 121000),
};
/* TBR: Is frame rate mode mandatory */
static const str_map frame_rate_modes[] = {
{QCameraParameters::KEY_QC_PREVIEW_FRAME_RATE_AUTO_MODE, FPS_MODE_AUTO},
{QCameraParameters::KEY_QC_PREVIEW_FRAME_RATE_FIXED_MODE, FPS_MODE_FIXED}
};
static const str_map picture_formats[] = {
{QCameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
//{QCameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
};
static camera_size_type picture_sizes[] = {
{ 1920, 1088}, //HD1080
{ 1280, 720}, //HD720
{ 640, 480}, // VGA
{ 320, 240}, // QVGA
};
/* aspect ratio removed */
static camera_size_type thumbnail_sizes[] = {
{ 512, 288 }, //1.777778
{ 480, 288 }, //1.666667
{ 256, 154 }, //1.66233
{ 432, 288 }, //1.5
{ 512, 384 }, //1.333333
{ 352, 288 }, //1.222222
{ 320, 240 }, //1.33333
{ 176, 144 }, //1.222222
};
static const str_map recording_Hints[] = {
{"false", FALSE},
{"true", TRUE}
};
/* Static functions list */
static String8 create_sizes_str(const camera_size_type *sizes, int len);
static String8 create_values_str(const str_map *values, int len);
static String8 create_fps_str(const android:: FPSRange* fps, int len);
static String8 create_values_range_str(int min, int max);
static int usbCamSetPrvwSize( camera_hardware_t *camHal,
const QCameraParameters& params);
static int usbCamSetPictSize( camera_hardware_t *camHal,
const QCameraParameters& params);
static int usbCamSetThumbnailSize( camera_hardware_t *camHal,
const QCameraParameters& params);
static int usbCamSetJpegQlty( camera_hardware_t *camHal,
const QCameraParameters& params);
/******************************************************************************
* Function: usbCamInitDefaultParameters
* Description: This function sets default parameters to camera HAL context
*
* Input parameters:
* camHal - camera HAL handle
*
* Return values:
* None
*
* Notes: none
*****************************************************************************/
int usbCamInitDefaultParameters(camera_hardware_t *camHal)
{
ALOGD("%s: E", __func__);
int rc = 0;
char tempStr[FILENAME_LENGTH];
/* Default initializations */
camHal->prevFormat = DEFAULT_USBCAM_PRVW_FMT;
camHal->prevWidth = DEFAULT_USBCAM_PRVW_WD;
camHal->prevHeight = DEFAULT_USBCAM_PRVW_HT;
camHal->dispFormat = camHal->prevFormat;
camHal->dispWidth = camHal->prevWidth;
camHal->dispHeight = camHal->prevHeight;
camHal->pictFormat = DEFAULT_USBCAM_PICT_FMT;
camHal->pictWidth = DEFAULT_USBCAM_PICT_WD;
camHal->pictHeight = DEFAULT_USBCAM_PICT_HT;
camHal->pictJpegQlty = DEFAULT_USBCAM_PICT_QLTY;
camHal->thumbnailWidth = DEFAULT_USBCAM_THUMBNAIL_WD;
camHal->thumbnailHeight = DEFAULT_USBCAM_THUMBNAIL_HT;
camHal->thumbnailJpegQlty = DEFAULT_USBCAM_THUMBNAIL_QLTY;
camHal->previewEnabledFlag = 0;
camHal->prvwStoppedForPicture = 0;
camHal->prvwCmdPending = 0;
camHal->takePictInProgress = 0;
//Set picture size values
camHal->pictSizeValues = create_sizes_str(
picture_sizes, sizeof(picture_sizes) / sizeof(camera_size_type));
camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
camHal->pictSizeValues.string());
camHal->qCamParams.setPictureSize(camHal->pictWidth, camHal->pictHeight);
//Set picture format
camHal->pictFormatValues = create_values_str(
picture_formats, sizeof(picture_formats) / sizeof(str_map));
camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
camHal->pictFormatValues.string());
if(PICTURE_FORMAT_JPEG == camHal->pictFormat)
camHal->qCamParams.setPictureFormat(QCameraParameters::PIXEL_FORMAT_JPEG);
//Set picture quality
sprintf(tempStr, "%d", camHal->pictJpegQlty);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_QUALITY, tempStr);
//Set Thumbnail size
camHal->thumbnailSizeValues = create_sizes_str(
thumbnail_sizes, sizeof(thumbnail_sizes) /sizeof(camera_size_type));
camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
camHal->thumbnailSizeValues.string());
sprintf(tempStr, "%d", camHal->thumbnailWidth);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
tempStr);
sprintf(tempStr, "%d", camHal->thumbnailHeight);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
tempStr);
//Set Thumbnail quality
sprintf(tempStr, "%d", camHal->thumbnailJpegQlty);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
tempStr);
//Set Preview Format
camHal->prevFormatValues = create_values_str(
preview_formats, sizeof(preview_formats) / sizeof(str_map));
camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
camHal->prevFormatValues.string());
if(HAL_PIXEL_FORMAT_YCrCb_420_SP == camHal->prevFormat)
camHal->qCamParams.setPreviewFormat(QCameraParameters::PIXEL_FORMAT_YUV420SP);
//Set Preview size
camHal->prevSizeValues = create_sizes_str(
previewSizes, sizeof(previewSizes) / sizeof(camera_size_type));
camHal->qCamParams.set(QCameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
camHal->prevSizeValues.string());
camHal->qCamParams.setPreviewSize(camHal->prevWidth, camHal->prevHeight);
//Set Preivew fps range
camHal->prevFpsRangesValues = create_fps_str(
prevFpsRanges, sizeof(prevFpsRanges) / sizeof(android::FPSRange));
camHal->qCamParams.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
camHal->prevFpsRangesValues);
camHal->qCamParams.setPreviewFpsRange(MIN_PREV_FPS, MAX_PREV_FPS);
ALOGD("%s: X", __func__);
return rc;
} /* usbCamInitDefaultParameters */
/******************************************************************************
* Function: usbCamSetParameters
* Description: This function parses the parameter string and stores the
* parameters in the camera HAL handle
*
* Input parameters:
* camHal - camera HAL handle
* params - pointer to parameter string
*
* Return values:
* 0 Success
* -1 Error
* Notes: none
*****************************************************************************/
int usbCamSetParameters(camera_hardware_t *camHal, const char *params)
{
int rc = 0;
String8 str = String8(params);
QCameraParameters qParam;
ALOGD("%s: E", __func__);
if(params)
PRINT_PARAM_STR(params);
qParam.unflatten(str);
if(usbCamSetPrvwSize(camHal, qParam))
rc = -1;
if(usbCamSetPictSize(camHal, qParam))
rc = -1;
if(usbCamSetThumbnailSize(camHal, qParam))
rc = -1;
if(usbCamSetJpegQlty(camHal, qParam))
rc = -1;
ALOGD("%s: X", __func__);
return rc;
} /* usbCamSetParameters */
/******************************************************************************
* Function: usbCamGetParameters
* Description: This function allocates memory for parameter string,
* composes and returns the parameter string
*
* Input parameters:
* camHal - camera HAL handle
*
* Return values:
* Address to the parameter string
*
* Notes: none
*****************************************************************************/
char* usbCamGetParameters(camera_hardware_t *camHal)
{
ALOGD("%s: E", __func__);
char *parms = NULL;
char* rc = NULL;
String8 str;
QCameraParameters qParam = camHal->qCamParams;
//qParam.dump();
str = qParam.flatten( );
rc = (char *)malloc(sizeof(char)*(str.length()+1));
if(rc != NULL){
memset(rc, 0, sizeof(char)*(str.length()+1));
strncpy(rc, str.string(), str.length());
rc[str.length()] = 0;
parms = rc;
}
PRINT_PARAM_STR(parms);
ALOGD("%s: X", __func__);
return (parms);
} /* usbCamGetParameters */
/******************************************************************************
* Function: usbCamPutParameters
* Description: This function frees the memory allocated for parameter string
*
* Input parameters:
* camHal - camera HAL handle
* parms - Parameter string
*
* Return values:
* None
*
* Notes: none
*****************************************************************************/
void usbCamPutParameters(camera_hardware_t *camHal, char *parms)
{
ALOGD("%s: E", __func__);
if(parms)
free(parms);
parms = NULL;
ALOGD("%s: X", __func__);
} /* usbCamPutParameters */
/******************************************************************************
* Function: create_sizes_str
* Description: This function loops through /dev/video entries and probes with
* UVCIOC query. If the device responds to the query, then it is
* detected as UVC webcam
* Input parameters:
* devname - String pointer. The function return dev entry
* name in this string
* Return values:
* 0 Success
* -1 Error
* Notes: none
*****************************************************************************/
static String8 create_sizes_str(const camera_size_type *sizes, int len) {
String8 str;
char buffer[32];
if (len > 0) {
snprintf(buffer, sizeof(buffer), "%dx%d", sizes[0].width, sizes[0].height);
str.append(buffer);
}
for (int i = 1; i < len; i++) {
snprintf(buffer, sizeof(buffer), ",%dx%d", sizes[i].width, sizes[i].height);
str.append(buffer);
}
return str;
}
/******************************************************************************
* Function: create_values_str
* Description: This function loops through /dev/video entries and probes with
* UVCIOC query. If the device responds to the query, then it is
* detected as UVC webcam
* Input parameters:
* devname - String pointer. The function return dev entry
* name in this string
* Return values:
* 0 Success
* -1 Error
* Notes: none
*****************************************************************************/
static String8 create_values_str(const str_map *values, int len) {
String8 str;
if (len > 0) {
str.append(values[0].desc);
}
for (int i = 1; i < len; i++) {
str.append(",");
str.append(values[i].desc);
}
return str;
}
/******************************************************************************
* Function: create_fps_str
* Description: This function loops through /dev/video entries and probes with
* UVCIOC query. If the device responds to the query, then it is
* detected as UVC webcam
* Input parameters:
* devname - String pointer. The function return dev entry
* name in this string
* Return values:
* 0 Success
* -1 Error
* Notes: none
*****************************************************************************/
static String8 create_fps_str(const android:: FPSRange* fps, int len) {
String8 str;
char buffer[32];
if (len > 0) {
snprintf(buffer, sizeof(buffer), "(%d,%d)", fps[0].minFPS, fps[0].maxFPS);
str.append(buffer);
}
for (int i = 1; i < len; i++) {
snprintf(buffer, sizeof(buffer), ",(%d,%d)", fps[i].minFPS, fps[i].maxFPS);
str.append(buffer);
}
return str;
}
/******************************************************************************
* Function: create_values_range_str
* Description: This function loops through /dev/video entries and probes with
* UVCIOC query. If the device responds to the query, then it is
* detected as UVC webcam
* Input parameters:
* devname - String pointer. The function return dev entry
* name in this string
* Return values:
* 0 Success
* -1 Error
* Notes: none
*****************************************************************************/
static String8 create_values_range_str(int min, int max){
String8 str;
char buffer[32];
if(min <= max){
snprintf(buffer, sizeof(buffer), "%d", min);
str.append(buffer);
for (int i = min + 1; i <= max; i++) {
snprintf(buffer, sizeof(buffer), ",%d", i);
str.append(buffer);
}
}
return str;
}
/******************************************************************************
* Function: usbCamSetPrvwSize
* Description: This function parses preview width and height from the input
* parameters and stores into the context
*
* Input parameters:
* camHal - camera HAL handle
* params - QCameraParameters reference
*
* Return values:
* 0 If parameters are valid
* -1 If parameters are invalid
*
* Notes: none
*****************************************************************************/
static int usbCamSetPrvwSize( camera_hardware_t *camHal,
const QCameraParameters& params)
{
int rc = 0, width, height, i, numPrvwSizes, validSize;
ALOGD("%s: E", __func__);
params.getPreviewSize(&width, &height);
ALOGI("%s: Requested preview size %d x %d", __func__, width, height);
// Validate the preview size
numPrvwSizes = sizeof(previewSizes) / sizeof(camera_size_type);
for (i = 0, validSize = 0; i < numPrvwSizes; i++) {
if (width == previewSizes[i].width
&& height == previewSizes[i].height) {
validSize = 1;
camHal->qCamParams.setPreviewSize(width, height);
ALOGD("%s: setPreviewSize: width: %d height: %d",
__func__, width, height);
camHal->prevWidth = width;
camHal->prevHeight = height;
camHal->dispWidth = width;
camHal->dispHeight = height;
/* TBD: restrict pictures size and video to preview size */
}
}
if(!validSize)
ALOGE("%s: Invalid preview size %dx%d requested", __func__,
width, height);
rc = (validSize == 0)? -1:0;
ALOGD("%s: X", __func__);
return rc;
} /* usbCamSetPrvwSize */
/******************************************************************************
* Function: usbCamSetPictSize
* Description: This function parses picture width and height from the input
* parameters and stores into the context
*
* Input parameters:
* camHal - camera HAL handle
* params - QCameraParameters reference
*
* Return values:
* 0 If parameters are valid
* -1 If parameters are invalid
*
* Notes: none
*****************************************************************************/
static int usbCamSetPictSize( camera_hardware_t *camHal,
const QCameraParameters& params)
{
int rc = 0, width, height, i, numPictSizes, validSize;
ALOGD("%s: E", __func__);
/* parse for picture width and height */
params.getPictureSize(&width, &height);
ALOGI("%s: Requested picture size %d x %d", __func__, width, height);
// Validate the picture size
numPictSizes = sizeof(picture_sizes) / sizeof(camera_size_type);
for (i = 0, validSize = 0; i < numPictSizes; i++) {
if (width == picture_sizes[i].width
&& height == picture_sizes[i].height) {
validSize = 1;
camHal->qCamParams.setPictureSize(width, height);
ALOGD("%s: setPictureSize: width: %d height: %d",
__func__, width, height);
/* TBD: If new pictSize is different from old size, restart prvw */
camHal->pictWidth = width;
camHal->pictHeight = height;
}
}
if(!validSize)
ALOGE("%s: Invalid picture size %dx%d requested", __func__,
width, height);
rc = (validSize == 0)? -1:0;
ALOGD("%s: X", __func__);
return rc;
} /* usbCamSetPictSize */
/******************************************************************************
* Function: usbCamSetThumbnailSize
* Description: This function parses picture width and height from the input
* parameters and stores into the context
*
* Input parameters:
* camHal - camera HAL handle
* params - QCameraParameters reference
*
* Return values:
* 0 If parameters are valid
* -1 If parameters are invalid
*
* Notes: none
*****************************************************************************/
static int usbCamSetThumbnailSize( camera_hardware_t *camHal,
const QCameraParameters& params)
{
int rc = 0, width, height, i, numThumbnailSizes, validSize;
char tempStr[FILENAME_LENGTH];
ALOGD("%s: E", __func__);
/* parse for thumbnail width and height */
width = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
height = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
ALOGI("%s: Requested thumbnail size %d x %d", __func__, width, height);
// Validate the thumbnail size
numThumbnailSizes = sizeof(thumbnail_sizes) / sizeof(camera_size_type);
for (i = 0, validSize = 0; i < numThumbnailSizes; i++) {
if (width == thumbnail_sizes[i].width
&& height == thumbnail_sizes[i].height) {
validSize = 1;
camHal->thumbnailWidth = width;
camHal->thumbnailHeight = height;
sprintf(tempStr, "%d", camHal->thumbnailWidth);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
width);
sprintf(tempStr, "%d", camHal->thumbnailHeight);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
height);
}
}
if(!validSize)
ALOGE("%s: Invalid picture size %dx%d requested", __func__,
width, height);
rc = (validSize == 0)? -1:0;
ALOGD("%s: X", __func__);
return rc;
} /* usbCamSetThumbnailSize */
/******************************************************************************
* Function: usbCamSetJpegQlty
* Description: This function parses picture and thumbnail JPEG quality and
* validates before storing in the context
*
* Input parameters:
* camHal - camera HAL handle
* params - QCameraParameters reference
*
* Return values:
* 0 If parameters are valid
* -1 If parameters are invalid
*
* Notes: none
*****************************************************************************/
static int usbCamSetJpegQlty( camera_hardware_t *camHal,
const QCameraParameters& params)
{
int rc = 0, quality = 0;
char tempStr[FILENAME_LENGTH];
ALOGD("%s: E", __func__);
/**/
quality = params.getInt(QCameraParameters::KEY_JPEG_QUALITY);
ALOGI("%s: Requested picture qlty %d", __func__, quality);
if (quality >= 0 && quality <= 100) {
camHal->pictJpegQlty = quality;
sprintf(tempStr, "%d", camHal->pictJpegQlty);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_QUALITY, quality);
} else {
ALOGE("Invalid jpeg quality=%d", quality);
rc = -1;
}
quality = params.getInt(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
ALOGI("%s: Requested thumbnail qlty %d", __func__, quality);
if (quality >= 0 && quality <= 100) {
camHal->thumbnailJpegQlty = quality;
sprintf(tempStr, "%d", camHal->thumbnailJpegQlty);
camHal->qCamParams.set(QCameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
tempStr);
} else {
ALOGE("Invalid jpeg thumbnail quality=%d", quality);
rc = -1;
}
ALOGD("%s: X rc:%d", __func__, rc);
return rc;
}
}; /*namespace android */