qtmobility/plugins/contacts/symbiansim/src/cntsimstoreprivate.cpp
changeset 14 6fbed849b4f4
parent 5 453da2cfceef
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
    65 CntSimStorePrivate::CntSimStorePrivate(CntSymbianSimEngine &engine, CntSimStore &simStore, const QString &storeName)
    65 CntSimStorePrivate::CntSimStorePrivate(CntSymbianSimEngine &engine, CntSimStore &simStore, const QString &storeName)
    66     :CActive(CActive::EPriorityStandard),
    66     :CActive(CActive::EPriorityStandard),
    67      m_state(InactiveState),
    67      m_state(InactiveState),
    68      m_engine(engine),
    68      m_engine(engine),
    69      m_simStore(simStore),
    69      m_simStore(simStore),
    70      m_storeName(storeName),
    70      m_listener(0),
    71      m_readOnlyAccess(false),
    71      m_extraDetailsChecked(false)
    72      m_storeInfoPckg(m_storeInfo),
       
    73      m_listener(0)
       
    74 {
    72 {
    75     CActiveScheduler::Add(this);
    73     CActiveScheduler::Add(this);
    76     m_managerUri = engine.managerUri();
    74     m_managerUri = engine.managerUri();
       
    75     
       
    76     // Initialize store info
       
    77     m_storeInfo.m_storeName                 = storeName;
       
    78     m_storeInfo.m_totalEntries              = -1;
       
    79     m_storeInfo.m_usedEntries               = -1;
       
    80     m_storeInfo.m_readOnlyAccess            = false; 
       
    81     m_storeInfo.m_numberSupported           = true; // allways supported
       
    82     m_storeInfo.m_nameSupported             = true; // allways supported
       
    83     m_storeInfo.m_secondNameSupported       = false;
       
    84     m_storeInfo.m_additionalNumberSupported = false;
       
    85     m_storeInfo.m_emailSupported            = false;
       
    86     
       
    87     // SDN store is allways read only
       
    88     if (m_storeInfo.m_storeName == KParameterValueSimStoreNameSdn)
       
    89         m_storeInfo.m_readOnlyAccess = true;
    77 }
    90 }
    78 
    91 
    79 void CntSimStorePrivate::ConstructL()
    92 void CntSimStorePrivate::ConstructL()
    80 {
    93 {
    81     TBuf<RMobilePhoneBookStore::KMaxPBIDSize> storeName;
    94     TBuf<RMobilePhoneBookStore::KMaxPBIDSize> storeName;
    82     convertStoreNameL(storeName);
    95     convertStoreNameL(storeName);
    83     
    96     
    84     // SDN store is always read only
       
    85     if (m_storeName == KParameterValueSimStoreNameSdn)
       
    86         m_readOnlyAccess = true;
       
    87 
       
    88     // Open etel server
    97     // Open etel server
    89     User::LeaveIfError(m_etelServer.Connect());
    98     User::LeaveIfError(m_etelServer.Connect());
    90     User::LeaveIfError(m_etelServer.LoadPhoneModule(KMmTsyModuleName));
    99     User::LeaveIfError(m_etelServer.LoadPhoneModule(KMmTsyModuleName));
    91 
   100 
    92     // Open etel phone
   101     // Open etel phone
    93     RTelServer::TPhoneInfo info;
   102     RTelServer::TPhoneInfo info;
    94     User::LeaveIfError(m_etelServer.GetPhoneInfo(0, info));
   103     User::LeaveIfError(m_etelServer.GetPhoneInfo(0, info));
    95     User::LeaveIfError(m_etelPhone.Open(m_etelServer, info.iName));
   104     User::LeaveIfError(m_etelPhone.Open(m_etelServer, info.iName));
    96     
   105     
    97     // open Etel store
   106     // Open Etel store
    98     User::LeaveIfError(m_etelStore.Open(m_etelPhone, storeName));
   107     User::LeaveIfError(m_etelStore.Open(m_etelPhone, storeName));
    99     
   108 
   100     //check what information can be saved to the Etel store
   109     // Update store info
   101     TRequestStatus requestStatus;
   110     updateStoreInfoL();
   102     m_etelStore.GetInfo(requestStatus, (TDes8&)m_storeInfoPckg);
   111     
   103     User::WaitForRequest(requestStatus);
   112     // Start listening for events
   104     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - GetInfo err = %d"),
       
   105         requestStatus.Int());
       
   106     User::LeaveIfError(requestStatus.Int());
       
   107 
       
   108     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - TotalEntries = %d"),
       
   109             m_storeInfo.iTotalEntries);
       
   110     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - UsedEntries = %d"),
       
   111             m_storeInfo.iUsedEntries);
       
   112     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - MaxNumLength = %d"),
       
   113             m_storeInfo.iMaxNumLength);
       
   114     PbkPrintToLog(_L("CntSymbianSimEngine::getEtelStoreInfoL() - MaxTextLength = %d"),
       
   115             m_storeInfo.iMaxTextLength);
       
   116     
       
   117     m_listener = new (ELeave) CntSimStoreEventListener(m_engine, m_etelStore);
   113     m_listener = new (ELeave) CntSimStoreEventListener(m_engine, m_etelStore);
   118     m_listener->start();
   114     m_listener->start();
   119 }
   115 }
   120 
   116 
   121 CntSimStorePrivate::~CntSimStorePrivate()
   117 CntSimStorePrivate::~CntSimStorePrivate()
   131 {
   127 {
   132     if(storeName.MaxLength() < RMobilePhoneBookStore::KMaxPBIDSize) {
   128     if(storeName.MaxLength() < RMobilePhoneBookStore::KMaxPBIDSize) {
   133         User::Leave(KErrArgument);
   129         User::Leave(KErrArgument);
   134     }
   130     }
   135 
   131 
   136     if (m_storeName.isEmpty()) {
   132     if (m_storeInfo.m_storeName.isEmpty()) {
   137         // Default to ADN store
   133         // Default to ADN store
   138         m_storeName = (QLatin1String) KParameterValueSimStoreNameAdn;
   134         m_storeInfo.m_storeName = (QLatin1String) KParameterValueSimStoreNameAdn;
   139         storeName.Copy(KETelIccAdnPhoneBook);
   135         storeName.Copy(KETelIccAdnPhoneBook);
   140     } else if (m_storeName == KParameterValueSimStoreNameFdn) {
   136     } else if (m_storeInfo.m_storeName == KParameterValueSimStoreNameFdn) {
   141         storeName.Copy(KETelIccFdnPhoneBook);
   137         storeName.Copy(KETelIccFdnPhoneBook);
   142     } else if (m_storeName == KParameterValueSimStoreNameAdn) {
   138     } else if (m_storeInfo.m_storeName == KParameterValueSimStoreNameAdn) {
   143         storeName.Copy(KETelIccAdnPhoneBook);
   139         storeName.Copy(KETelIccAdnPhoneBook);
   144     } else if (m_storeName == KParameterValueSimStoreNameSdn) {
   140     } else if (m_storeInfo.m_storeName == KParameterValueSimStoreNameSdn) {
   145         storeName.Copy(KETelIccSdnPhoneBook);
   141         storeName.Copy(KETelIccSdnPhoneBook);
   146     }
   142     }
   147 
   143 
   148     // Check that we got a valid store name
   144     // Check that we got a valid store name
   149     if(storeName.Length() == 0) {
   145     if(storeName.Length() == 0) {
   231         return false;
   227         return false;
   232     }
   228     }
   233     
   229     
   234     // start reading
   230     // start reading
   235     m_buffer.Zero();
   231     m_buffer.Zero();
   236     m_buffer.ReAlloc(KOneSimContactBufferSize*m_storeInfo.iTotalEntries);
   232     m_buffer.ReAlloc(KOneSimContactBufferSize*m_storeInfo.m_totalEntries);
   237     m_etelStore.Read(iStatus, 1, m_storeInfo.iTotalEntries, m_buffer);
   233     m_etelStore.Read(iStatus, 1, m_storeInfo.m_totalEntries, m_buffer);
   238     SetActive();
   234     SetActive();
   239     m_state = ReadReservedSlotsState;
   235     m_state = ReadReservedSlotsState;
   240     
   236     
   241     *error = QContactManager::NoError;
   237     *error = QContactManager::NoError;
   242     return true;  
   238     return true;  
   269     {
   265     {
   270         case ReadState:
   266         case ReadState:
   271         {
   267         {
   272             QList<QContact> contacts = decodeSimContactsL(m_buffer);
   268             QList<QContact> contacts = decodeSimContactsL(m_buffer);
   273 
   269 
   274             // set sync target and set type as read only
   270             // set sync target and read only access constraint and display label
   275             QList<QContact>::iterator i;
   271             QList<QContact>::iterator i;
   276             for (i = contacts.begin(); i != contacts.end(); ++i) {
   272             for (i = contacts.begin(); i != contacts.end(); ++i) {
   277                 QContactSyncTarget syncTarget;
   273                 QContactSyncTarget syncTarget;
   278                 syncTarget.setSyncTarget(KSimSyncTarget);
   274                 syncTarget.setSyncTarget(KSimSyncTarget);
   279                 m_engine.setReadOnlyAccessConstraint(&syncTarget);
   275                 m_engine.setReadOnlyAccessConstraint(&syncTarget);
   280                 i->saveDetail(&syncTarget);
   276                 i->saveDetail(&syncTarget);
   281                 QContactType contactType = i->detail(QContactType::DefinitionName);
   277                 QContactType contactType = i->detail(QContactType::DefinitionName);
   282                 m_engine.setReadOnlyAccessConstraint(&contactType);
   278                 m_engine.setReadOnlyAccessConstraint(&contactType);
   283                 i->saveDetail(&contactType);
   279                 i->saveDetail(&contactType);
       
   280                 m_engine.updateDisplayLabel(*i);
   284             }
   281             }
   285             
   282             
   286             emit m_simStore.readComplete(contacts, QContactManager::NoError);
   283             emit m_simStore.readComplete(contacts, QContactManager::NoError);
   287         }
   284         }
   288         break;
   285         break;
   415                             QContactPhoneNumber lastNumber = static_cast<QContactPhoneNumber>(
   412                             QContactPhoneNumber lastNumber = static_cast<QContactPhoneNumber>(
   416                                 phoneNumbers.at(phoneNumbers.count() - 1));
   413                                 phoneNumbers.at(phoneNumbers.count() - 1));
   417                             QString number = lastNumber.number();
   414                             QString number = lastNumber.number();
   418                             number.insert(0, "+");
   415                             number.insert(0, "+");
   419                             lastNumber.setNumber(number);
   416                             lastNumber.setNumber(number);
   420                             if (m_readOnlyAccess)
   417                             if (m_storeInfo.m_readOnlyAccess)
   421                                 m_engine.setReadOnlyAccessConstraint(&lastNumber);
   418                                 m_engine.setReadOnlyAccessConstraint(&lastNumber);
   422                             currentContact.saveDetail(&lastNumber);
   419                             currentContact.saveDetail(&lastNumber);
   423                         }
   420                         }
   424                     }
   421                     }
   425                 }
   422                 }
   439                     else {
   436                     else {
   440                         // Contact name otherwise
   437                         // Contact name otherwise
   441                         QContactName name;
   438                         QContactName name;
   442                         QString nameString = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   439                         QString nameString = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   443                         name.setCustomLabel(nameString);
   440                         name.setCustomLabel(nameString);
   444                         if (m_readOnlyAccess)
   441                         if (m_storeInfo.m_readOnlyAccess)
   445                             m_engine.setReadOnlyAccessConstraint(&name);
   442                             m_engine.setReadOnlyAccessConstraint(&name);
   446                         currentContact.saveDetail(&name);
   443                         currentContact.saveDetail(&name);
   447                         QContactManager::Error error(QContactManager::NoError);
   444                         QContactManager::Error error(QContactManager::NoError);
   448                         m_engine.setContactDisplayLabel(&currentContact, m_engine.synthesizedDisplayLabel(currentContact, &error));
   445                         m_engine.setContactDisplayLabel(&currentContact, m_engine.synthesizedDisplayLabel(currentContact, &error));
   449                     }
   446                     }
   454             {
   451             {
   455                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   452                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   456                     QContactNickname nickName;
   453                     QContactNickname nickName;
   457                     QString name = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   454                     QString name = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   458                     nickName.setNickname(name);
   455                     nickName.setNickname(name);
   459                     if (m_readOnlyAccess)
   456                     if (m_storeInfo.m_readOnlyAccess)
   460                         m_engine.setReadOnlyAccessConstraint(&nickName);
   457                         m_engine.setReadOnlyAccessConstraint(&nickName);
   461                     currentContact.saveDetail(&nickName);
   458                     currentContact.saveDetail(&nickName);
   462                 }
   459                 }
   463                 break;
   460                 break;
   464             }
   461             }
   466             {
   463             {
   467                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   464                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   468                     QContactPhoneNumber phoneNumber;
   465                     QContactPhoneNumber phoneNumber;
   469                     QString number = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   466                     QString number = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   470                     phoneNumber.setNumber(number);
   467                     phoneNumber.setNumber(number);
   471                     if (m_readOnlyAccess)
   468                     if (m_storeInfo.m_readOnlyAccess)
   472                         m_engine.setReadOnlyAccessConstraint(&phoneNumber);
   469                         m_engine.setReadOnlyAccessConstraint(&phoneNumber);
   473                     currentContact.saveDetail(&phoneNumber);
   470                     currentContact.saveDetail(&phoneNumber);
   474                 }
   471                 }
   475                 break;
   472                 break;
   476             }
   473             }
   484             {
   481             {
   485                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   482                 if (pbBuffer->GetValue(bufPtr) == KErrNone) {
   486                     QContactEmailAddress email;
   483                     QContactEmailAddress email;
   487                     QString emailAddress = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   484                     QString emailAddress = QString::fromUtf16(bufPtr.Ptr(), bufPtr.Length());
   488                     email.setEmailAddress(emailAddress);
   485                     email.setEmailAddress(emailAddress);
   489                     if (m_readOnlyAccess)
   486                     if (m_storeInfo.m_readOnlyAccess)
   490                         m_engine.setReadOnlyAccessConstraint(&email);
   487                         m_engine.setReadOnlyAccessConstraint(&email);
   491                     currentContact.saveDetail(&email);
   488                     currentContact.saveDetail(&email);
   492                 }
   489                 }
   493                 break;
   490                 break;
   494             }
   491             }
   529  * \param contact QContact to be converted
   526  * \param contact QContact to be converted
   530  * \param rawData Contact in TLV format on return.
   527  * \param rawData Contact in TLV format on return.
   531 */
   528 */
   532 void CntSimStorePrivate::encodeSimContactL(QContact* contact, TDes8& rawData) const
   529 void CntSimStorePrivate::encodeSimContactL(QContact* contact, TDes8& rawData) const
   533 {
   530 {
   534     // TODO: get detail definition schema and verify (unique)
       
   535 
       
   536     // Keep track of the count of phone numbers added
   531     // Keep track of the count of phone numbers added
   537     int phoneNumberCount(0);
   532     int phoneNumberCount(0);
   538     int emailCount(0);
   533 
   539 
   534     // Create buffer
   540     CPhoneBookBuffer* pbBuffer = new(ELeave) CPhoneBookBuffer();
   535     CPhoneBookBuffer* pbBuffer = new(ELeave) CPhoneBookBuffer();
   541     CleanupStack::PushL(pbBuffer);
   536     CleanupStack::PushL(pbBuffer);
   542     pbBuffer->Set(&rawData);
   537     pbBuffer->Set(&rawData);
   543     User::LeaveIfError(pbBuffer->AddNewEntryTag());
   538     User::LeaveIfError(pbBuffer->AddNewEntryTag());
   544 
   539 
   545     foreach(QContactDetail detail, contact->details()) {
   540     // Loop through details
       
   541     foreach(QContactDetail detail, contact->details()) 
       
   542     {
   546         QString definitionName = detail.definitionName();
   543         QString definitionName = detail.definitionName();
   547 
   544         
   548         if (definitionName == QContactName::DefinitionName) {
   545         // NOTE: If the detail is too long let the etel store return
   549             // Name
   546         // an error about it. We could check the maximum lenghts for each
       
   547         // detail but then we would need to read it before every write operation
       
   548         // bacause it seems to change depending on how full the sim card is.
       
   549 
       
   550         // Name
       
   551         if (definitionName == QContactName::DefinitionName) 
       
   552         {
   550             QContactName nameDetail = static_cast<QContactName>(detail);
   553             QContactName nameDetail = static_cast<QContactName>(detail);
   551             // Trim to the max possible length
   554             QString name = nameDetail.customLabel();
   552             QString name = nameDetail.customLabel().left(m_storeInfo.iMaxTextLength);
   555             putTagAndValueL(pbBuffer, RMobilePhoneBookStore::ETagPBText, name);
   553             if (name.isEmpty()) {
   556         }
   554                 name = "Unnamed";
   557         // Phone number
   555             }
   558         else if (definitionName == QContactPhoneNumber::DefinitionName)
   556             putTagAndValueL(
   559         {
   557                 pbBuffer,
   560             if (m_storeInfo.m_additionalNumberSupported == false && phoneNumberCount>0)
   558                 RMobilePhoneBookStore::ETagPBText,
   561                 User::Leave(KErrNotSupported);
   559                 name);
   562 
   560             // Replace detail value with the trimmed one
       
   561             nameDetail.setCustomLabel(name);
       
   562             contact->saveDetail(&nameDetail);
       
   563         } else if (definitionName == QContactPhoneNumber::DefinitionName
       
   564 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
       
   565             && (phoneNumberCount == 0
       
   566             || phoneNumberCount <= m_storeInfo.iMaxAdditionalNumbers)) {
       
   567 #else
       
   568             && phoneNumberCount == 0) {
       
   569 #endif
       
   570             // Phone number
       
   571             phoneNumberCount++;
   563             phoneNumberCount++;
   572             QContactPhoneNumber numberDetail = static_cast<QContactPhoneNumber>(detail);
   564             QString number = static_cast<QContactPhoneNumber>(detail).number();
   573             QString number = numberDetail.number();
   565             if (number.isEmpty())
       
   566                 continue;
   574 
   567 
   575             // Verify the number only contains legal digits
   568             // Verify the number only contains legal digits
   576             foreach (const QChar character, number) {
   569             foreach (const QChar character, number) {
   577                 if(!character.isDigit()) {
   570                 if(!character.isDigit()) {
   578                     if(character != QChar('+')
   571                     if(character != QChar('+')
   583                         User::Leave(KErrArgument);
   576                         User::Leave(KErrArgument);
   584                     }
   577                     }
   585                 }
   578                 }
   586             }
   579             }
   587 
   580 
   588             // TODO: check if the number is empty (do we have a test case for that?)
       
   589 
       
   590             // Verify the number length
       
   591             PbkPrintToLog(_L("CntSymbianSimEngine::encodeSimContactL() - phone number length = %d"),
       
   592                 numberDetail.number().length());
       
   593             if (numberDetail.number().length() > m_storeInfo.iMaxNumLength) {
       
   594                 User::Leave(KErrTooBig);
       
   595             }
       
   596 
       
   597             if (phoneNumberCount > 1) {
   581             if (phoneNumberCount > 1) {
   598                 // Mark the beginning of an additional number
   582                 // Mark the beginning of an additional number
   599                 User::LeaveIfError(pbBuffer->AddNewNumberTag());
   583                 User::LeaveIfError(pbBuffer->AddNewNumberTag());
   600             }
   584             }
   601 
   585 
   602             // The number itself
   586             // The number itself
   603             putTagAndValueL(
   587             putTagAndValueL(pbBuffer, RMobilePhoneBookStore::ETagPBNumber, number);
   604                 pbBuffer,
   588         }
   605                 RMobilePhoneBookStore::ETagPBNumber,
   589         // Nickname
   606                 number);
   590         else if (definitionName == QContactNickname::DefinitionName)
   607 #ifndef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
   591         {
   608         // Phonebook info version 1 does not support nick name or e-mail
   592             if (m_storeInfo.m_secondNameSupported == false)
   609         } else if (definitionName == QContactNickname::DefinitionName
   593                 User::Leave(KErrNotSupported);
   610             && m_storeInfo.iMaxSecondNames > 0) {
   594             
   611             // nickname
   595             QString nickname = static_cast<QContactNickname>(detail).nickname();
   612             QContactNickname nicknameDetail = static_cast<QContactNickname>(detail);
   596             if (nickname.isEmpty())
   613             // Trim to the max possible length;
   597                 continue;
   614             QString nickname = nicknameDetail.nickname().left(m_storeInfo.iMaxTextLengthSecondName);
   598             
   615             putTagAndValueL(
   599             putTagAndValueL(pbBuffer, RMobilePhoneBookStore::ETagPBSecondName, nickname);
   616                 pbBuffer,
   600         } 
   617                 RMobilePhoneBookStore::ETagPBSecondName,
   601         // email
   618                 nickname);
   602         else if (definitionName == QContactEmailAddress::DefinitionName)
   619             // Replace detail value with the trimmed one
   603         {
   620             nicknameDetail.setNickname(nickname);
   604             if (m_storeInfo.m_emailSupported == false)
   621             contact->saveDetail(&nicknameDetail);
   605                 User::Leave(KErrNotSupported);
   622         } else if (definitionName == QContactEmailAddress::DefinitionName
   606             
   623             && emailCount < m_storeInfo.iMaxEmailAddr) {
   607             QString email = static_cast<QContactEmailAddress>(detail).emailAddress();
   624             emailCount++;
   608             if (email.isEmpty())
   625             QContactEmailAddress emailDetail = static_cast<QContactEmailAddress>(detail);
   609                 continue;            
   626             if (emailDetail.emailAddress().length() > m_storeInfo.iMaxTextLengthEmailAddr) {
   610             
   627                 User::Leave(KErrTooBig);
   611             putTagAndValueL(pbBuffer, RMobilePhoneBookStore::ETagPBEmailAddress, email);
   628             }
   612         }
   629             putTagAndValueL(
       
   630                 pbBuffer,
       
   631                 RMobilePhoneBookStore::ETagPBEmailAddress,
       
   632                 emailDetail.emailAddress());
       
   633 #endif
       
   634         // These are ignored in the conversion
   613         // These are ignored in the conversion
   635         } else if (definitionName == QContactSyncTarget::DefinitionName
   614         else if (definitionName == QContactSyncTarget::DefinitionName
   636             || definitionName == QContactDisplayLabel::DefinitionName
   615             || definitionName == QContactDisplayLabel::DefinitionName
   637             || definitionName == QContactType::DefinitionName) {
   616             || definitionName == QContactType::DefinitionName) 
       
   617         {
   638             // Do nothing
   618             // Do nothing
   639         } else {
   619         } 
       
   620         else 
       
   621         {
       
   622             // Unknown detail
   640             User::Leave(KErrArgument);
   623             User::Leave(KErrArgument);
   641         }
   624         }
   642     }
   625     }
   643     CleanupStack::PopAndDestroy(pbBuffer);
   626     CleanupStack::PopAndDestroy(pbBuffer);
   644 }
   627 }
   673     } //while
   656     } //while
   674     
   657     
   675     CleanupStack::PopAndDestroy(pbBuffer);
   658     CleanupStack::PopAndDestroy(pbBuffer);
   676     return reservedSlots;
   659     return reservedSlots;
   677 }
   660 }
       
   661 
       
   662 void CntSimStorePrivate::writeL(QContact *contact)
       
   663 {
       
   664     if (IsActive())
       
   665         User::Leave(KErrLocked);
       
   666     
       
   667     // get index
       
   668     int index = KErrNotFound;
       
   669     if (contact->id().managerUri() == m_managerUri &&
       
   670         contact->localId() > 0) {
       
   671         index = contact->localId();
       
   672     }
       
   673     
       
   674     // encode
       
   675     m_buffer.Zero();
       
   676     m_buffer.ReAlloc(KOneSimContactBufferSize);
       
   677     encodeSimContactL(contact, m_buffer);
       
   678 
       
   679     // write
       
   680     TRequestStatus status;
       
   681     m_etelStore.Write(status, m_buffer, index);
       
   682     User::WaitForRequest(status);
       
   683     User::LeaveIfError(status.Int());
       
   684     
       
   685     // update id
       
   686     QContactId id;
       
   687     id.setLocalId(index);
       
   688     id.setManagerUri(m_managerUri);
       
   689     contact->setId(id);
       
   690 }
       
   691 
       
   692 void CntSimStorePrivate::removeL(int index)
       
   693 {
       
   694     if (IsActive())
       
   695         User::Leave(KErrLocked);
       
   696     
       
   697     // NOTE:
       
   698     // If index points to an empty slot and running in hardware the 
       
   699     // delete operation will not return any error.
       
   700     
       
   701     TRequestStatus status;
       
   702     m_etelStore.Delete(status, index);
       
   703     User::WaitForRequest(status);
       
   704     User::LeaveIfError(status.Int());
       
   705 }
       
   706 
       
   707 void CntSimStorePrivate::updateStoreInfoL()
       
   708 {
       
   709 #ifdef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
       
   710     RMobilePhoneBookStore::TMobilePhoneBookInfoV1 info;
       
   711     RMobilePhoneBookStore::TMobilePhoneBookInfoV1Pckg infoPckg(info);
       
   712 #else
       
   713     RMobilePhoneBookStore::TMobilePhoneBookInfoV5 info;
       
   714     RMobilePhoneBookStore::TMobilePhoneBookInfoV5Pckg infoPckg(info);
       
   715 #endif
       
   716 
       
   717     // Get info
       
   718     TRequestStatus status;
       
   719     m_etelStore.GetInfo(status, infoPckg);
       
   720     User::WaitForRequest(status);
       
   721     User::LeaveIfError(status.Int());
       
   722 
       
   723     // Update entry counts
       
   724     m_storeInfo.m_totalEntries = info.iTotalEntries;
       
   725     m_storeInfo.m_usedEntries  = info.iUsedEntries;
       
   726     
       
   727 #ifdef SYMBIANSIM_BACKEND_TEST_EXTRADETAILS
       
   728     // Check if store supports the extra details
       
   729     //
       
   730     // NOTE: 
       
   731     // We cannot rely on TMobilePhoneBookInfoV5 to check if we support
       
   732     // these details. For example iMaxSecondNames is allways -1 even if the sim
       
   733     // card supports a second name.
       
   734     //
       
   735     // There is an API for checking these but it's Nokia internal so we must
       
   736     // do it this way - by checking if saving these details is possible.
       
   737     
       
   738     // Have we checked these already?
       
   739     if (m_extraDetailsChecked == false)
       
   740     {
       
   741         // Cannot test extra details if sim card is full 
       
   742         if (m_storeInfo.m_usedEntries == m_storeInfo.m_totalEntries)
       
   743             return;
       
   744 
       
   745         // Cancel store event listener temporarily
       
   746         if (m_listener)
       
   747             m_listener->Cancel();
       
   748 
       
   749         // Test writing nickname
       
   750         QContact contact;
       
   751         QContactNickname nick;
       
   752         nick.setNickname("simbackend test");
       
   753         contact.saveDetail(&nick);
       
   754         TRAPD(err, {
       
   755             m_storeInfo.m_secondNameSupported = true; // enable to pass encodeSimContactL()
       
   756             writeL(&contact);
       
   757             removeL(contact.localId());
       
   758         } );
       
   759         if (err)
       
   760             m_storeInfo.m_secondNameSupported = false;
       
   761 
       
   762         // Test writing additional number
       
   763         contact = QContact();
       
   764         QContactPhoneNumber num1;
       
   765         num1.setNumber("1111111111");
       
   766         contact.saveDetail(&num1);
       
   767         QContactPhoneNumber num2;
       
   768         num2.setNumber("2222222222");
       
   769         contact.saveDetail(&num2);
       
   770         TRAP(err, {
       
   771             m_storeInfo.m_additionalNumberSupported = true; // enable to pass encodeSimContactL()
       
   772             writeL(&contact); 
       
   773             removeL(contact.localId()); 
       
   774         } );
       
   775         if (err)
       
   776             m_storeInfo.m_additionalNumberSupported = false;
       
   777 
       
   778         // Test writing email
       
   779         contact = QContact();
       
   780         QContactEmailAddress email;
       
   781         email.setEmailAddress("simbackend@test.com");
       
   782         contact.saveDetail(&email);
       
   783         TRAP(err, {
       
   784             m_storeInfo.m_emailSupported = true; // enable to pass encodeSimContactL()
       
   785             writeL(&contact); 
       
   786             removeL(contact.localId()); 
       
   787         } );
       
   788         if (err)
       
   789             m_storeInfo.m_emailSupported = false;
       
   790 
       
   791         // Start store event listener again
       
   792         if (m_listener)
       
   793             m_listener->start();
       
   794 
       
   795         m_extraDetailsChecked = true;
       
   796     }
       
   797 #endif
       
   798 
       
   799     /*
       
   800     qDebug() << "Store info:"
       
   801         << "\nStore name                :" << m_storeInfo.m_storeName
       
   802         << "\nTotal entries             :" << m_storeInfo.m_totalEntries
       
   803         << "\nUsed entries              :" << m_storeInfo.m_usedEntries
       
   804         << "\nRead only access          :" << m_storeInfo.m_readOnlyAccess
       
   805         << "\nNumber supported          :" << m_storeInfo.m_numberSupported
       
   806         << "\nName supported            :" << m_storeInfo.m_nameSupported
       
   807         << "\nSecond name supported     :" << m_storeInfo.m_secondNameSupported
       
   808         << "\nAdditional name supported :" << m_storeInfo.m_additionalNumberSupported
       
   809         << "\nEmail supported           :" << m_storeInfo.m_emailSupported;
       
   810     */
       
   811 }