Skip to content

Add Mix&Match option for USB#779

Open
rastersoft wants to merge 1 commit intoPaulStoffregen:masterfrom
rastersoft:allow-to-select-usb-devices
Open

Add Mix&Match option for USB#779
rastersoft wants to merge 1 commit intoPaulStoffregen:masterfrom
rastersoft:allow-to-select-usb-devices

Conversation

@rastersoft
Copy link

@rastersoft rastersoft commented Mar 28, 2025

This patch allows to freely select keyboard (with or without multimedia keys), mouse, joystick, serial port, and debug, in a mix&match way, allowing to have any combination of those USB interfaces (as long as your microcontroller has enough endpoints, of course).

It uses some C PreProcessor magic to dinamically assign the endpoints, addresses and everything else, as it can be seen in usb_private.h, lines 116 onward, and usb.c, lines 288 onward.

To use this mode, select "USB Mix and Match (M&M)" as the USB type in ArduinoIDE, and then enable or disable the M&M options, according to your needs. Or define the desired elements by adding as many -DUSB_MAM_XXXXX_1 as required (with XXXXX being SERIAL, KEYBOARD, MULTIMEDIA, MOUSE, JOYSTIC or DEBUG).

Currently it's only implemented for teensy 2.0 because that's the only board I have, but should be straightforward to implement for all others, and also to add all the other interfaces (disc, MIDI...).

This patch allows to freely select keyboard (with or without
multimedia keys), mouse, joystick, serial port, and debug, in a
mix&match way, allowing to have any combination of those USB
interfaces (as long as your microcontroller has enough endpoints,
of course).

It uses some C PreProcessor magic to dinamically assign the
endpoints, addresses and everything else, as it can be seen
in usb_private.h, lines 116 onward, and usb.c, lines 288 onward.

To use this mode, select "USB Mix and Match (M&M)" as the USB
type, and then enable or disable the M&M options, according to
your needs.

Currently it's only implemented for teensy 2.0, but should be
straightforward to implement for all others, and also to add
all the other interfaces (disc, MIDI...).
@rastersoft
Copy link
Author

Where should I send the patch with the boards.txt and platform.txt files?

@rastersoft
Copy link
Author

Ok, this .diff contains the changes required to boards.txt and platform.txt for ArduinoIDE 2.x. It's simpler to use a .diff than to paste the whole files.

diff --git a/boards.txt b/boards.txt
index aea9bed..0c791b1 100644
--- a/boards.txt
+++ b/boards.txt
@@ -5,6 +5,14 @@ menu.usb=USB Type
 menu.speed=CPU Speed
 menu.opt=Optimize
 menu.keys=Keyboard Layout
+# used menu.zXXXX to ensure that these options are put at the bottom of the menu,
+# because ArduinoIDE sort them by the name
+menu.zserialmam=USB M&M Serial port
+menu.zkeyboardmam=USB M&M Keyboard
+menu.zmousemam=USB M&M Mouse
+menu.zjoystickmam=USB M&M Joystick
+menu.zmultimediamam=USB M&M MultiMedia keys
+menu.zdebugmam=USB M&M Debug port
 
 
 # TODO: consider whether these compiler warnings are worthwhile
@@ -1907,6 +1915,40 @@ teensy2.build.flags.libs=-lm
 teensy2.build.serial_number=true
 teensy2.serial.restart_cmd=true
 
+
+teensy2.menu.zserialmam.disabled=Disabled
+teensy2.menu.zserialmam.disabled.build.usbmamserial=0
+teensy2.menu.zserialmam.enabled=Enabled
+teensy2.menu.zserialmam.enabled.build.usbmamserial=1
+
+teensy2.menu.zkeyboardmam.disabled=Disabled
+teensy2.menu.zkeyboardmam.disabled.build.usbmamkeyboard=0
+teensy2.menu.zkeyboardmam.enabled=Enabled
+teensy2.menu.zkeyboardmam.enabled.build.usbmamkeyboard=1
+
+teensy2.menu.zmousemam.disabled=Disabled
+teensy2.menu.zmousemam.disabled.build.usbmammouse=0
+teensy2.menu.zmousemam.enabled=Enabled
+teensy2.menu.zmousemam.enabled.build.usbmammouse=1
+
+teensy2.menu.zjoystickmam.disabled=Disabled
+teensy2.menu.zjoystickmam.disabled.build.usbmamjoystick=0
+teensy2.menu.zjoystickmam.enabled=Enabled
+teensy2.menu.zjoystickmam.enabled.build.usbmamjoystick=1
+
+teensy2.menu.zmultimediamam.disabled=Disabled
+teensy2.menu.zmultimediamam.disabled.build.usbmammultimedia=0
+teensy2.menu.zmultimediamam.enabled=Enabled
+teensy2.menu.zmultimediamam.enabled.build.usbmammultimedia=1
+
+teensy2.menu.zdebugmam.disabled=Disabled
+teensy2.menu.zdebugmam.disabled.build.usbmamdebug=0
+teensy2.menu.zdebugmam.enabled=Enabled
+teensy2.menu.zdebugmam.enabled.build.usbmamdebug=1
+
+teensy2.menu.usb.mixandmatch=USB Mix and Match (M&M)
+teensy2.menu.usb.mixandmatch.build.usbtype=USB_MIX_AND_MATCH
+teensy2.menu.usb.mixandmatch.upload_port.usbtype=USB_MIX_AND_MATCH
 teensy2.menu.usb.serial=Serial
 teensy2.menu.usb.serial.build.usbtype=USB_SERIAL
 teensy2.menu.usb.serial.upload_port.usbtype=USB_SERIAL
diff --git a/platform.txt b/platform.txt
index d6089bc..96461c9 100644
--- a/platform.txt
+++ b/platform.txt
@@ -30,10 +30,10 @@ compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,
 compiler.elf2hex.flags=-O ihex -R .eeprom
 
 ## Preprocessor Includes
-recipe.preproc.includes="{compiler.path}{build.toolchain}{build.command.g++}" -M -MG -MP -x c++ -w {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DLAYOUT_{build.keylayout} {includes} "{source_file}"
+recipe.preproc.includes="{compiler.path}{build.toolchain}{build.command.g++}" -M -MG -MP -x c++ -w {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DUSB_MAM_SERIAL_{build.usbmamserial} -DUSB_MAM_KEYBOARD_{build.usbmamkeyboard} -DUSB_MAM_MOUSE_{build.usbmammouse} -DUSB_MAM_JOYSTICK_{build.usbmamjoystick} -DUSB_MAM_MULTIMEDIA_{build.usbmammultimedia} -DUSB_MAM_DEBUG_{build.usbmamdebug} -DLAYOUT_{build.keylayout} {includes} "{source_file}"
 
 ## Preprocessor Macros
-recipe.preproc.macros="{compiler.path}{build.toolchain}{build.command.g++}" -E -CC -x c++ -w {compiler.cpp.flags} {build.flags.common} {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DLAYOUT_{build.keylayout} {includes} "{source_file}" -o "{preprocessed_file_path}"
+recipe.preproc.macros="{compiler.path}{build.toolchain}{build.command.g++}" -E -CC -x c++ -w {compiler.cpp.flags} {build.flags.common} {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DUSB_MAM_SERIAL_{build.usbmamserial} -DUSB_MAM_KEYBOARD_{build.usbmamkeyboard} -DUSB_MAM_MOUSE_{build.usbmammouse} -DUSB_MAM_JOYSTICK_{build.usbmamjoystick} -DUSB_MAM_MULTIMEDIA_{build.usbmammultimedia} -DUSB_MAM_DEBUG_{build.usbmamdebug} -DLAYOUT_{build.keylayout} {includes} "{source_file}" -o "{preprocessed_file_path}"
 
 ## New Preprocessor for Arduino 1.9
 tools.arduino-preprocessor.path={runtime.tools.arduino-preprocessor.path}
@@ -41,16 +41,16 @@ tools.arduino-preprocessor.cmd.path={path}/arduino-preprocessor
 tools.arduino-preprocessor.pattern="{cmd.path}" "{source_file}" "{codecomplete}" -- -std=gnu++14
 
 ## Precompile Arduino.h header
-recipe.hooks.sketch.prebuild.1.pattern="{teensytools.path}precompile_helper" "{runtime.platform.path}/cores/{build.core}" "{build.path}" "{compiler.path}{build.toolchain}{build.command.g++}" -x c++-header {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DLAYOUT_{build.keylayout} "-I{runtime.platform.path}/cores/{build.core}" "{build.path}/pch/Arduino.h" -o "{build.path}/pch/Arduino.h.gch"
+recipe.hooks.sketch.prebuild.1.pattern="{teensytools.path}precompile_helper" "{runtime.platform.path}/cores/{build.core}" "{build.path}" "{compiler.path}{build.toolchain}{build.command.g++}" -x c++-header {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DUSB_MAM_SERIAL_{build.usbmamserial} -DUSB_MAM_KEYBOARD_{build.usbmamkeyboard} -DUSB_MAM_MOUSE_{build.usbmammouse} -DUSB_MAM_JOYSTICK_{build.usbmamjoystick} -DUSB_MAM_MULTIMEDIA_{build.usbmammultimedia} -DUSB_MAM_DEBUG_{build.usbmamdebug} -DLAYOUT_{build.keylayout} "-I{runtime.platform.path}/cores/{build.core}" "{build.path}/pch/Arduino.h" -o "{build.path}/pch/Arduino.h.gch"
 
 ## Compile c++ files
-recipe.cpp.o.pattern="{compiler.path}{build.toolchain}{build.command.g++}" -c {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DLAYOUT_{build.keylayout} "-I{build.path}/pch" {includes} "{source_file}" -o "{object_file}"
+recipe.cpp.o.pattern="{compiler.path}{build.toolchain}{build.command.g++}" -c {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.cpp} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DUSB_MAM_SERIAL_{build.usbmamserial} -DUSB_MAM_KEYBOARD_{build.usbmamkeyboard} -DUSB_MAM_MOUSE_{build.usbmammouse} -DUSB_MAM_JOYSTICK_{build.usbmamjoystick} -DUSB_MAM_MULTIMEDIA_{build.usbmammultimedia} -DUSB_MAM_DEBUG_{build.usbmamdebug} -DLAYOUT_{build.keylayout} "-I{build.path}/pch" {includes} "{source_file}" -o "{object_file}"
 
 ## Compile c files
-recipe.c.o.pattern="{compiler.path}{build.toolchain}{build.command.gcc}" -c {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.c} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DLAYOUT_{build.keylayout} {includes} "{source_file}" -o "{object_file}"
+recipe.c.o.pattern="{compiler.path}{build.toolchain}{build.command.gcc}" -c {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.c} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DUSB_MAM_SERIAL_{build.usbmamserial} -DUSB_MAM_KEYBOARD_{build.usbmamkeyboard} -DUSB_MAM_MOUSE_{build.usbmammouse} -DUSB_MAM_JOYSTICK_{build.usbmamjoystick} -DUSB_MAM_MULTIMEDIA_{build.usbmammultimedia} -DUSB_MAM_DEBUG_{build.usbmamdebug} -DLAYOUT_{build.keylayout} {includes} "{source_file}" -o "{object_file}"
 
 ## Compile S files
-recipe.S.o.pattern="{compiler.path}{build.toolchain}{build.command.gcc}" -c {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.S} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DLAYOUT_{build.keylayout} {includes} "{source_file}" -o "{object_file}"
+recipe.S.o.pattern="{compiler.path}{build.toolchain}{build.command.gcc}" -c {build.flags.optimize} {build.flags.common} {build.flags.dep} {build.flags.S} {build.flags.cpu} {build.flags.defs} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DF_CPU={build.fcpu} -D{build.usbtype} -DUSB_MAM_SERIAL_{build.usbmamserial} -DUSB_MAM_KEYBOARD_{build.usbmamkeyboard} -DUSB_MAM_MOUSE_{build.usbmammouse} -DUSB_MAM_JOYSTICK_{build.usbmamjoystick} -DUSB_MAM_MULTIMEDIA_{build.usbmammultimedia} -DUSB_MAM_DEBUG_{build.usbmamdebug} -DLAYOUT_{build.keylayout} {includes} "{source_file}" -o "{object_file}"
 
 ## Create archives
 recipe.ar.pattern="{compiler.path}{build.toolchain}{build.command.ar}" rcs "{archive_file_path}" "{object_file}"

@rastersoft
Copy link
Author

The files were made by "mixing" the ones from "usb_serial_hid" into "usb_hid".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant