Git Product home page Git Product logo

pico-pio-usb's Introduction

Pico-PIO-USB

USB host/device implementation using PIO of raspberry pi pico (RP2040).

You can add additional USB port to RP2040.

Demo

demo.mp4

Project status

Planned Features Status
FS Host
LS Host
Hub support
Multi port
FS Device

Examples

  • capture_hid_report.c is a USB host sample program which print HID reports received from device. Open serial port and connect devices to pico. Default D+/D- is gp0/gp1. Call pio_usb_add_port() to use additional ports.
  • usb_device.c is a HID USB FS device sample which moves mouse cursor every 0.5s. External 1.5kohm pull-up register is necessary to D+ pin (Default is gp0).
  • host_hid_to_device_cdc.c is similar to capture_hid_report.c which print mouse/keyboard report from host port to device port's cdc. TinyUSB is used to manage both device (native usb) and host (pio usb) stack.
cd examples
mkdir build
cd build
cmake ..
make
# Copy UF2 file in capture_hid_report/ or usbdevice/ to RPiPico

Another sample program for split keyboard with QMK

https://github.com/sekigon-gonnoc/qmk_firmware/tree/rp2040/keyboards/pico_pico_usb

Resource Usage

  • Two PIO
    • One PIO is for USB transmitter using 22 instruction and one state machine
    • Another PIO is for USB receiver using 31 instruction and two state machine
  • Two GPIO for D+/D- (Series 22ohm resitors are better)
  • 15KB ROM and RAM
  • (For Host) One 1ms repeating timer
  • (For Device) One PIO IRQ for receiver

pico-pio-usb's People

Contributors

devdtc avatar dglaude avatar fahimfba avatar hathach avatar kilograham avatar lyusupov avatar molorius avatar rppicomidi avatar sekigon-gonnoc avatar spamixofficial avatar tannewt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pico-pio-usb's Issues

GPIO device hid

Hello!

This is not a problem or a request for new functionality

I just wonder if it is possible to use GPIO to send keystrokes. I have seen several examples in the Adafruit library that use GPIO for USB Host. Is it possible to use this for HID device?

Thanks!

💡[FEATURE] host_hid_to_device_cdc example - controlling keyboard LEDs - working sample code

Hi,

In the host_hid_to_device_cdc example, you mention in a comment:
// TODO control LED on keyboard of host stack

In the above example, I tried playing with the keyboard Caps Lock LED using the tuh_hid_set_report function like so:

static uint8_t leds = KEYBOARD_LED_CAPSLOCK; //  = 2
tuh_hid_set_report(dev_addr, instance, 0, HID_REPORT_TYPE_OUTPUT, &leds, sizeof(leds));

but failed to get any results.

Is it because I am not doing things the right way or is it something that the Pico-PIO-USB library does not yet support?

Thank you.

USB 1:2 Mux

I'm looking to implement a USB mux for a keyboard and mouse. I know these exist in IC form with chips such as the FSUSB42UMX but I thought it would be neat if I could intercept a certain key combo on the keyboard to toggle the mux. I immediately though of the PIO on the RP2040 knowing it would be fast enough for USB FS. I was really happy to see that this library already existed.

With the current implementation would it be possible to create 2 device ports and a host port? Or could I create two device ports and use the native USB as the host? I know you have examples for multiple host ports but I need multiple devices. It looks like it should be possible, I just wanted to check before I get too deep into this.

Thanks for the help!

🪲[BUG] Example links in Readme not working due to 3 missing "s"

Describe the bug you encountered:
The links to

Examples

on main Readme page do not connect to anything

What did you expect to happen instead?
I expected them to link me to

examples/capture_hid_report/capture_hid_report.c
examples/usb_device/usb_device.c
examples/host_hid_to_device_cdc/tinyusb_host_hid_to_device_cdc.c

What actually happened in your case?
I was redirected to a github 404 page

Additional information
I think the "examples" folder was once renamed from "example" to "examples", but those links were not updated.

This should be a drop in replacement, obviously you could add the "s" instead

- [capture_hid_report.c](examples/capture_hid_report/capture_hid_report.c) is a USB host sample program which print HID reports received from device. Open serial port and connect devices to pico. Default D+/D- is gp0/gp1. Call `pio_usb_add_port()` to use additional ports.
- [usb_device.c](examples/usb_device/usb_device.c) is a HID USB FS device sample which moves mouse cursor every 0.5s. External 1.5kohm pull-up register is necessary to D+ pin (Default is gp0).
- [host_hid_to_device_cdc.c](examples/host_hid_to_device_cdc/tinyusb_host_hid_to_device_cdc.c) is similar to **capture_hid_report.c** which print mouse/keyboard report from host port to device port's cdc. TinyUSB is used to manage both device (native usb) and host (pio usb) stack.

Have a great day, your library is awesome

libusb possible?

I'd love to be able to control a USB 2.0 device (not keyboard/mouse/HID) with RP2040. Is that possible with this project?

💡[FEATURE] Make repo Arduino library compatible

Hi hi, I am trying to get pico-pio-usb working with arduino platform, basically with

It is actually quite easy to make this repo compatible with Arduino IDE. We only need to

  • add library.properties
  • rename example to examples (plugrals)
  • also included generated usb_rx/tx.pio.h since we probably don't have access to cmake pico_generate_pio_header
  • Finally registry to arduino indexer https://github.com/arduino/library-registry

Another gotcha that Arduino IDE will recursive compiles all the files/folders under src, but I think we are good with it, just need to pay attention to this in the future PRs. But we could add an ci to verify that it build with arduino just fine.

Let me know what you think, since I have done a decent amount of work with Arduino library, I could help making all of these.

@ladyada

💡[FEATURE] High Speed capability on a supported Pi device?

**Hi,
I'm very thankful that you have made this library. I have been able to poll my devices at 1KHz thanks to this library. I was wondering if the same code can be replicated to work on a Pi board that supports high speed usb port speed so that it may be possible to poll devices at even higher rates - say up to even 4KHz? Any idea where one can start in order to do this? Which board would you recommend and how challenging would it be to do it? **

Missing the issue templates

The project is currently missing the issue templates. I want to add a PR with those templates if you approve that.

Thanks.

🪲[BUG] control in[error] Enumeration failed(-1)

Describe the bug you encountered:
I've been attempting to get the example capture_hid_report code working, but upon running and testing it, I discovered that most keyboards, when plugged in, don't actually print anything to the uart. A select few that I've tried do print something to the log when plugged in or when a key is pressed, but it appears there's an error with parsing or reading anything the device is sending.

What did you expect to happen instead?

I'm expecting the keyboard to show up in UART and display received data

What actually happened in your case?

Root 0 connected
Device 0 Connected
control in[error]
Enumeration failed(-1)
Root 0 disconnected
Disconnect
Disconnect device 0

