this is the Peter Barrett USBHostShell program, a bit modified for being a bit more talkactive, just to let u know how the USB protocol layer is going on, and all the data trasnfers. Also there is a small implementation of HID descriptors, but not functional... yet :S the aim is to at least implement the gamepad HID, and make an array of function pointer to each HID function

Dependencies:   mbed

HID.cpp

Committer:
Sergio
Date:
2010-09-13
Revision:
0:e1e03118b8fe

File content as of revision 0:e1e03118b8fe:



#include "mbed.h"
#include "HID.h"



const char ItemSize[4]={0,1,2,4};

void ResetParser(HIDParser* pParser)
{
    pParser->Pos=0;
    pParser->Count=0;
    pParser->nObject=0;
    pParser->nReport=0;
    pParser->UsageSize=0;
    memset(pParser->UsageTab,0,sizeof(pParser->UsageTab));
    memset(pParser->OffsetTab,0,sizeof(pParser->OffsetTab));
    memset(&pParser->Data,0,sizeof(pParser->Data));
}
    
static void ResetLocalState(HIDParser* pParser)
{
    pParser->UsageSize=0;
    memset(pParser->UsageTab,0,sizeof(pParser->UsageTab));
}
    
u8* GetReportOffset(HIDParser* pParser, 
                        const u8 ReportID, 
                        const u8 ReportType)
 {
   u8 Pos=0;
   while(Pos<MAX_REPORT && pParser->OffsetTab[Pos][0]!=0)
   {
     if(pParser->OffsetTab[Pos][0]==ReportID 
       && pParser->OffsetTab[Pos][1]==ReportType)
       return &pParser->OffsetTab[Pos][2];
     Pos++;
   }
   if(Pos<MAX_REPORT)
   {
     /* Increment Report count */
     pParser->nReport++;
     pParser->OffsetTab[Pos][0]=ReportID;
     pParser->OffsetTab[Pos][1]=ReportType;
     pParser->OffsetTab[Pos][2]=0;
     return &pParser->OffsetTab[Pos][2];
   }
   return NULL;
 }    
    
    
long FormatValue(long Value, char Size)
 {
   if(Size==1) 
     Value=(long)(char)Value;
   else if(Size==2) 
     Value=(long)(short)Value;
   return Value;
 }

 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;

       memcpy(&pParser->Value, &pParser->ReportDesc[pParser->Pos], ItemSize[pParser->Item & SIZE_MASK]);

       /* 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=(u8)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=(u8)(pParser->Value>>16);
         else
          pParser->UsageTab[pParser->UsageSize].UPage=pParser->UPage;
 
         /* Copy Usage in Usage stack */
         pParser->UsageTab[pParser->UsageSize].Usage=(u8)(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)
         {
           u8 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)
         {
           u8 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=(u8)(pParser->Item & ITEM_MASK);
 
         /* Copy data attribute */
        pParser->Data.Attribute=(u8)pParser->Value;
 
         /* Store offset */
         pParser->Data.Offset=*GetReportOffset(pParser, pParser->Data.ReportID, (u8)(pParser->Item & ITEM_MASK));
     
         /* Get Object in pData */
         /* -------------------------------------------------------------------------- */
         memcpy(pData, &pParser->Data, sizeof(HIDData));
         /* -------------------------------------------------------------------------- */
 
         /* Increment Report Offset */
         *GetReportOffset(pParser, pParser->Data.ReportID, (u8)(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=(u8)pParser->Value;
        break;
       }
       case ITEM_REP_SIZE :
       {
         pParser->Data.Size=(u8)pParser->Value;
         break;
       }
       case ITEM_REP_COUNT :
       {
        pParser->ReportCount=(u8)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+=(u8)(pParser->Value & 0xff);
       }
    }
   } /* while(!Found && pParser->Pos<pParser->ReportDescSize) */
 
/*   ERROR(pParser->Data.Path.Size>=PATH_SIZE);
   ERROR(pParser->ReportDescSize>=REPORT_DSC_SIZE);
   ERROR(pParser->UsageSize>=USAGE_TAB_SIZE);
   ERROR(pParser->Data.ReportID>=MAX_REPORT);
 */
   return Found;
 }
 
 int FindObject(HIDParser* pParser, HIDData* pData)
 {
   HIDData FoundData;
   ResetParser(pParser);
   while(HIDParse(pParser, &FoundData))
   {
     if(pData->Path.Size>0 && 
       FoundData.Type==pData->Type &&
       memcmp(FoundData.Path.Node, pData->Path.Node, (pData->Path.Size)*sizeof(HIDNode))==0)
     {
       memcpy(pData, &FoundData, sizeof(HIDData));
       return 1;
     }
     /* Found by ReportID/Offset */
     else if(FoundData.ReportID==pData->ReportID && 
       FoundData.Type==pData->Type &&
       FoundData.Offset==pData->Offset)
     {
       memcpy(pData, &FoundData, sizeof(HIDData));
       return 1;
     }
   }
   return 0;
 }
 
 void GetValue(const u8* Buf, HIDData* pData)
 {
   int Bit=pData->Offset+8; /* First byte of report indicate report ID */
   int Weight=0;
   pData->Value=0;
 
  while(Weight<pData->Size)
   {
     int State=Buf[Bit>>3]&(1<<(Bit%8));
     if(State)
    {
       pData->Value+=(1<<Weight);
     }
     Weight++;
    Bit++;
   }
 /*  if(pData->Value > pData->LogMax)
     pData->Value=FormatValue(pData->Value, (uchar)((pData->Size-1)/8+1));
 */
   if (pData->Value > pData->LogMax)
     pData->Value |= ~pData->LogMax;
 }
 
 void SetValue(const HIDData* pData, u8* Buf)
 {
  int Bit=pData->Offset+8; /* First byte of report indicate report ID */
  int Weight=0;
 
   while(Weight<pData->Size)
   {
     int State=pData->Value & (1<<Weight);
     
     if(Bit%8==0)
       Buf[Bit/8]=0;
 
     if(State)
     {
      Buf[Bit/8]+=(1<<(Weight%8));
     }
     Weight++;
     Bit++;
   }
 }