-
Notifications
You must be signed in to change notification settings - Fork 34
feature(usb_host): Support multiple DWC OTG peripheral ports in Host mode #269
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
base: refactor/usb_host_cleanup_hub_parent_child_dependencies
Are you sure you want to change the base?
feature(usb_host): Support multiple DWC OTG peripheral ports in Host mode #269
Conversation
47ba0b1 to
6e126f3
Compare
33e40ea to
a6bb309
Compare
a6bb309 to
e928ef9
Compare
0da5710 to
fbc08d7
Compare
|
You have run out of free Bugbot PR reviews for this billing cycle. This will reset on October 20. To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial. |
415021a to
dcf010b
Compare
- HUB: Added periph_idx argument to hub_root_start() and hub_root_stop()
dcf010b to
85b3cc0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I presume, the suspend/resume feature will have to be supported for multiple peripherals.
| * | ||
| * @return uint8_t Port number | ||
| */ | ||
| uint8_t hcd_port_get_number(hcd_port_handle_t port_hdl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can add get_port_number to the function name? Right now, if you don't' look at the prefix hcd_port, the function name is just get_numer. But up to you.
| uint8_t hcd_port_get_number(hcd_port_handle_t port_hdl); | |
| uint8_t hcd_port_get_port_number(hcd_port_handle_t port_hdl); |
| * - ESP_ERR_INVALID_STATE: Hub driver is not installed, or root port is in other state than not powered | ||
| */ | ||
| esp_err_t hub_root_start(void); | ||
| esp_err_t hub_root_start(uint8_t port_idx); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
During the usb_host_install() we define peripheral map by esp_bit_defs.h, BIT0 and BIT1 respectively. Would it make sense to unify the peripherals selection?
| esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr); | ||
|
|
||
| /** | ||
| * @brief Get the root port handle of a device |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this context, the device is the external hub? Getting a root port handle of device is bit misleading term.
| uint8_t hcd_port_get_number(hcd_port_handle_t port_hdl) | ||
| { | ||
| port_t *port = (port_t *)port_hdl; | ||
| return port->port_num; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In (I think) all the functions in hcd_dwc.c, whenever we are working with port handle, we are using critical section. hcd_port_get_state() is a perfect example which matches this scenario.
| SemaphoreHandle_t mux_lock; | ||
| usb_phy_handle_t phy_handle; // Will be NULL if host library is installed with skip_phy_setup | ||
| unsigned peripheral_map; // Peripheral map | ||
| usb_phy_handle_t phy_hdls[4 /* TODO: 1 */]; // Will be NULL if host library is installed with skip_phy_setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why 4, if we have only 2 USB-OTG peripherals?
| // Start the root hub according to the peripheral map | ||
| for (unsigned idx = 0; idx < 4 /* TODO: 1 */; idx++) { | ||
| if (p_host_lib_obj->constant.peripheral_map & (BIT0 << idx)) { | ||
| ESP_ERROR_CHECK(hub_root_start(idx)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also break form the cycle, once you find the correct peripheral.
| ESP_ERROR_CHECK(hub_root_start(idx)); | |
| ESP_ERROR_CHECK(hub_root_start(idx)); | |
| break; |
| } | ||
| } | ||
|
|
||
| return ret; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case the usb_host_install() has not been called prior to the usb_host_lib_set_root_port_power() call, this function returns just ret, which would be undefined.
Since the for cycle never finds the peripheral map and the if (p_host_lib_obj->constant.peripheral_map & (BIT0 << idx)) is never executed.
You can consider declaring esp_err_t ret as esp_err_t ret = ESP_ERR_NOT_FOUND for example.
Maybe there will be similar unsafe condition, whenever using the similar for cycle for some further action based on peripheral map index.
| static void root_port_handle_events(root_port_t *root_port) | ||
| { | ||
| hcd_port_handle_t root_port_hdl = root_port->constant.hdl; | ||
| uint8_t port_idx = hcd_port_get_number(root_port_hdl); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use const to indicate the port_index is not changing in the function
| uint8_t port_idx = hcd_port_get_number(root_port_hdl); | |
| const uint8_t port_idx = hcd_port_get_number(root_port_hdl); |
| SemaphoreHandle_t mux_lock; | ||
| usb_phy_handle_t phy_handle; // Will be NULL if host library is installed with skip_phy_setup | ||
| unsigned peripheral_map; // Peripheral map | ||
| usb_phy_handle_t phy_hdls[4 /* TODO: 1 */]; // Will be NULL if host library is installed with skip_phy_setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of hardcoding the USB instance count, could we use SOC_USB_OTG_PERIPH_NUM from soc/soc_caps.h? It’s defined per-SoC, so this stays portable across targets.
| implement the bare minimum to control the root HCD port. | ||
| */ | ||
| /* Max support value based on the implementation: 4 */ | ||
| #define HUB_ROOT_PORTS 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can use soc_caps define instead
| #define HUB_ROOT_PORTS 2 | |
| #define HUB_ROOT_PORTS SOC_USB_OTG_PERIPH_NUM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@roma-jam Thank you for your work!
For this feature we were expecting some breaking changes. The is an incomplete list of what must be changed:
usb_host_lib_set_root_port_power()should accept root port index. (or, alternatively, it can always power on/off both ports, but this can be too limiting)- Following members of
usb_host_config_tare specific to USB-DWC configuration, and therefore it should be possible to configure them for each peripheral separately:
root_power_unpoweredintr_flagsfifo_settings_custom
In case we want to avoid the breaking changes, we can just extend the API for dual host. Eg. introduce new function usb_host_install_dual() and usb_host_lib_set_root_power_dual().
This would make the code less cumbersome while providing the feature to users in a clear way.
We can discuss offline when you're ready
1e9a582 to
d9045f6
Compare
Description
Follow-up for: 35401#note_1958915
root_port_hdlto static buffer ofroot_port_hdls[HUB_ROOT_PORTS]whereHUB_ROOT_PORTSis configured statically, via #define (supports<= 4by design, but can be increased)Limitation
usb_host_lib_handle_events())TODO: Refactor HUB_PORTS_NUM: make them dynamically configurable by hub_config_t::port_mapin usb_host.cRelated
N/A
Testing
Common usb host tests.
Checklist
Before submitting a Pull Request, please ensure the following: