Zero-length packets for USB control transfers - controls

In the context of a DFU driver, I'm trying to respond with a packet of length zero (not ZLP as in multiples of max size, just zero bytes) to a USB control in transfer. However, the host returns with a timeout condition. I tried both, the dfu-util tool and the corresponding protocol, as well as a minimal working example with pyusb just issuing a control in transfer of some length and the device returning no data.
My key question is: Do I achieve this by responding with a NAK or should I set the endpoint valid but without any data? The specs are rather vague about this, imo.
Here are some technical details since I'm not sure where the problem is:
Host: Linux Kernel 5.16.10, dfu-util and pyusb (presumably) both using libusb 0.1.12
Device: STM32L1 with ChibiOS 21.11.1 USB stack (sends NAK in the above situation, I also tried to modify it to send a zero-length packet without success)

It sounds like you are programming the firmware of a device, and you want your device to give a response that is 0 bytes long when the host starts a control read transfer.
You can't simply send a NAK token: that is what the device does when the data isn't ready yet, and it causes the host to try again later to read the data.
Instead, you must actually send a 0-length IN packet to the host. When the host receives this packet, it sees that the packet is shorter than the maximum packet size, so it knows the data phase of the control transfer is done, and it moves on to the status stage.

Related

Embarcadero RAD Studio & Indy. Error message “Package Size Too Big”

