OMXFocus.cpp revision 85c859b69b3c003b8db810371e24fe41599fc7de
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/**
19* @file OMXFocus.cpp
20*
21* This file contains functionality for handling focus configurations.
22*
23*/
24
25#undef LOG_TAG
26
27#define LOG_TAG "CameraHAL"
28
29#include "CameraHal.h"
30#include "OMXCameraAdapter.h"
31#include "ErrorUtils.h"
32
33#define TOUCH_FOCUS_RANGE 0xFF
34#define AF_CALLBACK_TIMEOUT 10000000 //10 seconds timeout
35
36namespace android {
37
38status_t OMXCameraAdapter::setParametersFocus(const CameraParameters &params,
39                                              BaseCameraAdapter::AdapterState state)
40{
41    status_t ret = NO_ERROR;
42    const char *str = NULL;
43
44    LOG_FUNCTION_NAME;
45
46    str = params.get(CameraParameters::KEY_FOCUS_AREAS);
47    mFocusAreas.clear();
48    if ( NULL != str ) {
49        ret = CameraArea::parseFocusArea(str, strlen(str), mFocusAreas);
50    }
51
52    if ( NO_ERROR == ret ) {
53        if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) {
54            CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d",
55                         MAX_FOCUS_AREAS,
56                         mFocusAreas.size());
57            ret = -EINVAL;
58        }
59    }
60
61    LOG_FUNCTION_NAME;
62
63    return ret;
64}
65
66status_t OMXCameraAdapter::doAutoFocus()
67{
68    status_t ret = NO_ERROR;
69    OMX_ERRORTYPE eError = OMX_ErrorNone;
70    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
71    OMX_PARAM_FOCUSSTATUSTYPE focusStatus;
72
73    LOG_FUNCTION_NAME;
74
75    if ( OMX_StateExecuting != mComponentState )
76        {
77        CAMHAL_LOGEA("OMX component not in executing state");
78        returnFocusStatus(false);
79        return NO_INIT;
80        }
81
82    if ( 0 != mDoAFSem.Count() )
83        {
84        CAMHAL_LOGEB("Error mDoAFSem semaphore count %d", mDoAFSem.Count());
85        return NO_INIT;
86        }
87
88    // If the app calls autoFocus, the camera will stop sending face callbacks.
89    pauseFaceDetection(true);
90
91    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
92    focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
93
94    //In case we have CAF running we should first check the AF status.
95    //If it has managed to lock, then do as usual and return status
96    //immediately. If lock is not available, then switch temporarily
97    //to 'autolock' and do normal AF.
98    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
99//FIXME: The CAF seems to return focus failure all the time.
100// Probably this is tuning related, disable this until the
101// MMS IQ team fixes it
102#if 0
103        ret = checkFocus(&focusStatus);
104#else
105        ret = NO_ERROR;
106        focusStatus.eFocusStatus = OMX_FocusStatusReached;
107#endif
108        if ( NO_ERROR != ret ) {
109            CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
110            return ret;
111        } else {
112            CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
113        }
114
115        if ( OMX_FocusStatusReached != focusStatus.eFocusStatus ) {
116            focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock;
117        }
118    }
119
120    if ( ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
121         ( focusControl.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
122                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
123
124        ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
125                                    (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
126                                    OMX_ALL,
127                                    OMX_IndexConfigCommonFocusStatus,
128                                    mDoAFSem);
129
130        if ( NO_ERROR == ret ) {
131            ret = setFocusCallback(true);
132        }
133
134    }
135
136    eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
137                            OMX_IndexConfigFocusControl,
138                            &focusControl);
139
140    if ( OMX_ErrorNone != eError ) {
141        CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
142        return INVALID_OPERATION;
143    } else {
144        CAMHAL_LOGDA("Autofocus started successfully");
145    }
146
147    if ( ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
148         ( focusControl.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
149                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
150        ret = mDoAFSem.WaitTimeout(AF_CALLBACK_TIMEOUT);
151        //Disable auto focus callback from Ducati
152        setFocusCallback(false);
153        //Signal a dummy AF event so that in case the callback from ducati
154        //does come then it doesnt crash after
155        //exiting this function since eventSem will go out of scope.
156        if(ret != NO_ERROR) {
157            CAMHAL_LOGEA("Autofocus callback timeout expired");
158            SignalEvent(mCameraAdapterParameters.mHandleComp,
159                                        (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
160                                        OMX_ALL,
161                                        OMX_IndexConfigCommonFocusStatus,
162                                        NULL );
163            returnFocusStatus(true);
164        } else {
165            CAMHAL_LOGDA("Autofocus callback received");
166            ret = returnFocusStatus(false);
167        }
168
169    } else {
170        if ( NO_ERROR == ret ) {
171            ret = returnFocusStatus(false);
172        }
173    }
174
175    //Restore CAF if needed
176    if ( ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) &&
177         ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAutoLock ) ) {
178        mPending3Asettings |= SetFocus;
179    }
180
181    LOG_FUNCTION_NAME_EXIT;
182
183    return ret;
184}
185
186status_t OMXCameraAdapter::stopAutoFocus()
187{
188    status_t ret = NO_ERROR;
189    OMX_ERRORTYPE eError = OMX_ErrorNone;
190    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
191
192    LOG_FUNCTION_NAME;
193
194    if ( OMX_StateExecuting != mComponentState )
195        {
196        CAMHAL_LOGEA("OMX component not in executing state");
197        return NO_INIT;
198        }
199
200    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
201        // No need to stop focus if we are in infinity mode. Nothing to stop.
202        return NO_ERROR;
203    }
204
205    if ( NO_ERROR == ret )
206       {
207       //Disable the callback first
208       ret = setFocusCallback(false);
209       }
210
211    if ( NO_ERROR == ret )
212        {
213        OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
214        focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
215
216        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
217                                OMX_IndexConfigFocusControl,
218                                &focusControl);
219        if ( OMX_ErrorNone != eError )
220            {
221            CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
222            return ErrorUtils::omxToAndroidError(eError);
223            }
224        }
225
226    //Query current focus distance after AF is complete
227    updateFocusDistances(mParameters);
228
229    LOG_FUNCTION_NAME_EXIT;
230
231    return ret;
232}
233
234status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
235{;
236    OMX_ERRORTYPE eError = OMX_ErrorNone;
237
238    LOG_FUNCTION_NAME;
239
240    if ( OMX_StateInvalid == mComponentState ) {
241        CAMHAL_LOGEA("OMX component is in invalid state");
242        return NO_INIT;
243    }
244
245    OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
246    focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
247
248    eError =  OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
249                            OMX_IndexConfigFocusControl,
250                            &focusMode);
251
252    if ( OMX_ErrorNone != eError ) {
253        CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
254    }
255
256    LOG_FUNCTION_NAME_EXIT;
257
258    return ErrorUtils::omxToAndroidError(eError);
259}
260
261status_t OMXCameraAdapter::cancelAutoFocus()
262{
263    status_t ret = NO_ERROR;
264    OMX_ERRORTYPE eError = OMX_ErrorNone;
265    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
266
267    LOG_FUNCTION_NAME;
268    // Unlock 3A locks since they were locked by AF
269    if( set3ALock(OMX_FALSE) != NO_ERROR) {
270      CAMHAL_LOGEA("Error Unlocking 3A locks");
271    }
272    else{
273      CAMHAL_LOGDA("AE/AWB unlocked successfully");
274    }
275
276    ret = getFocusMode(focusMode);
277    if ( NO_ERROR != ret ) {
278        return ret;
279    }
280
281    //Stop the AF only for modes other than CAF  or Inifinity
282    if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
283         ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
284                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
285        stopAutoFocus();
286        //Signal a dummy AF event so that in case the callback from ducati
287        //does come then it doesnt crash after
288        //exiting this function since eventSem will go out of scope.
289        ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
290                                    (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
291                                    OMX_ALL,
292                                    OMX_IndexConfigCommonFocusStatus,
293                                    NULL );
294    }
295
296    // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
297    pauseFaceDetection(false);
298
299    LOG_FUNCTION_NAME_EXIT;
300
301    return ret;
302
303}
304
305status_t OMXCameraAdapter::setFocusCallback(bool enabled)
306{
307    status_t ret = NO_ERROR;
308    OMX_ERRORTYPE eError = OMX_ErrorNone;
309    OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
310
311    LOG_FUNCTION_NAME;
312
313    if ( OMX_StateExecuting != mComponentState )
314        {
315        CAMHAL_LOGEA("OMX component not in executing state");
316        ret = -1;
317        }
318
319    if ( NO_ERROR == ret )
320        {
321
322        OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
323        focusRequstCallback.nPortIndex = OMX_ALL;
324        focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
325
326        if ( enabled )
327            {
328            focusRequstCallback.bEnable = OMX_TRUE;
329            }
330        else
331            {
332            focusRequstCallback.bEnable = OMX_FALSE;
333            }
334
335        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
336                                (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
337                                &focusRequstCallback);
338        if ( OMX_ErrorNone != eError )
339            {
340            CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
341            ret = -1;
342            }
343        else
344            {
345            CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
346                         OMX_IndexConfigCommonFocusStatus);
347            }
348        }
349
350    LOG_FUNCTION_NAME_EXIT;
351
352    return ret;
353}
354
355status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
356{
357    status_t ret = NO_ERROR;
358    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
359    bool focusStatus = false;
360    BaseCameraAdapter::AdapterState state;
361    BaseCameraAdapter::getState(state);
362
363    LOG_FUNCTION_NAME;
364
365    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
366
367    if( ( AF_ACTIVE & state ) != AF_ACTIVE )
368       {
369        /// We don't send focus callback if focus was not started
370       return NO_ERROR;
371       }
372
373    if ( NO_ERROR == ret )
374        {
375
376        if ( !timeoutReached )
377            {
378            ret = checkFocus(&eFocusStatus);
379
380            if ( NO_ERROR != ret )
381                {
382                CAMHAL_LOGEA("Focus status check failed!");
383                }
384            }
385        }
386
387    if ( NO_ERROR == ret )
388        {
389
390        if ( timeoutReached )
391            {
392            focusStatus = false;
393            }
394        ///FIXME: The ducati seems to return focus as false always if continuous focus is enabled
395        ///So, return focus as locked always until this is fixed.
396        else if(mParameters3A.Focus == OMX_IMAGE_FocusControlAuto )
397            {
398            focusStatus = true;
399            }
400        else
401            {
402            switch (eFocusStatus.eFocusStatus)
403                {
404                    case OMX_FocusStatusReached:
405                        {
406                        focusStatus = true;
407                        //Lock the AE and AWB here sinc the focus is locked
408                        // Apply 3A locks after AF
409                        if( set3ALock(OMX_TRUE) != NO_ERROR) {
410                            CAMHAL_LOGEA("Error Applying 3A locks");
411                        }
412                        else
413                            {
414                            CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
415                            }
416                        break;
417                        }
418                    case OMX_FocusStatusOff:
419                    case OMX_FocusStatusUnableToReach:
420                    case OMX_FocusStatusRequest:
421                    default:
422                        {
423                        focusStatus = false;
424                        break;
425                        }
426                }
427
428            stopAutoFocus();
429            }
430        }
431
432    ret =  BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
433    if ( NO_ERROR == ret )
434        {
435        ret = BaseCameraAdapter::commitState();
436        }
437    else
438        {
439        ret |= BaseCameraAdapter::rollbackState();
440        }
441
442    if ( NO_ERROR == ret )
443        {
444        notifyFocusSubscribers(focusStatus);
445        }
446
447    // After focus, face detection will resume sending face callbacks
448    pauseFaceDetection(false);
449
450    LOG_FUNCTION_NAME_EXIT;
451
452    return ret;
453}
454
455status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
456{
457    status_t ret = NO_ERROR;
458    OMX_ERRORTYPE eError = OMX_ErrorNone;
459
460    LOG_FUNCTION_NAME;
461
462    if ( NULL == eFocusStatus )
463        {
464        CAMHAL_LOGEA("Invalid focus status");
465        ret = -EINVAL;
466        }
467
468    if ( OMX_StateExecuting != mComponentState )
469        {
470        CAMHAL_LOGEA("OMX component not in executing state");
471        ret = -EINVAL;
472        }
473
474    if ( NO_ERROR == ret )
475        {
476        OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
477
478        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
479                               OMX_IndexConfigCommonFocusStatus,
480                               eFocusStatus);
481        if ( OMX_ErrorNone != eError )
482            {
483            CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
484            ret = -1;
485            }
486        }
487
488    if ( NO_ERROR == ret )
489        {
490        CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
491        }
492
493    LOG_FUNCTION_NAME_EXIT;
494
495    return ret;
496}
497
498status_t OMXCameraAdapter::updateFocusDistances(CameraParameters &params)
499{
500    OMX_U32 focusNear, focusOptimal, focusFar;
501    status_t ret = NO_ERROR;
502
503    LOG_FUNCTION_NAME;
504
505    ret = getFocusDistances(focusNear, focusOptimal, focusFar);
506    if ( NO_ERROR == ret)
507        {
508        ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
509            if ( NO_ERROR != ret )
510                {
511                CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
512                }
513        }
514    else
515        {
516        CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
517        }
518
519    LOG_FUNCTION_NAME_EXIT;
520
521    return ret;
522}
523
524status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
525{
526    status_t ret = NO_ERROR;
527    OMX_ERRORTYPE eError;
528
529    OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
530
531    LOG_FUNCTION_NAME;
532
533    if ( OMX_StateInvalid == mComponentState )
534        {
535        CAMHAL_LOGEA("OMX component is in invalid state");
536        ret = UNKNOWN_ERROR;
537        }
538
539    if ( NO_ERROR == ret )
540        {
541        OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
542        focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
543
544        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
545                               ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
546                               &focusDist);
547        if ( OMX_ErrorNone != eError )
548            {
549            CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
550            ret = UNKNOWN_ERROR;
551            }
552
553        }
554
555    if ( NO_ERROR == ret )
556        {
557        near = focusDist.nFocusDistanceNear;
558        optimal = focusDist.nFocusDistanceOptimal;
559        far = focusDist.nFocusDistanceFar;
560        }
561
562    LOG_FUNCTION_NAME_EXIT;
563
564    return ret;
565}
566
567status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
568{
569    status_t ret = NO_ERROR;
570    uint32_t focusScale = 1000;
571    float distFinal;
572
573    LOG_FUNCTION_NAME;
574
575    if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
576        {
577        dist=0;
578        }
579
580    if ( NO_ERROR == ret )
581        {
582        if ( 0 == dist )
583            {
584            strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
585            }
586        else
587            {
588            distFinal = dist;
589            distFinal /= focusScale;
590            snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
591            }
592        }
593
594    LOG_FUNCTION_NAME_EXIT;
595
596    return ret;
597}
598
599status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
600                                             OMX_U32 &optimal,
601                                             OMX_U32 &far,
602                                             CameraParameters& params)
603{
604    status_t ret = NO_ERROR;
605
606    LOG_FUNCTION_NAME;
607
608    if ( NO_ERROR == ret )
609        {
610        ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
611        if ( NO_ERROR != ret )
612            {
613            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
614            }
615        }
616
617    if ( NO_ERROR == ret )
618        {
619        ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
620        if ( NO_ERROR != ret )
621            {
622            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
623            }
624        }
625
626    if ( NO_ERROR == ret )
627        {
628        ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
629        if ( NO_ERROR != ret )
630            {
631            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
632            }
633        }
634
635    if ( NO_ERROR == ret )
636        {
637        snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
638                                                                              mFocusDistOptimal,
639                                                                              mFocusDistFar);
640
641        params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
642        }
643
644    LOG_FUNCTION_NAME_EXIT;
645
646    return ret;
647}
648
649status_t OMXCameraAdapter::setTouchFocus(size_t posX,
650                                         size_t posY,
651                                         size_t posWidth,
652                                         size_t posHeight,
653                                         size_t previewWidth,
654                                         size_t previewHeight)
655{
656    status_t ret = NO_ERROR;
657    OMX_ERRORTYPE eError = OMX_ErrorNone;
658    OMX_CONFIG_EXTFOCUSREGIONTYPE touchControl;
659
660    LOG_FUNCTION_NAME;
661
662    if ( OMX_StateInvalid == mComponentState )
663        {
664        CAMHAL_LOGEA("OMX component is in invalid state");
665        ret = -1;
666        }
667
668    if ( NO_ERROR == ret )
669        {
670        OMX_INIT_STRUCT_PTR (&touchControl, OMX_CONFIG_EXTFOCUSREGIONTYPE);
671        touchControl.nLeft = ( posX * TOUCH_FOCUS_RANGE ) / previewWidth;
672        touchControl.nTop =  ( posY * TOUCH_FOCUS_RANGE ) / previewHeight;
673        touchControl.nWidth = ( posWidth * TOUCH_FOCUS_RANGE ) / previewWidth;
674        touchControl.nHeight = ( posHeight * TOUCH_FOCUS_RANGE ) / previewHeight;
675
676        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
677                                ( OMX_INDEXTYPE ) OMX_IndexConfigExtFocusRegion,
678                                &touchControl);
679        if ( OMX_ErrorNone != eError )
680            {
681            CAMHAL_LOGEB("Error while configuring touch focus 0x%x", eError);
682            ret = -1;
683            }
684        else
685            {
686            CAMHAL_LOGDB("Touch focus %d,%d %d,%d configured successfuly",
687                         ( int ) touchControl.nLeft,
688                         ( int ) touchControl.nTop,
689                         ( int ) touchControl.nWidth,
690                         ( int ) touchControl.nHeight);
691            }
692        }
693
694    LOG_FUNCTION_NAME_EXIT;
695
696    return ret;
697}
698
699};
700