how to usb device serial output connect to teensy 4.0 usb

So below what I get. I do think the problem is the initialisation of the device after the first handshake. It accepts few bytes, but after go to sleep. At the end it is trying to write data to 70x320 section of display so quite lot of data.

How should I write big amount of data, 16200 bytes in this case. Now it is just write a byte at the time.

This part is unclear

USBSerial, rxep=1(512), txep=1(512)
rx buffer size:1024
tx buffer size:1024

Can I write 512 or 1024 at one write?

I assume this is no response from the device? This continues for ever (or maybe the 16200 bytes) They come at fast rate difficult to say, but maybe several 100 per second.

What does the TX:moar data!!!! mean, and what is the tx2.




txtimer
TX data (14) 82 FF 00 00 00 00 00 00 3F 48 00 00 00 00
tx1:
tx1:
tx1:
TX:moar data!!!!
tx2:
TX:moar data!!!!
tx1:


At the start when setting up the USB there is the

Descriptor 36 = ???
Descriptor 36 = ???
Descriptor 36 = ???
Descriptor 36 = ???

Is this something to worry about. Is it missing some service the device would like to have?



Code:
USB Host Testing - Serial
USB2 PLL running
 reset waited 6
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 20003000
periodictable = 20003000
port change: 10001803
    connect
  begin reset
port change: 18001205
  port enabled
  end recovery
new_Device: 480 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 00 02 EF 02 01 40 C2 2E 04 00 00 01 01 02 03 01 
    VendorID = 2EC2, ProductID = 0004, Version = 0100
    Class/Subclass/Protocol = 239 / 2 / 1
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: Loupedeck
enumeration:
Product: Loupedeck Live
enumeration:
Serial Number: LDD2001014022200100398B2002
enumeration:
Config data length = 75
enumeration:
Configuration Descriptor:
  09 02 4B 00 02 01 04 A0 32 
    NumInterfaces = 2
    ConfigurationValue = 1
  08 0B 00 02 02 02 00 05 
    Interface Association = 0 through 1
    Class / Subclass / Protocol = 2 / 2 / 5
  09 04 00 00 01 02 02 01 05 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 2 / 2 / 1
  05 24 00 10 01 
  05 24 01 03 01 
  04 24 02 06 
  05 24 06 00 01 
  07 05 82 03 40 00 07 
    Endpoint = 2 IN
    Type = Interrupt
    Max Size = 64
    Polling Interval = 7
  09 04 01 00 02 0A 00 00 06 
    Interface = 1
    Number of endpoints = 2
    Class/Subclass/Protocol = 10 / 0 / 0
  07 05 01 02 00 02 01 
    Endpoint = 1 OUT
    Type = Bulk
    Max Size = 512
    Polling Interval = 1
  07 05 81 02 00 02 01 
    Endpoint = 1 IN
    Type = Bulk
    Max Size = 512
    Polling Interval = 1
enumeration:
USBHub memory usage = 960
USBHub claim_device this=20004620
USBHub memory usage = 960
USBHub claim_device this=200049E0
HIDParser claim this=200031E0
HIDParser claim this=200038A0
HIDParser claim this=20003F60
USBSerial(512)claim this=20004F20
vid=2EC2, pid=4, bDeviceClass = 239, bDeviceSubClass = 2, bDeviceProtocol = 1
08 0B 00 02 02 02 00 05 09 04 00 00 01 02 02 01 05 05 24 00 10 01 05 24 01 03 01 04 24 02 06 05 24 06 00 01 07 05 82 03 40 00 07 09 04 01 00 02 0A 00 00 06 07 05 01 02 00 02 01 07 05 81 02 00 02 01 
Descriptor 11 = IAD
Descriptor 4 = INTERFACE
HIDParser claim this=200031E0
HIDParser claim this=200038A0
HIDParser claim this=20003F60
USBSerial(512)claim this=20004F20
vid=2EC2, pid=4, bDeviceClass = 239, bDeviceSubClass = 2, bDeviceProtocol = 1
09 04 00 00 01 02 02 01 05 05 24 00 10 01 05 24 01 03 01 04 24 02 06 05 24 06 00 01 07 05 82 03 40 00 07 09 04 01 00 02 0A 00 00 06 07 05 01 02 00 02 01 07 05 81 02 00 02 01 
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
HIDParser claim this=200031E0
HIDParser claim this=200038A0
HIDParser claim this=20003F60
USBSerial(512)claim this=20004F20
vid=2EC2, pid=4, bDeviceClass = 239, bDeviceSubClass = 2, bDeviceProtocol = 1
09 04 01 00 02 0A 00 00 06 07 05 01 02 00 02 01 07 05 81 02 00 02 01 
len = 23
USBSerial, rxep=1(512), txep=1(512)
  rx buffer size:1024
  tx buffer size:1024
new_Pipe
new_Pipe
Control - CDCACM LINE_CODING
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
control callback (serial) 4
Control - 0x21,0x22, 0x3
control callback (serial) 0
*** Device USERIAL 2ec2:4 - connected ***
  manufacturer: Loupedeck
  product: Loupedeck Live
  Serial: LDD2001014022200100398B2
control callback (serial) 6
CDCACM setup: 00 10 27 00 00 00 08 
control callback (serial) 4
Control - 0x21,0x22, 0x3
userial started

Request1 WS 

GET /index.html
HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: 123abc

control callback (serial) 0
txtimer
  TX data (98) 47 45 54 20 2F 69 6E 64 65 78 2E 68 74 6D 6C 0D 0A 48 54 54 50 2F 31 2E 31 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 55 70 67 72 61 64 65 0D 0A 55 70 67 72 61 64 65 3A 20 77 65 62 73 6F 63 6B 65 74 0D 0A 53 65 63 2D 57 65 62 53 6F 63 6B 65 74 2D 4B 65 79 3A 20 31 32 33 61 62 63 0D 0A 0D 0A 00 