The above error is printed any time a button is pressed or whenever the keyboard is plugged in (on the few keyboards I own that seem to get somewhat recognized by the pico).

Additional information

Standard cmake compile setup using ninja for builds via the Windows pico-sdk's included VSCode install. Latest SDK, latest repo version, using a Pico W.

It's possible I might just be doing something wrong on the hardware side, but for the moment I just have the USB device connected to D+ on gp0 and D- on gp1.

Thanks so much for this :)

🪲[BUG] USB Flash drive descriptor read fails unless log level is 3

Describe the bug you encountered:
I realize this is not supported yet officially, but I am attempting to implement a USB MSC Host with the Pico-PIO-USB. If log level is 1, enumeration fails getting the USB descriptor of the flash drive with a printout

[1:0] Control FAILED

If I set the log level to 3, enumeration succeeds. The flash drive mounts and I am able to read the block size and block count.
...

What did you expect to happen instead?
I expected the host to at least be able to read the USB device descriptor even if USB MSC Host is not yet supported.
...

What actually happened in your case?
Descriptor read fails every time.

...

Additional information

I am using a Raspberry Pi Pico board and a USB A breakout board that I modified to insert 27 ohm SMT resistors in series with the D+ and D- pins. I have routed D+ to Pico board pin 1 and D- to Pico board pin 2 as per default. I am using a Picoprobe for debug and for UART output; UART0 is the debug UART; I am using Pico board pins 21 and 22 for the UART: i.e., in my CMakeLists.txt

PICO_DEFAULT_UART_TX_PIN=16
PICO_DEFAULT_UART_RX_PIN=17

Power is supplied by my PC via the Pico Board microUSB connector. The USB device mode on the microUSB connector is not yet initialized. I have tested this hardware system with a USB Keyboard connected to the USB A + sample code and with 3 different MIDI devices connected to the USB A + my own USB MIDI host code. All work correctly.

I have a DreamSourceLab logic analyzer, so I can dig deeper. Any hints as to where I should look? Are there PulseView traces that you would recommend I examine?


🪲[BUG] Can not communicate with Arduino nano every

At this point I have been at this for days so here is the issue, I have this code on an arduino nano

void setup() {
  Serial.begin(115200);
}

void loop() {
  while (Serial.available())
  {
    const uint8_t res = Serial.read();
    if (res == 'V')
      Serial.println("4.7V"); 
  }
  Serial.println("test");
  delay(1500);
}

and this is the code on the pico

// pio-usb is required for rp2040 host
#include "pio_usb.h"

// TinyUSB lib
#include "Adafruit_TinyUSB.h"

// Pin D+ for host, D- = D+ + 1
#define HOST_PIN_DP       2

// USB Host object
Adafruit_USBH_Host USBHost;

// CDC Host object
Adafruit_USBH_CDC  SerialHost;

//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+

void setup() {
  Serial1.begin(115200);

  Serial.begin(115200);
  while ( !Serial ) delay(10);   // wait for native usb

  Serial.println("TinyUSB Host Serial Echo Example");
}

void loop()
{
  //Serial.printf("%d\n", SerialHost.connected());
  uint8_t buf[64];

  // Serial -> SerialHost
  if (Serial.available()) {
    size_t count = Serial.read(buf, sizeof(buf));
    if ( SerialHost && SerialHost.connected() ) {
      Serial.printf("sending %s\n", buf);
      SerialHost.write(buf, count);
      SerialHost.flush();
    }
  }

  // SerialHost -> Serial
  if ( SerialHost.connected() && SerialHost.available() ) {
    size_t count = SerialHost.read(buf, sizeof(buf));
    Serial.printf("%s\n", buf);
  }
}

//--------------------------------------------------------------------+
// Setup and Loop on Core1
//--------------------------------------------------------------------+

void setup1() {
  while ( !Serial ) delay(10);   // wait for native usb
  Serial.println("Core1 setup to run TinyUSB host with pio-usb");

  // Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
  uint32_t cpu_hz = clock_get_hz(clk_sys);
  if ( cpu_hz != 120000000UL && cpu_hz != 240000000UL ) {
    while ( !Serial ) {
      delay(10);   // wait for native usb
    }
    Serial.printf("Error: CPU Clock = %u, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
    Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n", cpu_hz);
    while(1) {
      delay(1);
    }
  }

#ifdef HOST_PIN_VBUS_EN
  pinMode(HOST_PIN_VBUS_EN, OUTPUT);

  // power off first
  digitalWrite(HOST_PIN_VBUS_EN, 1-HOST_PIN_VBUS_EN_STATE);
  delay(1);

  // power on
  digitalWrite(HOST_PIN_VBUS_EN, HOST_PIN_VBUS_EN_STATE);
  delay(10);
#endif

  pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
  pio_cfg.pin_dp = HOST_PIN_DP;
  USBHost.configure_pio_usb(1, &pio_cfg);

  // run host stack on controller (rhport) 1
  // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
  // host bit-banging processing works done in core1 to free up core0 for other works
  USBHost.begin(1);
}

void loop1()
{
  USBHost.task();

  // periodically flush SerialHost if connected
  if ( SerialHost && SerialHost.connected() ) {
    SerialHost.flush();
  }
}

void tuh_mount_cb(uint8_t daddr) {
  Serial.printf("Device attached, address = %d\r\n", daddr);

  if (tuh_cdc_mounted(0)) {
    Serial.printf("Device at %d is a cdc device!\n", daddr);
    cdc_line_coding_t line_encoding;
    if (tuh_cdc_get_local_line_coding(0, &line_encoding))
    {
      Serial.printf("baud = %d\n", line_encoding.bit_rate);
      Serial.printf("data bits = %d\n", line_encoding.data_bits);
      Serial.printf("stop bits = %d\n", line_encoding.stop_bits);
      Serial.printf("parity = %d\n", line_encoding.parity);
    }
  } else {
    Serial.printf("Device at %d is NOT cdc DEVICE!\n", daddr);
  }

  // Get Device Descriptor
  //tuh_descriptor_get_device(daddr, &desc_device, 18, print_device_descriptor, 0);
}

//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+

// Invoked when a device with CDC interface is mounted
// idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) {
  // bind SerialHost object to this interface index
  SerialHost.begin(idx);

  Serial.printf("SerialHost is connected to a new CDC device (%d)\n", idx);
}

// Invoked when a device with CDC interface is unmounted
void tuh_cdc_umount_cb(uint8_t idx) {
  if (idx == SerialHost.getIndex()) {
    // unbind SerialHost if this interface is unmounted
    SerialHost.end();
    Serial.println("SerialHost is disconnected");
  }
}

I plug in the nano via its usb port to the gpio 2 and 3 of pico and it is recognized as a cdc device and does connect yet I can not communicate with it

