Skip to content

Conversation

eric-ocasio-nxp
Copy link

@eric-ocasio-nxp eric-ocasio-nxp commented Sep 2, 2025

Add USB device binding for MCTP. Created new USB device class for MCTP, libMCTP binding, and sample application.

In order to support the USB binding for libMCTP, we must first add a device
class for MCTP. MCTP is one of the base classes in the USB specification.

Signed-off-by: Eric Ocasio <eric.ocasio@nxp.com>
Adds support for the USB device binding for MCTP. Binding created based on
the DMTF specification for USB Transport Binding. The overall design of
this binding follows the existing UART and I2C+GPIO bindings that already
exist in Zephyr. This binding interacts with the new USBD_MCTP device class
that is part of this PR.

Signed-off-by: Eric Ocasio <eric.ocasio@nxp.com>
Based on the existing sample applications for MCTP, this new sample
demonstrates how to use MCTP using the USB device binding.

Signed-off-by: Eric Ocasio <eric.ocasio@nxp.com>
Copy link

github-actions bot commented Sep 2, 2025

Hello @eric-ocasio-nxp, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

@zephyrbot zephyrbot added area: Devicetree area: USB Universal Serial Bus area: PMCI Platform Management Communications Infrastructure area: Samples Samples labels Sep 2, 2025
Copy link

sonarqubecloud bot commented Sep 2, 2025

@@ -0,0 +1,11 @@
.. _usbd_mctp:

MCTP USB device API
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please detail what "MCTP" actually is here.


cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(mctp_endpoint)
Copy link
Contributor

@teburd teburd Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

project name could use something more descriptive, I get I'm guilty of probably starting this but perhaps mctp_usb_endpoint would be better

project(mctp_endpoint)

include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
FILE(GLOB app_sources src/*.c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't glob here


An example script to test this interface is provided below.

.. code-block:: python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly probably better to put this into scripts or into the sample directory itself as a python script with requirements.txt and all rather than pushing users to copy/paste, and figure out how to get the python deps installed.

Can always include whole code files into the docs like this with literalinclude

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. I moved it to a script within the sample folder with a requirements.txt and instructions in the README.

@teburd
Copy link
Contributor

teburd commented Sep 17, 2025

Non-blocking comments obviously, but would be good to see improvements.

@jfischer-no jfischer-no changed the title Feature/add mctp usb binding Add MCTP over USB Binding support Sep 17, 2025
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to support the USB binding for libMCTP, we must first add a device
class for MCTP. MCTP is one of the base classes in the USB specification.

Well no, it is specified by the "DMTF association", https://www.dmtf.org/sites/default/files/standards/documents/DSP0283_1.0.0.pdf

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's base class 0x14 in the USB spec, so I'm not sure what you mean here.

https://www.usb.org/defined-class-codes

+-----------------------------------+-------------------------+-------------------------+
| USB Video Class (UVC) | Video device | :samp:`uvc_{n}` |
+-----------------------------------+-------------------------+-------------------------+
| USB MCTP over USB Endpoint | :ref:`usbd_mctp` | :samp:`mctp_{n}` |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/USB MCTP over USB Endpoint/MCTP over USB Binding


* :zephyr:code-sample:`usb-hid-mouse`

* :zephyr:code-sample:`mctp-usb-endpoint`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* :zephyr:code-sample:mctp-usb-binding`` Anyway, you cannot add it in this commit, this sample does not exist yet.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you suggest that I just update this file in a commit with the sample application, or do one 'super commit' with all of these feature/MCTP changes? I did it this way for human readability, but didn't fully understand the need for every commit to build.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Commits in a pull request should represent clear, logical units of change that are easy to review and maintain bisectability." https://docs.zephyrproject.org/latest/contribute/contributor_expectations.html#pr-requirements


/**
* @file
* @brief USB MCTP over USB Protocol Endpoint Device Class (MCTP) public header
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brief MCTP over USB Binding implementation

* @brief USB MCTP over USB Protocol Endpoint Device Class (MCTP) public header
*
* This header describes MCTP class interactions desgined to be used by libMCTP.
* The MCTP device itself is modelled with devicetree zephyr,mctp-usb compatible.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what that means, but usually devicetree is used to describe and instantiate a device. Whether it makes sense here or not is disputable.

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(usbd_mctp, CONFIG_USBD_MCTP_LOG_LEVEL);

#define DT_DRV_COMPAT zephyr_mctp_usb
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you thing it should model a device and use DT for instantiation. You do not have to follow usbd_hid approach. This looks more like a backend implementation, and for that you could provide hooks and instantiation macro, please take a look at new USB DFU device implementation.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it this way because there exists the possibility of having multiple MCTP buses/bindings. If the application requires more than one MCTP endpoint, a USB composite device could be used with more than one instance of USBD MCTP. Is there a way to accomplish this without DT?


config MCTP_USB
bool "MCTP USB Binding"
depends on USB_DEVICE_STACK_NEXT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant, USBD_MCTP_CLASS already depends on USB_DEVICE_STACK_NEXT.

Comment on lines +56 to +61
.name = STRINGIFY(_name), .version = 1, \
.pkt_size = \
MCTP_PACKET_SIZE(MCTP_USB_MAX_PACKET_LENGTH), \
.pkt_header = 0, .pkt_trailer = 0, \
.start = mctp_usb_start, .tx = mctp_usb_tx, \
}, \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broken style.

* @param _name Symbolic name of the bus binding variable
* @param _dev DeviceTree Node containing the configuration of this MCTP binding
*/
#define MCTP_USB_DT_DEFINE(_name, _dev) \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not get the purpose of this macro and the mctp_usb.c, you already have implemented instantiation and support for this function in the previous commit, what it that and why does it have to be divided?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not following. This macro was created based on the other libmctp binding implementations. What do you mean by it being divided?

@@ -0,0 +1,9 @@
# Copyright (c) 2023 Nordic Semiconductor ASA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused, is PMCI/MCTP not part of the Zephyr but an external module? If so then I do not think you can add any dependency on it to the USB subsystem.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I looked at it is that MCTP is called out as a base class on usb.org, so the device class implementation can exists in Zephyr, even if the higher-level MCTP protocol management comes from an external module. Right now it comes from libmctp (https://github.com/openbmc/libmctp).

I understand this concern. Is there something you think would create such a dependency? Again, I'm new to Zephyr, so maybe I don't fully understand something.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused, is PMCI/MCTP not part of the Zephyr but an external module?

mctp is not an external module, it is part of the main manifest and there are dependencies on it already.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused, is PMCI/MCTP not part of the Zephyr but an external module?

mctp is not an external module, it is part of the main manifest and there are dependencies on it already.

Anyway, the implementation cannot be part of subsys/usb, and has to go to the modules.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that MCTP is listed on usb.org doesn't matter then?

Copy link
Contributor

@teburd teburd Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfischer-no I too am confused by the comment that this should go to modules, mctp is a subsystem in zephyr built on libmctp.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfischer-no I too am confused by the comment that this should go to a modules, mctp is a subsystem in zephyr built on libmctp.

yeah, this is confusing. The fact that libmctp is a module is irrelevant, this is implementing usb bindings, using both mctp and usb in zephyr, this has nothing to do with libmctp, the usb binding is a zephyr thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that MCTP is listed on usb.org doesn't matter then?

It does not mean anything. The specification is from DMTF association, and I already mentioned that, see #95347 (comment). You should know that, as you had to read it to write this code, or where does the code come from?

I too am confused by the comment that this should go to modules, mctp is a subsystem in zephyr built on libmctp.

What is external dependency, and like a sample in this PR is placed under sample/modules the implementation should be in modules/foobar.

yeah, this is confusing. The fact that libmctp is a module is irrelevant, this is implementing usb bindings, using both mctp and usb in zephyr, this has nothing to do with libmctp, the usb binding is a zephyr thing.

"usb binding" are useless without libmctp, "usb binding" is some trivial USB code that I will not accept in subsys/usb as long as there is no native libmctp implementation in Zephyr. And even then there is no need to place yet another backend to "something" in subsys/usb, a very good example is 6fddc44.

Copy link
Contributor

@teburd teburd Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jfischer-no please, this is like saying I should not accept any code that depends on a hal, we've passed that rubicon long ago

To say it should go in subsys/pmci/mctp that's fine, its where the rest of the binding code is anyways. I get if you don't want to take maintainership of this code that's very understandable and reasonable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"usb binding" are useless without libmctp

right, but we have libmctp and it is not optional.

Anyways, what is it exactly that you want?

  • Is it about the location where the code should be hosted?
  • Is it about this base class not being defined by USB-IF? Where should those go? What about bluetooth, not defined by USB-IF yet it is hosted in subsys/usb/device/class?
  • Or is it about libmctp being a module? In this case, this is a library, mctp and bindings use this library, libmctp on its own does not do anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree area: PMCI Platform Management Communications Infrastructure area: Samples Samples area: USB Universal Serial Bus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants