So, here is a USB library compatible with the main libmaple-based core:
(The library is also bundled with Roger’s core.)
As of February 2018, the library supports:
- USB HID
- Serial (use CompositeSerial, not Serial)
- USB MIDI
- XBox 360 controller
- Mass storage
You can do various composite combinations, e.g., HID+Serial, Mass storage+HID, etc.
Here’s some example code: an adapter from the IBM PC game port to USB joystick:
#include <GameControllers.h> // https://github.com/arpruss/GameControllersSTM32
#include <USBComposite.h>
USBHID HID; // declare HID plugin instance
HIDJoystick Joystick(HID); // declare Joystick profile instance
GamePortController controller(PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7);
void setup()
{
// to composite serial, use USBHID_begin_with_serial() instead
USBHID.begin(HID_JOYSTICK); // other options: HID_KEYBOARD, HID_MOUSE, HID_KEYBOARD_JOYSTICK, HID_KEYBOARD_MOUSE, HID_KEYBOARD_MOUSE_JOYSTICK
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, 1);
controller.begin();
Joystick.setManualReportMode(true); // aggregate data before sending
}
void loop()
{
GameControllerData_t data;
if (controller.read(&data)) {
Joystick.X(data.joystickX);
Joystick.Y(data.joystickY);
Joystick.Xrotate(data.cX);
Joystick.sliderRight(data.shoulderRight);
uint8_t mask = 1;
for (int i=1; i<=8; i++, mask <<= 1)
Joystick.button(i, (data.buttons & mask) != 0);
Joystick.send();
}
delay(10);
}
[RogerClark – Sun Dec 03, 2017 9:16 pm] –
Any idea how we could stop the code hanging if calls are made to Serial ?
Actually, my note about hanging was unduly alarmist: when I actually tried it, there was no hang.
Nonetheless, to be safe, I just added a USBSerialNOP class that extends USBSerial and does nothing, and made the init code for HID and MIDI overwrite Serial with an instance of USBSerialNOP. We still waste flash space by having the Serial code, but at least we won’t have any issues with interference.
Thanks
I’ll give the libs a try when I get chance (possibly this evening)
If the Serial.begin() call were removed from the global setup code in the core, and if one left the issues about using Serial by mistake for the user to worry about out, then the linker wouldn’t link in the USBSerial and usbcdcacm code, and library users would save flash. It’s that one call to Serial.begin() in the default board_setup_usb() that gets the linker to pull in the usb serial code.
What’s weird is that board_setup_usb() is declared __weak and I override it in the library. The override works, but the stupid(?) linker still pulls in the dependencies for the original __weak board_setup_usb(). This happens even in LTO mode, which make no sense to me. But if one comments out the Serial.begin() line in the core, all that unnecessary code disappears.