SerialHost is connected to a new CDC device (0)
Device attached, address = 1
Device at 1 is a cdc device!
baud = 0
data bits = 0
stop bits = 0
parity = 0

I have tried changing this

#define CFG_TUH_CDC_LINE_CODING_ON_ENUM   { 115200, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }

in the config thinking maybe it was a baud issue but then isConnected() just returns false for SerialUSB..furthermore if you try this same thing on an arduino uno it doesnt even show up as a cdc device...can someone post an example of how to simply plug in a device and communicate over serial like u would if you plugged it into the pc?

🪲[BUG] First RX fails with bits shifted by one.

Describe the bug you encountered:

The capture of the response to the very first setup packet fails. I think this is the very first time anything is captured by the RX PIO. Maybe its initial state is incorrect?

What did you expect to happen instead?

The RX PIO should capture the SYNC and ACK packets (0x80 and 0xd2).

What actually happened in your case?

Instead, it errors because it captured 0x01 and 0xa5. Note that this is (0xd2 << 1 | 1).

Additional information

This is using USB Host via CircuitPython for testing. However, this is low level enough that I don't think it's the issue. Subsequent ACKs are captured correctly.

Serial console setup       << Start of CircuitPython
Get 8 byte of Device Descriptor
ctrl xfer 0x20009f58 cb 0x1009b471 << TinyUSB control transfer for getting device desc
setup send 06
pio SETUP error 202 01 a5 delay 0  << Errors due to not matching SYNC and ACK
pio error
Enumeration attempt 1 failed 1 << TinyUSB fails
ctrl xfer 0x20009f58 cb 0x1009b471 << Tries again
setup send 06
pio SETUP ok 33e 80 d2 << Captures ACK correctly
ctrl setup 00 00
[1:0] Control data len 8
Set Address = 1 << Set address works ok too
ctrl xfer 0x0 cb 0x1009b471
setup send 05
pio SETUP ok 3ed 80 d2

This causes issues when using a device running TinyUSB because it can't handle two SETUP packets in a row. It (currently) expects to finish the first control transaction before the second setup packet.

usb host stops working after some seconds

Describe the bug you encountered:

capture_hid_report

I connected a mouse to the gpio usb host, it works as expected during few seconds, then it just stop working until i restart the pico, then it works during few seconds... It looks like something breaks after few seconds of operation. How can I debug that?

What did you expect to happen instead?

capture_hid_report should work permanently.

What actually happened in your case?

capture_hid_report works only for a few seconds after power on. Then it just stop working.

...

Additional information

connected as: #7

Output:

4e53:5407 EP 0x81:      01 00 fd df 00 00 
4e53:5407 EP 0x81:      01 00 ff ef 00 00 
4e53:5407 EP 0x81:      01 00 00 f0 00 00 
4e53:5407 EP 0x81:      01 00 00 f0 00 00 
4e53:5407 EP 0x81:      01 00 01 e0 ff 00 
4e53:5407 EP 0x81:      01 00 01 f0 ff 00 
4e53:5407 EP 0x81:      01 00 02 f0 ff 00 
4e53:5407 EP 0x81:      01 00 02 e0 ff 00 
4e53:5407 EP 0x81:      01 00 02 e0 ff 00 
4e53:5407 EP 0x81:      01 00 02 d0 ff 00 
4e53:5407 EP 0x81:      01 00 00 d0 ff 00 
4e53:5407 EP 0x81:      01 00 ff 9f ff 00 

And after few seconds, it just stop working.

Writing to flash

I'm making some progress with the library and need a little help again. I'm trying to persist some config information in flash while listening for input reports on a USB port.

The flash writing code looks something like this:

    uint32_t ints = save_and_disable_interrupts();
    flash_range_erase(CONFIG_OFFSET_IN_FLASH, FLASH_SECTOR_SIZE);
    flash_range_program(CONFIG_OFFSET_IN_FLASH, buffer, FLASH_PAGE_SIZE);
    restore_interrupts(ints);

I noticed that this breaks the code that's receiving data via USB. It's possibly related to the fact that the other core is executing code from flash. I've tried using the multicore locking mechanism described here:

https://raspberrypi.github.io/pico-sdk-doxygen/group__multicore__lockout.html

But it doesn't seem to help.

Any idea on how I could do this?

💡[FEATURE] Combo device support

There is support for hub and it is possible to add additional port on host side. Is it also possible to support combo devices on device side: example simultaneous keyboard and mouse?


🪲[BUG] First Packet in the Data Stage of a Control Transfer is Data0

I was using the PICO as a USB Host for a radio, using the built-in USB connector. I switched to the PIO implementation and the device no longer worked.

Setup of the radio requires Control Transfers with data stages.

Using a Logic Analyzer I compared the output from the PICO when using the built-in connector and PIO. The data stage of the control transfer starts with Data1 on the working built-in USB connector.
The data stage of the control transfer starts with Data0 when using PIO.

https://www.keil.com/pack/doc/mw/USB/html/_u_s_b__control__transfers.html
states: "The DATA stage is optional. If present, it always starts with a transaction containing a DATA1 packet. Then, the transaction type alternates between DATA0 and DATA1 until all required data have been transferred."

The radio works and the first packet of the data stage is set correctly after I set ep_data_id to 1 instead of 0 here: https://github.com/sekigon-gonnoc/Pico-PIO-USB/blob/main/src/pio_usb_host.c#L515

I have a branch I can use to make a pull request if that looks like a good solution.
Edit: I just created a pull request. https://github.com/sekigon-gonnoc/Pico-PIO-USB/pull/56

Thanks.

🪲[BUG] Pico W CYW43 and Pico-PIO-USB host code conflict

I am running a MSC Host Demo with Pico-PIO-USB host a Pico W board. Right now, my code uses the CYW43 module just to blink an LED. The code works just fine on a regular Pico board with Pico-PIO-USB. The code also works fine on Pico W board if I use the native USB hardware for the USB host. However, if I build the program to run on a Pico W board with a Pico-PIO-USB host, the program fails to work properly in various ways.
...

I expected the LED on the Pico W board to blink periodically to show the main loop is running and I expected the Pioc-PIO-USB host to properly enumerate a connected flash drive.

...

What I saw instead was: The CYW43 blinks the LED fine until I plug in a USB flash drive. Then the console spits error messages related to CYW43 initialization.

I have found one issue that prevents the stream of error messages, but does not completely fix the problem.

...

Additional information
My program initializes the CYW43 module in core 0. The Pico-PIO-USB host code runs in core 1. The pico-sdk file src/rp2_common/pico_cyw43_driver.c uses a PIO program that uses one state machine and 6 instructions to communicate between the RP2040 and the CYW43 module. I am using the default configuration of Pico-PIO-USB, so the pio_usb_tx program is loaded into PIO 0 and uses state machine 0 and the receiver programs run in PIO 1. By default, the CYW43 module runs in PIO 1, but there are no available instructions there, so I set CYW43_SPI_PIO_PREFERRED_PIO=0 to force that driver to run in PIO 0.

