mtpfws/mtpfw/datatypes/src/cmtptypeservicepropdesclist.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:11:40 +0200
changeset 0 d0791faffa3f
permissions -rw-r--r--
Revision: 201003 Kit: 201005

// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// 

/**
@file
@internalComponent
*/

#include <mtp/cmtptypeservicepropdesclist.h>
#include <mtp/mtpdatatypeconstants.h>
#include <mtp/mtpprotocolconstants.h>

#include "mtpdatatypespanic.h"

// Dataset constants

const TUint CMTPTypeServicePropDesc::KFlat1ChunkSize(6);
const TUint CMTPTypeServicePropDesc::KNumChunksWithoutForm(EIdFlat1Chunk + 1);
const TUint CMTPTypeServicePropDesc::KNumChunksWithForm(EIdFormChunk + 1);

//Dataset element metadata    
const CMTPTypeCompoundBase::TElementInfo CMTPTypeServicePropDesc::iElementMetaData[CMTPTypeServicePropDesc::ENumElements] = 
    {
        {EIdFlat1Chunk,       EMTPTypeFlat,       {EMTPTypeUINT16,    0,                  KMTPTypeUINT16Size}},   // EServicePropertyCode
        {EIdFlat1Chunk,       EMTPTypeFlat,       {EMTPTypeUINT16,    2,                  KMTPTypeUINT16Size}},   // EDataType1
        {EIdFlat1Chunk,       EMTPTypeFlat,       {EMTPTypeUINT8,     4,                  KMTPTypeUINT8Size}},   // EGetSet1
        {EIdFlat1Chunk,       EMTPTypeFlat,       {EMTPTypeUINT8,     5,                  KMTPTypeUINT8Size}},    // EFormFlag
        {EIdFormChunk,        EMTPTypeReference,  {EMTPTypeUndefined, KMTPNotApplicable,  KMTPNotApplicable}},    // EForm
    };



EXPORT_C CMTPTypeServicePropDescList* CMTPTypeServicePropDescList::NewL()
    {
    CMTPTypeServicePropDescList* self = CMTPTypeServicePropDescList::NewLC(); 
    CleanupStack::Pop(self);
    return self;  
    }


EXPORT_C CMTPTypeServicePropDescList* CMTPTypeServicePropDescList::NewLC()
    {
    CMTPTypeServicePropDescList* self = new(ELeave) CMTPTypeServicePropDescList();
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }

/**
Destructor.
*/
EXPORT_C CMTPTypeServicePropDescList::~CMTPTypeServicePropDescList()
    {
    
    }

CMTPTypeServicePropDescList::CMTPTypeServicePropDescList() :
CMTPTypeList(EMTPTypeServicePropDescList,EMTPTypeServicePropDesc)
    {
    }

void CMTPTypeServicePropDescList::ConstructL()
    {
    InitListL();
    }

EXPORT_C void CMTPTypeServicePropDescList::AppendL(CMTPTypeServicePropDesc* aElement)
    {
    CMTPTypeList::AppendL(aElement);
    }

EXPORT_C CMTPTypeServicePropDesc& CMTPTypeServicePropDescList::ElementL(TUint aIndex) const
    {
    return static_cast<CMTPTypeServicePropDesc&>( CMTPTypeList::ElementL(aIndex) );
    }

/**
MTP Service Object Property Extension FORM dataset factory method. This method is used to 
create an empty MTP Service Object Property Extension FORM  of the specified Datatype. 
@return A pointer to the form type. Ownership IS 
transfered.
@leave One of the system wide error codes, if unsuccessful.
*/ 
EXPORT_C  CMTPTypeServicePropDesc* CMTPTypeServicePropDesc::NewL()
    {
    CMTPTypeServicePropDesc* self = CMTPTypeServicePropDesc::NewLC();
    CleanupStack::Pop(self); 
    return self;
    }
/**
MTP DevicePropDesc  Service Object Property Extension FORM  factory method. This method is used to 
create an empty MTP Service Object Property Extension FORM  of the specified Datatype. 
@return A pointer to the form type. Ownership IS 
transfered.
@leave One of the system wide error codes, if unsuccessful.
*/
EXPORT_C  CMTPTypeServicePropDesc* CMTPTypeServicePropDesc::NewLC()
    {
    CMTPTypeServicePropDesc* self = new(ELeave) CMTPTypeServicePropDesc();
    CleanupStack::PushL(self);
    const TUint16 KUndefinedCode = 0; 
    self->ConstructL( KUndefinedCode , EMTPTypeUndefined,CMTPTypeObjectPropDesc::EReadOnly , CMTPTypeObjectPropDesc::ENone, NULL );
    return self;
    }
   
EXPORT_C  CMTPTypeServicePropDesc* CMTPTypeServicePropDesc::NewL( const TUint16  aServicePropCode, const TUint16 aDataType, const TUint8 aGetSet, const TUint8 aFormFlag, const MMTPType* aForm )
    {
    CMTPTypeServicePropDesc* self = CMTPTypeServicePropDesc::NewLC( aServicePropCode, aDataType, aGetSet, aFormFlag, aForm );
    CleanupStack::Pop(self); 
    return self;
    }
   
  
EXPORT_C  CMTPTypeServicePropDesc* CMTPTypeServicePropDesc::NewLC( const TUint16  aServicePropCode, const TUint16 aDataType, const TUint8 aGetSet, const TUint8 aFormFlag, const MMTPType* aForm)
    {
    CMTPTypeServicePropDesc* self = new(ELeave) CMTPTypeServicePropDesc();
    CleanupStack::PushL(self);
    self->ConstructL( aServicePropCode, aDataType, aGetSet, aFormFlag, aForm );
    return self;
    }


/**
Destructor.
*/
EXPORT_C CMTPTypeServicePropDesc::~CMTPTypeServicePropDesc()
    {
    iChunkFlat1.Close();
    iChunkForm.Close();
    }

CMTPTypeServicePropDesc::CMTPTypeServicePropDesc() : 
    CMTPTypeCompoundBase((KJustInTimeConstruction), KNumChunksWithoutForm),
    iElementInfo(iElementMetaData, ENumElements),
    iChunkFlat1(KFlat1ChunkSize, *this)
    {

    }

EXPORT_C TUint CMTPTypeServicePropDesc::Type() const
    {
    return EMTPTypeServicePropDesc;
    } 



EXPORT_C TInt CMTPTypeServicePropDesc::FirstWriteChunk(TPtr8& aChunk)
    {
    /* 
    Reset the type in preparation for the data stream, by deleting all
    except the first chunk.
    */
    for (TUint i(ChunkCount() - 1); (i >= (EIdFlat1Chunk + 1)); i--)
      {
      ChunkRemove(i);
      }
      
    // Setup the write chunk pointer.
       TInt err(CMTPTypeCompoundBase::FirstWriteChunk(aChunk));
       switch (err)
           {
       case KMTPChunkSequenceCompletion:
           err = KErrNone;
           // Don't break, fall through to set the write sequence state.
           
       case KErrNone:
           // Set the write sequence state.
           iWriteSequenceState = EFormChunk;
           iWriteSequenceCompletionState = EFormChunk;
           break;
           
       default:
           break;
           }
      
    return  err;
    }

EXPORT_C TInt CMTPTypeServicePropDesc::NextWriteChunk(TPtr8& /*aChunk*/)
    {
        return KMTPChunkSequenceCompletion;
    }


EXPORT_C TBool CMTPTypeServicePropDesc::CommitRequired() const
    {
    return ETrue;
    }


EXPORT_C MMTPType* CMTPTypeServicePropDesc::CommitChunkL(TPtr8& aChunk)
    {
        switch (iWriteSequenceState)
            {
        case EFormChunk:
            {
            iChunkForm.Close();
            TUint8 flag(Uint8L(EFormFlag));
            TUint16 type(Uint16L(EDataType1));
            iChunkForm.SetMeta(flag, type);
            if (HasFormField(flag))
                {
                iChunkForm.OpenL(iElementInfo[EForm].iType);
                ChunkAppendL(iChunkForm);
                SetExpectedChunkCount(KNumChunksWithForm);
                }
            else
                {
                // Adjust the write sequence completion state.            
                iWriteSequenceCompletionState = EFormChunk;
                }   
            }
            break;
            
        case EIdle:
            // Completing the last element in the write sequence.
            break;
            
        default:
            Panic(EMTPTypeBadStorage);
            break;
            }
        
    if ( (iWriteSequenceState != EIdle ) && (iWriteSequenceState < iWriteSequenceCompletionState) )
        {
        iWriteSequenceState++;
        }
    else
        {
        iWriteSequenceState = EIdle;
        }

        
    if (CMTPTypeCompoundBase::CommitRequired())
        {
        CMTPTypeCompoundBase::CommitChunkL(aChunk);
        }
    return NULL;
    }


TBool CMTPTypeServicePropDesc::HasFormField(TUint8 aFormFlag) const
    {
    return ((aFormFlag != CMTPTypeObjectPropDesc::EDateTimeForm) && (aFormFlag != CMTPTypeObjectPropDesc::ENone)&&(aFormFlag != CMTPTypeObjectPropDesc::EObjectIDForm));
    }


const CMTPTypeCompoundBase::TElementInfo& CMTPTypeServicePropDesc::ElementInfo(TInt aElementId) const
    {
    __ASSERT_ALWAYS((aElementId < ENumElements), Panic(EMTPTypeBoundsError));
    
    return iElementInfo[aElementId];  
    }

void CMTPTypeServicePropDesc::ConstructL( const TUint16  aServicePropCode, const TUint16 aDataType, const TUint8 aGetSet, const TUint8 aFormFlag, const MMTPType* aForm )
    {  
    for (TUint i(0); (i < ENumElements); i++)
       {
       const TElementInfo& element(iElementInfo[i]);
       if (ChunkCount() <= element.iChunkId)
           {
           MMTPType* chunk(NULL);
           switch (element.iChunkId)
               {
           case EIdFlat1Chunk:
               iChunkFlat1.OpenL();
               chunk = &iChunkFlat1;
               break;
               
           case EIdFormChunk:
               iChunkForm.SetMeta(aFormFlag, aDataType);
               if (HasFormField(aFormFlag))
                   {
                   iChunkForm.OpenL(element.iType);
                   chunk = &iChunkForm;
                   SetExpectedChunkCount(KNumChunksWithForm);
                   }
               break;
               
           default:
               Panic(EMTPTypeBoundsError);
               break;
               }
           if (chunk)
               {
               ChunkAppendL(*chunk);   
               }
           }
       }
    
    // Set the construction values.
    SetUint16L( EServicePropertyCode, aServicePropCode );
    SetUint16L( EDataType1, aDataType );
    SetUint8L( EGetSet1, aGetSet );
    SetUint8L(EFormFlag, aFormFlag);
    
    if (aForm)
        {
        if (!HasFormField(aFormFlag))
            { 
            User::Leave(KMTPDataTypeInvalid);
            } 
        else
            {
            SetL(EForm, *aForm); 
            }
        }
    }