Skip to content

allow external construction of EUsbWire{Tx,Rx} by providing new functions#147

Open
hvraven wants to merge 1 commit into
jamesmunns:mainfrom
hvraven:eusbwirexx_new
Open

allow external construction of EUsbWire{Tx,Rx} by providing new functions#147
hvraven wants to merge 1 commit into
jamesmunns:mainfrom
hvraven:eusbwirexx_new

Conversation

@hvraven
Copy link
Copy Markdown
Contributor

@hvraven hvraven commented Nov 20, 2025

In my setup I would like to attach two more endpoints to the USB interface for another communication stream. The probably not best, but reasonably easy, way I implemented this, is by creating a custom copy of the init_without_build function, setting up the interfaces myself and wrapping them in the corresponding wires.
To allow for this, it is necessary to allow for external construction of EUsbWireTx and EUsbWireRx. I introduced new() functions for them, and changed the existing code to is those instead of direct initialisation.

@dingari
Copy link
Copy Markdown
Collaborator

dingari commented May 15, 2026

Thanks for the PR!

However, based on your setup I feel like you'd rather want another function/interface for your custom communication stream. So rather than using WireStorage::init(...) you'd use init_without_build(...).

// Initialize the postcard-rpc interface without building the USB device
let (mut builder, tx_impl, rx_impl) = STORAGE.init_without_build(
    driver,
    config,
    pbufs.tx_buf.as_mut_slice(),
    USB_FS_MAX_PACKET_SIZE,
);

// Set up another function/interface for the other 
// This is just a reference implementation copy from the postcard-rpc server source.
// You might want to tweak the class/protocol, but for your use case I think it should be fine.
let mut function = builder.function(0xFF, 0, 0);
let mut interface = function.interface();
let mut alt = interface.alt_setting(0xFF, 0, 0, None);
let ep_out = alt.endpoint_bulk_out(None, USB_FS_MAX_PACKET_SIZE);
let ep_in = alt.endpoint_bulk_in(None, USB_FS_MAX_PACKET_SIZE);
drop(function);

// Then use `ep_in/ep_out` in your code...

// Then build the USB device
let device = builder.build();

This separates prpc from any other comms you might do over USB. On the host side you'd then just need to claim the correct interface for prpc and your custom interface. Does this make sense?

@hvraven
Copy link
Copy Markdown
Contributor Author

hvraven commented May 15, 2026

This was my initial approach, but the problem is, that this creates a new USB interface due to the second call to function.interface(). This results in a different USB device layout. I wanted to avoid this, as this significantly complicates the drive handling (at least for Windows).
If the function builder would have an option to re-open an interface this would work, but I couldn't find one.

@dingari
Copy link
Copy Markdown
Collaborator

dingari commented May 15, 2026

Oh I see - I think I misunderstood your initiali intention!

So you essentially just want to use EUsbWireTx/Rx as framed USB transport alongside prpc in your application code? I don't think that's unreasonable.

Would it help if init_wihtout_build returned (Builder, Interface) to the caller instead (or maybe you'd need the alt to tack your EPs on top - so maybe the way you suggest is simpler).

@dingari
Copy link
Copy Markdown
Collaborator

dingari commented May 15, 2026

BTW - I think the CI will be happy once you rebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants