Thanks a lot RoystonS!
Now we know that -c arduino works and -c stk500v1 it is easy to figure out what goes wrong. The answer is in CDC.cpp:
size_t Serial_::write(uint8_t c)
{
/* only try to send bytes if the high-level CDC connection itself
is open (not just the pipe) - the OS should set lineState when the port
is opened and clear lineState when the port is closed.
bytes sent before the user opens the connection or after
the connection is closed are lost - just like with a UART. */
// TODO - ZE - check behavior on different OSes and test what happens if an
// open connection isn't broken cleanly (cable is yanked out, host dies
// or locks up, or host virtual serial port hangs)
if (_usbLineInfo.lineState > 0) {
int r = USB_Send(CDC_TX,&c,1);
...
(The TODO says it all...)
The two lsb bits of lineState correspond to DTR and RTS. Apparently on windows, DTR and RTS are not set, and the Leonardo will refuse to send out anything under these conditions.
I checked in avrdude, the code on linux and mac is the same, it does not do anything special to set RTS/DTR, so apparently the os does that. The windows code uses the win32 api, does nothing special either, but windows does not seem to set the signals.
Why does -c arduino work? Because for this protocol, avrdude explictly drops the signals for 250 ms to discharge the autoreset capacitor! Then it explicitly sets them back high! As a consequence this works also on windows with the Leonardo.
I don't know if we miss functionality when using arduino instead of stk500v1: to check...
I updated my writeup with this info. I am afraid Fulg is not the only one at all. Lots of people must have tried this and have been disappointed it did not work :-(.