espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.46k stars 7.25k forks source link

Support for 1-level USB hub in USB host implementation (IDFGH-11416) #12554

Open dordnung opened 11 months ago

dordnung commented 11 months ago

Is your feature request related to a problem?

The ESP32-S3 has only one USB port and furthermore some USB ICs integrate several devices/ports in one chip via a USB hub interface. The XR22800IL32TR-F, for example, has a USB 2.0 hub with 3 downstream ports. However, the host hub implementation currently only supports the root hub. It looks like the usbh.c already supports multiple devices via a USB hub, for example there are already methods like usbh_hub_add_dev. However, the hub implementation itself only supports the root hub. As a result, there are currently no options for integrating more than one device or accessing a specific device behind a hub

Describe the solution you'd like.

It would be handy if the USB host implementation would support at least a 1-level USB hub to connect more than one device to the ESP32 or to use ICs that use an internal USB hub interface

Describe alternatives you've considered.

TinyUSB already supports a 1-level hub in the host implementation, but TinyUSB does not provide host support for the ESP32. Unfortunately I do not have enough understanding of the USB specification to port the implementation of TinyUSB into the esp-idf implementation

Additional context.

No response

roma-jam commented 11 months ago

Hi @dordnung,

Thank for the request!

Yes, that is true that it would be handy to support external HUBs and we have this task in TODO list. At the moment, the focus is much more on the HS support for upcoming chips.

Meanwhile, do you have any specific request regarding external HUBs or any ideas that could help us to make the better requirements for implementation? Please, feel free to share them.

Thanks.

dordnung commented 10 months ago

Hello @roma-jam

good to hear that it's already on the todo list.

Currently I don't have any specific requirements for the implementation, except that it should happen in the background and no user control should be necessary

roma-jam commented 10 months ago

Hi @dordnung ,

Thanks for the information. Right, that is exactly how it suppose to be!

After the implementation is available, there will be an update in this ticket.

Thanks again for you request.

rtek1000 commented 10 months ago

Following

suryasid09 commented 10 months ago

following

sramrajkar commented 8 months ago

Following This has been something I have been looking forward to for a long time. I develop a IoT gateway platform based on ESP32S3 and having way to add more than one USB device will greatly improve flexibility at hardware design level.

spanky411 commented 7 months ago

Also interested. My specific application is connecting to an integrated device that is behind a dedicated hub. I know its not a general solution, but if you know the details of the hub, is there a way (in the current framework) to connect to the device behind it?

Docfch commented 7 months ago

when it will be available ?

Docfch commented 7 months ago

still not available ?

rtek1000 commented 7 months ago

"Status: In Progress" nice!

rtek1000 commented 7 months ago

I don't know if it helps, but there are other libraries with USB HUB implementation, like this: (It is for MAX3421 IC)

Current working USB interface drivers

HID RAW
MIDI
Hub
Mass storage
CDC-ACM serial
XR21B1411 serial
PROLIFIC serial
FTDI serial

https://github.com/felis/UHS30

ramalhais commented 7 months ago

Also waiting for hub support. Thanks!

rtek1000 commented 7 months ago

I remembered another library that implements a USB Hub, it is the simplest library I found about Hub, apparently it expands the variables (arrays) to serve more than one device, which is why it seems to be so difficult to understand, and transparent at the same time:

https://github.com/mori-br/STM32F4HUB/tree/master/Project/Middlewares/ST/STM32_USB_Host_Library/Class/HUB

emanuelelaface commented 4 months ago

Still no news about this?

roma-jam commented 4 months ago

Hi @rtek1000,

Still in progress. First release planned to June.

alex-k8 commented 4 months ago

Hi @rtek1000,

Still in progress. First release planned to June.

Hey @roma-jam, good to hear that it's still in progress! In the meantime, I've been trying to handle it on my own, and I feel like I've hit a wall. To summarize what I've done, I analyzed the packets sent to (and from) the HUB using Wireshark on MAC, and I'm replicating those control transfers on my ESP32S3. I'm able to enumerate the ports on the HUB and detect when a device is connected.

I can send commands to the HUB to get the HUB Descriptor, and I also send the PORT_RESET feature to reset the port and start the communication to the connected device. However this is where my issue is. When I use GET_DESCRIPTOR it returns the HUB descriptor instead of the device. From what I've read, after the PORT_RESET command, the connected device is assigned to the default address 0. I suspect the GET_DESCRIPTOR is returning the HUB Descriptor because I'm passing the saved device handle, which on the background has an address of not 0?

usb_transfer_t *transfer;
  usb_host_transfer_alloc(8 + 18 + 1, 0, &transfer); // Allocate transfer buffer

  transfer->num_bytes = 8 + 18;
  transfer->data_buffer[0] = 0x80;
  transfer->data_buffer[1] = 0x06; // bRequest (GET_DESCRIPTOR)
  transfer->data_buffer[2] = 0x00; // wValue (LSB) 
  transfer->data_buffer[3] = 0x01; // wValue (MSB) DEVICE
  transfer->data_buffer[4] = 0x00; // wIndex (LSB)
  transfer->data_buffer[5] = 0x00; // wIndex (MSB)
  transfer->data_buffer[6] = 0x12; // wLength (LSB) 18
  transfer->data_buffer[7] = 0x00; // wLength (MSB)

  transfer->device_handle = deviceHandle;
  transfer->bEndpointAddress = 0x00;
  transfer->callback = _onReceiveHubDescriptor;
  transfer->context = this;

  esp_err_t err = usb_host_transfer_submit_control(clientHandle, transfer);

I tried using the SET_ADDRESS command but it didn't seem to do much. Do I have to close and open the handle again with the new address? Even if that's the case, I suspect the SET_ADDRESS command will run on the HUB and not the device, since again I'm passing the deviceHandle as seen above (which is the HUB handle)?

Since I'm handling the enumeration by myself, do I have to call usb_host_device_open by myself to get the connected device handle? Can I have two handles open at the same time, or does this mean that I can't "Only supports a single device, but the Host Library's API is designed for multiple device support"?

If I try to use usb_host_device_open on address 0, I get the error: (0x102): Invalid argument and if I try to use it on address 2 (after using SET_ADDRESS to change the address to 2), I get the error: (0x105): Requested resource not found

By using the usb_host_device_addr_list_fill command, I can only see one device which is the HUB at address 1, even after using the SET_ADDRESS to change it.

Lastly, if I try to use GET_DESCRIPTOR after SET_ADDRESS, I get an error: USBH: Dev 1 EP 0 Error so I suppose the address of the HUB is indeed changing, but I have to update the device handle somehow? Not that I want to change the address of the HUB, I want to change the address of the connected device so I can communicate with it. If I use the built in usb_host_get_device_descriptor it returns the HUB Descriptor, because it's probably cached.

Sorry for the lengthy reply, any tip is highly appreciated, thank you!

I'm using the Arduino IDE by the way.

Edit: I tried calling SET_ADDRESS and setting it to 2, and on its response I tried calling usb_host_device_open, and I got the error: (0x105): Requested resource not found. Actually this happens on every command I try to send, after SET_ADDRESS. I somehow have to call the enumeration again from scratch? How do I do that?

archef2000 commented 4 months ago

Following Is there a way to see the progress? Wanting to try it out with a usbip implementation.

Docfch commented 4 months ago

Me too, i have to do it to send 3 hubs connected each other and 1 stm32 for each hub through wifi, usb ip as you said

rtek1000 commented 4 months ago

Hi @rtek1000,

Still in progress. First release planned to June.

Please, there is no need to stress, the important thing is to achieve it, take as much time as you need. Thank you.

emanuelelaface commented 3 months ago

Hi @rtek1000,

Still in progress. First release planned to June.

looking forward for it. I have several project that can use multiple USB and the HUB is really an important feature.

devemin commented 3 months ago

I'm watching this thread 😆 i hope this Hub support!

By the way, I tried ESP32-S3 multi device plug and play.

https://x.com/devemin/status/1806618148449472649?t=dUanlXj-NXaKhUdyFNlA8A&s=19

I can't wait your supporting the USB Hub! Thanks for fantastic Espressif devices.

Docfch commented 2 months ago

@devemin i saw your video, you are running one device at time but the idea is to run multi device and multi hubs at the same time of course

archef2000 commented 2 months ago

@roma-jam Any updates?

rtek1000 commented 2 months ago

We may need to see if there are resources for multiple HUB levels, such as RAM.

At first, I believe that it is already interesting to be able to operate with just 1 HUB (1 Level) and 4 devices.

Note: A 7-port HUB usually has 2 HUB levels.

archef2000 commented 2 months ago

Maybe for that let the user decide what levels and devices should be available.

roma-jam commented 2 months ago

Hi @archef2000 ,

Its currently in the review state. Took a bit longer, than expected, but we are closer to complete this ticket than ever.

There will be a multiple Hubs support with a configurable option to have only 1 layer supported.

archef2000 commented 2 months ago

Oh thats great to hear. I am looking forward to trying it out.

bwhitman commented 1 month ago

I see that exthub.c and friends were committed to master a couple of months ago. And there are docs for external hubs available. It's my understanding that although this code is committed, it's still not all setup yet to work. I tested it out on my application, using the usb_host_lib, just the hub is being enumerated, not any devices connected to the hub. Please let me know if I've misunderstood anything, otherwise, i will wait for further commits!

I (2379) CLASS: Installing USB Host Library
W (2385) EXT_HUB: Port Driver has not been installed
D (2390) EXT_HUB: Driver installed
I (2424) CLASS: Registering Client
D (3274) HUB: Root port reset
D (3274) HUB: New device tree node (uid=1)
D (3274) ENUM: [0:0] Start processing, device address 0
D (3275) ENUM: [0:0] GET_SHORT_DEV_DESC OK
D (3279) USBH: Processing actions 0x4
D (3283) USBH: Default pipe device 0
D (3287) ENUM: [0:0] CHECK_SHORT_DEV_DESC OK
D (3891) ENUM: [0:0] SECOND_RESET OK
D (3891) ENUM: [0:0] SET_ADDR OK
D (3891) USBH: Processing actions 0x4
D (3891) USBH: Default pipe device 0
D (3894) ENUM: Assign address (dev_addr=1)
D (3898) ENUM: [0:0] CHECK_ADDR OK
D (3912) ENUM: [0:0] SET_ADDR_RECOVERY OK
D (3912) ENUM: [0:0] GET_FULL_DEV_DESC OK
D (3912) USBH: Processing actions 0x4
D (3914) USBH: Default pipe device 1
D (3917) ENUM: [0:0] CHECK_FULL_DEV_DESC OK
D (3921) ENUM: Selected bConfigurationValue=1
D (3926) ENUM: [0:0] SELECT_CONFIG OK
D (3929) ENUM: [0:0] GET_SHORT_CONFIG_DESC OK
D (3934) USBH: Processing actions 0x4
D (3938) USBH: Default pipe device 1
D (3941) ENUM: [0:0] CHECK_SHORT_CONFIG_DESC OK
D (3946) ENUM: [0:0] GET_FULL_CONFIG_DESC OK
D (3950) USBH: Processing actions 0x4
D (3954) USBH: Default pipe device 1
D (3958) ENUM: [0:0] CHECK_FULL_CONFIG_DESC OK
D (3962) ENUM: [0:0] GET_SHORT_LANGID_TABLE OK
D (3967) USBH: Processing actions 0x4
D (3970) USBH: Default pipe device 1
D (3974) ENUM: [0:0] CHECK_SHORT_LANGID_TABLE OK
D (3979) ENUM: [0:0] GET_FULL_LANGID_TABLE OK
D (3983) USBH: Processing actions 0x4
D (3987) USBH: Default pipe device 1
D (3991) ENUM: [0:0] CHECK_FULL_LANGID_TABLE OK
D (3995) ENUM: String iManufacturer not set, skip
D (4000) ENUM: [0:0] GET_SHORT_MANU_STR_DESC OK
D (4004) ENUM: String iManufacturer not set, skip
D (4009) ENUM: [0:0] CHECK_SHORT_MANU_STR_DESC OK
D (4014) ENUM: String iManufacturer not set, skip
D (4019) ENUM: [0:0] GET_FULL_MANU_STR_DESC OK
D (4023) ENUM: String iManufacturer not set, skip
D (4028) ENUM: [0:0] CHECK_FULL_MANU_STR_DESC OK
D (4033) ENUM: [0:0] GET_SHORT_PROD_STR_DESC OK
D (4037) USBH: Processing actions 0x4
D (4041) USBH: Default pipe device 1
D (4045) ENUM: [0:0] CHECK_SHORT_PROD_STR_DESC OK
D (4050) ENUM: [0:0] GET_FULL_PROD_STR_DESC OK
D (4054) USBH: Processing actions 0x4
D (4058) USBH: Default pipe device 1
D (4062) ENUM: [0:0] CHECK_FULL_PROD_STR_DESC OK
D (4066) ENUM: String iSerialNumber not set, skip
D (4071) ENUM: [0:0] GET_SHORT_SER_STR_DESC OK
D (4075) ENUM: String iSerialNumber not set, skip
D (4080) ENUM: [0:0] CHECK_SHORT_SER_STR_DESC OK
D (4085) ENUM: String iSerialNumber not set, skip
D (4090) ENUM: [0:0] GET_FULL_SER_STR_DESC OK
D (4094) ENUM: String iSerialNumber not set, skip
D (4099) ENUM: [0:0] CHECK_FULL_SER_STR_DESC OK
D (4104) ENUM: [0:0] SET_CONFIG OK
D (4107) USBH: Processing actions 0x4
D (4111) USBH: Default pipe device 1
D (4114) ENUM: [0:0] CHECK_CONFIG OK
D (4118) ENUM: [0:0] Processing complete, new device address 1
D (4124) ENUM: [0:0] COMPLETE OK
D (4127) USBH: Processing actions 0x40
D (4131) USBH: New device 1
I (4134) CLASS: Opening device at address 1
I (4139) CLASS: Getting device information
I (4143) CLASS:     Full speed
I (4147) CLASS:     bConfigurationValue 1
I (4151) CLASS: Getting device descriptor
*** Device descriptor ***
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0x9
bDeviceSubClass 0x0
bDeviceProtocol 0x0
bMaxPacketSize0 64
idVendor 0x1a40
idProduct 0x101
bcdDevice 1.00
iManufacturer 0
iProduct 1
iSerialNumber 0
bNumConfigurations 1
I (4179) CLASS: Getting config descriptor
*** Configuration descriptor ***
bLength 9
bDescriptorType 2
wTotalLength 25
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xe0
bMaxPower 100mA
    *** Interface descriptor ***
    bLength 9
    bDescriptorType 4
    bInterfaceNumber 0
    bAlternateSetting 0
    bNumEndpoints 1
    bInterfaceClass 0x9
    bInterfaceSubClass 0x0
    bInterfaceProtocol 0x0
    iInterface 0
        *** Endpoint descriptor ***
        bLength 7
        bDescriptorType 5
        bEndpointAddress 0x81   EP 1 IN
        bmAttributes 0x3    INT
        wMaxPacketSize 1
        bInterval 255
