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