I noticed in pio_usb.c that there are no calls to pio_sm_claim() when state machines are assigned. That means that the call to pio_claim_unused_sm() in src/rp2_common/pico_cyw43_driver.c cannot work properly. I thought that was the only issue, so I added the following code to the end of apply_config()

  pio_sm_claim(pp->pio_usb_tx, pp->sm_tx);
  pio_sm_claim(pp->pio_usb_rx, pp->sm_rx);
  pio_sm_claim(pp->pio_usb_rx, pp->sm_eop);

Also, my code now waits until core 1 initialization is complete before it attempts to initialize the CYW43 hardware on core 1 so that the pio_sm_claim() calls have time to execute. Now instead of seeing a stream of error messages, I see the program lock up as soon as I plug in a USB drive. After some time, I see on the console

[CYW43] do_ioctl(2, 263, 16): timeout                                           
[CYW43] got unexpected packet 0

and then the LEDs start flashing again, but the flash drive does not enumerate. There must be some other conflict(s) too.

If I comment out the code that initializes the CYW43 and blinks the LED, then flash drive enumerates properly, so I can say my USB hardware works OK.

Are there any PIO operations in the Pico-PIO-USB USB TX code that might conflict with another state machine running in the same PIO?


Usage with Pico W

This is not a bug report, more of a note of how I got this working. I spent a bunch of time tracking this down, so hopefully this can help someone. The Pico W uses PIO SPI to communicate with the CYW43 chip.

From what I can tell, it needs 1sm, 6 instructions of memory, pins 24 and 29, and 2 DMA channels in 1 PIO.

I do the following things in my code, but I'm not sure which ones actually help (none of them hurt though):

  • delay WiFi initialization by 3000ms (basically let the USB fully initialize first)
  • pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
  • pio_cfg.pin_dp = 3;
  • pio_cfg.sm_tx = 3;
  • pio_cfg.sm_rx = 2;
  • pio_cfg.sm_eop = 3;
  • pio_cfg.pio_rx_num = 0;
  • pio_cfg.pio_tx_num = 1;
  • pio_cfg.tx_ch = 9;

I have WiFi on core0 and USB on core1.
Before setting the delay and some of these settings, the code just got stuck not having enough instruction space, or having dma channel conflicts. Now my code works much better (however it still has some issues I don't know whether they're related to this or not, so don't take these settings as a silver bullet).

Pin Confusion

Hello,

I am planning to use a Raspberry Pi Pico W with the Pico-PIO-USB library, an ST7735 LCD screen, and an SD card reader. I want to make sure there are no conflicts between the spi busses. AFAIK your library uses gpio 2 3 and 9 aswell?

I was wondering if you could provide me with more information on which pins the library is using or if there's a way to configure the library to use different pins.

Thank you in advance for your assistance.

Best regards,
Isaac

Mouse Data Packet Clarification

Describe the bug you encountered:

The capture_hid_report shows the following data on mouse movements:

4e53:5407 EP 0x81:      01 00 fd df 00 00 
4e53:5407 EP 0x81:      01 00 ff ef 00 00 
4e53:5407 EP 0x81:      01 00 00 f0 00 00 
4e53:5407 EP 0x81:      01 00 00 f0 00 00 
4e53:5407 EP 0x81:      01 00 01 e0 ff 00 
4e53:5407 EP 0x81:      01 00 01 f0 ff 00 
4e53:5407 EP 0x81:      01 00 02 f0 ff 00 
4e53:5407 EP 0x81:      01 00 02 e0 ff 00 
4e53:5407 EP 0x81:      01 00 02 e0 ff 00 
4e53:5407 EP 0x81:      01 00 02 d0 ff 00 
4e53:5407 EP 0x81:      01 00 00 d0 ff 00 
4e53:5407 EP 0x81:      01 00 ff 9f ff 00 
4e53:5407 EP 0x81:      01 00 fd 9f ff 00 
4e53:5407 EP 0x81:      01 00 fb 7f ff 00 
4e53:5407 EP 0x81:      01 00 fb 7f ff 00 
4e53:5407 EP 0x81:      01 00 fa 7f ff 00 
4e53:5407 EP 0x81:      01 00 fc 7f ff 00 
4e53:5407 EP 0x81:      01 00 fc 8f ff 00 
4e53:5407 EP 0x81:      01 00 fe 9f ff 00 
4e53:5407 EP 0x81:      01 00 ff bf ff 00 
4e53:5407 EP 0x81:      01 00 00 d0 ff 00 
4e53:5407 EP 0x81:      01 00 ff df ff 00 
4e53:5407 EP 0x81:      01 00 00 e0 ff 00 
4e53:5407 EP 0x81:      01 00 00 f0 ff 00 
4e53:5407 EP 0x81:      01 00 00 f0 ff 00 

As you can see, changes are only in bytes 2,3,4.

On button events:

4e53:5407 EP 0x81:      01 01 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 02 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 02 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 02 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 02 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 08 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 08 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 
4e53:5407 EP 0x81:      01 08 00 00 00 00 
4e53:5407 EP 0x81:      01 00 00 00 00 00 

... for buttons, changes are in byte 1 only
... for wheel events, changes are in byte 5 only.
... byte 0 never changes, it is always 01

What did you expect to happen instead?

I was expecting:
byte0 = Button number
byte1, byte2 = 16bit x axis
byte3, byte4 = 16bit y axis
byte5 = wheel
...

What actually happened in your case?

Am I misinterpreting the data?

Apparently the actual data looks like:

byte0 = always 01
byte1 = Button
byte2, byte3[0-3] = 12 bit X axis ?
byte3[4-7], byte4 = 12 bit Y axis ?
byte5 = wheel

Does it make sense?

🪲[BUG] device_descriptor_t member name clash

Great project. I have a small issue when using in a c++ project.

When including the headers into a c++ file the member variable "class" in device_descriptor_t struct will not compiled as "class" is a reserved word in c++.

Changing this to device_class and changing it's single use at line 1070 in pio_usb.c fixes the issue and allows the code to be used in a c++ project.

Many thanks :)

🪲[BUG] Issue Compiling

Describe the bug you encountered:
I am trying to ccompile the example program "capture_hid_report", and I kept getting this error:

Cannot find source file:
/home/pi/pico/pico-sdk/lib/tinyusb/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c
...

What did you expect to happen instead?

Command complete sucessfully so I can run make.
...
Additional information

I tried on ubuntu and Raspberry Pi desktop, both got the same error.
I also looked into the pico-sdk folders, and it seems like the folder structure has changed a bit: instead of /tinyusb/portable/raspberrypi/pio_usb/
now it's
/tinyusb/portable/raspberrypi/rp2040/


