--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/accessoryservices/pluggeddisplay/edidparser/src/cea861edidparser.cpp Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,1921 @@
+/*
+ * Copyright (c) 2008,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:
+ * Implementation of CCea861EdidParser class.
+ *
+ */
+
+#include "cea861edidparser.h"
+#include "trace.h"
+
+// ======== LOCAL FUNCTIONS ========
+
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::CCea861EdidParser
+// ---------------------------------------------------------------------------
+//
+CCea861EdidParser::CCea861EdidParser() :
+ iParsed( EFalse ),
+ iAudioDataBlockSupported( EFalse ),
+ iVideoDataBlockSupported( EFalse ),
+ iVendorSpecificDataBlockSupported( EFalse ),
+ iSpeakerAllocationDataBlockSupported( EFalse )
+ {
+ FUNC_LOG;
+ }
+
+// ---------------------------------------------------------------------------
+// CEdidParserBase::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CCea861EdidParser::ConstructL( const TExtDataBlock& aData )
+ {
+ FUNC_LOG;
+
+ iParsedInfo = CCea861ExtEdidInformation::NewL();
+ ParseExtensionBlockL( aData );
+ }
+
+// ---------------------------------------------------------------------------
+// CEdidParserBase::NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CCea861EdidParser* CCea861EdidParser::NewL( const TExtDataBlock& aData )
+ {
+ FUNC_LOG;
+
+ CCea861EdidParser* self = CCea861EdidParser::NewLC( aData );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CEdidParserBase::NewLC
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CCea861EdidParser* CCea861EdidParser::NewLC( const TExtDataBlock& aData )
+ {
+ FUNC_LOG;
+
+ CCea861EdidParser* self = new ( ELeave ) CCea861EdidParser();
+ CleanupStack::PushL( self );
+ self->ConstructL( aData );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::~CCea861EdidParser
+// ---------------------------------------------------------------------------
+//
+CCea861EdidParser::~CCea861EdidParser()
+ {
+ FUNC_LOG;
+
+ delete iParsedInfo;
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::ParseExtensionBlockL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CCea861EdidParser::ParseExtensionBlockL( const TExtDataBlock& aData )
+ {
+ FUNC_LOG;
+
+ TInt err( KErrNone );
+ TInt index( 0 );
+
+ // Check first byte to see if tag is 0x2.
+ // If not return error.
+ if( aData[index] != KBit1 )
+ {
+ return KErrNotSupported;
+ }
+
+ iParsedInfo->iExtensionTag = aData[index];
+ index++;
+
+ // Check revision
+ iParsedInfo->iRevision = aData[index];
+ index++;
+ switch( iParsedInfo->iRevision )
+ {
+ case 1:
+ err = ReadCeaVersion1L( aData, index );
+ break;
+ case 2:
+ err = ReadCeaVersion2L( aData, index );
+ break;
+ case 3:
+ err = ReadCeaVersion3L( aData, index );
+ break;
+ default:
+ err = KErrNotSupported;
+ break;
+ }
+
+ if( err == KErrNone )
+ {
+ iParsed = ETrue;
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::isExtensionBlockParsed
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::IsExtensionBlockParsed()
+ {
+ FUNC_LOG;
+
+ return iParsed;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVIC
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TInt8 CCea861EdidParser::GetVIC( TUint8 aNumber )
+ {
+ FUNC_LOG;
+
+ if( !iParsed )
+ {
+ return KErrNotFound;
+ }
+
+ if( IsVideoDataBlockSupported() )
+ {
+ return KErrNotFound;
+ }
+
+ if( iParsedInfo->iShortVideoDescriptors )
+ {
+ TCEA861VideoDataBlock* cur = iParsedInfo->iShortVideoDescriptors;
+ TUint8 count = 0;
+ while( cur )
+ {
+ if( cur->iNative )
+ {
+ if( count == aNumber )
+ {
+ return cur->iVIC;
+ }
+ count++;
+ }
+ cur = cur->iNext;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::Underscan
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::Underscan()
+ {
+ FUNC_LOG;
+
+ if( iParsedInfo->UnderscanDataSupported() )
+ {
+ return iParsedInfo->iUnderscan;
+ }
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::BasicAudio
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::BasicAudio()
+ {
+ FUNC_LOG;
+
+ if( iParsedInfo->AudioDataSupported() )
+ {
+ return iParsedInfo->iAudio;
+ }
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::YCbCr444
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::YCbCr444()
+ {
+ FUNC_LOG;
+
+ if( iParsedInfo->YCbCr444DataSupported() )
+ {
+ return iParsedInfo->iYCbCr444;
+ }
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::YCbCr422
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::YCbCr422()
+ {
+ FUNC_LOG;
+
+ if( iParsedInfo->YCbCr422DataSupported() )
+ {
+ return iParsedInfo->iYCbCr422;
+ }
+ return EFalse;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::TotalNumberOfNativeFormats
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TUint8 CCea861EdidParser::TotalNumberOfNativeFormats()
+ {
+ FUNC_LOG;
+
+ return iParsedInfo->TotalNumberOfNativeFormats();
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::IsAudioDataBlockSupported
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::IsAudioDataBlockSupported()
+ {
+ FUNC_LOG;
+
+ return iAudioDataBlockSupported;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::IsVideoDataBlockSupported
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::IsVideoDataBlockSupported()
+ {
+ FUNC_LOG;
+
+ return iVideoDataBlockSupported;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::IsVideoDataBlockSupported
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::IsVendorSpecificDataBlockSupported()
+ {
+ FUNC_LOG;
+
+ return iVendorSpecificDataBlockSupported;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetParsedInformation
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CCea861ExtEdidInformation* CCea861EdidParser::GetParsedInformation()
+ {
+ FUNC_LOG;
+
+ return iParsedInfo;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::IsSpeakerAllocationDataBlockSupported
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TBool CCea861EdidParser::IsSpeakerAllocationDataBlockSupported()
+ {
+ FUNC_LOG;
+
+ return iSpeakerAllocationDataBlockSupported;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVideoLatency
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TUint8 CCea861EdidParser::GetVideoLatency()
+ {
+ FUNC_LOG;
+
+ // Video latency is kept in Vendor Specific Data Block according to
+ // HDMISpecification13a.pdf, table 8-6
+ TUint8 latency = 0;
+ TCEA861VendorSpecificDataBlock* data = iParsedInfo->iVendorSpecificData;
+ if( ( !data ) || ( !IsVendorSpecificDataBlockSupported() ) )
+ {
+ return latency;
+ }
+
+ TCEA861VendorSpecificDataBlockPayload* cur = data->iVendorSpecificPayloadStart;
+
+ // According to HDMI spec table 8-6, index of video latency is 9
+ // Start counting from index 4
+ for( TInt ii = 0; ii < 6; ii++ )
+ {
+ if( !cur )
+ {
+ break;
+ }
+
+ // Byte 8
+ else if( ii == 4 )
+ {
+ // Check if latency field bits are present
+ if( !LatencyFieldsPresent( cur->iData ) )
+ {
+ // Latency fields are not present
+ break;
+ }
+ }
+
+ // Byte 9
+ else if( ii == 5 )
+ {
+ // Get Video_latency byte
+ latency = cur->iData;
+ }
+
+ cur = cur->iNext;
+ }
+
+ // Convert latency in to ms
+ latency = LatencyInMs( latency );
+
+ return latency;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetAudioLatency
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TUint8 CCea861EdidParser::GetAudioLatency()
+ {
+ FUNC_LOG;
+
+ // Audio latency is kept in Vendor Specific Data Block according to
+ // HDMISpecification13a.pdf, table 8-6
+ TUint8 latency = 0;
+ TCEA861VendorSpecificDataBlock* data = iParsedInfo->iVendorSpecificData;
+ if( ( !data ) || ( !IsVendorSpecificDataBlockSupported() ) )
+ {
+ return latency;
+ }
+
+ TCEA861VendorSpecificDataBlockPayload* cur = data->iVendorSpecificPayloadStart;
+
+ // According to HDMI spec table 8-6, index of audio latency is 10
+ // Start counting from index 4
+ for( TInt ii = 0; ii < 7; ii++ )
+ {
+ if( !cur )
+ {
+ break;
+ }
+
+ // Byte 8
+ else if( ii == 4 )
+ {
+ // Check if latency field bits are present
+ if( !LatencyFieldsPresent( cur->iData ) )
+ {
+ // Latency fields are not present
+ break;
+ }
+ }
+
+ // Byte 10
+ else if( ii == 6 )
+ {
+ latency = cur->iData;
+ }
+
+ cur = cur->iNext;
+ }
+
+ // Convert latency in to ms
+ latency = LatencyInMs( latency );
+
+ return latency;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetInterlacedVideoLatency
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TUint8 CCea861EdidParser::GetInterlacedVideoLatency()
+ {
+ // Video latency is kept in Vendor Specific Data Block according to
+ // HDMISpecification13a.pdf, table 8-6
+ TUint8 latency = 0;
+ TCEA861VendorSpecificDataBlock* data = iParsedInfo->iVendorSpecificData;
+ if( ( !data ) || ( !IsVendorSpecificDataBlockSupported() ) )
+ {
+ return latency;
+ }
+
+ TCEA861VendorSpecificDataBlockPayload* cur = data->iVendorSpecificPayloadStart;
+
+ // According to HDMI spec table 8-6, index of video latency is 9 or 11
+ // Start counting from index 4
+
+ // Start index == 4, video latency == 9 (4 + 5)
+ TInt videoLatencyByte = 5;
+ for( TInt ii = 0; ii < 8; ii++ )
+ {
+ if( !cur )
+ {
+ break;
+ }
+
+ // Byte 8
+ else if( ii == 4 )
+ {
+ // Check if latency field bits are present
+ TUint8 byte8 = cur->iData;
+ if( InterlacedLatencyFieldsPresent( byte8 ) )
+ {
+ // Interlaced latency fields are present
+ // Start index == 4, interlaced video latency == 11 (4 + 7)
+ videoLatencyByte = 7;
+ }
+ else if( !LatencyFieldsPresent( byte8 ) )
+ {
+ // Latency fields are not present
+ break;
+ }
+ }
+
+ // Byte 9 or Byte 11
+ else if( ii == videoLatencyByte )
+ {
+ // Get Video_latency byte
+ latency = cur->iData;
+ }
+
+ cur = cur->iNext;
+ }
+
+ // Convert latency in to ms
+ latency = LatencyInMs( latency );
+
+ return latency;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetInterlacedAudioLatency
+//
+// ----------------------------------------------------------------------------
+//
+EXPORT_C TUint8 CCea861EdidParser::GetInterlacedAudioLatency()
+ {
+ FUNC_LOG;
+
+ // Audio latency is kept in Vendor Specific Data Block according to
+ // HDMISpecification13a.pdf, table 8-6
+ TUint8 latency = 0;
+ TCEA861VendorSpecificDataBlock* data = iParsedInfo->iVendorSpecificData;
+ if( ( !data ) || ( !IsVendorSpecificDataBlockSupported() ) )
+ {
+ return latency;
+ }
+
+ TCEA861VendorSpecificDataBlockPayload* cur = data->iVendorSpecificPayloadStart;
+
+ // According to HDMI spec table 8-6, index of audio latency is 10 or 12
+ // Start counting from index 4
+
+ // Start index == 4, audio latency == 10 (4 + 6)
+ TInt audioLatencyByte = 6;
+ for( TInt ii = 0; ii < 9; ii++ )
+ {
+ if( !cur )
+ {
+ break;
+ }
+
+ // Byte 8
+ else if( ii == 4 )
+ {
+ // Check if interlaced latency field bits are present
+ TUint8 byte8 = cur->iData;
+ if( InterlacedLatencyFieldsPresent( byte8 ) )
+ {
+ // Start index == 4, interlaced audio latency == 12 (4 + 8)
+ audioLatencyByte = 8;
+ }
+
+ // Check if latency field bits are present
+ else if( !LatencyFieldsPresent( byte8 ) )
+ {
+ // Latency fields are not present
+ break;
+ }
+ }
+
+ // Byte 10 or Byte 12
+ else if( ii == audioLatencyByte )
+ {
+ latency = cur->iData;
+ }
+
+ cur = cur->iNext;
+ }
+
+ // Convert latency in to ms
+ latency = LatencyInMs( latency );
+
+ return latency;
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::ReadCeaVersion1L
+// ---------------------------------------------------------------------------
+//
+TInt CCea861EdidParser::ReadCeaVersion1L( const TExtDataBlock& aData,
+ TInt aIndex )
+ {
+ FUNC_LOG;
+
+ if( aIndex > KEdidParserSizeOfEdidBlock )
+ {
+ return KErrOverflow;
+ }
+
+ for( TInt index = aIndex; index < KEdidParserSizeOfEdidBlock; index++ )
+ {
+ // Offset. If this is a newer version of CEA-861,
+ // then this is skipped (we are already past the offset)
+ if( index == 2 )
+ {
+ iParsedInfo->iOffset = aData[index];
+ // Skip over the offset
+ while( index < iParsedInfo->iOffset )
+ {
+ index++;
+ }
+ }
+
+ if( aData[index] != KEdidPaddingByte ) // padding = 0x00
+ {
+ // start of 18-byte descriptors: See section 3.10.2 of VESA E-EDID Standard [10]
+
+ TBool first = ETrue;
+ if( iParsedInfo->iDescriptorBlocks == 0 )
+ {
+ iParsedInfo->iDescriptorBlocks
+ = new ( ELeave ) TCEA861TEdidDescriptorBlockList();
+ }
+
+ // read the descriptors here
+ TEdidDescriptorBlock tmp = GetDescriptorBlock( aData, index );
+ if( first )
+ {
+ first = EFalse;
+ iParsedInfo->iDescriptorBlocks->iData = tmp;
+ continue;
+ }
+ TCEA861TEdidDescriptorBlockList* last =
+ iParsedInfo->iDescriptorBlocks;
+ while( last->iNext != 0 ) // go to last block
+ {
+ last = last->iNext;
+ }
+ last->iNext = new ( ELeave ) TCEA861TEdidDescriptorBlockList();
+ last = last->iNext;
+ last->iData = tmp;
+ }
+ else
+ {
+ // this is only padding, no need to do anything
+ }
+
+ // after the descriptors there is padding to fill Extension block to 128 bytes.
+ // beginning of padding | End of padding | Checksum
+ // d+(18*n) ..........................| 126 | 127
+ if( index == 0x7F )
+ {
+ iParsedInfo->iChecksum = aData[index];
+ // Finished reading
+ return KErrNone;
+ }
+ }
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::ReadCeaVersion2L
+// ---------------------------------------------------------------------------
+//
+TInt CCea861EdidParser::ReadCeaVersion2L( const TExtDataBlock& aData,
+ TInt aIndex )
+ {
+ FUNC_LOG;
+
+ ReadCeaVersion2and3Common( aData, aIndex );
+
+ return ReadCeaVersion1L( aData, aIndex );
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::ReadCeaVersion3L
+// ---------------------------------------------------------------------------
+//
+TInt CCea861EdidParser::ReadCeaVersion3L( const TExtDataBlock& aData,
+ TInt aIndex )
+ {
+ FUNC_LOG;
+
+ // first read the common information in versions 2 and 3
+ ReadCeaVersion2and3Common( aData, aIndex );
+
+ if( aIndex == 4 ) // start of the Data block collection (see table 39)
+ {
+ while( aIndex < iParsedInfo->iOffset ) // it is possible to have more than one DataBlockCollection
+ {
+ TInt ret = ReadCeaDataBlockCollectionL( aData, aIndex );
+ if( ret != KErrNone )
+ {
+ return ret;
+ }
+ if( aIndex > KEdidParserSizeOfEdidBlock )
+ {
+ return KErrOverflow;
+ }
+ }
+ // after reading the CEADataBlockCollections, we can read all the descriptors
+ }
+ else
+ {
+ // error
+ if( aIndex < 4 )
+ {
+ return KErrNotFound;
+ }
+ else
+ {
+ return KErrOverflow;
+ }
+ }
+ return ReadCeaVersion1L( aData, aIndex );
+ }
+
+// ---------------------------------------------------------------------------
+// CCea861EdidParser::ReadCeaVersion2L
+// ---------------------------------------------------------------------------
+//
+TInt CCea861EdidParser::ReadCeaVersion2and3Common( const TExtDataBlock& aData,
+ TInt& aIndex )
+ {
+ FUNC_LOG;
+
+ for( TInt i = aIndex; i < KEdidParserSizeOfEdidBlock; i++ )
+ {
+ if( aIndex == 2 ) // offset
+ {
+ iParsedInfo->iOffset = aData[i];
+ // don't skip over the offset
+ }
+ if( aIndex == 3 )
+ {
+ // bit 7 = underscan: 1 if sink underscans IT video formats by default
+ // bit 6 = audio : 1 if sink supports basic audio
+ // bit 5 = YCbCr 4:4:4 = 1 if sink supports YCbCr 4:4:4 in addition to RGB
+ // bit 4 = YCbCr 4:2:2 = 1 if sink supports YCbCr 4:2:2 in addition to RGB
+ // lower 4 bits = total number of native DTDs (detailed timing descriptors) (see section 2.2 for definition of "native format")
+ iParsedInfo->iUnderscan = ( KBit7 & aData[i] ? ETrue : EFalse );
+ iParsedInfo->iAudio = ( KBit6 & aData[i] ? ETrue : EFalse );
+ iParsedInfo->iYCbCr444 = ( KBit5 & aData[i] ? ETrue : EFalse );
+ iParsedInfo->iYCbCr422 = ( KBit4 & aData[i] ? ETrue : EFalse );
+ iParsedInfo->iTotalNumberOfNativeFormats = 0x0F & aData[i];
+ aIndex++;
+ return KErrNone; // end of common data
+ }
+ aIndex++;
+ }
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetDescriptorBlock
+//
+// ----------------------------------------------------------------------------
+//
+TEdidDescriptorBlock CCea861EdidParser::GetDescriptorBlock( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ TEdidDescriptorBlock descBlock;
+
+ descBlock.iPixelClock = GetPixelClock( aData, aIndex );
+
+ descBlock.iHorizontalAddressableVideoPixels
+ = GetHorizontalAddressableVideoPixels( aData, aIndex );
+
+ descBlock.iHorizontalBlanking = GetHorizontalBlanking( aData, aIndex );
+
+ descBlock.iVerticalAddressableVideoPixels
+ = GetVerticalAddressableVideoPixels( aData, aIndex );
+
+ descBlock.iVerticalBlanking = GetVerticalBlanking( aData, aIndex );
+
+ descBlock.iHorizontalFrontPorch = GetHorizontalFrontPorch( aData, aIndex );
+
+ descBlock.iHorizontalSyncPulse
+ = GetHorizontalSyncPulseWidth( aData, aIndex );
+
+ descBlock.iVerticalFrontPorch = GetVerticalFrontPorch( aData, aIndex );
+
+ descBlock.iVerticalSyncPulse = GetVerticalSyncPulseWidth( aData, aIndex );
+
+ descBlock.iHorizontalAddressableImageSize
+ = GetHorizontalAddressableImageSizeInMm( aData, aIndex );
+
+ descBlock.iVerticalAddressableImageSize
+ = GetVerticalAddressableImageSizeInMm( aData, aIndex );
+
+ descBlock.iHorizontalBorder = GetHorizontalBorderSize( aData, aIndex );
+
+ descBlock.iVerticalBorder = GetVerticalBorderSize( aData, aIndex );
+
+ descBlock.iInterlacedVideo = GetVideoIsInterlaced( aData, aIndex );
+
+ descBlock.iStereoSupport = GetStereoViewingSupport( aData, aIndex );
+
+ descBlock.iSyncs = GetSyncSignalDefinitions( aData, aIndex );
+
+ return descBlock;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetPixelClock
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetPixelClock( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // Stored Value = Pixel clock ÷ 10,000
+ // LSB stored in byte 0 and MSB stored in byte 1
+ // 0, 1 2 Range: 10 kHz to 655.35 MHz in 10 kHz steps
+ // (00 00)h Reserved: Do not use for Detailed Timing Descriptor
+ TUint16 word1 = aData[aIndex];
+ TUint16 word2 = aData[aIndex + 1];
+
+ TUint16 pixelClock = word2; // xxxx xxxx 1010 1010
+ pixelClock = pixelClock << 8; // 1010 1010 xxxx xxxx shifted to left (MSB)
+ pixelClock += word1; // 1010 1010 0101 0101 add the LSB
+
+ aIndex += 2;
+
+ return pixelClock;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetHorizontalAddressableVideoPixels
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetHorizontalAddressableVideoPixels( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #2
+ TUint16 word1 = aData[aIndex];
+ TUint16 word2 = aData[aIndex + 2];
+
+ // 12bits long, defined in 8 bits of byte 2 and upper nibble of byte 4 (4bits), range 0-4095
+ TUint16 horAddrVideo = 0;
+
+ // nullify the 4 lsb
+ // ---- ---- xxxx yyyy >> 4 = ---- ---- ---- xxxx
+ horAddrVideo = word1 >> 4;
+ // return back to original position (4)+4
+ // ---- ---- ---- xxxx << 4 = ---- xxxx 0000 0000
+ horAddrVideo = horAddrVideo << ( 4 + 4 );
+ // ---- xxxx zzzz zzzz = correct values for the 12-bit-long var
+ horAddrVideo += word2;
+
+ aIndex++; // to byte #3
+
+ return horAddrVideo;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetHorizontalBlanking
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetHorizontalBlanking( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #3
+ TUint16 word1 = aData[aIndex];
+ TUint16 word2 = aData[aIndex + 1];
+
+ TUint16 horBlanking = 0;
+
+ // nullify the 4 msb
+ // ---- ---- xxxx yyyy << 12 = yyyy ---- ---- ----
+ horBlanking = word1 << 12;
+ // nullify the 4 msb
+ // yyyy ---- ---- ---- >> 4 = ---- yyyy ---- ----
+ horBlanking = horBlanking >> 4;
+ // ---- yyyy zzzz zzzz = correct values for the 12-bit-long var
+ horBlanking += word2;
+
+ aIndex += 2; // to byte #5
+
+ return horBlanking;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVerticalAddressableVideoPixels
+// Vertical Addressable Video in lines
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetVerticalAddressableVideoPixels( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #5
+ TUint16 word1 = aData[aIndex + 2];
+ TUint16 word2 = aData[aIndex];
+
+ //Upper nibble of byte 7 and the 8 bits of byte 5) - Range is 0 lines to 4095 lines
+ TUint16 vertAddrVideo = 0;
+ vertAddrVideo = word1 >> 4;
+ vertAddrVideo = vertAddrVideo << ( 4 + 4 );
+ vertAddrVideo += word2; // like before with HorAddrVideo
+
+ aIndex++; // to byte #6
+ return vertAddrVideo;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVerticalBlanking
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetVerticalBlanking( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #6
+ TUint16 word1 = aData[aIndex + 1];
+ TUint16 word2 = aData[aIndex];
+
+ // 12bits long, defined in 8 bits of byte 2 and upper nibble of byte 4 (4bits), range 0-4095
+ TUint16 vertBlanking = 0;
+
+ // nullify the 4 msb
+ // ---- ---- xxxx yyyy << 12 = yyyy ---- ---- ----
+ vertBlanking = word1 << 12;
+ // nullify the 4 msb
+ // yyyy ---- ---- ---- >> 4 = 0000 yyyy ---- ----
+ vertBlanking = vertBlanking >> 4;
+ // ---- yyyy zzzz zzzz = correct values for the 12-bit-long var
+ vertBlanking += word2;
+
+ aIndex += 2; // to byte #8
+ return vertBlanking;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetHorizontalFrontPorch
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetHorizontalFrontPorch( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #8
+
+ TUint16 word1 = aData[aIndex];
+ TUint16 word2 = aData[aIndex + 3]; // 2 bits from #11
+
+ // Horizontal Front Porch in Pixels (from blanking start to start of sync) is represented by a 10 bit
+ // number (Bits 7 & 6 of byte 11 and the 8 bits of byte 8) - Range is 0 pixels to 1023 pixels.
+
+ TUint16 horFrontPorch = 0;
+
+ TUint8 bit67 = word1;
+ bit67 = ( bit67 & KBit7 ) | ( bit67 & KBit6 ); // bits 6 and 7 remain
+
+ horFrontPorch = bit67 << 2;
+ horFrontPorch += word2;
+
+ aIndex++; // to byte #9
+ return horFrontPorch;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetHorizontalSyncPulseWidth
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetHorizontalSyncPulseWidth( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #9
+ TUint16 word1 = aData[aIndex];
+ TUint16 word2 = aData[aIndex + 2]; // 2 bits from #11
+
+ //Horizontal Sync Pulse Width in Pixels (from the end of the front porch to the start of the back
+ //porch) is represented by a 10 bit number (Bits 5 & 4 of byte 11 and the 8 bits of byte 9) - Range
+ //is 0 pixels to 1023 pixels.
+
+ TUint16 horSyncPulseWidth = word1;
+ horSyncPulseWidth = ( horSyncPulseWidth & KBit5 ) | ( horSyncPulseWidth
+ & KBit4 ); // only bits 5 and 4 remain
+ horSyncPulseWidth = horSyncPulseWidth << 4;
+ horSyncPulseWidth += word2;
+
+ aIndex++; // aIndex at byte #10
+
+ return horSyncPulseWidth;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVerticalFrontPorch
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetVerticalFrontPorch( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // Vertical Front Porch in Lines (from blanking start to start of sync) is represented by a 6 bit
+ // number (Bits 3 & 2 of byte 11 and the upper nibble of byte 10) - Range is 0 lines to 63 lines.
+
+ // aIndex at byte #10
+ TUint16 word1 = aData[aIndex + 1];
+ TUint16 word2 = aData[aIndex]; // 2 bits from #11
+
+ TUint16 vertFrontPorch = 0;
+
+ TUint8 bit23 = word1;
+ // bits 2 and 3 remain 0000 xx00
+ bit23 = ( bit23 & KBit3 ) | ( bit23 & KBit2 );
+
+ // 00xx 0000
+ vertFrontPorch = bit23 << 2;
+ // 00xx yyyy
+ vertFrontPorch += ( word2 >> 4 );
+
+ //Index remains at byte #10
+
+ return vertFrontPorch;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVerticalSyncPulseWidth
+//
+// ----------------------------------------------------------------------------
+//
+TUint8 CCea861EdidParser::GetVerticalSyncPulseWidth( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // Vertical Sync Pulse Width in Lines (from the end of the front porch to the start of the back
+ // porch) is represented by a 6 bit number (Bits 1 & 0 of byte 11 and the lower nibble of byte 10 -
+ // Range is 0 lines to 63 lines.
+
+ // aIndex at byte #10
+ TUint16 word1 = aData[aIndex];
+ TUint16 word2 = aData[aIndex + 1]; // 2 bits from #11
+
+ // Vertical Sync Pulse Width in Lines (from the end of the front porch to the start of the back
+ // porch) is represented by a 6 bit number (Bits 1 & 0 of byte 11 and the lower nibble of byte 10 -
+ // Range is 0 lines to 63 lines.
+ TUint8 vertSyncPulse = 0;
+
+ // bits 1 and 0 remain 0000 00xx
+ word2 = ( word2 & KBit1 ) | ( word2 & KBit0 );
+
+ // 00xx 0000
+ vertSyncPulse = word2 << 4;
+ // only the lower nibble, %16 removes the upper nibble
+ word1 = word1 % 16;
+ // 00xx yyyy
+ vertSyncPulse += word1;
+
+ aIndex += 2; // to byte #12
+
+ return vertSyncPulse;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetHorizontalAddressableImageSizeInMm
+// Horizontal Addressable Video Image Size in mm
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetHorizontalAddressableImageSizeInMm( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #12
+ TUint16 word1 = aData[aIndex + 2];
+ TUint16 word2 = aData[aIndex];
+
+ //Horizontal Addressable Video Image Size in mm is represented by a 12 bit number (Upper
+ //nibble of byte 14 and the 8 bits of byte 12) - Range is 0 mm to 4095 mm.
+
+ // first nullify 4 lsb
+ TUint16 hais = word1 >> 4;
+ // and then move back the first 4 and then again 4
+ hais = hais << ( 4 + 4 );
+ hais += word2;
+
+ aIndex++; // to byte #13
+
+ return hais;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVerticalAddressableImageSizeInMm
+//
+// ----------------------------------------------------------------------------
+//
+TUint16 CCea861EdidParser::GetVerticalAddressableImageSizeInMm( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #13
+ TUint16 word1 = aData[aIndex + 1];
+ TUint16 word2 = aData[aIndex];
+
+ //Vertical Addressable Video Image Size in mm is represented by a 12 bit number (Lower nibble
+ //of byte 14 and the 8 bits of byte 13) - Range is 0 mm to 4095 mm.
+
+ TUint16 vais = word1;
+ // first nullify 4 msb and then move back 1 nibble
+ vais = vais << 12;
+ vais = vais >> 4;
+ vais += word2;
+
+ aIndex += 2; // to byte #15
+
+ return vais;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetHorizontalBorderSize
+//
+// ----------------------------------------------------------------------------
+//
+TUint8 CCea861EdidParser::GetHorizontalBorderSize( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #15
+ TUint16 word1 = aData[aIndex];
+
+ //Right Horizontal Border or Left Horizontal Border in Pixels is represented by an 8 bit number
+ //(the 8 bits of byte 15) - Range is 0 pixels to 255 pixels.
+
+ // the same value is used for (left and right) / (top and bottom)
+ aIndex++; // to byte #16
+ return word1;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVerticalBorderSize
+// Top Vertical Border or Bottom Vertical Border in Lines
+//
+// ----------------------------------------------------------------------------
+//
+TUint8 CCea861EdidParser::GetVerticalBorderSize( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #16
+ TUint16 word1 = aData[aIndex];
+
+ //Top Vertical Border or Bottom Vertical Border in Lines is represented by an 8 bit number (the
+ //8 bits of byte 16) - Range is 0 lines to 255 lines.
+
+ aIndex++; // to byte #17
+ return word1;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetVideoIsInterlaced
+//
+// ----------------------------------------------------------------------------
+//
+TBool CCea861EdidParser::GetVideoIsInterlaced( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #17
+ TUint16 word1 = aData[aIndex];
+
+ // byte 17
+ //Bytes Bit Definitions Detailed Timing Definitions
+ //7 6 5 4 3 2 1 0 Signal Interface Type:
+ //0 _ _ _ _ _ _ _ Non-Interlaced (1 frame = 1 field)
+ //1 _ _ _ _ _ _ _ Interlaced (1 frame = 2 fields)
+
+ // Index remains at byte #17
+
+ return KBit7 & word1;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetStereoViewingSupport
+//
+// ----------------------------------------------------------------------------
+//
+TEdidStereoViewingSupport CCea861EdidParser::GetStereoViewingSupport( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #17
+ TUint16 word1 = aData[aIndex];
+
+ // See TEdidStereoViewingSupport enum declaration
+
+ // byte 17
+ //Bytes Bit Definitions Detailed Timing Definitions
+ //_ 6 5 _ _ _ _ 0 Stereo Viewing Support:
+ // 0 0 _ _ _ _ x Normal Display – No Stereo. The value of bit 0 is "don't care"
+ // 0 1 _ _ _ _ 0 Field sequential stereo, right image when stereo sync signal = 1
+ // 1 0 _ _ _ _ 0 Field sequential stereo, left image when stereo sync signal = 1
+ // 0 1 _ _ _ _ 1 2-way interleaved stereo, right image on even lines
+ // 1 0 _ _ _ _ 1 2-way interleaved stereo, left image on even lines
+ // 1 1 _ _ _ _ 0 4-way interleaved stereo
+ // 1 1 _ _ _ _ 1 Side-by-Side interleaved stereo
+ TUint8 bit17 = word1;
+
+ // Index remains at byte #17
+
+ if( !( ( KBit6 & bit17 ) | ( KBit5 & bit17 ) ) ) // 0 0 _ _ _ _ x Normal Display – No Stereo.
+ { // The value of bit 0 is "don't care"
+ return ENormalDisplay;
+ }
+ else
+ {
+ if( !( KBit6 & bit17 ) && ( KBit5 & bit17 ) && !( KBit0 & bit17 ) ) // 0 1 _ _ _ _ 0 Field sequential stereo,
+ { // right image when stereo sync signal=1
+ return EFieldSequentialStereoRightWhenStereoSyncSignal1;
+ }
+ else
+ {
+ if( ( KBit6 & bit17 ) && !( KBit5 & bit17 ) && !( KBit0 & bit17 ) ) // 1 0 _ _ _ _ 0 Field sequential stereo,
+ { // left image when stereo sync signal=1
+ return EFieldSequentialStereoLeftWhenStereoSyncSignal1;
+ }
+ else
+ {
+ if( !( KBit6 & bit17 ) && ( KBit5 & bit17 ) && ( KBit0 & bit17 ) ) // 0 1 _ _ _ _ 1 2-way interleaved stereo,
+ { // right image on even lines
+ return ETwoWayInterleavedStereoRightImageOnEvenLines;
+ }
+ else
+ {
+ if( ( KBit6 & bit17 ) && !( KBit5 & bit17 ) && ( KBit0
+ & bit17 ) )// 1 0 _ _ _ _ 1 2-way interleaved stereo,
+ { // left image on even lines
+ return ETwoWayInterleavedStereoLeftImageOnEvenLines;
+ }
+ else
+ {
+ if( ( KBit6 & bit17 ) && ( KBit5 & bit17 ) && !( KBit0
+ & bit17 ) ) // 1 1 _ _ _ _ 0 4-way interleaved stereo
+ {
+ return EFourWayInterleaverStereo;
+ }
+ else
+ {
+ if( ( KBit6 & bit17 ) && ( KBit5 & bit17 )
+ && ( KBit0 & bit17 ) ) // 1 1 _ _ _ _ 1 Side-by-Side interleaved stereo
+ {
+ return ESideBySideInterleavedStere;
+ }
+ else
+ {
+ return EUnknownStereoViewingSupport;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetAnalogSyncSignalDefinitions
+//
+// ----------------------------------------------------------------------------
+//
+TEdidSyncSignalDefinitions CCea861EdidParser::GetSyncSignalDefinitions( const TExtDataBlock& aData,
+ TInt& aIndex ) const
+ {
+ FUNC_LOG;
+
+ // aIndex at byte #18
+ TUint8 byte17 = aData[aIndex];
+
+ // byte 17
+ // 4 3 2 1 _ Analog Sync Signal Definitions:
+ //------------------------------------------
+ // 0 0 _ _ _ Analog Composite Sync:
+ // 0 1 _ _ _ Bipolar Analog Composite Sync:
+
+ aIndex++; // advance to byte #18 finally -> this descriptor block is now finished
+
+ if( !( KBit4 & byte17 ) ) // if bit4 == 0 then this is analog display
+ {
+ return GetAnalogSyncSignalDefinitions( byte17 );
+ }
+
+ return GetDigitalSyncSignalDefinitions( byte17 );
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetAnalogSyncSignalDefinitions
+//
+// ----------------------------------------------------------------------------
+//
+TEdidSyncSignalDefinitions CCea861EdidParser::GetAnalogSyncSignalDefinitions( const TUint8 aByte17 )
+ {
+ FUNC_LOG;
+
+ // byte 17
+ // 4 3 2 1 _ Analog Sync Signal Definitions:
+ //------------------------------------------
+ // 0 0 _ _ _ Analog Composite Sync:
+ // 0 1 _ _ _ Bipolar Analog Composite Sync:
+ // 0 _ 0 _ _ ---------- Without Serrations;
+ // 0 _ 1 _ _ ---------- With Serrations (H-sync during V-sync);
+ // 0 _ _ 0 _ -------------------- Sync On Green Signal only
+ // 0 _ _ 1 _ -------------------- Sync On all three (RGB) video signals
+
+ TBool ACS = !( KBit3 & aByte17 ); // if true -> bipolar analog composite sync
+ TBool serrations = KBit2 & aByte17;
+ TBool syncOnGreen = !( KBit1 & aByte17 );
+
+ if( ACS )
+ {
+ if( !serrations )
+ {
+ if( syncOnGreen )
+ {
+ return EAnalogCompositeSyncWithoutSerrationsSyncSyncOnGreenSignalOnly;
+ }
+ else
+ {
+ return EAnalogCompositeSyncWithoutSerrationsSyncOnAllThreeVideoSignals;
+ }
+ }
+ else
+ {
+ if( syncOnGreen )
+ {
+ return EAnalogCompositeSyncWithoutSerrationsSyncSyncOnGreenSignalOnly;
+ }
+ else
+ {
+ return EAnalogCompositeSyncWithoutSerrationsSyncOnAllThreeVideoSignals;
+ }
+ }
+ }
+ else
+ {
+ if( !serrations )
+ {
+ if( syncOnGreen )
+ {
+ return EAnalogBipolarAnalogCompositeSyncWithoutSerrationsSyncSyncOnGreenSignalOnly;
+ }
+ else
+ {
+ return EAnalogBipolarAnalogCompositeSyncWithoutSerrationsSyncOnAllThreeVideoSignals;
+ }
+ }
+ else
+ {
+ if( syncOnGreen )
+ {
+ return EAnalogBipolarAnalogCompositeSyncWithSerrationsSyncSyncOnGreenSignalOnly;
+ }
+ else
+ {
+ return EAnalogBipolarAnalogCompositeSyncWithSerrationsSyncOnAllThreeVideoSignals;
+ }
+ }
+ }
+ // unreachable
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::GetDigitalSyncSignalDefinitions
+//
+// ----------------------------------------------------------------------------
+//
+TEdidSyncSignalDefinitions CCea861EdidParser::GetDigitalSyncSignalDefinitions( const TUint8 aByte17 )
+ {
+ FUNC_LOG;
+
+ // 4 3 2 1 0 bit
+ // --------------
+ // 1 0 _ _ _ Digital Composite Sync:
+ // 1 0 0 _ _ ---------- Without Serrations;
+ // 1 0 1 _ _ ---------- With Serrations (H-sync during V-sync);
+ // 1 1 _ _ _ Digital Separate Sync:
+ // 1 1 0 _ _ ---------- Vertical Sync is Negative;
+ // 1 1 1 _ _ ---------- Vertical Sync is Positive;
+ // 1 _ _ 0 _ -------------------- Horizontal Sync is Negative (outside of V-sync)
+ // 1 _ _ 1 _ -------------------- Horizontal Sync is Positive (outside of V-sync)
+
+ TBool digComp = !( KBit3 & aByte17 ); // ETrue == digital separate sync
+ TBool bit2 = KBit2 & aByte17;
+
+ if( digComp ) // digital composite sync
+ {
+ if( !bit2 ) // without serrations
+ {
+ return EDigitalCompositeSyncWithoutSerrations;
+ }
+ else // with serrations
+ {
+ return EDigitalCompositeSyncWithSerrations;
+ }
+ } // endif digital composite sync
+ else // digital separate sync
+ {
+ TBool bit1 = KBit1 & aByte17;
+
+ if( !bit2 ) // vertical = neg
+ {
+ if( !bit1 )
+ { // vertical = neg, horizontal = neg
+ return EDigitalSeparateSyncVerticalSyncIsNegativeHorizontalSyncIsNegative;
+ }
+ else
+ { // vertical = neg, horizontal = pos
+ return EDigitalSeparateSyncVerticalSyncIsNegativeHorizontalSyncIsPositive;
+ }
+ }
+ else // vertical = pos
+ {
+ if( !bit1 )
+ { // vertical = pos, horizontal = neg
+ return EDigitalSeparateSyncVerticalSyncIsPositiveHorizontalSyncIsNegative;
+ }
+ else
+ { // vertical = pos, horizontal = pos
+ return EDigitalSeparateSyncVerticalSyncIsPositiveHorizontalSyncIsPositive;
+ }
+ }
+ }
+ // unreachable
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::ReadCeaDataBlockCollectionL
+//
+// ----------------------------------------------------------------------------
+//
+TInt CCea861EdidParser::ReadCeaDataBlockCollectionL( const TExtDataBlock& aData,
+ TInt& aIndex )
+ {
+ FUNC_LOG;
+
+ // bits 5-7 | bits 0-4
+ // Tag Code | Length = total number of video bytes following this byte (L1)
+ TInt tag = 0; // video tag code
+ TInt L1 = 0; // lenght (L1)
+ if( KBit7 & aData[aIndex] )
+ {
+ tag += 4;
+ }
+ if( KBit6 & aData[aIndex] )
+ {
+ tag += 2;
+ }
+ if( KBit5 & aData[aIndex] )
+ {
+ tag += 1;
+ }
+ L1 = aData[aIndex] & 0x1F; // clear the 3 MSBits
+
+ aIndex++; // jump over the first byte
+
+ TInt auxTag = 0;
+ switch( tag )
+ {
+ case 0:
+ //reserved
+ break;
+ case 1:
+ ReadCea861ShortAudioDataBlockL( aData, aIndex, L1 );
+ break;
+ case 2:
+ ReadCea861ShortVideoDataBlockL( aData, aIndex, L1 );
+ break;
+ case 3:
+ ReadCea861VendorSpecificDataBlockL( aData, aIndex, L1 );
+ break;
+ case 4:
+ ReadCea861SpeakerAllocationDataBlock( aData, aIndex, L1 );
+ break;
+ case 5:
+ //VESA DTC Data Block
+ ReadUnknownTagCode( aData, aIndex, L1 );
+ break;
+ case 6:
+ //reserved
+ ReadUnknownTagCode( aData, aIndex, L1 );
+ break;
+ case 7:
+ //use extended tag (second byte holds the extended tag-code)
+ // (see table 43 in CEA-861 spec) (if using repeater, then these information must be re-transmitted)
+ auxTag = aData[aIndex + 1];
+ if( auxTag == 5 ) // colorimetry, see table 51, table 52 and table 53 in CEA-861-E.pdf
+ {
+ }
+ else if( auxTag == 0x07 ) // video Capability Data Block, see table 54
+ {
+ ReadVideoCapabilityDataBlockL( aData, aIndex, L1 );
+ }
+ else if( auxTag == 0x01 ) // Vendor-Specific Video Data Block, see table 56
+ {
+ }
+ else if( auxTag == 0x11 ) // Vendor-Specific Audio Data Block, see table 57
+ {
+ }
+ // TODO: these should be read as well, not just as unknown
+ ReadUnknownTagCode( aData, aIndex, L1 );
+ break;
+ default:
+ // if tag-code is unknown, we still must read through it
+ ReadUnknownTagCode( aData, aIndex, L1 );
+ break;
+ }
+
+ return KErrNone;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::ReadCea861ShortAudioDataBlockL
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::ReadCea861ShortAudioDataBlockL( const TExtDataBlock& aData,
+ TInt& aIndex,
+ const TInt8 aLen )
+ {
+ FUNC_LOG;
+
+ iAudioDataBlockSupported = ETrue;
+
+ if( !iParsedInfo->iShortAudioDescriptors ) // linked list
+ {
+ iParsedInfo->iShortAudioDescriptors
+ = new ( ELeave ) TCEA861AudioDataBlock();
+ }
+ TCEA861AudioDataBlock* cur = iParsedInfo->iShortAudioDescriptors;
+
+ while( cur->iNext != 0 )
+ {
+ cur = cur->iNext; // jump to the end
+ }
+
+ TBool first = ETrue;
+ for( int i = 0; i < aLen; i++ )
+ {
+ // read aLen-amount of short video descriptors
+
+ // first link is a special case
+ if( ( iParsedInfo->iShortAudioDescriptors == cur ) && first )
+ {
+ first = EFalse;
+ cur->iByte1 = aData[aIndex];
+ cur->iByte2 = aData[aIndex + 1];
+ cur->iByte3 = aData[aIndex + 2];
+ DetermineAudioBlockInformation( cur );
+ aIndex += 3;
+ i += 3;
+ continue;
+ }
+
+ // create new data blocks
+ cur->iNext = new ( ELeave ) TCEA861AudioDataBlock();
+ cur = cur->iNext;
+ cur->iByte1 = aData[aIndex];
+ cur->iByte2 = aData[aIndex + 1];
+ cur->iByte3 = aData[aIndex + 2];
+ cur->iNext = 0;
+
+ DetermineAudioBlockInformation( cur );
+
+ aIndex += 3;
+ i += 3;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::ReadCea861ShortVideoDataBlockL
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::ReadCea861ShortVideoDataBlockL( const TExtDataBlock& aData,
+ TInt& aIndex,
+ const TInt8 aLen )
+ {
+ FUNC_LOG;
+
+ TBool first = ETrue;
+ iVideoDataBlockSupported = ETrue;
+ if( !iParsedInfo->iShortVideoDescriptors ) // linked list
+ {
+ iParsedInfo->iShortVideoDescriptors
+ = new ( ELeave ) TCEA861VideoDataBlock();
+ iParsedInfo->iShortVideoDescriptors->iNext = 0; // make sure there are no stray pointers
+ }
+
+ TCEA861VideoDataBlock* cur = iParsedInfo->iShortVideoDescriptors;
+ while( cur->iNext != 0 )
+ {
+ cur = cur->iNext; // jump to the end
+ first = EFalse; // there is already some links, so set first to false
+ }
+
+ for( int i = 0; i < aLen; i++ )
+ {
+
+ // read aLen-amount of short video descriptors
+
+ // first link is a special case
+ if( ( iParsedInfo->iShortVideoDescriptors == cur ) && first )
+ {
+ first = EFalse;
+ cur->iNative = KBit7 & aData[aIndex];
+ cur->iVIC = ( ~KBit7 ) & aData[aIndex]; // nullify the most signicant bit
+ cur->iNext = 0;
+ aIndex++;
+ continue;
+ }
+
+ // create new data blocks
+ cur->iNext = new ( ELeave ) TCEA861VideoDataBlock();
+ cur = cur->iNext;
+ cur->iNative = KBit7 & aData[aIndex];
+ cur->iVIC = ( ~KBit7 ) & aData[aIndex]; // nullify the most signicant bit
+ cur->iNext = 0;
+ aIndex++;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::ReadCea861VendorSpecificDataBlockL
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::ReadCea861VendorSpecificDataBlockL( const TExtDataBlock& aData,
+ TInt& aIndex,
+ TInt8 aLen )
+ {
+ FUNC_LOG;
+
+ iVendorSpecificDataBlockSupported = ETrue;
+
+ if( !iParsedInfo->iVendorSpecificData )
+ {
+ iParsedInfo->iVendorSpecificData = new ( ELeave ) TCEA861VendorSpecificDataBlock();
+ }
+
+
+ TUint8 data1 = aData[aIndex]; // least significant byte first
+ TUint8 data2 = aData[aIndex + 1];
+ TUint8 data3 = aData[aIndex + 2];
+ aIndex += 3; // three bytes of IEEE registration identifier
+
+ iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier = 0; // convert from LSB -> MSB
+ iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier += data3;
+ iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier
+ = iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier
+ << 8;
+ iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier += data2;
+ iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier
+ = iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier
+ << 8;
+ iParsedInfo->iVendorSpecificData->iIEEE24bitRegistrationIdentifier += data1;
+
+ aLen -= 3; // this is needed: Vendor specific payload length = L4-3bytes
+
+ TBool first = ETrue;
+ if( iParsedInfo->iVendorSpecificData->iVendorSpecificPayloadStart == 0 )
+ {
+ iParsedInfo->iVendorSpecificData->iVendorSpecificPayloadStart
+ = new ( ELeave ) TCEA861VendorSpecificDataBlockPayload();
+ }
+ TCEA861VendorSpecificDataBlockPayload* cur =
+ iParsedInfo->iVendorSpecificData->iVendorSpecificPayloadStart;
+ // traverse to the end of the list
+ while( cur->iNext != 0 )
+ {
+ cur = cur->iNext;
+ }
+
+ for( int i = 0; i < aLen; i++ )
+ {
+ if( ( cur == iParsedInfo->iVendorSpecificData->iVendorSpecificPayloadStart )
+ && first ) // first byte is special case
+ {
+ first = EFalse;
+ cur->iData = aData[aIndex];
+ cur->iNext = NULL;
+ aIndex++;
+ continue;
+ }
+ cur->iNext = new ( ELeave ) TCEA861VendorSpecificDataBlockPayload();
+ cur = cur->iNext;
+ cur->iData = aData[aIndex];
+ cur->iNext = 0;
+ aIndex++;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::ReadCea861SpeakerAllocationDataBlock
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::ReadCea861SpeakerAllocationDataBlock( const TExtDataBlock& aData,
+ TInt& aIndex,
+ const TInt8 aLen )
+ {
+ FUNC_LOG;
+
+ // read the 3 bytes
+ if( aLen != 3 )
+ {
+ return;
+ }
+
+ iSpeakerAllocationDataBlockSupported = ETrue;
+
+ for( TInt i = 0; i < aLen; i++ )
+ {
+ switch( i )
+ {
+ case 0:
+ iParsedInfo->iSpeakerAllocationData.iByte1 = aData[aIndex];
+ break;
+ case 1:
+ iParsedInfo->iSpeakerAllocationData.iByte2 = aData[aIndex];
+ break;
+ case 2:
+ iParsedInfo->iSpeakerAllocationData.iByte3 = aData[aIndex];
+ break;
+ default:
+ // error
+ break;
+ }
+ aIndex++;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::ReadVideoCapabilityDataBlockL
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::ReadVideoCapabilityDataBlockL( const TExtDataBlock& aData,
+ TInt& aIndex,
+ const TInt8 aLen )
+ {
+ FUNC_LOG;
+
+ aIndex++; // jump to the extended tag code (aLen is the length from extended tag to the end)
+
+ if( iParsedInfo->iVideoCapabilityDataBlock == 0 )
+ {
+ iParsedInfo->iVideoCapabilityDataBlock
+ = new ( ELeave ) TCEA861VideoCapabilityDataBlock();
+ }
+ TCEA861VideoCapabilityDataBlock* cur =
+ iParsedInfo->iVideoCapabilityDataBlock;
+ TBool first = ETrue;
+ while( cur->iNext != 0 )
+ {
+ first = EFalse;
+ cur = cur->iNext;
+ }
+
+ // Payload currently only contains a single byte in addition to the extended tag code. The Source should ignore such additional bytes when present.
+ for( int i = 0; i < aLen; i++ )
+ {
+ if( i == 1 )
+ {
+ if( !first ) // if this wasn't the first time we are reading to this
+ {
+ cur->iNext = new ( ELeave ) TCEA861VideoCapabilityDataBlock(); // sets Next to 0
+ cur = cur->iNext;
+ }
+ cur->iInitialized = ETrue;
+ cur->iQuantizationRange = aData[aIndex] & KBit7;
+ cur->iQuantizationRangeSelectable = aData[aIndex] & KBit6;
+ cur->iS_PT1 = aData[aIndex] & KBit5;
+ cur->iS_PT0 = aData[aIndex] & KBit4;
+ cur->iS_IT1 = aData[aIndex] & KBit3;
+ cur->iS_IT0 = aData[aIndex] & KBit2;
+ cur->iS_CE1 = aData[aIndex] & KBit1;
+ cur->iS_CE0 = aData[aIndex] & KBit0;
+ cur->iNext = 0;
+ }
+ aIndex++;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::readUnknownTagCode
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::ReadUnknownTagCode( const TExtDataBlock& /*aData*/,
+ TInt& aIndex,
+ const TInt8 aLen )
+ {
+ FUNC_LOG;
+
+ // Skip the data. This must be done if the tag is unknown
+ aIndex += aLen;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::DetermineAudioBlockInformation
+//
+// ----------------------------------------------------------------------------
+//
+void CCea861EdidParser::DetermineAudioBlockInformation( TCEA861AudioDataBlock* aAudioBlock )
+ {
+ FUNC_LOG;
+
+ // x6543xxx we need the information in the bytes 6543
+ aAudioBlock->iAudioFormatCode = ( KBit3 | KBit2 | KBit1 | KBit0 )
+ & ( aAudioBlock->iByte1 >> 3 );
+ aAudioBlock->iSupport192kHz = ( aAudioBlock->iByte2 & KBit6 ? ETrue : EFalse );
+ aAudioBlock->iSupport176kHz = ( aAudioBlock->iByte2 & KBit5 ? ETrue : EFalse );
+ aAudioBlock->iSupport96kHz = ( aAudioBlock->iByte2 & KBit4 ? ETrue : EFalse );
+ aAudioBlock->iSupport88kHz = ( aAudioBlock->iByte2 & KBit3 ? ETrue: EFalse );
+ aAudioBlock->iSupport48kHz = ( aAudioBlock->iByte2 & KBit2 ? ETrue : EFalse );
+ aAudioBlock->iSupport44kHz = ( aAudioBlock->iByte2 & KBit1 ? ETrue : EFalse );
+ aAudioBlock->iSupport32kHz = ( aAudioBlock->iByte2 & KBit0 ? ETrue : EFalse );
+ aAudioBlock->iMaxChannels = aAudioBlock->iByte1 & 0x07; // only the 3 LSB is used
+ //TODO: 3rd byte shall be read according to the audioformatcode (see table 45 in CEA-861-E.pdf)
+ switch( aAudioBlock->iAudioFormatCode )
+ {
+ case 1:
+ aAudioBlock->iSupport24Bit = ( aAudioBlock->iByte3 & KBit2 ? ETrue : EFalse );
+ aAudioBlock->iSupport20Bit = ( aAudioBlock->iByte3 & KBit1 ? ETrue : EFalse );
+ aAudioBlock->iSupport16Bit = ( aAudioBlock->iByte3 & KBit0 ? ETrue : EFalse );
+ break;
+ case 2: //cases 2-8
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ aAudioBlock->iMaxBitrate = aAudioBlock->iByte3 * 8;
+ break;
+ case 9: // cases 9-13
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ // byte3 is Audio format code dependent value
+ break;
+ case 14:
+ // byte3 bits 0,1,2 is profile. bits 3-7 are reserved.
+ break;
+ case 15: // bits 7-3 = audio format code extension, bits 2-0
+ aAudioBlock->iAudioFormatCodeExtension = aAudioBlock->iByte3 >> 3;
+ break;
+ default:
+ // error
+ break;
+ }
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::LatencyFieldsPresent
+//
+// ----------------------------------------------------------------------------
+//
+TBool CCea861EdidParser::LatencyFieldsPresent( TUint8 aByte ) const
+ {
+ FUNC_LOG;
+
+ TBool present = EFalse;
+
+ // Latency_Fields_Preset bit is bit6 (01000000) in the aByte
+ if( aByte & 0x40 )
+ {
+ present = ETrue;
+ }
+ return present;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::InterlacedLatencyFieldsPresent
+//
+// ----------------------------------------------------------------------------
+//
+TBool CCea861EdidParser::InterlacedLatencyFieldsPresent( TUint8 aByte ) const
+ {
+ FUNC_LOG;
+
+ TBool present = EFalse;
+
+ // Latency_Fields_Preset bit is bit7 (10000000) in the aByte
+ if( aByte & 0x80 )
+ {
+ present = ETrue;
+ }
+ return present;
+ }
+
+// ----------------------------------------------------------------------------
+// CCea861EdidParser::InterlacedLatencyFieldsPresent
+//
+// ----------------------------------------------------------------------------
+//
+TUint8 CCea861EdidParser::LatencyInMs( TUint8 aByte ) const
+ {
+ FUNC_LOG;
+
+ TUint8 latency = 0;
+ if( aByte > 0 && aByte <= 251 )
+ {
+ latency = ( aByte - 1 ) * 2;
+ }
+
+ return latency;
+ }
+
+// End of file