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 }