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
Diff: HID.cpp
- Revision:
- 0:e1e03118b8fe
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HID.cpp Mon Sep 13 12:40:05 2010 +0000 @@ -0,0 +1,345 @@ + + +#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++; + } + } + + + + + + + + \ No newline at end of file