1 //
2 // Copyright (c) 2010-2019 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System;
9 using System.Collections.Generic;
10 using System.Linq;
11 using System.Threading;
12 using Antmicro.Renode.Core;
13 using Antmicro.Renode.Core.Structure.Registers;
14 using Antmicro.Renode.Core.USB;
15 using Antmicro.Renode.Logging;
16 using Antmicro.Renode.Utilities;
17 using Antmicro.Renode.Utilities.Packets;
18 
19 namespace Antmicro.Renode.Peripherals.USB
20 {
21     public class ValentyUSB : BasicDoubleWordPeripheral, IUSBDevice, IKnownSize
22     {
ValentyUSB(IMachine machine, int maximumPacketSize = 64)23         public ValentyUSB(IMachine machine, int maximumPacketSize = 64) : base(machine)
24         {
25             maxPacketSize = maximumPacketSize;
26             USBCore = new USBDeviceCore(this, customSetupPacketHandler: SetupPacketHandler);
27             DefineRegisters();
28         }
29 
Reset()30         public override void Reset()
31         {
32             base.Reset();
33             slaveToMasterBufferVirtualBase = 0;
34             state = State.Idle;
35 
36             masterToSlaveBuffer.Clear();
37             masterToSlaveAdditionalDataBuffer.Clear();
38             slaveToMasterBuffer.Clear();
39         }
40 
41         public long Size => 0x100;
42 
43         public USBDeviceCore USBCore { get; }
44 
45         public GPIO IRQ { get; } = new GPIO();
46 
DefineRegisters()47         private void DefineRegisters()
48         {
49             Registers.Endpoint0OutEventPending.Define(this)
50                 .WithFlag(0, out endpoint0OutErrorPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "error")
51                 .WithFlag(1, out endpoint0OutPacketPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "packet")
52                 .WithReservedBits(2, 30)
53                 .WithWriteCallback((_, __) => UpdateInterrupts())
54             ;
55 
56             Registers.Endpoint0OutEventEnable.Define(this)
57                 .WithFlag(0, out endpoint0OutErrorEventEnabled, name: "error")
58                 .WithFlag(1, out endpoint0OutPacketEventEnabled, name: "packet")
59                 .WithReservedBits(2, 30)
60                 .WithWriteCallback((_, __) => UpdateInterrupts())
61             ;
62 
63             Registers.Endpoint0InEventPending.Define(this)
64                 .WithFlag(0, out endpoint0InErrorPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "error")
65                 .WithFlag(1, out endpoint0InPacketPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "packet")
66                 .WithReservedBits(2, 30)
67                 .WithWriteCallback((_, __) => UpdateInterrupts())
68             ;
69 
70             Registers.Endpoint0InEventEnable.Define(this)
71                 .WithFlag(0, out endpoint0InErrorEventEnabled, name: "error")
72                 .WithFlag(1, out endpoint0InPacketEventEnabled, name: "packet")
73                 .WithReservedBits(2, 30)
74                 .WithWriteCallback((_, __) => UpdateInterrupts())
75             ;
76 
77             Registers.Endpoint0LastTokenRead.Define(this)
78                 .WithEnumField<DoubleWordRegister, USBTokenType>(0, 2, FieldMode.Read, valueProviderCallback: _ =>
79                 {
80                     switch(state)
81                     {
82                     case State.SetupTokenReceived:
83                     case State.SetupTokenAcked:
84                         return USBTokenType.Setup;
85 
86                     case State.ReadyForDataFromMaster:
87                     case State.DataFromMasterAcked:
88                         return USBTokenType.Out;
89 
90                     case State.DataToMasterReady:
91                         return USBTokenType.In;
92 
93                     default:
94                         return USBTokenType.Out;
95                     }
96                 })
97                 .WithReservedBits(2, 30);
98             ;
99 
100             Registers.Endpoint0OutBufferEmpty.Define(this)
101                 .WithFlag(0, FieldMode.Read, name: "bufferEmpty", valueProviderCallback: _ => !masterToSlaveBuffer.Any())
102                 .WithReservedBits(1, 31)
103             ;
104 
105             Registers.Endpoint0OutBufferHead.Define(this)
106                 .WithValueField(0, 8, name: "bufferHeadByte",
107                     // this buffer works in a special way -
108                     // in order to move to the next item
109                     // software must execute 'write' operation
110                     valueProviderCallback: _ =>
111                     {
112                         if(masterToSlaveBuffer.Count == 0)
113                         {
114                             this.Log(LogLevel.Warning, "Trying to read from an empty queue");
115                             return 0u;
116                         }
117 
118                         var result = masterToSlaveBuffer.Peek();
119                         this.Log(LogLevel.Noisy, "Reading byte from out buffer: 0x{0:X}. Bytes left: {1}", result, masterToSlaveBuffer.Count);
120                         return result;
121                     },
122                     writeCallback: (_, __) => masterToSlaveBuffer.Dequeue())
123                 .WithReservedBits(8, 24)
124             ;
125 
126             Registers.Endpoint0OutRespond.Define(this)
127                 .WithEnumField<DoubleWordRegister, USBResponse>(0, 2, writeCallback: (_, v) =>
128                 {
129                     this.Log(LogLevel.Noisy, "Endpoint 0 OUT response set to: {0} in state {1}", v, state);
130                     switch(v)
131                     {
132                     case USBResponse.Stall:
133                         state = State.Stall;
134                         HandleStall();
135                         break;
136 
137                     case USBResponse.Ack:
138                         HandleOutAckRespond();
139                         break;
140 
141                     case USBResponse.NotAck:
142                         // intentionally do nothing
143                         break;
144 
145                     default:
146                         this.Log(LogLevel.Warning, "Unexpected endpoint 0 OUT response: {0}. Expect problems", v);
147                         state = State.Error;
148                         break;
149                     }
150                 })
151                 .WithReservedBits(2, 30)
152             ;
153 
154             Registers.Endpoint0InRespond.Define(this)
155                 .WithEnumField<DoubleWordRegister, USBResponse>(0, 2, writeCallback: (_, v) =>
156                 {
157                     this.Log(LogLevel.Noisy, "Endpoint 0 IN response set to: {0} in state {1}", v, state);
158                     switch(v)
159                     {
160                     case USBResponse.Ack:
161                         state = State.DataToMasterReady;
162                         ProduceDataToMaster();
163                         break;
164 
165                     case USBResponse.Stall:
166                         state = State.Stall;
167                         HandleStall();
168                         break;
169 
170                     case USBResponse.NotAck:
171                         // intentionally do nothing
172                         break;
173 
174                     default:
175                         this.Log(LogLevel.Warning, "Unexpected endpoint 0 IN response: {0}. Expect problems", v);
176                         state = State.Error;
177                         break;
178                     }
179                 })
180                 .WithReservedBits(2, 30)
181             ;
182 
183             Registers.Endpoint0InBufferEmpty.Define(this)
184                 .WithFlag(0, FieldMode.Read, name: "bufferEmpty", valueProviderCallback: _ => slaveToMasterBuffer.Count == slaveToMasterBufferVirtualBase)
185                 .WithReservedBits(1, 31)
186             ;
187 
188             Registers.Endpoint0InBufferHead.Define(this)
189                 .WithValueField(0, 8, FieldMode.Write, name: "bufferHeadByte",
190                         writeCallback: (_, b) => slaveToMasterBuffer.Enqueue((byte)b))
191                 .WithReservedBits(8, 24)
192             ;
193 
194             Registers.Endpoint0InDataToggleBit.Define(this)
195                 // since we don't generate separate Data0/Data1 packets in a transaction anyway, writes can be ignored
196                 // we must return 0, because otherwise foboot does not work...
197                 .WithFlag(0, name: "Data Toggle Bit", valueProviderCallback: _ => false)
198                 .WithReservedBits(1, 31)
199             ;
200 
201             Registers.Address.Define(this)
202                 .WithValueField(0, 8, name: "USBAddress",
203                     writeCallback: (_, val) => { USBCore.Address = (byte)val; },
204                     valueProviderCallback: _ => USBCore.Address)
205                 .WithReservedBits(8, 24)
206             ;
207         }
208 
SendSetupPacketResponse()209         private void SendSetupPacketResponse()
210         {
211             if(masterToSlaveAdditionalDataBuffer.Count != 0)
212             {
213                 this.Log(LogLevel.Error, "Setup packet handling finished, but there is still some unhandled additional data left. Dropping it, but expect problems");
214                 masterToSlaveAdditionalDataBuffer.Clear();
215             }
216 
217             this.Log(LogLevel.Noisy, "Setup packet handled");
218 #if DEBUG_PACKETS
219             this.Log(LogLevel.Noisy, "Response bytes: [{0}]", Misc.PrettyPrintCollectionHex(slaveToMasterBuffer));
220 #endif
221             slaveToMasterBufferVirtualBase = 0;
222 
223             if(setupPacketResultCallback == null)
224             {
225                 this.Log(LogLevel.Error, "No setup packet is handled at the moment, but the software wants to send data back. It might indicate a faulty driver");
226                 return;
227             }
228 
229             setupPacketResultCallback(slaveToMasterBuffer.DequeueAll());
230             setupPacketResultCallback = null;
231         }
232 
HandleStall()233         private void HandleStall()
234         {
235             this.Log(LogLevel.Debug, "Endpoint 0 stalled");
236 
237             // this could happen since HandleStall is called for both IN and OUT packets
238             if(setupPacketResultCallback == null)
239             {
240                 return;
241             }
242 
243             SendSetupPacketResponse();
244         }
245 
ProduceDataToMaster()246         private void ProduceDataToMaster()
247         {
248             var chunkSize = slaveToMasterBuffer.Count - slaveToMasterBufferVirtualBase;
249             slaveToMasterBufferVirtualBase = slaveToMasterBuffer.Count;
250 
251             if(chunkSize < maxPacketSize)
252             {
253                 this.Log(LogLevel.Noisy, "Data chunk was shorter than max packet size (0x{0:X} vs 0x{1:X}), so this is the end of data", chunkSize, maxPacketSize);
254                 SendSetupPacketResponse();
255             }
256 
257             // IN packet pending means that the master is waiting for more data
258             // and slave should generate it
259             endpoint0InPacketPending.Value = true;
260             UpdateInterrupts();
261         }
262 
PrepareDataFromMaster()263         private void PrepareDataFromMaster()
264         {
265             if(masterToSlaveAdditionalDataBuffer.Count == 0)
266             {
267                 this.Log(LogLevel.Warning, "Asked for additional data from master, but there is no more of it");
268                 return;
269             }
270 
271             var chunk = masterToSlaveAdditionalDataBuffer.DequeueRange(maxPacketSize);
272             this.Log(LogLevel.Noisy, "Enqueuing chunk of additional data from master of size {0}", chunk.Length);
273             EnqueueDataFromMaster(chunk);
274         }
275 
276 
EnqueueDataFromMaster(IEnumerable<byte> data)277         private void EnqueueDataFromMaster(IEnumerable<byte> data)
278         {
279             masterToSlaveBuffer.EnqueueRange(data);
280 
281             // fake 16-bit CRC
282             masterToSlaveBuffer.Enqueue(0);
283             masterToSlaveBuffer.Enqueue(0);
284 
285             endpoint0OutPacketPending.Value = true;
286             UpdateInterrupts();
287         }
288 
HandleOutAckRespond()289         private void HandleOutAckRespond()
290         {
291             switch(state)
292             {
293             case State.Idle:
294                 // do nothing
295                 break;
296 
297             case State.SetupTokenReceived:
298                 state = State.SetupTokenAcked;
299                 break;
300 
301             case State.SetupTokenAcked:
302             case State.DataFromMasterAcked:
303                 state = State.ReadyForDataFromMaster;
304                 PrepareDataFromMaster();
305                 break;
306 
307             case State.ReadyForDataFromMaster:
308                 state = State.DataFromMasterAcked;
309                 break;
310 
311             default:
312                 this.Log(LogLevel.Warning, "Unexpected state when handling OUT ACK response: {0}. Expect problems", state);
313                 state = State.Error;
314                 break;
315             }
316         }
317 
UpdateInterrupts()318         private void UpdateInterrupts()
319         {
320             var irqState = (endpoint0OutPacketPending.Value && endpoint0OutPacketEventEnabled.Value)
321                 || (endpoint0OutErrorPending.Value && endpoint0OutErrorEventEnabled.Value)
322                 || (endpoint0InPacketPending.Value && endpoint0InPacketEventEnabled.Value)
323                 || (endpoint0InErrorPending.Value && endpoint0InErrorEventEnabled.Value);
324 
325             IRQ.Set(irqState);
326         }
327 
328         // NOTE: Here we assume that the communication is well-formed, i.e.,
329         // the controller does not send two setup packets in a row (without waiting for a response),
330         // or a device does not start to respond by itself (without the request from the master).
331         // There are some checks verifying it and printing errors, but there is no mechanism enforcing it.
SetupPacketHandler(SetupPacket packet, byte[] additionalData, Action<byte[]> resultCallback)332         private void SetupPacketHandler(SetupPacket packet, byte[] additionalData, Action<byte[]> resultCallback)
333         {
334             this.Log(LogLevel.Noisy, "Received setup packet: {0}", packet.ToString());
335 
336             if(setupPacketResultCallback != null)
337             {
338                 this.Log(LogLevel.Error, "Setup packet result handler is set. It means that the previous setup packet handler has not yet finished. Expect problems!");
339             }
340             setupPacketResultCallback = resultCallback;
341 
342             slaveToMasterBuffer.Clear();
343             slaveToMasterBufferVirtualBase = 0;
344             state = State.SetupTokenReceived;
345 
346             var packetBytes = Packet.Encode(packet);
347 #if DEBUG_PACKETS
348             this.Log(LogLevel.Noisy, "Setup packet bytes: [{0}]", Misc.PrettyPrintCollectionHex(packetBytes));
349 #endif
350             EnqueueDataFromMaster(packetBytes);
351 
352             // this is a trick:
353             // in fact we don't know if the master expects any data from the slave,
354             // but we can safely assume so - if there is no data, we should simply
355             // receive NAK;
356             // without generating this interrupt the slave would never know that
357             // it should generate any response and we would be stuck
358             endpoint0InPacketPending.Value = true;
359             UpdateInterrupts();
360 
361             if(additionalData != null)
362             {
363                 masterToSlaveAdditionalDataBuffer.EnqueueRange(additionalData);
364             }
365         }
366 
367         private Action<byte[]> setupPacketResultCallback;
368 
369         private State state;
370         // in order to avoid copying data from `slaveToMasterBuffer`
371         // into another buffer it's not cleared after generating ACK
372         // packet; in order to detect how much data has been added to
373         // the buffer this variable contains the length of the buffer
374         // before the previous ACK packet
375         private int slaveToMasterBufferVirtualBase;
376 
377         private IFlagRegisterField endpoint0OutPacketPending;
378         private IFlagRegisterField endpoint0InPacketPending;
379         private IFlagRegisterField endpoint0InPacketEventEnabled;
380         private IFlagRegisterField endpoint0InErrorEventEnabled;
381         private IFlagRegisterField endpoint0InErrorPending;
382         private IFlagRegisterField endpoint0OutPacketEventEnabled;
383         private IFlagRegisterField endpoint0OutErrorEventEnabled;
384         private IFlagRegisterField endpoint0OutErrorPending;
385 
386         private readonly int maxPacketSize;
387         private readonly Queue<byte> masterToSlaveBuffer = new Queue<byte>();
388         private readonly Queue<byte> masterToSlaveAdditionalDataBuffer = new Queue<byte>();
389         private readonly Queue<byte> slaveToMasterBuffer = new Queue<byte>();
390 
391         private enum USBResponse
392         {
393             Ack,
394             NotAck,
395             None,
396             Stall
397         }
398 
399         private enum USBTokenType
400         {
401             Out = 0,
402             StartOfFrame = 1,
403             In = 2,
404             Setup = 3
405         }
406 
407         private enum State
408         {
409             Idle,
410             Stall,
411             DataToMasterReady,
412             ReadyForDataFromMaster,
413             SetupTokenReceived,
414             SetupTokenAcked,
415             DataFromMasterAcked,
416             Error,
417         }
418 
419         private enum Registers
420         {
421             PullupOut = 0x0,
422 
423             Endpoint0OutEventStatus = 0x4,
424             Endpoint0OutEventPending = 0x08,
425             Endpoint0OutEventEnable = 0x0C,
426             Endpoint0LastTokenRead = 0x10,
427             Endpoint0OutRespond = 0x14,
428             Endpoint0OutDataToggleBit = 0x18,
429             Endpoint0OutBufferHead = 0x1C,
430             Endpoint0OutBufferEmpty = 0x20,
431 
432             Endpoint0InEventStatus = 0x24,
433             Endpoint0InEventPending = 0x28,
434             Endpoint0InEventEnable = 0x2C,
435             Endpoint0InLastToken = 0x30,
436             Endpoint0InRespond = 0x34,
437             Endpoint0InDataToggleBit = 0x38,
438             Endpoint0InBufferHead = 0x3C,
439             Endpoint0InBufferEmpty = 0x40,
440 
441             Endpoint1InEventStatus = 0x44,
442             Endpoint1InEventPending = 0x48,
443             Endpoint1InEventEnable = 0x4C,
444             Endpoint1InLastToken = 0x50,
445             Endpoint1InRespond = 0x54,
446             Endpoint1InDataToggleBit = 0x58,
447             Endpoint1InBufferHead = 0x5C,
448             Endpoint1InBufferEmpty = 0x60,
449 
450             Endpoint2OutEventStatus = 0x64,
451             Endpoint2OutEventPending = 0x68,
452             Endpoint2OutEventEnable = 0x6C,
453             Endpoint2OutLastToken = 0x70,
454             Endpoint2OutRespond = 0x74,
455             Endpoint2OutDataToggleBit = 0x78,
456             Endpoint2OutBufferHead = 0x7C,
457             Endpoint2OutBufferEmpty = 0x80,
458 
459             Endpoint2InEventStatus = 0x84,
460             Endpoint2InEventPending = 0x88,
461             Endpoint2InEventEnable = 0x8C,
462             Endpoint2InLastToken = 0x90,
463             Endpoint2InRespond = 0x94,
464             Endpoint2InDataToggleBit = 0x98,
465             Endpoint2InBufferHead = 0x9C,
466             Endpoint2InBufferEmpty = 0xA0,
467 
468             Address = 0xA4
469         }
470     }
471 }
472