I use Embarcadero RAD Studio & Indy and I have a problem.
I am using component IdUDPServer and try to send file via UDP messages.
The file is successfully transferred if it is not large.
However, the error message “Package Size Too Big” appears if the file is large.
My code:
FileAPP->ReadBuffer(Buffer, Size);
IdUDPServer1->SendBuffer("10.6.1.255", 34004, RawToBytes(&Buffer, Size));
I see two ways to solve this problem:
1) Compose small messages and send these messages in a loop.
This is an easy way to solve the problem, however I will need to fix the remote application.
This is currently difficult. I do not have much time.
2)I want to find a condition in the source code where this error message is generated.
Maybe I can fix the condition and it will work for my specific task.
I have added some pictures. This is all the information that I now have.
Screenshots from help file: Picture 1, Picture 2, Picture 3
Error message: Picture 4
Please help me if you know the solution.
"Package Size Too Big" means you tried to send a datagram that is too large for UDP to handle. UDP has an effective max limit of 65507 bytes of payload data per datagram. You can't send a large file in a single datagram, it just won't fit.
So yes, you will have to break up your file into smaller chucks that are sent in separate datagrams. And as such, because UDP is connection-less and does not guarantee delivery, you will also have to solve the issues of lost packets and out-of-order packets. You will have to put a rolling sequence number inside your packets so that the receiver can save packets in the proper order. And you will have to implement a re-transmission mechanism to re-send lost packets that the receiver did not receive.
I would suggest not using TIdUDPClient/TIdUDPServer to implement file transfers manually, if possible. Indy has TIdTrivialFTP/TIdTrivialFTPServer components that implement the standardized UDP-based TFTP protocol, which handles these kind of details for you. By default, TFTP has a limit of ~32MB per file (512 bytes per datagram * 65535 datagrams max), but you can increase that limit using the TIdTrivialFTP.RequestedBlockSize property to request permission from a TFTP server to send more bytes per datagram. RequestedBlockSize is set to 1500 bytes by default, which can accommodate files up to ~93.7MB in size (though in practice it should not be set higher than 1468 bytes so TFTP datagrams won't exceed the MTU size of Ethernet packets, thus limiting the max file size closer to ~91.7MB). The RequestedBlockSize can be set as high as 65464 bytes per datagram to handle files up to ~3.9GB (at the risk of fragmenting UDP packets at the IP layer).
It is also possible for TFTP to handle unlimited file sizes with smaller datagram sizes, though TidTrivialFTP/TIdTrivialFTPServer do not currently implement this, because this behavior is not currently standardized in the TFTP protocol, but is commonly implemented as an extension in 3rd party implementations.
Otherwise, you should consider using TCP instead of UDP for your file transfers. TCP doesn't suffer from these problems.

serial stops between mbed and processing

I want a solution right now...
The LPC1768 which is one of a mbed prototyping boards communicates with processing through Serial whose baud rate is 115200. However, as time passes, the serial communication stops.
As a situation, the LPC1768 sends sensor data with serial.putc() of the default serial library. On the other hand, processing receives the data with serial.read(). The processing code is the following:
if(serial.available()>1) { serial.read(); }
To explore the solution of this problem, I tired these things.
I checked serial.available() is 46 and used serial.clear() in processing, but mbed stopped and didn't send data. Because I thought the cause of this was an overflow of receiving buffer of processing.
I added serial.writable() and check the serial buffers for sending has space. If there are no space, I used the following codes and initialized the serial:
LPC_UART2->FCR |= 0x06;
serial.baud(115200);
, because I thought the cause of this was an overflow of sending buffer of mbed. However, they didn't work.
Please note that these codes work correctly and basically.
However, serial communication stops suddenly. What can I do anything else?
Best regards

How CSMA/CA works on XBee?

I'm trying to implement S-MAC protocol on waspmote xbee sensors and i know it has its own CSMA/CA. So first of all I need to understand the basic of xBee collision avoidance.
Two senders set up in api mode in libraries and both periodically sending single bytes to a common receiver. I reduce the delay and many changing in libabries to make collision and to see how algorithm works. But when i monitor data at the receiver all looks as expected at the receiver .. byte1, byte 2 .. byte1, byte2.
Do u have any idea how can i make collision?
Are you sniffing the 802.15.4 traffic? That's the only way you'd see a collision.
The XBee module buffers the data you want to send, using the host communication parameters (baud rate, API mode, etc.) and then sends it out over 802.15.4 at 250kbps. The module has all of the collision avoidance built in, and will retransmit as necessary to deliver your message. If it's unable to deliver after some number of transmission attempts, you'll get a Transmit Status frame indicating failure.
On the receiving end, it buffers the data and delivers it to the local host using local serial settings (baud rate and API mode).
If you're trying to implement S-MAC, you need a different radio processor where you have low-level control over the radio. The XBee module provides an application layer and handles the MAC layer itself.

HW device via COM port, access individual pins

I'm currently working on a project which involves dealing with a HW device tailor-made for this purpose.
The device will serve the purpose of sending certain data via serial port (COM1, for instance). The data it is supposed to send doesn't matter that much.
I already have some knowledge regarding Windows serial port communication. CreateFile, WriteFile, and so on... BUT...
There is one "engine" on the device, which will send me the data when I ask it to, and in order to do so, I need to send there a signal (10101010) the rate of which will indicate the clock rate of that device "engine".
Here comes the explanation of how this device work. It gets a signal to send data through one pin. I'm supposed to send there 0 for start, 1 for end. Then, after this, it will watch some other pin for signal, sample it, and based on the frequency of ones and zeroes I send to it, it will start sending data via the thrid pin.
My questions are:
How to access individual pins of COM port?
How to manage the frequency and any delays I will need by myself?
I think that maybe I will have to do on this in kernel more by use of device drivers which will have to be developed.
There is an easier way. The COM port will send out the signal of alternating 1s and 0s if you just send a 0xAA byte.

SnmpExtensionTrap has a size limit?

I am working on a problem in SNMP extension agent in windows, which is passing traps to snmp.exe via SnmpExtensionTrap callback.
We added a couple of fields to the agent recently, and I am starting to see that some traps are getting lost. When I intercept the call in debugger and reduce the length of some strings, the same traps, that would have been lost, will go through.
I cannot seem to find any references to size limit or anything on the data passed via SnmpExtensionTrap. Does anyone know of one?
I would expect the trap size to be limited by the UDP packet size, since SNMP runs over the datagram-oriented UDP protocol.
The maximum size of a UDP packet is 64Kb but you'll have to take into account the SNMP overhead plus any limitations of the transport you're running over (e.g. ethernet).

Resources