Spark Logic

USB Composite (HID / MIDI / Mass Storage) library

arpruss

I’ve worked hard to bring the addMidiHID branch of the libmaple-based core up to date, and even made a pull request to merge that into the main branch, but then today I realized that it would be simpler for maintenance and customization to put all the stuff into a separate library, making use of the fact that the core’s USB serial support has __weak references where it matters.

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);
}

Replies8

arpruss Tue Jun 12, 2018 2:04 pm

I would experiment with the order and combination of components. Try midi+serial and midi+hid.
I think Windows doesn’t recognize all possible combinations.

arpruss Wed Jun 13, 2018 3:32 pm

I did some experiments with Win10.

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.

Pito Wed Jun 13, 2018 4:51 pm

Statistically it is more probable the issue is in the library than in the WinX :)

I think the most attractive combo would be the Serial + Mass Storage..

arpruss Wed Jun 13, 2018 9:10 pm

[Pito – Wed Jun 13, 2018 4:51 pm] –
I think the most attractive combo would be the Serial + Mass Storage..

That works fine.

arpruss Wed Jun 13, 2018 10:01 pm

I found why some combinations don’t work and added this to the readme file:

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.

arpruss Thu Jun 14, 2018 9:33 am

I’m adding code to control the buffer sizes. I’ve just added it in the repository to the composite serial code, and may add it to the other plugins, too. For instance, you can now do:
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
}

arpruss Sun Jun 17, 2018 7:57 pm

I’ve added code so you can control packet size in HID and MIDI, too, and some more information on combining plugins has been added to the README.md file.

arpruss Thu Aug 16, 2018 2:49 pm

I’ve made major revisions to the library to save flash and RAM. Previously, there were lots of convenience instances like BootKeyboard and USBHID defined. In the new version, the only convenience object is USBComposite. Everything else needs to be explicitly instanced. This requires minor rewrites to all code using the library.

See: https://github.com/arpruss/USBHID_stm32 … O-0.90.txt

Also, note that all examples have been updated to the new API.

Sign in to reply