Exemple #1
0
int HIDParse(HIDParser* pParser, HIDData* pData)
{
  int Found=0;

  while(!Found && pParser->Pos<pParser->ReportDescSize)
    {
      /* Get new pParser->Item if current pParser->Count is empty */
      if(pParser->Count==0)
	{
	  pParser->Item=pParser->ReportDesc[pParser->Pos++];
	  pParser->Value=0;
	  #ifdef WORDS_BIGENDIAN
	  {
	    int i;
	    unsigned long valTmp=0;
	    for (i=0;i<ItemSize[pParser->Item & SIZE_MASK];i++)
	      {
		memcpy(&valTmp, &pParser->ReportDesc[(pParser->Pos)+i], 1);
		pParser->Value+=valTmp>>((3-i)*8);
		valTmp=0;
	      }
	  }
	  #else
	  memcpy(&pParser->Value, &pParser->ReportDesc[pParser->Pos], ItemSize[pParser->Item & SIZE_MASK]);
	  #endif
	  /* Pos on next item */
	  pParser->Pos+=ItemSize[pParser->Item & SIZE_MASK];
	}

      switch(pParser->Item & ITEM_MASK)
	{
	case ITEM_UPAGE :
	  {
	    /* Copy UPage in Usage stack */
	    pParser->UPage=(ushort)pParser->Value;
	    break;
	  }
	case ITEM_USAGE :
	  {
	    /* Copy global or local UPage if any, in Usage stack */
	    if((pParser->Item & SIZE_MASK)>2)
	      pParser->UsageTab[pParser->UsageSize].UPage=(ushort)(pParser->Value>>16);
	    else
	      pParser->UsageTab[pParser->UsageSize].UPage=pParser->UPage;

	    /* Copy Usage in Usage stack */
	    pParser->UsageTab[pParser->UsageSize].Usage=(ushort)(pParser->Value & 0xFFFF);

	    /* Increment Usage stack size */
	    pParser->UsageSize++;

	    break;
	  }
	case ITEM_COLLECTION :
	  {
	    /* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
	    pParser->Data.Path.Node[pParser->Data.Path.Size].UPage=pParser->UsageTab[0].UPage;
	    pParser->Data.Path.Node[pParser->Data.Path.Size].Usage=pParser->UsageTab[0].Usage;
	    pParser->Data.Path.Size++;

	    /* Unstack UPage/Usage from UsageTab (never remove the last) */
	    if(pParser->UsageSize>0)
	      {
		uchar ii=0;
		while(ii<pParser->UsageSize)
		  {
		    pParser->UsageTab[ii].Usage=pParser->UsageTab[ii+1].Usage;
		    pParser->UsageTab[ii].UPage=pParser->UsageTab[ii+1].UPage;
		    ii++;
		  }
		/* Remove Usage */
		pParser->UsageSize--;
	      }

	    /* Get Index if any */
	    if(pParser->Value>=0x80)
	      {
		pParser->Data.Path.Node[pParser->Data.Path.Size].UPage=0xFF;
		pParser->Data.Path.Node[pParser->Data.Path.Size].Usage=pParser->Value & 0x7F;
		pParser->Data.Path.Size++;
	      }
	    ResetLocalState(pParser);
	    break;
	  }
	case ITEM_END_COLLECTION :
	  {
	    pParser->Data.Path.Size--;
	    /* Remove Index if any */
	    if(pParser->Data.Path.Node[pParser->Data.Path.Size].UPage==0xFF)
	      pParser->Data.Path.Size--;
	    ResetLocalState(pParser);
	    break;
	  }
	case ITEM_FEATURE :
	case ITEM_INPUT :
	case ITEM_OUTPUT :
	  {
	    /* An object was found */
	    Found=1;

	    /* Increment object count */
	    pParser->nObject++;

	    /* Get new pParser->Count from global value */
	    if(pParser->Count==0)
	      {
		pParser->Count=pParser->ReportCount;
	      }

	    /* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
	    pParser->Data.Path.Node[pParser->Data.Path.Size].UPage=pParser->UsageTab[0].UPage;
	    pParser->Data.Path.Node[pParser->Data.Path.Size].Usage=pParser->UsageTab[0].Usage;
	    pParser->Data.Path.Size++;

	    /* Unstack UPage/Usage from UsageTab (never remove the last) */
	    if(pParser->UsageSize>0)
	      {
		uchar ii=0;
		while(ii<pParser->UsageSize)
		  {
		    pParser->UsageTab[ii].UPage=pParser->UsageTab[ii+1].UPage;
		    pParser->UsageTab[ii].Usage=pParser->UsageTab[ii+1].Usage;
		    ii++;
		  }
		/* Remove Usage */
		pParser->UsageSize--;
	      }

	    /* Copy data type */
	    pParser->Data.Type=(uchar)(pParser->Item & ITEM_MASK);

	    /* Copy data attribute */
	    pParser->Data.Attribute=(uchar)pParser->Value;

	    /* Store offset */
	    pParser->Data.Offset=*GetReportOffset(pParser, pParser->Data.ReportID, (uchar)(pParser->Item & ITEM_MASK));

	    /* Get Object in pData */
	    /* -------------------------------------------------------------------------- */
	    memcpy(pData, &pParser->Data, sizeof(HIDData));
	    /* -------------------------------------------------------------------------- */

	    /* Increment Report Offset */
	    *GetReportOffset(pParser, pParser->Data.ReportID, (uchar)(pParser->Item & ITEM_MASK)) += pParser->Data.Size;

	    /* Remove path last node */
	    pParser->Data.Path.Size--;

	    /* Decrement count */
	    pParser->Count--;
	    if (pParser->Count == 0) {
	      ResetLocalState(pParser);
	    }
	    break;
	  }
	case ITEM_REP_ID :
	  {
	    pParser->Data.ReportID=(uchar)pParser->Value;
	    break;
	  }
	case ITEM_REP_SIZE :
	  {
	    pParser->Data.Size=(uchar)pParser->Value;
	    break;
	  }
	case ITEM_REP_COUNT :
	  {
	    pParser->ReportCount=(uchar)pParser->Value;
	    break;
	  }
	case ITEM_UNIT_EXP :
	  {
	    pParser->Data.UnitExp=(char)pParser->Value;
	    // Convert 4 bits signed value to 8 bits signed value
	    if (pParser->Data.UnitExp > 7)
	      pParser->Data.UnitExp|=0xF0;
	    break;
	  }
	case ITEM_UNIT :
	  {
	    pParser->Data.Unit=pParser->Value;
	    break;
	  }
	case ITEM_LOG_MIN :
	  {
	    pParser->Data.LogMin=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
	    break;
	  }
	case ITEM_LOG_MAX :
	  {
	    pParser->Data.LogMax=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
	    break;
	  }
	case ITEM_PHY_MIN :
	  {
	    pParser->Data.PhyMin=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
	    break;
	  }
	case ITEM_PHY_MAX :
	  {
	    pParser->Data.PhyMax=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
	    break;
	  }
	case ITEM_LONG :
	  {
	    /* can't handle long items, but should at least skip them */
	    pParser->Pos+=(u_char)(pParser->Value & 0xff);
	  }
	}
Exemple #2
0
/*
 * HIDParse(HIDParser_t* pParser, HIDData_t *pData)
 *
 * Analyse Report descriptor stored in HIDParser struct and store local and
 * global context. 
 * Return in pData the last object found.
 * Return -1 when there is no other Item to parse, 1 if a new object was found
 * or 0 if a continuation of a previous object was found.
 * -------------------------------------------------------------------------- */
static int HIDParse(HIDParser_t *pParser, HIDData_t *pData)
{
	int	Found = -1;

	while ((Found < 0) && (pParser->Pos < pParser->ReportDescSize)) {
		/* Get new pParser->Item if current pParser->Count is empty */
		if (pParser->Count == 0) {
			pParser->Item = pParser->ReportDesc[pParser->Pos++];
			pParser->Value = 0;
#if WORDS_BIGENDIAN
			{
				int	i;
				unsigned long	valTmp = 0;

				for (i = 0; i < ItemSize[pParser->Item & SIZE_MASK]; i++) {
					memcpy(&valTmp, &pParser->ReportDesc[(pParser->Pos)+i], 1);
					pParser->Value += valTmp >> ((3-i)*8);
					valTmp = 0;
				}
			}
#else
			memcpy(&pParser->Value, &pParser->ReportDesc[pParser->Pos], ItemSize[pParser->Item & SIZE_MASK]);
#endif
			/* Pos on next item */
      			pParser->Pos += ItemSize[pParser->Item & SIZE_MASK];
		}

		switch (pParser->Item & ITEM_MASK)
		{
		case ITEM_UPAGE:
			/* Copy UPage in Usage stack */
			pParser->UPage=(uint16_t)pParser->Value;
			break;

		case ITEM_USAGE:
			/* Copy global or local UPage if any, in Usage stack */
			if ((pParser->Item & SIZE_MASK) > 2) {
				pParser->UsageTab[pParser->UsageSize] = pParser->Value;
			} else {
				pParser->UsageTab[pParser->UsageSize] = (pParser->UPage << 16) | (pParser->Value & 0xFFFF);
			}

			/* Increment Usage stack size */
			pParser->UsageSize++;
			break;

		case ITEM_COLLECTION:
			/* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
			pParser->Data.Path.Node[pParser->Data.Path.Size] = pParser->UsageTab[0];
			pParser->Data.Path.Size++;

			/* Unstack UPage/Usage from UsageTab (never remove the last) */
			if (pParser->UsageSize > 0) {
				int	i;
			
				for (i = 0; i < pParser->UsageSize; i++) {
					pParser->UsageTab[i] = pParser->UsageTab[i+1];
				}

				/* Remove Usage */
				pParser->UsageSize--;
		        }

			/* Get Index if any */
			if (pParser->Value >= 0x80) {
				pParser->Data.Path.Node[pParser->Data.Path.Size] = 0x00ff0000 | (pParser->Value & 0x7F);
				pParser->Data.Path.Size++;
			}

			ResetLocalState(pParser);
			break;

		case ITEM_END_COLLECTION :
			pParser->Data.Path.Size--;
			
			/* Remove Index if any */
			if((pParser->Data.Path.Node[pParser->Data.Path.Size] & 0xffff0000) == 0x00ff0000) {
				pParser->Data.Path.Size--;
			}
			
			ResetLocalState(pParser);
			break;
			
		case ITEM_FEATURE:
		case ITEM_INPUT:
		case ITEM_OUTPUT:
			if (pParser->UsageTab[0] != 0x00000000) {
				/* An object was found if the path does not end with 0x00000000 */
				Found = 1;
			} else {
				/* It is a continuation of a previous object */
				Found = 0;
			}
			
			/* Get new pParser->Count from global value */
			if(pParser->Count == 0) {
				pParser->Count = pParser->ReportCount;
			}
			
			/* Get UPage/Usage from UsageTab and store them in pParser->Data.Path */
			pParser->Data.Path.Node[pParser->Data.Path.Size] = pParser->UsageTab[0];
			pParser->Data.Path.Size++;
			
			/* Unstack UPage/Usage from UsageTab (never remove the last) */
			if(pParser->UsageSize > 0) {
				int i;
				
				for (i = 0; i < pParser->UsageSize; i++) {
					pParser->UsageTab[i] = pParser->UsageTab[i+1];
				}
				/* Remove Usage */
				pParser->UsageSize--;
			}
			
			/* Copy data type */
			pParser->Data.Type = (uint8_t)(pParser->Item & ITEM_MASK);
			
			/* Copy data attribute */
			pParser->Data.Attribute = (uint8_t)pParser->Value;
			
			/* Store offset */
			pParser->Data.Offset = *GetReportOffset(pParser, pParser->Data.ReportID, (uint8_t)(pParser->Item & ITEM_MASK));
			
			/* Get Object in pData */
			/* -------------------------------------------------------------------------- */
			memcpy(pData, &pParser->Data, sizeof(HIDData_t));
			/* -------------------------------------------------------------------------- */
			
			/* Increment Report Offset */
			*GetReportOffset(pParser, pParser->Data.ReportID, (uint8_t)(pParser->Item & ITEM_MASK)) += pParser->Data.Size;
			
			/* Remove path last node */
			pParser->Data.Path.Size--;
			
			/* Decrement count */
			pParser->Count--;
			
			if (pParser->Count == 0) {
				ResetLocalState(pParser);
			}
			break;
			
		case ITEM_REP_ID :
			pParser->Data.ReportID = (uint8_t)pParser->Value;
			break;
			
		case ITEM_REP_SIZE :
			pParser->Data.Size = (uint8_t)pParser->Value;
			break;
			
		case ITEM_REP_COUNT :
			pParser->ReportCount = (uint8_t)pParser->Value;
			break;
			
		case ITEM_UNIT_EXP :
			pParser->Data.UnitExp = (int8_t)pParser->Value;
			if (pParser->Data.UnitExp > 7) {
				pParser->Data.UnitExp |= 0xF0;
			}
			break;
			
		case ITEM_UNIT :
			pParser->Data.Unit = pParser->Value;
			break;
			
		case ITEM_LOG_MIN :
			pParser->Data.LogMin = FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
			break;
			
		case ITEM_LOG_MAX :
			pParser->Data.LogMax = FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
			break;
			
		case ITEM_PHY_MIN :
			pParser->Data.PhyMin=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
			pParser->Data.have_PhyMin = 1;
			break;
			
		case ITEM_PHY_MAX :
			pParser->Data.PhyMax=FormatValue(pParser->Value, ItemSize[pParser->Item & SIZE_MASK]);
			pParser->Data.have_PhyMax = 1;
			break;
			
		case ITEM_LONG :
			/* can't handle long items, but should at least skip them */
			pParser->Pos += (uint8_t)(pParser->Value & 0xff);
			break;
		}
	} /* while ((Found < 0) && (pParser->Pos < pParser->ReportDescSize)) */