1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Storage; 12 using Antmicro.Renode.Utilities; 13 using System.IO; 14 15 namespace Antmicro.Renode.Peripherals.USBDeprecated 16 { 17 public class MassStorage: IUSBPeripheral, IDisposable 18 { 19 public event Action <uint> SendInterrupt 20 { 21 add {} 22 remove {} 23 } 24 25 public event Action <uint> SendPacket 26 { 27 add {} 28 remove {} 29 } 30 31 byte[] controlPacket; 32 uint addr; 33 GetAddress()34 public uint GetAddress() 35 { 36 return addr; 37 } 38 GetSpeed()39 public USBDeviceSpeed GetSpeed() 40 { 41 return USBDeviceSpeed.High; 42 } 43 Dispose()44 public void Dispose() 45 { 46 lbaBackend.Dispose(); 47 } 48 MassStorage(int numberOfBlocks, int blockSize = 512)49 public MassStorage(int numberOfBlocks, int blockSize = 512) 50 { 51 lbaBackend = new LBABackend(numberOfBlocks, blockSize); 52 Init(); 53 } 54 MassStorage(string underlyingFile, int? numberOfBlocks = null, int blockSize = 512, bool persistent = true)55 public MassStorage(string underlyingFile, int? numberOfBlocks = null, int blockSize = 512, bool persistent = true) 56 { 57 lbaBackend = new LBABackend(underlyingFile, numberOfBlocks, blockSize, persistent); 58 Init(); 59 60 } 61 62 public string ImageFile 63 { 64 get 65 { 66 return lbaBackend.UnderlyingFile; 67 } 68 set 69 { 70 if(lbaBackend != null) 71 { 72 lbaBackend.Dispose(); 73 } 74 if(!File.Exists(value)) 75 { 76 if(lbaBackend.UnderlyingFile != null && File.Exists(lbaBackend.UnderlyingFile)) 77 { 78 FileCopier.Copy(lbaBackend.UnderlyingFile, value); 79 } 80 else 81 { 82 lbaBackend = new LBABackend(value, lbaBackend.NumberOfBlocks, lbaBackend.BlockSize); 83 return; 84 } 85 } 86 lbaBackend = new LBABackend(value, lbaBackend.BlockSize); 87 } 88 } 89 Reset()90 public void Reset() 91 { 92 //throw new NotImplementedException(); 93 } 94 95 #region IUSBDevice implementation ProcessClassGet(USBPacket packet, USBSetupPacket setupPacket)96 public byte[] ProcessClassGet(USBPacket packet, USBSetupPacket setupPacket) 97 { 98 byte request = setupPacket.request; 99 switch((MassStorageRequestCode)request) 100 { 101 102 case MassStorageRequestCode.GetMaxLUN: 103 controlPacket = new [] {MaxLun}; 104 return new [] {MaxLun}; 105 default: 106 controlPacket = new byte[0]; 107 return new byte[0]; 108 } 109 } 110 GetDescriptor(USBPacket packet, USBSetupPacket setupPacket)111 public byte[] GetDescriptor(USBPacket packet, USBSetupPacket setupPacket) 112 { 113 var type = (DescriptorType)((setupPacket.value & 0xff00) >> 8); 114 switch(type) 115 { 116 case DescriptorType.Device: 117 controlPacket = deviceDescriptor.ToArray(); 118 break; 119 case DescriptorType.Configuration: 120 controlPacket = configurationDescriptor.ToArray(); 121 break; 122 case DescriptorType.DeviceQualifier: 123 controlPacket = deviceQualifierDescriptor.ToArray(); 124 break; 125 case DescriptorType.InterfacePower: 126 throw new NotImplementedException("Interface Power Descriptor is not yet implemented. Please contact AntMicro for further support."); 127 case DescriptorType.OtherSpeedConfiguration: 128 controlPacket = otherConfigurationDescriptor.ToArray(); 129 break; 130 case DescriptorType.String: 131 uint index = (uint)(setupPacket.value & 0xff); 132 if(index == 0) 133 { 134 stringDescriptor = new StringUSBDescriptor(1); 135 stringDescriptor.LangId[0] = EnglishLangId; 136 } 137 else 138 { 139 stringDescriptor = new StringUSBDescriptor(stringValues[setupPacket.index][index]); 140 } 141 controlPacket = stringDescriptor.ToArray(); 142 break; 143 default: 144 this.Log(LogLevel.Warning, "Unsupported descriptor"); 145 return null; 146 } 147 return controlPacket; 148 } 149 WriteDataBulk(USBPacket packet)150 public void WriteDataBulk(USBPacket packet) 151 { 152 if(packet.data != null && packet.bytesToTransfer != 31) 153 { 154 oData.AddRange(packet.data); 155 } 156 else if(packet.bytesToTransfer == 31 || oData.Count > 0) 157 { 158 byte[] data; 159 var cbw = new CommandBlockWrapper(); 160 var cdb = new SCSI.CommandDescriptorBlock(); 161 if(packet.bytesToTransfer == 31) 162 { 163 data = packet.data; 164 } 165 else 166 { 167 data = oData.ToArray(); 168 oData.Clear(); 169 } 170 if(!cbw.Fill(data)) 171 { 172 if(writeFlag) 173 { 174 writeFlag = false; 175 lbaBackend.Write((int)writeCDB.LogicalBlockAddress, data, (int)writeCDB.TransferLength); 176 writeCSW.DataResidue -= (uint)(data.Length); 177 transmissionQueue.Enqueue(writeCSW.ToArray()); 178 179 } 180 else 181 { 182 //throw new InvalidOperationException ("Corrupted Command Block Wrapper"); 183 this.Log(LogLevel.Warning, "Corrupted Command Block Wrapper"); 184 } 185 } 186 else 187 { 188 ReceiveCommandBlockWrapper(cbw, cdb, data); 189 } 190 } 191 } 192 ReceiveCommandBlockWrapper(CommandBlockWrapper cbw, SCSI.CommandDescriptorBlock cdb, byte[] data)193 void ReceiveCommandBlockWrapper(CommandBlockWrapper cbw, SCSI.CommandDescriptorBlock cdb, byte[] data) 194 { 195 this.DebugLog("Received Command Block Wrapper"); 196 var csw = new CommandStatusWrapper(); 197 var cdbData = new byte[cbw.Length]; 198 Array.Copy(data, 15, cdbData, 0, cbw.Length); 199 cdb.Fill(cdbData); 200 switch((SCSI.CommandDescriptorBlock.GroupCode)cdb.OperationCode) 201 { 202 case SCSI.CommandDescriptorBlock.GroupCode.Inquiry: 203 csw.Tag = cbw.Tag; 204 csw.DataResidue = 0x00; 205 csw.Status = 0x00; 206 transmissionQueue.Enqueue(inquiry.ToArray()); 207 //enqueue inquiry data 208 transmissionQueue.Enqueue(csw.ToArray()); 209 break; 210 case SCSI.CommandDescriptorBlock.GroupCode.ModeSense: 211 var msc = new SCSI.ModeSenseCommand(); 212 msc.Fill(cdbData); 213 var retArr = new byte[192]; 214 retArr[0] = 0x03; 215 //FIXME: probably it should return sth with more sense 216 csw.Tag = cbw.Tag; 217 csw.DataResidue = cbw.DataTransferLength - 0x03; 218 csw.Status = 0x00; 219 transmissionQueue.Enqueue(retArr); 220 transmissionQueue.Enqueue(csw.ToArray()); 221 break; 222 case SCSI.CommandDescriptorBlock.GroupCode.PreventAllowMediumRemoval: 223 csw.Tag = cbw.Tag; 224 csw.DataResidue = 0x00; 225 csw.Status = 0x00; 226 transmissionQueue.Enqueue(csw.ToArray()); 227 break; 228 case SCSI.CommandDescriptorBlock.GroupCode.Read10: 229 var dataRead = lbaBackend.Read((int)cdb.LogicalBlockAddress, (int)cdb.TransferLength); 230 csw.Tag = cbw.Tag; 231 csw.DataResidue = (uint)(cbw.DataTransferLength - dataRead.Length); 232 csw.Status = 0x00; 233 transmissionQueue.Enqueue(dataRead); 234 transmissionQueue.Enqueue(csw.ToArray()); 235 break; 236 case SCSI.CommandDescriptorBlock.GroupCode.Write10: 237 writeFlag = true; 238 //next write command could be data 239 csw.Tag = cbw.Tag; 240 csw.DataResidue = cbw.DataTransferLength; 241 csw.Status = 0x00; 242 writeCSW = csw; 243 writeCDB = cdb; 244 //transmissionQueue.Enqueue(csw.ToArray()); 245 break; 246 case SCSI.CommandDescriptorBlock.GroupCode.ReadCapacity: 247 var capData = new SCSI.CapacityDataStructure(); 248 capData.ReturnedLBA = (uint)lbaBackend.NumberOfBlocks - 1; 249 capData.BlockLength = (uint)lbaBackend.BlockSize; 250 csw.Tag = cbw.Tag; 251 csw.DataResidue = 0x00; 252 csw.Status = 0x00; 253 transmissionQueue.Enqueue(capData.ToArray()); 254 transmissionQueue.Enqueue(csw.ToArray()); 255 break; 256 case SCSI.CommandDescriptorBlock.GroupCode.RequestSense: 257 // TODO: this was copied from TestUnitReady. do a proper implementation 258 csw.Tag = cbw.Tag; 259 csw.DataResidue = 0x00; 260 csw.Status = 0x00; 261 transmissionQueue.Enqueue(csw.ToArray()); 262 break; 263 case SCSI.CommandDescriptorBlock.GroupCode.TestUnitReady: 264 csw.Tag = cbw.Tag; 265 csw.DataResidue = 0x00; 266 csw.Status = 0x00; 267 transmissionQueue.Enqueue(csw.ToArray()); 268 break; 269 default: 270 this.Log(LogLevel.Warning, "Unsuported Command Code: 0x{0:X}", cdb.OperationCode); 271 break; 272 } 273 } 274 WriteDataControl(USBPacket packet)275 public void WriteDataControl(USBPacket packet) 276 { 277 278 } 279 WriteInterrupt(USBPacket packet)280 public byte[] WriteInterrupt(USBPacket packet) 281 { 282 return null; 283 } 284 285 byte[] currentIDataRegister; 286 int currentIDataPointer; 287 List<byte> oData; 288 GetDataBulk(USBPacket packet)289 public byte[] GetDataBulk(USBPacket packet) 290 { 291 292 USBPacket pack; 293 pack.data = null; 294 pack.ep = 0; 295 pack.bytesToTransfer = 0; 296 if(oData.Count != 0) 297 { 298 WriteDataBulk(pack); 299 oData.Clear(); 300 } 301 if(transmissionQueue.Count > 0) 302 { 303 if(packet.bytesToTransfer > 0) 304 { 305 var dataPacket = new byte[packet.bytesToTransfer]; 306 if(currentIDataRegister == null) 307 { 308 currentIDataRegister = transmissionQueue.Dequeue(); 309 310 } 311 Array.Copy(currentIDataRegister, currentIDataPointer, dataPacket, 0, (int)packet.bytesToTransfer); 312 currentIDataPointer += (int)packet.bytesToTransfer; 313 if(currentIDataPointer >= currentIDataRegister.Length) 314 { 315 currentIDataRegister = null; 316 currentIDataPointer = 0; 317 } 318 319 return dataPacket; 320 } 321 //TODO: Rly? A nie przypadkiem "Trying to read 0 bytes"? 322 this.Log(LogLevel.Warning, "Trying to read from empty queue"); 323 return new byte[0]; 324 325 } 326 return null; 327 } 328 GetTransferStatus()329 public byte GetTransferStatus() 330 { 331 return 0; 332 } 333 GetDataControl(USBPacket packet)334 public byte[] GetDataControl(USBPacket packet) 335 { 336 return controlPacket; 337 } 338 ProcessClassSet(USBPacket packet, USBSetupPacket setupPacket)339 public void ProcessClassSet(USBPacket packet, USBSetupPacket setupPacket) 340 { 341 byte request = setupPacket.request; 342 343 switch((MassStorageRequestCode)request) 344 { 345 case MassStorageRequestCode.MassStorageReset: 346 this.DebugLog("Mass storage reset"); 347 break; 348 default: 349 this.Log(LogLevel.Warning, "Unknown Class Set Code ({0:X})", request); 350 break; 351 } 352 } 353 SetDataToggle(byte endpointNumber)354 public void SetDataToggle(byte endpointNumber) 355 { 356 throw new NotImplementedException(); 357 } 358 CleanDataToggle(byte endpointNumber)359 public void CleanDataToggle(byte endpointNumber) 360 { 361 throw new NotImplementedException(); 362 } 363 ToggleDataToggle(byte endpointNumber)364 public void ToggleDataToggle(byte endpointNumber) 365 { 366 throw new NotImplementedException(); 367 } 368 GetDataToggle(byte endpointNumber)369 public bool GetDataToggle(byte endpointNumber) 370 { 371 throw new NotImplementedException(); 372 } 373 ClearFeature(USBPacket packet, USBSetupPacket setupPacket)374 public void ClearFeature(USBPacket packet, USBSetupPacket setupPacket) 375 { 376 throw new NotImplementedException(); 377 } 378 GetConfiguration()379 public byte[] GetConfiguration() 380 { 381 throw new NotImplementedException(); 382 } 383 GetInterface(USBPacket packet, USBSetupPacket setupPacket)384 public byte[] GetInterface(USBPacket packet, USBSetupPacket setupPacket) 385 { 386 throw new NotImplementedException(); 387 } 388 GetStatus(USBPacket packet, USBSetupPacket setupPacket)389 public byte[] GetStatus(USBPacket packet, USBSetupPacket setupPacket) 390 { 391 controlPacket = new byte[2]; 392 var recipient = (MessageRecipient)(setupPacket.requestType & 0x3); 393 switch(recipient) 394 { 395 case MessageRecipient.Device: 396 controlPacket[0] = (byte)(((configurationDescriptor.RemoteWakeup ? 1 : 0) << 1) | (configurationDescriptor.SelfPowered ? 1 : 0)); 397 break; 398 case MessageRecipient.Endpoint: 399 //TODO: endpoint halt status 400 goto default; 401 default: 402 controlPacket[0] = 0; 403 break; 404 } 405 return controlPacket; 406 } 407 SetAddress(uint address)408 public void SetAddress(uint address) 409 { 410 addr = address; 411 } 412 SetConfiguration(USBPacket packet, USBSetupPacket setupPacket)413 public void SetConfiguration(USBPacket packet, USBSetupPacket setupPacket) 414 { 415 // throw new NotImplementedException(); 416 } 417 SetDescriptor(USBPacket packet, USBSetupPacket setupPacket)418 public void SetDescriptor(USBPacket packet, USBSetupPacket setupPacket) 419 { 420 throw new NotImplementedException(); 421 } 422 SetFeature(USBPacket packet, USBSetupPacket setupPacket)423 public void SetFeature(USBPacket packet, USBSetupPacket setupPacket) 424 { 425 throw new NotImplementedException(); 426 } 427 SetInterface(USBPacket packet, USBSetupPacket setupPacket)428 public void SetInterface(USBPacket packet, USBSetupPacket setupPacket) 429 { 430 throw new NotImplementedException(); 431 } 432 SyncFrame(uint endpointId)433 public void SyncFrame(uint endpointId) 434 { 435 throw new NotImplementedException(); 436 } 437 WriteData(byte[] data)438 public void WriteData(byte[] data) 439 { 440 441 } 442 GetData()443 public byte[] GetData() 444 { 445 446 return null; 447 } 448 ProcessVendorGet(USBPacket packet, USBSetupPacket setupPacket)449 public byte[] ProcessVendorGet(USBPacket packet, USBSetupPacket setupPacket) 450 { 451 throw new NotImplementedException(); 452 } 453 ProcessVendorSet(USBPacket packet, USBSetupPacket setupPacket)454 public void ProcessVendorSet(USBPacket packet, USBSetupPacket setupPacket) 455 { 456 throw new NotImplementedException(); 457 } 458 #endregion 459 Init()460 void Init() 461 { 462 endpointDescriptor = new EndpointUSBDescriptor[NumberOfEndpoints]; 463 for(int i = 0; i < NumberOfEndpoints; i++) 464 { 465 endpointDescriptor[i] = new EndpointUSBDescriptor(); 466 } 467 FillEndpointsDescriptors(endpointDescriptor); 468 interfaceDescriptor[0].EndpointDescriptor = endpointDescriptor; 469 configurationDescriptor.InterfaceDescriptor = interfaceDescriptor; 470 inquiry.FillVendor("Generic "); 471 inquiry.FillIdentification("STORAGE DEVICE "); 472 inquiry.FillRevision("0207"); 473 oData = new List<byte>(); 474 } 475 476 #region Massage Data Structure 477 478 private Queue<byte[]> transmissionQueue = new Queue<byte[]>(); 479 480 #endregion 481 482 #region Device constans 483 private const byte MaxLun = 0; 484 private const byte NumberOfEndpoints = 2; 485 private const ushort EnglishLangId = 0x09; 486 487 #endregion 488 489 #region Mass Storage data structures 490 491 private class CommandBlockWrapper 492 { 493 Fill(byte[] data)494 public bool Fill(byte[] data) 495 { 496 if(data.Length != 31) 497 { 498 return false; 499 } 500 501 this.Signature = BitConverter.ToUInt32(data, 0); 502 503 if(this.Signature != ProperSignature) 504 { 505 return false; 506 } 507 this.Tag = BitConverter.ToUInt32(data, 4); 508 this.DataTransferLength = BitConverter.ToUInt32(data, 8); 509 this.Flags = data[12]; 510 this.LogicalUnitNumber = (byte)(data[13] & (byte)(0x0fu)); 511 this.Length = (byte)(data[14] & (byte)(0x1fu)); 512 513 return true; 514 } 515 516 private const uint ProperSignature = 0x43425355; 517 public uint Signature; 518 public uint Tag; 519 public uint DataTransferLength; 520 public byte Flags; 521 public byte LogicalUnitNumber; 522 public byte Length; 523 } 524 525 private class CommandStatusWrapper 526 { ToArray()527 public byte[] ToArray() 528 { 529 arr[0] = (byte)(CommandStatusWrapperSignature & 0xFF); 530 arr[1] = (byte)((CommandStatusWrapperSignature & 0xFF00) >> 8); 531 arr[2] = (byte)((CommandStatusWrapperSignature & 0xFF0000) >> 16); 532 arr[3] = (byte)((CommandStatusWrapperSignature & 0xFF000000) >> 24); 533 534 arr[4] = (byte)(Tag & 0xFF); 535 arr[5] = (byte)((Tag & 0xFF00) >> 8); 536 arr[6] = (byte)((Tag & 0xFF0000) >> 16); 537 arr[7] = (byte)((Tag & 0xFF000000) >> 24); 538 539 arr[8] = (byte)(DataResidue & 0xFF); 540 arr[9] = (byte)((DataResidue & 0xFF00) >> 8); 541 arr[10] = (byte)((DataResidue & 0xFF0000) >> 16); 542 arr[11] = (byte)((DataResidue & 0xFF000000) >> 24); 543 544 arr[12] = Status; 545 546 return arr; 547 } 548 private byte[] arr = new byte[13]; 549 private const uint CommandStatusWrapperSignature = 0x53425355; 550 public uint Tag; 551 public uint DataResidue; 552 public byte Status; 553 } 554 555 #endregion 556 557 #region USB descriptors 558 559 private ConfigurationUSBDescriptor configurationDescriptor = new ConfigurationUSBDescriptor 560 { 561 ConfigurationIndex = 0, 562 SelfPowered = false, 563 NumberOfInterfaces = 1, 564 RemoteWakeup = true, 565 MaxPower = 250, //500mA 566 ConfigurationValue = 1 567 }; 568 private ConfigurationUSBDescriptor otherConfigurationDescriptor = new ConfigurationUSBDescriptor(); 569 private StringUSBDescriptor stringDescriptor; 570 private StandardUSBDescriptor deviceDescriptor = new StandardUSBDescriptor 571 { 572 DeviceClass=0x00,//specified in interface descritor 573 DeviceSubClass = 0x00,//specified in interface descritor 574 USB = 0x0200, 575 DeviceProtocol = 0x00,//specified in interface descritor 576 MaxPacketSize = 64, 577 VendorId = 0x05e3, 578 ProductId = 0x0727, 579 Device = 0x0207, 580 ManufacturerIndex = 0, 581 ProductIndex = 0, 582 SerialNumberIndex = 0, 583 NumberOfConfigurations = 1 584 }; 585 private DeviceQualifierUSBDescriptor deviceQualifierDescriptor = new DeviceQualifierUSBDescriptor(); 586 private EndpointUSBDescriptor[] endpointDescriptor; 587 private InterfaceUSBDescriptor[] interfaceDescriptor = new[]{new InterfaceUSBDescriptor 588 { 589 AlternateSetting = 0, 590 InterfaceNumber = 0, 591 NumberOfEndpoints = NumberOfEndpoints, 592 InterfaceClass = 0x08, //vendor specific 593 InterfaceProtocol = 0x50, //Bulk only 594 InterfaceSubClass = 0x06, //SCSI transparent 595 InterfaceIndex = 0 596 } 597 }; 598 private Dictionary<ushort, string[]> stringValues = new Dictionary<ushort, string[]> 599 { 600 {EnglishLangId, new string[]{ 601 "", 602 "Mass Storage", 603 "0xALLMAN", 604 "Configuration", 605 "AntMicro" 606 }} 607 }; 608 FillEndpointsDescriptors(EndpointUSBDescriptor[] endpointDesc)609 private void FillEndpointsDescriptors(EndpointUSBDescriptor[] endpointDesc) 610 { 611 endpointDesc[0].EndpointNumber = 1; 612 endpointDesc[0].InEnpoint = true; 613 endpointDesc[0].TransferType = EndpointUSBDescriptor.TransferTypeEnum.Bulk; 614 endpointDesc[0].MaxPacketSize = 512; 615 endpointDesc[0].SynchronizationType = EndpointUSBDescriptor.SynchronizationTypeEnum.NoSynchronization; 616 endpointDesc[0].UsageType = EndpointUSBDescriptor.UsageTypeEnum.Data; 617 endpointDesc[0].Interval = 0; 618 619 endpointDesc[1].EndpointNumber = 2; 620 endpointDesc[1].InEnpoint = false; 621 endpointDesc[1].TransferType = EndpointUSBDescriptor.TransferTypeEnum.Bulk; 622 endpointDesc[1].MaxPacketSize = 512; 623 endpointDesc[1].SynchronizationType = EndpointUSBDescriptor.SynchronizationTypeEnum.NoSynchronization; 624 endpointDesc[1].UsageType = EndpointUSBDescriptor.UsageTypeEnum.Data; 625 endpointDesc[1].Interval = 0; 626 627 628 } 629 630 private SCSI.StandardInquiryData inquiry = new SCSI.StandardInquiryData//all data sniffed from real device 631 { 632 633 PeripheralQualifier = (byte)SCSI.PeripheralQualifier.Connected, 634 PeripheralDeviceType = (byte)SCSI.PeripheralDeviceType.DirectAccessBlockDevice, 635 RMB = true, 636 Version = (byte)SCSI.VersionCode.NotStandard, 637 NormalACASupport = false, 638 HierachicalSupport = false, 639 ResponseDataFormat = 0x00, 640 AdditionalLength = 0x29, 641 SCCSupport = false, 642 AccessControlsCoordintor = false, 643 TargetPortGroupSupport = 0x00, 644 ThirdPartyCopy = false, 645 Protect = false, 646 BasingQueuing = false, 647 EnclosureServices = false, 648 VS1 = false, 649 MultiPort = false, 650 MediumChanger = false, 651 ADDR16 = false, 652 WBUS16a = false, 653 Sync = false, 654 LinkedCommand = false, 655 VS2 = false 656 657 }; 658 659 private enum MassStorageRequestCode 660 { 661 AcceptDeviceSpecificCommand = 0x00, 662 GetRequest = 0xFC, 663 PutRequest = 0xFD, 664 GetMaxLUN = 0xFE, 665 MassStorageReset = 0xFE//Bulk Only 666 } 667 #endregion 668 669 #region lba backend 670 671 private LBABackend lbaBackend; 672 private CommandStatusWrapper writeCSW; 673 private SCSI.CommandDescriptorBlock writeCDB; 674 private bool writeFlag; 675 676 #endregion 677 678 679 } 680 681 } 682