It would still be nice to find some way to override it without bringing in the unnecessary dependencies.
Unfortunately, the Serial.begin is essential so that the core can be triggered to reboot via the IDE
I did look to see if commands can be sent via HID which could be uses to reboot, but i could not find much useful information about how this could be done using the generic Windows HID driver
So it would break things for anyone currently using Serial or BMP upload, if it was defaulted to being turned on.
Unfortunately, the menu system in the IDE is not cascading, so there is no way to just have this as an option for the upload methods which currently have USB Serial turned included in the build.
From what I understand, having USB Serial initially turned on, means the code is bigger, but your code turns it off.
i dont see this as a big problem, because conversely, someone may want to use USB HID to start with, but then switch back to USB Serial later in their code. In which case USB Serial would need to be compiled in.
Most BluePills have 128k so I dont think an additional 5k all the time is a big problem
if the problem is that USB Serial starts and then stops again ( because the HID library disables Serial), perhaps there is a way to add a global flag which is set as part if the HID library, which prevents the code calling Serial.begin() in the core.
HID.begin(device); // where HID is your instance of USBHID
Looks good
I will try to test, when I get time, probably at the weekend
One problem I haven’t figured out is how to reset the USB connection. HID.begin(USB_HID_JOYSTICK); HID.end(); HID.begin(USB_HID_KEYBOARD); doesn’t work, at least not with Windows. Windows still sees the joystick device, not the keyboard, even though HID.begin() includes the PA12 reset code.
A minor issue I noticed is that if you send data to the keyboard (and probably other devices) too soon after HID.begin(), it will disappear. A 500ms pause is good enough.
Sending too soon after the USB starts, causes the data to be lost.
I’m a bit snowed under with PR’s at the moment.
There are 2 urgent ones, because Wire is not working correctly and nor is tone()
And there seem to be other assorted PR’s some of which I will decline
I’m also in the middle of bringing the ZumSpot branch up to date, as it was nearly 300 commits out of date…
So I need to confirm the merge with Head Master (plus some manual changes) are OK.
If your PR is just the addition of lib’s I should be able to take a look at the weekend.
I am not merging in the libraries yet, as I would like to be able to make improvements to them over the next couple of weeks, as I have a project that will use them, so I may have more ideas for them.
I closed my PR to merge in the addMidiHID branch. If you want, I can give you a PR to bring the addMidiHID branch up to date with Master, but I am thinking that that branch is obsolete given the libraries.
One thing I haven’t been able to get working — it also wasn’t working in the branch — is two-way HID RAW. I have one-way (device to host) transmission working, but the receive interrupt function isn’t being called.
If anybody has ideas on how to get HID RAW host-to-device working, I would welcome input. Not that I really need it for anything — just would be a nice completion to the library.
Re: USB power enable and disable
If Serial.end disables power in your PR, Serial.begin should enable power, as it should be possible to all end() and then call begin()
I agree that moving the USB reset to Serial.begin() should be investigated, but I have not had time to look at the existing code to see if there are any pitfalls with this.
Serial.end() currently calls usb_cdcacm_disable() which I think should power down the USB peripheral (it does that in my PR).
I am inclined to think the best place for the GENERIC_BOOTLOADER usb reset code for serial is usb_cdcacm_enable(), because that’s where the disconnect code is for devices that have disconnect hardware. The only issue I foresee with that is that if a user has an explicit Serial.begin(), then there will be two calls to the usb reset code. I don’t know if that’s a problem or not.
if (_hasBegun)
return;
I understand its done elsewhere, its just not obvious to anyone looking in the code.
Perhaps we could have a function that can do both enable and disable the USB power, or have separate functions.
OK.
I didnt mean to move the function. So perhaps some comments would be useful, for anyone else who investigates the USB
By the way, I still can’t get RAWHID host-to-device to work, but host-to-device feature settings now work in the featuresetting branch of the library.
(In theory, one could use host-to-device feature setting to implement a software-forced reset.)
A few weeks ago, I did try to find if it was possible to send a command via HID, as its supposed to be bi-directional, but did not find anything useful
There was a post on AVRFreaks where someone was using VUSB for HID and wanted to send commands to the AVR but he seemed to have a roadblock with the default HID drivers on Windows, and custom drivers may be required for that functionality
To test it on Windows, install it to an stm32f1, run send.py (which needs pywinusb) on the PC, and then look in the Game Controllers config tool in Windows to see if the joystick is moving. (Win-R, joy.cpl, enter, click on “Maple”, click on “Properties”) Another test is whether the fetch line matches the previous send line in the output.
$ c:/python36/python send.py
HID device (vID=0x1eaf, pID=0x0024, v=0x0200); LeafLabs; Maple, Path: \\?\hid#vid_1eaf&pid_0024#6&149a03ce&2&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
send: [3, 7, 0, 0, 0, 15, 0, 0, 0, 2, 8, 32, 128]
fetch: [3, 7, 0, 0, 0, 15, 0, 0, 0, 2, 8, 32, 128]
So could you send a command via HID to reboot ??
But one would have to decide which HID description(s) to add it to, and there would be some SRAM wasted (40-300 bytes or so) depending on how one implemented it.
Also there would need to be binary tools for all platforms to send this command, as people would not necessarily have python installed
[RogerClark – Mon Dec 11, 2017 7:54 pm] –
OK. it’s not so good that it needs more RAMAlso there would need to be binary tools for all platforms to send this command, as people would not necessarily have python installed
Personally, I think this is more trouble than it’s worth. I’d rather just pull the plug or press the reset button instead of testing things on three platforms.
[arpruss – Mon Dec 11, 2017 9:28 pm] –[RogerClark – Mon Dec 11, 2017 7:54 pm] –
OK. it’s not so good that it needs more RAMAlso there would need to be binary tools for all platforms to send this command, as people would not necessarily have python installed
Personally, I think this is more trouble than it’s worth.
I’d rather just pull the plug or press the reset button instead of testing things on three platforms.
Agreed
The only thing I couldn’t figure out to do is how to override the core’s Serial, so currently if you want to do serial i/o, you need to use CompositeSerial.
Maybe one could make a virtual USBSerial class and make the Serial instance be __weak in the core or something like that. I don’t know enough about C++ inheritance to figure this out right now.
Tried usb keyboard. USB HID is detected but can’t be configured.
Serial interface is detected and module loaded.
This is my dmesg output when I plug the device.
74281.945860] usb 1-4: new full-speed USB device number 107 using xhci_hcd
[74282.115902] usb 1-4: New USB device found, idVendor=1eaf, idProduct=0024
[74282.115904] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[74282.115905] usb 1-4: Product: Maple
[74282.115905] usb 1-4: Manufacturer: LeafLabs
[74292.251940] cdc_acm 1-4:1.0: ttyACM0: USB ACM device
[74292.253017] usbhid 1-4:1.2: can’t add hid device: -71
[74292.253026] usbhid: probe of 1-4:1.2 failed with error -71
[74293.769062] cdc_acm 1-4:1.0: failed to set dtr/rts
[74306.967792] cdc_acm 1-4:1.0: failed to set dtr/rts
[74306.969538] cdc_acm 1-4:1.0: failed to set dtr/rts
[74316.062451] cdc_acm 1-4:1.0: failed to set dtr/rts
[74316.063964] cdc_acm 1-4:1.0: failed to set dtr/rts
[74322.061371] cdc_acm 1-4:1.0: failed to set dtr/rts
Source code for the program:
#include <USBHID.h>
const uint8_t reportDescription[] = {
USB_HID_ABS_MOUSE_REPORT_DESCRIPTOR(USB_HID_MOUSE_REPORT_ID)
,USB_HID_KEYBOARD_REPORT_DESCRIPTOR(USB_HID_KEYBOARD_REPORT_ID)
};
HIDAbsMouse mouse;
void setup(){
HID.begin(reportDescription, sizeof(reportDescription));
delay(1000);
mouse.move(0,0);
delay(1000);
mouse.press(MOUSE_LEFT);
mouse.move(500,500);
mouse.release(MOUSE_ALL);
mouse.click(MOUSE_RIGHT);
}
void loop(){
delay(100);
mouse.move(16384,16384);
Keyboard.write('h');
Keyboard.write('o');
Keyboard.write('l');
Keyboard.write('a');
delay(100);
}
[anv – Tue Dec 12, 2017 7:43 pm] –
Just downloaded master branch. The example for twojoysticks does not compile.
Sorry: I changed the API without changing the example. It’s fixed now.
Tried usb keyboard. USB HID is detected but can’t be configured.
That’s not good. I’ve only tested on Windows.
1. Do you know if the libarra111 USB core works for you?
2. Can you try something super-basic like:
#include <USBHID.h>
void setup() {
USB.begin(USB_HID_JOYSTICK);
}
void loop() {
Joystick.X(0);
delay(500);
Joystick.X(1023);
delay(500);
}
https://aweirdimagination.net/2015/04/0 … id-errors/
Also, you can send or post the lsusb output, like in this post: https://bbs.archlinux.org/viewtopic.php … 2#p1578802
[arpruss – Wed Dec 13, 2017 1:04 am] –
Now it works under Android and in the Ubuntu VM. The problem was in a descriptor I grabbed from the libarra111 fork.
This is indeed interesting.
I played much a long time ago with the AVR-specific V-USB implementation. I also played with the ATmega32U4 “micro.”
Ray
Of course, it’s not really needed, except maybe for speed and efficiency. Everything you can do with an output report you can do with a feature report, I think.
[arpruss – Wed Dec 13, 2017 1:04 am] –
Now it works under Android and in the Ubuntu VM. The problem was in a descriptor I grabbed from the libarra111 fork.
Yes!! Keyboard now works under linux. If you need tests or USB info from real joysticks, keyboard, mous or midi devices just ask me. I can copy it for you.
I.E. here is the info from a real usb keyboard:
Kernel information (dmesg) when plugging the device:
[ 579.488436] usb 1-4: new low-speed USB device number 7 using xhci_hcd
[ 579.663196] usb 1-4: New USB device found, idVendor=0461, idProduct=4e29
[ 579.663197] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 579.663198] usb 1-4: Product: Wired USB Keyboard
[ 579.663199] usb 1-4: Manufacturer: PRIMAX
[ 579.666268] input: PRIMAX Wired USB Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/0003:0461:4E29.0005/input/input19
[ 579.717495] hid-generic 0003:0461:4E29.0005: input,hidraw4: USB HID v1.10 Keyboard [PRIMAX Wired USB Keyboard] on usb-0000:00:14.0-4/input0
[ 579.723297] input: PRIMAX Wired USB Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.1/0003:0461:4E29.0006/input/input20
[ 579.775720] hid-generic 0003:0461:4E29.0006: input,hiddev0,hidraw5: USB HID v1.10 Device [PRIMAX Wired USB Keyboard] on usb-0000:00:14.0-4/input1
[arpruss – Wed Dec 13, 2017 4:38 pm] –
What I do need help with is figuring out how to make HID output (host-to-device) reports work. HID feature reports work fine in both directions.Of course, it’s not really needed, except maybe for speed and efficiency. Everything you can do with an output report you can do with a feature report, I think.
May be you could check the HID-project library https://github.com/NicoHood/HID
It works OK reciving data from the host like keyboard leds. See this example (I tested it with an Arduino Leonardo and works ok):
/*
Copyright (c) 2014-2015 NicoHood
See the readme for credit to other people.
KeyboardLed example
Press a button to toogle caps lock.
Caps lock state is represented by the onboard led.
Leds are only supported on single report HID devices.
See HID Project documentation for more information.
https://github.com/NicoHood/HID/wiki/Keyboard-API
*/
#include "HID-Project.h"
const int pinLed = LED_BUILTIN;
const int pinButton = 2;
void setup() {
pinMode(pinLed, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Sends a clean report to the host. This is important on any Arduino type.
BootKeyboard.begin();
}
void loop() {
// Update Led equal to the caps lock state.
// Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted.
if (BootKeyboard.getLeds() & LED_CAPS_LOCK)
digitalWrite(pinLed, HIGH);
else
digitalWrite(pinLed, LOW);
// Trigger caps lock manually via button
if (!digitalRead(pinButton)) {
BootKeyboard.write(KEY_CAPS_LOCK);
// Simple debounce
delay(300);
}
}
[anv – Wed Dec 13, 2017 6:39 pm] –[arpruss – Wed Dec 13, 2017 1:04 am] –
Now it works under Android and in the Ubuntu VM. The problem was in a descriptor I grabbed from the libarra111 fork.Yes!! Keyboard now works under linux.
But my changes broke feature reports on Windows. I made some more changes and it now seems to work under both Windows and Android. Can you check Linux? (I know Android is Linux, but it might use other USB drivers.)
I recall there was some old code from the leaflabs forum, which I tried a long time ago.
I presume that in theory we could add USB mass storage as a library ???
If someone else wants it, they can add it
1. The publicly useful USB_HID_xxx macros have been renamed to just HID_xxx.
2. The main USBDevice instance should now be referred to as USB instead of HID.
3. Added a consumer control device (volume, pause/play, brightness, etc.). See the consumer example.
4. Improved flow control for host-to-device.
i pulled your change for USB power, to my local machine, and then manually checked out the tools files ( from my local master) which had been also changed by your PR, but I think if I merge this back into my local Master (HEAD), it tracks the changes to the tool files as if they were changed twice.
So I think I will need to start again, and manually update the individual USB files, otherwise the git history is confusing as it has those changes to the tools, which are unnecessary
[arpruss – Mon Dec 18, 2017 3:40 pm] –
Added serial number support to the library. Default serial number is 00000000000000000001. It can be specified in the USB.begin() call. You can even make it be the device ID, but then you lose any potential usefulness it might have for cryptographic purposes.
Great job. Is it possible also to assign a text string of the device?
[arpruss – Tue Dec 19, 2017 2:50 pm] –
What do you mean?
I’m talking about the ascii strings that describes the devices:
Bus 001 Device 004: ID 0bda:57f3 Realtek Semiconductor Corp. <---webcam
Bus 001 Device 003: ID 8087:0a2a Intel Corp. <-- bluetooth
Bus 001 Device 007: ID 054c:0268 Sony Corp. Batoh Device / PlayStation 3 Controller <-- PS3 joystick
Bus 001 Device 005: ID 0079:0006 DragonRise Inc. PC TWIN SHOCK Gamepad <-- arkade joystick
Bus 001 Device 006: ID 1eaf:0024 <-- STM32
And added a keyboardwithleds example that echoes keyboard LED status to serial.
[arpruss – Wed Jan 03, 2018 6:06 pm] –
I added a no-wait option for output/feature host-to-device, so that the USB HID handler silently updates the output/feature buffers in the background without polling being needed to ensure that the sketch doesn’t miss data.And added a keyboardwithleds example that echoes keyboard LED status to serial.
Great job!
It’s not composited with serial support, unlike the standard USBHID stuff.

I also added a setSerial() method that lets you turn off the CompositeSerial support, which might be useful for OSes like Win 8.1. Just call USBHID.setSerial(0) before USBHID.begin().
USBHID.begin(HID_KEYBOARD);
Keyboard.begin();
...
ledState = Keyboard.getLEDs();
[RogerClark – Wed Dec 13, 2017 10:45 pm] –
Just a thought, but I noticed someone asking about USB Mass storage…I recall there was some old code from the leaflabs forum, which I tried a long time ago.
I presume that in theory we could add USB mass storage as a library ???
In the “generalizable” branch of the library, I now have working mass storage code. I created a 12K RAM disk hosted on the stm32f1 and successfully formatted it with a hacked version mkdosfs. The API for the mass storage code will change, however.
The “generalizable” branch is meant to allow one to mix and match different “parts” of a composite USB device, e.g., mass storage + hid + serial, or midi + serial, etc. Not all combinations can be expected to work. (E.g., xbox360 + serial doesn’t work.)

The Mass Storage code is based on Joe Ferner’s code. A fun example of the Mass Storage code is in examples/mass, which is probably the world’s most useless USB drive, backed by 12kb of SRAM in the stm32. The drive is pre-formatted to present as a tiny FAT12 disk, and actually seems to work on Windows 10.
Here’s an example for how to set up Keyboard/Mouse/Joystick + MassStorage:
#include <USBHID.h>
#include <USBMassStorage.h>
// supply driveSize, readFunction(offset, buff, len) and writeFunction(offset, buff, len)
void setup() {
MassStorage.setDrive(0, driveSize, readFunction, writeFunction);
MassStorage.registerComponent();
USBHID.setReportDescriptor(HID_KEYBOARD_MOUSE_JOYSTICK);
USBHID.registerComponent();
USBComposite.begin();
Keyboard.println("hello");
}
void loop() {
MassStorage.loop();
}
I will try it at the weekend, when I get some free time…..
I will try it too!
Edit:
Just a basic test.
Got the library from the generalizable branch (there is not mass storage examples in the master branch)
loaded the mass example it doesn’t compile since in MassStorage.h there is a reference to USBComposite.h but there is only the cpp file.
So I got the missing file from the master branch and it compiles.
So it would be possible to get SD card mounted also by just implementing read and write functions ? one could use also spiffs fs and utilize board’s flash memory, although there’s not much of space .
[michael_l – Fri Feb 02, 2018 12:25 pm] –
So it would be possible to get SD card mounted also by just implementing read and write functions ?
Yes: should be very simple (you also need to read the capacity, of course).
I wanted to try this this morning, but I couldn’t get sdfat (either the official version or victor’s version) to recognize either of the two cards I tried. I think my sd card adapter may be broken.
one could use also spiffs fs and utilize board’s flash memory, although there’s not much of space .
Right.
Also, if you just want the host to have read-only access, you can just use the flash straight with a FAT system, and include a disk image. Might be useful for distributing a small driver or script that goes with a device, I suppose.
[arpruss – Fri Feb 02, 2018 4:07 pm] –[michael_l – Fri Feb 02, 2018 12:25 pm] –
So it would be possible to get SD card mounted also by just implementing read and write functions ?Yes: should be very simple (you also need to read the capacity, of course).
I wanted to try this this morning, but I couldn’t get sdfat (either the official version or victor’s version) to recognize either of the two cards I tried. I think my sd card adapter may be broken.
one could use also spiffs fs and utilize board’s flash memory, although there’s not much of space .
Right.
Also, if you just want the host to have read-only access, you can just use the flash straight with a FAT system, and include a disk image. Might be useful for distributing a small driver or script that goes with a device, I suppose.
I hacked earlier SPIFFS to work with WDxxx SPI flash memories on stm32duino. It works but the code is a bit *couch* sketchy. It’s really not a fast fs but feasible for small projects. Together with MSC that would make a nice addition.
I wonder if current libmaple/stm32duino have ready made functions for reading/writing from flash memory ?
[michael_l – Fri Feb 02, 2018 4:22 pm] – I wonder if current libmaple/stm32duino have ready made functions for reading/writing from flash memory ?
Reading is just memcpy.
Writing is here: https://github.com/rogerclarkmelbourne/ … ies/EEPROM
Testing suggests that the low speed is due to SD access rather than due to USB transmission.
[arpruss – Sat Feb 03, 2018 4:54 am] –
I added an SD reader example. It works, but it is ridiculously slow: 11s/mb.Testing suggests that the low speed is due to SD access rather than due to USB transmission.
I re-ran the tests this morning and was getting 479 kb/s reading, which is way better. I have a wonky SD card breadboard adapter, so maybe when the connection is poor there are a lot of retries. At the current speed, with the card and file I was testing, reads take 50% longer than the built-in card reader on my laptop, which isn’t that bad.
[michael_l – Fri Feb 02, 2018 4:22 pm] –
I hacked earlier SPIFFS to work with WDxxx SPI flash memories on stm32duino. It works but the code is a bit *couch* sketchy. It’s really not a fast fs but feasible for small projects. Together with MSC that would make a nice addition.
If you port SPIFFS to the internal flash, you should remember that the internal flash can only be written two bytes at a time. The SPIFFS readme suggests that the library assumes you can always turn 1s into 0s. This isn’t correct for the stm32f1 internal flash. You can turn 0xFFFF to anything, but if a memory word holds anything other than 0xFFFF, you can’t write anything to it, not even 0x0000.
Perhaps it can be used with the Pig-O-Scope code, which already can read the ADC via DMA.
Audio output is a bit more tricky, as the BluePill etc don’t have a DAC. I know there is code to do clever things with PWM to simulate a DAC but I am not sure of the system overhead
There is also Video or Camera input, as we have code that will read the OV7670 camera, at 320 x 240 at around 11 FPS.
I think the frame speed may be a limitation of the ILI9341, that we use to display the image.
( SteveStrong is the guru this)
Unfortunately I have other more pressing commitments of my time, so I can’t help with this
PS. I WIsh I had time to understand the internals of USB as I have several projects where I need to reverse engineer some USB protocols, but they are all on the back-burner because I don’t have time
[arpruss – Sat Feb 03, 2018 4:40 pm] –
There is one more major USB device type that isn’t yet supported: audio. Anybody want to write a USBAudio plugin?
Sorry for simple question but what can I do with the USB Audio – and what kind of specifications there are for USB audio interface ?
Unfortunately, I had to make some changes to the API, as my previous implementation of USB compositing used classes with virtual functions. But when such a class is initialized, automatically all the virtual functions get linked in, even if they are never used.
Two main changes:
1. USBHID.begin() does not include serial any more. To force serial to be included, use the convenience function USBHID_begin_with_serial() instead. And the USBHID.setSerial() method has been removed.
2. To add a component to the composite device, do: component.registerComponent() instead of the previous USBComposite.add(component). See the mass storage examples.
Also, I renamed the mass storage and x360 classes and/or instances.
Try the keyboardwithleds example which should echo the keyboard led status to serial.
“‘myMidi midi’ redeclared as a different kind of symbol”
Is there a quick fix to this? do I need to go in and change one of the two libraries?
Aslo, on one of the three computers I have tried it on, the midi device isn’t found by the computer. (a stationary running win10) Its a blue pill board with the wrong resistor on R10 but curiously the Maple serial port shows up and works just fine. could this still be explained by the R10 resistor value? or is there something else wrong?
[Cpt.Credible – Wed Feb 28, 2018 4:53 pm] –
just adding “#include <MIDI.h> in the “midiin.ino” example throws this error:
“‘myMidi midi’ redeclared as a different kind of symbol”
No need to change the libraries. Just change the example by replacing the midi variable in the example with something else, e.g., usbmidi.
Aslo, on one of the three computers I have tried it on, the midi device isn’t found by the computer. (a stationary running win10) Its a blue pill board with the wrong resistor on R10 but curiously the Maple serial port shows up and works just fine. could this still be explained by the R10 resistor value? or is there something else wrong?
I wouldn’t think the resistor thing would have this kind of effect given that the serial shows up. You might check if joystick shows up (e.g., use the SimpleJoystick example).
For me, the MIDI examples work on Win10pro. But I have occasionally had Windows get confused when switching between different USB devices that all have the same vendor and product ids. So if you plugged the board in in a different mode (e.g., serial or HID), you might have confused Windows. You can try deleting the old driver in the Windows device manager, and then hotplugging again, or changing the product id in the code. E.g., in my midiin example, add midi.setProductId(0x25) before calling midi.begin().
Years ago I argued about the benefit of Mass Storage for a simply reason:
You have finished a project for a third person without really MCU/coding knowledge (call this protoype person “Mother”). There is a mistake in the code you have to correct it, simple for you, but the “third person” cannot upload it as we do. So the “project device” has an upload feature (combined buttons on start, on display, whatever), switching the device to Mass Storage and just plugin to computer, upload the new *.bin file -> ready.
So this should be now possible, isn’t it?
Second:
It should also be possible to switch between USB HID states (like switching from USB-MIDI to USB Mass Storage and so on)?
Regards
Matthias
In fact I would like to use my arduino as an emulated mass storage (like an usb drive) when plugged to a PC providing files stored from a microSD card used with a shield.
sorry for the inconvenience if my message is innapropriate but I can’t find any clue except this page from arduino : https://github.com/arduino/arduino/wiki … ehid-howto
I’m not confident with microcontrollers programming unfortunatelly
It’s all written here:
https://github.com/arduino-libraries/MIDIUSB
“This library allows an Arduino board with USB capabilites to act as a MIDI instrument over USB. The library is based on PluggableUSB, so is only compatible with IDE 1.6.6 and nightly builds (AVR core > 1.6.8, SAM core > 1.6.4, SAMD core > 1.6.1)
Furthermore, since PluggableUSB only targets boards with native USB capabilities, this library only supports these boards (eg. Leonardo, Micro, Due, Zero and so on)
“
But: You can get a STM32 “blue pill” for under 2 Euros on Ebay/Aliexpress, so try it out!
Keep in mind that the “micro” sold on Ebay/Aliexpress is mostly an Atmega 328p!
Edit: This would be your friend, but keep in mind that it costs more than a blue pill!
https://www.aliexpress.com/item/Pro-Mic … 76437.html
I have the version you suggested in the link. I already use the HID.h provided by Arduino to emulate a keyboard but current work seems to only allow keyboard and mouse emulation :-/ Nothing for mass storage emulation ;-(
[arpruss – Thu Mar 01, 2018 2:19 pm] –
No need to change the libraries. Just change the example by replacing the midi variable in the example with something else, e.g., usbmidi.
Ehem, cough, yes, of course.
[arpruss – Thu Mar 01, 2018 2:19 pm] –
For me, the MIDI examples work on Win10pro. But I have occasionally had Windows get confused when switching between different USB devices that all have the same vendor and product ids. So if you plugged the board in in a different mode (e.g., serial or HID), you might have confused Windows. You can try deleting the old driver in the Windows device manager, and then hotplugging again, or changing the product id in the code. E.g., in my midiin example, add midi.setProductId(0x25) before calling midi.begin().
I’ll try that!
I have an existing device/project using HID RAW for high speed data transfer protocol that is implemented on ATMEGA16U2 using LUFA library. I’ll try porting it to STM32 now thanks to this new library that supports HID RAW, eventually. Thank you again, @arpruss.
Also, the recent work on USB mass storage is exciting. The possible simple file upload for firmware upgrade is just dream come true
[petr – Thu Mar 01, 2018 11:01 pm] – I have an existing device/project using HID RAW for high speed data transfer protocol that is implemented on ATMEGA16U2 using LUFA library. I’ll try porting it to STM32 now thanks to this new library that supports HID RAW, eventually.
I should say that HID RAW is not as well tested as other parts of the library. So I won’t be surprised if there are bugs. It’s also set to do host-to-device transmission over the control endpoint, which may not be ideal for speed.
[madias – Thu Mar 01, 2018 3:56 pm] –
You have finished a project for a third person without really MCU/coding knowledge (call this protoype person “Mother”). There is a mistake in the code you have to correct it, simple for you, but the “third person” cannot upload it as we do. So the “project device” has an upload feature (combined buttons on start, on display, whatever), switching the device to Mass Storage and just plugin to computer, upload the new *.bin file -> ready.
I can think on many uses for USB-Storage. I.e. a data logger that can be read just plugging an usb cable and readig as a read-only disk. There is no need to have a complete filesystem on memory. The FAT structures can be simulated on software.
[madias – Thu Mar 01, 2018 3:56 pm] – You have finished a project for a third person without really MCU/coding knowledge (call this protoype person “Mother”). There is a mistake in the code you have to correct it, simple for you, but the “third person” cannot upload it as we do. So the “project device” has an upload feature (combined buttons on start, on display, whatever), switching the device to Mass Storage and just plugin to computer, upload the new *.bin file -> ready.
So this should be now possible, isn’t it?
I think you could do this. You’d probably have to have a virtual disk in the upper 64K of flash, and then you have the host write to that disk, and then you flash from it. But you’d need to worry about bricking the device mid-flash. I think the way I’d implement it would be by writing a custom bootloader which first checks if there is data for flashing in the upper 64K of flash, and if so, it flashes that data and marks it erased. To make the custom bootloader as simple as possible, I would store the .bin file in a container that divides it up into 492 byte chunks (say) and adds a 20 byte header to each chunk, to produce a 512 byte sector. The header would have some magic characters as well as information about where in flash the 492 bytes are supposed to go. The bootloader could then just scan the upper 64K of flash for the magic characters, and write any chunks it finds, and then erase their magic characters after writing them. This would save the bootloader from having to understand FAT.
Second:
It should also be possible to switch between USB HID states (like switching from USB-MIDI to USB Mass Storage and so on)?
Yes. I do it in my Gamecube USB adapter, which can emulate both a standard USB HID device (joystick/keyboard/mouse), or an XBox controller, or dual joysticks, and can switch between the devices by software or hard button.
Basically, you just set up one device, call its begin() method, and then call the end() method, set up another device, and call the begin() method. E.g.:
USBHID.begin(HID_KEYBOARD);
...
USBHID.end(HID_KEYBOARD);
MassStorage.setDrive(0, sizeof(image), read, write);
MassStorage.begin();
...
MassStorage.end();
USBHID.begin(HID_JOYSTICK);
...
USBHID.end();
[arduinoob – Thu Mar 01, 2018 4:22 pm] –
I never heard about STM32 before today and I would like to know if the code shared above is compatible with “classic” arduino nano/pro micro.
No, the code is specific to the STM32F1 platform.
I Hve tried mass storage bootloaders which don’t implement FAT format storage, which are quite small ( not sure if they are less than 8k) but they need special programs on Windows to upload to a non formatted storage device.
Which only makes them marginally better than the DFU based bootloader.
I suppose DFU needs a driver, but you may as well use HID RAW if you need a special tool to upload.
Is there a way to set the device name in the user program ? So far I was editing the header files. It worked but I am switching often so not very practical.
[nicolas_soundforce – Sat Mar 03, 2018 12:00 pm] – Is there a way to set the device name in the user program ? So far I was editing the header files. It worked but I am switching often so not very practical.
USBComposite.setManufacturerString("My Garage");
USBComposite.setProductString("My Thingy");
If you like this behavior, you must call Keyboard.begin() before calling any keyboard functions. (Normally, Keyboard.begin() is optional, but it’s needed for LED state.)
If you don’t like this behavior, you can call Keyboard.setAdjustForHostCapsLock(false).
[arpruss – Sat Mar 03, 2018 3:12 pm] –[nicolas_soundforce – Sat Mar 03, 2018 12:00 pm] – Is there a way to set the device name in the user program ? So far I was editing the header files. It worked but I am switching often so not very practical.
USBComposite.setManufacturerString("My Garage");
USBComposite.setProductString("My Thingy");
[vitor_boss – Sat Mar 03, 2018 5:51 pm] –
Hi, this code could run as HID only?
Sure. Do you mean raw hid? There is example code for that.
As mentioned earlier, after mucking about trying to set up MIDI and serial in parallel for debugging, occasionally setting code up that results in “device malfunctioned” And suddenly, for reasons unbeknownst to me, my computer will no longer detect the MIDI USB device. It still detects the Maple Serial device though. And If I plug it into a different machine, it shows up fine as both the maple serial device and the Midi device.
And when I say it doesn’t show up, I mean it doesn’t show up at all. Windows doesn’t acknowledge that it exists at all. no “unknown device” no “device malfunctioned” it is completely invisible to both device manager and the tool USBdeview by Nirsoft.
[arpruss – Thu Mar 01, 2018 2:19 pm] –
You can try deleting the old driver in the Windows device manager, and then hotplugging again, or changing the product id in the code. E.g., in my midiin example, add midi.setProductId(0x25) before calling midi.begin().
As arpruss suggested, changing the product ID to something else using USBComposite.setProductId() allows my computer to detect and use the MIDI device, but that breaks the maple serial driver that is expecting a Product ID of 4. And on the note of deleting drivers, no amount of driver deletion seems to help. I even used USBdeview to uninstall ALL USB devices ever connected to the machine to no avail.
This magical disappearing has happened on 2 of my machines now, one win10 and one win7 and I appreciate that this is not really an issue with this glorious library, more an issue with my ignorance and my PC. But I am tearing out my hair and was wondering if anybody knows how to fix this.
Is the device blacklisted somewhere at a low level? Is it some hardware on the motherboard that has decided to start ignoring this device? should I just give in and use hardware serial for debugging (not optimal as it seems to be blocking and causing audio dropouts (I’m making a synthesizer))
Any insight or help would be greatly appreciated
EDIT:
All tools for removing “ghost devices” and removing all traces of previously connected devices failed, “Ghostbuster” and “USBOblivion”. What worked though was programming the stm32f103c with the midiout example, upon which it erroneously showed up as a Serial device that wouldn’t start. Right clicking and selecting remove device and uninstall driver allowed it to be rediscovered as a midi device.
[Cpt.Credible – Tue Mar 06, 2018 12:14 pm] –
And when I say it doesn’t show up, I mean it doesn’t show up at all. Windows doesn’t acknowledge that it exists at all. no “unknown device” no “device malfunctioned” it is completely invisible to both device manager and the tool USBdeview by Nirsoft.
When it’s gone missing, do you do Action -> Scan for hardware changes? I’ve had to do that on many occasions so Windows would ‘re-discover’ a device for which I removed (disabled + deleted!) the driver.
Also, does a reboot of the PC help at all?
2. Have you set your device manager to view hidden devices? https://technet.microsoft.com/en-us/lib … 84583.aspx
[arpruss – Wed Mar 07, 2018 5:49 am] –
1. You can install the serial driver for a different product id. Just edit the batch file.
That is handy to know!
[arpruss – Wed Mar 07, 2018 5:49 am] –
2. Have you set your device manager to view hidden devices? https://technet.microsoft.com/en-us/lib … 84583.aspx
Yes, and rebooted, but as I mentioned in the edit it seems like somewhere there was something data I couldn’t find in the registry or using any of the USB device fixing tools I have found that made the computer confused about the MIDI device. Making it show up as ONLY the midi device using the midiout example and then uninstalling the incorrectly recognized “Serial device unable to start” in device manager, fixed the situation. I spoke to some other developers familiar with developing USB and the message I got is that this is a known pain in windows and I should be using linux to develop something like that
On a related note, is there anything else needed in setup() in the midiin example in order to use serial alongside with midi? should there be a CompositeSerial.begin(250000) or something? or is that all handled in the USBComposite.begin()? should I be able to just add a CompositeSerial.println(“Hello world”) in the main loop?
[Cpt.Credible – Wed Mar 07, 2018 8:19 am] –
On a related note, is there anything else needed in setup() in the midiin example in order to use serial alongside with midi? should there be a CompositeSerial.begin(250000) or something?
No. See the README file, which alas is still unfinished. CompositeSerial is a plugin, and the only time you call a plugin’s begin() method is if you are making a simple USB device (with only one plugin). Otherwise, you register the plugins with plugin.registerComponent() and call USBComposite.begin().
or is that all handled in the USBComposite.begin()? should I be able to just add a CompositeSerial.println(“Hello world”) in the main loop?
All you need is the CompositeSerial.println(). Note that there already are calls to CompositeSerial.println() in the noteOn and noteOff handlers in the example.
I was wondering what was the difference between “BootKeyboard” and “Keyboard ? Also is it possible to have NKRO capability for the keyboard ? It would be interesting for building mechanical keyboards. Here are some notes regarding nkro https://github.com/tmk/tmk_core/blob/ma … B_NKRO.txt
https://forum.pjrc.com/threads/23993-Te … O-Keyboard
[Freakeyyy – Wed Mar 07, 2018 10:19 pm] – I was wondering what was the difference between “BootKeyboard” and “Keyboard ?
BootKeyboard cannot be composited with another USB device, but works in system BIOS.
Also is it possible to have NKRO capability for the keyboard ? It would be interesting for building mechanical keyboards.
The default is 6KRO. You can try to increase that to any number you wish, at the expense of slowing down the data transmission and using a bit more memory. To increase it, edit USBHID.h and change the HID_KEYBOARD_ROLLOVER value. This is untested: let me know if it works for you.
It’s possible you will run into trouble above 62. Or above 6. Like I said, it’s not tested.
[arpruss – Wed Mar 07, 2018 2:55 pm] –
Note that there already are calls to CompositeSerial.println() in the noteOn and noteOff handlers in the example.
Are we using the same example? I am using https://github.com/arpruss/USBHID_stm32 … midiin.ino
all I can see in the in the noteOn and noteOff handlers are calls to tone() and noTone()
Is there a more recent version of the library I should be using?
[Cpt.Credible – Thu Mar 08, 2018 4:38 pm] –[arpruss – Wed Mar 07, 2018 2:55 pm] –
Note that there already are calls to CompositeSerial.println() in the noteOn and noteOff handlers in the example.Are we using the same example? I am using https://github.com/arpruss/USBHID_stm32 … midiin.ino
all I can see in the in the noteOn and noteOff handlers are calls to tone() and noTone()Is there a more recent version of the library I should be using?
Oh, I guess I had the code inserted for testing purposes, but not committed.
Board: Maple mini
- SD-Card example works better as expected (decent speed, even without “ex” – I was even able to play MP3 from card)
“Consumer” example is tricky on my Macbook(Hitting the two small buttons right (perpetual bootloader) before the light goes out!)
The mass storage example does not work: Even on Windows or OSX the generated containing device is empty (no files on it). Has anybody checked this?
On OSX (El Captain 10.11.6, Macbook Pro middle 2009) playing with USB-HID can be dangerous. After some examples (I think “consumer”) I wasn’t able to communicate with the maple mini anymore (not even in perpetual bootloader mode or rebooting the system). So I flashed under Windows a simple empty code for getting the maple working again. But this is a OSX specific problem, so it should not matter)
But all in all: Everything is working correct and it’s a major step forward using USB-HID stuff without using an alternative Repro.
So: Thanks Arpuss!
[madias – Wed Apr 04, 2018 10:56 am] –
The mass storage example does not work: Even on Windows or OSX the generated containing device is empty (no files on it). Has anybody checked this?[/list]
I am pretty sure the image in image.h is empty. But you may be able to copy a small file to the drive from the host. At least, last I was testing it on Win10, I could. It wouldn’t surprise me, however, if some operating systems had trouble with a FAT-12 image that is less than 12K in size.
Of course, any file you copy will disappear when you power off the device, as the storage is in RAM.
On OSX (El Captain 10.11.6, Macbook Pro middle 2009) playing with USB-HID can be dangerous. After some examples (I think “consumer”) I wasn’t able to communicate with the maple mini anymore (not even in perpetual bootloader mode or rebooting the system). So I flashed under Windows a simple empty code for getting the maple working again. But this is a OSX specific problem, so it should not matter)
Maybe setting a different USB product ID from the default one when experimenting would help? I am guessing that OSes get confused when you switch USB device types without changing the vendor/product IDs.
[michael_l – Fri Feb 02, 2018 4:22 pm] –
I hacked earlier SPIFFS to work with WDxxx SPI flash memories on stm32duino. It works but the code is a bit *couch* sketchy. It’s really not a fast fs but feasible for small projects. Together with MSC that would make a nice addition.I wonder if current libmaple/stm32duino have ready made functions for reading/writing from flash memory ?
Do you share the SPIFFS hacked?
For me the USB-HID (library) is one of the best features even a little bluepill can provide making it to an outstanding little beast.
[arpruss – Sat Apr 14, 2018 3:05 pm] –
A quick note: The library is now bundled with Roger’s core.
sweet
So as soon as the Blue Pill USB MIDI device receives a MIDI message, the main program simply stops running.
Anybody sucesfully used USB MIDI input ? Is this tested ?
I am using the version including in the last repo.
Thanks,
Nicolas.
class myMidi : public USBMidi {
virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {
}
virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {
}
virtual void handleProgramChange(unsigned int channel, unsigned int program) {
}
};

I am building a sim racing button box with LCD display, magnetic shifters (joystick buttons) and dual clutch paddles (joystick axis).
While testing the joystick axis I noticed that I can only send values from 0 to 1023 for the joystick movement.
When reading my analog clutch (analogRead) I have a 12bit resolution (0 to 4096) which I would like to retain.
In “Joystick.cpp” you have
void HIDJoystick::X(uint16_t val){
if (val > 1023) val = 1023;
joyReport.x = val;
safeSendReport();
}
Tried sdcardreader, mass, absmouse, jigglemouse and mouse jiggler examples.
With Blue103ZET (sdcardreader, STLink upload) and the BluePill (the others, stm32duino bootloader latest).
I uninstalled the HID-bootloader device from my previous exercises.
I got “USB device not recognised” or it installed Maple Serial with SerNum 00000000000000000001 and I see no activity or any special HID device installed (watched with usbdeview).
Win7 64bit here.
Can somebody confirm some of the examples work with Win7 64bit and BPill plz?
What I missed or did wrong way?
PS: I managed to get “mass” working, it even remembers the disk content when plugged off the usb port (powered via stlink)
No fun with mouse yet..
I get this usbdeview:
- Maple Composite.jpg (59.32 KiB) Viewed 760 times

Flashed in the stm32duino bootloader (the generic one). Maple Serial uninstalled (driver deleted).
Compiled (Sloeber) the sdreader demo (set the sdcard’s /CS and the LED pins properly, SdFat (not Ex)), uploaded.
Inserted a 16GB CL10 samsung sdcard into the 103ZET’es socket.
After re-plugging the 103ZET (and cleaning up the old mess with usbdeview), waiting several seconds, I got a window saying the sdcard needs to be reformatted (used in android). I put the sdcard off and reformatted under Win7 (SDformatter). Put the sdcard back into 103ZET, re-plugged and I got again the window saying sdcards needs to be reformatted.
I clicked ok and got the standard Win formatting window offering me beefy 2.92GB/FAT32 size. Ok, understood, started with formatting. After about a ~minute it finished fine and I re-plugged the 103ZET again.
After about 10 secs waiting I got a window with a new drive E:, opened it, was empty, therefore I started to copy a 160MB large Sloeber zip file on it. The copying started with a standard copy window, indicating 13minutes and 216kB/sec speed. While storing the file I wrote this report
It finished ok.
Re-plugged the 103ZET again. Opened E: and checked the file’s sha-1 (took several minutes to read) and it passed.. Nice..
PS: I put the sdcard off the 103ZET’es sdcard socket and double checked under Win7 again, the sha-1 passed..
Note that my mouse example is an absolute rather than the more usual relative mouse. (The JiggerMouse example that I added yesterday is a relative mouse.)
[Pito – Fri Jun 08, 2018 6:46 pm] –
So, tried again with my 103ZET (64kB+512kB of sram and an sdcard socket).
Flashed in the stm32duino bootloader (the generic one). Maple Serial uninstalled (driver deleted).
Compiled (Sloeber) the sdreader demo (set the sdcard’s /CS and the LED pins properly, SdFat (not Ex)), uploaded.Inserted a 16GB CL10 samsung sdcard into the 103ZET’es socket.
After re-plugging the 103ZET (and cleaning up the old mess with usbdeview), waiting several seconds, I got a window saying the sdcard needs to be reformatted (used in android). I put the sdcard off and reformatted under Win7 (SDformatter). Put the sdcard back into 103ZET, re-plugged and I got again the window saying sdcards needs to be reformatted.
I clicked ok and got the standard Win formatting window offering me beefy 2.92GB/FAT32 size. Ok, understood, started with formatting. After about a ~minute it finished fine
and I re-plugged the 103ZET again.
After about 10 secs waiting I got a window with a new drive E:, opened it, was empty, therefore I started to copy a 160MB large Sloeber zip file on it. The copying started with a standard copy window, indicating 13minutes and 216kB/sec speed. While storing the file I wrote this report
It finished ok.Re-plugged the 103ZET again. Opened E: and checked the file’s sha-1 (took several minutes to read) and it passed.. Nice..
PS: I put the sdcard off the 103ZET’es sdcard socket and double checked under Win7 again, the sha-1 passed..
wow, that’s pretty good, i’m wondering how far we can push the 216 KB/s speed, in theory usb 2.0 full speed is capable of 10 mbps which i’d guess could give closer to 1MB per sec
With SdFat or SdFatEX, and
if (sd.begin(SD_CHIP_SELECT, SD_SCK_MHZ(36)))
i’ve had some sd cards with linux partitions which windows give those ‘reformat’ prompts with ‘ordinary’ sd card readers
however, i’m not too sure if there is anything else more than the on disk/card partition (data) format which may cause the prompts
tuning / optimizing it on the stm32f103 c8 or cb could be rather challenging given its 20k sram limits, if we keep a ‘buffer’ of 4k there is 16k left for ‘everything else’ and usb needs its own buffers. currently my guess is that most of the classes and libraries are pretty much modular than ‘optimised to bare metal’, in a sense if we do dedicated optimization between spi and usb and solely for usb mass storage it could pretty much push the limits of what is possible. but keeping it modular would simplify maintenance, make codes more readable, less bugs etc and that it would be easier to ‘plug and play’ modules
i’m thinking that a usb bus with several devices could also be very busy and could in itself be its own bottleneck rather than stm32 itself
just 2 cents
1. 10MB file copy PC->BlueZET: 33secs, 303kB/sec
2. 10MB file copy BlueZET->PC: 21secs, 476kB/sec
With the 10MB file on the sdcard the E: window appears 3secs after plugging in the BlueZET into the usp port.
I’m running into an issue when using your lib, basically the device hangs as soon as it goes into any code related to USB. First of all, no matter which example I test, I only see “Maple Serial” in devices (using Windows),so no additional devices appear. If I just use blink example it works ok, so there’s no issue with flashing the chip. However if I use any of the USBComposite examples, the board doesn’t do anything. If I modify example to blick a few times before executing USB function (i.e. before Keyboard.print()), it blinks and then hangs. Commenting use of such USB function makes the device run it’s loop without issues.
Any ideas why this could be? I think the most direct indicator of the issue is that no additional device appears in the system. Could it be because I have not replaced the default 10kOhm resistor R10? As I mentioned before, device shows up as DFU ok (when using bootloader_only bootloader), as well as Serial (when using bootlear+empty scketch type of bootleader), and I can reflash it using Arduino IDE “stm32duino bootloader” mode without issues. I uploaded bootleader using J-Link, if that matters.
Thank you, that helped!
arpruss, Pito,
Now I’ve found out that USBMIDI is not compatible with other components. WHich is not the case with main Arduino libs, there they’re based on some “pluggableUSB” module and I can instantiate Serial + Keyboard + Mouse + MIDI just by including headers Keyboard.h, Mouse.h MIDIUSB.h and having “Keyboard.begin()…” in my setup. With USBComposite I have this code:
#ifdef _LIBMAPLE_STM32_H_ //my goal is to make the same app compile on stm and arduino so I'm testing this #ifdef thing... works ok
#include <USBComposite.h>
#include <USBMIDI.h>
#endif
void setup() {
USBHID.setReportDescriptor(hidReportKeyboardMouse); // most likely this is not compatible as MIDIUSB is also a HID device?
USBComposite.clear();
CompositeSerial.registerComponent();
USBHID.registerComponent();
//USBMIDI.registerComponent(); // if I uncomment this, the device is not recognized
USBComposite.begin();
}
void loop() {
delay(10000);
}
I think Windows doesn’t recognize all possible combinations.
HID+MIDI+Serial can’t seem to work all together.
MIDI+Serial works.
MIDI+HID works.
Serial+MID and HID+MIDI didn’t work, due to a bug in the library that required MIDI to be the first registered component. I just fixed the bug. It doesn’t help with HID+MIDI+Serial. Maybe that’s just too much for Windows to handle.

I think the most attractive combo would be the Serial + Mass Storage..
[Pito – Wed Jun 13, 2018 4:51 pm] –
I think the most attractive combo would be the Serial + Mass Storage..
That works fine.
There are 320 bytes of hardware buffer memory available after endpoint 0 is taken into account. The following
are the buffer memory needs of the current components:
* USB Serial: 144 bytes
* USB HID: 64 bytes
* USB Mass Storage: 128 bytes
* USB MIDI: 128 bytes
* XBox360 controller: 64 bytes
This places a limit on what combinations can be used together. For instance, HID+Mass storage+MIDI should be theoretically
OK (320 bytes), but Serial+HID+Mass storage (336 bytes) will fail (and return false from USBComposite.begin()) due to
lack of memory.
void setup() {
USBHID.setReportDescriptor(hidReportKeyboardMouse);
USBComposite.clear();
USBMIDI.registerComponent(); // 128 bytes of PMA
USBHID.registerComponent(); // 64 bytes of PMA
CompositeSerial.setRXPacketSize(32);
CompositeSerial.setTXPacketSize(32);
CompositeSerial.registerComponent(); // 80 bytes of PMA (cannot control size of control channel PMA)
USBComposite.begin(); // total 272 bytes of PMA, out of 320 available
}
See: https://github.com/arpruss/USBHID_stm32 … O-0.90.txt
Also, note that all examples have been updated to the new API.