// Path: src/main/java/com/felhr/usbmassstorageforandroid/utilities/EndianessUtil.java
// public class EndianessUtil
// {
//     private EndianessUtil()
//     {
// 
//     }
// 
//     public static int swapEndianess(int i)
//     {
//         return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
//     }
// }
// 
// Path: src/main/java/commandwrappers/CommandBlockWrapper.java
// public class CommandBlockWrapper extends CommandWrapper
// {
//     private int dCBWSignature;
//     private int dCBWTag;
//     private int dCBWDataLength;
//     private byte bmCBWFlags;
//     private byte bCBWLUN;
//     private byte bCBWCBLength;
//     private byte[] commandBlock;
// 
// 
//     public CommandBlockWrapper(int dCBWSignature, int dCBWTag, int dCBWDataLength,
//                                byte bmCBWFlags, byte bCBWLUN, byte bCBWCBLength)
//     {
//         this.dCBWSignature = dCBWSignature;
//         this.dCBWTag = dCBWTag;
//         this.dCBWDataLength = dCBWDataLength;
//         this.bmCBWFlags = bmCBWFlags;
//         this.bCBWLUN = bCBWLUN;
//         this.bCBWCBLength = bCBWCBLength;
//     }
// 
//     public CommandBlockWrapper( int dCBWDataLength,
//                                 byte bmCBWFlags, byte bCBWLUN, byte bCBWCBLength)
//     {
//         this.dCBWSignature = CommandWrapper.CBW_SIGNATURE;
//         this.dCBWTag = generateTag();
//         this.dCBWDataLength = dCBWDataLength;
//         this.bmCBWFlags = bmCBWFlags;
//         this.bCBWLUN = bCBWLUN;
//         this.bCBWCBLength = bCBWCBLength;
//     }
// 
//     public void setCommandBlock(byte[] commandBlock)
//     {
//         this.commandBlock = commandBlock;
//     }
// 
//     public int getdCBWDataLength()
//     {
//         return dCBWDataLength;
//     }
// 
//     public int generateTag()
//     {
//         Random random = new Random();
//         return random.nextInt();
//     }
// 
//     @Override
//     public byte[] getCWBuffer()
//     {
//         ByteBuffer buffer = ByteBuffer.allocate(CBW_SIZE);
//         buffer.putInt(EndianessUtil.swapEndianess(dCBWSignature));
//         buffer.putInt(dCBWTag);
//         buffer.putInt(EndianessUtil.swapEndianess(dCBWDataLength));
//         buffer.put(bmCBWFlags);
//         buffer.put(bCBWLUN);
//         buffer.put(bCBWCBLength);
//         buffer.put(commandBlock);
//         return buffer.array();
//     }
// }
// 
// Path: src/main/java/commandwrappers/CommandWrapper.java
// public abstract class CommandWrapper
// {
//     public static final int CBW_SIGNATURE = 0x43425355;
//     public static final int CBS_SIGNATURE = 0x53425355;
//     public static final int CBW_SIZE = 31;
//     public static final int CBS_SIZE = 13;
// 
//     public CommandWrapper()
//     {
// 
//     }
// 
//     public abstract byte[] getCWBuffer();
// 
// 
//     protected class CommandBlock
//     {
//         // 128 bit command instruction
//         private int data1; // Most Significant
//         private int data2;
//         private int data3;
//         private int data4; // Less Significant
// 
//         public CommandBlock(int data1, int data2, int data3, int data4)
//         {
//             this.data1 = data1;
//             this.data2 = data2;
//             this.data3 = data3;
//             this.data4 = data4;
//         }
// 
//         public byte[] getBuffer()
//         {
//             ByteBuffer buffer = ByteBuffer.allocate(4);
//             buffer.putInt(data1);
//             buffer.putInt(data2);
//             buffer.putInt(data3);
//             buffer.putInt(data4);
//             return buffer.array();
//         }
// 
//     }
// 
// }


