esp32-usb-host-demos icon indicating copy to clipboard operation
esp32-usb-host-demos copied to clipboard

Printer demo needs a little further help

Open ralphrmartin opened this issue 3 years ago • 5 comments

With the printer demo, it seems if you try to print just a fixed string like "hello world" instead of a line read from Serial, the program crashes, because PrinterOut is a null pointer.

I guess some extra logic is needed to check for PrinterOut being null, and it would be most instructive and helpful if you could add this.

Or perhaps a better approach would use some callback to tell when the printer is ready to accept data?

ralphrmartin avatar Jun 14 '22 11:06 ralphrmartin

With the printer demo, it seems if you try to print just a fixed string like "hello world" instead of a line read from Serial, the program crashes, because PrinterOut is a null pointer.

PrintOut is initialized as follows so is not NULL.

    err = usb_host_transfer_alloc(endpoint->wMaxPacketSize*PRINTER_OUT_BUFFERS, 0, &PrinterOut);
    if (err != ESP_OK) {
      PrinterOut = NULL;
      Dbg_printf("usb_host_transfer_alloc Out fail: %x", err);
      return;
    }

The following is a an older version of the program that prints "Hello" instead of reading from terminal.

touchgadget avatar Jun 15 '22 00:06 touchgadget

"The following" seems to be missing...

Maybe there is a race condition? I was trying this on an ESP32S3 and v 3.0.2 of the Arduino ESP32 package.

If I use this modification of the loop, printing basically works, but if I leave out the test for PrinterOut being Null, the program just crashes with an illegal memory access exception and restarts, over and over again.

int times = 0;

void loop()
{
  usbh_task();
  
  if ( (PrinterOut != NULL) && (times < 5) ) {
    String aLine = String(times)+"\n";  // Read line ending with newline
    Serial.printf("%d\n",times);
    // readStringUntil removes the newline so add it back
    PrinterOut->num_bytes = aLine.length();
    memcpy(PrinterOut->data_buffer, aLine.c_str(), PrinterOut->num_bytes);
    esp_err_t err = usb_host_transfer_submit(PrinterOut);
    if (err != ESP_OK) {
      ESP_LOGI("", "usb_host_transfer_submit Out fail: %x", err);
    }
    times++;
  } 
}

ralphrmartin avatar Jun 15 '22 05:06 ralphrmartin

This is the older version that just prints hello.

https://github.com/touchgadget/esp32-usb-host-demos/blob/ce8088f4dd3fbf12a8e81b16ee273ae8c30cbc27/examples/usbhprinter/usbhprinter.ino

touchgadget avatar Jun 15 '22 22:06 touchgadget

I note that older version also has a test (PrinterOut != NULL) in it. My example is pretty much the same, except that it prints several lines using a counter, rather than a Boolean flag. If you remove the test for PrinterOut being Null, your old program also crashes.

It seems that, from start up, it takes a time for PrinterOut to become non-Null, and essentially, we must wait for this before trying to print.

ralphrmartin avatar Jun 16 '22 06:06 ralphrmartin

Of course, there must be a check for NULL. The printer may be unplugged on power up. The Arduino sketch runs as a freeRTOS task. The USB host stack is interfaced with another task. If you like, you can create semaphores to sync the tasks.

Prerequisite: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/peripherals/usb_host.html

The ESP-IDF has USB host examples using one more task for the client/class driver and semaphores to sync main, usb host lib task, and usb client/class tasks.

touchgadget avatar Jun 16 '22 17:06 touchgadget