14e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park/** @addtogroup MCD_IMPL_LIB 24e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * @{ 34e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * @file 44e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 54e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * Client library device management. 64e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 74e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * Device and Trustlet Session management Funtions. 84e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 94e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 --> 109081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim * 114e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * Redistribution and use in source and binary forms, with or without 124e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * modification, are permitted provided that the following conditions 134e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * are met: 144e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 1. Redistributions of source code must retain the above copyright 154e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * notice, this list of conditions and the following disclaimer. 164e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 2. Redistributions in binary form must reproduce the above copyright 174e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * notice, this list of conditions and the following disclaimer in the 184e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * documentation and/or other materials provided with the distribution. 194e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 3. The name of the author may not be used to endorse or promote 204e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * products derived from this software without specific prior 214e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * written permission. 224e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 234e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 244e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 254e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 264e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 274e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 284e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 294e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 304e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 314e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 324e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 334e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 344e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park */ 354e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <stdint.h> 364e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <vector> 374e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 389081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim#include "mc_linux.h" 394e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include "Device.h" 404e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 414e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include "log.h" 427b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim#include <assert.h> 434e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 444e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 454e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 469081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun KimDevice::Device(uint32_t deviceId, Connection *connection) 479081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 487b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim this->deviceId = deviceId; 497b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim this->connection = connection; 504e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 517b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim pMcKMod = new CMcKMod(); 524e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 534e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 544e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 554e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 569081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun KimDevice::~Device(void) 579081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 587b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim /* Delete all session objects. Usually this should not be needed as closeDevice() 597b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim * requires that all sessions have been closed before. 607b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim */ 617b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim sessionIterator_t sessionIterator = sessionList.begin(); 627b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim while (sessionIterator != sessionList.end()) { 637b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim delete (*sessionIterator); 647b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim sessionIterator = sessionList.erase(sessionIterator); 657b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 667b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 677b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // Free all allocated WSM descriptors 687b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim wsmIterator_t wsmIterator = wsmL2List.begin(); 697b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim while (wsmIterator != wsmL2List.end()) { 707b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim CWsm_ptr pWsm = *wsmIterator; 717b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 727b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // ignore return code 737b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim pMcKMod->free(pWsm->handle, pWsm->virtAddr, pWsm->len); 747b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 757b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim delete (*wsmIterator); 767b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim wsmIterator = wsmL2List.erase(wsmIterator); 777b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 787b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim delete connection; 797b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim delete pMcKMod; 804e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 814e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 824e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 834e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 847b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kimbool Device::open(const char *deviceName) 859081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 867b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return pMcKMod->open(deviceName); 874e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 884e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 894e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 904e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 919081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kimvoid Device::close(void) 929081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 937b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim pMcKMod->close(); 944e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 954e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 964e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 974e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 989081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kimbool Device::hasSessions(void) 999081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 1007b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return sessionList.size() > 0; 1014e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 1024e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1034e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1044e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 1059081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kimvoid Device::createNewSession(uint32_t sessionId, Connection *connection) 1069081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 1077b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim Session *session = new Session(sessionId, pMcKMod, connection); 1087b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim sessionList.push_back(session); 1094e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 1104e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1114e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1124e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 1139081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kimbool Device::removeSession(uint32_t sessionId) 1149081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 1157b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim bool ret = false; 1167b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 1177b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim sessionIterator_t interator = sessionList.begin(); 1187b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim while (interator != sessionList.end()) { 1197b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if ((*interator)->sessionId == sessionId) { 1207b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim delete (*interator); 1217b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim interator = sessionList.erase(interator); 1227b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ret = true; 1237b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim break; 1247b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } else { 1257b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim interator++; 1267b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1277b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1287b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return ret; 1294e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 1304e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1314e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1324e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 1339081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun KimSession *Device::resolveSessionId(uint32_t sessionId) 1349081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 1357b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim Session *ret = NULL; 1367b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 1377b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // Get Session for sessionId 1387b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim for ( sessionIterator_t interator = sessionList.begin(); 1397b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim interator != sessionList.end(); 1407b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ++interator) { 1417b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if ((*interator)->sessionId == sessionId) { 1427b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ret = (*interator); 1437b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim break; 1447b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1457b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1467b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return ret; 1474e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 1484e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1494e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1504e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 1517b143edf281bed18c8ebd0733465f3af5af327ebJungtae KimmcResult_t Device::allocateContiguousWsm(uint32_t len, CWsm **wsm) 1529081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 1537b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // Allocate shared memory 1547b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim addr_t virtAddr; 1557b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim uint32_t handle; 1567b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim addr_t physAddr; 1577b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim mcResult_t ret; 1589081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim 1597b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim assert(wsm != NULL); 1604e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1617b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if (!len) { 1627b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return MC_DRV_ERR_INVALID_LENGTH; 1637b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1644e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1657b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ret = pMcKMod->mapWsm(len, &handle, &virtAddr, &physAddr); 1667b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if (ret) { 1677b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return ret; 1687b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1699081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim 1707b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim LOG_I(" mapped handle %d to %p, phys=%p ", handle, virtAddr, physAddr); 1719081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim 1727b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // Register (vaddr,paddr) with device 1737b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim *wsm = new CWsm(virtAddr, len, handle, physAddr); 1744e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1757b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim wsmL2List.push_back(*wsm); 1767b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 1777b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // Return pointer to the allocated memory 1787b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return MC_DRV_OK; 1794e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 1804e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1814e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 1824e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 1837b143edf281bed18c8ebd0733465f3af5af327ebJungtae KimmcResult_t Device::freeContiguousWsm(CWsm_ptr pWsm) 1849081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 1857b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim mcResult_t ret = MC_DRV_ERR_WSM_NOT_FOUND; 1867b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim wsmIterator_t iterator; 1877b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 1887b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim for (iterator = wsmL2List.begin(); iterator != wsmL2List.end(); ++iterator) { 1897b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if (pWsm == *iterator) { 1907b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ret = MC_DRV_OK; 1917b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim break; 1927b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1937b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 1947b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // We just looked this up using findContiguousWsm 1957b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim assert(ret == MC_DRV_OK); 1967b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 1977b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim LOG_I(" unmapping handle %d from %p, phys=%p", 1987b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim pWsm->handle, pWsm->virtAddr, pWsm->physAddr); 1997b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 2007b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ret = pMcKMod->free(pWsm->handle, pWsm->virtAddr, pWsm->len); 2017b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if (ret != MC_DRV_OK) { 2027b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim // developer forgot to free all references of this memory, we do not remove the reference here 2037b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return ret; 2047b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 2057b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 2067b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim iterator = wsmL2List.erase(iterator); 2077b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim delete pWsm; 2087b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 2097b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return ret; 2104e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 2114e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 2124e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 2134e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------ 2149081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun KimCWsm_ptr Device::findContiguousWsm(addr_t virtAddr) 2159081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim{ 2167b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim CWsm_ptr pWsm = NULL; 2177b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 2187b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim for ( wsmIterator_t iterator = wsmL2List.begin(); 2197b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim iterator != wsmL2List.end(); 2207b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim ++iterator) { 2217b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim CWsm_ptr pTmpWsm = *iterator; 2227b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim if (virtAddr == pTmpWsm->virtAddr) { 2237b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim pWsm = pTmpWsm; 2247b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim break; 2257b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 2267b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim } 2277b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim 2287b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim return pWsm; 2294e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park} 2304e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park 2314e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park/** @} */ 232