1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Exceptions; 11 using Antmicro.Renode.Utilities; 12 13 namespace Antmicro.Renode.Core.USB 14 { 15 public class USBConfiguration : DescriptorProvider 16 { USBConfiguration(IUSBDevice device, byte identifier, string description = null, bool selfPowered = false, bool remoteWakeup = false, short maximalPower = 0)17 public USBConfiguration(IUSBDevice device, 18 byte identifier, 19 string description = null, 20 bool selfPowered = false, 21 bool remoteWakeup = false, 22 short maximalPower = 0) : base(9, (byte)DescriptorType.Configuration) 23 { 24 if(maximalPower > 500 || maximalPower < 0) 25 { 26 throw new ConstructionException("Maximal power should be between 0 and 500 mA"); 27 } 28 29 this.device = device; 30 31 interfaces = new List<USBInterface>(); 32 33 Identifier = identifier; 34 Description = description; 35 MaximalPower = maximalPower; 36 SelfPowered = selfPowered; 37 RemoteWakeup = remoteWakeup; 38 39 RegisterSubdescriptors(interfaces); 40 } 41 42 public USBConfiguration WithInterface<T>(byte subClassCode, 43 byte protocol, 44 string description = null, 45 Action<T> configure = null) where T : USBInterface 46 { 47 var newInterface = (T)Activator.CreateInstance(typeof(T), device, (byte)interfaces.Count, subClassCode, protocol, description); 48 configure?.Invoke(newInterface); 49 return WithInterface(newInterface); 50 } 51 WithInterface(USBInterface iface)52 public USBConfiguration WithInterface(USBInterface iface) 53 { 54 if(interfaces.Count == byte.MaxValue) 55 { 56 throw new ConstructionException("The maximal number of interfaces reached"); 57 } 58 59 interfaces.Add(iface); 60 return this; 61 } 62 63 public USBConfiguration WithInterface<T>(T iface, Action<USBInterface> configure = null) where T : USBInterface 64 { 65 if(interfaces.Count == byte.MaxValue) 66 { 67 throw new ConstructionException("The maximal number of interfaces reached"); 68 } 69 70 configure?.Invoke(iface); 71 interfaces.Add(iface); 72 return this; 73 } 74 WithInterface(USBClassCode classCode = USBClassCode.NotSpecified, byte subClassCode = 0, byte protocol = 0, string description = null, Action<USBInterface> configure = null)75 public USBConfiguration WithInterface(USBClassCode classCode = USBClassCode.NotSpecified, 76 byte subClassCode = 0, 77 byte protocol = 0, 78 string description = null, 79 Action<USBInterface> configure = null) 80 { 81 var newInterface = new USBInterface(device, (byte)interfaces.Count, classCode, subClassCode, protocol, description); 82 configure?.Invoke(newInterface); 83 return WithInterface(newInterface); 84 } 85 86 public byte Identifier { get; } 87 public string Description { get; } 88 public short MaximalPower { get; } 89 public bool SelfPowered { get; } 90 public bool RemoteWakeup { get; } 91 92 public IReadOnlyCollection<USBInterface> Interfaces => interfaces; 93 FillDescriptor(BitStream buffer)94 protected override void FillDescriptor(BitStream buffer) 95 { 96 buffer 97 .Append((short)RecursiveDescriptorLength) 98 .Append((byte)Interfaces.Count) 99 .Append(Identifier) 100 .Append(USBString.FromString(Description).Index) 101 .Append((byte)(((SelfPowered ? 1 : 0) << 6) | ((RemoteWakeup ? 1 : 0) << 5))) 102 .Append((byte)((MaximalPower + 1) / 2)); 103 } 104 105 private readonly List<USBInterface> interfaces; 106 private readonly IUSBDevice device; 107 } 108 }