tx1:
rx token: 817F8100 transfer length: 512 len:129 - 48 54
rx: 48 54 54 50 2F 31 2E 31 20 31 30 31 20 53 77 69 74 63 68 69 6E 67 20 50 72 6F 74 6F 63 6F 6C 73 0D 0A 55 70 67 72 61 64 65 3A 20 77 65 62 73 6F 63 6B 65 74 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 55 70 67 72 61 64 65 0D 0A 53 65 63 2D 57 65 62 53 6F 63 6B 65 74 2D 41 63 63 65 70 74 3A 20 41 4C 74 6C 5A 6F 39 46 4D 45 55 45 51 6C 65 58 4A 6D 71 2B 2B 75 6B 55 51 31 73 3D 0D 0A 0D 0A 

Response1 

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ALtlZo9FMEUEQleXJmq++ukUQ1s=

TEST 

START 

txtimer
  TX data (14) 82 FF 00 00 00 00 00 00 3F 48 00 00 00 00 
tx1:
tx1:
tx1:
TX:moar data!!!!
tx2:
TX:moar data!!!!
tx1:
TX:moar data!!!!
tx2:
TX:moar data!!!!
tx1:
TX:moar data!!!!
tx2:
TX:moar data!!!!


This is disconnecting the devise (unplug USB) from the previous state

Code:
TX:moar data!!!!
tx2:
TX:moar data!!!!
tx1:
TX:moar data!!!!
tx2:
TX:moar data!!!!
tx1:
TX:moar data!!!!
port change: 1C00100A
    disconnect
disconnect_Device:
USBDriver (available_drivers) list: 20004620 -> 200049E0 -> 200031E0 -> 200038A0 -> 20003F60
USBDriver (dev->drivers) list: 20004F20
disconnect driver 20004F20
USBDriver (available_drivers) list: 20004F20 -> 20004620 -> 200049E0 -> 200031E0 -> 200038A0 -> 20003F60
delete_Pipe 20005000
  remove QH from async schedule
  Free transfers
    * 536883488 * remove * free
    * 536883424 * remove * defer free until QH
    * 536883616
    * 536891808
  Free transfers attached to QH
    * 536883424
    * 536891872
* Delete Pipe completed
delete_Pipe 20004FA0
  remove QH from async schedule
  Free transfers
    * 536883616 * remove * free
    * 536891808 * remove * defer free until QH
  Free transfers attached to QH
    * 536891808
    * 536883552
* Delete Pipe completed
delete_Pipe 20003080
  shut down async schedule
  Free transfers
  Free transfers attached to QH
    * 536891744
* Delete Pipe completed
removed Device_t from devlist
  disable
txtimer
 *** No buffers ***
 
Last edited:
This is when the devise encoder is rotated, how the device reports it

Code:
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05


The rx: 82 05 is websocket type message, the 0x80 Indicates that this is the final fragment in a message., 0x02 * %x2 denotes a binary frame and 0x05 length

For some reason the data starts also with length but ok, so this is what the data means 82, 5, 5, 1, 0, 6, 1, Button number: 6, Encoder: 1

So this is all ok and the incoming data is easy to parse.

But what is the rx token: 81FB8100 transfer length: 512 len:5 - 5 1. ? if I want to do the same when sending do I need to do something? and it seems it wants to send the header and data separate, so how to do that

When I try to send data I get this


txtimer
TX data (14) 82 FF 00 00 00 00 00 00 3F 48 00 00 00 00
tx1:
tx1:
tx1:
TX:moar data!!!!
tx2:
TX:moar data!!!!


So the header and data is send as one (the above is actually just long format header, but if I add data to it, it just continues after), I tried also sending them with delay, and they appear as two package if with long enough delay. but is it the same as if separated with token like the rx? and the debug does not ever print anything on tx1: ?

So could there be some problem on the USB serial driver on sending the data?

Could this be some flow control that needs to be implemented, or is not working as it should when sending? referring to here https://felhr85.net/2016/02/13/usbserial-now-allows-using-flow-control-signals-rtscts-and-dtrdts/


Code:
"Finally I’ve managed to get some time to implement hardware flow control in UsbSerial! It is probably the most trickiest part of treating with these chipsets because every single one handles this in a very particular manner."
 
Last edited:
USB Serial - works like Serial from Teensy to PC...

64 versus 512 - A lot of serial devices use the slower speed and 64 byte packets, where this one is setup with the 512 byte packets, that is where 512 comes into play.

Regardless of how you do your writes, like 1 byte or 40 bytes... they simply are put into a buffer. When the buffer fills, the whole packet is sent with all of the data.
If there is stuff in the buffer and you have not sent any more data for some period of time, it will then send out a partial buffer with the currently cached data.

If you try to write out more data than can be held in the big buffer, your code will be held up, until there is enough room to queue up the remaining parts of your request.

If you don't want to wait for a buffer to fill or timeout, you can tell the system to do it now, by calling the flush() method.
The age-old tradeoff between latency and throughput. That is telling it to send 5 bytes now, takes as much time to send those 5 bytes as it takes to send full packet of 512 bytes.

But for example, if I am doing something like talking to servos, which have distinct packets, I will call flush() each time I comlete a logical packet.

As for Flow control, this is can be important if for example your device is something like a USB to serial adapter where the adapter is trying to output at lets sayd 9600 baud, and only
internally has buffer space for X bytes.
 
Thanks, I will test the flush().

Any idea what the Descriptor 36 = ??? is

Code:
vid=2EC2, pid=4, bDeviceClass = 239, bDeviceSubClass = 2, bDeviceProtocol = 1
09 04 00 00 01 02 02 01 05 05 24 00 10 01 05 24 01 03 01 04 24 02 06 05 24 06 00 01 07 05 82 03 40 00 07 09 04 01 00 02 0A 00 00 06 07 05 01 02 00 02 01 07 05 81 02 00 02 01 
Descriptor 36 =  ???

(couple of posts up the complete output)


Yesterday I was looking the output with google and looked like the serial port is 9600 8N2, so trying with that, but what does that mean in terms of USB Serial. There is big images that need to be updated to the device and for sure they use faster rate.
 
First fast test, and the flush does not seem to help.

But the tx: should it not have the outgoing data after it when debug is on?

Code:
USBSerialBase::flush - Empty
USBSerialBase::flush completed
txtimer
  TX data (6) 82 93 00 00 00 00 
tx1:
USBSerialBase::flush completed
txtimer
  TX data (19) 13 0E 01 3D A8 1C 9B A7 2A 8C 87 D4 F6 A1 35 A2 89 06 6C 
tx1:
USBSerialBase::flush completed
txtimer
  TX data (6) 82 93 00 00 00 00 
tx1:
USBSerialBase::flush completed

This is how incoming data looks like when debug is on

Code:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ALtlZo9FMEUEQleXJmq++ukUQ1s=

rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
�5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
 
With many of these things it is sometimes hard to understand fully what messages are without the context.

As for descriptor 36 (0x24) no idea...
If you look at USB documents, I don't see anywhere that one is defined... Note this is an area that Paul has mostly touched, but:
https://www.engineersgarage.com/usb-descriptors-and-their-types-part-3-6/
Shows the standard ones I know of.

But you might take a look through the USB documents. https://usb.org/documents and see if you find anything.

The flush code, in here simply set the timeout to 0, so that it would send it then.

As for the debug output, it is often in which state helped at the time to figure out what is going on.
The TX Data: was I am assuming the current data when the timer/flush code forced out the partial packet
 
I did look for those, but do not know what to make of it.

My quest was that the 36 ??? comes from Serial.h

Code:
else if (type == 0x24) {  // 0x24 = CS_INTERFACE, 
				uint32_t subtype = p[2];
				print("    CS_INTERFACE - subtype: ", subtype);
				if (len >= 4) print(" ", p[3], HEX);
				if (len >= 5) print(" ", p[4], HEX);
				if (len >= 6) print(" ", p[5], HEX);
				switch (subtype) {
					case 0: println(" - Header Functional Descriptor"); break;
					case 1: println(" - Call Management Functional"); break;
					case 2: println(" - Abstract Control Management"); break;
					case 4: println(" - Telephone Ringer"); break;
					case 6: println("  - union Functional"); break;
					default: println(" - ??? other"); break;

So // 0x24 = CS_INTERFACE, subtype 0x24 (36) and I did look for that and as understood from CSC120 table 13 1Dh-7Fh RESERVED (future use) so not RESERVED (vendor specific) but future use?

I did not look for the tx1: but assume it does the same print as rx: but now looking serial.h seems to be just println("tx1:"); but not sure if the later code should print something.did not look that deep.

I still do think that the Loupe deck waits some end of data packet etc handshake. Otherwise the header could well be found in data and cause problems did not see exactly but the image that comes after header is big maybe 300kbytes. The header is simple uint8_t HEADER_LONG[]={ 0x82, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x48, 0x00, 0x00, 0x00, 0x00};

The header is a bit suspicious, for some reason the examples I have found use this longer format that includes mask, but mask is the 4 last 0x00 so I assume not doing anything.

But even the simplest and sorted messages do not go trough, or cause any response.

I will not install on this computer Wireshark, but will during weekend have access to an other computer where that can be installed, so maybe that will help seeing how the communication is with the device SW.
 
Again context: You showed the message:
Descriptor 36 = ???

I believe this is printed from within enumeration.cpp
Code:
void USBHost::claim_drivers(Device_t *dev)
{
	USBDriver *driver, *prev=NULL;

	// first check if any driver wishes to claim the entire device
	for (driver=available_drivers; driver != NULL; driver = driver->next) {
		if (driver->device != NULL) continue;
		if (driver->claim(dev, 0, enumbuf + 9, enumlen - 9)) {
			if (prev) {
				prev->next = driver->next;
			} else {
				available_drivers = driver->next;
			}
			driver->device = dev;
			driver->next = NULL;
			dev->drivers = driver;
			return;
		}
		prev = driver;
	}
	// parse interfaces from config descriptor
	const uint8_t *p = enumbuf + 9;
	const uint8_t *end = enumbuf + enumlen;
	while (p < end) {
		uint8_t desclen = *p;
		uint8_t desctype = *(p+1);
		print("Descriptor ");
		print(desctype);
		print(" = ");
		if (desctype == 4) println("INTERFACE");
		else if (desctype == 5) println("ENDPOINT");
		else if (desctype == 6) println("DEV_QUALIFIER");
		else if (desctype == 7) println("OTHER_SPEED");
		else if (desctype == 11) println("IAD");
		else if (desctype == 33) println("HID");
		else println(" ???");
...

You are right and we have ran into them before in Serial.cpp and we skip over them. But do try to print out some data. The code was added as to keep the enumeration code in serial from bailing before it found the endpoints
 
As I mentioned, it is ignored and not coming from Serial:

If you are talking about:
Code:
Descriptor 11 = IAD
Descriptor 4 = INTERFACE
HIDParser claim this=200031E0
HIDParser claim this=200038A0
HIDParser claim this=20003F60
[COLOR="#008000"]USBSerial(512)claim this=20004F20
vid=2EC2, pid=4, bDeviceClass = 239, bDeviceSubClass = 2, bDeviceProtocol = 1
09 04 00 00 01 02 02 01 05 05 24 00 10 01 05 24 01 03 01 04 24 02 06 05 24 06 00 01 07 05 82 03 40 00 07 09 04 01 00 02 0A 00 00 06 07 05 01 02 00 02 01 07 05 81 02 00 02 01 [/COLOR]
[COLOR="#FF0000"]Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???
Descriptor 36 =  ???[/COLOR]
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
HIDParser claim this=200031E0
HIDParser claim this=200038A0
HIDParser claim this=20003F60
USBSerial(512)claim this=20004F20
vid=2EC2, pid=4, bDeviceClass = 239, bDeviceSubClass = 2, bDeviceProtocol = 1
09 04 01 00 02 0A 00 00 06 07 05 01 02 00 02 01 07 05 81 02 00 02 01 
len = 23
USBSerial, rxep=1(512), txep=1(512)
  rx buffer size:1024
  tx buffer size:1024
new_Pipe
new_Pipe
Control - CDCACM LINE_CODING
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
control callback (serial) 4
Control - 0x21,0x22, 0x3
control callback (serial) 0
The ones in RED, these are not coming from Serial, but instead from the enumeration code.
The stuff in green is from Serial claim code.

If you look at that code, you will see that the code that knowns something maybe about:
(type == 0x24) { // 0x24 = CS_INTERFACE,
Is under the if: if ((dev->bDeviceClass == 2) && (dev->bDeviceSubClass == 0)) {
Which is checking to see if your Serial device is a CDC/ACM which is not:


But at that point we are asking if it wishes to claim at the device level, as the previous debug out: bDeviceClass = 239, bDeviceSubClass = 2,
It then bails from here as it then wants to claim at the Interface level.

Then the enumeration code goes through the descriptors prints out those messages and then finds an interface descriptor, and then calls off again to the claim methods for each of the objects, and at this point the Serial object claims it.

And ...

So, I am not sure if that has any relationship to the issues you are having.
 
What is the token on the incoming data printout?

Code:
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05

i.e is it something to separate received packages? Some underlying USB communication providing that? My thinking was that maybe the Descriptor 36 = ??? does not get initialised correctly and maybe because of that the other end does not get this message separator.

When data is received I just read all incoming bytes and detect the sequence 82, 5, 5, 1, 0, 6, 1,, i.e x82 at start, 2 times indication of length of the data package (5 second 5 is the first byte of data)

That works good for short messages and though on some messages it is possible to have 0x82 also on data, it will never follow two times with same number.

It would be tough easier to get the header and data separated like this

rx: 82 05
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01

And I think also necessary when data is very long, so I am assuming on Loopdeck end it would be very useful to detect the sent packages, to get the header and data separated.

Also the question how could that be done for the received data. Now I see it on the debug print, but do not know how it could be detected on code?
 
Last edited:
The token is the QTD.token. ;)

In current IMXRT 1062RM I believe the section is 42.5.2.5.3 - But you would probably also need to read several other sections of it.

But the interesting point at this point is the token inplies how many bytes were transferred, or more specifically on how many more bytes that transfer could have received.
That is we queued up the receive transfer saying it can receive 512 bytes. If it is sent with less than that could have fit.
So from that you can compute how many that were actually transferred.
Which is why you see lines like: uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);

Now as for how you wish to pack the data into the physical USB packets is up to you.
For example you could do something like:

Code:
uint8_t mystr[]r="ABCDEFG";
for (uint8_t i = 0; i < sizeof(mystr); i++) {
    userial->write(mystr[i]);
    userial->flush();
}
And you would output one byte per USB packet.
Versus all of the data in one:
Code:
userial->write(mystr);
userial->flush();
Which will write it in one packet.

Without the flush it will continue to try to add data to packet until either full or timeout or flush

So yes you could choose to break up your writes to have the header go out first, do flush after that
then output the data, do another flush, if you need trailing stuff, output it and do another flush....

But I would hope that would not be necessary:
That is you hope you simply pack up the data and send it
 
I got confirmation from a code developer who's code I have used as the interface documentation, that it should work also with 0.2.8 (Newest FW that my device has and can not be downgraded)

One of the problems is that the Javascript etc codes that I have been using as interface definition use the USB communication services that computer provide. and the question is does the Teensy USB Host provide the same and can I use them correctly. Expesially as the "interface specifications" are with language I do not understand, very difficult for me to read Javascrit, Pyhton etc.

I did notice that the token implies lenght somehow, uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); but still do not understand what and why it is, and how could I catch it from my code to separate the incoming packets.

I will do some more testing with the flush for sending.

What I still wonder does the USB Serial have RTS/CTS and DTR/DSR and are they used here, and if so how. also unclear what affect Baud 9600 8N2 has on USB serial communication.

The thing is that this is probably something very simple and stupid, when finally figuring it out and that I have spend tens of hours on it already.
 
I am trying now the serial flush

This

Code:
   uint8_t HEADER6 []  = {0x82, 0x80+sizeof(DATA6 ), 0x00, 0x00, 0x00, 0x00};
   uint8_t   DATA6 []    = {0x03, 0x03, 0x06};

   Serial.println("START \r\n");

   userial.flush(); delay(10); 
   userial.write(HEADER6 , sizeof(HEADER6 ));
   userial.flush(); 
   userial.write(DATA6 , sizeof(DATA6 ));
   userial.flush();

   delay(10);Serial.println("DONE \r\n");
   
   delay(10);  while (userial.available()) {Serial.print("RECEIVED: ");Serial.print(userial.read(), HEX);   }
gives

Code:
START 

USBSerialBase::flush - Empty
USBSerialBase::flush completed
USBSerialBase::flush completed
txtimer
  TX data (9) 82 83 00 00 00 00 03 03 06 
tx1:
DONE

Soo despite using the flush it seems to send the header and data as one package TX data (9) 82 83 00 00 00 00 03 03 06 ?


If I put delay in between header and data like this

Code:
   userial.write(HEADER6 , sizeof(HEADER6 ));
   userial.flush(); 
   delay(1);
   userial.write(DATA6 , sizeof(DATA6 ));
   userial.flush();

then I get

Code:
START 

USBSerialBase::flush - Empty
USBSerialBase::flush completed
txtimer
  TX data (6) 82 83 00 00 00 00 
tx1:
USBSerialBase::flush completed
txtimer
  TX data (3) 03 03 06 
tx1:
DONE

But still no response.
 
Again I believe that maybe this might be barking up the wrong tree: That is the breaking up of message into two physical USB packets, but I have been wrong before.

But: in your RX case:
Code:
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05 
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01 
82, 5, 5, 1, 0, 6, 1,   	 Button number: 6, Encoder: 1
rx token: 1FE8100 transfer length: 512 len:2 - 82 5
rx: 82 05

You showed it broken into two parts: 7 bytes and 2 bytes.

But your TX you are doing 6 and 3.
Code:
  TX data (6) 82 83 00 00 00 00 
  TX data (3) 03 03 06
Not sure that would matter, but ????

Again I don't know your device, or if there is a standard or reverse engineering doc or...Don't know JavaScript. I am getting better at Python, as long as I have
examples of in front of me, plus google...

So I would not know if what you are sending: But from your previous talking about RX
The rx: 82 05 is websocket type message, the 0x80 Indicates that this is the final fragment in a message., 0x02 * %x2 denotes a binary frame and 0x05 length

For some reason the data starts also with length but ok, so this is what the data means 82, 5, 5, 1, 0, 6, 1, Button number: 6, Encoder: 1

So this is all ok and the incoming data is easy to parse.

But what is the rx token: 81FB8100 transfer length: 512 len:5 - 5 1. ? if I want to do the same when sending do I need to do something? and it seems it wants to send the header and data separate, so how to do that
So what is: 0x82 0x83 mean? Does it imply that you are needing to send 131 bytes of data?
If so you are only sending 7 bytes?
And what do those 7 bytes mean?

In the RX case: You show: 82, 5, 5, 1, 0, 6, 1, Button number: 6, Encoder: 1
And so far you have mentioned what some of these bytes mean, but what do the ones mean in RED?
Are they telling what the last two bytes are? Is there some form of checksum or the like?

I know probably not much help, but not sure what else to say
 
So what could, should be done regarding the 0x24 (36)

Regarding this question, the short answer is to ignore it. (which I believe it what the code is doing)

A longer answer, which could be seen as either cynical or pragmatic, is the USB class specifications are a perfect example of "design by committee". Aside from the fact that they literally are created by committees, they include a pretty large number of optional features and specs meant to satisfy a broad range of stakeholders... pretty much the traditional understanding of "design by committee".

From a pragmatic point of view, the specs are written before Microsoft and others create their drivers. And over the years, those drivers change, often with early versions more narrowly focused on certain features or initially tested with only 1 device which exists at the time. So as a result, many USB devices are created with essentially meaningless USB descriptors meant only for compatibility with certain USB device drivers in old versions of Windows, MacOS and sometimes even Linux.

In the context of a generic USB-Serial converter, or USB Serial implemented by Teensy or other microcontrollers (using CDC ACM protocol), it's meaningless. If you really wanted to know what it was originally intended to mean, by the committee who wrote the specs before any devices or device drivers existed, you could go to www.usb.org and download the communication class spec. But I can tell you from experience (I have read that spec...) to prepare to be underwhelmed. It's quite vague and ACM seems to be a sort of "catch all" for serial devices which aren't known to be specific types of modems or other telco equipment, so highly specific answers are nowhere to be found. It really is just meaningless cruft which almost all CDC ACM devices have to include because so drivers on certain operating systems recognize it as a serial device.
 
Trying to answer more specific questions....


I did notice that the token implies lenght somehow, uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); but still do not understand what and why it is, and how could I catch it from my code to separate the incoming packets.

With USB Serial communication, the application level software does not concern itself with how the USB device drivers divy the byte stream into packets. It is much like how a web browser and web server do not concern themselves with how the networking stack puts their bytes into TCP/IP packets. To the application level software, it is simply a stream of bytes.


What I still wonder does the USB Serial have RTS/CTS and DTR/DSR and are they used here, and if so how. also unclear what affect Baud 9600 8N2 has on USB serial communication.

Communication always happens at the native USB speed, either 12 or 480 Mbit/sec, with USB "bulk" protocol overhead. The baud rate and stop/start bit settings are not used for the actual communication. Likewise, traditional modem control signals RTS, CTS, DTR, DSR are not used. USB protocol always has built-in flow control and built in session management. It is not optional. All USB hardware always implements those features at the lowest levels. Both sides have transmit and receive buffers. The USB protocol automatically moves data only when the receiving side has spaces in its buffer to receive.

The CDC ACM protocol has special messages (outside the normal byte stream) to communicate the RTS, DTR, DSR bits and the baud rate and other settings. When software on the host side changes RTS, DTR, baud, those changes are communicated to the device side. Likewise when the device wants to change DSR, it is communicated to the host. As far as I know, there is no support for CTS in the protocol. For USB serial communication where you only care about the byte stream between software running on both sides, these extra messages are usually ignored. When the device is actual USB-Serial hardware, when the device hears the baud rate and stop/start message, it configures the actual serial hardware with those settings. Likewise for the modem control signals, the USB messages are used to actually change the physical signals on the serial side.


The thing is that this is probably something very simple and stupid, when finally figuring it out and that I have spend tens of hours on it already.

Yeah, reverse engineering an unknown device and working with code samples in unfamiliar languages takes a lot of time. Not sure if any of these answers really help, but hopefully it can save you a little time from worrying about details which probably don't matter.
 
The web socket header is explained here on page 28 https://www.rfc-editor.org/rfc/rfc6455

But this device uses not exactly WS I think. the TX data (6) 82 83 00 00 00 00; 0x82 is th binary data start. the second byte first bit (0x80) tells that mask is used, and the 4 following bytes are the mask. The second byte 0x03 part is the length of data so 0x80 + 0x03 = 0x83.

This is strange as the mask is 0 and the WS has also the header format 0x82, 0x03, when mask is not used... The incoming data seems to be this format.

I just found that it might be that the out going header is always 16 bytes (for this device), the remaining bytes 0, must investigate that more.

regarding the "In the RX case: You show: 82, 5, 5, 1, 0, 6, 1, Button number: 6, Encoder: 1" 0x82, 0x05 is the incoming header. The data always starts with the lenght of data (5) the second data byte (1) is the type of control, button or encoder, (the encoder has also button) the 3rd byte is message counter. the 4th byte is the button/encoder number, and last byte encoder direction 0x01 or 0x0F. provides one message for every click.

There is no checksum, so I think the separation of header and data would be pretty useful when data is long (image)

I found now also some pretty complex startup initialisation, it might be required before any response, will be difficult to get that exactly right blindly, and not sure if there is other problems, but will try.
 
Thanks Paul for the detailed info, Those documents are indeed not the easiest ones to dig into and it is very good to get this summary how things work.

I still insist one more time on the

rx: 82 05
rx token: 81FB8100 transfer length: 512 len:5 - 5 1
rx: 05 01 00 06 01

It seems the debug print can separate the incoming packages. Is this just as there has been enough time between those bytes? Would there be some way to get the "rx token: 81FB8100" tricker on the code. As the incoming data is short not really needed, but could be useful, and also maybe when the device starts reporting more data (but those should also be short.)
 
Good luck, will try to throw darts at some of the stuff, but.

As Paul mentioned, most Serial objects don't know about how the USB may split or not split the data.

When I have played with sending data through Serial (either USB or hardware Uart), I have sent things back and forth over them. As I mentioned like DXL servos, where maybe I am doing an update of 18 servos (hexapod with 3 servos per leg), and for each servo lets say I will send 8 bytes pers servo (new position, new speed or time)... So it adds up more than one USB packet (on most Serial USB...)

So how do we know the start of the packet. Theirs has specific starter (0xff 0xff ...), but followed by some other stuff and in their case they also have either checksum (Protocol 1) or CRC (Protocol 2). So it can detect that as well.
But in addition to this, I will typically for example check that if I have a larger packet which may not fit in one usb transfer (or for that matter over UART), and the time to when I receive the next set of data is > (some timeout), then I assume that
the packet was aborted, and I reset looking for start of new packet.

And I also wondered if there may be some initialization handshake you may have to do, that you are not already doing.

Kurt
 
There is the


GET /index.html
HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: 123abc

That is send as plain text at startup, no header needed, and to that I get the plain text response:


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: ALtlZo9FMEUEQleXJmq++ukUQ1s=

So the basic communication is working, and after that it provides the "WS" binary reports when moving encoder etc.But when sending any more than 4 bytes to the device it goes to sleep within about 10 seconds.

Today I learned that I should send all parameters (button colours, display data and some other stuff to initialise it.) that is challenging as it is not exactly clear what should be sent (no byte arrays or actual API description available). Need to figure it out from this https://github.com/CommandPost/Comm...zmxVkCyEY_mpJNIRnovCG18_923elc0KHCGgt_PM#L323

Will see it in near future.

There is one more thing, I got also some logs what happens on startup, on them I can see (/dev/cu.usbmodem32301) Serial message sent, this is how computer sees it /dev/cu.usbmodem32301 , why would it be modem?

Then there is also the confusion that before FW 0.2.x it was actually Websocket communication, but then they changed it to serial communication, but kept the WS protocol partially.
 
Last edited:
I got finally a computer I could instal the WireShark, and should have done tis much sooner.

Looking the data it provides it looks pretty clear I should be getting responses to every binary messages sent and it shows "clearly" what data is sent.


Well "clearly" as there is also much data I do not understand, that I assume is the USB protocol using behind.

Also looking this wondering if I should just use RAW data and send all?

Here is the data in WireShark format and PDF.

https://drive.google.com/drive/folders/1WBTS8CHe4cD77GUWxybnNvd6P5jhmq8o?usp=sharing

Much better to look with WireShark, but if you use the PDF, search for Frame 125:, that is the 'GET /index.html...' sending and Frame 127: is the response 'HTTP/1.1 101 Switching Protocols...' those do work on my code. What happens after does not work, it looks like the device should be responding, but I never get responses though I try to send same data they seem to be sending, but as mentioned there is messages I do not understand. This is what I am currently trying (and have tied many ways to separate or not the packages, but nothing works, the device just does not respond.

There is also the LDinit.pdf screen captures from the WireShark

I do think the problem is on interface level, but no idea how to approach it. What are those empty messages, and how could I sent them? Or are they just part what automatically happens.

The printout of current communication trials, after the first message I get nothing back from the device

Code:
Request1 WS 

GET /index.html
HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

control callback (serial) 0
txtimer
  TX data (116) 47 45 54 20 2F 69 6E 64 65 78 2E 68 74 6D 6C 0D 0A 48 54 54 50 2F 31 2E 31 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 55 70 67 72 61 64 65 0D 0A 55 70 67 72 61 64 65 3A 20 77 65 62 73 6F 63 6B 65 74 0D 0A 53 65 63 2D 57 65 62 53 6F 63 6B 65 74 2D 4B 65 79 3A 20 64 47 68 6C 49 48 4E 68 62 58 42 73 5A 53 42 75 62 32 35 6A 5A 51 3D 3D 0D 0A 0D 0A 00 
tx1:
rx token: 817F8100 transfer length: 512 len:129 - 48 54
rx: 48 54 54 50 2F 31 2E 31 20 31 30 31 20 53 77 69 74 63 68 69 6E 67 20 50 72 6F 74 6F 63 6F 6C 73 0D 0A 55 70 67 72 61 64 65 3A 20 77 65 62 73 6F 63 6B 65 74 0D 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 55 70 67 72 61 64 65 0D 0A 53 65 63 2D 57 65 62 53 6F 63 6B 65 74 2D 41 63 63 65 70 74 3A 20 73 33 70 50 4C 4D 42 69 54 78 61 51 39 6B 59 47 7A 7A 68 5A 52 62 4B 2B 78 4F 6F 3D 0D 0A 0D 0A 

Response1 

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

TEST 

START 

USBSerialBase::flush - Empty
txtimer
  TX data (6) 82 93 00 00 00 00 
tx1:
USBSerialBase::flush - Empty
txtimer
  TX data (19) 13 0E 01 4C 8F 8D 83 CA FA 07 7E DF E3 48 D3 9D 8E 3D 26 
tx1:
DONE 




char      WS_UPGRADE_HEADER[] = "GET /index.html\r\n"
                                "HTTP/1.1\r\n"
                                "Connection: Upgrade\r\n"
                                "Upgrade: websocket\r\n"
                                "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
                                //"Sec-WebSocket-Key: 123abc\r\n\r\n";
                                

And the code that produce that if (FistByteReceived == false){
      //this goes out ok
      Serial.println("\r\nRequest1 WS \r\n");
      Serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER));
      userial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER));
      delay(200);
      //we get expected response
      Serial.println("\r\nResponse1 \r\n");
      while (userial.available()) {Serial.write(userial.read());  FistByteReceived = true; }

      Serial.println("TEST \r\n");

      // uint8_t   START1[] = { 0x13, 0x0e, 0x01, 0xcb, 0x6b, 0x97, 0x53, 0x23, 0xa3, 0x2b, 0x41, 0x9e, 0x79, 0xa8, 0x9f, 0x50, 0x99, 0x34, 0x09 };//wireshark 1
       uint8_t   START1[] = { 0x13, 0x0e, 0x01, 0x4c, 0x8f, 0x8d, 0x83, 0xca, 0xfa, 0x07, 0x7e, 0xdf, 0xe3, 0x48, 0xd3, 0x9d, 0x8e, 0x3d, 0x26 };//wireshark 
       uint8_t START1_HEADER[]={0x82, 0x80+sizeof(START1 ), 0x00, 0x00, 0x00, 0x00}; 



       Serial.println("START \r\n");
    
       userial.flush(); delay(10); 
       userial.write(START1_HEADER , sizeof(START1_HEADER ));delay(10);
       
       //we get nothing back
       while (userial.available()) {Serial.print("RECEIVED1: ");Serial.print(userial.read(), HEX);   }
       userial.flush(); delay(10); 
       userial.write(START1 , sizeof(START1 ));delay(10);
       
       //we get nothing back
       while (userial.available()) {Serial.print("RECEIVED2: ");Serial.print(userial.read(), HEX);   }
       delay(1000);
       //just making sure we did not miss any incoming data, and nothing received
       while (userial.available()) {Serial.print("RECEIVED3: ");Serial.print(userial.read(), HEX);   }
          Serial.println("DONE \r\n");
  
      }
 
