-
Notifications
You must be signed in to change notification settings - Fork 20
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
feat(usb_host_uvc): support dual camera with hub (IEC-246) #109
base: master
Are you sure you want to change the base?
feat(usb_host_uvc): support dual camera with hub (IEC-246) #109
Conversation
93fde33
to
7d193d8
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.
@lijunru-hub thank you very much for fixing this limitation.
The new open API with dev_addr
looks good to me.
I left few comments for your consideration
host/class/uvc/usb_host_uvc/private_include/uvc_descriptors_priv.h
Outdated
Show resolved
Hide resolved
host/class/uvc/usb_host_uvc/private_include/uvc_descriptors_priv.h
Outdated
Show resolved
Hide resolved
union { | ||
struct { | ||
uint8_t dev_addr; | ||
uint8_t iface_num; //!< Disconnection event |
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'm not sure why we need to pass iface_num
to the user... Do you have any example of usage?
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 misunderstood the meaning of uvc_host_stream_config_t: uvc_stream_index. We should change iface_num to uvc_stream_index here.
If a camera supports multiple video streams, the callback will be called multiple times, with the uvc_stream_index being returned incrementally each time.
// Create UAC interfaces list in RAM, connected to the particular USB dev | ||
if (is_uvc_device) { | ||
// TODO: add config to control it | ||
// usb_print_config_descriptor(config_desc, &uvc_print_desc); | ||
// Create Interfaces list for a possibility to claim Interface | ||
ESP_RETURN_ON_ERROR(uvc_host_interface_check(addr, config_desc), TAG, "uvc stream interface not found"); | ||
} else { | ||
ESP_LOGW(TAG, "USB device with addr(%d) is not UVC device", addr); | ||
} |
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.
If we do not pass iface_num
to the user, this whole part can be removed, simplifying the code a lot. Do we really need it?
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.
7d193d8
to
c037c57
Compare
@tore-espressif I added an API, |
0bb1f2b
to
9bc9961
Compare
9bc9961
to
290d524
Compare
|
||
num_frame = this_format->bNumFrameDescriptors; | ||
new_frame_info = calloc(num_frame, sizeof(uvc_host_frame_info_t)); | ||
UVC_CHECK(new_frame_info != NULL, ESP_ERR_NO_MEM); |
Check warning
Code scanning / clang-tidy
Potential leak of memory pointed to by 'frame_info' [clang-analyzer-unix.Malloc] Warning
|
||
num_frame = this_format->bNumFrameDescriptors; | ||
new_frame_info = calloc(num_frame, sizeof(uvc_host_frame_info_t)); | ||
UVC_CHECK(new_frame_info != NULL, ESP_ERR_NO_MEM); |
Check warning
Code scanning / clang-tidy
Potential leak of memory pointed to by 'new_frame_info' [clang-analyzer-unix.Malloc] Warning
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.
@lijunru-hub Thank you very much for this PR!
The API changes LGTM and the features are very useful. I have only one concern about memory allocation. Could you please fix it? You can contact me if anything is unclear
Thanks again!
* | ||
* @param[in] config_desc Pointer to the USB configuration descriptor. | ||
* @param[in] bInterfaceNumber The interface number to search for frame descriptors. | ||
* @param[out] frame_info_list Pointer to a list of frame info structures (allocated dynamically). |
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.
My main concern aligns with the issues flagged by the static analyzer: the use of dynamic memory allocation.
This violates the principle of ownership in dynamic memory management—if you allocate memory, it's your responsibility to ensure it is properly freed. Relying on others to manage memory you allocate can lead to resource leaks or undefined behavior. Consider revising this to avoid dynamic allocation or clearly define ownership and the lifecycle of the allocated memory.
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.
This API needs to be designed to be called twice: the first call retrieves the list length, and after the user allocates sufficient memory, the second call fills the data.
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.
How about this:
- the new device callback (
uvc_host_driver_event_data_t
) gives user number of frame formats. - In the callback, the user allocates the memory (array of
uvc_host_frame_info_t
) and passes pointer and size of this array touvc_desc_get_frame_list
, which fills the array - The user is responsible for freeing the memory when he is done
So it could look like this
typedef struct {
enum uvc_host_driver_event type; /**< Event type */
union {
struct {
uint8_t dev_addr; /**< Device address */
uint8_t uvc_stream_index; /**< Index of UVC function you want to use. Set to 0 to use first available UVC function */
size_t frame_info_num; /**< Number of frame information list */
} device_connected; /**< UVC_HOST_DEVICE_CONNECTED event */
};
} uvc_host_driver_event_data_t;
// This is public API
esp_err_t uvc_desc_get_frame_list(
uint8_t dev_addr; /**< Pass value from the callback */
uint8_t uvc_stream_index; /**< Pass value from the callback */ // TODO:Update these comments. This function can be also called from other places
uvc_host_frame_info_t (*frame_info_list)[], // Pointer to array of uvc_host_frame_info_t
size_t list_size // Size of the list - to avoid out-of-boundaries array access
);
Description
Feature:
usb_handle
ordev_addr
.Related
Testing
Checklist
Before submitting a Pull Request, please ensure the following: