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;
            }
        }