does this mean USB will use up two PIOs fully?

the existing Pico USB provides either a host mode, or device mode with 32 endpoints(or 16 two-way), which typically is enough but it is a mux-mode(can't use both host and device at the same time), so this project can make Pico act as both a host and device(one uses existing USB hw, another one uses this project), but it means I have no PIO at all left for other purposes? correct? It seems even though not all SMs are used by USB here, but all instructions memory are used up. Please let me know if I misunderstood. Thanks!

Dropped input reports

Hi,

While evaluating this project I encountered an issue with HID input reports seemingly dropped. I'm not sure it it's a problem with this library or if I'm doing something wrong.

I have a USB mouse that sends 1000 input reports per second. In the HID report there's a counter field that increases by 1 with every consecutive report. Here's what it looks like when connected directly to the computer (usbhid-dump output). Note the consecutive numbers:

002:006:000:STREAM             1645632911.827409
 00 00 00 00 00 81 23

002:006:000:STREAM             1645632911.828371
 00 00 00 00 00 82 23

002:006:000:STREAM             1645632911.829447
 00 00 00 00 00 83 23

002:006:000:STREAM             1645632911.830400
 00 00 00 00 00 84 23

002:006:000:STREAM             1645632911.831391
 00 00 00 00 00 85 23

002:006:000:STREAM             1645632911.832444
 00 00 00 00 00 86 23

But when I connect it to my Raspberry Pi Pico and run the "capture_hid_report" example, here's what I get (note that some of the numbers in the counter field are missing - they are not consecutive):

cafe:baba EP 0x81:	00 00 00 00 00 3f 0e 
cafe:baba EP 0x81:	00 00 00 00 00 43 0e 
cafe:baba EP 0x81:	00 00 00 00 00 46 0e 
cafe:baba EP 0x81:	00 00 00 00 00 4a 0e 
cafe:baba EP 0x81:	00 00 00 00 00 4e 0e 
cafe:baba EP 0x81:	00 00 00 00 00 51 0e 
cafe:baba EP 0x81:	00 00 00 00 00 55 0e 
cafe:baba EP 0x81:	00 00 00 00 00 58 0e 

It seems like I'm only getting every third or fourth input report.

Any help?

💡[FEATURE] Can someone provide a detailed description of the PIO instructions?

The rp2040 is an amazing chip and the two PIO units are powerful! However, as I try to learn the exact timing, it's hard to get it right. For example, I see this helpful image in this repo:

timing

But, it's hard to follow exactly the exact timing, because we have D+ and D- and then the inverses of them (since their pins are inverted), etc. It's also hard for me to see exactly when the bits flip exactly how that impacts the PIO instructions. I've read through the data sheet, but it doesn't totally help answer my questions such as exactly when do instructions meet certain conditions and move to the next instruction or perform a jump.

Is there anyone here that understands at least the rx_pio code enough (and has some spare time) to be able to describe in more detail the actual PIO instructions below?

A few questions I have are:

  1. Who fires the IRQ_RX_EOP interrupt?
  2. When exactly does a command like jmp pin start move to the next instruction? If the pin is high for 3.05 cycles, does the jmp program move to the next instruction at the 4th cycle? Or, since the condition is still true at the start of the 3rd cycle and first fails when checking at the start of the 4th cycle, do we have to wait for that cycle to complete and then run the next instruction at the 5th cycle? I have the same question for wait instructions.
  3. Maybe it would be easier to take one of the cases, such as only FS (Full speed) mode of USB and summarize the code from that context. Also, because we have FS and LS here and D+ and D- and they are also inverted, it is just sort of melting my brain trying to map it all out.

If someone could describe in detail what the 17 instruction edge detection program and the 15 instruction NRZI decoder are doing, it would be extremely helpful.

I think there might be many others that would also benefit from reading through a clear description.

Sorry to ask for something that seems like I should "do on my own", I've spent about 10 days looking at these 32 instructions and my (apparently) small brain is still having a problem understanding them.

If someone has the time to write up a quick summary, it would be greatly appreciated. Thanks!


.define public IRQ_RX_BS_ERR 1 ; bit stuffinc error
.define public IRQ_RX_EOP    2 ; eop detect flag
.define public IRQ_RX_START  3 ; packet start flag
.define public IRQ_DECODER   4 ; NRZI decoder trigger

.define db0 0
.define db1 1

; --[ edge detector ]---------------------------------------------------------

; USB signal edge and eop detector (17 instructions)
;            FS(12M)  LS(1.5M)
; Run at     96MHz    12MHz
; jmp_pin    D-       D+
; in_pin     D+       D-
;
; both D+ and D- pins should be input invert overridden

.program usb_edge_detector
.side_set 1

eop:
  irq wait IRQ_RX_EOP     side db0 ; TODO: who triggers this irq?
start:
  jmp pin start           side db1 ; wait for a falling edge
  irq IRQ_RX_START [1]    side db0 ; see pio_usb_device.c?

.wrap_target
pin_still_low:
  irq IRQ_DECODER [1]     side db0 ; trigger NRZI decoder

; resync on rising edge
pin_low:
  jmp pin pin_went_high   side db1
pin_went_low:
  jmp pin pin_went_high   side db1
  jmp pin pin_went_high   side db1
  jmp pin pin_went_high   side db1
  jmp pin pin_went_high   side db1
  jmp pin pin_went_high   side db1
.wrap

pin_still_high:
  mov x isr [2]           side db1
  jmp x-- eop             side db1 ; jump to eop if jmp_pin and in_pin are high because both inputs are inverted

; jump here on rising edge
pin_went_high:
  mov isr null            side db1
  in pins 1               side db0 ; capture pin to check for eop
  irq IRQ_DECODER         side db0 ; trigger NRZI decoder
  jmp pin pin_still_high  side db0
  jmp pin_went_low        side db1 ; jump to pin_went_low (not pin_low) to adjust interval of decoder trigger

.wrap

; --[ NRZI decoder ]----------------------------------------------------------

; USB NRZI data decoder (15 instructions)
;            FS(12M)  LS(1.5M)
; Run at     as fast as possible
; jmp_pin    D+       D-
;
; both D+ and D- pins should be input invert overridden
;
; NOTE: you must fill OSR by 1 and set 0 to x before runnning this program

.program usb_nrzi_decoder
.side_set 1 opt

start:
  ; set x 0 side db0

.wrap_target

set_y:
  set y 6

irq_wait:
  wait 1 irq IRQ_DECODER ; wait for edge detector
  jmp pin pin_high

pin_low:
  jmp !y flip side db0 ; ignore stuffed bit (no error)
  jmp !x K1   side db0
K2:
  ; x == 1
  in null 1
  jmp flip
K1:
  ; x == 0
  in osr 1
  jmp y-- irq_wait

pin_high:
  jmp !y flip side db1 ; ignore stuffed bit (no error)
  jmp !x J1   side db1
J2:
  ; x == 1
  in x 1
  jmp y-- irq_wait
J1:
  ; x == 0
  in null 1

flip:
  mov x ~x

.wrap

💡[FEATURE] Sample code for writing to HID device without tinyusb

Hi,

I have seen your capture_hid_report sample showing how to receive HID reports using the low-level pio_usb_get_in_data() function, without the tinyusb stack (typically done via tuh_hid_report_received_cb()).

Writing back to the device via tinyusb would be achieved via the tuh_hid_set_report() function. For instance, if the hosted device is a keyboard, turning the caps lock led on would be achieved by something like this:

static uint8_t leds = 2; 
tuh_hid_set_report(dev_addr, instance, 0, HID_REPORT_TYPE_OUTPUT, &leds, sizeof(leds));

What would be the equivalent code for writing the out report to the keyboard without tinyusb, by using the Pico-PIO-USB API? Can you point me in the right direction for which Pico-PIO-USB API function to look at? Maybe pio_usb_set_out_data?

Thank you!

[BUG] capture_hid_report fails on cheap ONN Mouse from Walmart using QT Py RP2040

UPDATE: Thanks to Dan Halbert at Adafruit, I tried testing with not just two mice, but two DIFFERENT mice and the original code worked with the other brand. So, this issue is very different now... it's that Pico-PIO-USB doesn't enumerate or support a very cheap mouse from Walmart. My gaming mouse enumerated and reported fine.

So, we could close this one and open a new issue or update this one - I'll add the new info in a separate comment and we can split if if needed. Thanks


I have wired a USB Female jack via 2x 22Ohm resistors to pins A0 and A1 of a QT Py RP2040 (GPIO29 and GPIO28) respectively. (See Image).
WIN_20220322_17_19_34_Pro

When trying the capture_hid_report example, I get errors when an optical mouse is plugged in. (See attached USB Descriptor from USBView)
opticalmouseDescr.txt
...

I expected to see HID reports printed to the USB console.
...

When run as-is, with only the config.pin_dp set to 28 instead of the default of 0, I got no terminal at all. When placed back in bootloader mode, Putty would fail with "unable to configure USB".

When I commented out the config.alarm_pool line (Line 18 of capture_hid_report) which I thought would put the interrupts in the main core, I got

Root 0 connected
Device 0 Connected
control in[timeout]
Enumeration failed(-2)

When I moved all of the processing to core0 by calling core1_main() directly from main() and moving pio_usb_host_task() to the main loop, I got:

Root 0 connected
Device 0 Connected
control in[complete]
Enumerating 093a:2510, class:0, address:1
control out[complete]
control in[timeout]
Failed to get string descriptor (Manufacture)
control in[timeout]
Failed to get string descriptor (Product)
control in[timeout]
Enumeration failed(-2)
Root 0 disconnected
Disconnect
Disconnect device 1
Root 0 connected
Device 0 Connected
control in[complete]
Enumerating 093a:2510, class:0, address:1
control out[complete]
control in[timeout]
Failed to get string descriptor (Manufacture)
control in[timeout]
Failed to get string descriptor (Product)
control in[timeout]
Enumeration failed(-2)
Root 0 disconnected
Disconnect
Disconnect device 1
Root 0 connected
Device 0 Connected

I realize that this may be my fault, but I am at a loss as to what to try next... :-/

Any ideas?


Resistors For USB Host

Does this project follow the USB Specification for the host implementation? Im having trouble understanding if it requires 15k (changed to 14.5k - 24.8k) resistors and if there something that needs to be disconnected after the device negotiates what speed its using. Or does PIO USB implement this somewhere I havent seen? There is a resistor pdf in the link below.

https://www.usb.org/sites/default/files/usb_20_20230224.zip

P.S, What are the 22ohm resistors mentioned in the README used for?

[Docs] Hub example

Would it be possible to add a short example of how to use the hub support?

Demo video too awesome

Describe the bug you encountered:
Demo video ("This is a keyboard..") is excessively awesome.
...

What did you expect to happen instead?
Expected video to show single USB device in action, something dull like a regular keyboard or mouse.
Expected it to be little over-long, have excessive introduction and talking, demonstrate less features, and not be as crisply amusing.
...

What actually happened in your case?
LOL'd, spat tea over keyb. Clean up required.

...

Additional information
In future - consider reviewing other similar product videos from around the web; perhaps lower the quality of your offerings.

My house.

💡[FEATURE] Support swapped DP/DM pins

Describe the feature you want to implement here:

I have designed a board with DM on GPIO18 and DP on GPIO19.

Pico-PIO-USB requires that DP is always first and this is hardcoded in many places. It seems possible(?) to reverse everything in the PIO code.

On the RP2040 the USB DM pin comes before USB DP pin and I copied that convention thinking it wouldn't be a problem, maybe others will make the same assumption.

Thanks for your consideration.

USB Communication problem (newbie question)

Describe the bug you encountered:
After clone, build and flash, used minicom to see, at leasts "hello!" should appear right? But there is no communication

minicom -D /dev/ttyACM0

Welcome to minicom 2.7.1

OPTIONS: I18n 
Compiled on Aug 13 2017, 15:25:34.
Port /dev/ttyACM0, 11:13:37

Press CTRL-A Z for help on special keys

control in[timeout]
Enumeration failed(-2)
Root 0 disconnected
Disconnect                                                                                                                                                                
Disconnect device 0                                                                                                                                                       
Root 0 connected                                                                                                                                                          
Device 0 Connected                                                                                                                                                        
control in[complete]                                                                                                                                                      
Enumerating 10c4:8108, class:0, address:1                                                                                                                                 
control out[complete]                                                                                                                                                     
control in[timeout]                                                                                                                                                       
Failed to get string descriptor (Manufacture)                                                                                                                             
control in[timeout]                                                                                                                                                       
Failed to get string descriptor (Product)                                                                                                                                 
control in[timeout]                                                                                                                                                       
Enumeration failed(-2)                                                                                                                                                    
Root 0 disconnected                                                                                                                                                       
Disconnect                                                                                                                                                                
Disconnect device 1                                                                                                                                                       
Root 0 connected                                                                                                                                                          
Device 0 Connected                                                                                                                                                        
control in[complete]                                                                                                                                                      
Enumerating 10c4:8108, class:0, address:1
control out[complete]
control in[complete]
control in[timeout]
Failed to get string descriptor (Manufacture)
control in[complete]
control in[timeout]
Failed to get string descriptor (Product)
control in[complete]
control in[timeout]
Enumeration failed(-2)
Root 0 disconnected
Disconnect
Disconnect device 1
Root 0 connected
Device 0 Connected
control in[complete]
Enumerating 10c4:8108, class:0, address:1
control out[complete]
control in[complete]
control in[timeout]
Failed to get string descriptor (Manufacture)
control in[timeout]
Failed to get string descriptor (Product)
control in[timeout]
Enumeration failed(-2)
Root 0 disconnected
Disconnect
Disconnect device 1
Root 0 connected
Device 0 Connected
control in[complete]
Enumerating 10c4:8108, class:0, address:1
control out[complete]
control in[timeout]
Failed to get string descriptor (Manufacture)
control in[timeout]
Failed to get string descriptor (Product)
control in[timeout]
Enumeration failed(-2)
Root 0 disconnected
Disconnect
Disconnect device 1
Root 0 connected
Device 0 Connected

What did you expect to happen instead?

I expected the connection to succeed and to see "hello!" at least.

What actually happened in your case?

No communication.

Additional information

git clone https://github.com/sekigon-gonnoc/Pico-PIO-USB.git
cd Pico-PIO-USB/example
mkdir build
cd bulild
cmake ..
make

Then copied: Pico-PIO-USB/example/build/capture_hid_report/capture_hid_report.uf2 to Pico board and Disconnect/Reconnect.

[BUG] Found an error on pio_usb_host.c

So I was playing around with that file given that I'm writing an xinput USB host implementation for the Pico, when I found a bug.

It looks like it is a typo, it is on line 851 (request_length is declared on line 849):
https://github.com/sekigon-gonnoc/Pico-PIO-USB/blob/main/src/pio_usb_host.c#L851

  uint16_t request_length =
      get_configuration_descriptor_request.length_lsb |
      (get_configuration_descriptor_request.index_msb << 8); // <- HERE, that *index_msb* should be *length_msb*

It should say:

  uint16_t request_length =
      get_configuration_descriptor_request.length_lsb |
      (get_configuration_descriptor_request.length_msb << 8);

It is a minor typo, but generates wrong information.

USB Hub causes a CONTROL_ERROR when plugged in

I noticed that when using a USB Hub with the capture_hid_report example, it would cause a CONTROL_ERROR. I found that by adding a wait of 1000us in the control_in_protocol function, it would allow the USB Hub to initialize without erroring.

//=======================================
//    src/pio_usb_host.c
//=======================================
static int __no_inline_not_in_flash_func(control_in_protocol)(
    usb_device_t *device, uint8_t *tx_data, uint16_t tx_length,
    uint8_t *rx_buffer, uint16_t request_length) {
  int res = 0;

  control_pipe_t *pipe = &device->control_pipe;

  busy_wait_us(1000); // Adding this line fixes the usb hub

I am using USB Female Module and a USB High Speed Hub with 4 Ports

Question: QMK USB-USB converter possible?

Came to know of this via HN.

So question around re-purposing this for a usb-usb converter (the hasu converter type which are mostly pro-micro + usb A shield are pretty limiting). Is that a possibility?

  1. basically hook up a type A port to the PIO Usb
  2. Pi Pico connects via micro usb as usual and reports as a HID device
  3. QMK converter fw... reads the PIO USB and reports key strokes to host

I suppose it all depends on what interface the PIO USB exposes to the uC - if it can be like a 'virtual SPI' (no idea if that's even a thing - limited hw/uc knowledge) then the QMK fw could be probably made to work?

Anyway - great project... Amazing work!

💡[FEATURE] Simultaneous PIO Host and Device

Describe the feature you want to implement here:

I have a project that currently uses the built-in USB as device and your PIO USB library as host. If possible, I would like to use your PIO USB library as an additional device.

Is it currently possible to use your PIO library for device and host simultaneously?

If it is not currently possible, could it be possible in the future? I realize that there may be hardware constraints.

Assuming it is possible, my request is to have simultaneous PIO USB host and device.

💡[FEATURE] Please make an new arduino release

Describe the feature you want to implement here:
If possible, please make an new release and also update library.properties for Arduino. Recent PRs include host_frame_number and abort transfer is not availabe in 0.5.2 causing arduino cli to throw warnings. Although these aren't used yet, it is still nice to release to sync between latest tinyusb and pio-usb. Thank you in advance.

Arduino\libraries\Adafruit_TinyUSB_Library\src\portable\raspberrypi\pio_usb\hcd_pio_usb.c:100:10: warning: implicit declaration of function 'pio_usb_host_get_frame_number' [-Wimplicit-function-declaration]
  100 |   return pio_usb_host_get_frame_number();
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Arduino\libraries\Adafruit_TinyUSB_Library\src\portable\raspberrypi\pio_usb\hcd_pio_usb.c: In function 'hcd_edpt_abort_xfer':
Arduino\libraries\Adafruit_TinyUSB_Library\src\portable\raspberrypi\pio_usb\hcd_pio_usb.c:131:10: warning: implicit declaration of function 'pio_usb_host_endpoint_abort_transfer'; did you mean 'pio_usb_host_endpoint_transfer'? [-Wimplicit-function-declaration]
  131 |   return pio_usb_host_endpoint_abort_transfer(pio_rhport, dev_addr, ep_addr);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |          pio_usb_host_endpoint_tran

💡[FEATURE] USB Power Delivery

Hi hi,

PIO-USB is a great library, and we have been doing lots of great stuffs thanks to it. I would like to ask whether you have an plan to add support for USB Power Deliery message. The reason is I am starting to add USB PD support to tinysub stack, firstly with UCPD hardware from stm32 G4 (g0 etc ..). Though since CC is operating around 300 KB/s on single pin, and is probably simpler comparing to D+/D- pair.

It would be super helpful if we could support PD. We don't have to fully support it, just enough e.g to allow RP2040 to request higher operating VBUS e.g 12V from vastly available wall charger or power bank to power an long strip of LED or motor etc ... i.e received Source Cap and reply with Request message.

Note: PD via CC pin is kind of side channel, therefore it may also make sense if you decide to implement it in a seperate library !?

Missing dcd_pio_usb.c

When I try to run cmake .. I get this:

PICO_SDK_PATH is /home/user/pico-sdk
PICO platform is rp2040.
Build type is Release
PICO target board is pico.
Using board configuration from /home/user/pico-sdk/src/boards/include/boards/pico.h
TinyUSB available at /home/user/pico-sdk/lib/tinyusb/src/portable/raspberrypi/rp2040; enabling build support for USB.
cyw43-driver available at /home/user/pico-sdk/lib/cyw43-driver
lwIP available at /home/user/pico-sdk/lib/lwip
-- Configuring done
CMake Error at host_hid_to_device_cdc/CMakeLists.txt:2 (add_executable):
  Cannot find source file:

    /home/user/pico-sdk/lib/tinyusb/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c

  Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
  .hpp .hxx .in .txx


-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.

Quick workaround is to disable host_hid_to_device_cdc in CMakeLists.txt like this:

add_subdirectory(capture_hid_report)
add_subdirectory(usb_device)
# add_subdirectory(host_hid_to_device_cdc)

But where can an individual obtains missing files to get all examples to work?

🪲[BUG] USB Device not being recognised by host

Describe the bug you encountered:

The examples/usb_device example does not present as a USB device to my MacOS host.

What did you expect to happen instead?

I expected it to be enumerated, show up as cafe:0000 in lsusb, and cause a mouse wiggle every 0.5s.

What actually happened in your case?

No device is enumerated. With my logic analyser I can see a regular SOF frames every 1 millisecond, and a reset every second - suggesting the circuit is physically valid, and the firmware is running on device.

image

https://github.com/sekigon-gonnoc/Pico-PIO-USB/blob/main/src/pio_usb_device.c#L368

The reset suggests to me the Pico does not have an accurate reading of the GPIO pins as it is reading the pair as low, but oddly is able to drive them to reset the connection.

Additional information

I have the Pico wired up as:
GPIO 0 -> 1.5 kΩ pull up to 3.3v -> D+
GPIO 1 -> D-
Pico GND -> USB GND

I have tried this with another Pico just to sanity check, as well as confirmed the version of Pico-SDK is contemporary with the examples commit date.

Any guidance you can provide to debug further would be appreciated.


💡[FEATURE] MIDI support

So few MCUs offer USB MIDI HOST support, it would be AMAZING to have RPI2040 support for that. If possible, could you add an example that shows how to implement this?
Thanks!!!

usb 2.0 device mode

I'd like to have higher speed above usb1.1 when pico is used as a usb device, is this possible, or Pico can not sustain anything above usb1.1 speed? I don't really need usb host mode, anything above 12Mbps will be good.

[bug?] usb 1.0 Low-Speed device detection in host mode / lsusb.ino

hi and thanks for this awesome library 👍

I'm the maintainer of ESP32-USB-Soft-Host.
This library does not use tinyUSB, nor does it use the builtin usb chip that comes with some variants of the esp32 (s2/s3), also it is limited to a few set of pins.
It is similar to Pico-PIO-USB in a sense it's also a wrapper around a third party usb library, only it is limited to usb 1.0 Low-Speed (1.5Mbps).

I was very happy to find that Pico-PIO-USB works out of the box and supports usb 1.1, so I expanded the device_info example sketch to match the precision of linux lsusb -v system command, and wrote down the list of successfully detected devices:

  • Akai MPK Mini midi keyboard (hidraw/audio stream, midi stream)
  • 32GB key (mass storage)
  • sdcard adapter (smart card)
  • audio dongle (headphone+mic)
  • cp21xx/ch34x uart from random devices (pico, esp32, arduino, esp8266)
  • yubico key (hid)
  • android phone (imaging+mass storage)

However none of the usb 1.0 Low-speed device I tried got detected.

This log shows a low cost keyboard from pimoroni as seen from linux, works with ESP32-USB-Soft-Host but can't get detected by Pico-PIO-USB:

april 30 10:58:35 kernel: usb 1-3.4.3: new low-speed USB device number 97 using xhci_hcd
april 30 10:58:36 kernel: usb 1-3.4.3: new low-speed USB device number 98 using xhci_hcd
april 30 10:58:37 kernel: usb 1-3.4.3: New USB device found, idVendor=1c4f, idProduct=0002, bcdDevice= 1.10
april 30 10:58:37 kernel: usb 1-3.4.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
april 30 10:58:37 kernel: usb 1-3.4.3: Product: USB Keyboard
april 30 10:58:37 kernel: usb 1-3.4.3: Manufacturer: SIGMACHIP
april 30 10:58:37 kernel: input: SIGMACHIP USB Keyboard as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.3/1-3.4.3:1.0/0003:1C4F:0002.001D/input/input21
april 30 10:58:37 kernel: hid-generic 0003:1C4F:0002.001D: input,hidraw6: USB HID v1.10 Keyboard [SIGMACHIP USB Keyboard] on usb-0000:00:14.0-3.4.3/input0
april 30 10:58:37 kernel: input: SIGMACHIP USB Keyboard Consumer Control as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.3/1-3.4.3:1.1/0003:1C4F:0002.001E/input/input22
april 30 10:58:37 mtp-probe[245579]: checking bus 1, device 98: "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.3"
april 30 10:58:37 mtp-probe[245579]: bus: 1, device: 98 was not an MTP device
april 30 10:58:37 kernel: input: SIGMACHIP USB Keyboard System Control as /devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3.4/1-3.4.3/1-3.4.3:1.1/0003:1C4F:0002.001E/input/input23
april 30 10:58:37 kernel: hid-generic 0003:1C4F:0002.001E: input,hidraw7: USB HID v1.10 Device [SIGMACHIP USB Keyboard] on usb-0000:00:14.0-3.4.3/input1

Is this behaviour by design (e.g. tinyUSB can't do usb 1.0 and 1.1 simultaneously), unexpected, or just unimplemented?

💡[FEATURE] Dedicated Controller API

Describe the feature you want to implement here:

First of all, thank you for this brilliant project. I have never worked with an software (bit-banging) controller that works as great as yours. I am sure lots of others will find this project helpful as well since it literally add free usb ports to pico mcu.

I am trying to add support for pico-usb as software controller to TinyUSB project, so that user can let's say have native usb for device, and pico-usb for host concurrently (or vice versa) while running in a single TinyUSB stack. It is a bit hacky at the moment but runs well in host mode as proof of concept, and is able to enumerate and get report my hid device. If you are interested in testing it out: cdc_msc_hid. I do have to temporarily remove some static of pico_usb.c so that tinyusb could extern and update the internal struct

https://github.com/hathach/Pico-PIO-USB/blob/92268187f3b0490a43d139ed2cb598b06258011f/pio_usb.c#L66-L69

After working on the port, I realize that both TinyUSB and pico-usb have host/device stack which handles anything above transaction-level e.g enumeration, class driver etc... This makes porting and maintaining a bit difficult and could potentially waste ram/rom for having same thing twice. I have spent more time to go through pio_usb.c and quite positive that we could separate controller (sub-transaction) and protocol stack. Though I am not sure if you are willing to do so.

TLDR, are you interested in separating controller to has its own API ? Which can be used by either TinyUSB (optional config) or your own driver (default config). You already did a great job with most of the abstraction, we only need to move them to a new file with a clear API with some hardware register style and/or callback e.g pio_usb_endpoint_irqhandle() when an transfer is complete etc... We could work out on the detail later. If you agree I will try my best to make an (draft) PR then you could review and shape the API to your liking or if you already have in your mind, that would be great to start with. The cons would be a bit of overhead is introduced, but I doubt that it is noticeable. Let me know what you think.

@tannewt @ladyada

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.