Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: udc: eliminate C++ errors by casting void* to the target type #69490

Merged

Conversation

benedekkupper
Copy link
Contributor

When this header is included in a C++ source file, compilation fails due to invalid syntax. It can be converted to a warning with -fpermissive, but the long term solution is to just perform the missing casts as done here.

@zephyrbot zephyrbot added the area: USB Universal Serial Bus label Feb 26, 2024
tmon-nordic
tmon-nordic previously approved these changes Feb 28, 2024
de-nordic
de-nordic previously approved these changes Feb 28, 2024
@benedekkupper benedekkupper force-pushed the bugfix/udc-cast-void-pointers branch from 8c497c4 to 78cf4f7 Compare February 29, 2024 21:44
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Apr 30, 2024
@benedekkupper
Copy link
Contributor Author

@jfischer-no is there anything to be done to move this PR forward?

@tmon-nordic tmon-nordic removed the Stale label Apr 30, 2024
Copy link
Collaborator

@jfischer-no jfischer-no left a comment

Choose a reason for hiding this comment

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

Here in project, we are using C language. Implicit conversion to a pointer to void is fine and vice versa.
What this PR is trying to fix?

yperess
yperess previously approved these changes May 28, 2024
@benedekkupper
Copy link
Contributor Author

It may be that the bugfix in the branch name is a misnomer, since the Zephyr codebase itself builds without issues. However, Zephyr claims to support applications written in both C and C++. This PR is a step to reach this claim in effect. It has absolutely no adverse effects when compiled into C, but this change is vital to allow compilation into C++.

@benedekkupper benedekkupper requested a review from jfischer-no June 5, 2024 07:29
@kartben
Copy link
Collaborator

kartben commented Aug 9, 2024

@jfischer-no please revisit

@henrikbrixandersen
Copy link
Member

Here in project, we are using C language. Implicit conversion to a pointer to void is fine and vice versa.

But we do support out-of-tree applications written in C++, where implicit pointer conversion leads to a warning.

@kartben
Copy link
Collaborator

kartben commented Jan 10, 2025

@jfischer-no please revisit. There are many drivers in-tree that do this already so I find it really hard to justify why this would be an issue. Thanks!

@henrikbrixandersen
Copy link
Member

@jfischer-no please revisit. There are many drivers in-tree that do this already so I find it really hard to justify why this would be an issue. Thanks!

We even have a dedicated test for including device driver headers from C++: https://github.com/zephyrproject-rtos/zephyr/blob/main/tests/lib/cpp/cxx/src/main.cpp

Copy link
Collaborator

@jfischer-no jfischer-no left a comment

Choose a reason for hiding this comment

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

This is UDC driver API, for the drivers written in C, for the USB device stack written in C, you have to compile it with C compiler not C++. There is no need for this type conversion in C!

@carlescufi
Copy link
Member

carlescufi commented Jan 10, 2025

@benedekkupper can you expand on your use case to try and figure out what the issue is here? Are you trying to write a UDC driver in C++, or are you including the udc.h header in a C++ file? or is it being auto-included making your build fail?

The reason I ask is that I don't see this file included in any public header file that you'd want to include from the application, nor it seems to be included by any .c file outside the core of the USB stack.

@benedekkupper
Copy link
Contributor Author

I am using the UDC driver (and zephyr itself) as one of the supported platforms of an alternative USB device stack (written in C++).

You might be asking, why not using zephyr's own USB device stack instead?

  1. Our project (UHK-80) started 2 years ago, when zephyr's USB device stack was nowhere yet, we needed something working sooner.
  2. C++ allows for a compile-time HID report descriptor parser, so with this solution the USB endpoint max packet sizes are calculated from the report descriptor directly, providing a single source of truth. (It also provides the number of BLE HOGP attributes needed in compile-time, making GATT characteristic and UUID pools unnecessary - but that's nrf sdk territory.)

And now a question from my side: why put so much effort into such a well-defined and well-designed separation between the USB device stack and the UDC driver, if you don't let them be used on their own?

@carlescufi
Copy link
Member

I am using the UDC driver (and zephyr itself) as one of the supported platforms of an alternative USB device stack (written in C++).

You might be asking, why not using zephyr's own USB device stack instead?

  1. Our project (UHK-80) started 2 years ago, when zephyr's USB device stack was nowhere yet, we needed something working sooner.
  2. C++ allows for a compile-time HID report descriptor parser, so with this solution the USB endpoint max packet sizes are calculated from the report descriptor directly, providing a single source of truth. (It also provides the number of BLE HOGP attributes needed in compile-time, making GATT characteristic and UUID pools unnecessary - but that's nrf sdk territory.)

And now a question from my side: why put so much effort into such a well-defined and well-designed separation between the USB device stack and the UDC driver, if you don't let them be used on their own?

Thanks @benedekkupper! This explains it very clearly. I am very much in favor of this change following your explanation. This is a +1 from me.

@jfischer-no
Copy link
Collaborator

I am using the UDC driver (and zephyr itself) as one of the supported platforms of an alternative USB device stack (written in C++).

You might be asking, why not using zephyr's own USB device stack instead?

1. Our project (UHK-80) started 2 years ago, when zephyr's USB device stack was nowhere yet, we needed something working sooner.

2. C++ allows for a compile-time HID report descriptor parser, so with this solution the USB endpoint max packet sizes are calculated from the report descriptor directly, providing a single source of truth. (It also provides the number of BLE HOGP attributes needed in compile-time, making GATT characteristic and UUID pools unnecessary - but that's nrf sdk territory.)

(1) there was a USB device stack there more than two years ago, (2) there is no advantage to doing this for USB transfers.

And now a question from my side: why put so much effort into such a well-defined and well-designed separation between the USB device stack and the UDC driver, if you don't let them be used on their own?

Certainly not for third-party layers, but to enforce consistent behavior and maintainability of the drivers and stack. Unfortunately, there is no clear separation between user and internal headers/interfaces in Zephyr, such as include/zephyr/uapi, which would make it clearer which interfaces are for users.

You provide no information as to why you cannot fix this in your stack where you interface with the UDC API.

@benedekkupper
Copy link
Contributor Author

(1) there was a USB device stack there more than two years ago

Which didn't have the necessary feature-set that we needed, but I shouldn't need to explain this any more than you did when creating the USB device_next stack.

(2) there is no advantage to doing this for USB transfers

You are confused, the HID report sizes are calculated and used to populate the USB max packet size fields of the endpoint descriptors. Much less error-prone than having an independent definition of these descriptors, and having to remember to keep the two things in sync.

You provide no information as to why you cannot fix this in your stack where you interface with the UDC API.

The issue that this patch is trying to fix is syntactic, I have no control over the C++ syntax rules. I can't not include this C header, because the header provides the UDC API types and functions.

@yperess
Copy link
Collaborator

yperess commented Jan 24, 2025

I run into these issues all the time. If it's in a header we need to make it compatible with C++ which means cast it.

@jfischer-no
Copy link
Collaborator

(1) there was a USB device stack there more than two years ago

Which didn't have the necessary feature-set that we needed, but I shouldn't need to explain this any more than you did when creating the USB device_next stack.

(2) there is no advantage to doing this for USB transfers

You are confused, the HID report sizes are calculated and used to populate the USB max packet size fields of the endpoint descriptors. Much less error-prone than having an independent definition of these descriptors, and having to remember to keep the two things in sync.

I am not, especially on nRF USB the maximum allowable interrupt data payload size is 64 bytes or less, so there is no real benefit of using smaller endpoint MPS and no bandwidth issues.

You provide no information as to why you cannot fix this in your stack where you interface with the UDC API.

The issue that this patch is trying to fix is syntactic, I have no control over the C++ syntax rules. I can't not include this C header, because the header provides the UDC API types and functions.

You can add your own header as interface to the UDC API and do there what ever you want.

Also you commit message states:
"It would be nice if C warning was raised for these cases,
so they can be caught faster."
Implicit void pointer conversions are just fine in C and are widely used in Zephyr tree, because we write the code in C not c++. Please rework you commit message to reflect the issue you are facing, describing that the implicit pointer conversion in c++ is not possible.

This header file provides the public API of the UDC driver,
however it also contains inline function definitions.
Unfortunately these definitions contain implicit pointer conversions,
which are one of the cases where valid C syntax is invalid C++ syntax,
meaning that any C++ source code that intends to use the UDC API
cannot be compiled error-free (or warning-free, if using -fpermissive).

Signed-off-by: Benedek Kupper <[email protected]>
@benedekkupper benedekkupper force-pushed the bugfix/udc-cast-void-pointers branch from 5d69b3e to 8ab9914 Compare January 24, 2025 20:48
@benedekkupper
Copy link
Contributor Author

benedekkupper commented Jan 24, 2025

Please rework you commit message to reflect the issue you are facing, describing that the implicit pointer conversion in c++ is not possible.

Done (I also rebased the commit), please review.

Copy link
Collaborator

@jfischer-no jfischer-no left a comment

Choose a reason for hiding this comment

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

Okay, but in general C++ limitations should not weaken our interfaces.

@kartben kartben merged commit 332115c into zephyrproject-rtos:main Jan 27, 2025
24 checks passed
@kartben
Copy link
Collaborator

kartben commented Jan 27, 2025

@benedekkupper thanks so much for your patience! Glad this is now merged :)

@benedekkupper benedekkupper deleted the bugfix/udc-cast-void-pointers branch January 27, 2025 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: USB Universal Serial Bus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants