localconnectivityservice/generichid/src/hidparser.cpp
branchRCL_3
changeset 19 0aa8cc770c8a
equal deleted inserted replaced
18:453dfc402455 19:0aa8cc770c8a
       
     1 /*
       
     2 * Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  HID parser implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // ----------------------------------------------------------------------
       
    20 
       
    21 // References:
       
    22 //
       
    23 // [1] USB Device Class Definition for Human Interface Devices (HID),
       
    24 //     Firmware Specification, Version 1.11, USB Implementers' Forum,
       
    25 //     June 2001
       
    26 //
       
    27 // [2] HID Parser Error Codes (HID Parser Error Checking), Revision
       
    28 //     1.2, USB Implementers' Forum, February 2000
       
    29 //
       
    30 // [3] USB HID Usage Tables, Version 1.11, USB Implementers' Forum,
       
    31 //     June 2001
       
    32 //
       
    33 // ----------------------------------------------------------------------
       
    34 
       
    35 #include <e32std.h>
       
    36 #include <e32base.h>
       
    37 #include <e32des8.h>
       
    38 #include <e32svr.h>
       
    39 
       
    40 #include "hidreportroot.h"
       
    41 #include "hiditem.h"
       
    42 #include "hidparser.h"
       
    43 #include "debug.h"
       
    44 
       
    45 
       
    46 
       
    47 
       
    48 // ----------------------------------------------------------------------
       
    49 /*
       
    50 // Define PARSER_DEBUG to activate trace output for WINS debug builds:
       
    51 #undef PARSER_DEBUG
       
    52 
       
    53 #if defined(PARSER_DEBUG) && defined(_DEBUG) && defined(__WINS__)
       
    54 #define PDBG(a) a;
       
    55 #define PDBG_ACTIVE
       
    56 #else
       
    57 #define PDBG(a)
       
    58 #endif
       
    59 */
       
    60 #define PDBG_ACTIVE
       
    61 
       
    62 const TUint32 CParser::KLocalItemMask =
       
    63     EUsageMin | EUsageMax | EUsageId |
       
    64     EDesignatorIndex | EDesignatorMin | EDesignatorMax |
       
    65     EStringIndex | EStringMin | EStringMax;
       
    66 
       
    67 
       
    68 const TUint32 KMaxStandardType   = 0x06;
       
    69 const TUint32 KMinVendorType     = 0x80;
       
    70 const TUint32 KMaxVendorType     = 0xFF;
       
    71 const TUint32 KMaxUsagePage      = 0xffff;
       
    72 const TUint32 KUnitData          = 0x0f;
       
    73 
       
    74 const TUint32 CParser::KUnusedLocalItemsMask = KLocalItemMask & ~EUsageId;
       
    75 
       
    76 const TUint32 KInputReservedBitsMask    = 0xffffff00;
       
    77 const TUint32 KOutputReservedBitsMask   = 0xffffff00;
       
    78 const TUint32 KFeatureReservedBitsMask  = 0xffffff00;
       
    79 const TUint32 KUnitReservedBitsMask     = 0xf0000000;
       
    80 
       
    81 const TInt KConstantFlag    = 1<<0;  // Constant (1) or Data (0)
       
    82 const TInt KVariableFlag    = 1<<1;  // Array (0) or Variable (1)
       
    83 const TInt KNullStateFlag   = 1<<6;
       
    84 
       
    85 const TInt KExtendedDataSize  = 4;   // 32-bit extended data size
       
    86 const TInt KExtendedDataShift = 16;  // 16 bit shift if extended usage page is used
       
    87 const TInt KMaxReportIDMax    = 255;
       
    88 const TInt K32Bit             = 32;
       
    89 
       
    90 const TUint K32BitFirstBitOn   = 1u<<31;
       
    91 const TInt  KUnitSystemMin     = 5;
       
    92 const TInt  KUnitSystem15      = 15;
       
    93 
       
    94 const TUint32 CParser::KMandatoryItemMask = EUsagePage |
       
    95         ELogicalMin | ELogicalMax | EReportSize | EReportCount;
       
    96         
       
    97 const TUint32 CParser::KReportItemMask = EInputReport |
       
    98                   EOutputReport | EFeatureReport;        
       
    99 
       
   100 
       
   101 // Reserved values as per the HUT document 1.11, [3]:
       
   102 // This ranges are reserverd in future use.
       
   103 
       
   104 const TInt KReservedUsage = 0x0e;
       
   105 const TInt KReservedUsageRange1Min = 0x11;
       
   106 const TInt KReservedUsageRange1Max = 0x13;
       
   107 const TInt KReservedUsageRange2Min = 0x15;
       
   108 const TInt KReservedUsageRange2Max = 0x3f;
       
   109 const TInt KReservedUsageRange3Min = 0x41;
       
   110 const TInt KReservedUsageRange3Max = 0x7f;
       
   111 const TInt KReservedUsageRange4Min = 0x88;
       
   112 const TInt KReservedUsageRange4Max = 0x8b;
       
   113 const TInt KReservedUsageRange5Min = 0x92;
       
   114 const TInt KReservedUsageRange5Max = 0xfeff;
       
   115 
       
   116 // ======== MEMBER FUNCTIONS ========
       
   117 
       
   118 // ---------------------------------------------------------------------------
       
   119 // NewLC()
       
   120 // ---------------------------------------------------------------------------
       
   121 //
       
   122 EXPORT_C CParser* CParser::NewLC()
       
   123     {
       
   124     CParser* self = new (ELeave) CParser;
       
   125     CleanupStack::PushL(self);
       
   126     self->ConstructL();
       
   127     return self;
       
   128     }
       
   129 
       
   130 // ---------------------------------------------------------------------------
       
   131 // NewL()
       
   132 // ---------------------------------------------------------------------------
       
   133 //
       
   134 EXPORT_C CParser* CParser::NewL()
       
   135     {
       
   136     CParser* self = NewLC();
       
   137     CleanupStack::Pop();
       
   138     return self;
       
   139     }
       
   140 
       
   141 // ---------------------------------------------------------------------------
       
   142 // ConstructL()
       
   143 // ---------------------------------------------------------------------------
       
   144 //
       
   145 void CParser::ConstructL()
       
   146     {
       
   147     TRACE_FUNC_THIS
       
   148     iLocal = CField::NewL();
       
   149     }
       
   150 
       
   151 // ---------------------------------------------------------------------------
       
   152 // Constructor
       
   153 // ---------------------------------------------------------------------------
       
   154 //
       
   155 CParser::CParser():
       
   156     iFieldCount(0)
       
   157     {
       
   158     TRACE_FUNC_THIS
       
   159     }
       
   160 
       
   161 // ---------------------------------------------------------------------------
       
   162 // Destructor
       
   163 // ---------------------------------------------------------------------------
       
   164 //
       
   165 CParser:: ~CParser()
       
   166     {
       
   167     TRACE_FUNC_THIS
       
   168 
       
   169     // Free all RArray storage:
       
   170     iGlobalStack.Reset();
       
   171 
       
   172 
       
   173     // Although iCollectionStack is an RPointerArray, we aren't doing
       
   174     // a ResetAndDestroy() here, as all the collections are owned by
       
   175     // the report root object, iReportRoot:
       
   176     iCollectionStack.Reset();
       
   177 
       
   178     delete iReportRoot;
       
   179     delete iLocal;
       
   180     }
       
   181 
       
   182 // ---------------------------------------------------------------------------
       
   183 // CreateCollectionL
       
   184 // ---------------------------------------------------------------------------
       
   185 //
       
   186 TInt CParser::CreateCollectionL(TUint32 aType)
       
   187     {
       
   188     TInt err = CheckForCollectionErrors(aType);
       
   189 
       
   190     if (err == KErrNone)
       
   191         {
       
   192         CCollection* collection = Collection()->AddCollectionL(); // Created collection added
       
   193                                                                   // Collection's collection array
       
   194         collection->SetType(aType);
       
   195         collection->SetUsagePage(iGlobal.iUsagePage);
       
   196         collection->SetUsage(iLocal->LastUsage());
       
   197         PushCollectionL(collection);         
       
   198         }
       
   199     return err;
       
   200     }
       
   201 
       
   202 // ---------------------------------------------------------------------------
       
   203 // CheckForMainErrors()
       
   204 // ---------------------------------------------------------------------------
       
   205 //
       
   206 TInt CParser::CheckForMainErrors()
       
   207     {
       
   208     if ( ( iItemsDefined & ELogicalMin ) && ( iItemsDefined & ELogicalMax ) )
       
   209         {
       
   210         if ( iGlobal.iLogicalMin > iGlobal.iLogicalMax )
       
   211             {
       
   212             IssueWarning( ELogicalMinExceedsMax );
       
   213             }
       
   214         }
       
   215     if ( iItemsDefined & (EPhysicalMin | EPhysicalMax ) )
       
   216         {
       
   217         if ( !( iItemsDefined & EPhysicalMax ) )
       
   218             {
       
   219             return ELonelyPhysicalMin;
       
   220             }
       
   221         if (!( iItemsDefined & EPhysicalMin ))
       
   222             {
       
   223             return ELonelyPhysicalMax;
       
   224             }
       
   225 
       
   226         if ( iGlobal.iPhysicalMin > iGlobal.iPhysicalMax )
       
   227             {
       
   228             IssueWarning(EPhysicalMinExceedsMax);
       
   229             }
       
   230         }
       
   231     return KErrNone;
       
   232     }
       
   233 
       
   234 // ---------------------------------------------------------------------------
       
   235 // CheckForCollectionErrors()
       
   236 // ---------------------------------------------------------------------------
       
   237 //
       
   238 TInt CParser::CheckForCollectionErrors(TUint32 aType)
       
   239     {    
       
   240     if (iCollectionStack.Count() == 0 )
       
   241         {
       
   242         return ENoCollectionToCheck;
       
   243         }
       
   244 
       
   245     if (aType > KMaxStandardType)
       
   246         {
       
   247         if ((aType < KMinVendorType) || (aType > KMaxVendorType))
       
   248             {
       
   249             IssueWarning( ECollectionTypeUnknownReserved );
       
   250             }
       
   251         }
       
   252     
       
   253     if ( iItemsDefined & KUnusedLocalItemsMask )
       
   254         {
       
   255         IssueWarning( ECollectionLocalUnused );
       
   256         }
       
   257 
       
   258     TInt numUsages = iLocal->UsageCount();
       
   259 
       
   260     if ( numUsages > 1 )
       
   261         {
       
   262         // Only a single usage value can be associated with a collection:
       
   263         IssueWarning( ECollectionLocalUnused );
       
   264         }
       
   265 
       
   266     if ( numUsages == 0 )
       
   267         {
       
   268         // A usage tag must be associated with a collection (see [1],
       
   269         // Section 6.2.2.6):
       
   270         IssueWarning( ECollectionHasNoUsage );
       
   271         }
       
   272 
       
   273     if ( !( iItemsDefined & EUsagePage ) )
       
   274         {
       
   275         // A usage page must be associated with a collection (see [1],
       
   276         // Section 6.2.2.6):
       
   277         IssueWarning( ECollectionHasNoUsagePage );
       
   278         }
       
   279 
       
   280     if (( aType == CCollection::EApplication ) && ( iItemsDefined & EDelimiter ))
       
   281         {
       
   282         // Delimiters can't be used when defining usages that apply to
       
   283         // Application Collections ([1], Section 6.2.2.8):
       
   284         IssueWarning(EApplicationHasDelimiter);
       
   285 
       
   286         // It is an error to declare a delimiter for a top-level
       
   287         // application collection, [2]:
       
   288         if (iCollectionStack.Count() == 1)
       
   289             {
       
   290             return EDelimiterAtTopLevel;
       
   291             }
       
   292         }
       
   293     return CheckForMainErrors();
       
   294     }
       
   295 
       
   296 
       
   297 // ---------------------------------------------------------------------------
       
   298 // CheckForFieldErrors()
       
   299 // ---------------------------------------------------------------------------
       
   300 //
       
   301 TInt CParser::CheckForFieldErrors(CField::TType aType, TUint32 aAttributes)
       
   302     {  
       
   303     TInt ret = KErrNone;
       
   304     ret = CheckMandatoryFieldErrors(aType, aAttributes);
       
   305     if ( ret != KErrNone )
       
   306         {
       
   307         return ret;    
       
   308         }
       
   309     
       
   310     const TInt KLimitsError[] =
       
   311         { EInputMinExceedsMax, EOutputMinExceedsMax, EFeatureMinExceedsMax };
       
   312 
       
   313     if ( iGlobal.iLogicalMin > iGlobal.iLogicalMax )
       
   314         {
       
   315         return KLimitsError[aType];
       
   316         }
       
   317 
       
   318     if ( ( iItemsDefined & ( EPhysicalMin | EPhysicalMax ) )
       
   319         && ( iGlobal.iPhysicalMin > iGlobal.iPhysicalMax ))
       
   320         {
       
   321         return KLimitsError[aType];
       
   322         }   
       
   323     CheckLogicalMinAndMax( aAttributes );     
       
   324     CheckFieldBitNeeded( aType, aAttributes );
       
   325     return CheckForMainErrors();
       
   326     }
       
   327 
       
   328 
       
   329 // ---------------------------------------------------------------------------
       
   330 // BitsToRepresentRange()
       
   331 // ---------------------------------------------------------------------------
       
   332 //
       
   333 TInt CParser::BitsToRepresentRange(TInt aMin, TInt aMax)
       
   334     {
       
   335     // The number of bits required to represent all values in the
       
   336     // range aMin to aMax inclusive.  If the range is all positive
       
   337     // then there is no sign bit, otherwise twos complement format is
       
   338     // assumed. ([1], Section 6.2.2.7.)
       
   339 
       
   340     TInt bitsNeeded = 0;
       
   341 
       
   342     if (aMin != aMax)
       
   343         {
       
   344         TUint absVal = static_cast<TUint>(Max(Abs(aMin), Abs(aMax)));
       
   345 
       
   346         bitsNeeded = K32Bit - NumberOfLeadingZeros(absVal);
       
   347 
       
   348         // If either are negative, we'll need space for the sign bit:
       
   349         //
       
   350         if ((aMax < 0) || (aMin < 0))
       
   351             {
       
   352             bitsNeeded++;
       
   353 
       
   354             // However, 2s complement allows us to represent one extra
       
   355             // negative number than positive, and so our calculation
       
   356             // may be one bit over. Catch this with a special case:
       
   357             //
       
   358             if (bitsNeeded > 1)
       
   359                 {
       
   360                 TInt n = 1 << (bitsNeeded - 2);
       
   361                 if ((aMin == -n) && (aMax < n))
       
   362                     {
       
   363                     bitsNeeded--;
       
   364                     }
       
   365                 }
       
   366             }
       
   367         }
       
   368 
       
   369     return bitsNeeded;
       
   370     }
       
   371 
       
   372 // ---------------------------------------------------------------------------
       
   373 // NumberOfLeadingZeros()
       
   374 // ---------------------------------------------------------------------------
       
   375 //
       
   376 TInt CParser::NumberOfLeadingZeros(TUint32 aValue)
       
   377     {
       
   378     TInt count = 0;
       
   379 
       
   380     TUint32 pos = K32BitFirstBitOn;
       
   381     while ((pos != 0) && ((aValue & pos) == 0))
       
   382         {
       
   383         count++;
       
   384         pos >>= 1;
       
   385         }
       
   386 
       
   387     return count;
       
   388     }
       
   389 
       
   390 
       
   391 // ---------------------------------------------------------------------------
       
   392 // CheckAllReportSizes()
       
   393 // ---------------------------------------------------------------------------
       
   394 //
       
   395 TBool CParser::CheckAllReportSizes() const
       
   396     {
       
   397     // Final report sizes must be an integral number of bytes, [2]:
       
   398 
       
   399     TBool sizesOk = ETrue;
       
   400 
       
   401     for (TInt i=0; sizesOk && (i<iReportRoot->NumberOfReports()); ++i)
       
   402         {
       
   403         TInt bits = iReportRoot->ReportSize(i);
       
   404 
       
   405         if ((bits == 0) || ((bits % 8) != 0))
       
   406             {
       
   407             sizesOk = EFalse;
       
   408             }
       
   409         }
       
   410     return sizesOk;
       
   411     }
       
   412 
       
   413 
       
   414 // ---------------------------------------------------------------------------
       
   415 // CreateFieldL()
       
   416 // ---------------------------------------------------------------------------
       
   417 //
       
   418 TInt CParser::CreateFieldL(CField::TType aType, TUint32 aAttributes)
       
   419     {
       
   420     TInt err = CheckForFieldErrors( aType, aAttributes );
       
   421     //Microsoft Elite 2 keyboard HID bug fix
       
   422 	if ( err == EInputMissingItems && iGlobal.iUsagePage == 0x07 )
       
   423 		if ( iLocal->UsageMin( ) == 0xe0 && iLocal->UsageMax( ) == 0xe7 )
       
   424 			{
       
   425 			iGlobal.iLogicalMin = 0x0;
       
   426 			iGlobal.iLogicalMax = 0x1;
       
   427 			err = KErrNone;
       
   428 			}
       
   429 		else
       
   430 			{
       
   431 			iGlobal.iLogicalMin = 0x0;
       
   432 			err = KErrNone;
       
   433 			}
       
   434 
       
   435     if (err == KErrNone)
       
   436         {
       
   437         // Create a new field object:
       
   438         CField* field = Collection()->AddFieldL( );   // Created field added
       
   439                                                       // to collection's field array
       
   440         DumpStateTableL( field );
       
   441         field->SetType( aType );
       
   442         field->SetAttributes( aAttributes );
       
   443 
       
   444         // Set the field offset to the current report size, and
       
   445         // increase the report size by the size of this field:        
       
   446         if ( !iReportRoot )
       
   447             {
       
   448             User::Leave(ENoReportRoot);
       
   449             }
       
   450         field->SetOffset( iReportRoot->ReportSize( field->ReportId( ), aType) );
       
   451         iReportRoot->IncrementReportSizeL( field->ReportId(),
       
   452             aType, field->Count() * field->Size() );
       
   453         TRACE_INFO(_L("CParser::CreateFieldL Field added"));
       
   454         if ( field->UsageCount() )
       
   455             {
       
   456             iFieldCount++;
       
   457             }        
       
   458         }
       
   459     return err;
       
   460     }
       
   461 
       
   462 // ---------------------------------------------------------------------------
       
   463 // DumpStateTableL()
       
   464 // ---------------------------------------------------------------------------
       
   465 //
       
   466 void CParser::DumpStateTableL(CField *aField) const
       
   467     {
       
   468     TRACE_INFO((_L("DumpStateTableL(0x%08x)\n"), aField));
       
   469 
       
   470     // Copy global state:
       
   471     //
       
   472     iGlobal.Populate(aField);
       
   473 
       
   474     // Copy local state:
       
   475     //
       
   476     aField->SetUsageRange( iLocal->UsageMin(), iLocal->UsageMax() );
       
   477     aField->SetDesignatorIndex( iLocal->DesignatorIndex() );
       
   478     aField->SetDesignatorRange( iLocal->DesignatorMin(),
       
   479         iLocal->DesignatorMax() );
       
   480     aField->SetStringIndex( iLocal->StringIndex() );
       
   481     aField->SetStringRange( iLocal->StringMin(), iLocal->StringMax() );
       
   482 
       
   483     // Copy usage list (local state) and calculate the usage range, if
       
   484     // it hasn't already been explicitly specified:
       
   485     //
       
   486     if ( iLocal->UsageCount() > 0 )
       
   487         {
       
   488         TInt minUsage, maxUsage;
       
   489         minUsage = maxUsage = iLocal->Usage( 0 );
       
   490 
       
   491         for (TInt i=0; i<iLocal->UsageCount(); ++i)
       
   492             {
       
   493             TInt value = iLocal->Usage( i );
       
   494             aField->AddUsageL( value );
       
   495             if ( value < minUsage )
       
   496                 {
       
   497                 minUsage = value;
       
   498                 }
       
   499             if ( value > maxUsage )
       
   500                 {
       
   501                 maxUsage = value;
       
   502                 }
       
   503             }
       
   504         if ( (iItemsDefined & (EUsageMin | EUsageMax) ) == 0)
       
   505             {
       
   506             aField->SetUsageRange( minUsage, maxUsage );
       
   507             }
       
   508         }
       
   509     }
       
   510 
       
   511 
       
   512 // ---------------------------------------------------------------------------
       
   513 // Collection()
       
   514 // ---------------------------------------------------------------------------
       
   515 //
       
   516 CCollection* CParser::Collection()
       
   517     {    
       
   518     CCollection* lastcollection = NULL;
       
   519     if ( iCollectionStack.Count( ) > 0 )
       
   520         {
       
   521         lastcollection = iCollectionStack[ iCollectionStack.Count() - 1 ];
       
   522         }
       
   523     return lastcollection;
       
   524     }
       
   525 
       
   526 // ---------------------------------------------------------------------------
       
   527 // PushCollectionL()
       
   528 // ---------------------------------------------------------------------------
       
   529 //
       
   530 void CParser::PushCollectionL(const CCollection* aCollection)
       
   531     {
       
   532     User::LeaveIfError( iCollectionStack.Append( aCollection ) );
       
   533     }
       
   534 
       
   535 // ---------------------------------------------------------------------------
       
   536 // PopCollection()
       
   537 // ---------------------------------------------------------------------------
       
   538 //
       
   539 void CParser::PopCollection()
       
   540     {
       
   541     
       
   542     if ( iCollectionStack.Count() > 0 )
       
   543         {
       
   544         iCollectionStack.Remove( iCollectionStack.Count() - 1 );
       
   545         }
       
   546     }
       
   547 
       
   548 
       
   549 // ---------------------------------------------------------------------------
       
   550 // IssueWarning()
       
   551 // ---------------------------------------------------------------------------
       
   552 //
       
   553 void CParser::IssueWarning(TInt aHidWarningCode)
       
   554     {
       
   555     TRACE_ERROR((_L("Item %3d: Warning 0x%04x\n"), iItemNumber, aHidWarningCode));
       
   556     (void)aHidWarningCode;
       
   557     }
       
   558 
       
   559 // ---------------------------------------------------------------------------
       
   560 // ParseL()
       
   561 // ---------------------------------------------------------------------------
       
   562 //
       
   563 EXPORT_C CReportRoot* CParser::ParseL(const TDesC8& aRawData)
       
   564     {
       
   565     ResetParserL();    
       
   566     // Now we can parse the descriptor data:
       
   567     const TInt length = aRawData.Length();
       
   568     TInt posn = 0;
       
   569     TRACE_INFO((_L("CParser::ParseL() Start parsing length %d"), length));
       
   570     while ((posn < length) && (iErrorCode == 0))
       
   571         {
       
   572         iItemNumber++;
       
   573         TRACE_INFO((_L("posn is %d"), posn));
       
   574 
       
   575         TItem item(aRawData.Right(length-posn));
       
   576 
       
   577 #ifdef PDBG_ACTIVE
       
   578         TRACE_INFO((_L("Item: size %d, tag %d, type %d\n"),
       
   579                    item.DataSize(), item.Tag(), item.Type()));
       
   580         for (TInt i=0; i<item.DataSize(); ++i)
       
   581             {
       
   582             TRACE_INFO((_L("  Data[%d] = 0x%02x (%d)\n"),
       
   583                        i, item[i], item[i]))
       
   584             }
       
   585 #endif
       
   586 
       
   587         HandleItemL( item );        
       
   588         posn += item.ItemSize();
       
   589         if (posn > length)
       
   590             {
       
   591             iErrorCode = EInvalidItemLength;
       
   592             }
       
   593         }
       
   594 
       
   595     PopCollection();
       
   596 
       
   597     // PUSH without POP:
       
   598     CheckParseErrors();
       
   599 
       
   600     iGlobalStack.Reset();
       
   601     iCollectionStack.Reset();
       
   602 
       
   603     TRACE_INFO((_L("CParser::ParseL() error code is %d"), iErrorCode));
       
   604     // Finished, transfer ownership to caller:
       
   605     CReportRoot* reportRoot = iReportRoot;
       
   606     iReportRoot = 0;
       
   607     return reportRoot;
       
   608     }
       
   609 
       
   610 // ---------------------------------------------------------------------------
       
   611 // CParser::FieldCount()
       
   612 // ---------------------------------------------------------------------------
       
   613 //
       
   614 TInt CParser::FieldCount()
       
   615     {
       
   616     return iFieldCount;
       
   617     }
       
   618 
       
   619 // ---------------------------------------------------------------------------
       
   620 // CParser::MainItemL()
       
   621 // ---------------------------------------------------------------------------
       
   622 //
       
   623 TInt CParser::MainItemL(const TItem& aItem)
       
   624     {
       
   625     TInt retVal = 0;
       
   626 
       
   627     switch (aItem.Tag())
       
   628         {
       
   629         case EMainInput:
       
   630             retVal = HandleMainInputTagL( aItem );
       
   631             break;
       
   632 
       
   633         case EMainOutput:
       
   634             retVal = HandleMainOutputTagL( aItem );
       
   635             break;
       
   636 
       
   637         case EMainFeature:
       
   638             retVal = HandleMainFeatureL( aItem );
       
   639             break;
       
   640 
       
   641         case EMainCollection:
       
   642             retVal = HandleMainCollectionL( aItem );
       
   643             break;
       
   644 
       
   645         case EMainEndCollection:
       
   646             retVal = HandleMainEndCollection( aItem );
       
   647             break;
       
   648         default:
       
   649             TRACE_ERROR(_L("Error: unknown main item\n"));
       
   650             retVal = EUnknownItem;
       
   651             break;
       
   652         }
       
   653 
       
   654     // All main items cause local state to be cleared:
       
   655     ClearLocalState();
       
   656 
       
   657     // For checking if global items declared more than once between
       
   658     // main items:
       
   659     iGlobalItemsDefined = 0;
       
   660 
       
   661     return retVal;
       
   662     }
       
   663 // ---------------------------------------------------------------------------
       
   664 // ClearLocalState()
       
   665 // ---------------------------------------------------------------------------
       
   666 //
       
   667 void CParser::ClearLocalState()
       
   668     {
       
   669     iLocal->ClearUsageList();
       
   670     iLocal->SetUsageRange(0, 0);
       
   671     iLocal->SetStringIndex(0);
       
   672     iLocal->SetStringRange(0, 0);
       
   673     iLocal->SetDesignatorIndex(0);
       
   674     iLocal->SetDesignatorRange(0, 0);
       
   675 
       
   676     iItemsDefined &= ~(KLocalItemMask | EDelimiter);
       
   677     iLocalMultipleUse = EFalse;
       
   678     }
       
   679 
       
   680 // ---------------------------------------------------------------------------
       
   681 // GlobalItemL()
       
   682 // ---------------------------------------------------------------------------
       
   683 //
       
   684 TInt CParser::GlobalItemL(const TItem& aItem)
       
   685     {
       
   686     TInt retVal = 0;
       
   687     switch (aItem.Tag())
       
   688         {
       
   689         case EGlobalReportId:
       
   690             retVal = HandleGlobalReportId( aItem );
       
   691             break;
       
   692         case EGlobalUsagePage:
       
   693             retVal = HandleGlobalUsagePage( aItem );
       
   694             break;
       
   695         case EGlobalLogicalMinimum:
       
   696             retVal = HandleGlobalLogicalMinimum( aItem );
       
   697             break;
       
   698         case EGlobalLogicalMaximum:
       
   699             retVal = HandleGlobalLogicalMaximum( aItem );
       
   700             break;
       
   701         case EGlobalPhysicalMinimum:
       
   702             retVal = HandleGlobalPhysicalMinimum( aItem );
       
   703             break;
       
   704         case EGlobalPhysicalMaximum:
       
   705             retVal = HandleGlobalPhysicalMaximum( aItem );
       
   706             break;
       
   707         case EGlobalUnit:
       
   708             retVal = HandleGlobalUnit( aItem );
       
   709             break;
       
   710         case EGlobalUnitExponent:
       
   711             retVal = HandleGlobalUnitExponent( aItem );
       
   712             break;
       
   713         case EGlobalReportSize:
       
   714             retVal = HandleGlobalReportSize( aItem );
       
   715             break;
       
   716         case EGlobalReportCount:
       
   717             retVal = HandleGlobalReportCount(aItem );
       
   718             break;
       
   719         case EGlobalPush:
       
   720             retVal = HandleGlobalPushL( aItem );
       
   721             break;
       
   722         case EGlobalPop:
       
   723             retVal = HandleGlobalPop( aItem );
       
   724             break;
       
   725         default:
       
   726             TRACE_ERROR(_L("Error: unknown global item\n"));
       
   727             retVal = EUnknownItem;
       
   728             break;
       
   729         }
       
   730 
       
   731     return retVal;
       
   732     }
       
   733 
       
   734 // ---------------------------------------------------------------------------
       
   735 // LocalItemL()
       
   736 // ---------------------------------------------------------------------------
       
   737 //
       
   738 TInt CParser::LocalItemL(const TItem& aItem)
       
   739     {
       
   740     TInt retVal = 0;
       
   741     switch (aItem.Tag())
       
   742         {
       
   743         case ELocalUsage:
       
   744             retVal = HandleLocalUsageL( aItem );
       
   745             break;
       
   746         case ELocalUsageMinimum:
       
   747             retVal = HandleLocalUsageMinimum( aItem );
       
   748             break;
       
   749         case ELocalUsageMaximum:
       
   750             retVal = HandleLocalUsageMaximum( aItem );
       
   751             break;
       
   752         case ELocalDesignatorIndex:
       
   753             retVal = HandleLocalDesignatorIndex( aItem );
       
   754             break;
       
   755         case ELocalDesignatorMinimum:
       
   756             retVal = HandleLocalDesignatorMinimum( aItem );
       
   757             break;
       
   758         case ELocalDesignatorMaximum:
       
   759             retVal = HandleLocalDesignatorMaximum( aItem );
       
   760             break;
       
   761         case ELocalStringIndex:
       
   762             retVal = HandleLocalStringIndex( aItem );
       
   763             break;
       
   764         case ELocalStringMinimum:
       
   765             retVal = HandleLocalStringMinimum( aItem );
       
   766             break;
       
   767         case ELocalStringMaximum:
       
   768             retVal = HandleLocalStringMaximum( aItem );
       
   769             break;
       
   770         // "HID parsers must handle Delimiters however, the support
       
   771         // for the alternative usages that they define is optional.
       
   772         // Usages other than the first (most preferred) usage defined
       
   773         // may not be made accessible by system software.", [1],
       
   774         // Section 6.2.2.8.
       
   775         //
       
   776         // This parser only supports the first usage in a delimiter list.
       
   777         case ELocalDelimiter:
       
   778             retVal = HandleLocalDelimiter( aItem );
       
   779             break;
       
   780         default:
       
   781             TRACE_ERROR(_L("Error: unknown local item\n"));
       
   782             retVal = EUnknownItem;
       
   783             break;
       
   784         }
       
   785     return retVal;
       
   786     }
       
   787 
       
   788 // ---------------------------------------------------------------------------
       
   789 // IsReservedUsagePage()
       
   790 // ---------------------------------------------------------------------------
       
   791 //
       
   792 TBool CParser::IsReservedUsagePage(TInt aId)
       
   793     {   
       
   794     return (aId == KReservedUsage) ||                     
       
   795         ((aId >= KReservedUsageRange1Min ) && (aId <= KReservedUsageRange1Max)) ||     
       
   796         ((aId >= KReservedUsageRange2Min ) && (aId <= KReservedUsageRange2Max)) ||     
       
   797         ((aId >= KReservedUsageRange3Min) && (aId <= KReservedUsageRange3Max)) ||     
       
   798         ((aId >= KReservedUsageRange4Min ) && (aId <= KReservedUsageRange4Max)) ||     
       
   799         ((aId >= KReservedUsageRange5Min) && (aId <= KReservedUsageRange5Max));     
       
   800     }
       
   801 
       
   802 // ---------------------------------------------------------------------------
       
   803 // Populate()
       
   804 // ---------------------------------------------------------------------------
       
   805 //
       
   806 void TParserGlobalState::Populate(CField *aField) const
       
   807     {
       
   808     aField->SetUsagePage(iUsagePage);
       
   809     aField->SetReportId(iReportId);
       
   810     aField->SetLogicalRange(iLogicalMin, iLogicalMax);
       
   811     aField->SetSize(iSize);
       
   812     aField->SetCount(iCount);
       
   813     aField->SetUnit(iUnit);
       
   814     aField->SetUnitExponent(iUnitExponent);
       
   815 
       
   816     // If the physical min and max are both zero, then the HID class
       
   817     // document specifies that they should be assumed to be equal to
       
   818     // the corresponding logical values ([1], Section 6.2.2.7):
       
   819     //
       
   820     if ((iPhysicalMin == 0) && (iPhysicalMax == 0))
       
   821         {
       
   822         aField->SetPhysicalRange(iLogicalMin, iLogicalMax);
       
   823         }
       
   824     else
       
   825         {
       
   826         aField->SetPhysicalRange(iPhysicalMin, iPhysicalMax);
       
   827         }
       
   828     }
       
   829 
       
   830 
       
   831 // ---------------------------------------------------------------------------
       
   832 // TParserGlobalState()
       
   833 // ---------------------------------------------------------------------------
       
   834 //
       
   835 TParserGlobalState::TParserGlobalState()
       
   836     : iUsagePage(0), iLogicalMin(0), iLogicalMax(0),
       
   837       iPhysicalMin(0), iPhysicalMax(0), iUnit(0),
       
   838       iUnitExponent(0), iReportId(0), iSize(0), iCount(0)
       
   839     {
       
   840     // Nothing else to do
       
   841     }
       
   842 
       
   843 // ---------------------------------------------------------------------------
       
   844 // HandleMainInputTagL
       
   845 // ---------------------------------------------------------------------------
       
   846 //
       
   847 TInt CParser::HandleMainInputTagL(const TItem& aItem)
       
   848     {
       
   849     // Section 6.2.2.4 of the HID class specification, [1],
       
   850     // states that an Input item may have a data size of zero
       
   851     // bytes:
       
   852     //
       
   853     //   "In this case the value of each data bit for the item
       
   854     //   can be assumed to be zero. This is functionally
       
   855     //   identical to using a item tag that specifies a 4-byte
       
   856     //   data item followed by four zero bytes."
       
   857     //
       
   858     // For a data size of zero, TItem::Data() will return zero
       
   859     // and so we will get the required behaviour.
       
   860     TRACE_INFO((_L("Input %d\n"), aItem.Data()));
       
   861     TInt retVal=0;
       
   862 
       
   863     iItemsDefined |= EInputReport;
       
   864     
       
   865     if ( aItem.Data() & KInputReservedBitsMask )
       
   866         {
       
   867         IssueWarning( EInputReservedBitsNonZero );
       
   868         }
       
   869     if ( iLocalMultipleUse )
       
   870         {
       
   871         IssueWarning( EInputLocalMultipleUse );
       
   872         }
       
   873     if ( iWithinDelimiter )
       
   874         {
       
   875         retVal = EInputItemWithinDelimiter;
       
   876         }
       
   877     else
       
   878         {
       
   879         retVal = CreateFieldL( CField::EInput, aItem.Data() );
       
   880         }
       
   881     return retVal;
       
   882     }
       
   883 
       
   884 // ---------------------------------------------------------------------------
       
   885 // HandleMainOutputTagL
       
   886 // ---------------------------------------------------------------------------
       
   887 //
       
   888 TInt CParser::HandleMainOutputTagL(const TItem& aItem)
       
   889     {
       
   890     TRACE_INFO((_L("Output %d\n"), aItem.Data()));
       
   891     TInt retVal=0;
       
   892     iItemsDefined |= EOutputReport;
       
   893     
       
   894     if ( aItem.Data() & KOutputReservedBitsMask )
       
   895         {
       
   896         IssueWarning( EOutputReservedBitsNonZero );
       
   897         }
       
   898 
       
   899     if ( iLocalMultipleUse )
       
   900         {
       
   901         IssueWarning( EOutputLocalMultipleUse );
       
   902         }
       
   903 
       
   904     if ( iWithinDelimiter )
       
   905         {
       
   906         retVal = EOutputItemWithinDelimiter;
       
   907         }
       
   908     else
       
   909        {
       
   910        retVal = CreateFieldL( CField::EOutput, aItem.Data() );
       
   911        }
       
   912     return retVal;
       
   913     }
       
   914 
       
   915 // ---------------------------------------------------------------------------
       
   916 // HandleMainFeatureL
       
   917 // ---------------------------------------------------------------------------
       
   918 //
       
   919 TInt CParser::HandleMainFeatureL( const TItem& aItem )
       
   920     {
       
   921     TRACE_INFO((_L("Feature %d\n"), aItem.Data()));
       
   922     TInt retVal=0;
       
   923     iItemsDefined |= EFeatureReport;
       
   924         
       
   925     if ( aItem.Data() & KFeatureReservedBitsMask )
       
   926         {
       
   927         IssueWarning(EFeatureReservedBitsNonZero );
       
   928         }
       
   929 
       
   930     if ( iLocalMultipleUse )
       
   931         {
       
   932         IssueWarning( EFeatureLocalMultipleUse );
       
   933         }
       
   934 
       
   935     if ( iWithinDelimiter )
       
   936         {
       
   937         retVal = EFeatureItemWithinDelimiter;
       
   938         }
       
   939      else
       
   940         {
       
   941         retVal = CreateFieldL( CField::EFeature, aItem.Data() );
       
   942         }
       
   943 
       
   944     return retVal;
       
   945     }
       
   946 
       
   947 // ---------------------------------------------------------------------------
       
   948 // HandleMainCollectionL
       
   949 // ---------------------------------------------------------------------------
       
   950 //
       
   951 TInt CParser::HandleMainCollectionL( const TItem& aItem )
       
   952     {
       
   953     TRACE_INFO((_L("Start collection %d\n"), aItem.Data()));
       
   954     TInt retVal = 0;
       
   955 
       
   956     if ( iWithinDelimiter )
       
   957         {
       
   958         retVal = EBeginCollectionWithinDelimiter;
       
   959         }
       
   960     else
       
   961         {
       
   962         // Application collections can only be declared at
       
   963         // top-level:
       
   964         if ((aItem.Data() == CCollection::EApplication) &&
       
   965            (iCollectionStack.Count() != 1))
       
   966             {
       
   967             retVal = EApplicationCollectionLevel;
       
   968             }
       
   969         else
       
   970             {
       
   971             retVal = CreateCollectionL(aItem.Data());
       
   972             }
       
   973         }
       
   974     return retVal;
       
   975     }
       
   976 
       
   977 // ---------------------------------------------------------------------------
       
   978 // HandleMainEndCollection
       
   979 // ---------------------------------------------------------------------------
       
   980 //
       
   981 TInt CParser::HandleMainEndCollection( const TItem& aItem )
       
   982     {
       
   983     TRACE_INFO((_L("Start collection %d\n"), aItem.Data()));
       
   984     TInt retVal = 0;
       
   985 
       
   986     if (aItem.DataSize() != 0)
       
   987         {
       
   988         IssueWarning(EEndCollectionHasData);
       
   989         }
       
   990 
       
   991     if (iItemsDefined & KLocalItemMask)
       
   992         {
       
   993         IssueWarning(EEndCollectionLocalUnused);
       
   994         }
       
   995 
       
   996     if (iCollectionStack.Count() > 1)
       
   997         {
       
   998         PopCollection();
       
   999         }
       
  1000     else
       
  1001         {
       
  1002         retVal = ENoMatchingBeginCollection;
       
  1003         }
       
  1004 
       
  1005     if (iWithinDelimiter)
       
  1006         {
       
  1007         retVal = EEndCollectionWithinDelimiter;
       
  1008         }
       
  1009 
       
  1010     return  retVal;
       
  1011     }
       
  1012 
       
  1013 // ---------------------------------------------------------------------------
       
  1014 // HandleGlobalReportId
       
  1015 // ---------------------------------------------------------------------------
       
  1016 //
       
  1017 TInt CParser::HandleGlobalReportId( const TItem& aItem )
       
  1018     {
       
  1019     TRACE_INFO((_L("Global report ID %d\n"), aItem.Data()));
       
  1020     TInt retVal = 0;
       
  1021     TUint reportId = aItem.Data();
       
  1022 
       
  1023     if (reportId == 0)
       
  1024         {
       
  1025         retVal = EZeroReportId;
       
  1026         }
       
  1027     if (reportId > KMaxReportIDMax)
       
  1028         {
       
  1029         retVal = EReportIdTooBig;
       
  1030         }
       
  1031 
       
  1032     // If there are to be any report IDs specified at all,
       
  1033     // then a report ID must be defined before the first
       
  1034     // input, output or feature report:
       
  1035     //    
       
  1036     if ((iGlobal.iReportId == 0) && (iItemsDefined & KReportItemMask))
       
  1037         {
       
  1038         retVal = ELateReportId;
       
  1039         }
       
  1040 
       
  1041     // Report ID defined outside a top level collection (Microsoft
       
  1042     // restriction)
       
  1043     //
       
  1044     if (iCollectionStack.Count() == 1)
       
  1045         {
       
  1046         retVal = EReportIdOutsideTopLevel;
       
  1047         }
       
  1048 
       
  1049     // Same item shouldn't have been declared since last main item:
       
  1050     //
       
  1051     if (iGlobalItemsDefined & EReportId)
       
  1052         {
       
  1053         // This is an error according to [2], but as it isn't
       
  1054         // a critical problem, and as some real-world devices
       
  1055         // fail this check, we issue a warning instead:
       
  1056         IssueWarning(ERedundantGlobalItem);
       
  1057         }
       
  1058     iGlobalItemsDefined |= EReportId;
       
  1059 
       
  1060     iItemsDefined |= EReportId;
       
  1061     iGlobal.iReportId = reportId;
       
  1062 
       
  1063     return  retVal;
       
  1064     }
       
  1065 
       
  1066 // ---------------------------------------------------------------------------
       
  1067 // HandleGlobalUsagePage
       
  1068 // ---------------------------------------------------------------------------
       
  1069 //
       
  1070 TInt CParser::HandleGlobalUsagePage( const TItem& aItem )
       
  1071     {
       
  1072     TRACE_INFO((_L("Global usage page %d\n"), aItem.Data()));
       
  1073     TInt retVal = 0;
       
  1074 
       
  1075     iGlobal.iUsagePage = aItem.Data();
       
  1076 
       
  1077     if (aItem.Data() == 0)
       
  1078         {
       
  1079         retVal = EZeroUsagePage;
       
  1080         }
       
  1081     
       
  1082     if (aItem.Data() > KMaxUsagePage)
       
  1083         {
       
  1084         retVal = EUsagePageOutOfRange;
       
  1085         }
       
  1086 
       
  1087     if (IsReservedUsagePage(aItem.Data()))
       
  1088         {
       
  1089         IssueWarning(EReservedUsagePage);
       
  1090         }
       
  1091 
       
  1092     iItemsDefined |= EUsagePage;
       
  1093 
       
  1094     if (iGlobalItemsDefined & EUsagePage)
       
  1095         {
       
  1096         retVal = ERedundantGlobalItem;
       
  1097         }
       
  1098     iGlobalItemsDefined |= EUsagePage;
       
  1099 
       
  1100     return  retVal;
       
  1101     }
       
  1102 
       
  1103 // ---------------------------------------------------------------------------
       
  1104 // HandleGlobalLogicalMinimum
       
  1105 // ---------------------------------------------------------------------------
       
  1106 //
       
  1107 TInt CParser::HandleGlobalLogicalMinimum( const TItem& aItem )
       
  1108     {
       
  1109     TRACE_INFO((_L("Global logical min %d\n"), aItem.SignedData()));
       
  1110     TInt retVal = 0;
       
  1111     iGlobal.iLogicalMin = aItem.SignedData();
       
  1112     iItemsDefined |= ELogicalMin;
       
  1113 
       
  1114     if (iGlobalItemsDefined & ELogicalMin)
       
  1115         {
       
  1116         retVal = ERedundantGlobalItem;
       
  1117         }
       
  1118     iGlobalItemsDefined |= ELogicalMin;
       
  1119 
       
  1120     // "Until Physical Minimum and Physical Maximum are
       
  1121     // declared in a report descriptor they are assumed by the
       
  1122     // HID parser to be equal to Logical Minimum and Logical
       
  1123     // Maximum, respectively.", [1], Section 6.2.2.7.
       
  1124     //
       
  1125     if (!(iItemsDefined & EPhysicalMin))
       
  1126         {
       
  1127         iGlobal.iPhysicalMin = aItem.SignedData();
       
  1128         }
       
  1129     return retVal;
       
  1130     }
       
  1131 
       
  1132 // ---------------------------------------------------------------------------
       
  1133 // HandleGlobalLogicalMaximum
       
  1134 // ---------------------------------------------------------------------------
       
  1135 //
       
  1136 TInt CParser::HandleGlobalLogicalMaximum( const TItem& aItem )
       
  1137     {
       
  1138     TRACE_INFO((_L("Global logical max %d\n"), aItem.SignedData()));
       
  1139     TInt retVal = 0;
       
  1140 
       
  1141     iGlobal.iLogicalMax = aItem.SignedData();
       
  1142     if ( !(iItemsDefined & EPhysicalMax) )
       
  1143         {
       
  1144         iGlobal.iPhysicalMax = aItem.SignedData();
       
  1145         }
       
  1146     iItemsDefined |= ELogicalMax;
       
  1147 
       
  1148     if (iGlobalItemsDefined & ELogicalMax)
       
  1149         {
       
  1150         retVal = ERedundantGlobalItem;
       
  1151         }
       
  1152     iGlobalItemsDefined |= ELogicalMax;
       
  1153     return retVal;
       
  1154     }
       
  1155 
       
  1156 // ---------------------------------------------------------------------------
       
  1157 // HandleGlobalPhysicalMinimum
       
  1158 // ---------------------------------------------------------------------------
       
  1159 //
       
  1160 TInt CParser::HandleGlobalPhysicalMinimum( const TItem& aItem )
       
  1161     {
       
  1162     TRACE_INFO((_L("Global physical min %d\n"), aItem.SignedData()));
       
  1163     TInt retVal = 0;
       
  1164     iGlobal.iPhysicalMin = aItem.SignedData();
       
  1165     iItemsDefined |= EPhysicalMin;
       
  1166 
       
  1167     if (iGlobalItemsDefined & EPhysicalMin)
       
  1168         {
       
  1169         retVal = ERedundantGlobalItem;
       
  1170         }
       
  1171     iGlobalItemsDefined |= EPhysicalMin;
       
  1172     return retVal;
       
  1173     }
       
  1174 
       
  1175 // ---------------------------------------------------------------------------
       
  1176 // HandleGlobalPhysicalMaximum
       
  1177 // ---------------------------------------------------------------------------
       
  1178 //
       
  1179 TInt CParser::HandleGlobalPhysicalMaximum( const TItem& aItem )
       
  1180     {
       
  1181     TRACE_INFO((_L("Global physical max %d\n"), aItem.SignedData()));
       
  1182 
       
  1183     TInt retVal = 0;
       
  1184     iGlobal.iPhysicalMax = aItem.SignedData();
       
  1185     iItemsDefined |= EPhysicalMax;
       
  1186 
       
  1187     if ( iGlobalItemsDefined & EPhysicalMax )
       
  1188         {
       
  1189         retVal = ERedundantGlobalItem;
       
  1190         }
       
  1191     iGlobalItemsDefined |= EPhysicalMax;
       
  1192     return retVal;
       
  1193     }
       
  1194 
       
  1195 // ---------------------------------------------------------------------------
       
  1196 // HandleGlobalUnit
       
  1197 // ---------------------------------------------------------------------------
       
  1198 //
       
  1199 TInt CParser::HandleGlobalUnit( const TItem& aItem )
       
  1200     {
       
  1201     TRACE_INFO((_L("Global unit %d\n"), aItem.Data()));
       
  1202     TInt retVal = 0;
       
  1203     iGlobal.iUnit = aItem.Data();
       
  1204     iItemsDefined |= EUnit;
       
  1205 
       
  1206     if (iGlobalItemsDefined & EUnit)
       
  1207         {
       
  1208         retVal = ERedundantGlobalItem;
       
  1209         }
       
  1210     iGlobalItemsDefined |= EUnit;
       
  1211 
       
  1212     TInt unitSystem = aItem.Data() & KUnitData;
       
  1213     if (((unitSystem >= KUnitSystemMin ) && (unitSystem != KUnitSystem15)) ||
       
  1214         (aItem.Data() & KUnitReservedBitsMask ))
       
  1215         {               
       
  1216         IssueWarning(EUnitReservedBitsNonZero);
       
  1217         }
       
  1218     return retVal;
       
  1219     }
       
  1220 
       
  1221 // ---------------------------------------------------------------------------
       
  1222 // HandleGlobalUnitExponent
       
  1223 // ---------------------------------------------------------------------------
       
  1224 //
       
  1225 TInt CParser::HandleGlobalUnitExponent( const TItem& aItem )
       
  1226     {
       
  1227     TRACE_INFO((_L("Global unit exponent %d\n"), aItem.Data()));
       
  1228     TInt retVal = 0;
       
  1229     iGlobal.iUnitExponent = aItem.Data();
       
  1230     iItemsDefined |= EUnitExponent;
       
  1231 
       
  1232     if (iGlobalItemsDefined & EUnitExponent)
       
  1233         {
       
  1234         retVal = ERedundantGlobalItem;
       
  1235         }
       
  1236     iGlobalItemsDefined |= EUnitExponent;
       
  1237     const TUint32 KReservedBits = ~0x0fUL;
       
  1238     if (aItem.Data() & KReservedBits)
       
  1239         {
       
  1240         IssueWarning( EExponentReservedBitsNonZero );
       
  1241         }
       
  1242     return retVal;
       
  1243     }
       
  1244 
       
  1245 // ---------------------------------------------------------------------------
       
  1246 // HandleGlobalReportSize
       
  1247 // ---------------------------------------------------------------------------
       
  1248 //
       
  1249 TInt CParser::HandleGlobalReportSize( const TItem& aItem )
       
  1250     {
       
  1251     TRACE_INFO((_L("Global report size %d\n"), aItem.Data()));
       
  1252     TInt retVal = 0;
       
  1253     iGlobal.iSize = aItem.Data();
       
  1254     iItemsDefined |= EReportSize;
       
  1255 
       
  1256     if (iGlobalItemsDefined & EReportSize)
       
  1257         {
       
  1258         retVal = ERedundantGlobalItem;
       
  1259         }
       
  1260     iGlobalItemsDefined |= EReportSize;
       
  1261     return retVal;
       
  1262     }
       
  1263 
       
  1264 // ---------------------------------------------------------------------------
       
  1265 // HandleGlobalReportCount
       
  1266 // ---------------------------------------------------------------------------
       
  1267 //
       
  1268 TInt CParser::HandleGlobalReportCount( const TItem& aItem )
       
  1269     {
       
  1270     TRACE_INFO((_L("Global report count %d\n"), aItem.Data()));
       
  1271     TInt retVal = 0;
       
  1272     iGlobal.iCount = aItem.Data();
       
  1273     if (aItem.Data() == 0)
       
  1274         {
       
  1275         retVal = EZeroReportCount;
       
  1276         }
       
  1277     iItemsDefined |= EReportCount;
       
  1278 
       
  1279     if (iGlobalItemsDefined & EReportCount)
       
  1280         {
       
  1281         retVal = ERedundantGlobalItem;
       
  1282         }
       
  1283     iGlobalItemsDefined |= EReportCount;
       
  1284     return retVal;
       
  1285     }
       
  1286 
       
  1287 // ---------------------------------------------------------------------------
       
  1288 // HandleGlobalPushL
       
  1289 // ---------------------------------------------------------------------------
       
  1290 //
       
  1291 TInt CParser::HandleGlobalPushL( const TItem& aItem )
       
  1292     {
       
  1293     TRACE_INFO(_L("Global push\n"));
       
  1294     TInt retVal = 0;
       
  1295     if (aItem.DataSize() != 0)
       
  1296         {
       
  1297         retVal = EPushHasData;
       
  1298         }
       
  1299     User::LeaveIfError(iGlobalStack.Append(iGlobal));
       
  1300     return retVal;
       
  1301     }
       
  1302 
       
  1303 // ---------------------------------------------------------------------------
       
  1304 // HandleGlobalPop
       
  1305 // ---------------------------------------------------------------------------
       
  1306 //
       
  1307 TInt CParser::HandleGlobalPop( const TItem& aItem )
       
  1308     {
       
  1309     TRACE_INFO(_L("Global pop\n"));
       
  1310     TInt retVal = 0;
       
  1311     if (aItem.DataSize() != 0)
       
  1312         {
       
  1313         retVal = EPopHasData;
       
  1314         }
       
  1315 
       
  1316     if (iGlobalStack.Count() > 0)
       
  1317         {
       
  1318         iGlobal = iGlobalStack[iGlobalStack.Count()-1];
       
  1319         iGlobalStack.Remove(iGlobalStack.Count()-1);
       
  1320         }
       
  1321     else
       
  1322         {
       
  1323         retVal = EPopWithoutPush;
       
  1324         }
       
  1325     return retVal;
       
  1326     }
       
  1327 
       
  1328 // ---------------------------------------------------------------------------
       
  1329 // HandleLocalUsageL
       
  1330 // ---------------------------------------------------------------------------
       
  1331 //
       
  1332 TInt CParser::HandleLocalUsageL( const TItem& aItem )
       
  1333     {
       
  1334     TRACE_INFO((_L("Local usage %d\n"), aItem.Data()));
       
  1335     TInt retVal = 0;
       
  1336     
       
  1337     if (aItem.DataSize() == KExtendedDataSize )
       
  1338         {
       
  1339         // Extended (32-bit) usage:
       
  1340         TInt usagePage = (aItem.Data() >> KExtendedDataShift);
       
  1341         if (IsReservedUsagePage(usagePage))
       
  1342             {
       
  1343             IssueWarning(EReservedUsagePage);
       
  1344             }
       
  1345         }
       
  1346 
       
  1347     if ((aItem.Data() & 0xffff) == 0)
       
  1348         {
       
  1349         IssueWarning(EZeroUsage);
       
  1350         }
       
  1351 
       
  1352     if (!iWithinDelimiter || (iAliasCount++ == 0))
       
  1353         {
       
  1354         iLocal->AddUsageL(aItem.Data());
       
  1355         iItemsDefined |= EUsageId;
       
  1356         }
       
  1357     return retVal;
       
  1358     }
       
  1359 
       
  1360 // ---------------------------------------------------------------------------
       
  1361 // HandleLocalUsageMinimum
       
  1362 // ---------------------------------------------------------------------------
       
  1363 //
       
  1364 TInt CParser::HandleLocalUsageMinimum( const TItem& aItem )
       
  1365     {
       
  1366     TRACE_INFO((_L("Local usage min %d\n"), aItem.Data()));
       
  1367     TInt retVal = 0;
       
  1368     if (!iWithinDelimiter || (iAliasCountMin++ == 0))
       
  1369         {
       
  1370         TInt usagePage = iGlobal.iUsagePage;
       
  1371 
       
  1372         if (aItem.DataSize() == KExtendedDataSize )
       
  1373             {
       
  1374             // Extended usage specified.
       
  1375             usagePage = aItem.Data() >> KExtendedDataShift;
       
  1376             }
       
  1377 
       
  1378         if (iItemsDefined & EUsageMax)
       
  1379             {
       
  1380             TInt maxPage =
       
  1381             static_cast<TUint32>(iLocal->UsageMax()) >> KExtendedDataShift;
       
  1382             if (maxPage == 0)
       
  1383                 {
       
  1384                 maxPage = iGlobal.iUsagePage;
       
  1385                 }
       
  1386             if (usagePage != maxPage)
       
  1387                 {
       
  1388                 retVal = EUsagePageMismatchMin;
       
  1389                 }
       
  1390             }
       
  1391         iLocal->SetUsageMin(aItem.Data());
       
  1392         }
       
  1393     if (iItemsDefined & EUsageMin)
       
  1394         {
       
  1395         iLocalMultipleUse = ETrue;
       
  1396         }
       
  1397     iItemsDefined |= EUsageMin;
       
  1398     return retVal;
       
  1399     }
       
  1400 
       
  1401 // ---------------------------------------------------------------------------
       
  1402 // HandleLocalUsageMaximum
       
  1403 // ---------------------------------------------------------------------------
       
  1404 //
       
  1405 TInt CParser::HandleLocalUsageMaximum( const TItem& aItem )
       
  1406     {
       
  1407     TRACE_INFO((_L("Local usage max %d\n"), aItem.Data()));
       
  1408     
       
  1409     TInt retVal = 0;
       
  1410     
       
  1411     if (!iWithinDelimiter || (iAliasCountMax++ == 0))
       
  1412         {
       
  1413         TInt usagePage = iGlobal.iUsagePage;
       
  1414 
       
  1415         if (aItem.DataSize() == KExtendedDataSize )
       
  1416             {
       
  1417             // Extended usage specified.
       
  1418             usagePage = aItem.Data() >> KExtendedDataShift;
       
  1419             }
       
  1420         if (iItemsDefined & EUsageMin)
       
  1421             {
       
  1422             TInt minPage =
       
  1423                 static_cast<TUint32>(iLocal->UsageMin()) >> KExtendedDataShift;
       
  1424             if (minPage == 0)
       
  1425                 {
       
  1426                 minPage = iGlobal.iUsagePage;
       
  1427                 }
       
  1428             if (usagePage != minPage)
       
  1429                 {
       
  1430                 retVal = EUsagePageMismatchMax;
       
  1431                 }
       
  1432             }
       
  1433         iLocal->SetUsageMax(aItem.Data());
       
  1434         }
       
  1435     if (iItemsDefined & EUsageMax)
       
  1436         {
       
  1437         iLocalMultipleUse = ETrue;
       
  1438         }
       
  1439     iItemsDefined |= EUsageMax;
       
  1440     return retVal;
       
  1441     }
       
  1442 
       
  1443 // ---------------------------------------------------------------------------
       
  1444 // HandleLocalDesignatorIndex
       
  1445 // ---------------------------------------------------------------------------
       
  1446 //
       
  1447 TInt CParser::HandleLocalDesignatorIndex( const TItem& aItem )
       
  1448     {
       
  1449     TRACE_INFO((_L("Local designator index %d\n"),
       
  1450             aItem.Data()));
       
  1451     TInt retVal = 0;
       
  1452     iLocal->SetDesignatorIndex(aItem.Data());
       
  1453     if (iWithinDelimiter)
       
  1454         {
       
  1455         retVal = EInvalidItemWithinDelimiter;
       
  1456         }
       
  1457     if (iItemsDefined & EDesignatorIndex)
       
  1458         {
       
  1459         iLocalMultipleUse = ETrue;
       
  1460         }
       
  1461     iItemsDefined |= EDesignatorIndex;
       
  1462     return retVal;
       
  1463     }
       
  1464 
       
  1465 // ---------------------------------------------------------------------------
       
  1466 // HandleLocalDesignatorMinimum
       
  1467 // ---------------------------------------------------------------------------
       
  1468 //
       
  1469 TInt CParser::HandleLocalDesignatorMinimum( const TItem& aItem )
       
  1470     {
       
  1471     TRACE_INFO((_L("Local designator min %d\n"), aItem.Data()));
       
  1472     TInt retVal = 0;
       
  1473     iLocal->SetDesignatorMin(aItem.Data());
       
  1474     if ( iWithinDelimiter )
       
  1475         {
       
  1476         retVal = EInvalidItemWithinDelimiter;
       
  1477         }
       
  1478     if (iItemsDefined & EDesignatorMin)
       
  1479         {
       
  1480         iLocalMultipleUse = ETrue;
       
  1481         }
       
  1482     iItemsDefined |= EDesignatorMin;
       
  1483     return retVal;
       
  1484     }
       
  1485 
       
  1486 // ---------------------------------------------------------------------------
       
  1487 // HandleLocalDesignatorMaximum
       
  1488 // ---------------------------------------------------------------------------
       
  1489 //
       
  1490 TInt CParser::HandleLocalDesignatorMaximum( const TItem& aItem )
       
  1491     {
       
  1492     TRACE_INFO((_L("Local designator max %d\n"), aItem.Data()));
       
  1493     TInt retVal = 0;
       
  1494     iLocal->SetDesignatorMax(aItem.Data());
       
  1495     if ( iWithinDelimiter )
       
  1496         {
       
  1497         retVal = EInvalidItemWithinDelimiter;
       
  1498         }
       
  1499     if ( iItemsDefined & EDesignatorMax )
       
  1500         {
       
  1501         iLocalMultipleUse = ETrue;
       
  1502         }
       
  1503     iItemsDefined |= EDesignatorMax;
       
  1504     return retVal;
       
  1505     }
       
  1506 
       
  1507 // ---------------------------------------------------------------------------
       
  1508 // HandleLocalStringIndex
       
  1509 // ---------------------------------------------------------------------------
       
  1510 //
       
  1511 TInt CParser::HandleLocalStringIndex( const TItem& aItem )
       
  1512     {
       
  1513     TRACE_INFO((_L("Local string index %d\n"), aItem.Data()));
       
  1514     TInt retVal = 0;
       
  1515     iLocal->SetStringIndex(aItem.Data());
       
  1516     if ( iItemsDefined & EStringIndex )
       
  1517         {
       
  1518         iLocalMultipleUse = ETrue;
       
  1519         }
       
  1520     iItemsDefined |= EStringIndex;
       
  1521     if ( iWithinDelimiter )
       
  1522         {
       
  1523         retVal = EInvalidItemWithinDelimiter;
       
  1524         }
       
  1525     return retVal;
       
  1526     }
       
  1527 
       
  1528 // ---------------------------------------------------------------------------
       
  1529 // HandleLocalStringMinimum
       
  1530 // ---------------------------------------------------------------------------
       
  1531 //
       
  1532 TInt CParser::HandleLocalStringMinimum( const TItem& aItem )
       
  1533     {
       
  1534     TRACE_INFO((_L("Local string min %d\n"),
       
  1535             aItem.Data()));
       
  1536     TInt retVal = 0;
       
  1537     iLocal->SetStringMin(aItem.Data());
       
  1538     if ( iItemsDefined & EStringMin)
       
  1539         {
       
  1540         iLocalMultipleUse = ETrue;
       
  1541         }
       
  1542     iItemsDefined |= EStringMin;
       
  1543     if (iWithinDelimiter)
       
  1544         {
       
  1545         retVal = EInvalidItemWithinDelimiter;
       
  1546         }
       
  1547     return retVal;
       
  1548     }
       
  1549 
       
  1550 // ---------------------------------------------------------------------------
       
  1551 // HandleLocalStringMaximum
       
  1552 // ---------------------------------------------------------------------------
       
  1553 //
       
  1554 TInt CParser::HandleLocalStringMaximum( const TItem& aItem )
       
  1555     {
       
  1556     TRACE_INFO((_L("Local string max %d\n"),
       
  1557             aItem.Data()));
       
  1558     TInt retVal = 0;
       
  1559     iLocal->SetStringMax(aItem.Data());
       
  1560     if ( iItemsDefined & EStringMax )
       
  1561         {
       
  1562         iLocalMultipleUse = ETrue;
       
  1563         }
       
  1564     iItemsDefined |= EStringMax;
       
  1565     if ( iWithinDelimiter )
       
  1566         {
       
  1567         retVal = EInvalidItemWithinDelimiter;
       
  1568         }
       
  1569     return retVal;
       
  1570     }
       
  1571 
       
  1572 // ---------------------------------------------------------------------------
       
  1573 // HandleLocalDelimiter
       
  1574 // ---------------------------------------------------------------------------
       
  1575 //
       
  1576 TInt CParser::HandleLocalDelimiter( const TItem& aItem )
       
  1577     {
       
  1578     const TInt KBeginDelimiter = 1;
       
  1579     const TInt KEndDelimiter = 0;
       
  1580     TInt retVal = 0;
       
  1581 
       
  1582     switch ( aItem.Data() )
       
  1583         {
       
  1584         case KBeginDelimiter:
       
  1585             if ( iWithinDelimiter )
       
  1586                 {
       
  1587                 retVal = ENestedDelimiter;
       
  1588                 }
       
  1589             // Delimiters can't be used when defining usages
       
  1590             // that apply to array items ([1], Section 6.2.2.8):
       
  1591             //
       
  1592             if ( Collection()->Type() == CCollection::ENamedArray )
       
  1593                 {
       
  1594                 IssueWarning( EDelimiterWithinNamedArray );
       
  1595                 }
       
  1596             iWithinDelimiter = ETrue;
       
  1597             iAliasCount = 0;
       
  1598             iAliasCountMin = 0;
       
  1599             iAliasCountMax = 0;
       
  1600             break;
       
  1601 
       
  1602         case KEndDelimiter:
       
  1603             if ( !iWithinDelimiter )
       
  1604                 {
       
  1605                 retVal = ELonelyDelimiter;
       
  1606                 }
       
  1607             iWithinDelimiter = EFalse;
       
  1608             break;
       
  1609 
       
  1610         default:
       
  1611             retVal = EUnknownDelimiter;
       
  1612             TRACE_ERROR((_L("Error: Unknown delimiter type %d\n"),
       
  1613                     aItem.Data()));
       
  1614             break;
       
  1615         }
       
  1616     return retVal;
       
  1617     }
       
  1618 
       
  1619 // ---------------------------------------------------------------------------
       
  1620 // CheckMandatoryFieldExistence
       
  1621 // ---------------------------------------------------------------------------
       
  1622 //
       
  1623 TInt CParser::CheckMandatoryFieldExistence( CField::TType aType, TUint32 aAttributes )
       
  1624     {
       
  1625     TInt retVal = KErrNone;
       
  1626         
       
  1627     if ( ( ( iItemsDefined & KMandatoryItemMask ) != KMandatoryItemMask )
       
  1628         && (!(aAttributes & KConstantFlag)))
       
  1629         {
       
  1630         if ( aType == CField::EInput )
       
  1631             {
       
  1632             retVal = EInputMissingItems;
       
  1633             }
       
  1634         if ( aType == CField::EOutput )
       
  1635             {
       
  1636             retVal = EOutputMissingItems;
       
  1637             }
       
  1638         if ( aType == CField::EFeature )
       
  1639             {    
       
  1640             retVal = EFeatureMissingItems;
       
  1641             }
       
  1642         }    
       
  1643     return retVal;   
       
  1644     }
       
  1645 
       
  1646 // ---------------------------------------------------------------------------
       
  1647 // CheckUsageMinAndMaxErrors
       
  1648 // ---------------------------------------------------------------------------
       
  1649 //    
       
  1650 TInt CParser::CheckUsageMinAndMaxErrors()
       
  1651     {
       
  1652     TInt retVal = KErrNone;
       
  1653         
       
  1654     if ( iItemsDefined & ( EUsageMin | EUsageMax ))
       
  1655         {
       
  1656         if (!( iItemsDefined & EUsageMax ))
       
  1657             {
       
  1658             retVal = ELonelyUsageMin;
       
  1659             }
       
  1660         if (!( iItemsDefined & EUsageMin ))
       
  1661             {
       
  1662             retVal = ELonelyUsageMax;
       
  1663             }
       
  1664         if ( iLocal->UsageMin() > iLocal->UsageMax() )
       
  1665             {
       
  1666             retVal = EUsageMinExceedsMax;
       
  1667             }
       
  1668         }    
       
  1669     return retVal;       
       
  1670     }
       
  1671     
       
  1672 // ---------------------------------------------------------------------------
       
  1673 // CheckDesignatorMinAndMaxErrors
       
  1674 // ---------------------------------------------------------------------------
       
  1675 //      
       
  1676 TInt CParser::CheckDesignatorMinAndMaxErrors()
       
  1677     {
       
  1678     TInt retVal = KErrNone;
       
  1679         
       
  1680     if ( iItemsDefined & ( EDesignatorMin | EDesignatorMax ))
       
  1681         {
       
  1682         if ( !( iItemsDefined & EDesignatorMax ) )
       
  1683             {
       
  1684             retVal = ELonelyDesignatorMin;
       
  1685             }
       
  1686         if ( !( iItemsDefined & EDesignatorMin ) )
       
  1687             {
       
  1688             retVal = ELonelyDesignatorMax;
       
  1689             }
       
  1690         if ( iLocal->DesignatorMin( ) > iLocal->DesignatorMax( ) )
       
  1691             {
       
  1692             retVal = EDesignatorMinExceedsMax;
       
  1693             }
       
  1694         }    
       
  1695     return retVal;           
       
  1696     }    
       
  1697 
       
  1698 // ---------------------------------------------------------------------------
       
  1699 // CheckStringMinAndMaxErrors
       
  1700 // ---------------------------------------------------------------------------
       
  1701 //  
       
  1702 TInt CParser::CheckStringMinAndMaxErrors()
       
  1703     {
       
  1704     TInt retVal = KErrNone;
       
  1705             
       
  1706     if (iItemsDefined & (EStringMin | EStringMax))
       
  1707         {
       
  1708         if ( !( iItemsDefined & EStringMax ) )
       
  1709             {
       
  1710             retVal = ELonelyStringMin;
       
  1711             }
       
  1712         if ( !( iItemsDefined & EStringMin ) )
       
  1713             {
       
  1714             retVal = ELonelyStringMax;
       
  1715             }
       
  1716         if ( iLocal->StringMin( ) > iLocal->StringMax( ) )
       
  1717             {
       
  1718             retVal = EStringMinExceedsMax;
       
  1719             }
       
  1720         }    
       
  1721     return retVal;               
       
  1722     }
       
  1723 
       
  1724 
       
  1725 // ---------------------------------------------------------------------------
       
  1726 // CheckStringMinAndMaxErrors
       
  1727 // ---------------------------------------------------------------------------
       
  1728 //  
       
  1729 TInt CParser::CheckMandatoryFieldErrors( CField::TType aType, TUint32 aAttributes )
       
  1730     {
       
  1731     TInt ret = KErrNone;
       
  1732     // Check for mandatory items:       
       
  1733     ret = CheckMandatoryFieldExistence( aType, aAttributes );    
       
  1734     if ( ret != KErrNone )
       
  1735         {
       
  1736         return ret;
       
  1737         }
       
  1738     ret = CheckUsageMinAndMaxErrors();
       
  1739     if ( ret != KErrNone )
       
  1740         {
       
  1741         return ret;
       
  1742         }    
       
  1743     ret = CheckDesignatorMinAndMaxErrors();
       
  1744     if ( ret != KErrNone )
       
  1745         {
       
  1746         return ret;
       
  1747         }     
       
  1748     ret = CheckStringMinAndMaxErrors();
       
  1749     if ( ret != KErrNone )
       
  1750         {
       
  1751         return ret;
       
  1752         }          
       
  1753     return KErrNone;               
       
  1754     }
       
  1755 
       
  1756 // ---------------------------------------------------------------------------
       
  1757 // CheckLogicalMinAndMax
       
  1758 // ---------------------------------------------------------------------------
       
  1759 //  
       
  1760 void CParser::CheckLogicalMinAndMax( TUint32 aAttributes )
       
  1761     {
       
  1762     // Logical minimum and maximum must match the number of usage
       
  1763     // values defined if the Array flag is set (Var=0).  (Ignore this
       
  1764     // check for constant fields)
       
  1765     //
       
  1766     if ( !( aAttributes & KVariableFlag ) && ( ! ( aAttributes & KConstantFlag ) ) )
       
  1767         {
       
  1768         // Logical minimum must equal 1:
       
  1769         //
       
  1770         if ( iGlobal.iLogicalMin != 1 )
       
  1771             {
       
  1772             // This is an error according to [2], but we issue a
       
  1773             // warning instead, as many devices (including the
       
  1774             // Logitech diNovo keyboard) fail this check:
       
  1775             IssueWarning( ELogicalMinInvalidForArray );
       
  1776             }
       
  1777 
       
  1778         // Logical maximum must equal the number of defined usages:
       
  1779         //
       
  1780         TInt numUsages = iLocal->UsageCount();
       
  1781         if ( numUsages == 0 )
       
  1782             {
       
  1783             numUsages = iLocal->UsageMax( ) - iLocal->UsageMin( ) + 1;
       
  1784             }
       
  1785         if ( iGlobal.iLogicalMax != numUsages )
       
  1786             {
       
  1787             // Again, we issue a warning rather than an error:
       
  1788             IssueWarning( ELogicalMaxInvalidForArray );
       
  1789             }
       
  1790         }            
       
  1791     
       
  1792     }
       
  1793 
       
  1794 // ---------------------------------------------------------------------------
       
  1795 // CheckFieldBitNeeded
       
  1796 // ---------------------------------------------------------------------------
       
  1797 //      
       
  1798 void CParser::CheckFieldBitNeeded( CField::TType aType, TUint32 aAttributes )
       
  1799     {
       
  1800     // "The bit field declared by Report Size must be large enough to
       
  1801     // hold all values declared by Logical Minimum and Logical
       
  1802     // Maximum. This includes a sign bit if either are less than
       
  1803     // 0. Also if the Null flag is set then the field must be capable
       
  1804     // of reporting all values declared by Logical Minimum and Logical
       
  1805     // Maximum, and a null value.", [2] (footnote 5).
       
  1806 
       
  1807     TInt bitsNeeded = 0;
       
  1808 
       
  1809     if ( !( aAttributes & KConstantFlag ) )
       
  1810         {        
       
  1811         if ( aAttributes & KNullStateFlag )
       
  1812             {
       
  1813             // The null state flag is set, so there needs to be at
       
  1814             // least one extra "out of range" value. This could be
       
  1815             // below the lowest value or above the highest, whichever
       
  1816             // will fit better:
       
  1817             bitsNeeded = Min(
       
  1818                 BitsToRepresentRange(iGlobal.iLogicalMin - 1,
       
  1819                     iGlobal.iLogicalMax),
       
  1820                 BitsToRepresentRange(iGlobal.iLogicalMin,
       
  1821                     iGlobal.iLogicalMax + 1));
       
  1822             }
       
  1823         else
       
  1824             {
       
  1825             // No null state declared:
       
  1826             bitsNeeded = BitsToRepresentRange(iGlobal.iLogicalMin,
       
  1827                 iGlobal.iLogicalMax);
       
  1828             }
       
  1829         }
       
  1830 
       
  1831     if ( iGlobal.iSize < bitsNeeded )
       
  1832         {
       
  1833         // The Logitech diNovo is missing a Logical Min and Logical
       
  1834         // Max pair and so will trigger a range error here.  As a
       
  1835         // workaround, we will treat this as a warning rather than
       
  1836         // a critical error:
       
  1837         const TInt KRangeError[] =
       
  1838             { EInputReportSize, EOutputReportSize, EFeatureReportSize };
       
  1839         IssueWarning(KRangeError[aType]);
       
  1840         }        
       
  1841     }
       
  1842     
       
  1843 // ---------------------------------------------------------------------------
       
  1844 // HandleItem
       
  1845 // ---------------------------------------------------------------------------
       
  1846 //     
       
  1847 void CParser::HandleItemL( TItem& aItem )
       
  1848     {    
       
  1849     iErrorCode = EUnknownItem;
       
  1850     if (aItem.IsLocal())
       
  1851         {
       
  1852         iErrorCode = LocalItemL(aItem);
       
  1853         }   
       
  1854     else
       
  1855         {
       
  1856         // Not allowed non-local items within a delimiter pair:
       
  1857         //
       
  1858         if ( iWithinDelimiter )
       
  1859             {
       
  1860             iErrorCode = EInvalidItemWithinDelimiter;
       
  1861             }
       
  1862         else
       
  1863             {
       
  1864             if ( aItem.IsMain() )
       
  1865                 {
       
  1866                 iErrorCode = MainItemL(aItem);
       
  1867                 }
       
  1868 
       
  1869             if ( aItem.IsGlobal() )
       
  1870                 {
       
  1871                 iErrorCode = GlobalItemL(aItem);
       
  1872                 }
       
  1873             if ( aItem.IsLong() )
       
  1874                 {
       
  1875                 IssueWarning(ELongItemDefined);
       
  1876                 iErrorCode = 0;
       
  1877                 }
       
  1878             }
       
  1879         }        
       
  1880     }
       
  1881     
       
  1882 // ---------------------------------------------------------------------------
       
  1883 // CheckParseErrors()
       
  1884 // ---------------------------------------------------------------------------
       
  1885 //      
       
  1886 void CParser::CheckParseErrors()
       
  1887     {        
       
  1888     if ( !iErrorCode && ( iGlobalStack.Count() > 0) )
       
  1889         {
       
  1890         iErrorCode = EPushWithoutPop;
       
  1891         }
       
  1892 
       
  1893     // COLLECTION without END_COLLECTION:
       
  1894     if ( !iErrorCode && ( iCollectionStack.Count() != 0 ) )
       
  1895         {
       
  1896         iErrorCode = ENoMatchingEndCollection;
       
  1897         }
       
  1898 
       
  1899     // DELIMITER(Open) without DELIMITER(Close):
       
  1900     if ( !iErrorCode && iWithinDelimiter )
       
  1901         {
       
  1902         iErrorCode = ELonelyDelimiter;
       
  1903         }
       
  1904 
       
  1905     // Final size of all reports must be a multiple of eight bits:
       
  1906     if ( !CheckAllReportSizes() )
       
  1907         {        
       
  1908         IssueWarning( EReportMustBeEightBitMultiple );
       
  1909         }            
       
  1910     }
       
  1911     
       
  1912 // ---------------------------------------------------------------------------
       
  1913 // ResetParser
       
  1914 // ---------------------------------------------------------------------------
       
  1915 //  
       
  1916 void CParser::ResetParserL()    
       
  1917     {
       
  1918     // Create the root collection, which is the container for all
       
  1919     // other collections and fields:
       
  1920     //
       
  1921     delete iReportRoot;   // may exist if there has been a Leave()
       
  1922     iReportRoot = 0;
       
  1923     iReportRoot = CReportRoot::NewL();
       
  1924     iCollectionStack.Reset();
       
  1925     PushCollectionL(iReportRoot);
       
  1926 
       
  1927     // Clear the error code and the warnings list:
       
  1928     //
       
  1929     iErrorCode = 0;    
       
  1930 
       
  1931     // Reset the parser internal state:
       
  1932     //
       
  1933     iGlobal = TParserGlobalState();
       
  1934     iGlobalStack.Reset();
       
  1935     iWithinDelimiter = EFalse;
       
  1936     iItemsDefined = 0;
       
  1937     iGlobalItemsDefined = 0;
       
  1938     iItemNumber = 0;    
       
  1939     ClearLocalState();
       
  1940     }
       
  1941