with libmaple (roger's) core, usb composite is a way to start for one the contributing author has gone the distance to make some basic HID e.g. keyboard rather easy to emulate. HID is a complex protocol, it would help to get familiar with the protocol specs
https://www.usb.org/hid
i found some rather good stuff about programing usb on stm32
https://www.st.com/content/st_com/en/su ... ining.html
that one is original ST HAL but it is about as good a starting point as any, the callbacks etc aren't easy to figure out so the materials helps
then it would help to get a protocol sniffer and watch packets on the wire. that's one way i figured out some things about usb that i misunderstood all along.
it is an interesting venture but a difficult one. i'd think usb isn't for novice to start on, it is one of the very large and complex protocol stacks due to its design and aims to cater to a lot of devices, but it won't stop any one from going the distance to try to learn it.
hardware sniffers are like such
https://gimx.fr/wiki/index.php?title=Bbb_sniffer
http://maurillo71.blogspot.com/2014/02/ ... iffer.html
there are many software sniffers as well
linux has it literally in the kernel
https://www.kernel.org/doc/Documentation/usb/usbmon.txt
the hard part is to try to decode all that hex protocol units
i got close enough to decode some of the get descriptor responses, HID is one of the most complex with report descriptors.
still learning as well, some what close to try to emulate a mouse, the big deal? if i can figure that out stm32 can move that cursor on the screen 'on its own' and even clicks and make drawings and perhaps type essays too
usb virtual comm ports e.g. Serial (usb-serial) is one example, it isn't limited to the usual uart limits like 115200 baud. it can in theory go up to usb full speeds 12 mbps minus all the overheads and turn around. i've seen > 1mbps on usb-serial on a stm32f401. to get anything closer to the usb bandwidth, it'd take a lot of difficult optimizations like interleaving usb transfers with perhaps adc with dma to keep the pipeline filled.
for the determined, one might be able to take a ov7670 camera
https://www.arducam.com/wp-content/uplo ... evc_ds.pdf
use a stm32f4xx, pull that image out and compress on the fly into jpeg and send it over as usb-video mjpeg.
that'd literally give one a webcam. it can be a pretty involved project given all the camera interfacing, jpeg compression and protocols.
a big deal here is since you control the compression parameters, you can determine the quality between the raw image and the compressed output