Sooo...
I think I found what's going on with some of the issues triggering
things like
usb_composite_setup_continue: Unexpected call
Or possibly
gadget: common->fsg is NULL in fsg_setup at 489
But I mostly tracked down the former.
Fundamentally, it boils down to the storage going through multiple
attempts at FSG_STATE_CONFIG_CHANGE too quickly. In my case:
- The hub port gets reset, this eventually calls fsg_disable
- In the middle of handle_exception, we get a fsg_set_alt(), after
common->state is set back to FSG_STATE_NORMAL and before we get to
call do_set_interface (or inside it).
What happens is that not only new_fsg is indeterminate and possibly
racy (maybe not a huge deal per-se), but we end up in that
interesting situation where the handle_exception caused by fsg_disable
ends up applying "new_fsg" *and* calling usb_composite_setup_continue
because it sees new_fsg being set by fsg_set_alt.
But *then*, fsg_set_alt() also queues up a new exception. So we come
back a second time around. We call do_set_interface() again, which
resets everything for no reason, re-established the fsg and ... we call
usb_composite_setup_continue() again, this time completely at the wrong
time since there's nothing to continue.
I think the right fix is to replace that racy exception crap with a
little queue so we remove those races.
In the meantime however, I think the simpler patch that I'll send as
a reply to this works around it, provided the host doesn't do multiple
set_alt too quickly. The latter could be handled by setting new_fsg
with the lock used for the state, and reading it from that same lock.
But I haven't observed that problem in practice.
With this patch, I can now unplug & replug on my host solidly, this
wasn't the case before.
Cheers,
Ben.