-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More flexible USB setup flow #16
More flexible USB setup flow #16
Conversation
This commit adds a way for users to handle custom USB descriptor requests by adding a new Device struct field called `DescriptorSetup', just like the `Setup' field. A new field called `Conditional' has been added to the Device type. This field let the user decide whether a SetupData request should be handled by usb.doSetup() or by other logic defined in `Conditional' function logic. Both functions are optional, and their presence doesn't impact the logic currently implemented in Tamago's USB stack.
I think the We already do advertise I think we should simply have Device.GetDescriptor for optional class-specific descriptors, to reflect the same naming scheme. By doing so would there really be a need to override the existing functions? Rather than keeping custom ones as If a total override is needed wouldn't a simple boolean on device be better? We could export getDescriptor and doSetup as Descriptor and Setup to facilitate the override with a single boolean for both (so that the app can then re-use them). The boolean could be named |
On second thought maybe my naming scheme isn't the the best - a solution like the one you proposed surely looks cleaner. A thing like: // SetupFunction represents the function to process class-specific setup
// requests.
type SetupFunction func(setup *SetupData) (in []byte, err error)
// Device is a collection of USB device descriptors and host driven settings
// to represent a USB device.
type Device struct {
Descriptor *DeviceDescriptor
Qualifier *DeviceQualifierDescriptor
Configurations []*ConfigurationDescriptor
Strings [][]byte
// Host requested settings
ConfigurationValue uint8
AlternateSetting uint8
// Optional class-specific setup handler
Setup SetupFunction
CustomDescriptors SetupFunction
ExternalSetup bool
} where
If you're okay with this I can implement those changes on this PR. |
Given that I favor a minimal approach, for the sake of clarity, I propose the following (which goes somewhat in line to what you proposed originally but makes it even simpler):
I hope this can speak for itself: func (hw *USB) doSetup(dev *Device, setup *SetupData) (err error) {
if setup == nil {
return
}
if dev.Setup != nil {
in, done, err := dev.Setup(setup)
if err != nil {
hw.stall(0, IN)
} else if len(in) != 0 {
err = hw.tx(0, false, in)
} else {
err = hw.ack(0)
}
if done {
return
}
}
...
default:
hw.stall(0, IN)
return fmt.Errorf("unsupported request code: %#x", setup.Request)
} Does this make sense? This way I think we allow for maximum freedom and least code changes (we don't add functions or booleans and we very slightly change the behaviour of |
Makes sense.
What about Your solution could work for that too. |
There is no need for |
Instead of relying on extra functions for descriptor handling, delegate more to device.Setup and by calling it earlier. Let device.Setup hijack - completely or partially - USB.doSetup() execution flow.
Also, use := for dev.Setup() calls
This PR adds a way for users to handle custom USB descriptor
requests by adding a new Device struct field called
DescriptorSetup
,just like the
Setup
field.A new field called
Conditional
has been added to the Device type.This field let the user decide whether a SetupData request should be handled
by
usb.doSetup()
or by other logic defined inConditiona
function logic.Both functions are optional, and their presence doesn't impact the logic
currently implemented in Tamago's USB stack.