Git Product home page Git Product logo

usbcomposite_stm32f1's Introduction

USB Composite library for Roger's Melbourne's STM32F1 core: https://github.com/rogerclarkmelbourne/Arduino_STM32/

Protocols supported

  • standard USB HID, with many built-in profiles, and customizable with more

  • MIDI over USB

  • XBox360 wired and wireless controllers

  • Mass storage

  • USB Audio (unidirectional, but both directions are supported)

Basic concepts

Start with:

#include <USBComposite.h>

The library defines one central singleton object:

extern USBCompositeDevice USBComposite;

This controls USB device identification as well as registers the plugins that are connected to it.

Plugin classes included in the library:

USBHID
USBMIDI
USBMultiXBox360<n> / USBXBox360 / USBXBox360W<n>
USBMassStorage
USBCompositeSerial
USBMultiSerial<n>

NOTE: Only one of USBMultiXBox360 / USBXBox360 / USBXBox360W can be registered at a time: they cannot be composited together.

To use the plugins, you need to create instances of them. NOTE: Only one instance of each plugin class can be created.

If you want to make a simple (non-composite) USB device, you can create an instance of the plugin class and call the begin() method, and it will take care of registering itself with USBComposite and starting up USBComposite. If you want to make a composite USB device, however, you need to control the device with USBComposite:

USBComposite.clear(); // clear any plugins previously registered
plugin1.registerComponent(); 
plugin2.registerComponent();
USBComposite.begin();

Of course, you may need to do some further configuring of the plugins (e.g., if plugin1 is USBHID, then you may want to do USBHID.setReportDescriptor(HID_KEYBOARD)) or of the USBComposite device before the USBComposite.begin() call.

After starting up USBComposite, it's a good idea to wait for it to become ready before sending any data:

while(!USBComposite);

Finally, there are a number of classes that implement particular protocols for the USBHID class plugin. These include:

HIDMouse
HIDKeyboard
HIDJoystick
HIDAbsMouse
HIDConsumer
HIDRaw<txSize,rxSize>
HIDSwitchController

And you can customize with more. Moreover, the USBHID plugin itself allows for compositing multiple HID profiles, e.g., Mouse / Keyboard / three joysticks. Each of these has at least one required parameter, which is an instance of USBHID.

Not all combinations will fit within the constraints of the STM32F1 USB system, and not all combinations will be supported by all operating systems.

I recommend calling USBComposite.setDeviceId(device) with a different device number for each combination of plugins and profiles to prevent problems with cached configurations on the host computer.

Uploading with STM32duino bootloader

Normally, the STM32duino bootloader upload method in the Roger Melbourne STM32F1 core sends a command to reset the board via the USB serial port, and thereby put it in bootloader mode, just prior to uploading. If you have installed a sketch that includes a USB serial port in the composite device, this should still work. But if the sketch you've installed doesn't include a USB serial port, then you need to manually activate the bootloader mode next time you want to upload a sketch.

The bootloader mode is active for a short period after the board powers up or resets. So just initiate the upload in the Arduino IDE as usual, but when "Searching for DFU device [1EAF:0003]" is displayed, hit the reset button (or if the device is USB-powered, keep it unplugged from USB and plug it in when you get this message).

Simple USB device configuration

A simple USB device uses a single plugin. You need to create an instance of the plugin class, call any setup methods for the plugin and the begin() method for the plugin. For instance, to inject keyboard data, you should do:

USBHID HID; // create instance of USBHID plugin
HIDKeyboard Keyboard(HID); // create a profile

HID.begin();

and then call Keyboard.print("TextToInject") to inject keyboard data. Some plugin configurations may require further initialization code or further code that needs to be called inside the Arduino loop() function.

See the BootKeyboard, midiout and x360 example code for variants on this procedure.

(Additionally, the USBHID plugin has a convenience begin() method that lets you include an instance of a USBCompositeSerial plugin class, and that creates a composite HID-Serial device.)

However, if you want a USB device using more than one plugin, then you will NOT call the plugin's begin() method.

Note that a single HID plugin can support a device with multiple report profiles including a keyboard, several joysticks, a mouse, etc.:

USBHID HID; // create instance of USBHID plugin
HIDKeyboard Keyboard(HID); // create a profile
HIDJoystick Joystick1(HID); // create a profile
HIDJoystick Joystick2(HID); // create a profile
HIDMouse Mouse(HID); // create a profile

HID.begin();

Each of the profiles (e.g., Joystick1) contributes a part of the HID report descriptor to USBHID which automatically stitches them together and assigns report IDs. However, you can also make a single overarching custom HID report descriptor and include it in the HID.begin() call. The softjoystick example does this.

Memory limitations

There are 320 bytes of hardware buffer memory available after endpoint 0 is taken into account. The following are the default 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 with default settings (and return false from USBComposite.begin()) due to lack of memory.

However, USB Serial, USB HID and USB MIDI allow you to decrease buffer sizes (and allow for more complex composite devices) by calling:

USBHID HID;
USBCompositeSerial CompositeSerial;
USBMIDI MIDI;

CompositeSerial.setRXPacketSize(size);
CompositeSerial.setTXPacketSize(size);
HID.setTXPacketSize(size); 
MIDI.setRXPacketSize(size);
MIDI.setTXPacketSize(size);

The maximum and default packet size is 64. Smaller packet sizes have not been thoroughly tested and may slow things down. In particular, for HID you should make sure your packet size is sufficient for your largest HID report. The CompositeSerial device also has a control channel whose 16 byte packet size is not adjustable. Note that for reasons that I do not currently understand, CompositeSerial RX packets must be a power of two in size.

Note also that in the above, RX and TX are from the point of view of the MCU, not the host (i.e., RX corresponds to USB Out and TX to USB In).

Endpoint limitations

There is one bidirectional endpoint 0 that all endpoints share, and the hardware allows for seven more in each direction, but there are some complications in that the same endpoint number when used in different directions must have some of the same parameters. The USBComposite library takes care of these complications when allocating endpoints, but if you have too many plugins, you USBComposite.begin() will return false to indicate that you've used up too many.

This is pretty complicated, but a rule of thumb for having enough endpoints is to make sure that when you add up the following contributions for the plugins you use, your total is at most seven.

  • USB Serial: 2 (= 2 TX, 1 RX)

  • USB HID: 1 (= 1 TX)

  • USB Mass Storage: 1 (= 1 TX, 1 RX)

  • USB MIDI: 1 (= 1 TX, 1 RX)

  • XBox360 Controller: 1 per controller (= 1 TX, 1 RX)

  • USB Audio: 1 (= 1 TX or 1 RX depending on mode)

  • USB Multi Serial: 2 per port (= 2 TX, 1 RX)

usbcomposite_stm32f1's People

Contributors

4dvn avatar ardustorm avatar arpruss avatar ayavilevich avatar gromain avatar per1234 avatar semicontinuity avatar soreau avatar tomaszduda23 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

usbcomposite_stm32f1's Issues

Waiting for USBComposite

Arduino beginner trying the library out and running while (!USBComposite); gives me a compilation error

Sketch1.ino: 101:9: error: no match for 'operator!' (operand type is 'USBCompositeDevice')
Build failed for project 'Sketch1'
   if (millis() > t + 250) {
Sketch1.ino:101: note  candidate is
Sketch1.ino:101: note  operator!(bool) <built-in>
Sketch1.ino:101: note    no known conversion for argument 1 from USBCompositeDevice to bool

Midi in and Midi out in same component ?

Hello,

I m trying to create a midi in and out device. I can receive messages without problem. But I can't send messages. In usb_midi_tx function (usb_midi_device.c), usb_midi_is_transmitting() always return true. So usb_midi_tx function do nothing... If you have an idea, I ll be thankful :)

Regards,
Aurélien

Strange USBMIDI behaviour

Hello All.

Relatively new programmer and newb embedded system guy here, but old-time midi guru.

My programming/hardware/USBComposite library is encountering a weird issue that I can't seem to troubleshoot in the code. I am trying to dedicate 8 pins as outputs (PWM-capable outputs, to drive LEDs) and another 8 as digital inputs.

Everything is working well to a point:

A press-and-hold on an input sends a MIDI note ON out via USB. The associated output port lights up the LED. A release sends the corresponding MIDI note OFF, and the LED turns back off.
Additionally, a quick 'tap' of an input switch sends a MIDI ON note with no corresponding OFF. The subsequent press/release sends the OFF upon release.

BUT... then I set certain outputs to HIGH, and suddenly I am sending several predictable-yet-unintended MIDI note ON and OFF messages with every input trigger cycle. I have no idea why the status of an output port should be affecting the MIDI data being triggered.

For my part, this could be hardware, this could be library, or this could be my own poor coding/hardware knowledge.

I'll post my code below. Any insight would be appreciated.

_#include <USBComposite.h>

//Note assignment 
struct Assignment {
  byte note;
  byte notePin;
  byte ledPin;
};
struct State {
  byte currentPinStatus;
  byte prevPinStatus;
  bool tapCountFlag;
  int tapCount;
  bool heldNoteFlag;
};
struct ActionBuffer {
  Assignment assignment;
  State state;
};

//Data
const byte pinOFF = HIGH;
const byte pinON = LOW;
const byte loopDelay = 10;
const int tapDelay = 150;
const byte defaultPinValue = 2;
const byte boardLEDPin = 32;

State defaults = {defaultPinValue, defaultPinValue, false, 0, false};

//Pin 0 as LED output causes additional MIDI notes to be sent. (notes 0, 9, and 97... both ON and OFF commands are sent.)
//Pin 16 as LED output causes additional MIDI notes to be sent. (notes 0, 9, and 97... both ON and OFF commands are sent.)
//Using Pins 8, 9, 10, 17, 22, 23, 24, or 25 as LED output causes a suite of unintended MIDI notes to be sent.


Assignment assignments[] = {
  Assignment {note: 60, notePin: 19, ledPin: 1},
  Assignment {note: 61, notePin: 20, ledPin: 2},
  Assignment {note: 62, notePin: 21, ledPin: 3},
  Assignment {note: 63, notePin: 15, ledPin: 6},
  Assignment {note: 64, notePin: 31, ledPin: 7}
};
ActionBuffer actionBuffers[sizeof(assignments)] = {};
USBMIDI midi;
void LEDOn() {
  if (digitalRead(boardLEDPin) == HIGH) {
    digitalWrite(boardLEDPin, LOW);
  }
};
void LEDOff() {
  if (digitalRead(boardLEDPin) == LOW) {
    digitalWrite(boardLEDPin, HIGH);
  }
};
void flashLED(byte qty) {
  for (int i = 0; i < qty; i++) {
    LEDOn();
    delay(10);
    LEDOff();
  }
};
void setup() {
  //From Example
  USBComposite.setProductId(0x0031);
  midi.begin();
  delay(1000);
  //Chris's Setup Code
  for (int i = 0; i < sizeof(assignments); i++) {
    Assignment thisAssignment = assignments[i];
    actionBuffers[i] = {assignments[i], defaults};
    pinMode(actionBuffers[i].assignment.notePin, INPUT_PULLUP);
    pinMode(actionBuffers[i].assignment.ledPin, OUTPUT);
    //digitalWrite(actionBuffers[i].assignment.ledPin, LOW);
  };
  pinMode(boardLEDPin, OUTPUT);
  LEDOff();
}
void loop() {
  for (int i = 0; i < sizeof(assignments); i++) {
    //Shift existing pin value to 'previous' and check new status
    actionBuffers[i].state.prevPinStatus = actionBuffers[i].state.currentPinStatus;
    actionBuffers[i].state.currentPinStatus = digitalRead(actionBuffers[i].assignment.notePin);
    //If tap flag is on,
    if (actionBuffers[i].state.tapCountFlag == true) {
      //increment the tapDelayCount
      actionBuffers[i].state.tapCount += loopDelay;
      //if tap count is over the theshold
      if (actionBuffers[i].state.tapCount >= tapDelay) {
        //turn off the flag
        actionBuffers[i].state.tapCountFlag = false;
      };
    }
    //if tap flag is off
    if (actionBuffers[i].state.tapCountFlag == false) {
      //reset the counter
      actionBuffers[i].state.tapCount = 0;
    };

    //Skip the rest of this loop iteration if the pin has not changed
    if (actionBuffers[i].state.currentPinStatus != actionBuffers[i].state.prevPinStatus) {
      //If pin has changed to ON...
      /*else*/ if (actionBuffers[i].state.currentPinStatus == pinON) {
        //and the held note flag is off
        if (actionBuffers[i].state.heldNoteFlag == false) {
          //play note on
          midi.sendNoteOn(0, actionBuffers[i].assignment.note, 127);
          //and turn on tap count flag
          actionBuffers[i].state.tapCountFlag = true;
         digitalWrite(actionBuffers[i].assignment.ledPin, HIGH);    
        }
        //but if the held note flag is on
        else {
          //clear the held note flag
          actionBuffers[i].state.heldNoteFlag = false;
        }
      }
      //If pin has changed from ON
      /*else*/ if (actionBuffers[i].state.prevPinStatus == pinON && actionBuffers[i].state.currentPinStatus != pinON) {
        //and if tap count flag is OFF
        if (actionBuffers[i].state.tapCountFlag == false) {
          //turn note off
          midi.sendNoteOff(0, actionBuffers[i].assignment.note, 127);
         digitalWrite(actionBuffers[i].assignment.ledPin, LOW);    
        }
        //but if tap count flag is ON
        else {
          //throw the held note flag.
          actionBuffers[i].state.heldNoteFlag = true;
          //And clear the tap count flag
          actionBuffers[i].state.tapCountFlag = false;
          flashLED(1);
        }
      }
    }
  };
  delay(loopDelay);
  //flashLED(2);
}_

Some random noise on dmesg when inserting board

[20211.676311] cdc_acm 2-2:1.2: urb 4 failed submission with -19
[20211.677315] cdc_acm 2-2:1.2: urb 5 failed submission with -19
[20211.678312] cdc_acm 2-2:1.2: urb 6 failed submission with -19
[20211.679315] cdc_acm 2-2:1.2: urb 7 failed submission with -19
[20211.680201] cdc_acm 2-2:1.1: failed to set dtr/rts
[20211.680311] cdc_acm 2-2:1.2: urb 8 failed submission with -19
[20211.681311] cdc_acm 2-2:1.2: urb 9 failed submission with -19
or/and
[20938.069525] cdc_acm 2-2:1.2: urb 15 failed submission with -19
[20938.070523] cdc_acm 2-2:1.2: urb 0 failed submission with -19
[20938.071522] cdc_acm 2-2:1.2: urb 1 failed submission with -19
[20938.072524] cdc_acm 2-2:1.2: urb 2 failed submission with -19
[20938.073524] cdc_acm 2-2:1.2: urb 3 failed submission with -19
[20938.074526] cdc_acm 2-2:1.2: urb 4 failed submission with -19
[20938.075528] cdc_acm 2-2:1.2: urb 5 failed submission with -19
[20938.075562] cdc_acm 2-2:1.1: failed to set dtr/rts
[20938.078526] cdc_acm 2-2:1.2: urb 8 failed submission with -19
as already reported getting random numbers

After that log looks clean:
[20215.908051] usb 2-2: new full-speed USB device number 79 using uhci_hcd
[20216.082369] usb 2-2: New USB device found, idVendor=1eaf, idProduct=0003
[20216.082376] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[20216.082381] usb 2-2: Product: Maple 003
[20216.082386] usb 2-2: Manufacturer: LeafLabs
[20216.082390] usb 2-2: SerialNumber: LLM 003
[20217.380118] usb 2-2: USB disconnect, device number 79
[20217.644037] usb 2-2: new full-speed USB device number 80 using uhci_hcd
[20217.823371] usb 2-2: New USB device found, idVendor=1eaf, idProduct=0004
[20217.823377] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[20217.823380] usb 2-2: Product: Maple
[20217.823384] usb 2-2: Manufacturer: LeafLabs
[20217.823387] usb 2-2: SerialNumber: 00000000000000000001
[20217.852482] input: LeafLabs Maple as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/0003:1EAF:0004.0007/input/input14
[20217.914098] hid-generic 0003:1EAF:0004.0007: input,hidraw1: USB HID v1.10 Mouse [LeafLabs Maple] on usb-0000:00:1d.0-2/input0
[20217.914511] cdc_acm 2-2:1.1: ttyACM0: USB ACM device
[20286.820117] usb 2-2: USB disconnect, device number 80
[20294.276059] usb 2-2: new full-speed USB device number 81 using uhci_hcd
[20294.450840] usb 2-2: New USB device found, idVendor=1eaf, idProduct=0003
[20294.450845] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[20294.450848] usb 2-2: Product: Maple 003
[20294.450852] usb 2-2: Manufacturer: LeafLabs
[20294.450855] usb 2-2: SerialNumber: LLM 003
[20295.500120] usb 2-2: USB disconnect, device number 81
[20295.908076] usb 2-2: new full-speed USB device number 82 using uhci_hcd
[20296.090848] usb 2-2: New USB device found, idVendor=1eaf, idProduct=0004
[20296.090854] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[20296.090858] usb 2-2: Product: Maple
[20296.090862] usb 2-2: Manufacturer: LeafLabs
[20296.090865] usb 2-2: SerialNumber: 00000000000000000001
[20296.122220] input: LeafLabs Maple as /devices/pci0000:00/0000:00:1d.0/usb2/2-2/2-2:1.0/0003:1EAF:0004.0008/input/input15
[20296.181676] hid-generic 0003:1EAF:0004.0008: input,hidraw1: USB HID v1.10 Mouse [LeafLabs Maple] on usb-0000:00:1d.0-2/input0
[20296.181976] cdc_acm 2-2:1.1: ttyACM0: USB ACM device

midiin.ide didn't work in an WireSlave environment?

i use stm32duino in a linux environment.

my IDE is eclipse.

i create a new arduino sketch and use the midiin from USBCompositeexamples as a template.

i build and flash the sketch and everything works fine.

now i add the WireSlave library to the project.

i build and flash the sketch and now i get USB errors (EPROTO), the device don't get recognized.

thanks.

Touch Screen Example, Help!!!

Based on your work, I have developed the Touch Screen class after reading the document (DigitizerDrvs_touch),but it does not work well! Windows 10 can recognize it as the HID device not a pen or a touch panel. I think maybe it needs to send the feature data to win os. Now I have no idea about responsing the GET_REPORT or SET_REPORT request, Could you give me some suggestions?

Development Environment

  • stm32f103c8t6
  • win10

ReportDescriptor

#define MAX_TOUCH_POINT 0x0a /* 最多支持多少点触摸 */
#define HID_MTS_REPORT_ID 0x01
#define HID_STS_REPORT_ID 0x02
#define FEAUTURE_REPORT_ID 0x03

#define HID_TOUCH_SCREEN_REPORT_DESCRIPTOR(...)                             \
  0x05, 0x0d,                  /*  USAGE_PAGE (Digitizers) */               \
      0x09, 0x04,              /*  USAGE (Touch Screen) */                  \
      0xa1, 0x01,              /*  COLLECTION (Application) */              \
      0x85, HID_MTS_REPORT_ID, /*    REPORT_ID */                           \
      0x09, 0x22,              /*    USAGE (Finger) */                      \
      0xa1, 0x02,              /*    COLLECTION (Logical) */                \
      0x09, 0x42,              /*      USAGE (Tip Switch) */                \
      0x15, 0x00,              /*      LOGICAL_MINIMUM (0) */               \
      0x25, 0x01,              /*      LOGICAL_MAXIMUM (1) */               \
      0x75, 0x01,              /*      REPORT_SIZE (1) */                   \
      0x95, 0x01,              /*      REPORT_COUNT (1) */                  \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x32,              /*      USAGE (In Range) */                  \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x47,              /*      USAGE (Touch Valid) */               \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x05,              /*      REPORT_COUNT (5) */                  \
      0x81, 0x03,              /*      INPUT (Cnst,Ary,Abs) */              \
      0x25, MAX_TOUCH_POINT,   /*      LOGICAL_MAXIMUM (MAX_TOUCH_POINT) */ \
      0x75, 0x08,              /*      REPORT_SIZE (8) */                   \
      0x09, 0x51,              /*      USAGE (Contact Identifier) */        \
      0x95, 0x01,              /*      REPORT_COUNT (1) */                  \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs4) */             \
      0x05, 0x01,              /*      USAGE_PAGE (Generic Desktop) */      \
      0x26, 0x00, 0x10,        /*      LOGICAL_MAX9MUM (4096 ) */           \
      0x75, 0x10,              /*      REPORT_SIZE (16) */                  \
      0x55, 0x00,              /*      UNIT_EXPONENT (0) */                 \
      0x65, 0x00,              /*      UNIT (None) */                       \
      0x09, 0x30,              /*      USAGE (X) */                         \
      0x35, 0x00,              /*      PHYSICAL_MINIMUM (0) */              \
      0x46, 0x00, 0x00,        /*      PHYSICAL_MAXIMUM (0) */              \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x31,              /*      USAGE (Y) */                         \
      0x46, 0x00, 0x00,        /*      PHYSICAL_MAXIMUM (0) */              \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0xc0,                    /*    END_COLLECTION */                      \
      0xa1, 0x02,              /*    COLLECTION (Logical) */                \
      0x05, 0x0d,              /*      USAGE_PAGE (Digitizers) */           \
      0x09, 0x42,              /*      USAGE (Tip Switch) */                \
      0x15, 0x00,              /*      LOGICAL_MINIMUM (0) */               \
      0x25, 0x01,              /*      LOGICAL_MAXIMUM (1) */               \
      0x75, 0x01,              /*      REPORT_SIZE (1) */                   \
      0x95, 0x01,              /*      REPORT_COUNT (1) */                  \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x32,              /*      USAGE (In Range) */                  \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x47,              /*      USAGE (Touch Valid) */               \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x05,              /*      REPORT_COUNT (5) */                  \
      0x81, 0x03,              /*      INPUT (Cnst,Ary,Abs) */              \
      0x25, MAX_TOUCH_POINT,   /*      LOGICAL_MAXIMUM (MAX_TOUCH_POINT) */ \
      0x75, 0x08,              /*      REPORT_SIZE (8) */                   \
      0x09, 0x51,              /*      USAGE (Contact Identifier) */        \
      0x95, 0x01,              /*      REPORT_COUNT (1) */                  \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x05, 0x01,              /*      USAGE_PAGE (Generic Desktop) */      \
      0x26, 0x00, 0x10,        /*      LOGICAL_MAX9MUM (4096 ) */           \
      0x75, 0x10,              /*      REPORT_SIZE (16) */                  \
      0x55, 0x00,              /*      UNIT_EXPONENT (0) */                 \
      0x65, 0x00,              /*      UNIT (None) */                       \
      0x09, 0x30,              /*      USAGE (X) */                         \
      0x35, 0x00,              /*      PHYSICAL_MINIMUM (0) */              \
      0x46, 0x00, 0x00,        /*      PHYSICAL_MAXIMUM (0) */              \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0x09, 0x31,              /*      USAGE (Y) */                         \
      0x46, 0x00, 0x00,        /*      PHYSICAL_MAXIMUM (0) */              \
      0x81, 0x02,              /*      INPUT (Data,Var,Abs) */              \
      0xc0,                    /*    END_COLLECTION */                      \
      0x05, 0x0d,              /*    USAGE_PAGE (Digitizers) */             \
      0x09, 0x54,              /*    USAGE (Contact Count) */               \
      0x95, 0x01,              /*    REPORT_COUNT (1) */                    \
      0x75, 0x08,              /*    REPORT_SIZE (8) */                     \
      0x15, 0x00,              /*    LOGICAL_MINIMUM (0) */                 \
      0x25, MAX_TOUCH_POINT,   /*    LOGICAL_MAXIMUM (MAX_TOUCH_POINT) */   \
      0x81, 0x02,              /*    INPUT (Data,Var,Abs) */                \
      0x09, 0x55,              /*    USAGE (COntact Count Maximum) */       \
      0xb1, 0x02,              /*    FEATURE (Data,Var,Abs) */              \
      0xc0,                    /*  END_COLLECTION */

getMIDIPartDescriptor setting wrong packet size

The getMIDIPartDescriptor function in usb_midi_device.c is setting both the Rx and Tx endpoints of the descriptor to the same usb_midi_txEPSize value instead of setting the Rx to rxEPSize:

OUT_16(usbMIDIDescriptor_Config, DataInEndpoint.wMaxPacketSize) = usb_midi_txEPSize;
OUT_16(usbMIDIDescriptor_Config, DataOutEndpoint.wMaxPacketSize) = usb_midi_txEPSize;


This contradicts the logic of usb_midi_setTXEPSize and usb_midi_setRXEPSize and having separate Rx and Tx sizes:

void usb_midi_setTXEPSize(uint32_t size) {
size = (size+3)/4*4;
if (size == 0 || size > 64)
size = 64;
midiEndpoints[1].pmaSize = size;
usb_midi_txEPSize = size;
}
void usb_midi_setRXEPSize(uint32_t size) {
size = (size+3)/4*4;
if (size == 0 || size > 64)
size = 64;
midiEndpoints[0].pmaSize = size;
rxEPSize = size;
}


It seems line 289 should change as:

---    OUT_16(usbMIDIDescriptor_Config, DataOutEndpoint.wMaxPacketSize) = usb_midi_txEPSize;
+++    OUT_16(usbMIDIDescriptor_Config, DataOutEndpoint.wMaxPacketSize) = rxEPSize;


I don't see any reason it would be using the same Tx size for both and seems to be working only because the Rx and Tx sizes are generally set to the same value. Though on the other hand, if there is a reason for them to be the same that I'm not seeing, it should at least be appropriately commented in the code.

Need help for midi

Can you adding the example of midi controller with button push with note ( or matrix midi button ) and potentiometer ?

How to change MIDI device source name from Maple?

My composite MIDI device is working perfectly however I'd like to change how it displays on the host as something different than Maple. I've searched the library header files and elsewhere looking where this might be defined to no avail.

Such a great library this is. Thank you!

MIDI + Keyboard + Serial

How can i do this

HID.begin(HID_KEYBOARD);

midi.registerComponent();
CompositeSerial.registerComponent();

?

TwoJoysticks Example

Hi,
first of all congratulations for your job!! amazing and really usefull.
I tested the example provided and most of them works nicely.
Unfortunatly I tried the twojoystick.ino and it won't create the serial communication.
The Joysticks are well pointed. I can find them with a small utility and they work properly. BUT the serial port won't show up! no serial communication possible.
Any ideas around this?

I then try to add RawHid and joystick and again no way, it seems taht the descriptor is courruped when we add both. I need on joystick with a few buttons and the possibility to communicate (set ouptu) via either seerial or Raw. I would prefer Raw as no inf would then be needed.

Multiple USBHID instances ( Multiple HID Devices Mouse and RawHID )

Hello,

I Have an issue with instancing 2 separate HID Devices a Mouse and RawHID.
The code as Follows:

#include <USBComposite.h>

#define TXSIZE 256
#define RXSIZE 256

USBHID HID;
HIDRaw<TXSIZE,RXSIZE> raw(HID);

USBHID HIDMouse;
HIDAbsMouse mouse(HIDMouse);

const uint8_t reportDescriptionRaw[] = {
   HID_RAW_REPORT_DESCRIPTOR(TXSIZE,RXSIZE)
};
const uint8_t reportDescriptionMouse[] = {
  HID_ABS_MOUSE_REPORT_DESCRIPTOR(2)
};
void setup(){
  HIDMouse.setReportDescriptor(reportDescriptionMouse, sizeof(reportDescriptionMouse));
  HIDMouse.registerComponent();
  HID.setReportDescriptor(reportDescriptionRaw, sizeof(reportDescriptionRaw));
  HID.registerComponent();
  USBComposite.begin();
  raw.begin();
}

void loop(){
  // Data Gathering and Proccessing then sending via Raw
  //raw.send(data, sizeof(data));
  mouse.move(0,0);
  delay(1000);
  mouse.move(16384,16384);
  delay(1000);
  delay(5);
}

I think the problem is that the library sends the last Report Descriptor that was registered via the setReportDescriptor method.

There are 2 HID Devices but only the last one is Functional :
image

If I change the order of the 'setReportDescriptor' to report the Mouse last, the HIDRAW device stops and the mouse is instantiated instead like this:
image

SDReader Example

The SDReader example does not work for me (on blue pill). It compiles OK, but on one computer, nothing happens. When I plug the board to another laptop, it shows a a drive, when I click the drive, an error pops up.
I verified the connections using an SDFat example.

Mouse Polling rate to 1000Hz

Hello,
I need some help getting the mouse to work on 1000 Hz, I changed the bInterval setting in usb_hid.c to 0x01 :
.bInterval = 0x01
But it only seems to get to 500 Hz max. Any Idea how to increase the polling rate to 1000 Hz ?
Thank you

Making Absolute Mouse HID to work on Android

Hey, I am emulating a composite device with a keyboard and AbsMouse using default descriptors and based on the example in
https://github.com/arpruss/USBComposite_stm32f1/blob/master/examples/absmouse/absmouse.ino

This works ok in Windows. The cursor moves and clicks happen thought there is an offset to x.
When I connect the device to an Android phone, the mouse doesn't seem to work while keyboard works ok.

Any idea if the default absolute mouse descriptor should work for Android?

I searched for some resources online and found different options for descriptors. Some mention touch screens, touch pads, digitizers, etc.

https://stackoverflow.com/questions/46033581/what-is-a-correct-usbhidreportdescriptor-for-android
https://stackoverflow.com/questions/11896471/usb-touchscreen-on-android-4-0-3-not-possible-to-select-only-moving-the-poin
https://stackoverflow.com/questions/13474017/android-usb-touchscreen-hid-descriptors-issue

There seem to be lots of different parameters and combinations.
Can somebody help with a suggestion on how to continue? I am not familiar with the syntax of the descriptors. Thanks.

Buffer start address should have 2 bytes alignment as per reference manual.

rxPacketSize = size;

This is regarding the discussion we had over the libmaple pma->buffer copy functions. As per STM reference manual buffer size ( and buffer start position) should have 8 byte alignments. Just wanted to make the note here in the part that sets the buffer size.

EDIT: I see similar functions in MIDI:

void setRXPacketSize(uint32 size=64) {
rxPacketSize = size;
}
void setTXPacketSize(uint32 size=64) {
txPacketSize = size;
}

Controlling RTS & DTR usbcomposite stm32

I tried use stm32 as UART bridge (for programming esp via arduino), but i can't control RTS & DTR signal from stm32 as serial.

This is fragment of my code

void loop() {
  digitalWrite(DTR_Pin, (CompositeSerial.getDTR() == 0) ? 1 : 0 );
  digitalWrite(RTS_Pin, (CompositeSerial.getRTS() == 0) ? 1 : 0 );
  
  //programing esp  
  if (CompositeSerial.available() > 0) {
    //digitalWrite(RTS_Pin, (CompositeSerial.getRTS() == 0) ? 1 : 0 );
    //digitalWrite(RTS_Pin, (CompositeSerial.getRTS() == 0) ? 1 : 0 );
    Serial1.write(CompositeSerial.read());
  }

  if (Serial1.available() > 0) {
    CompositeSerial.write(Serial1.read());
  }  
}

It doesn't work =( How to correctly control DRT and RTS pins?

SD reader example - weirdo with Windows 10

Dear Arpruss,
today I recognized a weird behavior of the SD reader example under Windows 10 (64bit, actual version):
Trying to copy some files (each about ~10MB):
The progress bar raise immediately up to 99% and no update and response. I you wait, it will copy the files after a long time.
I don't know this bug is caused by a Windows update, or something else. I also tried an older Rogers core (about 2019-10) - same bad behavior.
The board I use is a own build PCB (with SD-read on board) I used for more than one year - so it's no hardware fail.
Maybe someone can cross check this?

Thanks,
Matthias

How do you use the serial debugger after compositing a midi? [SOLVED]

So when I run the midiout example the serial port get lost.

I can upload new sketches by resetting the blue pill but as long as the serial port is missing I can´t read the serial,print commands to debug it. How do you debug it?

Using stm32duino bootloader and USB, windows 10 64bit

That´s a great library. Thanks!!

MIDI and CompositeSerial not working together with latest release

I'm having trouble running MIDI and CompositeSerial together with the latest release. The same code works fine with older releases. What happens on the newer releases is while the CompositeSerial communication works the midi is silent both on transmit and receive. I'm finding Midi or Serial work ok configured independently with the later commits .. just not together.

Rolling back through the git the last commit where serial and midi work together for me is here:

commit d5917495d0358fd457d1d7562f8f3f04489e7293
Author: arpruss <[email protected]>
Date:   Fri Dec 20 21:14:56 2019 -0600

    foo

And I have no MIDI activity if I compile against any commits after that point .. before or after the merges:

image

Here's my test:

#include "USBComposite.h"
#include <Arduino.h>

uint8_t TX_CH=1;
uint8_t RX_CH=2;

uint8_t last_note=0;
uint8_t last_velocity=0;
uint8_t last_channel=0;

USBCompositeSerial mySerial;

class myMidi : public USBMIDI {
  virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {
    last_note=note;
    last_velocity=0;
    last_channel=channel;
  }
  virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {
    last_note=note;
    last_velocity=velocity;
    last_channel=channel;
  }
};

myMidi midi;

void pulseIt(int);

void setup() {
  
  pinMode(LED_BUILTIN,OUTPUT);

  USBComposite.clear(); // clear any plugins previously registered
  mySerial.registerComponent();
  midi.registerComponent();
  USBComposite.begin();
  USBComposite.setProductId(0x0031);  

  midi.begin();
  mySerial.begin(38400);

  while(!mySerial.isConnected()); // spin waiting for usb serial to come active
  delay(500);
  mySerial.print("TX Channel: ");mySerial.print(TX_CH); mySerial.print(" == MIDI Channel: ");mySerial.println(TX_CH+1);
  mySerial.print("RX Channel: ");mySerial.print(RX_CH); mySerial.print(" == MIDI Channel: ");mySerial.println(RX_CH+1);
  pulseIt(300);

} 


void loop() {

  //TX
  /*
  for (int i=0;i<5;i++) {
    midi.sendNoteOn(4, 68+i, 127);
    delay(50);
    midi.sendNoteOff(4, 68+i, 127);
    delay(50);
  }
  */

  // RX
  midi.poll(); // any midi coming in
  if (last_note!=0 && last_channel == RX_CH){ 
    mySerial.print(millis()); mySerial.print(" Note: ");mySerial.print(last_note);mySerial.print(" Velocity: ");mySerial.println(last_velocity); 
    last_note=0;
    pulseIt(200);
  }

}


void pulseIt(int pulseWidth ) {
  digitalWrite(LED_BUILTIN,LOW);
  delay(pulseWidth);
  digitalWrite(LED_BUILTIN,HIGH);
}

Perhaps this from something I'm not initializing correctly in my code?

thanks

Need help with multiple reports in one Collection(Application)

I'm sorry that I write here, just do not know where to write on the subject.

I implemented this descriptor part of FFB and delete all REPORT_ID (have only one ID)
https://github.com/shauleiz/vJoy/blob/master/driver/sys/hidReportDescSingle.h

I initialize data for INPUT report, where "&report" - is joystick control data
HIDReporter(HID, (uint8_t*)&report, sizeof(report), TLID),
It normaly work when manualy sendReport()

How to implement data reception from all other OUTPUT reports and FEATURE reports for so big descriptor with many different reports?

This is my project - JoyFFB
This is HID ForceTest programm - ForceTest.exe

ForceTest normaly work with "vJoy" driver, it see PID and create new effect, but for my joystick have error:
"An invalid parameter was passed to the returning function"
"Error creating Effect. Your joystick may not support this effect. "

I assume that it is necessary to write value = 12 in Feature report of "Usage Create New Effect Report"
but i don't understand how make it, and how get data from host

I would be very grateful for the help!

Add Xbox One Dongle Compatibility

Hi. Would it be possible to add compatibility for the Xbox One receiver dongle?
I'm really interested in being able to read data from an xbox one controller wirelessly. However, I don't have the knowledge to do it on my own.
It seems to me that doing it with the dongle (the large version of the dongle) would give better results than with bluetooth, because the dongle seems to have 3 antennas and a robust and good design.

I could help by donating some dongle so that compatibility could be added.
I would appreciate it too much. Thanks in advance.

[Blue Pill STM32F103C8T6] USB Mass Storage W28Q64 (Like a SD card Reader) Failed to format

With the help of another library, it was possible to replace the SD card with a SPI flash memory.

But Windows cannot format the memory.

W25Q64 flash memory is only 8MB (64Mbit) and if the library's own formatter is used, Windows can correctly find the available 8MB space. But when trying to format in Windows 10 x64 Explorer, the size of 4GB appears and then the formatting does not end.

Formatter:

// Adafruit SPI Flash FatFs Format Example
// Author: Tony DiCola
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!  NOTE: YOU WILL ERASE ALL DATA BY RUNNING THIS SKETCH!  !!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// Usage:
// - Modify the pins and type of fatfs object in the config
//   section below if necessary (usually not necessary).
// - Upload this sketch to your M0 express board.
// - Open the serial monitor at 115200 baud.  You should see a
//   prompt to confirm formatting.  If you don't see the prompt
//   close the serial monitor, press the board reset buttton,
//   wait a few seconds, then open the serial monitor again.
// - Type OK and enter to confirm the format when prompted.
// - Partitioning and formatting will take about 30-60 seconds.
//   Once formatted a message will be printed to notify you that
//   it is finished.
//
#include <SPI.h>
#include <SdFat.h>
#include <Adafruit_SPIFlash.h>

// Since SdFat doesn't fully support FAT12 such as format a new flash
// We will use Elm Cham's fatfs f_mkfs() to format
#include "ff.h"
#include "diskio.h"

// Use second SPI port
SPIClass SPI_2(2);

#define SS2 PB12

#if defined(__SAMD51__) || defined(NRF52840_XXAA)
Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
#else
//  #if (SPI_INTERFACES_COUNT == 1)
//    Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
//  #else
//    Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
//  #endif

Adafruit_FlashTransport_SPI flashTransport(SS2, &SPI_2);
#endif

Adafruit_SPIFlash flash(&flashTransport);

// file system object from SdFat
FatFileSystem fatfs;


void setup() {
  // Initialize serial port and wait for it to open before continuing.
  Serial.begin(115200);
  while (!Serial) {
    delay(100);
  }
  Serial.println("Adafruit SPI Flash FatFs Format Example");

  // Initialize flash library and check its chip ID.
  if (!flash.begin()) {
    Serial.println("Error, failed to initialize flash chip!");
    while(1);
  }
  Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);

  // Wait for user to send OK to continue.
  Serial.setTimeout(30000);  // Increase timeout to print message less frequently.
  do {
    Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
    Serial.println("This sketch will ERASE ALL DATA on the flash chip and format it with a new filesystem!");
    Serial.println("Type OK (all caps) and press enter to continue.");
    Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  }
  while ( !Serial.find("OK"));

  // Call fatfs begin and passed flash object to initialize file system
  Serial.println("Creating and formatting FAT filesystem (this takes ~60 seconds)...");

  // Make filesystem.
  uint8_t buf[512] = {0};          // Working buffer for f_fdisk function.    
  FRESULT r = f_mkfs("", FM_FAT | FM_SFD, 0, buf, sizeof(buf));
  if (r != FR_OK) {
    Serial.print("Error, f_mkfs failed with error code: "); Serial.println(r, DEC);
    while(1);
  }

  // sync to make sure all data is written to flash
  flash.syncBlocks();
  
  Serial.println("Formatted flash!");

  // Check new filesystem
  if (!fatfs.begin(&flash)) {
    Serial.println("Error, failed to mount newly formatted filesystem!");
    while(1) delay(1);
  }

  // Done!
  Serial.println("Flash chip successfully formatted with new empty filesystem!");
}

void loop() {
  // Nothing to be done in the main loop.
}


//--------------------------------------------------------------------+
// fatfs diskio
//--------------------------------------------------------------------+
extern "C"
{

DSTATUS disk_status ( BYTE pdrv )
{
  (void) pdrv;
	return 0;
}

DSTATUS disk_initialize ( BYTE pdrv )
{
  (void) pdrv;
	return 0;
}

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Start sector in LBA */
	UINT count		/* Number of sectors to read */
)
{
  (void) pdrv;
	return flash.readBlocks(sector, buff, count) ? RES_OK : RES_ERROR;
}

DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Start sector in LBA */
	UINT count			/* Number of sectors to write */
)
{
  (void) pdrv;
  return flash.writeBlocks(sector, buff, count) ? RES_OK : RES_ERROR;
}

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
  (void) pdrv;

  switch ( cmd )
  {
    case CTRL_SYNC:
      flash.syncBlocks();
      return RES_OK;

    case GET_SECTOR_COUNT:
      *((DWORD*) buff) = flash.size()/512;
      return RES_OK;

    case GET_SECTOR_SIZE:
      *((WORD*) buff) = 512;
      return RES_OK;

    case GET_BLOCK_SIZE:
      *((DWORD*) buff) = 8;    // erase block size in units of sector size
      return RES_OK;

    default:
      return RES_PARERR;
  }
}

}

Source: https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/SdFat_format

USB Reader:

// This uses the greiman sdfat library.
// To use SdFatEX, set ENABLE_EXTENDED_TRANSFER_CLASS to 1 in the library's
// src/SdFatConfig.h
#include <USBComposite.h>
#include <SPI.h>
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"

USBMassStorage MassStorage;
USBCompositeSerial CompositeSerial;

#define LED_PIN PC13
#define PRODUCT_ID 0x29

// Use first SPI port
//SdFat sd;

// Use second SPI port
SPIClass SPI_2(2);
//SdFat sd(&SPI_2);

#define SS2 PB12

Adafruit_FlashTransport_SPI flashTransport(SS2, &SPI_2);

Adafruit_SPIFlash flash(&flashTransport);

//SdFatEX sd;

const uint32_t speed = SPI_CLOCK_DIV2 ;
//const uint8_t SD_CHIP_SELECT = SS2; //PA15; //SS;
bool enabled = false;
uint32 cardSize;

bool write(const uint8_t *writebuff, uint32_t startSector, uint16_t numSectors) {
  //  return sd.card()->writeBlocks(startSector, writebuff, numSectors);
  return flash.writeBlocks(startSector, writebuff, numSectors);
}

bool read(uint8_t *readbuff, uint32_t startSector, uint16_t numSectors) {
  //  return sd.card()->readBlocks(startSector, readbuff, numSectors);
  return flash.readBlocks(startSector, readbuff, numSectors);
}

void setup() {
  //  // Remap SPI 1
  //  // Source: https://community.platformio.org/t/pio-arduino-stm32f103cbt6-remap/6786/5
  //  afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY); // PB3 free
  //  afio_remap(AFIO_REMAP_SPI1);
  //
  //  gpio_set_mode (GPIOB, 3, GPIO_AF_OUTPUT_PP);
  //  gpio_set_mode (GPIOB, 4, GPIO_INPUT_FLOATING);
  //  gpio_set_mode (GPIOB, 5, GPIO_AF_OUTPUT_PP);

  USBComposite.setProductId(PRODUCT_ID);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, 1);
}

void initReader() {
  digitalWrite(LED_PIN, 0);
  //  cardSize = sd.card()->cardSize();
  cardSize = flash.size();
  MassStorage.setDriveData(0, cardSize, read, write);
  MassStorage.registerComponent();
  CompositeSerial.registerComponent();
  USBComposite.begin();
  enabled = true;
}

void loop() {
  if (!enabled) {
    //    if (sd.begin(SD_CHIP_SELECT)) {
    if (flash.begin()) {
      initReader();
    }
    else {
      delay(50);
    }
  }
  else {
    MassStorage.loop();
  }
}

Adafruit SPI Flash, for FAT filesystems on SPI flash chips:
https://github.com/adafruit/Adafruit_SPIFlash

[Blue Pill STM32F103C8T6] Works!!! USB Mass Storage W28Q64 (Like a SD card Reader):
adafruit/Adafruit_SPIFlash#24 (comment)

STM32F401 compatibility

Hi!

We developing a project with STM32F103 using this library. For some limitations, we would like to use a STM32F401, but's library it's not compatible. We observe no one Midi arduino libraries are compatible with this F401 chip. Have a any type of hook, or adaptation we can make to solve this? Any light to these question?

USBMultiSerial not working on linux

Hi i just tried the MultiSerial example on an stm32f1 (blue pill)
On windows 10 it seems to work just fine,
On ubuntu (19.10) however it craps out. very slow to open and no data is coming true
even setting a baudrate stty -F /dev/ttyACM0 9600 seems to take about 8 seconds

Any suggestions?

exmples

So I'm trying to use your library, but only HID examples work. When i upload massStorage sketch my PC says it doesn't recognize the device. Also there are no examples for USB Serial, so I crafted my own code which in my opinion shall work, nut my PC also reports that it didn't recognize the device. I'm using Windows 7 x64 machine and I have plugged ST-link and blue pill at the same time if it makes any difference. Below I also include my code for USB Serial.
In the end I willing to make MIDI and storage device, but for now I'm testing on HID and Serial to exclude some variables.

It would also be nice if you would include some materials about USB in stm32 and in general, so that I wouldn't need to disturb you more often than needed.

[code]
#include <USBComposite.h>

#define LED PC13

USBHID HID;
HIDMouse Mouse(HID);
USBCompositeSerial Ser;

void setup(){
pinMode(LED,OUTPUT);
digitalWrite(LED,1);
HID.begin(HID_MOUSE);
Ser.begin(115200);
delay(1000);
}

void loop(){
digitalWrite(LED,0);
Mouse.move(4,0);
delay(500);
digitalWrite(LED,1);
delay(300);
digitalWrite(LED,0);
Mouse.move(-4,0);
delay(500);
digitalWrite(LED,1);
delay(300);
Ser.write("dupa\r\n");
}
[/code]

Support for OS to send led status

I am trying to revive a old keyboard and your library works like a charm but I am missing the ability to get the led status report. Is it implemented and if so how can I get that?

P.S. What is the status on Consumer. Every time I try to send a keypress the stm32(Blue pill) freezes

Unable to change the channel for MidiOut

Hi! Sorry for another bother. I'm trying to build an e-drum with the STM32F103C8T6. I followed your advice yesterday and I can reprogram the board perfectly now.

But, a new issue arose for me when I try to change the Midi channel to "10" for the General Midi Drums. I have used this link to set up the rest of the software requirements: https://www.arduino.cc/en/Tutorial/MidiDevice i.e. Using VirtualMIDISynth (with a soundfont FluidR3) and Virtual MIDI Piano Keyboard(VMPK) as the... inter-MIDI-ary software.

I used the example from your library and its working well, playing the notes with the coded velocity. But, I am unable to play drums by changing the channel variable, in the function, to "10". It always plays the same channel, no matter what I change in the VMPK. It's always the Piano.

I used the midiout.ino example given in the USBComposite library provided with the STM32F1 package for Arduino IDE ( From Roger's Git ).

What I have tried thus far:

  1. Various numbers in the first variable of the functions like "10", "0x9A", "0x8A" and other arbitrary numbers.
  2. Passing the above numbers to the begin function, that setChannel(Unsigned variable)'s the channel.
  3. I even tried to use the MIDIUSB.h just to check if it works after setting the board as a Composite USB. No, it does not. It still doesn't recognise the architecture.

My layman opinion of what the problem is:

  1. I am missing something with software application side of things. Unlikely, but I'm keeping my eyes and ears open for it.
  2. I went through the library files to understand them.
    In the file "USBMIDI.h":
    In the class USBMIDI, Public section at Line 119: void setChannel(unsigned channel=0);
    And further down at Line 135: void begin(unsigned int channel = 0);

Do these functions restrict changing channels by being initialised at 0? If so, how can I change this? When I try to change them locally for eperimenting on the file, I am restricted by a prompt that says "You don't have the permission to open this file. See the owner or Administrator of the file." more or less

TL;DR - Unable to change the channel to Percussion (Channel 10). Need help or advice on how to do the same. Read Last two paragraphs for the core.

Multi serial support

Hello,

Very nice work !!!

May you please add an example for multiple Serial device support.

Thanks a lot for your effort

Compile error on USB_EP_TYPE_ISO in usb_audio.c

Downloaded the latest but not compiling ...

Scanning dependencies...
Dependency Graph
|-- <FastLED> 3.1.4
|-- <USBComposite for STM32F1> 0.95
Building in release mode
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_audio.c.o
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_generic.c.o
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_hid.c.o
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_mass.c.o
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_mass_mal.c.o
lib/USBComposite_stm32f1/usb_audio.c:225:32: error: 'USB_EP_TYPE_ISO' undeclared here (not in a function); did you mean 'USB_EP_T_ISO'?
         .bmAttributes        = USB_EP_TYPE_ISO, /* isochronous, not shared */
                                ^~~~~~~~~~~~~~~
                                USB_EP_T_ISO
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_midi_device.c.o
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_multi_serial.c.o
*** [.pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_audio.c.o] Error 1
Compiling .pio/build/genericSTM32F103CB/lib6a2/USBComposite_stm32f1/usb_multi_x360.c.o

I'm running platformIO and it compiles OK if I revert back to the maple core version which is working fine. I only upgraded to pick up the midi fix I noticed was just fixed last week.

Awesome library .. thank you for this!

HID consumer and boot keyboard in same time?

Hello! First, thanks for Your efforts! My problem is that the half of commands required by my remote controller project is listed in HID consumer category, other half is in boot keyboard mode... Is it possible to initialize them in the same project? I had no luck until now, they work well in separate project, but got blocked each time when i try to merge them... Do You have a working example for it?

USB_EP_TYPE_ISO

I have to make this to usb_audio.h::
#define USB_EP_TYPE_ISO USB_EP_T_ISO

I am not sure why...

/Kasper

C:\Users\xxxx.platformio\lib\USBComposite for STM32F1_ID2052\usb_audio.c:227:32: error: 'USB_EP_TYPE_ISO' undeclared here (not in a function); did you mean 'USB_EP_T_ISO'?
.bmAttributes = USB_EP_TYPE_ISO, /* isochronous, not shared */
^~~~~~~~~~~~~~~
USB_EP_T_ISO

After using the MidiOut.ino example, Board stopped showing as Serial Port.

I used the MidiOut example and uploaded the program to my STM32F103C8T6 (Black pill) board with roger clark's bootloader to use USB to upload programs.

The program worked well and with no problems.

But, the board no longer comes up as a Serial Port to upload programs in the Arduino IDE. It used to be Port 5, but there are none anymore.

  1. How can I upload new programs or debug the board now? Is there another way to do so?
  2. Else, how can I reset the board to be able to use FTDI to program and keep USB port free for use with this library?

Adding and removing drives when USBComposite is started

Hi,

I am trying to add a sd drive when usbcomposite is already started but Windows won't detect it. The error I get is E:\ is not accessible. Incorrect function

The thing I am trying to do is to use a sd card as a easy to use storage for images and configs.
The goal is that I can select to enable mass storage and that the sd card will be visible to the computer and when I'm done with it that I can unmount it without losing HID functions.

The sdreader does work with both SdFat and SdFs.

Cannot change Joystick HID Descriptor to Add Buttons

I know this is a newbie question, but I am having trouble changing around the USB Joystick descriptor in USBHID.h.

I want to have a joystick with only buttons, and 50 of them. So far I cannot modify the descriptor to have more or less buttons, or anything else, without it crashing the software.

For example, I have tried to decrease the buttons to 16, and modify as such:

	0x15, 0x00,						/* 	 Logical Minimum (0) */ \
	0x25, 0x01,						/*    Logical Maximum (1) */ \
	0x75, 0x01,						/*    Report Size (1) */ \
	0x95, 0x10,						/*    Report Count 16) */ \
	0x05, 0x09,						/*    Usage Page (Button) */ \
	0x19, 0x01,						/*    Usage Minimum (Button #1) */ \
	0x29, 0x10,						/*    Usage Maximum (Button #16 ) */ \
	0x81, 0x02,						/*    Input (variable,absolute) */ \
	0x15, 0x00,						/*    Logical Minimum (0) */ \
	0x25, 0x07,						/*    Logical Maximum (7) */ \
	0x35, 0x00,						/*    Physical Minimum (0) */ \
	0x46, 0x3B, 0x01,				/*    Physical Maximum (315) */ \
	0x75, 0x02,						/*    Report Size (2) */ \
	0x95, 0x01,						/*    Report Count (1) */ \

But this just results in the code apparently no longer working, as it is not enumerated and my USB serial stops working.

In short, how does one create a bespoke descriptor? If this is the wrong place to ask this sort of question, maybe direct me to the proper place?

Thank you!

boards.h "no such file or directory"

The boards.h that the entire library is referencing appears to be missing. From what i've checked it seems to be a capitalization error, changing #include boards.h to #include Boards.h in all the header files seems to fix it

RawHid example

Hi, Using Simple HID Write utility and other similar utilities I find that the looped back data are incremented by 1 - so if I send 01, 02, 03, 04 hex the maplemini sends back 02, 03, 03, 04..
I've looked through the libs and I can't see the source of this shift. Could you point me in the right direction? If I send buffered data one-way from maple to pc then all is fine so my issue seems to be maple reception of SET REPORT.

Thanks for the great work.

Serial port & Mass storage

Hi,

What do i do wrong in this code.
I am trying to have a serial port and a Mass storage.
If i run mass or serial sepperate it seems to work.
Running this code her without toching pc, it will disconnect after short time, and re-enumerate again, but wrong.
Mass seems to work until re-enumeration, but serial will not connect.

Running 0.95 version.

Executed in platformIO:

Maple core

[env:genericSTM32F103RB]
platform = ststm32
board = genericSTM32F103RB
framework = arduino
debug_tool = stlink
debug_init_break =

Thank you.

#include <Arduino.h>
#include <USBComposite.h>
#include <SPI.h>
#include "SdFat.h"



#define PRODUCT_ID 0x30

USBMassStorage MassStorage;
USBCompositeSerial CompositeSerial;
SdFat sd; //ex
const uint32_t speed = SPI_CLOCK_DIV2 ;
const uint8_t SD_CHIP_SELECT = SS;
bool enabled = false;
uint32 cardSize;

bool write(const uint8_t *writebuff, uint32_t startSector, uint16_t numSectors) {
  return sd.card()->writeBlocks(startSector, writebuff, numSectors);
}

bool read(uint8_t *readbuff, uint32_t startSector, uint16_t numSectors) {
  return sd.card()->readBlocks(startSector, readbuff, numSectors);
}

void setup() {
  USBComposite.setProductId(PRODUCT_ID);
}

void initReader() {
  cardSize = sd.card()->cardSize();  
  MassStorage.setDriveData(0, cardSize, read, write);
  USBComposite.clear();
  MassStorage.registerComponent(); 
  CompositeSerial.registerComponent();
  USBComposite.begin();
  while (!USBComposite);
  enabled=true;
}

void loop() {
  uint32_t c = 0;
  if (!enabled) {
    if (sd.begin(SD_CHIP_SELECT)) {
      initReader();
    }
    else {
      delay(50);
    }
  }
  else {
    c++;
    MassStorage.loop(); 
    if (c>10000){
      if(CompositeSerial.isConnected())
        CompositeSerial.println("test"); 
      c = 0;
      }
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.