I (4231) CLASS: Getting Product string descriptor
USB2.0 HUB
D (4238) EXT_HUB: [1] New device (iface 0)
D (4242) EXT_HUB: [1] Processing actions 0x20
D (4247) EXT_HUB: Stage GET_HUB_DESCRIPTOR OK
D (4251) USBH: Processing actions 0x4
D (4255) USBH: Default pipe device 1
D (4258) EXT_HUB: [1] Processing actions 0x2
D (4263) EXT_HUB: [1] Device configure (iface 0)
D (4267) EXT_HUB:   Standalone HUB
D (4271) EXT_HUB:   4 external ports
D (4274) EXT_HUB:   All ports power at once
D (4278) EXT_HUB:   Global over-current protection
D (4283) EXT_HUB:   Port indicators are supported
D (4288) EXT_HUB:   Power on to power good time: 100ms
D (4293) EXT_HUB:   Maximum current: 100 mA
D (4297) EXT_HUB: Stage CHECK_HUB_DESCRIPTOR OK
archef2000 commented 1 month ago

You can talk to the hub but not the attached to it. It is not in any official release.

rtek1000 commented 1 month ago

I remembered another driver that supports HUB, which might be a source of research:

ChibiOS Forum "USB host stack and driver for STM32"

  • HUB driver, tightly integrated with the high level driver, to connect multiple devices to the USB port.

http://forum.chibios.org/viewtopic.php?f=16&t=2968&sid=afd037349cc1b55f54a428350fc8f5fc

Note: Unfortunately, there is a physical problem in STM32 IC so you may not be able to use HUB (appears to be related only to the internal PHY), but it is interesting to know that the code exists.

archef2000 commented 1 month ago

It is already implemented in esp-idf master just not released as a version. https://github.com/espressif/esp-idf/blob/master/components/usb/private_include/ext_hub.h#L75

roma-jam commented 1 month ago

Hi @bwhitman ,

There will be the second part regarding external hubs’ ports available soon. When the final release is done, we will notify about that and change the state of this ticket.

Sorry for the inconveniences.

maaamcube commented 4 days ago

@roma-jam i see that the status is done, where is the release ? thanks

roma-jam commented 4 days ago

Hi @maaamcube ,

The feature was added internally and usually it takes some time to pass the tests and synchronize them with the public repo. When it will be done, the ticket should be closed. The changes will be available soon.