ESP32-S3 - Two way USB comunication

marbalon
Posts: 23
Joined: Wed Dec 20, 2017 11:02 am

ESP32-S3 - Two way USB comunication

Postby marbalon » Fri Jan 13, 2023 9:58 am

Hi,

I want to communicate with EPOS printer using ESP32-S3 as a host. Everything is working fine as long I'm sending data to the printer. But this printer have two endpoints IN and OUT. To get information about the status of the printer etc. I need to read data coming from the printer. So my question is: What is the correct way to read IN endpoint?

What I'm doing now is sending starting communication like here every time I send something to the printer to get a possible answer:

Code: Select all

esp_err_t read_request(void)
{
    esp_err_t err;
    xfer_in->num_bytes = 64;
    xfer_in->device_handle = last_driver->dev_hdl;
    xfer_in->bEndpointAddress = endpoint_in_address;
    xfer_in->callback = receive_cb;
    xfer_in->timeout_ms = 5000;
    xfer_in->context = last_driver;

    err = usb_host_transfer_submit(xfer_in);

    ESP_LOGI(TAG, "read_request - start - 0x%04X", err);
    return ESP_OK;
}

But after this, I got a rapid callback with USB_TRANSFER_STATUS_COMPLETED and transfer->actual_num_bytes == 0 or 64, but sometimes with some data. Maybe I don't understand something but I thought I should get USB_TRANSFER_STATUS_TIMED_OUT when nothing is received in 5 seconds and USB_TRANSFER_STATUS_COMPLETED only when something is received.

I tried to find any examples with both-way communication but anything I can find is CDC component, but this is slightly different because there is another notify endpoint.

What is the best way to poll IN endpoint?
Last edited by marbalon on Fri Feb 24, 2023 10:17 am, edited 1 time in total.

marbalon
Posts: 23
Joined: Wed Dec 20, 2017 11:02 am

Re: ESP32-S3 - Two way USB comunication

Postby marbalon » Mon Jan 16, 2023 1:06 pm

I've tried to send a read request every 50ms but this gives me a response with 64bytes most of the time, even if the device is not sending anything.

In my callback, I always have status == USB_TRANSFER_STATUS_COMPLETED and actual_num_bytes == 64.

What I'm doing wrong?

Edit.

What is more, I sniffed the data with Wireshark when the printer is connected to the PC and this is working fine. All data is exchanged with BULK IO/OUT frames.

Here are some functions to show how I'm trying to read.

Code: Select all

static void receive_cb(usb_transfer_t *transfer)
{
    xEventGroupSetBits(event_group, DATA_RECEIVED);
}

esp_err_t read_request(void)
{
    esp_err_t err;

    if (xfer_in == NULL || endpoint_in_address == 0 || last_driver == NULL)
    {
        return ESP_OK;
    }

    xfer_in->num_bytes = 64;
    xfer_in->device_handle = last_driver->dev_hdl;
    xfer_in->bEndpointAddress = endpoint_in_address;
    xfer_in->callback = receive_cb;
    xfer_in->timeout_ms = 1000;
    xfer_in->context = last_driver;

    err = usb_host_transfer_submit(xfer_in);

    if (err != ESP_OK)
    {
        ESP_LOGW(TAG, "read_request failed - 0x%04X", err);
    }

    return ESP_OK;
}

static void read_poll_task(void *arg)
{
    ESP_LOGI(TAG, "read_poll task started.");
    while (1)
    {
        if (xfer_in && xfer_in->status == USB_TRANSFER_STATUS_COMPLETED)
        {
            read_request();
        }

        if (xEventGroupWaitBits(event_group, DATA_RECEIVED, pdTRUE, pdTRUE, 50 / portTICK_PERIOD_MS) != 0)
        {
            if (xfer_in->actual_num_bytes == 64)
            {
                //ESP_LOGI(TAG, "Bytes = 64 - ignoring");
                vTaskDelay(pdMS_TO_TICKS(50));
                continue;
            }

            if (xfer_in && xfer_in->status == USB_TRANSFER_STATUS_COMPLETED && xfer_in->actual_num_bytes > 0)
            {
                uint8_t answer[128];
                //ESP_LOGI(TAG, "USB %d bytes received", xfer_in->actual_num_bytes);
                ESP_LOG_BUFFER_HEXDUMP("<==", xfer_in->data_buffer, xfer_in->actual_num_bytes, ESP_LOG_INFO)

                //send it over uart....
            }
        }
        else
        {
            vTaskDelay(pdMS_TO_TICKS(50));
        }
    }
}
Edit2.
I tried many configurations:
- request IO transfer only after a successful OUT transfer
- request IN transfer in separate task every 50/100ms
- change IDF from 4.4 to 5.0

