hidparser.c

Go to the documentation of this file.
00001 
00025 #include "config.h"
00026 #include <string.h>
00027 #include "hidparser.h"
00028 
00029 /* to be implemented for DEBUG purpose */
00030 /* previously: #define ERROR(x) if(x) __asm { int 3 }; */
00032 #define ERROR(x)
00033 
00034 const char ItemSize[4]={0,1,2,4};
00035 
00040 void ResetParser(HIDParser* pParser)
00041 {
00042   pParser->Pos=0;
00043   pParser->Count=0;
00044   pParser->nObject=0;
00045   pParser->nReport=0;
00046 
00047   pParser->UsageSize=0;
00048   memset(pParser->UsageTab,0,sizeof(pParser->UsageTab));
00049 
00050   memset(pParser->OffsetTab,0,sizeof(pParser->OffsetTab));
00051   memset(&pParser->Data,0,sizeof(pParser->Data));
00052 }
00053 
00065 static void ResetLocalState(HIDParser* pParser)
00066 {
00067   pParser->UsageSize = 0;
00068   memset(pParser->UsageTab,0,sizeof(pParser->UsageTab));
00069 }
00070 
00075 uchar* GetReportOffset(HIDParser* pParser, 
00076                        const uchar ReportID, 
00077                        const uchar ReportType)
00078 {
00079   ushort Pos=0;
00080   while(Pos<MAX_REPORT && pParser->OffsetTab[Pos][0]!=0)
00081   {
00082     if(pParser->OffsetTab[Pos][0]==ReportID 
00083       && pParser->OffsetTab[Pos][1]==ReportType)
00084       return &pParser->OffsetTab[Pos][2];
00085     Pos++;
00086   }
00087   if(Pos<MAX_REPORT)
00088   {
00089     /* Increment Report count */
00090     pParser->nReport++;
00091     pParser->OffsetTab[Pos][0]=ReportID;
00092     pParser->OffsetTab[Pos][1]=ReportType;
00093     pParser->OffsetTab[Pos][2]=0;
00094     return &pParser->OffsetTab[Pos][2];
00095   }
00096   return NULL;
00097 }
00098 
00102 long FormatValue(long Value, uchar Size)
00103 {
00104   if(Size==1) 
00105     Value=(long)(char)Value;
00106   else if(Size==2) 
00107     Value=(long)(short)Value;
00108   return Value;
00109 }
00110 
00119 int HIDParse(HIDParser* pParser, HIDData* pData)
00120 {
00121   int Found=0;
00122 
00123   while(!Found && pParser->Pos<pParser->ReportDescSize)
00124   {
00125     /* Get new pParser->Item if current pParser->Count is empty */
00126     if(pParser->Count==0)
00127     {
00128       pParser->Item=pParser->ReportDesc[pParser->Pos++];
00129       pParser->Value=0;
00130 #ifdef WORDS_BIGENDIAN
00131   {
00132     int i;
00133     unsigned long valTmp=0;
00134     for (i=0;i<ItemSize[pParser->Item & SIZE_MASK];i++)
00135       {
00136     memcpy(&valTmp, &pParser->ReportDesc[(pParser->Pos)+i], 1);
00137     pParser->Value+=valTmp>>((3-i)*8);
00138     valTmp=0;
00139       }
00140   }
00141 #else
00142       memcpy(&pParser->Value, &pParser->ReportDesc[pParser->Pos], ItemSize[pParser->Item & SIZE_MASK]);
00143 #endif
00144       /* Pos on next item */
00145       pParser->Pos+=ItemSize[pParser->Item & SIZE_MASK];
00146     }
00147 
00148     switch(pParser->Item & ITEM_MASK)
00149     {
00150       case ITEM_UPAGE :
00151       {
00152         /* Copy UPage in Usage stack */
00153         pParser->UPage=(ushort)pParser->Value;
00154         break;
00155       }
00156       case ITEM_USAGE :
00157       {
00158         /* Copy global or local UPage if any, in Usage stack */
00159          if((pParser->Item & SIZE_MASK)>2)
00160           pParser->UsageTab[pParser->UsageSize].UPage=(ushort)(pParser->Value>>16);
00161         else
00162           pParser->UsageTab[pParser->UsageSize].UPage=pParser->UPage;
00163 
00164         /* Copy Usage in Usage stack */
00165         pParser->UsageTab[pParser->UsageSize].Usage=(ushort)(pParser->Value & 0xFFFF);
00166 
00167         /* Increment Usage stack size */
00168         pParser->UsageSize++;
00169 
00170         break;
00171       }
00172       case ITEM_COLLECTION :
00173       {
00174         /* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
00175         pParser->Data.Path.Node[pParser->Data.Path.Size].UPage=pParser->UsageTab[0].UPage;
00176         pParser->Data.Path.Node[pParser->Data.Path.Size].Usage=pParser->UsageTab[0].Usage;
00177         pParser->Data.Path.Size++;
00178       
00179         /* Unstack UPage/Usage from UsageTab (never remove the last) */
00180         if(pParser->UsageSize>0)
00181         {
00182           uchar ii=0;
00183           while(ii<pParser->UsageSize)
00184           {
00185             pParser->UsageTab[ii].Usage=pParser->UsageTab[ii+1].Usage;
00186             pParser->UsageTab[ii].UPage=pParser->UsageTab[ii+1].UPage;
00187             ii++;
00188           }
00189           /* Remove Usage */
00190           pParser->UsageSize--;
00191         }
00192 
00193         /* Get Index if any */
00194         if(pParser->Value>=0x80)
00195         {
00196           pParser->Data.Path.Node[pParser->Data.Path.Size].UPage=0xFF;
00197           pParser->Data.Path.Node[pParser->Data.Path.Size].Usage=pParser->Value & 0x7F;
00198           pParser->Data.Path.Size++;
00199         }
00200   ResetLocalState(pParser);
00201         break;
00202       }
00203       case ITEM_END_COLLECTION :
00204       {
00205         pParser->Data.Path.Size--;
00206         /* Remove Index if any */
00207         if(pParser->Data.Path.Node[pParser->Data.Path.Size].UPage==0xFF)
00208           pParser->Data.Path.Size--;
00209   ResetLocalState(pParser);
00210         break;
00211       }
00212       case ITEM_FEATURE :
00213       case ITEM_INPUT :
00214       case ITEM_OUTPUT :
00215       {
00216         /* An object was found */
00217         Found=1;
00218 
00219         /* Increment object count */
00220         pParser->nObject++;
00221 
00222         /* Get new pParser->Count from global value */
00223         if(pParser->Count==0)
00224         {
00225           pParser->Count=pParser->ReportCount;
00226         }
00227 
00228         /* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
00229         pParser->Data.Path.Node[pParser->Data.Path.Size].UPage=pParser->UsageTab[0].UPage;
00230         pParser->Data.Path.Node[pParser->Data.Path.Size].Usage=pParser->UsageTab[0].Usage;
00231         pParser->Data.Path.Size++;
00232   
00233         /* Unstack UPage/Usage from UsageTab (never remove the last) */
00234         if(pParser->UsageSize>0)
00235         {
00236           uchar ii=0;
00237           while(ii<pParser->UsageSize)
00238           {
00239             pParser->UsageTab[ii].UPage=pParser->UsageTab[ii+1].UPage;
00240             pParser->UsageTab[ii].Usage=pParser->UsageTab[ii+1].Usage;
00241             ii++;
00242           }
00243           /* Remove Usage */
00244           pParser->UsageSize--;
00245         }
00246 
00247         /* Copy data type */
00248         pParser->Data.Type=(uchar)(pParser->Item & ITEM_MASK);
00249 
00250         /* Copy data attribute */
00251         pParser->Data.Attribute=(uchar)pParser->Value;
00252 
00253         /* Store offset */
00254         pParser->Data.Offset=*GetReportOffset(pParser, pParser->Data.ReportID, (uchar)(pParser->Item & ITEM_MASK));
00255     
00256         /* Get Object in pData */
00257         /* -------------------------------------------------------------------------- */
00258         memcpy(pData, &pParser->Data, sizeof(HIDData));
00259         /* -------------------------------------------------------------------------- */
00260 
00261         /* Increment Report Offset */
00262         *GetReportOffset(pParser, pParser->Data.ReportID, (uchar)(pParser->Item & ITEM_MASK)) += pParser->Data.Size;
00263 
00264         /* Remove path last node */
00265         pParser->Data.Path.Size--;
00266 
00267         /* Decrement count */
00268         pParser->Count--;
00269   if (pParser->Count == 0) {
00270     ResetLocalState(pParser);
00271   }
00272         break;
00273       }
00274       case ITEM_REP_ID :
00275       {
00276         pParser->Data.ReportID=(uchar)pParser->Value;
00277         break;
00278       }
00279       case ITEM_REP_SIZE :
00280       {
00281         pParser->Data.Size=(uchar)pParser->Value;
00282         break;
00283       }
00284       case ITEM_REP_COUNT :
00285       {
00286         pParser->ReportCount=(uchar)pParser->Value;
00287         break;
00288       }
00289       case ITEM_UNIT_EXP :
00290       {
00291         pParser->Data.UnitExp=(char)pParser->Value;
00292   // Convert 4 bits signed value to 8 bits signed value
00293   if (pParser->Data.UnitExp > 7)
00294     pParser->Data.UnitExp|=0xF0;
00295         break;
00296       }
00297       case ITEM_UNIT :
00298       {
00299         pParser->Data.Unit=pParser->Value;
00300         break;
00301       }
00302       case ITEM_LOG_MIN :
00303       {
00304         pParser->Data.LogMin=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
00305         break;
00306       }
00307       case ITEM_LOG_MAX :
00308       {
00309         pParser->Data.LogMax=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
00310         break;
00311       }
00312       case ITEM_PHY_MIN :
00313       {
00314         pParser->Data.PhyMin=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
00315         break;
00316       }
00317       case ITEM_PHY_MAX :
00318       {
00319         pParser->Data.PhyMax=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
00320         break;
00321       }
00322       case ITEM_LONG :
00323       {
00324   /* can't handle long items, but should at least skip them */
00325   pParser->Pos+=(u_char)(pParser->Value & 0xff);
00326       }
00327     }
00328   } /* while(!Found && pParser->Pos<pParser->ReportDescSize) */
00329 
00330   ERROR(pParser->Data.Path.Size>=PATH_SIZE);
00331   ERROR(pParser->ReportDescSize>=REPORT_DSC_SIZE);
00332   ERROR(pParser->UsageSize>=USAGE_TAB_SIZE);
00333   ERROR(pParser->Data.ReportID>=MAX_REPORT);
00334 
00335   return Found;
00336 }
00337 
00342 int FindObject(HIDParser* pParser, HIDData* pData)
00343 {
00344   HIDData FoundData;
00345   ResetParser(pParser);
00346   while(HIDParse(pParser, &FoundData))
00347   {
00348     if(pData->Path.Size>0 && 
00349       FoundData.Type==pData->Type &&
00350       memcmp(FoundData.Path.Node, pData->Path.Node, (pData->Path.Size)*sizeof(HIDNode))==0)
00351     {
00352       memcpy(pData, &FoundData, sizeof(HIDData));
00353       return 1;
00354     }
00355     /* Found by ReportID/Offset */
00356     else if(FoundData.ReportID==pData->ReportID && 
00357       FoundData.Type==pData->Type &&
00358       FoundData.Offset==pData->Offset)
00359     {
00360       memcpy(pData, &FoundData, sizeof(HIDData));
00361       return 1;
00362     }
00363   }
00364   return 0;
00365 }
00366 
00374 void GetValue(const uchar* Buf, HIDData* pData)
00375 {
00376   int Bit=pData->Offset+8; /* First byte of report indicate report ID */
00377   int Weight=0;
00378   pData->Value=0;
00379 
00380   while(Weight<pData->Size)
00381   {
00382     int State=Buf[Bit>>3]&(1<<(Bit%8));
00383     if(State)
00384     {
00385       pData->Value+=(1<<Weight);
00386     }
00387     Weight++;
00388     Bit++;
00389   }
00390 /*  if(pData->Value > pData->LogMax)
00391     pData->Value=FormatValue(pData->Value, (uchar)((pData->Size-1)/8+1));
00392 */
00393   if (pData->Value > pData->LogMax)
00394     pData->Value |= ~pData->LogMax;
00395 }
00396 
00401 void SetValue(const HIDData* pData, uchar* Buf)
00402 {
00403   int Bit=pData->Offset+8; /* First byte of report indicate report ID */
00404   int Weight=0;
00405 
00406   while(Weight<pData->Size)
00407   {
00408     int State=pData->Value & (1<<Weight);
00409     
00410     if(Bit%8==0)
00411       Buf[Bit/8]=0;
00412 
00413     if(State)
00414     {
00415       Buf[Bit/8]+=(1<<(Weight%8));
00416     }
00417     Weight++;
00418     Bit++;
00419   }
00420 }

Generated on Sun Mar 30 15:28:24 2008 for libhid by  doxygen 1.5.1