Skip to content

Add unknown interface descriptors to Extra #127

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

juaoose
Copy link
Contributor

@juaoose juaoose commented May 16, 2024

Include the extra interface descriptors that libusb includes.

interface.go Outdated
@@ -51,6 +51,8 @@ type InterfaceSetting struct {
// Endpoints enumerates the endpoints available on this interface with
// this alternate setting.
Endpoints map[EndpointAddress]EndpointDesc
// Unknown interface descriptors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is sufficient.

First, the "extras" can be encountered in other types of descriptors, not just interface descriptors: config and endpoint descriptors also have the extra field. Why limit to interface only?

Second, I don't think this trivial format of []byte is a good one for this library and the most useful one for the user. The descriptors stored in libusb's extras are still valid descriptors, just of unknown/unsupported type. If you want to make them available to the users, I tink a []RawDescriptor would be a minimum:

 type RawDescriptor {
  Type DescriptorType
  Data []byte
}

Third, I expect the documentation to explain more clearly to the user what this data is and how it can be used. Just saying "unknown descriptors" and "extra" is meaningless, unless you know exactly what libusb does underneath. Explaining which types of descriptors will be stored here and how they can be processed would be better. Perhaps the field should be called "UnsupportedDescriptors"?

Copy link
Contributor Author

@juaoose juaoose May 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we were to use the RawDescriptor, should we include the original []byte in Data? Since descriptors change a bit by parent type (interface has a subtype where endpoint doesnt), plus that way you can potentially just pass Data to a specific encoding.BinaryUnmarshaler (I updated the implementation a bit to reflect some of the comments)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have an example of a struct that would implement the unmarshaler? I think you could pass the data either way, if the marshaler expects the payload of the descriptor rather than the header. And presumably the type that does the unmarshaling is already a type for a specific descriptor type.

Ultimately it could be either way, but it affects how the code that depends on RawDescriptor needs to behave. If you have an example of a subsequent change that handles specific descriptor types, we could take a look together.

Also if you intend to write implementations around specific standard (but not supported by libusb) descriptor types, we could do that in gousb directly rather than a separate package?

DescriptorTypeConfig DescriptorType = C.LIBUSB_DT_CONFIG
DescriptorTypeString DescriptorType = C.LIBUSB_DT_STRING
DescriptorTypeInterface DescriptorType = C.LIBUSB_DT_INTERFACE
DescriptorTypeCSInterface DescriptorType = 0x24
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about CSEndpoint?

also add a comment to specify where the value was sourced from. (in this case I assume this is CDC spec v1.1/1.2?), since this descriptor type is not a part of the USB spec as such.

@@ -35,6 +35,11 @@ func (i InterfaceDesc) String() string {
return fmt.Sprintf("Interface %d (%d alternate settings)", i.Number, len(i.AltSettings))
}

type RawDescriptor struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document the type. In particular whether the header of the descriptor (type+length) is a part of the data is an important information here.

interface.go Outdated
@@ -51,6 +51,8 @@ type InterfaceSetting struct {
// Endpoints enumerates the endpoints available on this interface with
// this alternate setting.
Endpoints map[EndpointAddress]EndpointDesc
// Unknown interface descriptors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have an example of a struct that would implement the unmarshaler? I think you could pass the data either way, if the marshaler expects the payload of the descriptor rather than the header. And presumably the type that does the unmarshaling is already a type for a specific descriptor type.

Ultimately it could be either way, but it affects how the code that depends on RawDescriptor needs to behave. If you have an example of a subsequent change that handles specific descriptor types, we could take a look together.

Also if you intend to write implementations around specific standard (but not supported by libusb) descriptor types, we could do that in gousb directly rather than a separate package?

Comment on lines +305 to +317
var extraDescriptors []*RawDescriptor
extra := C.GoBytes(unsafe.Pointer(alt.extra), alt.extra_length)
for i := 0; i != len(extra); i += int(extra[i]) {
block := extra[i : i+int(extra[i])]
bType := DescriptorType(block[1])

extraDescriptors = append(extraDescriptors,
&RawDescriptor{
Type: bType,
Data: block},
)
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract to a helper function, since we're going to use that on interfaces as well as endpoints and configs.

block := extra[i : i+int(extra[i])]
bType := DescriptorType(block[1])

extraDescriptors = append(extraDescriptors,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

join the line for append (i.e. the &RawDescriptor literal starts in the same line)

extraDescriptors = append(extraDescriptors,
&RawDescriptor{
Type: bType,
Data: block},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closing curly brace on the next line, together with closing parenthesis

@zagrodzki zagrodzki mentioned this pull request Jul 22, 2024
@zagrodzki
Copy link
Collaborator

any updates?

@zagrodzki
Copy link
Collaborator

ping again. A new release will be coming out in ~2wks and it would be nice if this was included.

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