NfcAdaptation.cpp revision 1569641423dac0a41af7596fdef972126e698f46
1/******************************************************************************
2 *
3 *  Copyright (C) 1999-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18#include "OverrideLog.h"
19#include "NfcAdaptation.h"
20extern "C"
21{
22    #include "gki.h"
23    #include "nfa_api.h"
24    #include "nfc_int.h"
25}
26#include "config.h"
27#include "android_logmsg.h"
28
29#define LOG_TAG "NfcAdaptation"
30
31extern "C" void GKI_shutdown();
32extern void resetConfig();
33extern "C" void verify_stack_non_volatile_store ();
34extern "C" void delete_stack_non_volatile_store (BOOLEAN forceDelete);
35
36NfcAdaptation* NfcAdaptation::mpInstance = NULL;
37ThreadMutex NfcAdaptation::sLock;
38nfc_nci_device_t* NfcAdaptation::mHalDeviceContext = NULL;
39tHAL_NFC_CBACK* NfcAdaptation::mHalCallback = NULL;
40tHAL_NFC_DATA_CBACK* NfcAdaptation::mHalDataCallback = NULL;
41ThreadCondVar NfcAdaptation::mHalOpenCompletedEvent;
42ThreadCondVar NfcAdaptation::mHalCloseCompletedEvent;
43
44UINT32 ScrProtocolTraceFlag = SCR_PROTO_TRACE_ALL; //0x017F00;
45UINT8 appl_trace_level = 0xff;
46char bcm_nfc_location[120];
47
48static UINT8 nfa_dm_cfg[sizeof ( tNFA_DM_CFG ) ];
49extern tNFA_DM_CFG *p_nfa_dm_cfg;
50extern UINT8 nfa_ee_max_ee_cfg;
51extern const UINT8  nfca_version_string [];
52extern const UINT8  nfa_version_string [];
53static UINT8 deviceHostWhiteList [NFA_HCI_MAX_HOST_IN_NETWORK];
54static tNFA_HCI_CFG jni_nfa_hci_cfg;
55extern tNFA_HCI_CFG *p_nfa_hci_cfg;
56
57/*******************************************************************************
58**
59** Function:    NfcAdaptation::NfcAdaptation()
60**
61** Description: class constructor
62**
63** Returns:     none
64**
65*******************************************************************************/
66NfcAdaptation::NfcAdaptation()
67{
68    memset (&mHalEntryFuncs, 0, sizeof(mHalEntryFuncs));
69}
70
71/*******************************************************************************
72**
73** Function:    NfcAdaptation::~NfcAdaptation()
74**
75** Description: class destructor
76**
77** Returns:     none
78**
79*******************************************************************************/
80NfcAdaptation::~NfcAdaptation()
81{
82    mpInstance = NULL;
83}
84
85/*******************************************************************************
86**
87** Function:    NfcAdaptation::GetInstance()
88**
89** Description: access class singleton
90**
91** Returns:     pointer to the singleton object
92**
93*******************************************************************************/
94NfcAdaptation& NfcAdaptation::GetInstance()
95{
96    AutoThreadMutex  a(sLock);
97
98    if (!mpInstance)
99        mpInstance = new NfcAdaptation;
100    return *mpInstance;
101}
102
103/*******************************************************************************
104**
105** Function:    NfcAdaptation::Initialize()
106**
107** Description: class initializer
108**
109** Returns:     none
110**
111*******************************************************************************/
112void NfcAdaptation::Initialize ()
113{
114    const char* func = "NfcAdaptation::Initialize";
115    ALOGD("%s: enter", func);
116    ALOGE("%s: ver=%s nfa=%s", func, nfca_version_string, nfa_version_string);
117    unsigned long num;
118
119    if ( GetNumValue ( NAME_USE_RAW_NCI_TRACE, &num, sizeof ( num ) ) )
120    {
121        if (num == 1)
122        {
123            // display protocol traces in raw format
124            ProtoDispAdapterUseRawOutput (TRUE);
125            ALOGD("%s: logging protocol in raw format", func);
126        }
127    }
128    if ( !GetStrValue ( NAME_NFA_STORAGE, bcm_nfc_location, sizeof ( bcm_nfc_location ) ) )
129    {
130        memset (bcm_nfc_location, 0, sizeof(bcm_nfc_location));
131        strncpy (bcm_nfc_location, "/data/nfc", 9);
132    }
133    if ( GetNumValue ( NAME_PROTOCOL_TRACE_LEVEL, &num, sizeof ( num ) ) )
134        ScrProtocolTraceFlag = num;
135
136    if ( GetStrValue ( NAME_NFA_DM_CFG, (char*)nfa_dm_cfg, sizeof ( nfa_dm_cfg ) ) )
137        p_nfa_dm_cfg = ( tNFA_DM_CFG * ) &nfa_dm_cfg[0];
138
139    if ( GetNumValue ( NAME_NFA_MAX_EE_SUPPORTED, &num, sizeof ( num ) ) )
140    {
141        nfa_ee_max_ee_cfg = num;
142        ALOGD("%s: Overriding NFA_EE_MAX_EE_SUPPORTED to use %d", func, nfa_ee_max_ee_cfg);
143    }
144
145    //configure device host whitelist of HCI host ID's; see specification ETSI TS 102 622 V11.1.10
146    //(2012-10), section 6.1.3.1
147    num = GetStrValue ( NAME_DEVICE_HOST_WHITE_LIST, (char*) deviceHostWhiteList, sizeof ( deviceHostWhiteList ) );
148    if (num)
149    {
150        memmove (&jni_nfa_hci_cfg, p_nfa_hci_cfg, sizeof(jni_nfa_hci_cfg));
151        jni_nfa_hci_cfg.num_whitelist_host = (UINT8) num; //number of HCI host ID's in the whitelist
152        jni_nfa_hci_cfg.p_whitelist = deviceHostWhiteList; //array of HCI host ID's
153        p_nfa_hci_cfg = &jni_nfa_hci_cfg;
154    }
155
156    initializeGlobalAppLogLevel ();
157
158    verify_stack_non_volatile_store ();
159    if ( GetNumValue ( NAME_PRESERVE_STORAGE, (char*)&num, sizeof ( num ) ) &&
160            (num == 1) )
161        ALOGD ("%s: preserve stack NV store", __FUNCTION__);
162    else
163    {
164        delete_stack_non_volatile_store (FALSE);
165    }
166
167    GKI_init ();
168    GKI_enable ();
169    GKI_create_task ((TASKPTR)NFCA_TASK, BTU_TASK, (INT8*)"NFCA_TASK", 0, 0, (pthread_cond_t*)NULL, NULL);
170    {
171        AutoThreadMutex guard(mCondVar);
172        GKI_create_task ((TASKPTR)Thread, MMI_TASK, (INT8*)"NFCA_THREAD", 0, 0, (pthread_cond_t*)NULL, NULL);
173        mCondVar.wait();
174    }
175
176    mHalDeviceContext = NULL;
177    mHalCallback =  NULL;
178    memset (&mHalEntryFuncs, 0, sizeof(mHalEntryFuncs));
179    InitializeHalDeviceContext ();
180    ALOGD ("%s: exit", func);
181}
182
183/*******************************************************************************
184**
185** Function:    NfcAdaptation::Finalize()
186**
187** Description: class finalizer
188**
189** Returns:     none
190**
191*******************************************************************************/
192void NfcAdaptation::Finalize()
193{
194    const char* func = "NfcAdaptation::Finalize";
195    AutoThreadMutex  a(sLock);
196
197    ALOGD ("%s: enter", func);
198    GKI_shutdown ();
199
200    resetConfig();
201
202    nfc_nci_close(mHalDeviceContext); //close the HAL's device context
203    mHalDeviceContext = NULL;
204    mHalCallback = NULL;
205    memset (&mHalEntryFuncs, 0, sizeof(mHalEntryFuncs));
206
207    ALOGD ("%s: exit", func);
208    delete this;
209}
210
211/*******************************************************************************
212**
213** Function:    NfcAdaptation::signal()
214**
215** Description: signal the CondVar to release the thread that is waiting
216**
217** Returns:     none
218**
219*******************************************************************************/
220void NfcAdaptation::signal ()
221{
222    mCondVar.signal();
223}
224
225/*******************************************************************************
226**
227** Function:    NfcAdaptation::NFCA_TASK()
228**
229** Description: NFCA_TASK runs the GKI main task
230**
231** Returns:     none
232**
233*******************************************************************************/
234UINT32 NfcAdaptation::NFCA_TASK (UINT32 arg)
235{
236    const char* func = "NfcAdaptation::NFCA_TASK";
237    ALOGD ("%s: enter", func);
238    GKI_run (0);
239    ALOGD ("%s: exit", func);
240    return 0;
241}
242
243/*******************************************************************************
244**
245** Function:    NfcAdaptation::Thread()
246**
247** Description: Creates work threads
248**
249** Returns:     none
250**
251*******************************************************************************/
252UINT32 NfcAdaptation::Thread (UINT32 arg)
253{
254    const char* func = "NfcAdaptation::Thread";
255    ALOGD ("%s: enter", func);
256
257    {
258        ThreadCondVar    CondVar;
259        AutoThreadMutex  guard(CondVar);
260        GKI_create_task ((TASKPTR)nfc_task, NFC_TASK, (INT8*)"NFC_TASK", 0, 0, (pthread_cond_t*)CondVar, (pthread_mutex_t*)CondVar);
261        CondVar.wait();
262    }
263
264    NfcAdaptation::GetInstance().signal();
265
266    GKI_exit_task (GKI_get_taskid ());
267    ALOGD ("%s: exit", func);
268    return 0;
269}
270
271/*******************************************************************************
272**
273** Function:    NfcAdaptation::GetHalEntryFuncs()
274**
275** Description: Get the set of HAL entry points.
276**
277** Returns:     Functions pointers for HAL entry points.
278**
279*******************************************************************************/
280tHAL_NFC_ENTRY* NfcAdaptation::GetHalEntryFuncs ()
281{
282    return &mHalEntryFuncs;
283}
284
285/*******************************************************************************
286**
287** Function:    NfcAdaptation::InitializeHalDeviceContext
288**
289** Description: Ask the generic Android HAL to find the Broadcom-specific HAL.
290**
291** Returns:     None.
292**
293*******************************************************************************/
294void NfcAdaptation::InitializeHalDeviceContext ()
295{
296    const char* func = "NfcAdaptation::InitializeHalDeviceContext";
297    ALOGD ("%s: enter", func);
298    int ret = 0; //0 means success
299    const hw_module_t* hw_module = NULL;
300
301    mHalEntryFuncs.initialize = HalInitialize;
302    mHalEntryFuncs.terminate = HalTerminate;
303    mHalEntryFuncs.open = HalOpen;
304    mHalEntryFuncs.close = HalClose;
305    mHalEntryFuncs.core_initialized = HalCoreInitialized;
306    mHalEntryFuncs.write = HalWrite;
307    mHalEntryFuncs.prediscover = HalPrediscover;
308    mHalEntryFuncs.control_granted = HalControlGranted;
309    mHalEntryFuncs.power_cycle = HalPowerCycle;
310    mHalEntryFuncs.get_max_ee = HalGetMaxNfcee;
311
312    ret = hw_get_module (NFC_NCI_HARDWARE_MODULE_ID, &hw_module);
313    if (ret == 0)
314    {
315        ret = nfc_nci_open (hw_module, &mHalDeviceContext);
316        if (ret != 0)
317            ALOGE ("%s: nfc_nci_open fail", func);
318    }
319    else
320        ALOGE ("%s: fail hw_get_module", func);
321    ALOGD ("%s: exit", func);
322}
323
324/*******************************************************************************
325**
326** Function:    NfcAdaptation::HalInitialize
327**
328** Description: Not implemented because this function is only needed
329**              within the HAL.
330**
331** Returns:     None.
332**
333*******************************************************************************/
334void NfcAdaptation::HalInitialize ()
335{
336    const char* func = "NfcAdaptation::HalInitialize";
337    ALOGD ("%s", func);
338}
339
340/*******************************************************************************
341**
342** Function:    NfcAdaptation::HalTerminate
343**
344** Description: Not implemented because this function is only needed
345**              within the HAL.
346**
347** Returns:     None.
348**
349*******************************************************************************/
350void NfcAdaptation::HalTerminate ()
351{
352    const char* func = "NfcAdaptation::HalTerminate";
353    ALOGD ("%s", func);
354}
355
356/*******************************************************************************
357**
358** Function:    NfcAdaptation::HalOpen
359**
360** Description: Turn on controller, download firmware.
361**
362** Returns:     None.
363**
364*******************************************************************************/
365void NfcAdaptation::HalOpen (tHAL_NFC_CBACK *p_hal_cback, tHAL_NFC_DATA_CBACK* p_data_cback)
366{
367    const char* func = "NfcAdaptation::HalOpen";
368    ALOGD ("%s", func);
369    if (mHalDeviceContext)
370    {
371        mHalCallback = p_hal_cback;
372        mHalDataCallback = p_data_cback;
373        mHalDeviceContext->open (mHalDeviceContext, HalDeviceContextCallback, HalDeviceContextDataCallback);
374    }
375}
376
377/*******************************************************************************
378**
379** Function:    NfcAdaptation::HalClose
380**
381** Description: Turn off controller.
382**
383** Returns:     None.
384**
385*******************************************************************************/
386void NfcAdaptation::HalClose ()
387{
388    const char* func = "NfcAdaptation::HalClose";
389    ALOGD ("%s", func);
390    if (mHalDeviceContext)
391    {
392        mHalDeviceContext->close (mHalDeviceContext);
393    }
394}
395
396/*******************************************************************************
397**
398** Function:    NfcAdaptation::HalDeviceContextCallback
399**
400** Description: Translate generic Android HAL's callback into Broadcom-specific
401**              callback function.
402**
403** Returns:     None.
404**
405*******************************************************************************/
406void NfcAdaptation::HalDeviceContextCallback (nfc_event_t event, nfc_status_t event_status)
407{
408    const char* func = "NfcAdaptation::HalDeviceContextCallback";
409    ALOGD ("%s: event=%u", func, event);
410    if (mHalCallback)
411        mHalCallback (event, (tHAL_NFC_STATUS) event_status);
412}
413
414/*******************************************************************************
415**
416** Function:    NfcAdaptation::HalDeviceContextDataCallback
417**
418** Description: Translate generic Android HAL's callback into Broadcom-specific
419**              callback function.
420**
421** Returns:     None.
422**
423*******************************************************************************/
424void NfcAdaptation::HalDeviceContextDataCallback (uint16_t data_len, uint8_t* p_data)
425{
426    const char* func = "NfcAdaptation::HalDeviceContextDataCallback";
427    ALOGD ("%s: len=%u", func, data_len);
428    if (mHalDataCallback)
429        mHalDataCallback (data_len, p_data);
430}
431
432/*******************************************************************************
433**
434** Function:    NfcAdaptation::HalWrite
435**
436** Description: Write NCI message to the controller.
437**
438** Returns:     None.
439**
440*******************************************************************************/
441void NfcAdaptation::HalWrite (UINT16 data_len, UINT8* p_data)
442{
443    const char* func = "NfcAdaptation::HalWrite";
444    ALOGD ("%s", func);
445    if (mHalDeviceContext)
446    {
447        mHalDeviceContext->write (mHalDeviceContext, data_len, p_data);
448    }
449}
450
451/*******************************************************************************
452**
453** Function:    NfcAdaptation::HalCoreInitialized
454**
455** Description: Adjust the configurable parameters in the controller.
456**
457** Returns:     None.
458**
459*******************************************************************************/
460void NfcAdaptation::HalCoreInitialized (UINT8* p_core_init_rsp_params)
461{
462    const char* func = "NfcAdaptation::HalCoreInitialized";
463    ALOGD ("%s", func);
464    if (mHalDeviceContext)
465    {
466        mHalDeviceContext->core_initialized (mHalDeviceContext, p_core_init_rsp_params);
467    }
468}
469
470/*******************************************************************************
471**
472** Function:    NfcAdaptation::HalPrediscover
473**
474** Description:     Perform any vendor-specific pre-discovery actions (if needed)
475**                  If any actions were performed TRUE will be returned, and
476**                  HAL_PRE_DISCOVER_CPLT_EVT will notify when actions are
477**                  completed.
478**
479** Returns:          TRUE if vendor-specific pre-discovery actions initialized
480**                  FALSE if no vendor-specific pre-discovery actions are needed.
481**
482*******************************************************************************/
483BOOLEAN NfcAdaptation::HalPrediscover ()
484{
485    const char* func = "NfcAdaptation::HalPrediscover";
486    ALOGD ("%s", func);
487    BOOLEAN retval = FALSE;
488
489    if (mHalDeviceContext)
490    {
491        retval = mHalDeviceContext->pre_discover (mHalDeviceContext);
492    }
493    return retval;
494}
495
496/*******************************************************************************
497**
498** Function:        HAL_NfcControlGranted
499**
500** Description:     Grant control to HAL control for sending NCI commands.
501**                  Call in response to HAL_REQUEST_CONTROL_EVT.
502**                  Must only be called when there are no NCI commands pending.
503**                  HAL_RELEASE_CONTROL_EVT will notify when HAL no longer
504**                  needs control of NCI.
505**
506** Returns:         void
507**
508*******************************************************************************/
509void NfcAdaptation::HalControlGranted ()
510{
511    const char* func = "NfcAdaptation::HalControlGranted";
512    ALOGD ("%s", func);
513    if (mHalDeviceContext)
514    {
515        mHalDeviceContext->control_granted (mHalDeviceContext);
516    }
517}
518
519/*******************************************************************************
520**
521** Function:    NfcAdaptation::HalPowerCycle
522**
523** Description: Turn off and turn on the controller.
524**
525** Returns:     None.
526**
527*******************************************************************************/
528void NfcAdaptation::HalPowerCycle ()
529{
530    const char* func = "NfcAdaptation::HalPowerCycle";
531    ALOGD ("%s", func);
532    if (mHalDeviceContext)
533    {
534        mHalDeviceContext->power_cycle (mHalDeviceContext);
535    }
536}
537
538/*******************************************************************************
539**
540** Function:    NfcAdaptation::HalGetMaxNfcee
541**
542** Description: Turn off and turn on the controller.
543**
544** Returns:     None.
545**
546*******************************************************************************/
547UINT8 NfcAdaptation::HalGetMaxNfcee()
548{
549    const char* func = "NfcAdaptation::HalPowerCycle";
550    UINT8 maxNfcee = 0;
551    ALOGD ("%s", func);
552    if (mHalDeviceContext)
553    {
554        // TODO maco call into HAL when we figure out binary compatibility.
555        return nfa_ee_max_ee_cfg;
556
557        //mHalDeviceContext->get_max_ee (mHalDeviceContext, &maxNfcee);
558    }
559
560    return maxNfcee;
561}
562
563
564/*******************************************************************************
565**
566** Function:    NfcAdaptation::DownloadFirmware
567**
568** Description: Download firmware patch files.
569**
570** Returns:     None.
571**
572*******************************************************************************/
573void NfcAdaptation::DownloadFirmware ()
574{
575    const char* func = "NfcAdaptation::DownloadFirmware";
576    ALOGD ("%s: enter", func);
577    HalInitialize ();
578
579    mHalOpenCompletedEvent.lock ();
580    ALOGD ("%s: try open HAL", func);
581    HalOpen (HalDownloadFirmwareCallback, HalDownloadFirmwareDataCallback);
582    mHalOpenCompletedEvent.wait ();
583
584    mHalCloseCompletedEvent.lock ();
585    ALOGD ("%s: try close HAL", func);
586    HalClose ();
587    mHalCloseCompletedEvent.wait ();
588
589    HalTerminate ();
590    ALOGD ("%s: exit", func);
591}
592
593/*******************************************************************************
594**
595** Function:    NfcAdaptation::HalDownloadFirmwareCallback
596**
597** Description: Receive events from the HAL.
598**
599** Returns:     None.
600**
601*******************************************************************************/
602void NfcAdaptation::HalDownloadFirmwareCallback (nfc_event_t event, nfc_status_t event_status)
603{
604    const char* func = "NfcAdaptation::HalDownloadFirmwareCallback";
605    ALOGD ("%s: event=0x%X", func, event);
606    switch (event)
607    {
608    case HAL_NFC_OPEN_CPLT_EVT:
609        {
610            ALOGD ("%s: HAL_NFC_OPEN_CPLT_EVT", func);
611            mHalOpenCompletedEvent.signal ();
612            break;
613        }
614    case HAL_NFC_CLOSE_CPLT_EVT:
615        {
616            ALOGD ("%s: HAL_NFC_CLOSE_CPLT_EVT", func);
617            mHalCloseCompletedEvent.signal ();
618            break;
619        }
620    }
621}
622
623/*******************************************************************************
624**
625** Function:    NfcAdaptation::HalDownloadFirmwareDataCallback
626**
627** Description: Receive data events from the HAL.
628**
629** Returns:     None.
630**
631*******************************************************************************/
632void NfcAdaptation::HalDownloadFirmwareDataCallback (uint16_t data_len, uint8_t* p_data)
633{
634}
635
636
637/*******************************************************************************
638**
639** Function:    ThreadMutex::ThreadMutex()
640**
641** Description: class constructor
642**
643** Returns:     none
644**
645*******************************************************************************/
646ThreadMutex::ThreadMutex()
647{
648    pthread_mutexattr_t mutexAttr;
649
650    pthread_mutexattr_init(&mutexAttr);
651    pthread_mutex_init(&mMutex, &mutexAttr);
652    pthread_mutexattr_destroy(&mutexAttr);
653}
654
655/*******************************************************************************
656**
657** Function:    ThreadMutex::~ThreadMutex()
658**
659** Description: class destructor
660**
661** Returns:     none
662**
663*******************************************************************************/
664ThreadMutex::~ThreadMutex()
665{
666    pthread_mutex_destroy(&mMutex);
667}
668
669/*******************************************************************************
670**
671** Function:    ThreadMutex::lock()
672**
673** Description: lock kthe mutex
674**
675** Returns:     none
676**
677*******************************************************************************/
678void ThreadMutex::lock()
679{
680    pthread_mutex_lock(&mMutex);
681}
682
683/*******************************************************************************
684**
685** Function:    ThreadMutex::unblock()
686**
687** Description: unlock the mutex
688**
689** Returns:     none
690**
691*******************************************************************************/
692void ThreadMutex::unlock()
693{
694    pthread_mutex_unlock(&mMutex);
695}
696
697/*******************************************************************************
698**
699** Function:    ThreadCondVar::ThreadCondVar()
700**
701** Description: class constructor
702**
703** Returns:     none
704**
705*******************************************************************************/
706ThreadCondVar::ThreadCondVar()
707{
708    pthread_condattr_t CondAttr;
709
710    pthread_condattr_init(&CondAttr);
711    pthread_cond_init(&mCondVar, &CondAttr);
712
713    pthread_condattr_destroy(&CondAttr);
714}
715
716/*******************************************************************************
717**
718** Function:    ThreadCondVar::~ThreadCondVar()
719**
720** Description: class destructor
721**
722** Returns:     none
723**
724*******************************************************************************/
725ThreadCondVar::~ThreadCondVar()
726{
727    pthread_cond_destroy(&mCondVar);
728}
729
730/*******************************************************************************
731**
732** Function:    ThreadCondVar::wait()
733**
734** Description: wait on the mCondVar
735**
736** Returns:     none
737**
738*******************************************************************************/
739void ThreadCondVar::wait()
740{
741    pthread_cond_wait(&mCondVar, *this);
742    pthread_mutex_unlock(*this);
743}
744
745/*******************************************************************************
746**
747** Function:    ThreadCondVar::signal()
748**
749** Description: signal the mCondVar
750**
751** Returns:     none
752**
753*******************************************************************************/
754void ThreadCondVar::signal()
755{
756    AutoThreadMutex  a(*this);
757    pthread_cond_signal(&mCondVar);
758}
759
760/*******************************************************************************
761**
762** Function:    AutoThreadMutex::AutoThreadMutex()
763**
764** Description: class constructor, automatically lock the mutex
765**
766** Returns:     none
767**
768*******************************************************************************/
769AutoThreadMutex::AutoThreadMutex(ThreadMutex &m)
770    : mm(m)
771{
772    mm.lock();
773}
774
775/*******************************************************************************
776**
777** Function:    AutoThreadMutex::~AutoThreadMutex()
778**
779** Description: class destructor, automatically unlock the mutex
780**
781** Returns:     none
782**
783*******************************************************************************/
784AutoThreadMutex::~AutoThreadMutex()
785{
786    mm.unlock();
787}
788