1 /* 2 * Copyright (C) Texas Instruments - http://www.ti.com/ 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @file OMXDccDataSave.cpp 19 * 20 * This file contains functionality for handling DCC data save 21 * 22 */ 23 24 #include "CameraHal.h" 25 #include "OMXCameraAdapter.h" 26 27 28 namespace Ti { 29 namespace Camera { 30 31 status_t OMXCameraAdapter::initDccFileDataSave(OMX_HANDLETYPE* omxHandle, int portIndex) 32 { 33 OMX_CONFIG_EXTRADATATYPE extraDataControl; 34 status_t ret = NO_ERROR; 35 OMX_ERRORTYPE eError = OMX_ErrorNone; 36 37 LOG_FUNCTION_NAME; 38 39 OMX_INIT_STRUCT_PTR (&extraDataControl, OMX_CONFIG_EXTRADATATYPE); 40 extraDataControl.nPortIndex = portIndex; 41 extraDataControl.eExtraDataType = OMX_TI_DccData; 42 extraDataControl.bEnable = OMX_TRUE; 43 44 eError = OMX_SetConfig(*omxHandle, 45 ( OMX_INDEXTYPE ) OMX_IndexConfigOtherExtraDataControl, 46 &extraDataControl); 47 48 if ( OMX_ErrorNone != eError ) 49 { 50 CAMHAL_LOGEB("Error while configuring dcc data overwrite extra data 0x%x", 51 eError); 52 53 ret = NO_INIT; 54 } 55 56 if (mDccData.pData) { 57 free(mDccData.pData); 58 mDccData.pData = NULL; 59 } 60 LOG_FUNCTION_NAME_EXIT; 61 62 return ret; 63 } 64 65 status_t OMXCameraAdapter::sniffDccFileDataSave(OMX_BUFFERHEADERTYPE* pBuffHeader) 66 { 67 OMX_OTHER_EXTRADATATYPE *extraData; 68 OMX_TI_DCCDATATYPE* dccData; 69 status_t ret = NO_ERROR; 70 71 LOG_FUNCTION_NAME; 72 73 android::AutoMutex lock(mDccDataLock); 74 75 if ( NULL == pBuffHeader ) { 76 CAMHAL_LOGEA("Invalid Buffer header"); 77 LOG_FUNCTION_NAME_EXIT; 78 return -EINVAL; 79 } 80 81 extraData = getExtradata(pBuffHeader->pPlatformPrivate, 82 (OMX_EXTRADATATYPE)OMX_TI_DccData); 83 84 if ( NULL != extraData ) { 85 CAMHAL_LOGVB("Size = %d, sizeof = %d, eType = 0x%x, nDataSize= %d, nPortIndex = 0x%x, nVersion = 0x%x", 86 extraData->nSize, 87 sizeof(OMX_OTHER_EXTRADATATYPE), 88 extraData->eType, 89 extraData->nDataSize, 90 extraData->nPortIndex, 91 extraData->nVersion); 92 } else { 93 CAMHAL_LOGVA("Invalid OMX_TI_DCCDATATYPE"); 94 LOG_FUNCTION_NAME_EXIT; 95 return NO_ERROR; 96 } 97 98 dccData = ( OMX_TI_DCCDATATYPE * ) extraData->data; 99 100 if (NULL == dccData) { 101 CAMHAL_LOGVA("OMX_TI_DCCDATATYPE is not found in extra data"); 102 LOG_FUNCTION_NAME_EXIT; 103 return NO_ERROR; 104 } 105 106 if (mDccData.pData) { 107 free(mDccData.pData); 108 } 109 110 memcpy(&mDccData, dccData, sizeof(mDccData)); 111 112 int dccDataSize = (int)dccData->nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData)); 113 114 mDccData.pData = (OMX_PTR)malloc(dccDataSize); 115 116 if (NULL == mDccData.pData) { 117 CAMHAL_LOGVA("not enough memory for DCC data"); 118 LOG_FUNCTION_NAME_EXIT; 119 return NO_ERROR; 120 } 121 122 memcpy(mDccData.pData, &(dccData->pData), dccDataSize); 123 124 LOG_FUNCTION_NAME_EXIT; 125 126 return ret; 127 } 128 129 // Recursively searches given directory contents for the correct DCC file. 130 // The directory must be opened and its stream pointer + path passed 131 // as arguments. As this function is called recursively, to avoid excessive 132 // stack usage the path param is reused -> this MUST be char array with 133 // enough length!!! (260 should suffice). Path must end with "/". 134 // The directory must also be closed in the caller function. 135 // If the correct camera DCC file is found (based on the OMX measurement data) 136 // its file stream pointer is returned. NULL is returned otherwise 137 FILE * OMXCameraAdapter::parseDCCsubDir(DIR *pDir, char *path) 138 { 139 FILE *pFile; 140 DIR *pSubDir; 141 struct dirent *dirEntry; 142 int initialPathLength = strlen(path); 143 144 LOG_FUNCTION_NAME; 145 146 /* check each directory entry */ 147 while ((dirEntry = readdir(pDir)) != NULL) 148 { 149 if (dirEntry->d_name[0] == '.') 150 continue; 151 152 strcat(path, dirEntry->d_name); 153 // dirEntry might be sub directory -> check it 154 pSubDir = opendir(path); 155 if (pSubDir) { 156 // dirEntry is sub directory -> parse it 157 strcat(path, "/"); 158 pFile = parseDCCsubDir(pSubDir, path); 159 closedir(pSubDir); 160 if (pFile) { 161 // the correct DCC file found! 162 LOG_FUNCTION_NAME_EXIT; 163 return pFile; 164 } 165 } else { 166 // dirEntry is file -> open it 167 pFile = fopen(path, "rb"); 168 if (pFile) { 169 // now check if this is the correct DCC file for that camera 170 OMX_U32 dccFileIDword; 171 OMX_U32 *dccFileDesc = (OMX_U32 *) &mDccData.nCameraModuleId; 172 int i; 173 174 // DCC file ID is 3 4-byte words 175 for (i = 0; i < 3; i++) { 176 if (fread(&dccFileIDword, sizeof(OMX_U32), 1, pFile) != 1) { 177 // file too short 178 break; 179 } 180 if (dccFileIDword != dccFileDesc[i]) { 181 // DCC file ID word i does not match 182 break; 183 } 184 } 185 186 fclose(pFile); 187 if (i == 3) { 188 // the correct DCC file found! 189 CAMHAL_LOGDB("DCC file to be updated: %s", path); 190 // reopen it for modification 191 pFile = fopen(path, "rb+"); 192 if (!pFile) 193 CAMHAL_LOGEB("ERROR: DCC file %s failed to open for modification", path); 194 LOG_FUNCTION_NAME_EXIT; 195 return pFile; 196 } 197 } else { 198 CAMHAL_LOGEB("ERROR: Failed to open file %s for reading", path); 199 } 200 } 201 // restore original path 202 path[initialPathLength] = '\0'; 203 } 204 205 LOG_FUNCTION_NAME_EXIT; 206 207 // DCC file not found in this directory tree 208 return NULL; 209 } 210 211 // Finds the DCC file corresponding to the current camera based on the 212 // OMX measurement data, opens it and returns the file stream pointer 213 // (NULL on error or if file not found). 214 // The folder string dccFolderPath must end with "/" 215 FILE * OMXCameraAdapter::fopenCameraDCC(const char *dccFolderPath) 216 { 217 FILE *pFile; 218 DIR *pDir; 219 char dccPath[260]; 220 221 LOG_FUNCTION_NAME; 222 223 strcpy(dccPath, dccFolderPath); 224 225 pDir = opendir(dccPath); 226 if (!pDir) { 227 CAMHAL_LOGEB("ERROR: Opening DCC directory %s failed", dccPath); 228 LOG_FUNCTION_NAME_EXIT; 229 return NULL; 230 } 231 232 pFile = parseDCCsubDir(pDir, dccPath); 233 closedir(pDir); 234 if (pFile) { 235 CAMHAL_LOGDB("DCC file %s opened for modification", dccPath); 236 } 237 238 LOG_FUNCTION_NAME_EXIT; 239 240 return pFile; 241 } 242 243 // Positions the DCC file stream pointer to the correct offset within the 244 // correct usecase based on the OMX mesurement data. Returns 0 on success 245 status_t OMXCameraAdapter::fseekDCCuseCasePos(FILE *pFile) 246 { 247 OMX_U32 dccNumUseCases = 0; 248 OMX_U32 dccUseCaseData[3]; 249 OMX_U32 i; 250 251 LOG_FUNCTION_NAME; 252 253 // position the file pointer to the DCC use cases section 254 if (fseek(pFile, 80, SEEK_SET)) { 255 CAMHAL_LOGEA("ERROR: Unexpected end of DCC file"); 256 LOG_FUNCTION_NAME_EXIT; 257 return -EINVAL; 258 } 259 260 if (fread(&dccNumUseCases, sizeof(OMX_U32), 1, pFile) != 1 || 261 dccNumUseCases == 0) { 262 CAMHAL_LOGEA("ERROR: DCC file contains 0 use cases"); 263 LOG_FUNCTION_NAME_EXIT; 264 return -EINVAL; 265 } 266 267 for (i = 0; i < dccNumUseCases; i++) { 268 if (fread(dccUseCaseData, sizeof(OMX_U32), 3, pFile) != 3) { 269 CAMHAL_LOGEA("ERROR: Unexpected end of DCC file"); 270 LOG_FUNCTION_NAME_EXIT; 271 return -EINVAL; 272 } 273 274 if (dccUseCaseData[0] == mDccData.nUseCaseId) { 275 // DCC use case match! 276 break; 277 } 278 } 279 280 if (i == dccNumUseCases) { 281 CAMHAL_LOGEB("ERROR: Use case ID %lu not found in DCC file", mDccData.nUseCaseId); 282 LOG_FUNCTION_NAME_EXIT; 283 return -EINVAL; 284 } 285 286 // dccUseCaseData[1] is the offset to the beginning of the actual use case 287 // from the beginning of the file 288 // mDccData.nOffset is the offset within the actual use case (from the 289 // beginning of the use case to the data to be modified) 290 291 if (fseek(pFile,dccUseCaseData[1] + mDccData.nOffset, SEEK_SET )) 292 { 293 CAMHAL_LOGEA("ERROR: Error setting the correct offset"); 294 LOG_FUNCTION_NAME_EXIT; 295 return -EINVAL; 296 } 297 298 LOG_FUNCTION_NAME_EXIT; 299 300 return NO_ERROR; 301 } 302 303 status_t OMXCameraAdapter::saveDccFileDataSave() 304 { 305 status_t ret = NO_ERROR; 306 307 LOG_FUNCTION_NAME; 308 309 android::AutoMutex lock(mDccDataLock); 310 311 if (mDccData.pData) 312 { 313 FILE *fd = fopenCameraDCC(DCC_PATH); 314 315 if (fd) 316 { 317 if (!fseekDCCuseCasePos(fd)) 318 { 319 int dccDataSize = (int)mDccData.nSize - (int)(&(((OMX_TI_DCCDATATYPE*)0)->pData)); 320 321 if (fwrite(mDccData.pData, dccDataSize, 1, fd) != 1) 322 { 323 CAMHAL_LOGEA("ERROR: Writing to DCC file failed"); 324 } 325 else 326 { 327 CAMHAL_LOGDA("DCC file successfully updated"); 328 } 329 } 330 fclose(fd); 331 } 332 else 333 { 334 CAMHAL_LOGEA("ERROR: Correct DCC file not found or failed to open for modification"); 335 } 336 } 337 338 LOG_FUNCTION_NAME_EXIT; 339 340 return ret; 341 } 342 343 status_t OMXCameraAdapter::closeDccFileDataSave() 344 { 345 status_t ret = NO_ERROR; 346 347 LOG_FUNCTION_NAME; 348 349 android::AutoMutex lock(mDccDataLock); 350 351 if (mDccData.pData) { 352 free(mDccData.pData); 353 mDccData.pData = NULL; 354 } 355 LOG_FUNCTION_NAME_EXIT; 356 357 return ret; 358 } 359 360 } // namespace Camera 361 } // namespace Ti 362