The effect is always the same. While it starts working it is working all the time, and transmission is in both directions. But if it is not working I got no response, sometimes I got the device gone event, and sometimes after a few frames send without a response the transmission start working again and everything works as it should.
Writing to the device is working all the time because I have zero problems with printing anything I want.

Edit3.
I tried also this example:
https://github.com/touchgadget/esp32-us ... rinter.ino

Output was working so I can do some prints. Then the code a bit to send a paper status query every 1 second. And once I got this working and every query I got the correct response. But then I got zero response 0x12.
What I found is that the printer receives these commands correctly and buffers this answer on the printer side, because when I restart the board and send a query for paper status I'm getting answers for frames sent before restart like 0x12 0x12 0x12 0x12 0x12 0x12 ...

So it looks like ESP32 has a problem with transfer IN for some reason.

tore-espressif
Posts: 19
Joined: Thu Oct 07, 2021 8:11 am

Re: ESP32-S3 - Two way USB comunication

Postby tore-espressif » Fri Jan 27, 2023 2:50 pm

Hello marbalon and thank for you interest in USB Host library. I'll try to help you out.

The timeout for transfers is not implemented yet. We have a note about that in the docs, but I can see that the code might be misleading. https://docs.espressif.com/projects/esp ... imeout_msE

Anyway, you should be able to communicate with the printer even without the timeout feature.

From the code that you shared I can see that you are reusing xfer_in for all you BULK IN transfers. This is OK, but keep in mind that once you submit a transfer, you should not modify or submit it again, before it is completed.

Once you submit an IN transfer, the USB-OTG will keep polling the device (printer) for new data until it responds with valid data. Then you get a 'USB_TRANSFER_STATUS_COMPLETED' callback and you can submit the xfer_in transfer again. (This is what the CDC driver is doing with BULK IN transfers too).

In other words: Submit the BULK IN transfer only once. The USB-OTG peripheral will handle the rest. (You can have multiple IN transfers in flight, but not for single IN endpoint).

Let me know if it helped!

marbalon
Posts: 23
Joined: Wed Dec 20, 2017 11:02 am

Re: ESP32-S3 - Two way USB comunication

Postby marbalon » Tue Feb 14, 2023 1:53 pm

Thanks for your reply. I will test it later and will let you know if this helps.

Edit.

Ok, I'm back on this task and I know what was the problem. I always wait for USB_TRANSFER_STATUS_COMPLETED, so only one in transfer is requested then I'm waiting for completion before I send another one. The USB_TRANSFER_STATUS_COMPLETED comes right after the request with actual_num_bytes=64, but I know in this case it is not a valid answer because I'm only asking for printer status and returned data should be only a few bytes, but sometimes it is a few bytes. But it is totally random.

I've just got USB hardware log analyzer so I will compare logs between the printer and host in both cases, maybe thanks to this I will know where is the difference.

Edit2 24.02.2023.

What I've just found is that probably I have to forward all messages, not only bluk transfers but also control frames from tud_vendor_control_xfer_cb() on the MCU emulating the printer and send it over usb_host_transfer_submit_control() on the second MCU acting as host for the printer.

tore-espressif
Posts: 19
Joined: Thu Oct 07, 2021 8:11 am

Re: ESP32-S3 - Two way USB comunication

Postby tore-espressif » Wed Mar 08, 2023 6:50 am

Hello again,
In case you are still having these issues, would you mind sharing USB traces with us? Ideally some Wireshark traces of working communication for reference and the traces from USB HW analyzer that you mentioned?
Cheers, Tomas

marks_cheider
Posts: 3
Joined: Tue Aug 15, 2023 7:25 am

Re: ESP32-S3 - Two way USB comunication

Postby marks_cheider » Tue Aug 15, 2023 11:45 am

Hi. Is somebody done two way usb communication(BULK IN)

Who is online

Users browsing this forum: MicroController and 130 guests