Preserving custom Teensy USB library changes

cjdickey36

New member
I have a project that needs MTP + two serial ports. From other forum posts and the long comment at the top of the file, I figured out how to edit usb_desc.h and got that part working.

The issue now is that usb_desc.h lives outside of the actual sketch folder, so it didn't transfer from my laptop to my desktop along with the rest of the sketch. Also, I'm afraid that the next time I update something, it's going to wipe out those changes.

The changes I would need to make seem to be limited to usb_desc.h and usb.c. Is there a way to make the affected code part of my sketch?
 
Yes, generally the power and problem of edits to CORES files is manually maintaining any edits to any IDE install or update.

Some changes may lend themselves to a means of isolating or extracting them to more maintainable edits, though some internal elements - perhaps the USB stack - may not.

The changes at hand aren't shown for any specifics to be offered.
 
Good point. The extent of my changes...

(cores/teensy3)

To usb_desc.h, I added an entry to the list at line 780:

C++:
#elif defined(USB_MTPDISK_DUALSERIAL)
  #define VENDOR_ID             0x16C0
  #define PRODUCT_ID    0x04D5
  #define DEVICE_CLASS    0xEF
  #define DEVICE_SUBCLASS 0x02
  #define DEVICE_PROTOCOL 0x01
  #define MANUFACTURER_NAME {'T','e','e','n','s','y','d','u','i','n','o'}
  #define MANUFACTURER_NAME_LEN 11
  #define PRODUCT_NAME    {'T','e','e','n','s','y',' ','M','T','P',' ','D','i','s','k'}
  #define PRODUCT_NAME_LEN  15
  #define EP0_SIZE              64

  #define NUM_ENDPOINTS         9
  #define NUM_USB_BUFFERS       30
  #define NUM_INTERFACE         5

  #define CDC_IAD_DESCRIPTOR    1
  #define CDC_STATUS_INTERFACE  0
  #define CDC_DATA_INTERFACE    1 // Serial
  #define CDC_ACM_ENDPOINT      1
  #define CDC_RX_ENDPOINT       2
  #define CDC_TX_ENDPOINT       3
  #define CDC_ACM_SIZE          16
  #define CDC_RX_SIZE           64
  #define CDC_TX_SIZE           64
 
  #define MTP_INTERFACE         2 // MTP Disk
  #define MTP_TX_ENDPOINT       4
  #define MTP_TX_SIZE           64
  #define MTP_RX_ENDPOINT       5
  #define MTP_RX_SIZE           64
  #define MTP_EVENT_ENDPOINT    6
  #define MTP_EVENT_SIZE        32
  #define MTP_EVENT_INTERVAL    10

  #define CDC2_STATUS_INTERFACE    3    // SerialUSB2
  #define CDC2_DATA_INTERFACE    4
  #define CDC2_ACM_ENDPOINT    7
  #define CDC2_RX_ENDPOINT    8
  #define CDC2_TX_ENDPOINT    9
  #define CDC2_ACM_SIZE        16
  #define CDC2_RX_SIZE        64
  #define CDC2_TX_SIZE        64

  #define ENDPOINT1_CONFIG      ENDPOINT_TRANSMIT_ONLY
  #define ENDPOINT2_CONFIG      ENDPOINT_RECEIVE_ONLY
  #define ENDPOINT3_CONFIG      ENDPOINT_TRANSMIT_ONLY
  #define ENDPOINT4_CONFIG      ENDPOINT_TRANSMIT_ONLY
  #define ENDPOINT5_CONFIG      ENDPOINT_RECEIVE_ONLY
  #define ENDPOINT6_CONFIG      ENDPOINT_TRANSMIT_ONLY
  #define ENDPOINT7_CONFIG        ENDPOINT_TRANSMIT_ONLY
  #define ENDPOINT8_CONFIG        ENDPOINT_RECEIVE_ONLY
  #define ENDPOINT9_CONFIG        ENDPOINT_TRANSMIT_ONLY

I realize now that I unnecessarily modified the usb.c file in the teensy4 folder, since line 1088 originally read:

Code:
#if defined(USB_MTPDISK) || defined(USB_MTPDISK_SERIAL)
and I changed it to:

Code:
#if defined(USB_MTPDISK) || defined(USB_MTPDISK_SERIAL) || defined(USB_MTPDISK_DUALSERIAL)

This isn't necessary for this project, but I do intend to port it to the Teensy 4.1 at some point.
 
I am not sure there is an easy way to easily preserve your changes an apply them to other projects or on other machines.

In that, you are currently required to update the core sources for these types of changes. And these changes are semi-fragile in that
you have to update each machine with your updates and if by chance you install a new release of the Teensy board type, your changes
will be overwritten by the new update board code.

When we were in the process of adding MTP, which still has not fully part of Teensyduino, the original developer for MTP included in
his github project, a directory (or maybe a couple) that contained the changes needed to add the MTP code to the system.

A second half of these level changes I wish we would address at some point:
I have never liked the code like:
Code:
#if defined(USB_MTPDISK) || defined(USB_MTPDISK_SERIAL)

Where it is determined by USB type, instead I wish we set it up where code like this is determined by if something is supported:
More like: #if defined(USB_MTP_ENABLED)
or some such thing.

Ditto for things like: I want to use SerialUSB1 if it is defined.
To do this currently I have to check for both dual serial and triple serial ...
But that is a different issue.
 
I thought about it more and poked around a bit, and concluded that fragility is be okay, and it's okay if I don't automatically get the latest version of cores either -- I can update manually. The things I really want to have are:
- project-based storage of my changes (such that I don't accidentally make a change to usb_desc.h that isn't recorded by version control and lose it)
- early, noisy failure (already have that; if usb_desc.h changes, code won't build)
- automated insertion/usage of the custom code (instead of maintaining a project copy of usb_desc.h, manually finding the cores directory, and copying it over on each machine)

I'm looking at one possible route -- using PlatformIO and forking platform-teensy and cores. platform-teensy needs a modification to platforms/teensy/builder/frameworks/arduino.py for intellisense to keep working -- specifically, the list of flags it checks for before auto-defining USB_SERIAL needs to be amended. And it needs to point to the customized cores. cores needs the aforementioned modification. How to actually do this is more of a question for the PlatformIO forum, probably. I found this, which seems helpful: https://community.platformio.org/t/how-can-i-use-a-custom-framework/27516/2
 
As far as keeping your changes while updating cores, using git with a separate branch for your changes and rebasing whenever there's an update makes it very easy.
 
Yep, that's the plan -- rebase on top of new versions of the library; see if a PR for the changes will be accepted.

I have it working now. There were more gotchas than I expected, but I learned things. Another goal that developed was to have minimal changes to the other files in the framework package and platform. Some names did have to change, but it was a fairly manageable amount.

I settled on submodule repositories within the project directory, with the actual files coming from the working directories, not the repositories. The short of it is, the end goal is to get PlatformIO to copy the framework-arduinoteensy directory to ~/.platformio/packages (and name it something NOT framework-arduinoteensy) and the platform-teensy directory to ~/.platformio/platforms (and name it "teensy"), then use both of those to build the project. Sounds a lot simpler than it felt.

Here are the things I learned along the way:

- Open platformio.ini and save it to refresh the platform and framework packages; the Output tab shows progress and errors

- The framework package needs to contain more than just the Teensy cores repo; the other stuff surrounding it is easy to pull from ~/.platformio/packages/framework-arduinoteensy, though. This was stated in the thread I linked earlier.

- If you change the name of the framework package (originally "framework-arduinoteensy"), you won't end up with this problem.

- To specify a local directory (as opposed to the git repo inside the directory), prepend file:// to the path; e.g.,
Code:
file://./framework-arduinoteensy-cjd
for that directory inside the build directory (I experienced mixed results with local git repositories, but bare ones generally worked better)

- The name of the framework package directory (e.g., "framework-arduinoteensy-cjd") matters, and needs to match the framework name before the @ symbol, e.g.,
Code:
platform_packages = framework-arduinoteensy-cjd @ file://./framework-arduinoteensy-cjd

- The names of the framework package inside the framework's files don't seem to matter at all (package.json, .piopm both contain framework-arduinoteensy) and everything builds regardless of whether it is changed to framework-arduinoteensy-cjd

- The names of the framework package inside the platform DO matter (builder/frameworks/arduino.py, platform.json)

- The name of the platform directory doesn't seem to matter, and doesn't need to be different from the original; when PlatformIO copies it to the build directory, it will append some long SHA1-looking thing to disambiguate. Note that this is first-come, first-serve; if you clear the ~/.platformio/platforms directory, the next time you save platformio.ini, it will repopulate with "teensy", containing the files from "platform = ". The directory named "teensy" without the suffix is NOT necessarily the unmodified library, just the first one of that name to be built since the directory was emptied.

- The name of the platform within the platform.json file determines the name of the directory in the build directory -- renaming from "name" : "teensy" to "name" : "teensy-cjd" caused a directory named "teensy-cjd" to appear in ~/.platformio/platforms, and caused the refresh to fail. I imagine more things would need to change for this to work.

- Don't rename the board or the framework. Attempting to rename the arduino framework (e.g., "framework = arduino" in platformio.ini) was neither necessary nor helpful. After I tracked down all of the locations and changed them, PlatformIO wouldn't fetch the dependencies that are regular Arduino libraries.

Also, after I finished, I found this: https://docs.platformio.org/en/latest/scripting/examples/override_package_files.html
 
Back
Top