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];
47char nci_hal_module[64];
48
49static UINT8 nfa_dm_cfg[sizeof ( tNFA_DM_CFG ) ];
50extern tNFA_DM_CFG *p_nfa_dm_cfg;
51extern UINT8 nfa_ee_max_ee_cfg;
52extern const UINT8  nfca_version_string [];
53extern const UINT8  nfa_version_string [];
54static UINT8 deviceHostWhiteList [NFA_HCI_MAX_HOST_IN_NETWORK];
55static tNFA_HCI_CFG jni_nfa_hci_cfg;
56extern tNFA_HCI_CFG *p_nfa_hci_cfg;
57
58/*******************************************************************************
59**
60** Function:    NfcAdaptation::NfcAdaptation()
61**
62** Description: class constructor
63**
64** Returns:     none
65**
66*******************************************************************************/
67NfcAdaptation::NfcAdaptation()
68{
69    memset (&mHalEntryFuncs, 0, sizeof(mHalEntryFuncs));
70}
71
72/*******************************************************************************
73**
74** Function:    NfcAdaptation::~NfcAdaptation()
75**
76** Description: class destructor
77**
78** Returns:     none
79**
80*******************************************************************************/
81NfcAdaptation::~NfcAdaptation()
82{
83    mpInstance = NULL;
84}
85
86/*******************************************************************************
87**
88** Function:    NfcAdaptation::GetInstance()
89**
90** Description: access class singleton
91**
92** Returns:     pointer to the singleton object
93**
94*******************************************************************************/
95NfcAdaptation& NfcAdaptation::GetInstance()
96{
97    AutoThreadMutex  a(sLock);
98
99    if (!mpInstance)
100        mpInstance = new NfcAdaptation;
101    return *mpInstance;
102}
103
104/*******************************************************************************
105**
106** Function:    NfcAdaptation::Initialize()
107**
108** Description: class initializer
109**
110** Returns:     none
111**
112*******************************************************************************/
113void NfcAdaptation::Initialize ()
114{
115    const char* func = "NfcAdaptation::Initialize";
116    ALOGD("%s: enter", func);
117    ALOGE("%s: ver=%s nfa=%s", func, nfca_version_string, nfa_version_string);
118    unsigned long num;
119
120    if ( GetNumValue ( NAME_USE_RAW_NCI_TRACE, &num, sizeof ( num ) ) )
121    {
122        if (num == 1)
123        {
124            // display protocol traces in raw format
125            ProtoDispAdapterUseRawOutput (TRUE);
126            ALOGD("%s: logging protocol in raw format", func);
127        }
128    }
129    if ( !GetStrValue ( NAME_NFA_STORAGE, bcm_nfc_location, sizeof ( bcm_nfc_location ) ) )
130    {
131        strlcpy (bcm_nfc_location, "/data/nfc", sizeof(bcm_nfc_location));
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    if ( !GetStrValue ( NAME_NCI_HAL_MODULE, nci_hal_module, sizeof ( nci_hal_module) ) )
300    {
301        ALOGE("No HAL module specified in config, falling back to BCM2079x");
302        strlcpy (nci_hal_module, "nfc_nci.bcm2079x", sizeof(nci_hal_module));
303    }
304    const hw_module_t* hw_module = NULL;
305
306    mHalEntryFuncs.initialize = HalInitialize;
307    mHalEntryFuncs.terminate = HalTerminate;
308    mHalEntryFuncs.open = HalOpen;
309    mHalEntryFuncs.close = HalClose;
310    mHalEntryFuncs.core_initialized = HalCoreInitialized;
311    mHalEntryFuncs.write = HalWrite;
312    mHalEntryFuncs.prediscover = HalPrediscover;
313    mHalEntryFuncs.control_granted = HalControlGranted;
314    mHalEntryFuncs.power_cycle = HalPowerCycle;
315    mHalEntryFuncs.get_max_ee = HalGetMaxNfcee;
316
317    ret = hw_get_module (nci_hal_module, &hw_module);
318    if (ret == 0)
319    {
320        ret = nfc_nci_open (hw_module, &mHalDeviceContext);
321        if (ret != 0)
322            ALOGE ("%s: nfc_nci_open fail", func);
323    }
324    else
325        ALOGE ("%s: fail hw_get_module %s", func, nci_hal_module);
326    ALOGD ("%s: exit", func);
327}
328
329/*******************************************************************************
330**
331** Function:    NfcAdaptation::HalInitialize
332**
333** Description: Not implemented because this function is only needed
334**              within the HAL.
335**
336** Returns:     None.
337**
338*******************************************************************************/
339void NfcAdaptation::HalInitialize ()
340{
341    const char* func = "NfcAdaptation::HalInitialize";
342    ALOGD ("%s", func);
343}
344
345/*******************************************************************************
346**
347** Function:    NfcAdaptation::HalTerminate
348**
349** Description: Not implemented because this function is only needed
350**              within the HAL.
351**
352** Returns:     None.
353**
354*******************************************************************************/
355void NfcAdaptation::HalTerminate ()
356{
357    const char* func = "NfcAdaptation::HalTerminate";
358    ALOGD ("%s", func);
359}
360
361/*******************************************************************************
362**
363** Function:    NfcAdaptation::HalOpen
364**
365** Description: Turn on controller, download firmware.
366**
367** Returns:     None.
368**
369*******************************************************************************/
370void NfcAdaptation::HalOpen (tHAL_NFC_CBACK *p_hal_cback, tHAL_NFC_DATA_CBACK* p_data_cback)
371{
372    const char* func = "NfcAdaptation::HalOpen";
373    ALOGD ("%s", func);
374    if (mHalDeviceContext)
375    {
376        mHalCallback = p_hal_cback;
377        mHalDataCallback = p_data_cback;
378        mHalDeviceContext->open (mHalDeviceContext, HalDeviceContextCallback, HalDeviceContextDataCallback);
379    }
380}
381
382/*******************************************************************************
383**
384** Function:    NfcAdaptation::HalClose
385**
386** Description: Turn off controller.
387**
388** Returns:     None.
389**
390*******************************************************************************/
391void NfcAdaptation::HalClose ()
392{
393    const char* func = "NfcAdaptation::HalClose";
394    ALOGD ("%s", func);
395    if (mHalDeviceContext)
396    {
397        mHalDeviceContext->close (mHalDeviceContext);
398    }
399}
400
401/*******************************************************************************
402**
403** Function:    NfcAdaptation::HalDeviceContextCallback
404**
405** Description: Translate generic Android HAL's callback into Broadcom-specific
406**              callback function.
407**
408** Returns:     None.
409**
410*******************************************************************************/
411void NfcAdaptation::HalDeviceContextCallback (nfc_event_t event, nfc_status_t event_status)
412{
413    const char* func = "NfcAdaptation::HalDeviceContextCallback";
414    ALOGD ("%s: event=%u", func, event);
415    if (mHalCallback)
416        mHalCallback (event, (tHAL_NFC_STATUS) event_status);
417}
418
419/*******************************************************************************
420**
421** Function:    NfcAdaptation::HalDeviceContextDataCallback
422**
423** Description: Translate generic Android HAL's callback into Broadcom-specific
424**              callback function.
425**
426** Returns:     None.
427**
428*******************************************************************************/
429void NfcAdaptation::HalDeviceContextDataCallback (uint16_t data_len, uint8_t* p_data)
430{
431    const char* func = "NfcAdaptation::HalDeviceContextDataCallback";
432    ALOGD ("%s: len=%u", func, data_len);
433    if (mHalDataCallback)
434        mHalDataCallback (data_len, p_data);
435}
436
437/*******************************************************************************
438**
439** Function:    NfcAdaptation::HalWrite
440**
441** Description: Write NCI message to the controller.
442**
443** Returns:     None.
444**
445*******************************************************************************/
446void NfcAdaptation::HalWrite (UINT16 data_len, UINT8* p_data)
447{
448    const char* func = "NfcAdaptation::HalWrite";
449    ALOGD ("%s", func);
450    if (mHalDeviceContext)
451    {
452        mHalDeviceContext->write (mHalDeviceContext, data_len, p_data);
453    }
454}
455
456/*******************************************************************************
457**
458** Function:    NfcAdaptation::HalCoreInitialized
459**
460** Description: Adjust the configurable parameters in the controller.
461**
462** Returns:     None.
463**
464*******************************************************************************/
465void NfcAdaptation::HalCoreInitialized (UINT8* p_core_init_rsp_params)
466{
467    const char* func = "NfcAdaptation::HalCoreInitialized";
468    ALOGD ("%s", func);
469    if (mHalDeviceContext)
470    {
471        mHalDeviceContext->core_initialized (mHalDeviceContext, p_core_init_rsp_params);
472    }
473}
474
475/*******************************************************************************
476**
477** Function:    NfcAdaptation::HalPrediscover
478**
479** Description:     Perform any vendor-specific pre-discovery actions (if needed)
480**                  If any actions were performed TRUE will be returned, and
481**                  HAL_PRE_DISCOVER_CPLT_EVT will notify when actions are
482**                  completed.
483**
484** Returns:          TRUE if vendor-specific pre-discovery actions initialized
485**                  FALSE if no vendor-specific pre-discovery actions are needed.
486**
487*******************************************************************************/
488BOOLEAN NfcAdaptation::HalPrediscover ()
489{
490    const char* func = "NfcAdaptation::HalPrediscover";
491    ALOGD ("%s", func);
492    BOOLEAN retval = FALSE;
493
494    if (mHalDeviceContext)
495    {
496        retval = mHalDeviceContext->pre_discover (mHalDeviceContext);
497    }
498    return retval;
499}
500
501/*******************************************************************************
502**
503** Function:        HAL_NfcControlGranted
504**
505** Description:     Grant control to HAL control for sending NCI commands.
506**                  Call in response to HAL_REQUEST_CONTROL_EVT.
507**                  Must only be called when there are no NCI commands pending.
508**                  HAL_RELEASE_CONTROL_EVT will notify when HAL no longer
509**                  needs control of NCI.
510**
511** Returns:         void
512**
513*******************************************************************************/
514void NfcAdaptation::HalControlGranted ()
515{
516    const char* func = "NfcAdaptation::HalControlGranted";
517    ALOGD ("%s", func);
518    if (mHalDeviceContext)
519    {
520        mHalDeviceContext->control_granted (mHalDeviceContext);
521    }
522}
523
524/*******************************************************************************
525**
526** Function:    NfcAdaptation::HalPowerCycle
527**
528** Description: Turn off and turn on the controller.
529**
530** Returns:     None.
531**
532*******************************************************************************/
533void NfcAdaptation::HalPowerCycle ()
534{
535    const char* func = "NfcAdaptation::HalPowerCycle";
536    ALOGD ("%s", func);
537    if (mHalDeviceContext)
538    {
539        mHalDeviceContext->power_cycle (mHalDeviceContext);
540    }
541}
542
543/*******************************************************************************
544**
545** Function:    NfcAdaptation::HalGetMaxNfcee
546**
547** Description: Turn off and turn on the controller.
548**
549** Returns:     None.
550**
551*******************************************************************************/
552UINT8 NfcAdaptation::HalGetMaxNfcee()
553{
554    const char* func = "NfcAdaptation::HalPowerCycle";
555    UINT8 maxNfcee = 0;
556    ALOGD ("%s", func);
557    if (mHalDeviceContext)
558    {
559        // TODO maco call into HAL when we figure out binary compatibility.
560        return nfa_ee_max_ee_cfg;
561
562        //mHalDeviceContext->get_max_ee (mHalDeviceContext, &maxNfcee);
563    }
564
565    return maxNfcee;
566}
567
568
569/*******************************************************************************
570**
571** Function:    NfcAdaptation::DownloadFirmware
572**
573** Description: Download firmware patch files.
574**
575** Returns:     None.
576**
577*******************************************************************************/
578void NfcAdaptation::DownloadFirmware ()
579{
580    const char* func = "NfcAdaptation::DownloadFirmware";
581    ALOGD ("%s: enter", func);
582    HalInitialize ();
583
584    mHalOpenCompletedEvent.lock ();
585    ALOGD ("%s: try open HAL", func);
586    HalOpen (HalDownloadFirmwareCallback, HalDownloadFirmwareDataCallback);
587    mHalOpenCompletedEvent.wait ();
588
589    mHalCloseCompletedEvent.lock ();
590    ALOGD ("%s: try close HAL", func);
591    HalClose ();
592    mHalCloseCompletedEvent.wait ();
593
594    HalTerminate ();
595    ALOGD ("%s: exit", func);
596}
597
598/*******************************************************************************
599**
600** Function:    NfcAdaptation::HalDownloadFirmwareCallback
601**
602** Description: Receive events from the HAL.
603**
604** Returns:     None.
605**
606*******************************************************************************/
607void NfcAdaptation::HalDownloadFirmwareCallback (nfc_event_t event, nfc_status_t event_status)
608{
609    const char* func = "NfcAdaptation::HalDownloadFirmwareCallback";
610    ALOGD ("%s: event=0x%X", func, event);
611    switch (event)
612    {
613    case HAL_NFC_OPEN_CPLT_EVT:
614        {
615            ALOGD ("%s: HAL_NFC_OPEN_CPLT_EVT", func);
616            mHalOpenCompletedEvent.signal ();
617            break;
618        }
619    case HAL_NFC_CLOSE_CPLT_EVT:
620        {
621            ALOGD ("%s: HAL_NFC_CLOSE_CPLT_EVT", func);
622            mHalCloseCompletedEvent.signal ();
623            break;
624        }
625    }
626}
627
628/*******************************************************************************
629**
630** Function:    NfcAdaptation::HalDownloadFirmwareDataCallback
631**
632** Description: Receive data events from the HAL.
633**
634** Returns:     None.
635**
636*******************************************************************************/
637void NfcAdaptation::HalDownloadFirmwareDataCallback (uint16_t data_len, uint8_t* p_data)
638{
639}
640
641
642/*******************************************************************************
643**
644** Function:    ThreadMutex::ThreadMutex()
645**
646** Description: class constructor
647**
648** Returns:     none
649**
650*******************************************************************************/
651ThreadMutex::ThreadMutex()
652{
653    pthread_mutexattr_t mutexAttr;
654
655    pthread_mutexattr_init(&mutexAttr);
656    pthread_mutex_init(&mMutex, &mutexAttr);
657    pthread_mutexattr_destroy(&mutexAttr);
658}
659
660/*******************************************************************************
661**
662** Function:    ThreadMutex::~ThreadMutex()
663**
664** Description: class destructor
665**
666** Returns:     none
667**
668*******************************************************************************/
669ThreadMutex::~ThreadMutex()
670{
671    pthread_mutex_destroy(&mMutex);
672}
673
674/*******************************************************************************
675**
676** Function:    ThreadMutex::lock()
677**
678** Description: lock kthe mutex
679**
680** Returns:     none
681**
682*******************************************************************************/
683void ThreadMutex::lock()
684{
685    pthread_mutex_lock(&mMutex);
686}
687
688/*******************************************************************************
689**
690** Function:    ThreadMutex::unblock()
691**
692** Description: unlock the mutex
693**
694** Returns:     none
695**
696*******************************************************************************/
697void ThreadMutex::unlock()
698{
699    pthread_mutex_unlock(&mMutex);
700}
701
702/*******************************************************************************
703**
704** Function:    ThreadCondVar::ThreadCondVar()
705**
706** Description: class constructor
707**
708** Returns:     none
709**
710*******************************************************************************/
711ThreadCondVar::ThreadCondVar()
712{
713    pthread_condattr_t CondAttr;
714
715    pthread_condattr_init(&CondAttr);
716    pthread_cond_init(&mCondVar, &CondAttr);
717
718    pthread_condattr_destroy(&CondAttr);
719}
720
721/*******************************************************************************
722**
723** Function:    ThreadCondVar::~ThreadCondVar()
724**
725** Description: class destructor
726**
727** Returns:     none
728**
729*******************************************************************************/
730ThreadCondVar::~ThreadCondVar()
731{
732    pthread_cond_destroy(&mCondVar);
733}
734
735/*******************************************************************************
736**
737** Function:    ThreadCondVar::wait()
738**
739** Description: wait on the mCondVar
740**
741** Returns:     none
742**
743*******************************************************************************/
744void ThreadCondVar::wait()
745{
746    pthread_cond_wait(&mCondVar, *this);
747    pthread_mutex_unlock(*this);
748}
749
750/*******************************************************************************
751**
752** Function:    ThreadCondVar::signal()
753**
754** Description: signal the mCondVar
755**
756** Returns:     none
757**
758*******************************************************************************/
759void ThreadCondVar::signal()
760{
761    AutoThreadMutex  a(*this);
762    pthread_cond_signal(&mCondVar);
763}
764
765/*******************************************************************************
766**
767** Function:    AutoThreadMutex::AutoThreadMutex()
768**
769** Description: class constructor, automatically lock the mutex
770**
771** Returns:     none
772**
773*******************************************************************************/
774AutoThreadMutex::AutoThreadMutex(ThreadMutex &m)
775    : mm(m)
776{
777    mm.lock();
778}
779
780/*******************************************************************************
781**
782** Function:    AutoThreadMutex::~AutoThreadMutex()
783**
784** Description: class destructor, automatically unlock the mutex
785**
786** Returns:     none
787**
788*******************************************************************************/
789AutoThreadMutex::~AutoThreadMutex()
790{
791    mm.unlock();
792}
793