Here is still the code I am currently testing with. If commenting out the part mentioned at end, you will get the button presses, encoder rotations and touch screen data. This is for Loupedec Live

(and the above mentioned WirwShark data https://drive.google.com/drive/folders/1WBTS8CHe4cD77GUWxybnNvd6P5jhmq8o)


Code:
char      WS_UPGRADE_HEADER[] = "GET /index.html\r\n"
                                "HTTP/1.1\r\n"
                                "Connection: Upgrade\r\n"
                                "Upgrade: websocket\r\n"
                                "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n";
                                

bool      FistByteReceived = false;


#include <USBHost_t36.h>
#define USBBAUD 9600
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N2;
USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBHIDParser hid3(myusb);

//USBSerial userial(myusb);  // works only for those Serial devices who transfer <=64 bytes (like T3.x, FTDI...)
USBSerial_BigBuffer userial(myusb, 1); // Handles anything up to 512 bytes
//USBSerial_BigBuffer userial(myusb); // Handles up to 512 but by default only for those > 64 bytes


USBDriver *drivers[] = {&hub1, &hub2, &hid1, &hid2, &hid3, &userial};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2",  "HID1", "HID2", "HID3", "USERIAL" };
bool driver_active[CNT_DEVICES] = {false, false, false, false};

void setup()
{
  while (!Serial && (millis() < 5000)) ; // wait for Arduino Serial Monitor
  Serial.println("\n\nUSB Host Testing - Serial");
  myusb.begin();
  delay(1000);
}


void loop()
{
  myusb.Task();
  // Print out information about different devices.
  for (uint8_t i = 0; i < CNT_DEVICES; i++) {
    if (*drivers[i] != driver_active[i]) {
      if (driver_active[i]) {
        Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
        driver_active[i] = false;
        FistByteReceived = false;

      } else {
        Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
            
        driver_active[i] = true;

        const uint8_t *psz = drivers[i]->manufacturer();
        if (psz && *psz) Serial.printf("  manufacturer: %s\n", psz);
        psz = drivers[i]->product();
        if (psz && *psz) Serial.printf("  product: %s\n", psz);
        psz = drivers[i]->serialNumber();
        if (psz && *psz) Serial.printf("  Serial: %s\n", psz);

        // If this is a new Serial device.
        if (drivers[i] == &userial) { userial.begin(baud, format); Serial.println("userial started");}
       
      }
    }
  }



if (FistByteReceived == false){
      //this goes out ok
      Serial.println("\r\nRequest1 WS \r\n");
      Serial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER));
      userial.write(WS_UPGRADE_HEADER, sizeof(WS_UPGRADE_HEADER));
      delay(200);
      //we get expected response
      Serial.println("\r\nResponse1 \r\n");
      while (userial.available()) {Serial.write(userial.read());  FistByteReceived = true; }

      /*Comment out starting here to get knob presses etc. the below section does not work and but the loupedeck to sleep*/

      Serial.println("TEST \r\n");

      // uint8_t   START1[] = { 0x13, 0x0e, 0x01, 0xcb, 0x6b, 0x97, 0x53, 0x23, 0xa3, 0x2b, 0x41, 0x9e, 0x79, 0xa8, 0x9f, 0x50, 0x99, 0x34, 0x09 };//wireshark 1
       uint8_t   START1[] = { 0x13, 0x0e, 0x01, 0x4c, 0x8f, 0x8d, 0x83, 0xca, 0xfa, 0x07, 0x7e, 0xdf, 0xe3, 0x48, 0xd3, 0x9d, 0x8e, 0x3d, 0x26 };//wireshark 
       uint8_t START1_HEADER[]={0x82, 0x80+sizeof(START1 ), 0x00, 0x00, 0x00, 0x00}; 



       Serial.println("START \r\n");
    
       userial.flush(); delay(10); 
       userial.write(START1_HEADER , sizeof(START1_HEADER ));delay(10);
       
       //we get nothing back
       while (userial.available()) {Serial.print("RECEIVED1: ");Serial.print(userial.read(), HEX);   }
       userial.flush(); delay(10); 
       userial.write(START1 , sizeof(START1 ));delay(10);
       
       //we get nothing back
       while (userial.available()) {Serial.print("RECEIVED2: ");Serial.print(userial.read(), HEX);   }
       delay(1000);
       //just making sure we did not miss any incoming data, and nothing received
       while (userial.available()) {Serial.print("RECEIVED3: ");Serial.print(userial.read(), HEX);   }
          Serial.println("DONE \r\n");

      /*Comment until here to get knob presses etc.*/
      }



while (userial.available()) {Serial.print(userial.read(), HEX);  FistByteReceived = true; }


}
 
To be more specific

What are these empty messages and how to send them, and what is the data on this message. Is this something the USB Host library takes care and does it do it correctly?

Empty.jpg

This is the WS header that follows the empty message, 0x82, 0x93, 0x00, 0x00, 0x00, 0x00 i.e 19 bytes long binary message with 0 mask follows.

0x820x93header.jpg

Just noted the alternating destination and source though they are out messages (URB_BULK out), host/2.5.1 what is that?

Would be great if the USBHost_t36.h debug printout would be in format that could be imported to WireShark :)

Following the communication that happened with the Loupedeck device and SW using the WireShark, the 'Left Over Capture Data' corresponds well with the communication with the device as. understand it should be, and that I could replicate, but just do not get any expected response from the device.
(The above mentioned WirwShark data https://drive.google.com/drive/folders/1WBTS8CHe4cD77GUWxybnNvd6P5jhmq8o)


In the quest of unknown the most difficult part is finding the right questions.


Reading the. https://www.pjrc.com/teensy/beta/usb20.pdf



"5.8.2 Bulk Transfer Direction
A bulk pipe is a stream pipe and, therefore, always has communication flowing either into or out of the host for a given pipe. If a device requires bi-directional bulk communication flow, two bulk pipes must be used, one in each direction."

Is this stuff I need to worry, Or should this be taken care by the library, is the serial communication correctly set up on the code above?

The confusing stuff is that the first message exchange works, so why not the following?

reading further

"A bulk transfer is complete when the endpoint does one of the following:
• Has transferred exactly the amount of data expected
• Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet"

So wondering if this is the problem, that the bulk transfer is not ever completed and hence no response from the device. SO what should be done to complete it? how do I transfers a zero-length packet?

The flush() does not seem to do the job.
 
Last edited:
But there is the thing that the first message content seems to change

// uint8_t START1[] = { 0x13, 0x0e, 0x01, 0xcb, 0x6b, 0x97, 0x53, 0x23, 0xa3, 0x2b, 0x41, 0x9e, 0x79, 0xa8, 0x9f, 0x50, 0x99, 0x34, 0x09 };//wireshark 1
// uint8_t START1[] = { 0x13, 0x0e, 0x01, 0x4c, 0x8f, 0x8d, 0x83, 0xca, 0xfa, 0x07, 0x7e, 0xdf, 0xe3, 0x48, 0xd3, 0x9d, 0x8e, 0x3d, 0x26 };//wireshark 1
uint8_t START1[] = { 0x13, 0x0e, 0x01, 0x9f, 0x88, 0x53, 0x3b, 0x1a, 0x4b, 0x15, 0x90, 0xd2, 0x9e, 0x03, 0xea, 0x26, 0x13, 0x58, 0e0 };//wireshark 1

And did some more testing, at each connection the first WS format data package the host sends seems to be same format but different data, 3 startups give

Leftover Capture Data: 130e010739256c9ed3422ad5c830ad307946db
Leftover Capture Data: 130e01233a7c7276ed0f2a53338277914706b4
Leftover Capture Data: 130e013d3d3ac6c0f60a1a8104af8089fa7227

However the other codes I have found in Github, are sending similar data like

Code:
 uint8_t   DATA0 [] = { 0x13, 0x1C, 0x01, 0x61, 0xf1, 0x39, 0x2a, 0x8e, 0x93, 0x6b, 0xa6, 0x6e, 0x99, 0x2d, 0xae, 0xdb, 0x40, 0xf6, 0x5f };                
         uint8_t   DATA1 [] = { 0x13, 0x0e, 0x01, 0x3d, 0xa8, 0x1c, 0x9b, 0xa7, 0x2a, 0x8c, 0x87, 0xd4, 0xf6, 0xa1, 0x35, 0xa2, 0x89, 0x06, 0x6c }; 
         uint8_t   DATA2 [] = { 0x13, 0x1c, 0x02, 0x61, 0xf1, 0x39, 0x2a, 0x8e, 0x93, 0x6b, 0xa6, 0x6e, 0x99, 0x2d, 0xae, 0xdb, 0x40, 0xf6, 0x5f };
         uint8_t   DATA3 [] = { 0x03, 0x07, 0x03};
         uint8_t   DATA4 [] = { 0x03, 0x0D, 0x04};
         uint8_t   DATA5 [] = { 0x03, 0x04, 0x05};
         uint8_t   DATA6 [] = { 0x03, 0x03, 0x06};
         uint8_t   DATA7 [] = { 0x04, 0x1a, 0x07, 0x00};
         uint8_t   DATA8 [] = { 0x04, 0x1a, 0x08, 0x01};
         uint8_t   DATA9 [] = { 0x04, 0x1a, 0x09, 0x02};
         uint8_t   DATA10[] = { 0x04, 0x1E, 0x0A, 0x00};
         uint8_t   DATA11[] = { 0x04, 0x09, 0x0B, 0x03};

I have tried, nothing works, never any response from the device.
....

Anyway, the question for now. How do I transfers a zero-length packet, or is that relevant.

and some other questions related to the interface setup, like there seems to be two pipes?

USBSerial, rxep=1(512), txep=1(512)
rx buffer size:1024
tx buffer size:1024
new_Pipe
new_Pipe
Control - CDCACM LINE_CODING
Descriptor 5 = ENDPOINT
Descriptor 5 = ENDPOINT
control callback (serial) 4
Control - 0x21,0x22, 0x3
control callback (serial) 0
*** Device USERIAL 2ec2:4 - connected ***
manufacturer: Loupedeck
product: Loupedeck Live
Serial: LDD2001014022200100398B2
control callback (serial) 6
CDCACM setup: 80 FB 1F 00 00 00 08
control callback (serial) 4
Control - 0x21,0x22, 0x3
userial started


Is it set up completely and correctly, is it just serial communication, and how much of the overall communication the USBHost_t36.h takes care of

I changed now the port settings to

#define USBBAUD 2096000
uint32_t baud = USBBAUD;
uint32_t format = USBHOST_SERIAL_8N1;
userial.begin(baud, format );

makes no difference, and do not know what this is supposed to affect.

So many questions and no idea if any of them is right one.
 
Last edited:
Back
Top