import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.felhr.usbmassstorageforandroid.utilities.EndianessUtil;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import commandwrappers.CommandBlockWrapper;
import commandwrappers.CommandWrapper;
    private class DataInThread extends Thread
    {
        private byte[] buffer;
        private AtomicBoolean keep;
        private AtomicBoolean waiting;

        public DataInThread()
        {
            this.buffer = new byte[USB_ENDPOINT_LENGTH];
            this.keep = new AtomicBoolean(true);
            this.waiting = new AtomicBoolean(true);
        }

        @Override
        public void run()
        {
            waitTillBufferSet();
            while(keep.get())
            {
                int response = mConnection.bulkTransfer(inEndpoint, buffer, USB_IN_BUFFER_LENGTH, 0);

                if(response > 0)
                {
                    byte[] receivedData = new byte[response];
                    System.arraycopy(buffer, 0, receivedData, 0, response);
                    int cswSignature = 0;
                    if(response == CommandWrapper.CBS_SIZE)
                        cswSignature = EndianessUtil.swapEndianess(
                                ByteBuffer.wrap(Arrays.copyOfRange(receivedData, 0, 4)).getInt());

// Path: src/main/java/com/felhr/usbmassstorageforandroid/utilities/EndianessUtil.java
// public class EndianessUtil
// {
//     private EndianessUtil()
//     {
// 
//     }
// 
//     public static int swapEndianess(int i)
//     {
//         return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff);
//     }
// }
// 
// Path: src/main/java/commandwrappers/CommandBlockWrapper.java
// public class CommandBlockWrapper extends CommandWrapper
// {
//     private int dCBWSignature;
//     private int dCBWTag;
//     private int dCBWDataLength;
//     private byte bmCBWFlags;
//     private byte bCBWLUN;
//     private byte bCBWCBLength;
//     private byte[] commandBlock;
// 
// 
//     public CommandBlockWrapper(int dCBWSignature, int dCBWTag, int dCBWDataLength,
//                                byte bmCBWFlags, byte bCBWLUN, byte bCBWCBLength)
//     {
//         this.dCBWSignature = dCBWSignature;
//         this.dCBWTag = dCBWTag;
//         this.dCBWDataLength = dCBWDataLength;
//         this.bmCBWFlags = bmCBWFlags;
//         this.bCBWLUN = bCBWLUN;
//         this.bCBWCBLength = bCBWCBLength;
//     }
// 
//     public CommandBlockWrapper( int dCBWDataLength,
//                                 byte bmCBWFlags, byte bCBWLUN, byte bCBWCBLength)
//     {
//         this.dCBWSignature = CommandWrapper.CBW_SIGNATURE;
//         this.dCBWTag = generateTag();
//         this.dCBWDataLength = dCBWDataLength;
//         this.bmCBWFlags = bmCBWFlags;
//         this.bCBWLUN = bCBWLUN;
//         this.bCBWCBLength = bCBWCBLength;
//     }
// 
//     public void setCommandBlock(byte[] commandBlock)
//     {
//         this.commandBlock = commandBlock;
//     }
// 
//     public int getdCBWDataLength()
//     {
//         return dCBWDataLength;
//     }
// 
//     public int generateTag()
//     {
//         Random random = new Random();
//         return random.nextInt();
//     }
// 
//     @Override
//     public byte[] getCWBuffer()
//     {
//         ByteBuffer buffer = ByteBuffer.allocate(CBW_SIZE);
//         buffer.putInt(EndianessUtil.swapEndianess(dCBWSignature));
//         buffer.putInt(dCBWTag);
//         buffer.putInt(EndianessUtil.swapEndianess(dCBWDataLength));
//         buffer.put(bmCBWFlags);
//         buffer.put(bCBWLUN);
//         buffer.put(bCBWCBLength);
//         buffer.put(commandBlock);
//         return buffer.array();
//     }
// }
// 
// Path: src/main/java/commandwrappers/CommandWrapper.java
// public abstract class CommandWrapper
// {
//     public static final int CBW_SIGNATURE = 0x43425355;
//     public static final int CBS_SIGNATURE = 0x53425355;
//     public static final int CBW_SIZE = 31;
//     public static final int CBS_SIZE = 13;
// 
//     public CommandWrapper()
//     {
// 
//     }
// 
//     public abstract byte[] getCWBuffer();
// 
// 
//     protected class CommandBlock
//     {
//         // 128 bit command instruction
//         private int data1; // Most Significant
//         private int data2;
//         private int data3;
//         private int data4; // Less Significant
// 
//         public CommandBlock(int data1, int data2, int data3, int data4)
//         {
//             this.data1 = data1;
//             this.data2 = data2;
//             this.data3 = data3;
//             this.data4 = data4;
//         }
// 
//         public byte[] getBuffer()
//         {
//             ByteBuffer buffer = ByteBuffer.allocate(4);
//             buffer.putInt(data1);
//             buffer.putInt(data2);
//             buffer.putInt(data3);
//             buffer.putInt(data4);
//             return buffer.array();
//         }
// 
//     }
// 
// }


// Path: src/main/java/com/felhr/usbmassstorageforandroid/bulkonly/UsbFacade.java
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.felhr.usbmassstorageforandroid.utilities.EndianessUtil;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;
import commandwrappers.CommandBlockWrapper;
import commandwrappers.CommandWrapper;

    private class DataInThread extends Thread
    {
        private byte[] buffer;
        private AtomicBoolean keep;
        private AtomicBoolean waiting;

        public DataInThread()
        {
            this.buffer = new byte[USB_ENDPOINT_LENGTH];
            this.keep = new AtomicBoolean(true);
            this.waiting = new AtomicBoolean(true);
        }

        @Override
        public void run()
        {
            waitTillBufferSet();
            while(keep.get())
            {
                int response = mConnection.bulkTransfer(inEndpoint, buffer, USB_IN_BUFFER_LENGTH, 0);

                if(response > 0)
                {
                    byte[] receivedData = new byte[response];
                    System.arraycopy(buffer, 0, receivedData, 0, response);
                    int cswSignature = 0;
                    if(response == CommandWrapper.CBS_SIZE)
                        cswSignature = EndianessUtil.swapEndianess(
                                ByteBuffer.wrap(Arrays.copyOfRange(receivedData, 0, 4)).getInt());

                    if(receivedData.length == CommandWrapper.CBS_SIZE && cswSignature == CommandBlockWrapper.CBS_SIGNATURE) // It is a CSW