github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/usb/descriptor.go (about)

     1  // USB descriptor support
     2  // https://github.com/usbarmory/tamago
     3  //
     4  // Copyright (c) WithSecure Corporation
     5  // https://foundry.withsecure.com
     6  //
     7  // Use of this source code is governed by the license
     8  // that can be found in the LICENSE file.
     9  
    10  package usb
    11  
    12  import (
    13  	"bytes"
    14  	"encoding/binary"
    15  	"errors"
    16  	"fmt"
    17  	"unicode/utf16"
    18  )
    19  
    20  // Standard USB descriptor sizes
    21  const (
    22  	DEVICE_LENGTH                = 18
    23  	CONFIGURATION_LENGTH         = 9
    24  	INTERFACE_ASSOCIATION_LENGTH = 8
    25  	INTERFACE_LENGTH             = 9
    26  	ENDPOINT_LENGTH              = 7
    27  	DEVICE_QUALIFIER_LENGTH      = 10
    28  )
    29  
    30  // DeviceDescriptor implements
    31  // p290, Table 9-8. Standard Device Descriptor, USB2.0.
    32  type DeviceDescriptor struct {
    33  	Length            uint8
    34  	DescriptorType    uint8
    35  	bcdUSB            uint16
    36  	DeviceClass       uint8
    37  	DeviceSubClass    uint8
    38  	DeviceProtocol    uint8
    39  	MaxPacketSize     uint8
    40  	VendorId          uint16
    41  	ProductId         uint16
    42  	Device            uint16
    43  	Manufacturer      uint8
    44  	Product           uint8
    45  	SerialNumber      uint8
    46  	NumConfigurations uint8
    47  }
    48  
    49  // SetDefaults initializes default values for the USB device descriptor.
    50  func (d *DeviceDescriptor) SetDefaults() {
    51  	d.Length = DEVICE_LENGTH
    52  	d.DescriptorType = DEVICE
    53  	// USB 2.0
    54  	d.bcdUSB = 0x0200
    55  	// maximum packet size for EP0
    56  	d.MaxPacketSize = 64
    57  	// http://pid.codes/1209/2702/
    58  	d.VendorId = 0x1209
    59  	d.ProductId = 0x2702
    60  }
    61  
    62  // Bytes converts the descriptor structure to byte array format.
    63  func (d *DeviceDescriptor) Bytes() []byte {
    64  	buf := new(bytes.Buffer)
    65  	binary.Write(buf, binary.LittleEndian, d)
    66  	return buf.Bytes()
    67  }
    68  
    69  // ConfigurationDescriptor implements
    70  // p293, Table 9-10. Standard Configuration Descriptor, USB2.0.
    71  type ConfigurationDescriptor struct {
    72  	Length             uint8
    73  	DescriptorType     uint8
    74  	TotalLength        uint16
    75  	NumInterfaces      uint8
    76  	ConfigurationValue uint8
    77  	Configuration      uint8
    78  	Attributes         uint8
    79  	MaxPower           uint8
    80  
    81  	Interfaces []*InterfaceDescriptor
    82  }
    83  
    84  // SetDefaults initializes default values for the USB configuration descriptor.
    85  func (d *ConfigurationDescriptor) SetDefaults() {
    86  	d.Length = CONFIGURATION_LENGTH
    87  	d.DescriptorType = CONFIGURATION
    88  	d.ConfigurationValue = 1
    89  	// Bus-powered
    90  	d.Attributes = 0x80
    91  	// 500 mA
    92  	d.MaxPower = 250
    93  }
    94  
    95  // AddInterface adds an Interface Descriptor to a configuration, updating the
    96  // interface number and Configuration Descriptor interface count accordingly.
    97  func (d *ConfigurationDescriptor) AddInterface(iface *InterfaceDescriptor) {
    98  	if iface.AlternateSetting == 0 {
    99  		iface.InterfaceNumber = d.NumInterfaces
   100  		d.NumInterfaces += 1
   101  	} else if d.NumInterfaces > 0 {
   102  		iface.InterfaceNumber = d.NumInterfaces - 1
   103  	}
   104  
   105  	d.Interfaces = append(d.Interfaces, iface)
   106  }
   107  
   108  // Bytes converts the descriptor structure to byte array format.
   109  func (d *ConfigurationDescriptor) Bytes() []byte {
   110  	buf := new(bytes.Buffer)
   111  
   112  	binary.Write(buf, binary.LittleEndian, d.Length)
   113  	binary.Write(buf, binary.LittleEndian, d.DescriptorType)
   114  	binary.Write(buf, binary.LittleEndian, d.TotalLength)
   115  	binary.Write(buf, binary.LittleEndian, d.NumInterfaces)
   116  	binary.Write(buf, binary.LittleEndian, d.ConfigurationValue)
   117  	binary.Write(buf, binary.LittleEndian, d.Configuration)
   118  	binary.Write(buf, binary.LittleEndian, d.Attributes)
   119  	binary.Write(buf, binary.LittleEndian, d.MaxPower)
   120  
   121  	return buf.Bytes()
   122  }
   123  
   124  // InterfaceAssociationDescriptor implements
   125  // p4, Table 9-Z. Interface Association Descriptors, USB2.0 (ECN).
   126  type InterfaceAssociationDescriptor struct {
   127  	Length           uint8
   128  	DescriptorType   uint8
   129  	FirstInterface   uint8
   130  	InterfaceCount   uint8
   131  	FunctionClass    uint8
   132  	FunctionSubClass uint8
   133  	FunctionProtocol uint8
   134  	Function         uint8
   135  }
   136  
   137  // SetDefaults initializes default values for the USB interface descriptor.
   138  func (d *InterfaceAssociationDescriptor) SetDefaults() {
   139  	d.Length = INTERFACE_ASSOCIATION_LENGTH
   140  	d.DescriptorType = INTERFACE_ASSOCIATION
   141  }
   142  
   143  // Bytes converts the descriptor structure to byte array format.
   144  func (d *InterfaceAssociationDescriptor) Bytes() []byte {
   145  	buf := new(bytes.Buffer)
   146  	binary.Write(buf, binary.LittleEndian, d)
   147  	return buf.Bytes()
   148  }
   149  
   150  // InterfaceDescriptor implements
   151  // p296, Table 9-12. Standard Interface Descriptor, USB2.0.
   152  type InterfaceDescriptor struct {
   153  	IAD *InterfaceAssociationDescriptor
   154  
   155  	Length            uint8
   156  	DescriptorType    uint8
   157  	InterfaceNumber   uint8
   158  	AlternateSetting  uint8
   159  	NumEndpoints      uint8
   160  	InterfaceClass    uint8
   161  	InterfaceSubClass uint8
   162  	InterfaceProtocol uint8
   163  	Interface         uint8
   164  
   165  	Endpoints        []*EndpointDescriptor
   166  	ClassDescriptors [][]byte
   167  }
   168  
   169  // SetDefaults initializes default values for the USB interface descriptor.
   170  func (d *InterfaceDescriptor) SetDefaults() {
   171  	d.Length = INTERFACE_LENGTH
   172  	d.DescriptorType = INTERFACE
   173  	d.NumEndpoints = 1
   174  }
   175  
   176  // Bytes converts the descriptor structure to byte array format,
   177  func (d *InterfaceDescriptor) Bytes() []byte {
   178  	buf := new(bytes.Buffer)
   179  
   180  	// Interface Association Descriptor for multi-function device support.
   181  	if d.IAD != nil {
   182  		buf = bytes.NewBuffer(d.IAD.Bytes())
   183  	}
   184  
   185  	binary.Write(buf, binary.LittleEndian, d.Length)
   186  	binary.Write(buf, binary.LittleEndian, d.DescriptorType)
   187  	binary.Write(buf, binary.LittleEndian, d.InterfaceNumber)
   188  	binary.Write(buf, binary.LittleEndian, d.AlternateSetting)
   189  	binary.Write(buf, binary.LittleEndian, d.NumEndpoints)
   190  	binary.Write(buf, binary.LittleEndian, d.InterfaceClass)
   191  	binary.Write(buf, binary.LittleEndian, d.InterfaceSubClass)
   192  	binary.Write(buf, binary.LittleEndian, d.InterfaceProtocol)
   193  	binary.Write(buf, binary.LittleEndian, d.Interface)
   194  
   195  	// add class descriptors
   196  	for _, classDesc := range d.ClassDescriptors {
   197  		buf.Write(classDesc)
   198  	}
   199  
   200  	return buf.Bytes()
   201  }
   202  
   203  // EndpointFunction represents the function to process either IN or OUT
   204  // transfers, depending on the endpoint configuration.
   205  //
   206  // On OUT endpoints the function is expected to receive data from the host in
   207  // the input buffer. The expected size, or a reserved DMA buffer (see
   208  // `dma.Reserve`), for the next OUT transfer can be passed as a result buffer,
   209  // otherwise a short or single packet is assumed. In case a reserved DMA buffer
   210  // is returned the next OUT transfer `buf` argument represents a slice of it,
   211  // care must be taken not to use such slice (without a copy) after the reserved
   212  // buffer is released.
   213  //
   214  // On IN endpoints the function is expected to return data, or reserved and
   215  // filled DMA buffer, for transmission to the host, such data is used to fill
   216  // the transmission queue in advance, to respond to IN requests. The function
   217  // is invoked by the EndpointHandler to fill the buffer as needed.
   218  type EndpointFunction func(buf []byte, lastErr error) (res []byte, err error)
   219  
   220  // EndpointDescriptor implements
   221  // p297, Table 9-13. Standard Endpoint Descriptor, USB2.0.
   222  type EndpointDescriptor struct {
   223  	Length          uint8
   224  	DescriptorType  uint8
   225  	EndpointAddress uint8
   226  	Attributes      uint8
   227  	MaxPacketSize   uint16
   228  	Interval        uint8
   229  
   230  	// Automatic Zero Length Termination
   231  	Zero bool
   232  
   233  	Function EndpointFunction
   234  }
   235  
   236  // SetDefaults initializes default values for the USB endpoint descriptor.
   237  func (d *EndpointDescriptor) SetDefaults() {
   238  	d.Length = ENDPOINT_LENGTH
   239  	d.DescriptorType = ENDPOINT
   240  	// EP1 IN
   241  	d.EndpointAddress = 0x81
   242  	// maximum packet size for EP1+ (high speed)
   243  	d.MaxPacketSize = 512
   244  	// most applications require Zero Length Termination
   245  	d.Zero = true
   246  }
   247  
   248  // Number returns the endpoint number.
   249  func (d *EndpointDescriptor) Number() int {
   250  	return int(d.EndpointAddress & 0b1111)
   251  }
   252  
   253  // Direction returns the endpoint direction.
   254  func (d *EndpointDescriptor) Direction() int {
   255  	return int(d.EndpointAddress&0b10000000) / 0b10000000
   256  }
   257  
   258  // TransferType returns the endpoint transfer type.
   259  func (d *EndpointDescriptor) TransferType() int {
   260  	return int(d.Attributes & 0b11)
   261  }
   262  
   263  // Bytes converts the descriptor structure to byte array format.
   264  func (d *EndpointDescriptor) Bytes() []byte {
   265  	buf := new(bytes.Buffer)
   266  
   267  	binary.Write(buf, binary.LittleEndian, d.Length)
   268  	binary.Write(buf, binary.LittleEndian, d.DescriptorType)
   269  	binary.Write(buf, binary.LittleEndian, d.EndpointAddress)
   270  	binary.Write(buf, binary.LittleEndian, d.Attributes)
   271  	binary.Write(buf, binary.LittleEndian, d.MaxPacketSize)
   272  	binary.Write(buf, binary.LittleEndian, d.Interval)
   273  
   274  	return buf.Bytes()
   275  }
   276  
   277  // StringDescriptor implements
   278  // p273, 9.6.7 String, USB2.0.
   279  type StringDescriptor struct {
   280  	Length         uint8
   281  	DescriptorType uint8
   282  }
   283  
   284  // SetDefaults initializes default values for the USB string descriptor.
   285  func (d *StringDescriptor) SetDefaults() {
   286  	d.Length = 2
   287  	d.DescriptorType = STRING
   288  }
   289  
   290  // Bytes converts the descriptor structure to byte array format.
   291  func (d *StringDescriptor) Bytes() []byte {
   292  	buf := new(bytes.Buffer)
   293  
   294  	binary.Write(buf, binary.LittleEndian, d.Length)
   295  	binary.Write(buf, binary.LittleEndian, d.DescriptorType)
   296  
   297  	return buf.Bytes()
   298  }
   299  
   300  // DeviceQualifierDescriptor implements
   301  // p292, 9.6.2 Device_Qualifier, USB2.0.
   302  type DeviceQualifierDescriptor struct {
   303  	Length            uint8
   304  	DescriptorType    uint8
   305  	bcdUSB            uint16
   306  	DeviceClass       uint8
   307  	DeviceSubClass    uint8
   308  	DeviceProtocol    uint8
   309  	MaxPacketSize     uint8
   310  	NumConfigurations uint8
   311  	Reserved          uint8
   312  }
   313  
   314  // SetDefaults initializes default values for the USB device qualifier
   315  // descriptor.
   316  func (d *DeviceQualifierDescriptor) SetDefaults() {
   317  	d.Length = DEVICE_QUALIFIER_LENGTH
   318  	d.DescriptorType = DEVICE_QUALIFIER
   319  	// USB 2.0
   320  	d.bcdUSB = 0x0200
   321  	// maximum packet size for EP0
   322  	d.MaxPacketSize = 64
   323  	d.NumConfigurations = 1
   324  }
   325  
   326  // Bytes converts the descriptor structure to byte array format.
   327  func (d *DeviceQualifierDescriptor) Bytes() []byte {
   328  	buf := new(bytes.Buffer)
   329  
   330  	binary.Write(buf, binary.LittleEndian, d.Length)
   331  	binary.Write(buf, binary.LittleEndian, d.DescriptorType)
   332  	binary.Write(buf, binary.LittleEndian, d.bcdUSB)
   333  	binary.Write(buf, binary.LittleEndian, d.DeviceClass)
   334  	binary.Write(buf, binary.LittleEndian, d.DeviceSubClass)
   335  	binary.Write(buf, binary.LittleEndian, d.DeviceProtocol)
   336  	binary.Write(buf, binary.LittleEndian, d.MaxPacketSize)
   337  	binary.Write(buf, binary.LittleEndian, d.NumConfigurations)
   338  	binary.Write(buf, binary.LittleEndian, d.Reserved)
   339  
   340  	return buf.Bytes()
   341  }
   342  
   343  // SetupFunction represents the function to process class-specific setup
   344  // requests.
   345  //
   346  // The function is invoked before standard setup handlers and is expected to
   347  // return an `in` buffer for transmission on IN endpoint 0, the `ack` boolean
   348  // can be used to signal whether a zero length packet should be sent (true) in
   349  // case the `in` buffer returned empty.
   350  //
   351  // A non-nil `err` results in a stall. The `done` flag can be used to signal
   352  // whether standard setup handlers should be invoked (false) or not (true)
   353  // if function returns with a non-nil error.
   354  type SetupFunction func(setup *SetupData) (in []byte, ack bool, done bool, err error)
   355  
   356  // Device is a collection of USB device descriptors and host driven settings
   357  // to represent a USB device.
   358  type Device struct {
   359  	Descriptor     *DeviceDescriptor
   360  	Qualifier      *DeviceQualifierDescriptor
   361  	Configurations []*ConfigurationDescriptor
   362  	Strings        [][]byte
   363  
   364  	// Host requested settings
   365  	ConfigurationValue uint8
   366  	AlternateSetting   uint8
   367  
   368  	// Optional class-specific setup handler
   369  	Setup SetupFunction
   370  }
   371  
   372  func (d *Device) setStringDescriptor(s []byte, zero bool) (uint8, error) {
   373  	var buf []byte
   374  
   375  	desc := &StringDescriptor{}
   376  	desc.SetDefaults()
   377  	desc.Length += uint8(len(s))
   378  
   379  	if desc.Length > 255 {
   380  		return 0, fmt.Errorf("string descriptor size (%d) cannot exceed 255", desc.Length)
   381  	}
   382  
   383  	buf = append(buf, desc.Bytes()...)
   384  	buf = append(buf, s...)
   385  
   386  	if zero && len(d.Strings) >= 1 {
   387  		d.Strings[0] = buf
   388  	} else {
   389  		d.Strings = append(d.Strings, buf)
   390  	}
   391  
   392  	return uint8(len(d.Strings) - 1), nil
   393  }
   394  
   395  // SetLanguageCodes configures String Descriptor Zero language codes
   396  // (p273, Table 9-15. String Descriptor Zero, Specifying Languages Supported by the Device, USB2.0).
   397  func (d *Device) SetLanguageCodes(codes []uint16) (err error) {
   398  	var buf []byte
   399  
   400  	if len(codes) > 1 {
   401  		return fmt.Errorf("only a single language is currently supported")
   402  	}
   403  
   404  	for i := 0; i < len(codes); i++ {
   405  		b := make([]byte, 2)
   406  		binary.LittleEndian.PutUint16(b, codes[i])
   407  		buf = append(buf, b...)
   408  	}
   409  
   410  	_, err = d.setStringDescriptor(buf, true)
   411  
   412  	return
   413  }
   414  
   415  // AddString adds a string descriptor to a USB device. The returned index can
   416  // be used to fill string descriptor index value in configuration descriptors
   417  // (p274, Table 9-16. UNICODE String Descriptor, USB2.0).
   418  func (d *Device) AddString(s string) (uint8, error) {
   419  	var buf []byte
   420  
   421  	desc := &StringDescriptor{}
   422  	desc.SetDefaults()
   423  
   424  	r := []rune(s)
   425  	u := utf16.Encode([]rune(r))
   426  
   427  	for i := 0; i < len(u); i++ {
   428  		buf = append(buf, byte(u[i]&0xff))
   429  		buf = append(buf, byte(u[i]>>8))
   430  	}
   431  
   432  	return d.setStringDescriptor(buf, false)
   433  }
   434  
   435  // AddConfiguration adds a Configuration Descriptor to a device, updating its
   436  // Device Descriptor configuration count accordingly.
   437  func (d *Device) AddConfiguration(conf *ConfigurationDescriptor) (err error) {
   438  	d.Configurations = append(d.Configurations, conf)
   439  
   440  	if d.Descriptor == nil {
   441  		return errors.New("invalid device descriptor")
   442  	}
   443  
   444  	d.Descriptor.NumConfigurations += 1
   445  
   446  	return
   447  }
   448  
   449  // Configuration converts the device configuration hierarchy to a buffer, as expected by Get
   450  // Descriptor for configuration descriptor type
   451  // (p281, 9.4.3 Get Descriptor, USB2.0).
   452  func (d *Device) Configuration(wIndex uint16) (buf []byte, err error) {
   453  	if int(wIndex+1) > len(d.Configurations) {
   454  		err = errors.New("invalid configuration index")
   455  		return
   456  	}
   457  
   458  	conf := d.Configurations[int(wIndex)]
   459  
   460  	for i := 0; i < len(conf.Interfaces); i++ {
   461  		iface := conf.Interfaces[i]
   462  
   463  		// If an IAD is present set the first interface value, unless
   464  		// already set, depending on where we are in the interface
   465  		// list.
   466  		if iface.IAD != nil && iface.IAD.FirstInterface == 0 {
   467  			iface.IAD.FirstInterface = uint8(i)
   468  		}
   469  
   470  		buf = append(buf, iface.Bytes()...)
   471  
   472  		for i := 0; i < len(iface.Endpoints); i++ {
   473  			ep := iface.Endpoints[i]
   474  			buf = append(buf, ep.Bytes()...)
   475  		}
   476  	}
   477  
   478  	conf.TotalLength = uint16(int(conf.Length) + len(buf))
   479  	buf = append(conf.Bytes(), buf...)
   480  
   481  	return
   482  }