USB LS and FS Analyzer been enhanced?

As was discussed a few times during the Logic 2 software beta cycle, including:

There are times when I try to use the Analyzer to capture, either protocol startups or data.

Today for example would like to capture an MTP file transfer to see if/when a USB data packet is either not sent or something wrong with one or more 64 byte data packet

Problem is with current analyzer there is so much other data, that I lose the tree in the forest.

What I have typically done in the past was to have to save report out to file, then use grep to find all of the lines that cantain data. I usually use the linux greap as to also capture the line before the data line.
Then I need to edit this file to remove a bunch of other stuff…

Would be nice to have a version of capture that does this for us.

Also were HLA hooks setup for this analyzer?

Thanks
Kurt

Hey Kurt, sorry for the trouble with that. Yeah, the USB analyzer can get pretty busy. Unfortunately, our USB analyzer is not supported by HLAs yet. Creating an HLA would have been a viable solution for this. The supported analyzers are listed below.

Can you give me an idea of what kind of data you typically search for? Allowing the ability to search a sequence of bytes could also be a step towards that direction (per the idea post we’re tracking below):

Apolgies we don’t have an immediate solution for this.

Thanks,

I showed an example back in I believe the 2nd posting of the thread:

Where I boiled down 1.9 million line output, to a few 100 lines of useful (to me) information.

That ended up looking something like:

|23.21607064|IN|0x02|0x18|0x48 0x20 0x53 0x00 0x4F 0x00 0x71 0x00 0xA1 0x11 0xC0 0x00 0x81 0x7C 0x81 0x7C 0x08 0x00 0x48 0x00 0x00 0xA0 0x7F 0xFC 0x0E 0x00 0x00 0x00 0x05 0x00 0x81 0x0A 0x7C 0x1E 0x1A 0x00 0x00 0x00 0x00 0x00 0x00 0x09 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00|
|23.21707062|IN|0x02|0x18|0x80 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 0x00 0xC3 0x7D 0xE1 0x8C|
|23.21807067|IN|0x02|0x18|0x48 0x20 0x53 0x00 0x4F 0x00 0x71 0x00 0xA1 0x11 0xC0 0x00 0x81 0x7C 0x81 0x7C 0x08 0x00 0x4C 0x00 0x00 0xF7 0x80 0xFC 0x0E 0x00 0x00 0x00 0x05 0x00 0x69 0x0A 0x83 0x1E 0x09 0x00 0x00 0x00 0x00 0x00 0x00 0x09 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x80 0x00 0x00 0x00 0x00|

Note: the copy and paste from the other thread sort of changed it slightly… But does show the point.

Sort of boiled down to In/out (which channel) how many bytes, and the data. Sometimes I leave the time stamp other times not.

Thanks again

Kurt

P.S. - Luckily yesterday was able to find where the messages were being lost to without resorting to this. But still would be great to have some solution for the next time

1 Like

As I only see one branch of the usb_analyzer: GitHub - saleae/usb-analyzer: Saleae USB Analyzer

I am guessing that there has not been much progress on supporting some different output formats or support for HLAs.

So I started wondering how hard it might be to add an HLA interface for the analyzer…
So I forked, and created a new Alpha branch. I merged in some of the external changes for alpha from the Serial and/or SPI analyzer and have it building, where I can UseFrameV2.

And started trying to add V2 frames most everywhere a V1 frame is… and it does build.
Have not done the USBControlTransfers yet.

But also now wondering about how the V2 packets should be done versus V1, for example if you look at:

U64 USBPacket::AddPacketFrames( USBAnalyzerResults* pResults, USBFrameFlags flagPID )
{
    AddSyncAndPidFrames( pResults, flagPID );

    // make the analyzer frames for this packet
    Frame f;
    f.mFlags = FF_None;
    FrameV2 fv2;
    const char* fv2_type;

    // do the payload & CRC frames
    if( IsTokenPacket() || IsSOFPacket() )
    {
        // address/endpoint  or  frame number
        f.mStartingSampleInclusive = *( mBitBeginSamples.begin() + 16 );
        f.mEndingSampleInclusive = *( mBitBeginSamples.begin() + 27 );

        // is this a SOF packet?
        if( mPID == PID_SOF )
        {
            f.mType = FT_FrameNum;
            f.mData1 = GetFrameNum();
            f.mData2 = 0;
            fv2.AddInteger( "frameNum", ( U8 )f.mData1 );
            fv2_type = "frame";
        }
        else
        {
            f.mType = FT_AddrEndp;
            f.mData1 = GetAddress();
            f.mData2 = GetEndpoint();
            fv2.AddInteger( "addr", ( U8 )f.mData1 );
            fv2.AddInteger( "endpoint", ( U8 )f.mData2 );
            fv2_type = "addrendp";
        }

        pResults->AddFrame( f );
        pResults->AddFrameV2( fv2, fv2_type, *( mBitBeginSamples.begin() + 16 ), *( mBitBeginSamples.begin() + 27 ) );

        // CRC5
        f.mStartingSampleInclusive = *( mBitBeginSamples.begin() + 27 );
        f.mEndingSampleInclusive = mBitBeginSamples.back();

        f.mType = FT_CRC5;
        f.mData1 = mCRC;
        f.mData2 = CalcCRC5( GetLastWord() & 0x7ff );
        pResults->AddFrame( f );

        FrameV2 frame_v2_crc;
        frame_v2_crc.AddInteger( "crc", ( S64 )f.mData1 );
        frame_v2_crc.AddInteger( "ccrc", ( S64 )f.mData2 );
        pResults->AddFrameV2( frame_v2_crc, "crc5", *( mBitBeginSamples.begin() + 27 ), mBitBeginSamples.back() );
    }
    else if( IsDataPacket() )
    {
        // raw data
        FrameV2 fv2;
        size_t bc;
        f.mType = FT_Byte;
        f.mData2 = 0;
        for( bc = 2; bc < mData.size() - 2; ++bc )
        {
            f.mStartingSampleInclusive = *( mBitBeginSamples.begin() + bc * 8 );
            f.mEndingSampleInclusive = *( mBitBeginSamples.begin() + ( bc + 1 ) * 8 );
            f.mData1 = mData[ bc ];

            pResults->AddFrame( f );
            fv2.AddByte( "data", mData[ bc ] );
            pResults->AddFrameV2( fv2, "result", *( mBitBeginSamples.begin() + bc * 8 ), *( mBitBeginSamples.begin() + ( bc + 1 ) * 8 ) );
        }

        AddCRC16Frame( pResults );
    }

    if( mPID != PID_PRE )
        AddEOPFrame( pResults );

    pResults->CommitResults();

    return mSampleEnd;
}

Which does build, I am doing a 1 to 1 V1 to V2 message.

But wondering for example:
if this should instead simply generate one or a few messages.
Where all the data should be just one item,
with a bytearray for a “data” item in the v2 frame. Not sure if things like SOF or CRC should be separate or again just another field.

So far just playing, I have not yet tried plugging it in to to the analyzer to see if it goes boom or generates data

Thoughts?

@timreyes - quick questions on LLA

I am assuming this is still a single path… i.e. nothing like , or ; between multiple

If I want work on a different one, but still use one like SPIEx, I probably just copy the
SPIEx one to where all of the others are, including the ones that you install. Which in my case is:
D:\Program Files\Logic\resources\windows\Analyzers

If I am working (Playing) with updates to one of your analyzers (this case USB) and
I update that path to where it builds, What will the analyzer list do with two with same name?
Fail? Show Both, or one takes priority over the other?

Thanks

Edit - Answered last question:
image

Was able to load experimental one by editing:

const char* GetAnalyzerName()
{
    return "USB(alpha) LS and FS";
}

Changed name…

Sorry I am mostly talking to self… :wink:

Making some maybe progress:

Will play more with HLA to see if it talks…

Sorry another quick update…

I have verified that I can talk to it with an HLA…
Here is some output from the HLA


Probably all for today

@KurtE Good to hear you’re making progress! For your question below:

I am assuming this is still a single path… i.e. nothing like , or ; between multiple

We definitely need to improve this to allow multiple source folder locations per LLA (similar to how we handle HLAs right now). We had another user submit a similar feature request below fairly recently.

Thanks.

I am not sure of best way to proceed. That is, will Saleae wish to incorporate some/all the FrameV2 for USB stuff into the official released version… And if so what is the best way to proceed… So I opened up an issue on the library: Support High level Analyzers using FrameV2 · Issue #3 · saleae/usb-analyzer · GitHub

My Fork/Branch is up at: GitHub - KurtE/usb-analyzer at alpha
I have also pushed up my WIP HLA using it: GitHub - KurtE/Saleae_USB_Data_Packets_HLA: USB Data Packets using my Alpha version of USB LS and FS

I have the bubbles and table stuff showing up reasonably well:

The print output is pretty well setup to output to something like excel:
Note: I trimmed this down as it included a lot of mouse inputs at end …
Which I would typically prune when I used it.
But it output I believe 2048 lines. But after pruning down to maybe 50-75 lines…

SETUP , DATA0 , 0x0 , 0x0 ,  0x80 0x6 0x0 0x1 0x0 0x0 0x8 0x0
IN , DATA1 , 0x0 , 0x0 ,  0x12 0x1 0x10 0x1 0x0 0x0 0x0 0x8
SETUP , DATA0 , 0x0 , 0x0 ,  0x0 0x5 0x1 0x0 0x0 0x0 0x0 0x0
SETUP , DATA0 , 0x0 , 0x1 ,  0x80 0x6 0x0 0x1 0x0 0x0 0x12 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x12 0x1 0x10 0x1 0x0 0x0 0x0 0x8
IN , DATA0 , 0x0 , 0x1 ,  0x8a 0x25 0x36 0x0 0x9 0x1 0x1 0x2
IN , DATA1 , 0x0 , 0x1 ,  0x0 0x1
SETUP , DATA0 , 0x0 , 0x1 ,  0x80 0x6 0x0 0x3 0x0 0x0 0xfc 0x1
IN , DATA1 , 0x0 , 0x1 ,  0x4 0x3 0x9 0x4
SETUP , DATA0 , 0x0 , 0x1 ,  0x80 0x6 0x1 0x3 0x9 0x4 0xfc 0x1
IN , DATA1 , 0x0 , 0x1 ,  0x16 0x3 0x53 0x0 0x49 0x0 0x4e 0x0
IN , DATA0 , 0x0 , 0x1 ,  0x4f 0x0 0x57 0x0 0x45 0x0 0x41 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x4c 0x0 0x54 0x0 0x48 0x0
SETUP , DATA0 , 0x0 , 0x1 ,  0x80 0x6 0x2 0x3 0x9 0x4 0xfc 0x1
IN , DATA1 , 0x0 , 0x1 ,  0x26 0x3 0x57 0x0 0x69 0x0 0x72 0x0
IN , DATA0 , 0x0 , 0x1 ,  0x65 0x0 0x64 0x0 0x20 0x0 0x47 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x61 0x0 0x6d 0x0 0x69 0x0 0x6e 0x0
IN , DATA0 , 0x0 , 0x1 ,  0x67 0x0 0x20 0x0 0x4d 0x0 0x6f 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x75 0x0 0x73 0x0 0x65 0x0
SETUP , DATA0 , 0x0 , 0x1 ,  0x80 0x6 0x0 0x2 0x0 0x0 0x9 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x9 0x2 0x3b 0x0 0x2 0x1 0x0 0xa0
IN , DATA0 , 0x0 , 0x1 ,  0xf0
SETUP , DATA0 , 0x0 , 0x1 ,  0x80 0x6 0x0 0x2 0x0 0x0 0x3b 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x9 0x2 0x3b 0x0 0x2 0x1 0x0 0xa0
IN , DATA0 , 0x0 , 0x1 ,  0xf0 0x9 0x4 0x0 0x0 0x1 0x3 0x1
IN , DATA1 , 0x0 , 0x1 ,  0x2 0x0 0x9 0x21 0x11 0x1 0x0 0x1
IN , DATA0 , 0x0 , 0x1 ,  0x22 0x47 0x0 0x7 0x5 0x81 0x3 0x8
IN , DATA1 , 0x0 , 0x1 ,  0x0 0x1 0x9 0x4 0x1 0x0 0x1 0x3
IN , DATA0 , 0x0 , 0x1 ,  0x1 0x1 0x0 0x9 0x21 0x11 0x1 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x1 0x22 0xd5 0x0 0x7 0x5 0x82 0x3
IN , DATA0 , 0x0 , 0x1 ,  0x8 0x0 0x1
SETUP , DATA0 , 0x0 , 0x1 ,  0x0 0x9 0x1 0x0 0x0 0x0 0x0 0x0
SETUP , DATA0 , 0x0 , 0x1 ,  0x81 0x6 0x0 0x22 0x0 0x0 0x47 0x0
IN , DATA1 , 0x0 , 0x1 ,  0x5 0x1 0x9 0x2 0xa1 0x1 0x9 0x1
IN , DATA0 , 0x0 , 0x1 ,  0xa1 0x0 0x5 0x9 0x19 0x1 0x29 0x5
IN , DATA1 , 0x0 , 0x1 ,  0x15 0x0 0x25 0x1 0x75 0x1 0x95 0x5
IN , DATA0 , 0x0 , 0x1 ,  0x81 0x2 0x95 0x3 0x81 0x1 0x5 0x1
IN , DATA1 , 0x0 , 0x1 ,  0x9 0x30 0x9 0x31 0x16 0x0 0x80 0x26
IN , DATA0 , 0x0 , 0x1 ,  0xff 0x7f 0x75 0x10 0x95 0x2 0x81 0x6
IN , DATA1 , 0x0 , 0x1 ,  0x9 0x38 0x15 0x80 0x25 0x7f 0x75 0x8
IN , DATA0 , 0x0 , 0x1 ,  0x95 0x1 0x81 0x6 0x5 0xc 0xa 0x38
IN , DATA1 , 0x0 , 0x1 ,  0x2 0x95 0x1 0x81 0x6 0xc0 0xc0
SETUP , DATA0 , 0x0 , 0x1 ,  0x21 0xa 0x0 0x0 0x0 0x0 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x1 0x0 0x0 0x0 0x0 0x0
IN , DATA1 , 0x1 , 0x1 ,  0x0 0x1 0x0 0x0 0x0 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x1 0x0 0xff 0xff 0x0 0x0
IN , DATA1 , 0x1 , 0x1 ,  0x0 0x1 0x0 0x0 0x0 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x1 0x0 0xff 0xff 0x0 0x0
IN , DATA1 , 0x1 , 0x1 ,  0x0 0x1 0x0 0x0 0x0 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x2 0x0 0x0 0x0 0x0 0x0
IN , DATA1 , 0x1 , 0x1 ,  0x0 0x1 0x0 0xff 0xff 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x1 0x0 0x0 0x0 0x0 0x0
IN , DATA1 , 0x1 , 0x1 ,  0x0 0x2 0x0 0xff 0xff 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x1 0x0 0x0 0x0 0x0 0x0
IN , DATA1 , 0x1 , 0x1 ,  0x0 0x2 0x0 0xff 0xff 0x0 0x0
IN , DATA0 , 0x1 , 0x1 ,  0x0 0x2 0x0 0x0 0x0 0x0 0x0
...

Which beats looking through in this case >43K lines, some case like 200K lines like:

Time [s],PID,Address,Endpoint,Frame #,Data,CRC
6.191137532000000,SOF,,,0x441,,0x02
6.192137538000000,SOF,,,0x442,,0x0A
6.193137546000000,SOF,,,0x443,,0x15
6.194137554000000,SOF,,,0x444,,0x1A
6.195137560000000,SOF,,,0x445,,0x05
6.196137568000000,SOF,,,0x446,,0x0D
6.197137576000000,SOF,,,0x447,,0x12
6.198137584000000,SOF,,,0x448,,0x13
6.199137592000000,SOF,,,0x449,,0x0C
6.200137600000000,SOF,,,0x44A,,0x04
6.201137606000000,SOF,,,0x44B,,0x1B
6.201140706000000,SETUP,0x00,0x00,,,0x02
6.201143806000000,DATA0,,,,0x80 0x06 0x00 0x01 0x00 0x00 0x08 0x00,0x94EB
6.201152438000000,ACK,,,,,
6.201155838000000,IN,0x00,0x00,,,0x02
6.201159118000000,NAK,,,,,
6.201162172000000,IN,0x00,0x00,,,0x02
6.201165464000000,NAK,,,,,
6.201168406000000,IN,0x00,0x00,,,0x02
6.201171644000000,NAK,,,,,
6.201174572000000,IN,0x00,0x00,,,0x02
6.201177822000000,NAK,,,,,
6.201180806000000,IN,0x00,0x00,,,0x02
6.201184086000000,NAK,,,,,
6.201187038000000,IN,0x00,0x00,,,0x02
6.201190348000000,NAK,,,,,
6.201193272000000,IN,0x00,0x00,,,0x02
6.201196526000000,NAK,,,,,
6.201199438000000,IN,0x00,0x00,,,0x02

And this mouse produces a lot less data than others…

Unfortunately, we don’t have a concrete date for this yet, but we do want to eventually convert all of our existing analyzers over to FrameV2 at some point. I’m actually meeting with the team tomorrow and I can add this to our discussion list. I’ll keep you updated.

Thought I would mention that I still play with this off and on.

I need/needed to decode some more USB startup information for some devices.
In this case Trying to understand how some of the Wacom Tablets, work on Ubuntu and WIndows as to better handle them in the Teensy USBHost_t36 library for T3.6 and 4.x Teensies.

I just pushed up some changes to the HLA for processing my ALPHA branch of the LS FS LLA
The HLA ( KurtE/Saleae_USB_Data_Packets_HLA: USB Data Packets using my Alpha version of USB LS and FS (github.com))

Now added some processing of the Setup messages, to give more data, so I don’t have to do that manually.

Example for Wacom InTuos S startup on Ubuntu:
So now in Data Tables mode you see data like:

Or in Report mode you see stuff like:

23.91371954 , SETUP , 0x0 , 0x0 , <GET_DESCRIPTOR - DEVICE #:0 I:0x0 L:0x40> ,  0x80 0x6 0x0 0x1 0x0 0x0 0x40 0x0
23.91378884 , IN , 0x0 , 0x0 ,  ,  0x12 0x1 0x0 0x2 0x0 0x0 0x0 0x40 0x6a 0x5 0x74 0x3 0x11 0x1 0x1 0x2 0x3 0x1
23.99383474 , SETUP , 0x0 , 0x0 , <SET_ADDRESS I:0x0 L:0x0> ,  0x0 0x5 0xb 0x0 0x0 0x0 0x0 0x0
24.01368234 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - DEVICE #:0 I:0x0 L:0x12> ,  0x80 0x6 0x0 0x1 0x0 0x0 0x12 0x0
24.01375654 , IN , 0x0 , 0xb ,  ,  0x12 0x1 0x0 0x2 0x0 0x0 0x0 0x40 0x6a 0x5 0x74 0x3 0x11 0x1 0x1 0x2 0x3 0x1
24.01389326 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - DEVICE_QUALIFIER #:0 I:0x0 L:0xa> ,  0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
24.01420976 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - DEVICE_QUALIFIER #:0 I:0x0 L:0xa> ,  0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
24.01448886 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - DEVICE_QUALIFIER #:0 I:0x0 L:0xa> ,  0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
24.01478456 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - CONFIG #:0 I:0x0 L:0x9> ,  0x80 0x6 0x0 0x2 0x0 0x0 0x9 0x0
24.01485754 , IN , 0x0 , 0xb ,  ,  0x9 0x2 0x22 0x0 0x1 0x1 0x0 0x80 0xfa
24.0150589 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - CONFIG #:0 I:0x0 L:0x22> ,  0x80 0x6 0x0 0x2 0x0 0x0 0x22 0x0
24.01513256 , IN , 0x0 , 0xb ,  ,  0x9 0x2 0x22 0x0 0x1 0x1 0x0 0x80 0xfa 0x9 0x4 0x0 0x0 0x1 0x3 0x0 0x0 0x0 0x9 0x21 0x10 0x1 0x0 0x1 0x22 0xf7 0x2 0x7 0x5 0x81 0x3 0x40 0x0 0x1
24.0153685 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - STRING #:0 I:0x0 L:0xff> ,  0x80 0x6 0x0 0x3 0x0 0x0 0xff 0x0
24.0154375 , IN , 0x0 , 0xb ,  ,  0x4 0x3 0x9 0x4
24.01551848 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - STRING #:2 I:0x409 L:0xff> ,  0x80 0x6 0x2 0x3 0x9 0x4 0xff 0x0
24.01558854 , IN , 0x0 , 0xb ,  ,  0x12 0x3 0x49 0x0 0x6e 0x0 0x74 0x0 0x75 0x0 0x6f 0x0 0x73 0x0 0x20 0x0 0x53 0x0
24.01577458 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - STRING #:1 I:0x409 L:0xff> ,  0x80 0x6 0x1 0x3 0x9 0x4 0xff 0x0
24.01584456 , IN , 0x0 , 0xb ,  ,  0x1e 0x3 0x57 0x0 0x61 0x0 0x63 0x0 0x6f 0x0 0x6d 0x0 0x20 0x0 0x43 0x0 0x6f 0x0 0x2e 0x0 0x2c 0x0 0x4c 0x0 0x74 0x0 0x64 0x0 0x2e 0x0
24.01604396 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - STRING #:3 I:0x409 L:0xff> ,  0x80 0x6 0x3 0x3 0x9 0x4 0xff 0x0
24.01611358 , IN , 0x0 , 0xb ,  ,  0x1c 0x3 0x31 0x0 0x47 0x0 0x45 0x0 0x30 0x0 0x30 0x0 0x52 0x0 0x32 0x0 0x30 0x0 0x31 0x0 0x30 0x0 0x30 0x0 0x31 0x0 0x33 0x0
24.02185008 , SETUP , 0x0 , 0xb , <SET_CONFIGURATION I:0x0 L:0x0> ,  0x0 0x9 0x1 0x0 0x0 0x0 0x0 0x0
24.02231764 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - STRING #:3 I:0x409 L:0xff> ,  0x80 0x6 0x3 0x3 0x9 0x4 0xff 0x0
24.02238652 , IN , 0x0 , 0xb ,  ,  0x1c 0x3 0x31 0x0 0x47 0x0 0x45 0x0 0x30 0x0 0x30 0x0 0x52 0x0 0x32 0x0 0x30 0x0 0x31 0x0 0x30 0x0 0x30 0x0 0x31 0x0 0x33 0x0
24.02253482 , SETUP , 0x0 , 0xb , <HID SET_IDLE I:0x0 L:0x0> ,  0x21 0xa 0x0 0x0 0x0 0x0 0x0 0x0
24.02285118 , SETUP , 0x0 , 0xb , <GET_DESCRIPTOR - HID REPORT I:0x0 L:0x2f7> ,  0x81 0x6 0x0 0x22 0x0 0x0 0xf7 0x2
24.0229613 , IN , 0x0 , 0xb ,  ,  0x6 0xd 0xff 0x9 0x1 0xa1 0x1 0x85 0x10 0x9 0x20 0x35 0x0 0x45 0x0 0x15 0x0 0x25 0x1 0xa1 0x0 0x9 0x42 0x9 0x44 0x9 0x5a 0x25 0x1 0x75 0x1 0x95 0x3 0x81 0x2 0x95 0x2 0x81 0x3 0x9 0x32 0x9 0x36 0x95 0x2 0x81 0x2 0x95 0x1 0x81 0x3 0xa 0x30 0x1 0x65 0x11 0x55 0xd 0x47 0x60 0x3b 0x0 0x0 0x27
24.02303338 , IN , 0x0 , 0xb ,  ,  0x60 0x3b 0x0 0x0 0x75 0x18 0x95 0x1 0x81 0x2 0xa 0x31 0x1 0x47 0x1c 0x25 0x0 0x0 0x27 0x1c 0x25 0x0 0x0 0x81 0x2 0x9 0x30 0x55 0x0 0x65 0x0 0x26 0xff 0xf 0x75 0x10 0x81 0x2 0x75 0x8 0x95 0x6 0x81 0x3 0xa 0x32 0x1 0x25 0x3f 0x75 0x8 0x95 0x1 0x81 0x2 0x9 0x5b 0x9 0x5c 0x17 0x0 0x0 0x0 0x80
24.02310988 , IN , 0x0 , 0xb ,  ,  0x27 0xff 0xff 0xff 0x7f 0x75 0x20 0x95 0x2 0x81 0x2 0x9 0x77 0x15 0x0 0x26 0xff 0xf 0x75 0x10 0x95 0x1 0x81 0x2 0xc0 0x85 0x11 0x65 0x0 0x55 0x0 0x35 0x0 0x45 0x0 0x9 0x39 0xa1 0x0 0xa 0x10 0x9 0xa 0x11 0x9 0xa 0x12 0x9 0xa 0x13 0x9 0x15 0x0 0x25 0x1 0x75 0x1 0x95 0x4 0x81 0x2 0x95 0x4 0x81
24.02317888 , IN , 0x0 , 0xb ,  ,  0x3 0x75 0x8 0x95 0x7 0x81 0x3 0xc0 0x85 0x13 0x65 0x0 0x55 0x0 0x35 0x0 0x45 0x0 0xa 0x13 0x10 0xa1 0x0 0xa 0x3b 0x4 0x15 0x0 0x25 0x64 0x75 0x7 0x95 0x1 0x81 0x2 0xa 0x4 0x4 0x25 0x1 0x75 0x1 0x81 0x2 0x9 0x0 0x26 0xff 0x0 0x75 0x8 0x81 0x2 0x75 0x8 0x95 0x6 0x81 0x3 0xc0 0x9 0xe 0xa1
24.02324802 , IN , 0x0 , 0xb ,  ,  0x2 0x85 0x2 0xa 0x2 0x10 0x15 0x1 0x25 0x2 0x75 0x8 0x95 0x1 0xb1 0x2 0x85 0x3 0xa 0x3 0x10 0x15 0x0 0x26 0xff 0x0 0x95 0x1 0xb1 0x2 0x85 0x4 0xa 0x4 0x10 0x15 0x1 0x25 0x1 0x95 0x1 0xb1 0x2 0x85 0x7 0xa 0x9 0x10 0x15 0x0 0x26 0xff 0x0 0x95 0x1 0xb1 0x2 0xb1 0x3 0xa 0x7 0x10 0x9 0x0
24.02336154 , IN , 0x0 , 0xb ,  ,  0x27 0xff 0xff 0x0 0x0 0x75 0x10 0x95 0x2 0xb1 0x2 0x75 0x8 0x95 0x9 0xb1 0x3 0x85 0xc 0xa 0x30 0xd 0xa 0x31 0xd 0xa 0x32 0xd 0xa 0x33 0xd 0x65 0x11 0x55 0xd 0x35 0x0 0x46 0xc8 0x0 0x15 0x0 0x26 0x90 0x1 0x75 0x10 0x95 0x4 0xb1 0x2 0x85 0xd 0xa 0xd 0x10 0x65 0x0 0x55 0x0 0x45 0x0 0x25 0x1
24.02343068 , IN , 0x0 , 0xb ,  ,  0x75 0x8 0x95 0x1 0xb1 0x2 0x85 0x14 0xa 0x14 0x10 0x26 0xff 0x0 0x95 0xd 0xb1 0x2 0x85 0xcc 0xa 0xcc 0x10 0x95 0x2 0xb1 0x2 0x85 0x31 0xa 0x31 0x10 0x25 0x64 0x95 0x3 0xb1 0x2 0x95 0x2 0xb1 0x3 0xc0 0xa 0xac 0x10 0xa1 0x2 0x15

Which cuts and pastes nicely into Excel

Now back to understanding this device

2 Likes

In case anyone is following this, I thought I would mention I just pushed up some changes to both the low-level Analyzer as well as the high-level analyzer.

For example, with the LLA I updated the FrameV2 data such that many of the frame types, now use the generic “value” and “value” for their output data, instead of more descriptive names.

Likewise updated the “pid” value frame to use strings instead of the hex/decimal value. Lots easier to then search for things like: data or IN or OUT…

I also started some work to create frame V2s for Control Transfer mode.
Still WIP.

Note: the HLA still mostly works when the LLA is in packet mode. But started to have it handle at least the setup packets data. Still need to now have it process the results of the setup packets.

Actually, now pretty easy to use the data table to find stuff, like type setup and go directly to them.
In Packet mode:

When in "Control packet mode, the setup packet, additional data is now output using
frame “protocol”

I updated the HLA to be able to get the data from it as well. It was relying on the "data’ frames which are not output in this mode:

Example:

I also added some LLA support for the result data coming back and frames for how the data
was parsed:

But I have not yet taken advantage of this in the HLA.

Again, not sure if anyone else is playing with this or not, but thought I would post this update.

1 Like

@timreyes @markgarrison or…,

Sorry for interruption. Right now I am trying to extend my enhancements of the FrameV2 into the Control Transfers, and was wondering about how (or if) to properly give more formatted data in the V2.
For example below: I have added some V2 frames for the HID Descriptor.
RIght now I have the raw data:

That is for example if you see the bubble data created for V1 frame:

Now in the data table I have:

name type start_time duration value pid addr endpoint data bmRequestType bRequest wValue wIndex wLength value2 text
USB(alpha) LS and FS hiditem 24.0229653 2.08e-06 0x060DFF 0x00 0xFF0D
USB(alpha) LS and FS hiditem 24.0229674 1.34e-06 0x0901 0x00 0xFF0D

First row there…
But I would really like it to maybe fill in the “text” or “data” field with the formatted data, like:
"Usage Page (Vendor Usage 0xFF0D) "
The bubble text is created in the AnalyzerResults code, not in the Parse code.

Is there a clean way to do something like this? Have you done something similar in other
LLA? Again would be nice as then the HLA could get this information. Alternative to to duplicate the code in LLA.

Suggestions?

Thanks
Kurt

1 Like

I have done some serious hacking, such that I now have it like:

But it brings up a lot of hacking and also interesting questions, on how more advanced LLAs like the USB and probably others, which define protocols and the like that have frames with more complex data than Asynch Serial or SPI which output simple packets.

For example, is it expected that the Data Tables could/should contain at least as much information as is shown in the Bubble texts?

If other LLAs wish to extend FramV2 stuff like this, there are the issues like, how much code can it share with the code in the AnalyzerResults code?

How does the analyzer get access to the current display_base?

I put hacks in that a few of the functions update a global variable with the last display_base that was passed to it. And then I use that global to call those functions.

My code generating this with the USBControlTransfers.cpp did external declares of several of the helper functions within USBAnalyzerResults:


    extern DisplayBase last_display_base;
    extern std::string int2str_sal( const U64 i, DisplayBase base, const int max_bits );
    extern std::string GetSignedDataValue( const U8* pItem, DisplayBase display_base );
    extern std::string GetCollectionData( U8 data );
    extern std::string GetInputData( U8 data1, U8 data2 );
    extern std::string GetOutputAndFeatureData( U8 data1, U8 data2 );
    extern std::string GetUnitExponent( U8 data );
    extern std::string GetUnit( const U8* pItem );

Obviously would be better to have all of this within common header.

Next up extend a few others similar to this. For example, I have results coming back like:

But so far my generated text for this just has the field name, like:

Lots more potential playing.

But would be interesting to get your take on this.

EDIT: I have extended it for more data generated in the LLA in the Table view, like the above, for Results coming back from a Setup message, it now when it parses the data, the Text field is filled in with both the field name and the value of it. I have also extended the HLA to look at this data and in some cases change it’s bubble output, in other cases it outputs some of the additional information in the Terminal window. So for example you can simply copy and paste it into excel, and find data like:

23.91371954 SETUP 0x0 0x0 [GET_DESCRIPTOR - DEVICE #:0 I:0x0 L:0x40] 0x80 0x6 0x0 0x1 0x0 0x0 0x40 0x0
23.91378884 Result Report Start 0x0 0x0
23.91379414 Item 0x0 0x0 bcdUSB=0x200
23.91379548 Item 0x0 0x0 bDeviceClass=Deferred to Interface Descriptors
23.91379614 Item 0x0 0x0 bDeviceSubClass=0x0
23.91379682 Item 0x0 0x0 bDeviceProtocol=0x0
23.91379748 Item 0x0 0x0 bMaxPacketSize0=0x40
23.91379814 Item 0x0 0x0 idVendor=Wacom Co. Ltd
23.91379948 Item 0x0 0x0 idProduct=0x374
23.91380082 Item 0x0 0x0 bcdDevice=0x111
23.91380214 Item 0x0 0x0 iManufacturer=0x1
23.91380282 Item 0x0 0x0 iProduct=0x2
23.91380348 Item 0x0 0x0 iSerialNumber=0x3
23.91380414 Item 0x0 0x0 bNumConfigurations=0x1
23.91378884 IN 0x0 0x0 0x0 0x2 0x2 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x40 0x0 0x40 0x6a 0x5 0x5 0x6a 0x74 0x3 0x3 0x74 0x11 0x1 0x1 0x11 0x0 0x1 0x0 0x1 0x0 0x2 0x0 0x2 0x0 0x3 0x0 0x3 0x0 0x1 0x0 0x1
23.99383474 SETUP 0x0 0x0 SET_ADDRESS I:0x0 L:0x0] 0x0 0x5 0xb 0x0 0x0 0x0 0x0 0x0
24.01368234 SETUP 0x0 0xb [GET_DESCRIPTOR - DEVICE #:0 I:0x0 L:0x12] 0x80 0x6 0x0 0x1 0x0 0x0 0x12 0x0
24.01375654 Result Report Start 0x0 0xb
24.01376184 Item 0x0 0xb bcdUSB=0x200
24.01376318 Item 0x0 0xb bDeviceClass=Deferred to Interface Descriptors
24.01376384 Item 0x0 0xb bDeviceSubClass=0x0
24.0137645 Item 0x0 0xb bDeviceProtocol=0x0
24.01376518 Item 0x0 0xb bMaxPacketSize0=0x40
24.01376584 Item 0x0 0xb idVendor=Wacom Co. Ltd
24.01376718 Item 0x0 0xb idProduct=0x374
24.0137685 Item 0x0 0xb bcdDevice=0x111
24.01376984 Item 0x0 0xb iManufacturer=0x1
24.0137705 Item 0x0 0xb iProduct=0x2
24.01377118 Item 0x0 0xb iSerialNumber=0x3
24.01377184 Item 0x0 0xb bNumConfigurations=0x1
24.01375654 IN 0x0 0xb 0x0 0x2 0x2 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x40 0x0 0x40 0x6a 0x5 0x5 0x6a 0x74 0x3 0x3 0x74 0x11 0x1 0x1 0x11 0x0 0x1 0x0 0x1 0x0 0x2 0x0 0x2 0x0 0x3 0x0 0x3 0x0 0x1 0x0 0x1
24.01389326 SETUP 0x0 0xb [GET_DESCRIPTOR - DEVICE_QUALIFIER #:0 I:0x0 L:0xa] 0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
24.01420976 SETUP 0x0 0xb [GET_DESCRIPTOR - DEVICE_QUALIFIER #:0 I:0x0 L:0xa] 0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
24.01448886 SETUP 0x0 0xb [GET_DESCRIPTOR - DEVICE_QUALIFIER #:0 I:0x0 L:0xa] 0x80 0x6 0x0 0x6 0x0 0x0 0xa 0x0
24.01478456 SETUP 0x0 0xb [GET_DESCRIPTOR - CONFIG #:0 I:0x0 L:0x9] 0x80 0x6 0x0 0x2 0x0 0x0 0x9 0x0
24.01485754 Result Report Start 0x0 0xb
24.01486276 Item 0x0 0xb wTotalLength=0x22
24.01486408 Item 0x0 0xb bNumInterfaces=0x1
24.01486474 Item 0x0 0xb bConfigurationValue=0x1
24.01486542 Item 0x0 0xb iConfiguration=0x0
24.01486608 Item 0x0 0xb bmAttributes=0x80
24.01486676 Item 0x0 0xb bMaxPower=0xFA
24.01485754 IN 0x0 0xb 0x22 0x0 0x0 0x22 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x1 0x0 0x0 0x0 0x0 0x0 0x80 0x0 0x80 0x0 0xfa 0x0 0xfa
1 Like

Hi Kurt,

Awesome work!

This is the perfect example of hitting all of the limitations of our LLA and HLA system, and a good reference for us when we eventually get to LLAs V2.

I’ll address your smaller questions first:

For example, is it expected that the Data Tables could/should contain at least as much information as is shown in the Bubble texts?

This is a big problem with the current LLA system, as bubbles are linked to FrameV1, while the data table is linked to FrameV2. We want to get rid of frameV1 completely.
In the future, one thing we want to do is allow bubbles to contain a lot more information, but make them expandable. For example, the bubble text could be a fairly short summary, but a button on the bubble could expand all of the key/values attached to that frame.

If other LLAs wish to extend FramV2 stuff like this, there are the issues like, how much code can it share with the code in the AnalyzerResults code?

I’m not sure if I follow your question here. Is there something specific you had in mind?

How does the analyzer get access to the current display_base?

Today, the display_radix is only applied to the LLA bubble render function and to the export function. When the user changes to the display radix in the UI, the software does not re-run the analyzers. Instead, it just re-renders the bubbles on screen with the new radix. The data table columns are also re-rendered, and exactly how they render in each radix depends on the data type of that value field.

The display format used by FrameV2 is confusing, and needs work. We’re thinking of introducing a optional schema into the API in the future to give the author more control over how values are rendered.

If you want to re-generate frameV2 text strings based on the display radix, I suggest adding your own radix into the LLA settings. When the user changes any setting on the analyzer, it will cause the analyzer to re-start, re-creating all of the FrameV2 results. Ideally, this wouldn’t be required, but we don’t have a good way to handle non-number values in the data table.

Details on the display radix formating here.

Feel free to send us sample code of what you think you would like the API to look like to make this easier. Without deep diving into USB and what you’ve built so far, It’s hard for me to imagine what types of improvements we may want to add. (which I’d love to do, just once we have some time to work on improvements to LLAs and HLAs)

Thanks for all of the information,

I sort of figured a lot of things like bubbles were mainly tied with the V1 frames.

With the data tables, I have gotten some of the information into it. When in packet mode, I have things working reasonably well for my usages. But if you in control packet mode, I still have several holes where I am not capturing the V1 frames with V2 frames. This has to do with some of advanced parsing that happens in that mode. Both with bubbles and the save to file stuff.

Example Data table stuff from LLA

name type start_time duration value pid data wValue wIndex wLength value2 text
USB(alpha) LS and FS presult 23.9137941 1.34e-06 0x0200 0x02 0x19 bcdUSB=0x200
USB(alpha) LS and FS presult 23.9137955 6.59999998e-07 0x0000 0x01 0x1A bDeviceClass=Deferred to Interface Descriptors
USB(alpha) LS and FS presult 23.9137961 6.80000005e-07 0x0000 0x01 0x00 bDeviceSubClass=0x0
USB(alpha) LS and FS presult 23.9137968 6.59999998e-07 0x0000 0x01 0x00 bDeviceProtocol=0x0
USB(alpha) LS and FS presult 23.9137975 6.60000002e-07 0x0040 0x01 0x00 bMaxPacketSize0=0x40
USB(alpha) LS and FS presult 23.9137981 1.34e-06 0x056A 0x02 0x15 idVendor=Wacom Co., Ltd
USB(alpha) LS and FS presult 23.9137995 1.34e-06 0x0374 0x02 0x00 idProduct=0x374
USB(alpha) LS and FS presult 23.9138008 1.32e-06 0x0111 0x02 0x19 bcdDevice=0x111
USB(alpha) LS and FS presult 23.9138021 6.80000001e-07 0x0001 0x01 0x1C iManufacturer=0x1
USB(alpha) LS and FS presult 23.9138028 6.59999998e-07 0x0002 0x01 0x1C iProduct=0x2
USB(alpha) LS and FS presult 23.9138035 6.60000002e-07 0x0003 0x01 0x1C iSerialNumber=0x3
USB(alpha) LS and FS presult 23.9138041 6.79999997e-07 0x0001 0x01 0x00 bNumConfigurations=0x1

The last column (text) is generated like the bubbles are. Alternatively, I could have output a textual name and a value and compose that later.

Alternatively, one could replicate all of that code in python in an HLA. I have done some of that as to get more textual information about some messages like Setups.

name type start_time duration value pid data wValue wIndex wLength value2 text
USB Data Packets HLA USB Text 24.0136823 9.16e-06 SETUP 0x80 0x6 0x0 0x1 0x0 0x0 0x12 0x0 [GET_DESCRIPTOR - DEVICE #:0 I:0x0 L:0x12]

Sorry I know that this is unclear. Not really sure myself. As there are several possible ranges of solutions. For example:

Simply hack it: That is when generating the table with V2 information for control packets, I found several helper functions in USBAnalyzerResults. So I simply added extern defines to use them. Should be in headers…

// Hack to use some of the formatting code in USBAnalyzerResults and other
extern DisplayBase last_display_base;
extern std::string int2str_sal( const U64 i, DisplayBase base, const int max_bits );
extern std::string GetSignedDataValue( const U8* pItem, DisplayBase display_base );
extern std::string GetCollectionData( U8 data );
extern std::string GetInputData( U8 data1, U8 data2 );
extern std::string GetOutputAndFeatureData( U8 data1, U8 data2 );
extern std::string GetUnitExponent( U8 data );
extern std::string GetUnit( const U8* pItem );

Alternative bubbles and data table share same code. Probably back to your V2, where everything is a V2 frame.

Alternative: Make real simple version of LLA - example remove Control… Move all of the smarts into Python LLA. (Could leave lots of in in HLA and replicate). As I mentioned I have replicated some of it.
But then maybe I want different filtering. So does that mean we have 5 HLAs all duplicating such code? Or can/should there be HHLAs which take inputs from HLAs?

I think this is going to take a team of people who fully understand the ins and outs of your setup. Hopefully with feedback from some of us who are playing with it.

So far I have been able to fumble my way through some of this more complex stuff. But can not figure out the simple things.

Like with the HLA, I can control the terminal output, and do a pretty good job of formatting it, such that I can make use of it.

29.11173622 ;HID Item; 0x0 ; 0xb ;     Report ID (0xE3)
29.11173756 ;HID Item; 0x0 ; 0xb ;     Usage (Usage Page=Vendor Usage 0xFF0D ID=0x01)
29.11173888 ;HID Item; 0x0 ; 0xb ;     Report count (0x02)
29.11174088 ;HID Item; 0x0 ; 0xb ;     Feature (Data,Variable,Absolute,No wrap,Linear,Preferred State,No Null position,Non Volatile,Bit Field)
29.1117422 ;HID Item; 0x0 ; 0xb ;     Report ID (0xE4)
29.11174356 ;HID Item; 0x0 ; 0xb ;     Usage (Usage Page=Vendor Usage 0xFF0D ID=0x01)
29.11174488 ;HID Item; 0x0 ; 0xb ;     Report count (0xFF)
29.11174696 ;HID Item; 0x0 ; 0xb ;     Feature (Data,Variable,Absolute,No wrap,Linear,Preferred State,No Null position,Non Volatile,Bit Field)
29.1117483 ;HID Item; 0x0 ; 0xb ; End Collection
29.11170818 ; IN ; 0x0 ; 0xb ;  ;  0x85 0xdf 0x9 0x1 0x96 0x22 0x0 0xb1 0x2 0x85 0xe0 0x9 0x1 0x96 0x1 0x0 0xb1 0x2 0x85 0xe1 0x9 0x1 0x96 0x2 0x0 0xb1 0x2 0x85 0xe2 0x9 0x1 0x96 0x2 0x0 0xb1 0x2 0x85 0xe3 0x9 0x1 0x96 0x2 0x0 0xb1 0x2 0x85 0xe4 0x9 0x1 0x96 0xff 0x1 0xb1 0x2 0xc0
29.11294998 ; SETUP ; 0x0 ; 0xb ; [GET_REPORT - FEATURE # 12 I:0x0 L:0x9] ;  0xa1 0x1 0xc 0x3 0x0 0x0 0x9 0x0
29.11311778 ; SETUP ; 0x0 ; 0xb ; [GET_REPORT - FEATURE # 12 I:0x0 L:0x9] ;  0xa1 0x1 0xc 0x3 0x0 0x0 0x9 0x0
29.11328266 ; SETUP ; 0x0 ; 0xb ; [GET_REPORT - FEATURE # 12 I:0x0 L:0x9] ;  0xa1 0x1 0xc 0x3 0x0 0x0 0x9 0x0
29.11344972 ; SETUP ; 0x0 ; 0xb ; [GET_REPORT - FEATURE # 12 I:0x0 L:0x9] ;  0xa1 0x1 0xc 0x3 0x0 0x0 0x9 0x0
29.22294964 ; IN ; 0x1 ; 0xb ;  ;  0x10 0x40 0x54 0x2 0x0 0x26 0x11 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x3e 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
29.22394974 ; IN ; 0x1 ; 0xb ;  ;  0x10 0x40 0x59 0x2 0x0 0x8 0x11 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x37 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
29.22494962 ; IN ; 0x1 ; 0xb ;  ;  0x10 0x40 0x59 0x2 0x0 0xfc 0x10 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x32 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
29.22594966 ; IN ; 0x1 ; 0xb ;  ;  0x10 0x60 0x8a 0x2 0x0 0xeb 0x10 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x29 0x11 0x3d 0x80 0x15 0x62 0x8 0x10 0x0 0x62 0x8

But who (what code) does the output of the LLA? And how to change it into something readable and usable?

NCPID SOFFrame # \x01ICRC OK \x1DEOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01JCRC OK \x15EOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01KCRC OK \nEOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01LCRC OK \x05EOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01MCRC OK \x1AEOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01NCRC OK \x12EOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01OCRC OK \rEOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01PCRC OK \x10EOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01QCRC OK \x0FEOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01RCRC OK \x07EOPSYNCPID INAddress=\x0B Endpoint=\x01CRC OK \x12EOPSYNCPID NAKEOPSYNCPID SOFFrame # \x01SCRC OK \x18EOPSYNCPID INAddress=\x0

Note: I go in spurts on playing with this stuff. Usually when I trying to figure out how to make a different device work when plugged into the USBHost port of a Teensy 3.6 or 4.x. Often times where I will see what the device does when plugged in to a Windows and/or Ubuntu machine and then compare to what we are doing on the Teensy.