This is a follow-up to my previous question, Need to write driver for USB peripheral device?
I'm working on designing a USB peripheral using an STM32 microcontroller (bare metal / no OS). The device will occasionally be connected to a Windows PC, and transfer a few KB of data in each direction. There will be a custom PC application that controls the data transfers, using a proprietary protocol (i.e. for the USB payloads).
The PC will always be the master (initiator) - it'll send commands, and the device will issue responses, with up to a few hundred bytes of data going in either direction in a single command or response. I think I'll want to use USB Bulk Transfer mode.
From what I understand, one option is I could use the USB Communications Device Class (CDC). On the device side, I could use sample code from ST for the USB CDC, e.g. from STM32Cube. On the PC side, the device would present as a Virtual COM Port (VCP). Then in software I'd basically have a raw, bidirectional stream, on top of which I'd have to define my messsage formats, commands, etc.
I'm having trouble wrapping my mind around exactly what this is, and how to work with it.
What is the relationship of WinUSB to USB device classes? It seems to function as a "generic" USB class, but I can't find any documentation that spells it out as such.
Does WinUSB provide any built-in message delimiters? e.g. Does WinUsb_WritePipe send the contents of the buffer down to the device as an atomic unit? Or do I just get raw streams like a VCP/UART?
How does one implement WinUSB on the device? Is there sample code available? (Preferably for STM32.)
WinUSB_WritePipe
sends the data as a single USB transfer. A transfer has a specific definition in the USB specification. You can tell when a transfer ends because you will get a short packet at the end of the transfer. A short packet is a packet that is smaller than the maximum packet size of the endpoint, and it could possibly be zero-length. You should double check whether that is actually true though; try sending a transfer that is a multiple of the maximum packet size and make sure that Windows sends a zero-length packet at the end of that. By the way, you should consider sending your data as a control transfer or series of control transfers on endpoint 0. Control transfers have a built-in concept of a request and a response to the request. Despite the name, control transfers can be used to transfer large amounts of data; they are commonly used in the USB bootloaders (see the DFU class). Another advantage of using control transfers instead of non-zero endpoints is that you don't have to add extra endpoint descriptors and initialize the endpoints in your firmware. Your USB stack should have the machinery for handling custom control transfers and you should be able to make custom control transfers just by writing a few callback functions.