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
initDccFileDataSave(OMX_HANDLETYPE * omxHandle,int portIndex)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
sniffDccFileDataSave(OMX_BUFFERHEADERTYPE * pBuffHeader)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
parseDCCsubDir(DIR * pDir,char * path)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 "/"
fopenCameraDCC(const char * dccFolderPath)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
fseekDCCuseCasePos(FILE * pFile)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
saveDccFileDataSave()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
closeDccFileDataSave()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