This section describes the library's data processing sequence. Whenever a new data packet is captured by the USBMC, the following occurs:
The following is a pseudo-code of library's data processing pipeline:
// pData is a pointer to data chunk, received from driver
void ProcessBuffer(void* pData,DWORD dwDataSize)
{
// for each client
for(...)
{
// this step is for NATIVE clients only
pClient->ProcessRawBuffer(...);
}
for (USBPACKET* packet=(USBPACKET *)pData,*stop=(USBPACKET*) ((BYTE *)pData+dwSize);
packet<stop && packet->Size;
(BYTE*&) packet+=packet->Size)
{
// for each client
for(...)
{
if(packet->Flags & UPF_DOWN)
pClient->OnPacketDown(...);
else
pClient->OnPacketUp(...);
switch(packet->EventType)
{
case EVENT_URB:
{
// parsing urb here
USBPACKET_URB* pUrb = (USBPACKET_URB *)pPacket;
BYTE* pUrbData = ...;
DWORD dwUrbSize = ...;
pClient->OnUrb(pUrbData,dwUrbSize);
switch (pUrb->urb.UrbHeader.Function)
{
case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
pClient->OnGetDescriptorFromDevice();
break;
// ...
}
break;
}
case EVENT_DEVICECONNECTED:
pClient->OnConnection(...);
break;
// ...
}
}
}
};
Let's take a OnGetDescriptorFromInterface method as an example.
USBMC uses URB_CONTROL_DESCRIPTOR_REQUEST structure to get the data from a URB packet. Native listener has the following signature for OnGetDescriptorFromInterface method:
HRESULT OnGetDescriptorFromInterface (FILETIME *fTime,void* pData,ULONG Size,
BYTE Index,BYTE DescriptorType,USHORT LanguageId);
pData points to the packet that has a type USBPACKET and can be cast to USBPACKET_URB. So, native client can manually parse this packet and extract fields it needs. Besides USBMC automatically decodes and provides severl packet fields, such as Index, DescriptorType and LanguageId.
Manual parsing can be implemented in C++ in this way:
USBPACKET_URB* pUrb = (USBPACKET_URB*)pData;
_URB_CONTROL_DESCRIPTOR_REQUEST &r = pUrb->urb.UrbControlDescriptorRequest;
// use r variable here
Please note that managed (dispatched) interface has a different method signature, without pData and Size:
OnGetDescriptorFromInterface([in] DATE time,
[in] BYTE Index,[in] BYTE DescriptorType,[in] USHORT LanguageId);
Nevertheless, several managed callback methods (such as _IMonitoringEvents.OnPacketDown, _IMonitoringEvents.OnPacketUp and _IMonitoringEvents.OnUrb) receive raw data by means of a safe array, allowing them to manually parse data.