localconnectivityservice/generichid/src/hidreportbase.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:40 +0100
branchRCL_3
changeset 40 52a167391590
parent 0 c3e98f10fcf4
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2004-2007 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:  Report base class implementation
*
*/


#include "hidfield.h"
#include "hidtranslate.h"
#include "hidinterfaces.h"

const TUint KValueMask      = 0xFFFFFFFF;
const TUint KSignBitMask    = 0x80000000;
const TInt  KThreeLSB       = 7;
const TInt  KThreeLSBShift  = 3;
// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// GetIndexOfUsage()
// ---------------------------------------------------------------------------
//
TBool TReportUtils::GetIndexOfUsage(const CField* aField,
    TInt aUsageId, TInt& aUsageIndex)
    {
    TArray<TInt> usages(aField->UsageArray());

    if ( usages.Count() > 0 )
        {
        // Find the usage in the array
        for ( TInt i = 0; i < usages.Count(); i++ )
            {
            if ( usages[i] == aUsageId )
                {
                aUsageIndex = i;
                return ETrue;
                }
            }
        }
    else
        {
        // The field includes all usages between the min and max
        if ( aField->UsageMin() <= aUsageId && aUsageId <= aField->UsageMax() )
            {
            aUsageIndex = aUsageId - aField->UsageMin();
            return ETrue;
            }
        }

    return EFalse;
    }

// ---------------------------------------------------------------------------
// UsageAtIndex()
// ---------------------------------------------------------------------------
//
TInt TReportUtils::UsageAtIndex(const CField* aField, TInt aUsageIndex)
    {
    TInt usageId = 0;
    TArray<TInt> usages(aField->UsageArray());

    if ( usages.Count() > 0 )
        {
        if ( aUsageIndex < 0 )
            {
            // Null state for array control
            }
        else if ( aUsageIndex < usages.Count() )
            {
            // Get the usage ID from the set of possible usages
            usageId = usages[aUsageIndex];
            }
        else
            {
            // If there aren't enough usages in the set, the last one repeats
            usageId = usages[usages.Count() - 1];
            }
        }
    else
        {
        // Get the usage ID from the range
        if ( 0 <= aUsageIndex
                && aUsageIndex <= (aField->UsageMax() - aField->UsageMin()) )
            {
            usageId = aField->UsageMin() + aUsageIndex;
            }
        }

    return usageId;
    }

// ---------------------------------------------------------------------------
// WriteData()
// ---------------------------------------------------------------------------
//
TInt TReportUtils::WriteData(HBufC8& aData, const CField* aField,
    TInt aIndex, TInt aValue)
    {
    if ( 0 <= aIndex && aIndex < aField->Count() )
        {
        // The offset in bits from the start of the report to the value
        TInt offset = aField->Offset() + aIndex * aField->Size();

        // How many bits in the least significant byte are not part of the value
        TInt bitsToShift = offset & KThreeLSB;

        TUint mask = KValueMask >> ((KSizeOfByte * sizeof(TInt)) - aField->Size());
        mask <<= bitsToShift;
        aValue <<= bitsToShift;

        TPtr8 data = aData.Des();

        // Write out the bytes, least significant first
        for ( TInt i = offset >> KThreeLSBShift; mask && i < aData.Length(); i++ )
            {
            TUint8 maskByte = static_cast<TUint8>(mask);

            // The extra cast is because MSVC6 thinks that or-ing 2
            // TUint8s together gives an int.
            data[i] = static_cast<TUint8>(
                (static_cast<TUint8>(aValue) & maskByte)
                | (aData[i] & ~maskByte));
            mask >>= KSizeOfByte;
            aValue >>= KSizeOfByte;
            }

        return KErrNone;
        }

    return KErrBadControlIndex;
    }

// ---------------------------------------------------------------------------
// ReadData()
// ---------------------------------------------------------------------------
//
TInt TReportUtils::ReadData(const TDesC8& aData, const CField* aField,
    TInt aIndex, TInt& aValue)
    {
    if ( 0 <= aIndex && aIndex < aField->Count() )
        {
        // The offset in bits from the start of the report to the value
        TInt offset = aField->Offset() + aIndex * aField->Size();

        // How many bits in the least significant byte are not part of
        // the value
        TInt bitsToShift = offset & KThreeLSB;

        // How many consecutive bytes we need to read to get the whole
        // value. According to the HID spec, a value cannot span more
        // than 4 bytes in a report
        TInt bytesToRead = (bitsToShift + aField->Size() + KThreeLSB) / KSizeOfByte;

        // Make sure we don't read past the end of the data
        if ( (offset >> KThreeLSBShift) + bytesToRead > aData.Length() )
            {
            bytesToRead = aData.Length() - (offset >> KThreeLSBShift);
            }

        TInt value = 0;

        // Read in the bytes, most significant first
        for ( TInt i = bytesToRead - 1; i >= 0; i-- )
            {
            value = (value << KSizeOfByte) | aData[(offset >> KThreeLSBShift) + i];
            }

        value >>= bitsToShift;

        // Make masks for the whole value and just the sign bit
        TUint valueMask = KValueMask >> ((KSizeOfByte * sizeof(TInt)) - aField->Size());
        TUint signMask = KSignBitMask >> ((KSizeOfByte * sizeof(TInt)) - aField->Size());

        if ( aField->LogicalMin() < 0 && (value & signMask) )
            {
            // The value is negative, so the leading bits should be 1s
            aValue = value | ~valueMask;
            }
        else
            {
            // The value is positive, so the leading bits should be 0s
            aValue = value & valueMask;
            }

        return KErrNone;
        }

    return KErrBadControlIndex;
    }