diff -r 000000000000 -r 4e1aa6a622a0 accessoryservices/pluggeddisplay/edidparser/src/cea861edidparser.cpp --- /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