public void WriteDataBulk(USBPacket packet) { if (packet.data != null && packet.bytesToTransfer != 31) { oData.AddRange(packet.data); } else if (packet.bytesToTransfer == 31 || oData.Count > 0) { byte[] data; var cbw = new CommandBlockWrapper(); var cdb = new SCSI.CommandDescriptorBlock(); if (packet.bytesToTransfer == 31) { data = packet.data; } else { data = oData.ToArray(); oData.Clear(); } if (!cbw.Fill(data)) { if (writeFlag) { writeFlag = false; lbaBackend.Write((int)writeCDB.LogicalBlockAddress, data, (int)writeCDB.TransferLength); writeCSW.DataResidue -= (uint)(data.Length); transmissionQueue.Enqueue(writeCSW.ToArray()); } else { //throw new InvalidOperationException ("Corrupted Command Block Wrapper"); this.Log(LogLevel.Warning, "Corrupted Command Block Wrapper"); } } else { ReceiveCommandBlockWrapper(cbw, cdb, data); } } }
void ReceiveCommandBlockWrapper(CommandBlockWrapper cbw, SCSI.CommandDescriptorBlock cdb, byte[] data) { this.DebugLog("Received Command Block Wrapper"); var csw = new CommandStatusWrapper(); var cdbData = new byte[cbw.Length]; Array.Copy(data, 15, cdbData, 0, cbw.Length); cdb.Fill(cdbData); switch ((SCSI.CommandDescriptorBlock.GroupCode)cdb.OperationCode) { case SCSI.CommandDescriptorBlock.GroupCode.Inquiry: csw.Tag = cbw.Tag; csw.DataResidue = 0x00; csw.Status = 0x00; transmissionQueue.Enqueue(inquiry.ToArray()); //enqueue inquiry data transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.ModeSense: var msc = new SCSI.ModeSenseCommand(); msc.Fill(cdbData); var retArr = new byte[192]; retArr[0] = 0x03; //FIXME: probably it should return sth with more sense csw.Tag = cbw.Tag; csw.DataResidue = cbw.DataTransferLength - 0x03; csw.Status = 0x00; transmissionQueue.Enqueue(retArr); transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.PreventAllowMediumRemoval: csw.Tag = cbw.Tag; csw.DataResidue = 0x00; csw.Status = 0x00; transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.Read10: var dataRead = lbaBackend.Read((int)cdb.LogicalBlockAddress, (int)cdb.TransferLength); csw.Tag = cbw.Tag; csw.DataResidue = (uint)(cbw.DataTransferLength - dataRead.Length); csw.Status = 0x00; transmissionQueue.Enqueue(dataRead); transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.Write10: writeFlag = true; //next write command could be data csw.Tag = cbw.Tag; csw.DataResidue = cbw.DataTransferLength; csw.Status = 0x00; writeCSW = csw; writeCDB = cdb; //transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.ReadCapacity: var capData = new SCSI.CapacityDataStructure(); capData.ReturnedLBA = (uint)lbaBackend.NumberOfBlocks - 1; capData.BlockLength = (uint)lbaBackend.BlockSize; csw.Tag = cbw.Tag; csw.DataResidue = 0x00; csw.Status = 0x00; transmissionQueue.Enqueue(capData.ToArray()); transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.RequestSense: // TODO: this was copied from TestUnitReady. do a proper implementation csw.Tag = cbw.Tag; csw.DataResidue = 0x00; csw.Status = 0x00; transmissionQueue.Enqueue(csw.ToArray()); break; case SCSI.CommandDescriptorBlock.GroupCode.TestUnitReady: csw.Tag = cbw.Tag; csw.DataResidue = 0x00; csw.Status = 0x00; transmissionQueue.Enqueue(csw.ToArray()); break; default: this.Log(LogLevel.Warning, "Unsuported Command Code: 0x{0:X}", cdb.OperationCode); break; } }