1 //
2 // Copyright (c) 2010-2020 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 USBInterface : DescriptorProvider
16     {
USBInterface(IUSBDevice device, byte identifier, USBClassCode classCode = USBClassCode.NotSpecified, byte subClassCode = 0, byte protocol = 0, string description = null)17         public USBInterface(IUSBDevice device,
18                             byte identifier,
19                             USBClassCode classCode = USBClassCode.NotSpecified,
20                             byte subClassCode = 0,
21                             byte protocol = 0,
22                             string description = null) : base(9, (byte)DescriptorType.Interface)
23         {
24             this.device = device;
25             endpoints = new List<USBEndpoint>();
26 
27             Identifier = identifier;
28             Class = classCode;
29             SubClass = subClassCode;
30             Protocol = protocol;
31             Description = description;
32 
33             RegisterSubdescriptors(endpoints);
34         }
35 
HandleRequest(SetupPacket packet)36         public virtual BitStream HandleRequest(SetupPacket packet)
37         {
38             return BitStream.Empty;
39         }
40 
WithEndpoint(Direction direction, EndpointTransferType transferType, short maximumPacketSize, byte interval, out USBEndpoint createdEndpoint, byte? id = null)41         public USBInterface WithEndpoint(Direction direction, EndpointTransferType transferType, short maximumPacketSize, byte interval, out USBEndpoint createdEndpoint, byte? id = null)
42         {
43             if(!id.HasValue && endpoints.Count == byte.MaxValue)
44             {
45                 throw new ConstructionException("The maximal number of endpoints reached");
46             }
47 
48             var localId = id ?? (byte)(endpoints.Count + 1);
49             if(endpoints.Any(x => x.Identifier == localId && x.Direction == direction))
50             {
51                 throw new ConstructionException($"Endpoint with id {localId} in direction {direction} already definied");
52             }
53 
54             createdEndpoint = new USBEndpoint(device, localId, direction, transferType, maximumPacketSize, interval);
55             endpoints.Add(createdEndpoint);
56             return this;
57         }
58 
59         public USBClassCode Class { get; }
60         public byte SubClass { get; }
61         public byte Protocol { get; }
62         public string Description { get; }
63         public byte Identifier { get; }
64         public IReadOnlyCollection<USBEndpoint> Endpoints => endpoints;
65 
FillDescriptor(BitStream buffer)66         protected override void FillDescriptor(BitStream buffer)
67         {
68             buffer
69                 .Append(Identifier)
70                 .Append(0) // TODO: implement alternate setting
71                 .Append((byte)Endpoints.Count)
72                 .Append((byte)Class)
73                 .Append(SubClass)
74                 .Append(Protocol)
75                 .Append(USBString.FromString(Description).Index);
76         }
77 
78         protected readonly IUSBDevice device;
79 
80         private readonly List<USBEndpoint> endpoints;
81     }
82 }
83