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
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++; } }