org.usb4java.DeviceHandle - java examples

Here are the examples of the java api org.usb4java.DeviceHandle taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

71 Examples 7

19 View Complete Implementation : ATCFpgaConfig.java
Copyright GNU Lesser General Public License v2.1
Author : SensorsINI
public clreplaced ATCFpgaConfig extends EventFilter2D {

    private int trackerId = getInt("trackerId", 1);

    private int cmCellInitX = getInt("cmCellInitX", 64);

    private int cmCellInitY = getInt("cmCellInitY", 64);

    private int cmCellRadixStep = getInt("cmCellRadixStep", 7);

    private int cmCellRadixTH = getInt("cmCellRadixTH", 7);

    private int cmCellInitRadix = getInt("cmCellInitRadix", 63);

    private int cmCellRadixMax = getInt("cmCellRadixMax", 127);

    private int cmCellRadixMin = getInt("cmCellRadixMin", 1);

    private int cmCellMaxTime = getInt("cmCellMaxTime", 200000);

    private int cmCellNevTh = getInt("cmCellNevTh", 10);

    private int cmCellAVG = getInt("cmCellAVG", 1);

    private boolean trackerEnable = getBoolean("trackerEnable", true);

    private boolean Reset = getBoolean("Reset", false);

    private int bgaFilterDeltaT = getInt("bgaFilterDeltaT", 100);

    private int bgaNeighbors = getInt("bgaNeighbors", 8);

    // OMC parameters
    private int IFthreshold = getInt("IFthreshold", 5);

    private int DecayTimeMs = getInt("DecayTimeMs", 2);

    private int TauNDecay = getInt("TauNDecay_S", 20);

    private int ExcitationStrength = getInt("ExcitationStrength", 1);

    private int Saturation = getInt("Saturation", 1);

    private int InhibitionStrength = getInt("InhibitionStrength", 1);

    // FPGA clock speed in MegaHertz (MHz) for time conversion.
    private final int CLOCK_SPEED = 50;

    public ATCFpgaConfig(final AEChip chip) {
        super(chip);
        initFilter();
        final String omc = "1) OMC", obt = "2) OBT", bga = "3) BGA";
        setPropertyTooltip(obt, "trackerId", "ID of the tracker to configure.");
        setPropertyTooltip(obt, "cmCellInitX", "Initial focus point (X axis).");
        setPropertyTooltip(obt, "cmCellInitY", "Initial focus point (Y axis).");
        setPropertyTooltip(obt, "cmCellRadixStep", "Step lenght for increasing cluster area dynamically.");
        setPropertyTooltip(obt, "cmCellRadixTH", "Threshold for increasing cluster area dynamically.");
        setPropertyTooltip(obt, "cmCellInitRadix", "Initial cluster radix.");
        setPropertyTooltip(obt, "cmCellRadixMax", "Maximmum cluster radix.");
        setPropertyTooltip(obt, "cmCellRadixMin", "Minimmum cluster radix.");
        setPropertyTooltip(obt, "cmCellMaxTime", "Maximum allowed delay without detecting events for current tracking (in �s). Once elapsed cell will reset itself.");
        setPropertyTooltip(obt, "cmCellNevTh", "Number of events to receive within a cluster before calculating center of mreplaced.");
        setPropertyTooltip(obt, "cmCellAVG", "Amount of CM history involved in calculating the average for the new CM point (2^cmCellAVG).");
        setPropertyTooltip(obt, "trackerEnable", "Enable this tracker.");
        setPropertyTooltip(obt, "Reset", "Global Reset.");
        setPropertyTooltip(bga, "bgaFilterDeltaT", "Delta time for BackgroundActivity filter (in �s).");
        setPropertyTooltip(bga, "bgaNeighbors", "Number of neighbors to correlate the BackgroundActivity filter (top-down and left-right).");
        // OMC parameters
        setPropertyTooltip(omc, "IFthreshold", "Integrate and Fire threshold of OMCs");
        setPropertyTooltip(omc, "DecayTimeMs", "Time intervals at which the subunits of the OMC are decayed");
        setPropertyTooltip(omc, "ExcitationStrength", "Factor that multiplies normalised excitation");
        setPropertyTooltip(omc, "Saturation", "Saturation of subunits");
        setPropertyTooltip(omc, "InhibitionStrength", "Factor that multiplies normalised inhibition");
        setPropertyTooltip(omc, "TauNDecay", "Neuron time constant of decay");
    }

    // OMC parameters
    public void setIFthreshold(final int IFthreshold) {
        this.IFthreshold = IFthreshold;
        putInt("IFthreshold", IFthreshold);
    }

    public int getIFthreshold() {
        return IFthreshold;
    }

    public void setTauNDecay(final int TauNDecay) {
        this.TauNDecay = TauNDecay;
        putInt("TauNDecay", TauNDecay);
    }

    public int getTauNDecay() {
        return TauNDecay;
    }

    public static int getMinIFthreshold() {
        return 0;
    }

    public static int getMaxIFthreshold() {
        return 33554431;
    }

    public void setDecayTimeMs(final int DecayTimeMs) {
        this.DecayTimeMs = DecayTimeMs;
        putInt("DecayTimeMs", DecayTimeMs);
    }

    public int getDecayTimeMs() {
        return DecayTimeMs;
    }

    public static int getMinDecayTimeMs() {
        return 0;
    }

    public static int getMaxDecayTimeMs() {
        return (2147483647 * 50 * 10 ^ (-6));
    }

    public void setExcitationStrength(final int ExcitationStrength) {
        this.ExcitationStrength = ExcitationStrength;
        putInt("ExcitationStrength", ExcitationStrength);
    }

    public int getExcitationStrength() {
        return ExcitationStrength;
    }

    public static int getMinExcitationStrength() {
        return 0;
    }

    public static int getMaxExcitationStrength() {
        return 128;
    }

    public void setSaturation(final int Saturation) {
        this.Saturation = Saturation;
        putInt("Saturation", Saturation);
    }

    public int getSaturation() {
        return Saturation;
    }

    public static int getMinSaturation() {
        return 1;
    }

    public static int getMaxSaturation() {
        return 128;
    }

    public void setInhibitionStrength(final int InhibitionStrength) {
        this.InhibitionStrength = InhibitionStrength;
        putInt("InhibitionStrength", InhibitionStrength);
    }

    public int getInhibitionStrength() {
        return InhibitionStrength;
    }

    public static int getMinInhibitionStrength() {
        return 0;
    }

    public static int getMaxInhibitionStrength() {
        return 128;
    }

    // End of OMC parameters
    // End of Configuration of OMC
    synchronized public void doConfigureOMC() {
        // Verify that we have a USB device to send to.
        if (devHandle == null) {
            return;
        }
        // Convert ms time into clock cycles.
        final int sendDecayTimeMs = getInt("DecayTimeMs", 0) / (CLOCK_SPEED * 10 ^ (-6));
        final int sendTauNDecay = getInt("TauNDecay", 0) / (CLOCK_SPEED * 10 ^ (-6));
        int sendExcitationStrength = 1;
        if (getInt("ExcitationStrength", 0) == 0) {
            sendExcitationStrength = 0;
        } else if (getInt("ExcitationStrength", 0) == 1) {
            sendExcitationStrength = 1;
        } else if (getInt("ExcitationStrength", 0) >= 2 && getInt("ExcitationStrength", 0) < 4) {
            sendExcitationStrength = 2;
        } else if (getInt("ExcitationStrength", 0) >= 4 && getInt("ExcitationStrength", 0) < 8) {
            sendExcitationStrength = 4;
        } else if (getInt("ExcitationStrength", 0) >= 8 && getInt("ExcitationStrength", 0) < 16) {
            sendExcitationStrength = 8;
        } else if (getInt("ExcitationStrength", 0) >= 16 && getInt("ExcitationStrength", 0) < 32) {
            sendExcitationStrength = 16;
        } else if (getInt("ExcitationStrength", 0) >= 32 && getInt("ExcitationStrength", 0) < 64) {
            sendExcitationStrength = 32;
        } else if (getInt("ExcitationStrength", 0) >= 64 && getInt("ExcitationStrength", 0) < 128) {
            sendExcitationStrength = 64;
        } else if (getInt("ExcitationStrength", 0) == 128) {
            sendExcitationStrength = 128;
        }
        int sendSaturation = 1;
        if (getInt("Saturation", 0) == 1) {
            sendSaturation = 1;
        } else if (getInt("Saturation", 0) >= 2 && getInt("Saturation", 0) < 4) {
            sendSaturation = 2;
        } else if (getInt("Saturation", 0) >= 4 && getInt("Saturation", 0) < 8) {
            sendSaturation = 4;
        } else if (getInt("Saturation", 0) >= 8 && getInt("Saturation", 0) < 16) {
            sendSaturation = 8;
        } else if (getInt("Saturation", 0) >= 16 && getInt("Saturation", 0) < 32) {
            sendSaturation = 16;
        } else if (getInt("Saturation", 0) >= 32 && getInt("Saturation", 0) < 64) {
            sendSaturation = 32;
        } else if (getInt("Saturation", 0) >= 64 && getInt("Saturation", 0) < 128) {
            sendSaturation = 64;
        } else if (getInt("Saturation", 0) == 128) {
            sendSaturation = 128;
        }
        int sendInhibitionStrength = 1;
        if (getInt("InhibitionStrength", 0) == 0) {
            sendInhibitionStrength = 0;
        } else if (getInt("InhibitionStrength", 0) == 1) {
            sendInhibitionStrength = 1;
        } else if (getInt("InhibitionStrength", 0) >= 2 && getInt("InhibitionStrength", 0) < 4) {
            sendInhibitionStrength = 2;
        } else if (getInt("InhibitionStrength", 0) >= 4 && getInt("InhibitionStrength", 0) < 8) {
            sendInhibitionStrength = 4;
        } else if (getInt("InhibitionStrength", 0) >= 8 && getInt("InhibitionStrength", 0) < 16) {
            sendInhibitionStrength = 8;
        } else if (getInt("InhibitionStrength", 0) >= 16 && getInt("InhibitionStrength", 0) < 32) {
            sendInhibitionStrength = 16;
        } else if (getInt("InhibitionStrength", 0) >= 32 && getInt("InhibitionStrength", 0) < 64) {
            sendInhibitionStrength = 32;
        } else if (getInt("InhibitionStrength", 0) >= 64 && getInt("InhibitionStrength", 0) < 128) {
            sendInhibitionStrength = 64;
        } else if (getInt("InhibitionStrength", 0) == 128) {
            sendInhibitionStrength = 128;
        }
        for (int i = 0; i <= 5; i++) {
            // Send all the OMC configuration.
            // F0 240
            sendCommand((byte) 240, (byte) (IFthreshold & 0xFF), true);
            // F1 241
            sendCommand((byte) 241, (byte) ((IFthreshold >>> 8) & 0xFF), true);
            // F2 242
            sendCommand((byte) 242, (byte) ((IFthreshold >>> 16) & 0xFF), true);
            // F3 243
            sendCommand((byte) 243, (byte) ((IFthreshold >>> 24) & 0xFF), true);
            // F4 244
            sendCommand((byte) 244, (byte) (sendDecayTimeMs & 0xFF), true);
            // F5 245
            sendCommand((byte) 245, (byte) ((sendDecayTimeMs >>> 8) & 0xFF), true);
            // F6 246
            sendCommand((byte) 246, (byte) ((sendDecayTimeMs >>> 16) & 0xFF), true);
            // F7 247
            sendCommand((byte) 247, (byte) ((sendDecayTimeMs >>> 24) & 0xFF), true);
            // F8 248
            sendCommand((byte) 248, (byte) (sendExcitationStrength & 0xFF), true);
            // F9 249
            sendCommand((byte) 249, (byte) (sendSaturation & 0xFF), true);
            // FA 250
            sendCommand((byte) 250, (byte) (sendInhibitionStrength & 0xFF), true);
            // FB 251
            sendCommand((byte) 251, (byte) (sendTauNDecay & 0xFF), true);
            // FB 252
            sendCommand((byte) 252, (byte) ((sendTauNDecay >>> 8) & 0xFF), true);
            // FB 253
            sendCommand((byte) 253, (byte) ((sendTauNDecay >>> 16) & 0xFF), true);
            // FB 25
            sendCommand((byte) 254, (byte) ((sendTauNDecay >>> 24) & 0xFF), true);
            sendCommand((byte) 0, (byte) 0, false);
            System.out.print("Sending ");
            System.out.println(i);
        }
    }

    // End of Configuration of OMC
    public int getTrackerId() {
        return trackerId;
    }

    public static int getMinTrackerId() {
        return 1;
    }

    public static int getMaxTrackerId() {
        return 4;
    }

    public void setTrackerId(final int trackerId) {
        this.trackerId = trackerId;
        putInt("trackerId", trackerId);
    }

    public int getCmCellInitX() {
        return cmCellInitX;
    }

    public static int getMinCmCellInitX() {
        return 0;
    }

    public static int getMaxCmCellInitX() {
        return 127;
    }

    public void setCmCellInitX(final int cmCellInitX) {
        this.cmCellInitX = cmCellInitX;
        putInt("cmCellInitX", cmCellInitX);
    }

    public int getCmCellInitY() {
        return cmCellInitY;
    }

    public static int getMinCmCellInitY() {
        return 0;
    }

    public static int getMaxCmCellInitY() {
        return 127;
    }

    public void setCmCellInitY(final int cmCellInitY) {
        this.cmCellInitY = cmCellInitY;
        putInt("cmCellInitY", cmCellInitY);
    }

    public int getCmCellRadixStep() {
        return cmCellRadixStep;
    }

    public static int getMinCmCellRadixStep() {
        return 0;
    }

    public static int getMaxCmCellRadixStep() {
        return 7;
    }

    public void setCmCellRadixStep(final int cmCellRadixStep) {
        this.cmCellRadixStep = cmCellRadixStep;
        putInt("cmCellRadixStep", cmCellRadixStep);
    }

    public int getCmCellRadixTH() {
        return cmCellRadixTH;
    }

    public static int getMinCmCellRadixTH() {
        return 0;
    }

    public static int getMaxCmCellRadixTH() {
        return 7;
    }

    public void setCmCellRadixTH(final int cmCellRadixTH) {
        this.cmCellRadixTH = cmCellRadixTH;
        putInt("cmCellRadixTH", cmCellRadixTH);
    }

    public int getCmCellInitRadix() {
        return cmCellInitRadix;
    }

    public static int getMinCmCellInitRadix() {
        return 0;
    }

    public static int getMaxCmCellInitRadix() {
        return 127;
    }

    public void setCmCellInitRadix(final int cmCellInitRadix) {
        this.cmCellInitRadix = cmCellInitRadix;
        putInt("cmCellInitRadix", cmCellInitRadix);
    }

    public int getCmCellRadixMin() {
        return cmCellRadixMin;
    }

    public static int getMinCmCellRadixMin() {
        return 0;
    }

    public static int getMaxCmCellRadixMin() {
        return 127;
    }

    public void setCmCellRadixMin(final int cmCellRadixMin) {
        this.cmCellRadixMin = cmCellRadixMin;
        putInt("cmCellRadixMin", cmCellRadixMin);
    }

    public int getCmCellRadixMax() {
        return cmCellRadixMax;
    }

    public static int getMinCmCellRadixMax() {
        return 0;
    }

    public static int getMaxCmCellRadixMax() {
        return 127;
    }

    public void setCmCellRadixMax(final int cmCellRadixMax) {
        this.cmCellRadixMax = cmCellRadixMax;
        putInt("cmCellRadixMax", cmCellRadixMax);
    }

    public int getCmCellMaxTime() {
        return cmCellMaxTime;
    }

    public static int getMinCmCellMaxTime() {
        // 1 micro-second (in �s).
        return 1;
    }

    public static int getMaxCmCellMaxTime() {
        // 1 second (in �s).
        return 1000000;
    }

    public void setCmCellMaxTime(final int cmCellMaxTime) {
        this.cmCellMaxTime = cmCellMaxTime;
        putInt("cmCellMaxTime", cmCellMaxTime);
    }

    public int getCmCellNevTh() {
        return cmCellNevTh;
    }

    public static int getMinCmCellNevTh() {
        return 1;
    }

    public static int getMaxCmCellNevTh() {
        return 1000;
    }

    public void setCmCellNevTh(final int cmCellNevTh) {
        this.cmCellNevTh = cmCellNevTh;
        putInt("cmCellNevTh", cmCellNevTh);
    }

    public int getCmCellAVG() {
        return cmCellAVG;
    }

    public static int getMinCmCellAVG() {
        return 1;
    }

    public static int getMaxCmCellAVG() {
        return 8;
    }

    public void setCmCellAVG(final int cmCellAVG) {
        this.cmCellAVG = cmCellAVG;
        putInt("cmCellAVG", cmCellAVG);
    }

    public boolean isTrackerEnable() {
        return trackerEnable;
    }

    public void setTrackerEnable(final boolean trackerEnable) {
        this.trackerEnable = trackerEnable;
        putBoolean("trackerEnable", trackerEnable);
    }

    public boolean isReset() {
        return Reset;
    }

    public void setReset(final boolean Reset) {
        this.Reset = Reset;
        putBoolean("Reset", Reset);
    }

    synchronized public void doConfigureCMCell() {
        // Verify that we have a USB device to send to.
        if (devHandle == null) {
            return;
        }
        // Convert time into cycles.
        final int cmCellMaxTimeCycles = getInt("cmCellMaxTime", 0) * CLOCK_SPEED;
        // Select the tracker.
        sendCommand((byte) 127, (byte) (getInt("trackerId", 0) & 0xFF), true);
        // Send all the tracker configuration.
        sendCommand((byte) 78, (byte) ((128 - getInt("cmCellInitY", 0)) & 0xFF), true);
        sendCommand((byte) 79, (byte) ((getInt("cmCellInitX", 0) + 128) & 0xFF), true);
        sendCommand((byte) 80, (byte) (getInt("cmCellRadixTH", 0) & 0xFF), true);
        sendCommand((byte) 81, (byte) (getInt("cmCellInitRadix", 0) & 0xFF), true);
        sendCommand((byte) 82, (byte) (cmCellMaxTimeCycles & 0xFF), true);
        sendCommand((byte) 83, (byte) ((cmCellMaxTimeCycles >>> 8) & 0xFF), true);
        sendCommand((byte) 84, (byte) ((cmCellMaxTimeCycles >>> 16) & 0xFF), true);
        sendCommand((byte) 85, (byte) ((cmCellMaxTimeCycles >>> 24) & 0xFF), true);
        sendCommand((byte) 86, (byte) (getInt("cmCellNevTh", 0) & 0xFF), true);
        sendCommand((byte) 87, (byte) (getInt("cmCellAVG", 0) & 0xFF), true);
        sendCommand((byte) 88, (byte) ((getBoolean("trackerEnable", true)) ? (0xFF) : (0x00)), true);
        sendCommand((byte) 89, (byte) (getInt("cmCellRadixStep", 0) & 0xFF), true);
        sendCommand((byte) 90, (byte) (getInt("cmCellRadixMax", 0) & 0xFF), true);
        sendCommand((byte) 91, (byte) (getInt("cmCellRadixMin", 0) & 0xFF), true);
        // Disable tracker configuration.
        sendCommand((byte) 127, (byte) 0xFF, true);
        sendCommand((byte) 0, (byte) 0, false);
    }

    public int getBgaFilterDeltaT() {
        return bgaFilterDeltaT;
    }

    public static int getMinBgaFilterDeltaT() {
        // 1 micro-second (in �s).
        return 1;
    }

    public static int getMaxBgaFilterDeltaT() {
        // 1 second (in �s).
        return 1000000;
    }

    public void setBgaFilterDeltaT(final int bgaFilterDeltaT) {
        this.bgaFilterDeltaT = bgaFilterDeltaT;
        putInt("bgaFilterDeltaT", bgaFilterDeltaT);
    }

    public int getBgaNeighbors() {
        return bgaNeighbors;
    }

    public static int getMinBgaNeighbors() {
        // No neighbors.
        return 0;
    }

    public static int getMaxBgaNeighbors() {
        // All closest neighbors.
        return 8;
    }

    public void setBgaNeighbors(final int bgaNeighbors) {
        this.bgaNeighbors = bgaNeighbors;
        putInt("bgaNeighbors", bgaNeighbors);
    }

    synchronized public void doConfigureBGAFilter() {
        // Verify that we have a USB device to send to.
        if (devHandle == null) {
            return;
        }
        // Convert time into cycles.
        final int bgaFilterDeltaTCycles = getInt("bgaFilterDeltaT", 0) * CLOCK_SPEED;
        // Send the four bytes that make up the integer to their respective
        // addresses.
        sendCommand((byte) 128, (byte) (bgaFilterDeltaTCycles & 0xFF), true);
        sendCommand((byte) 129, (byte) ((bgaFilterDeltaTCycles >>> 8) & 0xFF), true);
        sendCommand((byte) 130, (byte) ((bgaFilterDeltaTCycles >>> 16) & 0xFF), true);
        sendCommand((byte) 131, (byte) ((bgaFilterDeltaTCycles >>> 24) & 0xFF), true);
        sendCommand((byte) 135, (byte) (getInt("bgaNeighbors", 0) & 0xFF), true);
        sendCommand((byte) 136, (byte) ((getBoolean("Reset", true)) ? (0xFF) : (0x00)), true);
        setReset(false);
        sendCommand((byte) 0, (byte) 0, false);
    }

    @Override
    public EventPacket<?> filterPacket(final EventPacket<?> in) {
        // Don't modify events and packets going through.
        return (in);
    }

    // The SiLabs C8051F320 used by ATC has VID=0xC410 and PID=0x0000.
    private final short VID = (short) 0x10C4;

    private final short PID = 0x0000;

    private final byte ENDPOINT = 0x02;

    private final int PACKET_LENGTH = 64;

    private DeviceHandle devHandle = null;

    private void openDevice() {
        System.out.println("Searching for device.");
        // Already opened.
        if (devHandle != null) {
            return;
        }
        // Search for a suitable device and connect to it.
        LibUsb.init(null);
        final DeviceList list = new DeviceList();
        if (LibUsb.getDeviceList(null, list) > 0) {
            final Iterator<Device> devices = list.iterator();
            while (devices.hasNext()) {
                final Device dev = devices.next();
                final DeviceDescriptor devDesc = new DeviceDescriptor();
                LibUsb.getDeviceDescriptor(dev, devDesc);
                if ((devDesc.idVendor() == VID) && (devDesc.idProduct() == PID)) {
                    // Found matching device, open it.
                    devHandle = new DeviceHandle();
                    if (LibUsb.open(dev, devHandle) != LibUsb.SUCCESS) {
                        devHandle = null;
                        continue;
                    }
                    final IntBuffer activeConfig = BufferUtils.allocateIntBuffer();
                    LibUsb.getConfiguration(devHandle, activeConfig);
                    if (activeConfig.get() != 1) {
                        LibUsb.setConfiguration(devHandle, 1);
                    }
                    LibUsb.claimInterface(devHandle, 0);
                    System.out.println("Successfully found device.");
                }
            }
            LibUsb.freeDeviceList(list, true);
        }
    }

    private void closeDevice() {
        System.out.println("Shutting down device.");
        // Use reset to close connection.
        if (devHandle != null) {
            LibUsb.releaseInterface(devHandle, 0);
            LibUsb.close(devHandle);
            devHandle = null;
            LibUsb.exit(null);
        }
    }

    private void sendCommand(final byte cmd, final byte data, final boolean spiEnable) {
        System.out.println(String.format("Sending command - cmd: %X, data: %X", cmd, data));
        // Check for presence of ready device.
        if (devHandle == null) {
            return;
        }
        // Prepare message.
        final ByteBuffer dataBuffer = BufferUtils.allocateByteBuffer(PACKET_LENGTH);
        dataBuffer.put(0, (byte) 'A');
        dataBuffer.put(1, (byte) 'T');
        dataBuffer.put(2, (byte) 'C');
        // Command always 1 for SPI upload.
        dataBuffer.put(3, (byte) 0x01);
        // Data length always 1 for 1 byte.
        dataBuffer.put(4, (byte) 0x01);
        dataBuffer.put(5, (byte) 0x00);
        dataBuffer.put(6, (byte) 0x00);
        dataBuffer.put(7, (byte) 0x00);
        // Send actual SPI command (address usually).
        dataBuffer.put(8, cmd);
        dataBuffer.put(9, (byte) ((spiEnable) ? (0x00) : (0x01)));
        // Enable or disable SPI communication.
        // Send bulk transfer request on given endpoint.
        final IntBuffer transferred = BufferUtils.allocateIntBuffer();
        LibUsb.bulkTransfer(devHandle, ENDPOINT, dataBuffer, transferred, 0);
        if (transferred.get(0) != PACKET_LENGTH) {
            System.out.println("Failed to transfer whole packet.");
        }
        // Put content in a second packet.
        dataBuffer.put(0, data);
        // Send second bulk transfer request on given endpoint.
        LibUsb.bulkTransfer(devHandle, ENDPOINT, dataBuffer, transferred, 0);
        if (transferred.get(0) != PACKET_LENGTH) {
            System.out.println("Failed to transfer whole packet.");
        }
    }

    @Override
    public void resetFilter() {
        // Close any open device, and then open a new one.
        closeDevice();
        openDevice();
    }

    @Override
    public void initFilter() {
        // Open the device for the first time.
        openDevice();
    }
}

19 View Complete Implementation : AbstractDevice.java
Copyright MIT License
Author : usb4java
/**
 * Releases a claimed interface.
 *
 * @param number
 *            The number of the interface to release.
 * @throws UsbException
 *             When interface could not be claimed.
 */
final void releaseInterface(final byte number) throws UsbException {
    if (this.claimedInterfaceNumbers.isEmpty())
        throw new UsbClaimException("No interface is claimed");
    if (!this.claimedInterfaceNumbers.contains(number))
        throw new UsbClaimException("Interface not claimed");
    final DeviceHandle handle = open();
    int result = LibUsb.releaseInterface(handle, number & 0xff);
    if (result < 0) {
        throw ExceptionUtils.createPlatformException("Unable to release interface", result);
    }
    if (this.detachedKernelDriver) {
        result = LibUsb.attachKernelDriver(handle, number & 0xff);
        if (result < 0) {
            throw ExceptionUtils.createPlatformException("Unable to re-attach kernel driver", result);
        }
    }
    this.claimedInterfaceNumbers.remove(number);
}

19 View Complete Implementation : USBDisplay.java
Copyright GNU Lesser General Public License v3.0
Author : git-moss
/**
 * Connects to the display of the Push 2 via USB.
 *
 * Licensed under LGPLv3 - http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * @author Jürgen Moßgraber
 */
public clreplaced USBDisplay {

    /**
     * The pixel width of the display.
     */
    private static final int WIDTH = 960;

    /**
     * The pixel height of the display.
     */
    private static final int HEIGHT = 160;

    /**
     * The size of the display header.
     */
    private static final int HDR_SZ = 0x10;

    /**
     * The size of the display content.
     */
    private static final int DATA_SZ = 20 * 0x4000;

    private static final byte[] DISPLAY_HEADER = { (byte) 0xef, (byte) 0xcd, (byte) 0xab, (byte) 0x89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

    /**
     * Push 2 USB Vendor ID.
     */
    private static final short VENDOR_ID = 0x2982;

    /**
     * Push 2 USB Product ID.
     */
    private static final short PRODUCT_ID = 0x1967;

    /**
     * Push 2 USB Interface for the display.
     */
    private static final int INTERFACE_NUMBER = 0;

    private DeviceHandle handle;

    /**
     * Connect to the USB port and claim the display interface.
     */
    public void connect() {
        int result = LibUsb.init(null);
        if (result != LibUsb.SUCCESS)
            throw new LibUsbException("Unable to initialize libusb.", result);
        this.handle = openDeviceWithVidPid(VENDOR_ID, PRODUCT_ID);
        if (this.handle == null)
            throw new LibUsbException("Device not found.", LibUsb.ERROR_NO_DEVICE);
        result = LibUsb.claimInterface(this.handle, INTERFACE_NUMBER);
        if (result != LibUsb.SUCCESS)
            throw new LibUsbException("Unable to claim interface.", result);
    }

    /**
     * Send the image to the screen.
     *
     * @param image An image of size 960 x 160 pixel
     */
    public void send(final Image image) {
        if (this.handle == null)
            return;
        final ByteBuffer header = ByteBuffer.allocateDirect(HDR_SZ);
        final ByteBuffer buffer = ByteBuffer.allocateDirect(DATA_SZ);
        final IntBuffer transfered = IntBuffer.allocate(1);
        header.put(DISPLAY_HEADER);
        final PixelReader reader = image.getPixelReader();
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                final Color color = reader.getColor(x, y);
                // 3b(low) green - 5b red / 5b blue - 3b (high) green, e.g. gggRRRRR BBBBBGGG
                final int red = (int) Math.round(color.getRed() * 31);
                final int green = (int) Math.round(color.getGreen() * 63);
                final int blue = (int) Math.round(color.getBlue() * 31);
                buffer.put((byte) ((green & 0x07) << 5 | red & 0x1F));
                buffer.put((byte) ((blue & 0x1F) << 3 | (green & 0x38) >> 3));
            }
            for (int x = 0; x < 128; x++) buffer.put((byte) 0x00);
        }
        LibUsb.bulkTransfer(this.handle, (byte) 0x01, header, transfered, 1000L);
        LibUsb.bulkTransfer(this.handle, (byte) 0x01, buffer, transfered, 1000L);
    }

    /**
     * Send the buffered image to the screen.
     *
     * @param image An image of size 960 x 160 pixel
     */
    public void send(final BufferedImage image) {
        if (this.handle == null)
            return;
        final ByteBuffer header = ByteBuffer.allocateDirect(HDR_SZ);
        final ByteBuffer buffer = ByteBuffer.allocateDirect(DATA_SZ);
        final IntBuffer transfered = IntBuffer.allocate(1);
        header.put(DISPLAY_HEADER);
        final int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                final int pixel = pixels[x + y * WIDTH];
                final int red = ((pixel & 0x00FF0000) >> 16) * 31 / 255;
                final int green = ((pixel & 0x0000FF00) >> 8) * 63 / 255;
                final int blue = (pixel & 0x000000FF) * 31 / 255;
                // 3b(low) green - 5b red / 5b blue - 3b (high) green, e.g. gggRRRRR BBBBBGGG
                buffer.put((byte) ((green & 0x07) << 5 | red & 0x1F));
                buffer.put((byte) ((blue & 0x1F) << 3 | (green & 0x38) >> 3));
            }
            for (int x = 0; x < 128; x++) buffer.put((byte) 0x00);
        }
        LibUsb.bulkTransfer(this.handle, (byte) 0x01, header, transfered, 1000L);
        LibUsb.bulkTransfer(this.handle, (byte) 0x01, buffer, transfered, 1000L);
    }

    /**
     * Disconnect from the USB device.
     */
    public void disconnect() {
        if (this.handle == null)
            return;
        // Prevent further sending
        final DeviceHandle h = this.handle;
        this.handle = null;
        final int result = LibUsb.releaseInterface(h, INTERFACE_NUMBER);
        if (result != LibUsb.SUCCESS)
            throw new LibUsbException("Unable to release interface", result);
        LibUsb.close(h);
        LibUsb.exit(null);
    }

    /**
     * Find the device with the given vendor and product ID and open it.
     *
     * @param vendorId The vendor ID to look for
     * @param productId The product ID to look for
     * @return The device handle of the device or null if not found
     */
    private static DeviceHandle openDeviceWithVidPid(final short vendorId, final short productId) {
        final DeviceList list = new DeviceList();
        int result = LibUsb.getDeviceList(null, list);
        if (result < LibUsb.SUCCESS)
            throw new LibUsbException("Unable to get device list.", result);
        try {
            final Iterator<Device> iterator = list.iterator();
            LibUsbException ex = null;
            while (iterator.hasNext()) {
                final Device device = iterator.next();
                final DeviceDescriptor descriptor = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(device, descriptor);
                if (result != LibUsb.SUCCESS) {
                    ex = new LibUsbException("Unable to read device descriptor.", result);
                    // Continue, maybe there is a working device
                    continue;
                }
                if (descriptor.idVendor() == vendorId && descriptor.idProduct() == productId) {
                    final DeviceHandle handle = new DeviceHandle();
                    result = LibUsb.open(device, handle);
                    if (result != LibUsb.SUCCESS) {
                        ex = new LibUsbException("Unable to read device descriptor.", result);
                        // Continue, maybe there is a working device
                        continue;
                    }
                    return handle;
                }
            }
            if (ex != null)
                throw ex;
        } finally {
            LibUsb.freeDeviceList(list, true);
        }
        return null;
    }
}

19 View Complete Implementation : AbstractDevice.java
Copyright MIT License
Author : usb4java
/**
 * Claims the specified interface.
 *
 * @param number
 *            The number of the interface to claim.
 * @param force
 *            If claim should be forces if possible.
 * @throws UsbException
 *             When interface could not be claimed.
 */
final void claimInterface(final byte number, final boolean force) throws UsbException {
    if (this.claimedInterfaceNumbers.contains(number))
        throw new UsbClaimException("An interface is already claimed");
    final DeviceHandle handle = open();
    // Detach existing driver from the device if requested and
    // libusb supports it.
    if (force) {
        int result = LibUsb.kernelDriverActive(handle, number);
        if (result == LibUsb.ERROR_NO_DEVICE)
            throw new UsbDisconnectedException();
        if (result == 1) {
            result = LibUsb.detachKernelDriver(handle, number);
            if (result < 0) {
                throw ExceptionUtils.createPlatformException("Unable to detach kernel driver", result);
            }
            this.detachedKernelDriver = true;
        }
    }
    final int result = LibUsb.claimInterface(handle, number & 0xff);
    if (result < 0) {
        throw ExceptionUtils.createPlatformException("Unable to claim interface", result);
    }
    this.claimedInterfaceNumbers.add(number);
}

19 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
public static void releaseInterface(DeviceHandle handle) throws SourceException {
    int result = LibUsb.releaseInterface(handle, USB_INTERFACE);
    if (result != LibUsb.SUCCESS) {
        throw new SourceException("couldn't release interface [" + LibUsb.errorName(result) + "]");
    }
}

19 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static void enableI2CRepeater(DeviceHandle handle, boolean enabled) throws LibUsbException {
    Page page = Page.ONE;
    short address = 1;
    int value;
    if (enabled) {
        // ON
        value = 0x18;
    } else {
        // OFF
        value = 0x10;
    }
    writeDemodRegister(handle, page, address, value, 1);
}

19 View Complete Implementation : MissileLauncher.java
Copyright The Unlicense
Author : usb4java
/**
 * Sends a command to the missile launcher.
 *
 * @param handle
 *            The USB device handle.
 * @param command
 *            The command to send.
 */
public static void sendCommand(DeviceHandle handle, int command) {
    byte[] message = new byte[64];
    message[1] = (byte) ((command & CMD_LEFT) > 0 ? 1 : 0);
    message[2] = (byte) ((command & CMD_RIGHT) > 0 ? 1 : 0);
    message[3] = (byte) ((command & CMD_UP) > 0 ? 1 : 0);
    message[4] = (byte) ((command & CMD_DOWN) > 0 ? 1 : 0);
    message[5] = (byte) ((command & CMD_FIRE) > 0 ? 1 : 0);
    message[6] = 8;
    message[7] = 8;
    sendMessage(handle, INIT_A);
    sendMessage(handle, INIT_B);
    sendMessage(handle, message);
}

19 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Tests if the specified tuner type is contained in the usb tuner device.
 *
 * @param type - tuner type to test for
 * @param handle - handle to the usb tuner device
 * @param controlI2CRepeater - indicates if the method should control the
 * I2C repeater independently
 * @return - true if the device is the specified tuner type
 */
protected static boolean isTuner(TunerTypeCheck type, DeviceHandle handle, boolean controlI2CRepeater) {
    try {
        if (type == TunerTypeCheck.FC0012 || type == TunerTypeCheck.FC2580) {
            /* Initialize the GPIOs */
            setGPIOOutput(handle, (byte) 0x20);
            /* Reset tuner before probing */
            setGPIOBit(handle, (byte) 0x20, true);
            setGPIOBit(handle, (byte) 0x20, false);
        }
        int value = readI2CRegister(handle, type.getI2CAddress(), type.getCheckAddress(), controlI2CRepeater);
        if (type == TunerTypeCheck.FC2580) {
            return ((value & 0x7F) == type.getCheckValue());
        } else {
            return (value == type.getCheckValue());
        }
    } catch (LibUsbException e) {
    // Do nothing ... it's not the specified tuner
    }
    return false;
}

19 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Claims the USB interface.  Attempts to detach the active kernel driver
 * if one is currently attached.
 */
public static void claimInterface(DeviceHandle handle) throws SourceException {
    if (handle != null) {
        int result = LibUsb.kernelDriverActive(handle, USB_INTERFACE);
        if (result == 1) {
            result = LibUsb.detachKernelDriver(handle, USB_INTERFACE);
            if (result != LibUsb.SUCCESS) {
                mLog.error("failed attempt to detach kernel driver [" + LibUsb.errorName(result) + "]");
                throw new SourceException("couldn't detach kernel driver " + "from device");
            }
        }
        result = LibUsb.claimInterface(handle, USB_INTERFACE);
        if (result != LibUsb.SUCCESS) {
            throw new SourceException("couldn't claim usb interface [" + LibUsb.errorName(result) + "]");
        }
    } else {
        throw new SourceException("couldn't claim usb interface - no " + "device handle");
    }
}

19 View Complete Implementation : UsbDevice.java
Copyright GNU General Public License v3.0
Author : alchitry
public void setUsbDev(DeviceHandle dev) {
    device = dev;
}

19 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Writes a single byte to the 256-byte EEPROM using the specified offset.
 *
 * Note: introduce a 5 millisecond delay between each successive write to
 * the EEPROM or subsequent writes may fail.
 */
public void writeEEPROMByte(DeviceHandle handle, byte offset, byte value) throws IllegalArgumentException, UsbDisconnectedException, UsbException {
    if (offset < 0 || offset > 255) {
        throw new IllegalArgumentException("RTL2832 Tuner Controller - " + "EEPROM offset must be within range of 0 - 255");
    }
    int offsetAndValue = Integer.rotateLeft((0xFF & offset), 8) | (0xFF & value);
    writeRegister(handle, Block.I2C, EEPROM_ADDRESS, offsetAndValue, 2);
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static void write(DeviceHandle handle, short value, short index, ByteBuffer buffer) throws LibUsbException {
    if (handle != null) {
        int transferred = LibUsb.controlTransfer(handle, CONTROL_ENDPOINT_OUT, REQUEST_ZERO, value, index, buffer, TIMEOUT_US);
        if (transferred < 0) {
            throw new LibUsbException("error writing byte buffer", transferred);
        } else if (transferred != buffer.capacity()) {
            throw new LibUsbException("transferred bytes [" + transferred + "] is not what was expected [" + buffer.capacity() + "]", transferred);
        }
    } else {
        throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
    }
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Reads byte array from index at the address.
 *
 * @return big-endian byte array (needs to be swapped to be usable)
 */
protected static void read(DeviceHandle handle, short address, Block block, ByteBuffer buffer) throws LibUsbException {
    read(handle, address, block.getReadIndex(), buffer);
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static int readDemodRegister(DeviceHandle handle, Page page, short address, int length) throws LibUsbException {
    short index = page.getPage();
    short newAddress = (short) ((address << 8) | 0x20);
    ByteBuffer buffer = ByteBuffer.allocateDirect(length);
    read(handle, newAddress, index, buffer);
    buffer.order(ByteOrder.LITTLE_ENDIAN);
    if (length == 2) {
        return (int) (buffer.getShort() & 0xFFFF);
    } else {
        return (int) (buffer.get() & 0xFF);
    }
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static void writeRegister(DeviceHandle handle, Block block, short address, int value, int length) throws LibUsbException {
    ByteBuffer buffer = ByteBuffer.allocateDirect(length);
    buffer.order(ByteOrder.BIG_ENDIAN);
    if (length == 1) {
        buffer.put((byte) (value & 0xFF));
    } else if (length == 2) {
        buffer.putShort((short) value);
    } else {
        throw new IllegalArgumentException("Cannot write value greater " + "than 16 bits to the register - length [" + length + "]");
    }
    buffer.rewind();
    write(handle, address, block, buffer);
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Returns contents of the 256-byte EEPROM.  The contents are as follows:
 *
 * 256-byte EEPROM (in hex):
 * 00/01 - 2832 Signature
 * 03/02 - 0BDA Vendor ID
 * 05/04 - 2832 Product ID
 * 06 - A5 (has serial id?)
 * 07 - 16 (bit field - bit 0 = remote wakeup, bit 1 = IR enabled
 * 08 - 02 or 12
 * 10/09 0310 ETX(0x03) plus label length (includes length and ETX bytes)
 * 12/11 First UTF-16 character
 * 14/13 Second UTF-16 character ...
 *
 * Label 1: vendor
 * Label 2: product
 * Label 3: serial
 * Label 4,5 ... (user defined)
 */
public byte[] readEEPROM(DeviceHandle handle, short offset, int length) throws IllegalArgumentException {
    if (offset + length > 256) {
        throw new IllegalArgumentException("cannot read more than 256 " + "bytes from EEPROM - requested to read to byte [" + (offset + length) + "]");
    }
    byte[] data = new byte[length];
    ByteBuffer buffer = ByteBuffer.allocateDirect(1);
    try {
        /* Tell the RTL-2832 to address the EEPROM */
        writeRegister(handle, Block.I2C, EEPROM_ADDRESS, (byte) offset, 1);
    } catch (LibUsbException e) {
        mLog.error("usb error while attempting to set read address to " + "EEPROM register, prior to reading the EEPROM device " + "descriptor", e);
    }
    for (int x = 0; x < length; x++) {
        try {
            read(handle, EEPROM_ADDRESS, Block.I2C, buffer);
            data[x] = buffer.get();
            buffer.rewind();
        } catch (Exception e) {
            mLog.error("error while reading eeprom byte [" + x + "/" + length + "] aborting eeprom read and returning partially " + "filled descriptor byte array", e);
            x = length;
        }
    }
    return data;
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected void writeI2CRegister(DeviceHandle handle, byte i2CAddress, byte i2CRegister, byte value, boolean controlI2CRepeater) throws LibUsbException {
    short address = (short) (i2CAddress & 0xFF);
    ByteBuffer buffer = ByteBuffer.allocateDirect(2);
    buffer.put(i2CRegister);
    buffer.put(value);
    buffer.rewind();
    if (controlI2CRepeater) {
        enableI2CRepeater(handle, true);
        write(handle, address, Block.I2C, buffer);
        enableI2CRepeater(handle, false);
    } else {
        write(handle, address, Block.I2C, buffer);
    }
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 */
protected static void write(DeviceHandle handle, short address, Block block, ByteBuffer buffer) throws LibUsbException {
    write(handle, address, block.getWriteIndex(), buffer);
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static int readRegister(DeviceHandle handle, Block block, short address, int length) throws LibUsbException {
    ByteBuffer buffer = ByteBuffer.allocateDirect(2);
    read(handle, address, block, buffer);
    buffer.order(ByteOrder.LITTLE_ENDIAN);
    if (length == 2) {
        return (int) (buffer.getShort() & 0xFFFF);
    } else {
        return (int) (buffer.get() & 0xFF);
    }
}

18 View Complete Implementation : UsbDevice.java
Copyright GNU General Public License v3.0
Author : alchitry
protected static void UsbCloseInternal(DeviceHandle dev) {
    if (dev != null) {
        LibUsb.close(dev);
        dev = null;
    }
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static int readI2CRegister(DeviceHandle handle, byte i2CAddress, byte i2CRegister, boolean controlI2CRepeater) throws LibUsbException {
    short address = (short) (i2CAddress & 0xFF);
    ByteBuffer buffer = ByteBuffer.allocateDirect(1);
    buffer.put(i2CRegister);
    buffer.rewind();
    ByteBuffer data = ByteBuffer.allocateDirect(1);
    if (controlI2CRepeater) {
        enableI2CRepeater(handle, true);
        write(handle, address, Block.I2C, buffer);
        read(handle, address, Block.I2C, data);
        enableI2CRepeater(handle, false);
    } else {
        write(handle, address, Block.I2C, buffer);
        read(handle, address, Block.I2C, data);
    }
    return (int) (data.get() & 0xFF);
}

18 View Complete Implementation : LibUsbDeviceTest.java
Copyright MIT License
Author : usb4java
/**
 * Tests the {@link LibUsb#open(Device, DeviceHandle)} method. This can't be
 * really tested in a simple unit test like this. Most likely the user has
 * no access to the device. So this test succeeds on SUCCESS and on
 * ERROR_ACCESS. At least we have to make sure that the open() method doesn't
 * crash.
 */
@Test
public void testOpenAndClose() {
    replacedumeUsbTestsEnabled();
    replacedumeNotNull(this.device);
    final DeviceHandle handle = new DeviceHandle();
    final int result = LibUsb.open(this.device, handle);
    replacedertTrue((result == LibUsb.SUCCESS) || (result == LibUsb.ERROR_ACCESS));
    if (result == LibUsb.SUCCESS) {
        LibUsb.close(handle);
        try {
            LibUsb.close(handle);
            fail("Double-close should throw IllegalStateException");
        } catch (final IllegalStateException e) {
        // Expected behavior
        }
    }
}

18 View Complete Implementation : AbstractDevice.java
Copyright MIT License
Author : usb4java
/**
 * Opens the USB device and returns the USB device handle. If device was
 * already open then the old handle is returned.
 *
 * @return The USB device handle.
 * @throws UsbException
 *             When USB device could not be opened.
 */
public final DeviceHandle open() throws UsbException {
    if (this.handle == null) {
        final Device device = this.manager.getLibUsbDevice(this.id);
        try {
            final DeviceHandle handle = new DeviceHandle();
            final int result = LibUsb.open(device, handle);
            if (result < 0) {
                throw ExceptionUtils.createPlatformException("Can't open device " + this.id, result);
            }
            this.handle = handle;
        } finally {
            this.manager.releaseDevice(device);
        }
    }
    return this.handle;
}

18 View Complete Implementation : PS3Eye.java
Copyright MIT License
Author : diwi
/**
 * PS3Eye Camera for Java Applications.
 *
 * @author Thomas Diewald
 */
public clreplaced PS3Eye {

    // sensor address
    static final private int OV534_REG_ADDRESS = 0xf1;

    static final private int OV534_REG_SUBADDR = 0xf2;

    static final private int OV534_REG_WRITE = 0xf3;

    static final private int OV534_REG_READ = 0xf4;

    static final private int OV534_REG_OPERATION = 0xf5;

    static final private int OV534_REG_STATUS = 0xf6;

    static final private int OV534_OP_WRITE_3 = 0x37;

    static final private int OV534_OP_WRITE_2 = 0x33;

    static final private int OV534_OP_READ_2 = 0xf9;

    static final private int[][] ov534_reg_initdata = { { 0xe7, 0x3a }, // select OV772x sensor
    { OV534_REG_ADDRESS, 0x42 }, { 0x92, 0x01 }, { 0x93, 0x18 }, { 0x94, 0x10 }, { 0x95, 0x10 }, { 0xE2, 0x00 }, { 0xE7, 0x3E }, { 0x96, 0x00 }, { 0x97, 0x20 }, { 0x97, 0x20 }, { 0x97, 0x20 }, { 0x97, 0x0A }, { 0x97, 0x3F }, { 0x97, 0x4A }, { 0x97, 0x20 }, { 0x97, 0x15 }, { 0x97, 0x0B }, { 0x8E, 0x40 }, { 0x1F, 0x81 }, { 0xC0, 0x50 }, { 0xC1, 0x3C }, { 0xC2, 0x01 }, { 0xC3, 0x01 }, { 0x50, 0x89 }, { 0x88, 0x08 }, { 0x8D, 0x00 }, { 0x8E, 0x00 }, // video data start (V_FMT)
    { 0x1C, 0x00 }, // RAW8 mode
    { 0x1D, 0x00 }, // payload size 0x0200 * 4 = 2048 bytes
    { 0x1D, 0x02 }, // payload size
    { 0x1D, 0x00 }, // 
    // frame size = 0x012C00 * 4 = 307200 bytes (640 * 480 @ 8bpp)
    { 0x1D, 0x01 }, // frame size
    { 0x1D, 0x2C }, // frame size
    { 0x1D, 0x00 }, // 
    // video data start (V_CNTL0)
    { 0x1C, 0x0A }, // turn on UVC header
    { 0x1D, 0x08 }, { 0x1D, 0x0E }, { 0x34, 0x05 }, { 0xE3, 0x04 }, { 0x89, 0x00 }, { 0x76, 0x00 }, { 0xE7, 0x2E }, { 0x31, 0xF9 }, { 0x25, 0x42 }, { 0x21, 0xF0 }, { 0xE5, 0x04 } };

    static final private int[][] ov772x_reg_initdata = { // reset
    { 0x12, 0x80 }, { 0x3D, 0x00 }, // Processed Bayer RAW (8bit)
    { 0x12, 0x01 }, { 0x11, 0x01 }, { 0x14, 0x40 }, { 0x15, 0x00 }, // AWB
    { 0x63, 0xAA }, { 0x64, 0x87 }, { 0x66, 0x00 }, { 0x67, 0x02 }, { 0x17, 0x26 }, { 0x18, 0xA0 }, { 0x19, 0x07 }, { 0x1A, 0xF0 }, { 0x29, 0xA0 }, { 0x2A, 0x00 }, { 0x2C, 0xF0 }, { 0x20, 0x10 }, { 0x4E, 0x0F }, { 0x3E, 0xF3 }, { 0x0D, 0x41 }, { 0x32, 0x00 }, // COM8  - jfrancois 0xf0 orig x0f7
    { 0x13, 0xF0 }, { 0x22, 0x7F }, { 0x23, 0x03 }, { 0x24, 0x40 }, { 0x25, 0x30 }, { 0x26, 0xA1 }, { 0x2A, 0x00 }, { 0x2B, 0x00 }, { 0x13, 0xF7 }, { 0x0C, 0xC0 }, { 0x11, 0x00 }, { 0x0D, 0x41 }, // De-noise threshold - jfrancois 0x00 - orig 0x04
    { 0x8E, 0x00 } };

    static final private int[][] bridge_start_vga = { { 0x1c, 0x00 }, { 0x1d, 0x00 }, { 0x1d, 0x02 }, { 0x1d, 0x00 }, // frame size = 0x012C00 * 4 = 307200 bytes (640 * 480 @ 8bpp)
    { 0x1d, 0x01 }, // frame size
    { 0x1d, 0x2C }, // frame size
    { 0x1d, 0x00 }, { 0xc0, 0x50 }, { 0xc1, 0x3c } };

    static final private int[][] sensor_start_vga = { { 0x12, 0x01 }, { 0x17, 0x26 }, { 0x18, 0xa0 }, { 0x19, 0x07 }, { 0x1a, 0xf0 }, { 0x29, 0xa0 }, { 0x2c, 0xf0 }, { 0x65, 0x20 } };

    static final private int[][] bridge_start_qvga = { { 0x1c, 0x00 }, { 0x1d, 0x00 }, { 0x1d, 0x02 }, { 0x1d, 0x00 }, // frame size = 0x004B00 * 4 = 76800 bytes (320 * 240 @ 8bpp)
    { 0x1d, 0x00 }, // frame size
    { 0x1d, 0x4b }, // frame size
    { 0x1d, 0x00 }, { 0xc0, 0x28 }, { 0xc1, 0x1e } };

    static final private int[][] sensor_start_qvga = { { 0x12, 0x41 }, { 0x17, 0x3f }, { 0x18, 0x50 }, { 0x19, 0x03 }, { 0x1a, 0x78 }, { 0x29, 0x50 }, { 0x2c, 0x78 }, { 0x65, 0x2f } };

    static public enum Format {

        // Output in Bayer. Destination buffer must be width * height bytes
        Bayer(1),
        // Output in BGR. Destination buffer must be width * height * 3 bytes
        BGR(3),
        // Output in RGB. Destination buffer must be width * height * 3 bytes
        RGB(3);

        public final int bytes_per_pixel;

        private Format(int bytes_per_pixel) {
            this.bytes_per_pixel = bytes_per_pixel;
        }
    }

    static public enum Resolution {

        VGA(640, 480), QVGA(320, 240);

        public final int w, h, num_pixels;

        private Resolution(int w, int h) {
            this.w = w;
            this.h = h;
            this.num_pixels = w * h;
        }
    }

    static final protected USB usb = new USB();

    // PS3Eye id's
    static final public short VENDOR_ID = 0x1415;

    static final public short PRODUCT_ID = 0x2000;

    // LibUsb
    protected int device_idx;

    protected Device usb_device;

    protected DeviceHandle usb_device_handle;

    // frame
    protected int framerate = 60;

    // RGB, BRG, BAYER
    protected PS3Eye.Format format = PS3Eye.Format.RGB;

    // VGA, QVGA
    protected PS3Eye.Resolution resolution = PS3Eye.Resolution.VGA;

    // controls
    // gain        20 [0,  63]
    protected int gain = 20;

    // exposure   120 [0, 255]
    protected int exposure = 120;

    // sharpness    0 [0,  63]
    protected int sharpness = 0;

    // hue        143 [0, 255]
    protected int hue = 143;

    // brightness  20 [0, 255]
    protected int brightness = 20;

    // contrast    37 [0, 255]
    protected int contrast = 37;

    // blueblc    128 [0, 255]
    protected int blueblc = 128;

    // redblc     128 [0, 255]
    protected int redblc = 128;

    // greenblc   128 [0, 255]
    protected int greenblc = 128;

    protected boolean autogain = false;

    protected boolean awb = false;

    protected boolean flip_h = false;

    protected boolean flip_v = false;

    protected boolean is_streaming = false;

    protected URBDesc urb = new URBDesc();

    private static PS3Eye[] PS3EYE_LIST = null;

    /**
     * get a list of all devices
     *
     * @param papplet
     * @return
     */
    public static PS3Eye[] getDevices() {
        if (PS3EYE_LIST == null) {
            Device[] devices = usb.getDevices(PS3Eye.VENDOR_ID, PS3Eye.PRODUCT_ID);
            PS3EYE_LIST = new PS3Eye[devices.length];
            for (int i = 0; i < devices.length; i++) {
                PS3EYE_LIST[i] = new PS3Eye(devices[i], i);
            }
        }
        return PS3EYE_LIST;
    }

    /**
     * returns the number of available devices
     *
     * @param papplet
     * @return
     */
    public static int getDeviceCount() {
        return getDevices().length;
    }

    /**
     * returns the first device
     *
     * @param papplet
     * @return
     */
    public static PS3Eye getDevice() {
        return getDevice(0);
    }

    /**
     * returns a device with a given index
     *
     * @param papplet
     * @param idx
     * @return
     */
    public static PS3Eye getDevice(int idx) {
        PS3Eye[] list = getDevices();
        return list.length > idx ? list[idx] : null;
    }

    // cleanup
    public static void disposeAll() {
        if (PS3EYE_LIST != null) {
            for (int i = 0; i < PS3EYE_LIST.length; i++) {
                PS3EYE_LIST[i].release();
            }
            PS3EYE_LIST = null;
            usb.release();
        // System.out.println("PS3Eye.disposeAll()");
        }
    }

    protected PS3Eye(Device device, int device_idx) {
        this.usb_device = device;
        this.device_idx = device_idx;
    }

    // call on exit
    public void dispose() {
        // System.out.println("dispose");
        PS3Eye.disposeAll();
    }

    public void init() {
        init(60, Resolution.VGA, Format.RGB);
    }

    public void init(int framerate) {
        init(framerate, Resolution.VGA, Format.RGB);
    }

    public void init(int framerate, PS3Eye.Resolution resolution) {
        init(framerate, resolution, Format.RGB);
    }

    public void init(int framerate, PS3Eye.Resolution resolution, PS3Eye.Format format) {
        boolean push_is_streaming = isStreaming();
        if (push_is_streaming) {
            stop();
        }
        openUSB();
        this.format = format;
        this.resolution = resolution;
        this.framerate = ov534_set_frame_rate(framerate, true);
        // reset bridge
        ov534_reg_write(0xe7, 0x3a);
        ov534_reg_write(0xe0, 0x08);
        // initialize the sensor address
        ov534_reg_write(OV534_REG_ADDRESS, 0x42);
        // reset sensor
        sccb_reg_write(0x12, 0x80);
        // #ifdef _MSC_VER
        // Sleep(10);
        // #else
        // nanosleep((const struct timespec[]){{0, 10000000}}, NULL);
        // #endif
        // probe the sensor
        @SuppressWarnings("unused")
        int sensor_id = 0;
        sccb_reg_read(0x0a);
        sensor_id |= sccb_reg_read(0x0a) << 8;
        sccb_reg_read(0x0b);
        sensor_id |= sccb_reg_read(0x0b);
        // System.out.printf("Sensor ID: %04x\n", sensor_id);
        // initialize
        reg_w_array(ov534_reg_initdata);
        ov534_set_led(1);
        sccb_w_array(ov772x_reg_initdata);
        ov534_reg_write(0xe0, 0x09);
        ov534_set_led(0);
        if (push_is_streaming) {
            start();
        }
    }

    public void start() {
        if (is_streaming)
            return;
        if (usb_device_handle == null) {
            init();
        }
        switch(resolution) {
            case VGA:
                reg_w_array(bridge_start_vga);
                sccb_w_array(sensor_start_vga);
                break;
            case QVGA:
                reg_w_array(bridge_start_qvga);
                sccb_w_array(sensor_start_qvga);
                break;
            default:
                System.err.println("impossible resolution");
                break;
        }
        ov534_set_frame_rate(framerate);
        setAutogain(autogain);
        setAutoWhiteBalance(awb);
        setGain(gain);
        setHue(hue);
        setExposure(exposure);
        setBrightness(brightness);
        setContrast(contrast);
        setSharpness(sharpness);
        setRedBalance(redblc);
        setBlueBalance(blueblc);
        setGreenBalance(greenblc);
        setFlip(flip_h, flip_v);
        ov534_set_led(1);
        // start stream
        ov534_reg_write(0xe0, 0x00);
        // init and start urb
        urb.start_transfers(usb_device_handle, resolution.num_pixels);
        is_streaming = true;
    }

    public void stop() {
        if (!is_streaming)
            return;
        is_streaming = false;
        // stop streaming data
        ov534_reg_write(0xe0, 0x09);
        ov534_set_led(0);
        // close urb
        urb.close_transfers();
    }

    public void release() {
        stop();
        closeUSB();
    }

    private void openUSB() {
        if (usb_device_handle == null) {
            usb_device_handle = new DeviceHandle();
            int rval = LibUsb.open(usb_device, usb_device_handle);
            if (rval != LibUsb.SUCCESS) {
                throw new LibUsbException("error LibUsb.open", rval);
            }
        }
        if (usb_device_handle != null) {
            int rval = LibUsb.claimInterface(usb_device_handle, 0);
            if (rval != LibUsb.SUCCESS) {
                throw new LibUsbException("error LibUsb.claimInterface", rval);
            }
        }
    }

    private void closeUSB() {
        if (usb_device_handle != null) {
            LibUsb.releaseInterface(usb_device_handle, 0);
            LibUsb.close(usb_device_handle);
            usb_device_handle = null;
        }
        if (usb_device != null) {
            LibUsb.unrefDevice(usb_device);
            usb_device = null;
        }
    }

    public int getUSBPortNumber() {
        return LibUsb.getPortNumber(usb_device);
    }

    // Two bits control LED: 0x21 bit 7 and 0x23 bit 7 (direction and output)?
    private void ov534_set_led(int status) {
        int data;
        data = ov534_reg_read(0x21);
        data |= 0x80;
        ov534_reg_write(0x21, data);
        data = ov534_reg_read(0x23);
        if (status == 1)
            data |= 0x80;
        else
            data &= ~0x80;
        ov534_reg_write(0x23, data);
        if (status == 0) {
            data = ov534_reg_read(0x21);
            data &= ~0x80;
            ov534_reg_write(0x21, data);
        }
    }

    // fps, (byte)r11, (byte)r0d, (byte)re5
    private final int[][] rate_VGA = { // { 83, 0x01, 0xc1, 0x02}, // 83 FPS: video is partly corrupt
    // 75 FPS or below: video is valid
    { 75, 0x01, 0x81, 0x02 }, { 60, 0x00, 0x41, 0x04 }, { 50, 0x01, 0x41, 0x02 }, { 40, 0x02, 0xc1, 0x04 }, { 30, 0x04, 0x81, 0x02 }, { 25, 0x00, 0x01, 0x02 }, { 20, 0x04, 0x41, 0x02 }, { 15, 0x09, 0x81, 0x02 }, { 10, 0x09, 0x41, 0x02 }, { 8, 0x02, 0x01, 0x02 }, { 5, 0x04, 0x01, 0x02 }, { 3, 0x06, 0x01, 0x02 }, { 2, 0x09, 0x01, 0x02 } };

    private final int[][] rate_QVGA = { // {290, 0x00, 0xc1, 0x04},
    // {205, 0x01, 0xc1, 0x02}, // 205 FPS or above: video is partly corrupt
    // 187 FPS or below: video is valid
    { 187, 0x01, 0x81, 0x02 }, { 150, 0x00, 0x41, 0x04 }, { 137, 0x02, 0xc1, 0x02 }, { 125, 0x01, 0x41, 0x02 }, { 100, 0x02, 0xc1, 0x04 }, { 90, 0x03, 0x81, 0x02 }, { 75, 0x04, 0x81, 0x02 }, { 60, 0x04, 0xc1, 0x04 }, { 50, 0x04, 0x41, 0x02 }, { 40, 0x06, 0x81, 0x03 }, { 37, 0x00, 0x01, 0x04 }, { 30, 0x04, 0x41, 0x04 }, { 17, 0x18, 0xc1, 0x02 }, { 15, 0x18, 0x81, 0x02 }, { 12, 0x02, 0x01, 0x04 }, { 10, 0x18, 0x41, 0x02 }, { 7, 0x04, 0x01, 0x04 }, { 5, 0x06, 0x01, 0x04 }, { 3, 0x09, 0x01, 0x04 }, { 2, 0x18, 0x01, 0x02 } };

    public void printAvailableConfigs() {
        for (int i = 0; i < rate_VGA.length; i++) {
            System.out.println("VGA." + rate_VGA[i][0]);
        }
        for (int i = 0; i < rate_QVGA.length; i++) {
            System.out.println("QVGA." + rate_QVGA[i][0]);
        }
    }

    // validate frame rate and (if not dry run) set it
    private int ov534_set_frame_rate(int framerate) {
        return ov534_set_frame_rate(framerate, false);
    }

    private int ov534_set_frame_rate(int framerate, boolean dry_run) {
        final int[][] rate;
        switch(resolution) {
            case QVGA:
                rate = rate_QVGA;
                break;
            case VGA:
                rate = rate_VGA;
                break;
            default:
                rate = rate_VGA;
                break;
        }
        // find best (nearest) candidate
        int idx = 0;
        int dd_min = Integer.MAX_VALUE;
        for (int i = 0; i < rate.length; i++) {
            int d_cur = (rate[i][0] - framerate);
            int dd_cur = d_cur * d_cur;
            if (dd_cur < dd_min) {
                dd_min = dd_cur;
                idx = i;
            }
        }
        if (!dry_run) {
            sccb_reg_write(0x11, rate[idx][1]);
            sccb_reg_write(0x0d, rate[idx][2]);
            ov534_reg_write(0xe5, rate[idx][3]);
        }
        return rate[idx][0];
    }

    private void ov534_reg_write(int reg, int val) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(1);
        buffer.put(0, (byte) (val & 0xFF));
        int transfered = LibUsb.controlTransfer(usb_device_handle, (byte) (LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE), (byte) 0x01, (byte) 0x00, (short) reg, buffer, 500L);
        if (transfered < 0) {
            throw new LibUsbException("error ov534_reg_write, LibUsb.controlTransfer", transfered);
        }
    }

    private int ov534_reg_read(int reg) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(1);
        int transfered = LibUsb.controlTransfer(usb_device_handle, (byte) (LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE), (byte) 0x01, (byte) 0x00, (short) reg, buffer, 500);
        if (transfered < 0) {
            throw new LibUsbException("error ov534_reg_read, LibUsb.controlTransfer", transfered);
        }
        return buffer.get() & 0xFF;
    }

    private boolean sccb_check_status() {
        for (int i = 0; i < 5; i++) {
            int data = ov534_reg_read(OV534_REG_STATUS);
            switch(data) {
                case 0x00:
                    return true;
                case 0x04:
                    return false;
                case 0x03:
                    break;
                default:
                    System.out.printf("sccb_check_status 0x%02x, attempt %d/5\n", data, i + 1);
            }
        }
        return true;
    }

    private void sccb_reg_write(int reg, int val) {
        ov534_reg_write(OV534_REG_SUBADDR, reg);
        ov534_reg_write(OV534_REG_WRITE, val);
        ov534_reg_write(OV534_REG_OPERATION, OV534_OP_WRITE_3);
        if (!sccb_check_status()) {
            System.out.println("sccb_reg_write failed\n");
        }
    }

    private int sccb_reg_read(int reg) {
        ov534_reg_write(OV534_REG_SUBADDR, reg);
        ov534_reg_write(OV534_REG_OPERATION, OV534_OP_WRITE_2);
        if (!sccb_check_status()) {
            System.out.println("sccb_reg_read failed 1\n");
        }
        ov534_reg_write(OV534_REG_OPERATION, OV534_OP_READ_2);
        if (!sccb_check_status()) {
            System.out.println("sccb_reg_read failed 2\n");
        }
        return ov534_reg_read(OV534_REG_READ);
    }

    // output a bridge sequence (reg - val)
    private void reg_w_array(int[][] data) {
        for (int i = 0; i < data.length; i++) {
            ov534_reg_write(data[i][0], data[i][1]);
        }
    }

    // output a sensor sequence (reg - val)
    private void sccb_w_array(int[][] data) {
        for (int i = 0; i < data.length; i++) {
            int[] datai = data[i];
            if (datai[0] != 0xff) {
                sccb_reg_write(datai[0], datai[1]);
            } else {
                sccb_reg_read(datai[1]);
                sccb_reg_write(0xff, 0x00);
            }
        }
    }

    // ////////////////////////////////////////////////////////////////////////////
    // Controls
    // ////////////////////////////////////////////////////////////////////////////
    public boolean getAutogain() {
        return autogain;
    }

    public void setAutogain(boolean val) {
        autogain = val;
        if (val) {
            // AGC,AEC,AWB ON
            sccb_reg_write(0x13, 0xf7);
            sccb_reg_write(0x64, sccb_reg_read(0x64) | 0x03);
        } else {
            // AGC,AEC,AWB OFF
            sccb_reg_write(0x13, 0xf0);
            sccb_reg_write(0x64, sccb_reg_read(0x64) & 0xFC);
            setGain(gain);
            setExposure(exposure);
        }
    }

    public boolean getAutoWhiteBalance() {
        return awb;
    }

    public void setAutoWhiteBalance(boolean val) {
        awb = val;
        if (val) {
            // AWB ON
            sccb_reg_write(0x63, 0xe0);
        } else {
            // AWB OFF
            sccb_reg_write(0x63, 0xAA);
        }
    }

    public int getGain() {
        return gain;
    }

    public void setGain(int val) {
        gain = val;
        switch(val & 0x30) {
            case 0x00:
                val &= 0x0F;
                break;
            case 0x10:
                val &= 0x0F;
                val |= 0x30;
                break;
            case 0x20:
                val &= 0x0F;
                val |= 0x70;
                break;
            case 0x30:
                val &= 0x0F;
                val |= 0xF0;
                break;
        }
        sccb_reg_write(0x00, val);
    }

    public int getExposure() {
        return exposure;
    }

    public void setExposure(int val) {
        exposure = val;
        sccb_reg_write(0x08, val >> 7);
        sccb_reg_write(0x10, val << 1);
    }

    public int getSharpness() {
        return sharpness;
    }

    public void setSharpness(int val) {
        sharpness = val;
        // vga noise
        sccb_reg_write(0x91, val);
        // qvga noise
        sccb_reg_write(0x8E, val);
    }

    public int getContrast() {
        return contrast;
    }

    public void setContrast(int val) {
        contrast = val;
        sccb_reg_write(0x9C, val);
    }

    public int getBrightness() {
        return brightness;
    }

    public void setBrightness(int val) {
        brightness = val;
        sccb_reg_write(0x9B, val);
    }

    public int getHue() {
        return hue;
    }

    public void setHue(int val) {
        hue = val;
        sccb_reg_write(0x01, val);
    }

    public int getRedBalance() {
        return redblc;
    }

    public void setRedBalance(int val) {
        redblc = val;
        sccb_reg_write(0x43, val);
    }

    public int getBlueBalance() {
        return blueblc;
    }

    public void setBlueBalance(int val) {
        blueblc = val;
        sccb_reg_write(0x42, val);
    }

    public int getGreenBalance() {
        return greenblc;
    }

    public void setGreenBalance(int val) {
        greenblc = val;
        sccb_reg_write(0x44, val);
    }

    public boolean getFlipH() {
        return flip_h;
    }

    public boolean getFlipV() {
        return flip_v;
    }

    public void setFlip(boolean horizontal, boolean vertical) {
        flip_h = horizontal;
        flip_v = vertical;
        int val = sccb_reg_read(0x0c);
        val &= ~0xc0;
        if (!horizontal)
            val |= 0x40;
        if (!vertical)
            val |= 0x80;
        sccb_reg_write(0x0c, val);
        urb.frame_queue.flip_vert = flip_v;
    }

    public int getFramerate() {
        return framerate;
    }

    public void setFrameRate(int framerate) {
        this.framerate = ov534_set_frame_rate(framerate);
    }

    public PS3Eye.Format getFormat() {
        return format;
    }

    public void setFormat(PS3Eye.Format format) {
        this.format = format;
    }

    public PS3Eye.Resolution getResolution() {
        return resolution;
    }

    public boolean isStreaming() {
        return is_streaming;
    }

    public int getDeviceIndex() {
        return device_idx;
    }

    public Device getUsbDevice() {
        return usb_device;
    }

    public DeviceHandle getUsbDeviceHandle() {
        return usb_device_handle;
    }

    /**
     * @return true if a new frame is available
     */
    public boolean isAvailable() {
        return is_streaming && urb.frame_queue.isAvailable();
    }

    /**
     * When "true", the thread waits until a new frame is available for transfer.
     * The default value is "true".
     *
     * @param wait_for_frame_to_be_available
     */
    public void waitAvailable(boolean wait_for_frame_to_be_available) {
        urb.frame_queue.wait_for_frame_to_be_available = wait_for_frame_to_be_available;
    }

    /**
     * Copies the available frame-buffer data into the given buffer.
     * If buffer is null or of the wrong size, it gets (re)allocated.
     * In any case a buffer containing the current frame gets returned.
     */
    public byte[] getFrame(byte[] buffer) {
        int num_channels = format.bytes_per_pixel;
        int num_pixels = resolution.num_pixels;
        int num_bytes = num_pixels * num_channels;
        // (re)alloc
        if (buffer == null || buffer.length != num_bytes) {
            buffer = new byte[num_bytes];
        }
        // blocking data transfer
        if (is_streaming) {
            urb.frame_queue.Dequeue(buffer, resolution.w, resolution.h, format);
        }
        return buffer;
    }

    // local buffer ... lazy alloc + dynamic realloc
    protected byte[] frame_buffer;

    /**
     * Fills the given pixels-array with the current frame-buffer.
     * "pixels" needs to be allocated and resized to the full framesize.
     * The Pixels are formated either as 0xAARRGGBB or 0xAABBGGRR, depending on
     * chosen format (Format.RGB or Format.BGR)
     */
    public void getFrame(int[] pixels) {
        if (pixels == null || pixels.length != resolution.num_pixels) {
            System.out.println("error getFrame(pixels_ARGB). pixels_ARGB has wrong size!");
            return;
        }
        // get image data (bytes)
        frame_buffer = getFrame(frame_buffer);
        int bayer = 0, rgb_r = 0, rgb_g = 0, rgb_b = 0;
        if (format == Format.Bayer) {
            for (int i = 0; i < pixels.length; i++) {
                bayer = frame_buffer[i] & 0xFF;
                pixels[i] = 0xFF000000 | (bayer << 16) | (bayer << 8) | bayer;
            }
        }
        if (format == Format.RGB || format == Format.BGR) {
            for (int i = 0, ch = 0; i < pixels.length; i++) {
                rgb_r = frame_buffer[ch++] & 0xFF;
                rgb_g = frame_buffer[ch++] & 0xFF;
                rgb_b = frame_buffer[ch++] & 0xFF;
                pixels[i] = 0xFF000000 | (rgb_r << 16) | (rgb_g << 8) | rgb_b;
            }
        }
    }
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected static void writeDemodRegister(DeviceHandle handle, Page page, short address, int value, int length) throws LibUsbException {
    ByteBuffer buffer = ByteBuffer.allocateDirect(length);
    buffer.order(ByteOrder.BIG_ENDIAN);
    if (length == 1) {
        buffer.put((byte) (value & 0xFF));
    } else if (length == 2) {
        buffer.putShort((short) (value & 0xFFFF));
    } else {
        throw new IllegalArgumentException("Cannot write value greater " + "than 16 bits to the register - length [" + length + "]");
    }
    short index = (short) (0x10 | page.getPage());
    short newAddress = (short) (address << 8 | 0x20);
    write(handle, newAddress, index, buffer);
    readDemodRegister(handle, Page.TEN, (short) 1, length);
}

18 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Performs a control type read
 */
protected static void read(DeviceHandle handle, short address, short index, ByteBuffer buffer) throws LibUsbException {
    if (handle != null) {
        int transferred = LibUsb.controlTransfer(handle, CONTROL_ENDPOINT_IN, REQUEST_ZERO, address, index, buffer, TIMEOUT_US);
        if (transferred < 0) {
            throw new LibUsbException("read error", transferred);
        } else if (transferred != buffer.capacity()) {
            throw new LibUsbException("transferred bytes [" + transferred + "] is not what was expected [" + buffer.capacity() + "]", transferred);
        }
    } else {
        throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
    }
}

17 View Complete Implementation : LibUsbDeviceTest.java
Copyright MIT License
Author : usb4java
/**
 * Tests the {@link LibUsb#open(Device, DeviceHandle)} method without a
 * device.
 */
@Test(expected = IllegalArgumentException.clreplaced)
public void testOpenWithoutDevice() {
    replacedumeUsbTestsEnabled();
    final DeviceHandle handle = new DeviceHandle();
    LibUsb.open(null, handle);
}

17 View Complete Implementation : IrpQueue.java
Copyright MIT License
Author : usb4java
/**
 * Transfers data from or to the device.
 *
 * @param handle
 *            The device handle.
 * @param descriptor
 *            The endpoint descriptor.
 * @param type
 *            The endpoint type.
 * @param buffer
 *            The data buffer.
 * @return The number of transferred bytes.
 * @throws UsbException
 *             When data transfer fails.
 */
private int transfer(final DeviceHandle handle, final UsbEndpointDescriptor descriptor, final int type, final ByteBuffer buffer) throws UsbException {
    final byte address = descriptor.bEndpointAddress();
    final boolean in = this.pipe.getUsbEndpoint().getDirection() == UsbConst.ENDPOINT_DIRECTION_IN;
    if (type == UsbConst.ENDPOINT_TYPE_BULK) {
        return transferBulk(handle, address, in, buffer);
    } else if (type == UsbConst.ENDPOINT_TYPE_INTERRUPT) {
        return transferInterrupt(handle, address, in, buffer);
    } else {
        throw new UsbException("Unsupported endpoint type: " + type);
    }
}

17 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Sets the General Purpose Input/Output (GPIO) register bit
 *
 * @param handle - USB tuner device
 * @param bitMask - bit mask with one for targeted register bits and zero
 * for the non-targeted register bits
 * @param enabled - true to set the bit and false to clear the bit
 * @throws UsbDisconnectedException - if the tuner device is disconnected
 * @throws UsbException             - if there is a USB error while communicating with
 *                                  the device
 */
protected static void setGPIOBit(DeviceHandle handle, byte bitMask, boolean enabled) throws LibUsbException {
    // Get current register value
    int value = readRegister(handle, Block.SYS, Address.GPO.getAddress(), 1);
    // Update the masked bits
    if (enabled) {
        value |= bitMask;
    } else {
        value &= ~bitMask;
    }
    // Write the change back to the device
    writeRegister(handle, Block.SYS, Address.GPO.getAddress(), value, 1);
}

17 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
protected void deinitBaseband(DeviceHandle handle) throws IllegalArgumentException, UsbDisconnectedException, UsbException {
    writeRegister(handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0x20, 1);
}

17 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * Enables GPIO Output
 *
 * @param handle - usb tuner device
 * @param bitMask - mask containing one bit value in targeted bit field(s)
 * @throws UsbDisconnectedException
 * @throws UsbException
 */
protected static void setGPIOOutput(DeviceHandle handle, byte bitMask) throws LibUsbException {
    // Get current register value
    int value = readRegister(handle, Block.SYS, Address.GPD.getAddress(), 1);
    // Mask the value and rewrite it
    writeRegister(handle, Block.SYS, Address.GPO.getAddress(), value & ~bitMask, 1);
    // Get current register value
    value = readRegister(handle, Block.SYS, Address.GPOE.getAddress(), 1);
    // Mask the value and rewrite it
    writeRegister(handle, Block.SYS, Address.GPOE.getAddress(), value | bitMask, 1);
}

17 View Complete Implementation : USBDisplay.java
Copyright GNU Lesser General Public License v3.0
Author : git-moss
/**
 * Disconnect from the USB device.
 */
public void disconnect() {
    if (this.handle == null)
        return;
    // Prevent further sending
    final DeviceHandle h = this.handle;
    this.handle = null;
    final int result = LibUsb.releaseInterface(h, INTERFACE_NUMBER);
    if (result != LibUsb.SUCCESS)
        throw new LibUsbException("Unable to release interface", result);
    LibUsb.close(h);
    LibUsb.exit(null);
}

17 View Complete Implementation : LibUsbDeviceTest.java
Copyright MIT License
Author : usb4java
/**
 * Tests the {@link LibUsb#openDeviceWithVidPid(Context, short, short)}
 * method.
 * We can't test anything here because the device most likely can't be
 * opened anyway. We just make sure it does not crash.
 */
@Test
public void testOpenDeviceWithVidPid() {
    replacedumeUsbTestsEnabled();
    final DeviceHandle handle = LibUsb.openDeviceWithVidPid(this.context, this.vendorId, this.productId);
    if (handle != null) {
        LibUsb.close(handle);
    }
}

16 View Complete Implementation : UsbDevice.java
Copyright GNU General Public License v3.0
Author : alchitry
public clreplaced UsbDevice {

    public clreplaced TransferControl {

        public IntBuffer completed = BufferUtils.allocateIntBuffer();

        public byte[] buf;

        public int offset;

        public UsbDevice usbDev;

        public Transfer transfer;
    }

    protected static Context context;

    protected DeviceHandle device;

    protected int readTimeout;

    protected int writeTimeout;

    protected ByteBuffer readBuffer;

    protected int readBufferChunksize;

    protected int writeBufferChunksize;

    protected int maxPacketSize;

    protected int iface;

    protected byte inEndPoint;

    protected byte outEndPoint;

    protected DetachMode detachMode;

    public static final ByteBuffer EMPTY_BUF = ByteBuffer.allocateDirect(0);

    public clreplaced SizeAndTime {

        public long totalBytes;

        public long time;
    }

    public clreplaced ProgressInfo {

        public SizeAndTime first;

        public SizeAndTime prev;

        public SizeAndTime current;

        public double totalTime;

        public double totalRate;

        public double currentRate;
    }

    public clreplaced DeviceStrings {

        public String manufacture;

        public String product;

        public String serial;
    }

    public interface StreamCallback {

        void update(byte[] buffer, ProgressInfo progress, byte[] userData);
    }

    protected static void UsbCloseInternal(DeviceHandle dev) {
        if (dev != null) {
            LibUsb.close(dev);
            dev = null;
        }
    }

    protected void UsbCloseInternal() {
        UsbCloseInternal(device);
    }

    static {
        if (LibUsb.init(context) < 0)
            throw new LibUsbException("LibUsb.init() failed", -3);
    }

    protected void init() {
        device = null;
        readTimeout = 5000;
        writeTimeout = 5000;
        readBuffer = null;
        writeBufferChunksize = 4096;
        maxPacketSize = 0;
        detachMode = DetachMode.AUTO_DETACH_REATACH_SIO_MODULE;
        iface = 0;
        readDataSetChunkSize(4096);
    }

    public UsbDevice() {
        init();
    }

    public void setDetachMode(DetachMode mode) {
        if (device != null) {
            if (!mode.equals(detachMode))
                throw new LibUsbException("Detach mode can not be changed on an already open device", -3);
        }
        detachMode = mode;
    }

    public void deinit() {
        UsbCloseInternal();
        if (context != null) {
            LibUsb.exit(context);
            context = null;
        }
    }

    public void setUsbDev(DeviceHandle dev) {
        device = dev;
    }

    public static List<Device> usbFindAll(short vendor, short product, String description, String serial) {
        DeviceHandle device;
        // Read the USB device list
        DeviceList list = new DeviceList();
        int result = LibUsb.getDeviceList(null, list);
        if (result < 0)
            throw new LibUsbException("Unable to get device list", result);
        ArrayList<Device> devices = new ArrayList<>();
        try {
            // Iterate over all devices and scan for the right one
            for (Device dev : list) {
                DeviceDescriptor desc = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(dev, desc);
                if (result != LibUsb.SUCCESS)
                    throw new LibUsbException("Unable to read device descriptor", result);
                if (((vendor != 0 || product != 0) && desc.idVendor() == vendor && desc.idProduct() == product) || ((vendor == 0 && product == 0) && (desc.idVendor() == (short) 0x403) && (desc.idProduct() == (short) 0x6001 || desc.idProduct() == (short) 0x6010 || desc.idProduct() == (short) 0x6011 || desc.idProduct() == (short) 0x6014 || desc.idProduct() == (short) 0x6015))) {
                    device = new DeviceHandle();
                    if (LibUsb.open(dev, device) < 0)
                        throw new LibUsbException("LibUsb.open() failed", -4);
                    if (description != null) {
                        String sDesc = LibUsb.getStringDescriptor(device, desc.iProduct());
                        if (sDesc == null) {
                            UsbCloseInternal(device);
                            throw new LibUsbException("unalbe to fetch product description", -8);
                        }
                        if (!description.equals(sDesc)) {
                            UsbCloseInternal(device);
                            continue;
                        }
                    }
                    if (serial != null) {
                        String sSer = LibUsb.getStringDescriptor(device, desc.iSerialNumber());
                        if (sSer == null) {
                            UsbCloseInternal(device);
                            throw new LibUsbException("unalbe to fetch serial number", -9);
                        }
                        if (!serial.equals(sSer)) {
                            UsbCloseInternal(device);
                            continue;
                        }
                    }
                    UsbCloseInternal(device);
                    devices.add(dev);
                    LibUsb.refDevice(dev);
                }
            }
        } finally {
            // Ensure the allocated device list is freed
            LibUsb.freeDeviceList(list, true);
        }
        // Device not found
        return devices;
    }

    public static List<DeviceEntry> usbFindAll(List<UsbDescriptor> descriptions) {
        DeviceHandle device;
        // Read the USB device list
        DeviceList list = new DeviceList();
        int result = LibUsb.getDeviceList(null, list);
        if (result < 0)
            throw new LibUsbException("Unable to get device list", result);
        ArrayList<DeviceEntry> devices = new ArrayList<>();
        try {
            // Iterate over all devices and scan for the right one
            for (Device dev : list) {
                DeviceDescriptor desc = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(dev, desc);
                if (result != LibUsb.SUCCESS)
                    throw new LibUsbException("Unable to read device descriptor", result);
                boolean vidPidMatch = false;
                for (UsbDescriptor udes : descriptions) {
                    if (udes.vid == desc.idVendor() && udes.pid == desc.idProduct()) {
                        vidPidMatch = true;
                        break;
                    }
                }
                if (vidPidMatch) {
                    device = new DeviceHandle();
                    int code = LibUsb.open(dev, device);
                    if (code < 0)
                        throw new LibUsbException("LibUsb.open() failed", code);
                    String sDesc = LibUsb.getStringDescriptor(device, desc.iProduct());
                    if (sDesc == null) {
                        UsbCloseInternal(device);
                        throw new LibUsbException("unable to fetch product description", -8);
                    }
                    UsbDescriptor match = null;
                    for (UsbDescriptor udes : descriptions) {
                        if (udes.vid == desc.idVendor() && udes.pid == desc.idProduct() && (udes.product == null || udes.product.equals(sDesc))) {
                            match = udes;
                            break;
                        }
                    }
                    UsbCloseInternal(device);
                    if (match == null)
                        continue;
                    devices.add(new DeviceEntry(match, dev));
                    LibUsb.refDevice(dev);
                }
            }
        } finally {
            // Ensure the allocated device list is freed
            LibUsb.freeDeviceList(list, true);
        }
        // Device not found
        return devices;
    }

    public static void listFree(List<Device> devList) {
        for (Device dev : devList) LibUsb.unrefDevice(dev);
    }

    public static void entryListFree(List<DeviceEntry> devList) {
        for (DeviceEntry dev : devList) LibUsb.unrefDevice(dev.device);
    }

    public DeviceStrings usbGetStrings(Device dev) {
        boolean needOpen = device == null;
        if (needOpen) {
            device = new DeviceHandle();
            if (LibUsb.open(dev, device) < 0)
                throw new LibUsbException("LibUsb.open() failed", -4);
        }
        DeviceDescriptor desc = new DeviceDescriptor();
        if (LibUsb.getDeviceDescriptor(dev, desc) < 0)
            throw new LibUsbException("LibUsb.getDeviceDescriptor() failed", -11);
        DeviceStrings strings = new DeviceStrings();
        strings.product = LibUsb.getStringDescriptor(device, desc.iProduct());
        strings.manufacture = LibUsb.getStringDescriptor(device, desc.iManufacturer());
        strings.serial = LibUsb.getStringDescriptor(device, desc.iSerialNumber());
        if (needOpen)
            UsbCloseInternal();
        return strings;
    }

    protected int determinMaxPacketSize(Device dev, int defSize) {
        int packetSize = defSize;
        DeviceDescriptor desc = new DeviceDescriptor();
        ConfigDescriptor config = new ConfigDescriptor();
        if (dev == null)
            return 64;
        if (LibUsb.getDeviceDescriptor(dev, desc) < 0)
            return packetSize;
        if (LibUsb.getConfigDescriptor(dev, (byte) 0, config) < 0)
            return packetSize;
        if (desc.bNumConfigurations() > 0) {
            if (iface < desc.bNumConfigurations()) {
                Interface iface = config.iface()[0];
                if (iface.numAltsetting() > 0) {
                    InterfaceDescriptor descriptor = iface.altsetting()[0];
                    if (descriptor.bNumEndpoints() > 0) {
                        packetSize = descriptor.endpoint()[0].wMaxPacketSize();
                    }
                }
            }
        }
        LibUsb.freeConfigDescriptor(config);
        return packetSize;
    }

    public void setTimeouts(int read, int write) {
        readTimeout = read;
        writeTimeout = write;
    }

    public void usbOpenDev(Device dev) {
        DeviceDescriptor desc = new DeviceDescriptor();
        ConfigDescriptor config = new ConfigDescriptor();
        int cfg, cfg0, detachErrno = 0, errno;
        IntBuffer cfgBuf = IntBuffer.allocate(1);
        device = new DeviceHandle();
        if (LibUsb.open(dev, device) < 0)
            throw new LibUsbException("LibUsb.open() failed", -8);
        if (LibUsb.getDeviceDescriptor(dev, desc) < 0)
            throw new LibUsbException("LibUsb.getDeviceDescriptior() failed", -9);
        if (LibUsb.getConfigDescriptor(dev, (byte) 0, config) < 0)
            throw new LibUsbException("LibUsb.getConfigDescriptor() failed", -10);
        cfg0 = config.bConfigurationValue();
        LibUsb.freeConfigDescriptor(config);
        if (DetachMode.AUTO_DETACH_SIO_MODULE.equals(detachMode)) {
            if ((errno = LibUsb.detachKernelDriver(device, iface)) != LibUsb.SUCCESS)
                detachErrno = errno;
        } else if (DetachMode.AUTO_DETACH_REATACH_SIO_MODULE.equals(detachMode)) {
            if ((errno = LibUsb.setAutoDetachKernelDriver(device, true)) != LibUsb.SUCCESS)
                detachErrno = errno;
            if (detachErrno == LibUsb.ERROR_NOT_SUPPORTED)
                if ((errno = LibUsb.detachKernelDriver(device, iface)) != LibUsb.SUCCESS)
                    detachErrno = errno;
        }
        if (LibUsb.getConfiguration(device, cfgBuf) < 0)
            throw new LibUsbException("LibUsb.getConfiguration() failed", -12);
        cfg = cfgBuf.get(0);
        if (desc.bNumConfigurations() > 0 && cfg != cfg0) {
            if (LibUsb.setConfiguration(device, cfg0) < 0) {
                UsbCloseInternal();
                if (detachErrno == LibUsb.ERROR_ACCESS)
                    throw new LibUsbException("inappropriate permissions on device!", -8);
                else
                    throw new LibUsbException("unable to set usb configuration. Make sure the default Ftdi driver is not in use", -3);
            }
        }
        if (LibUsb.claimInterface(device, iface) < 0) {
            UsbCloseInternal();
            if (detachErrno == LibUsb.ERROR_ACCESS)
                throw new LibUsbException("inappropriate permissions on device!", -8);
            else
                throw new LibUsbException("unable to claim usb device. Make sure the default Ftdi driver is not in use", -5);
        }
        maxPacketSize = determinMaxPacketSize(dev, 512);
    }

    public boolean usbOpen(short vendor, short product) {
        return usbOpen(vendor, product, null, null);
    }

    public boolean usbOpen(short vendor, short product, String description, String serial) {
        return usbOpen(vendor, product, description, serial, 0);
    }

    public boolean usbOpen(short vendor, short product, String description, String serial, int index) {
        DeviceList devs = new DeviceList();
        if (LibUsb.getDeviceList(context, devs) < 0)
            throw new LibUsbException("LibUsb.getDeviceList() failed", -12);
        try {
            for (Device dev : devs) {
                DeviceDescriptor desc = new DeviceDescriptor();
                if (LibUsb.getDeviceDescriptor(dev, desc) < 0)
                    throw new LibUsbException("LibUsb.getDeviceDescriptor() failed", -13);
                if (desc.idVendor() == vendor && desc.idProduct() == product) {
                    device = new DeviceHandle();
                    if (LibUsb.open(dev, device) < 0)
                        throw new LibUsbException("LibUsb.open() failed", -4);
                    if (description != null) {
                        String sDesc = LibUsb.getStringDescriptor(device, desc.iProduct());
                        if (sDesc == null) {
                            UsbCloseInternal();
                            throw new LibUsbException("unalbe to fetch product description", -8);
                        }
                        if (!description.equals(sDesc)) {
                            UsbCloseInternal();
                            continue;
                        }
                    }
                    if (serial != null) {
                        String sSer = LibUsb.getStringDescriptor(device, desc.iSerialNumber());
                        if (sSer == null) {
                            UsbCloseInternal();
                            throw new LibUsbException("unalbe to fetch serial number", -9);
                        }
                        if (!serial.equals(sSer)) {
                            UsbCloseInternal();
                            continue;
                        }
                    }
                    UsbCloseInternal();
                    if (index > 0) {
                        index--;
                        continue;
                    }
                    usbOpenDev(dev);
                    return true;
                }
            }
        } finally {
            LibUsb.freeDeviceList(devs, true);
        }
        return false;
    }

    public boolean usbOpenBusAddr(int bus, int addr) {
        DeviceList devs = new DeviceList();
        if (LibUsb.getDeviceList(context, devs) < 0)
            throw new LibUsbException("LibUsb.getDeviceList() failed", -12);
        try {
            for (Device dev : devs) {
                if (LibUsb.getBusNumber(dev) == bus && LibUsb.getDeviceAddress(dev) == addr) {
                    usbOpenDev(dev);
                    return true;
                }
            }
        } finally {
            LibUsb.freeDeviceList(devs, true);
        }
        return false;
    }

    public boolean usbOpen(String description) {
        if (description == null || description.isEmpty() || description.charAt(1) != ':')
            throw new LibUsbException("illegal description format", -12);
        if (description.charAt(0) == 'd') {
            DeviceList devs = new DeviceList();
            Pattern p = Pattern.compile(".:(\\d+)\\/(\\d+)");
            Matcher m = p.matcher(description);
            if (!m.matches() || m.groupCount() != 2)
                throw new LibUsbException("illegal description format", -11);
            int busNumber, deviceAddress;
            try {
                busNumber = Integer.parseInt(m.group(1));
                deviceAddress = Integer.parseInt(m.group(2));
            } catch (NumberFormatException e) {
                throw new LibUsbException("illegal description format", -11);
            }
            if (LibUsb.getDeviceList(context, devs) < 0)
                throw new LibUsbException("LibUsb.getDeviceList() failed", -12);
            try {
                for (Device dev : devs) {
                    if (busNumber == LibUsb.getBusNumber(dev) && deviceAddress == LibUsb.getDeviceAddress(dev)) {
                        usbOpenDev(dev);
                        return true;
                    }
                }
            } finally {
                LibUsb.freeDeviceList(devs, true);
            }
        } else if (description.charAt(0) == 'i' || description.charAt(0) == 's') {
            Pattern p = Pattern.compile(".:([\\dx]+):([\\dx]+)(:(.+))?");
            Matcher m = p.matcher(description);
            if (!m.matches())
                throw new LibUsbException("illegal description format", -11);
            int vendor, product, index = 0;
            String serial = null;
            try {
                vendor = Integer.decode(m.group(1));
                product = Integer.decode(m.group(2));
            } catch (NumberFormatException e) {
                throw new LibUsbException("illegal description format", -11);
            }
            if (description.charAt(0) == 'i' && m.groupCount() == 4) {
                try {
                    index = Integer.decode(m.group(4));
                } catch (NumberFormatException e) {
                    throw new LibUsbException("illegal description format", -11);
                }
            }
            if (description.charAt(0) == 's') {
                if (m.groupCount() != 4)
                    throw new LibUsbException("illegal description format", -11);
                serial = m.group(4);
            }
            return usbOpen((short) vendor, (short) product, null, serial, index);
        }
        throw new LibUsbException("illegal description format", -11);
    }

    public boolean usbClose() {
        boolean rtn = true;
        if (device != null)
            if (LibUsb.releaseInterface(device, iface) < 0)
                rtn = false;
        UsbCloseInternal();
        return rtn;
    }

    public int writeData(byte[] data) {
        int offset = 0;
        ByteBuffer buf = ByteBuffer.allocateDirect(data.length);
        buf.put(data);
        IntBuffer transferred = IntBuffer.allocate(1);
        if (device == null)
            throw new LibUsbException("USB device unavailable", -666);
        while (offset < data.length) {
            int writeSize = writeBufferChunksize;
            if (offset + writeSize > data.length)
                writeSize = data.length - offset;
            buf.position(offset);
            int code;
            if ((code = LibUsb.bulkTransfer(device, inEndPoint, buf, transferred, writeTimeout)) < 0)
                throw new LibUsbException("usb bulk write failed", code);
            offset += transferred.get();
        }
        return offset;
    }

    public int transferDataDone(TransferControl tc) {
        int ret;
        while (tc.completed.get(0) == 0) {
            ret = LibUsb.handleEventsTimeoutCompleted(context, 0, tc.completed);
            if (ret < 0) {
                if (ret == LibUsb.ERROR_INTERRUPTED)
                    continue;
                LibUsb.cancelTransfer(tc.transfer);
                while (tc.completed.get(0) == 0) if (LibUsb.handleEventsTimeoutCompleted(context, 0, tc.completed) < 0)
                    break;
                LibUsb.freeTransfer(tc.transfer);
                return ret;
            }
        }
        ret = tc.offset;
        if (tc.transfer != null) {
            if (tc.transfer.status() != LibUsb.TRANSFER_COMPLETED)
                ret = -1;
            LibUsb.freeTransfer(tc.transfer);
        }
        return ret;
    }

    public void transferDataCancel(TransferControl tc, long timeout) {
        if (tc.completed.get(0) == 0 && tc.transfer != null) {
            LibUsb.cancelTransfer(tc.transfer);
            while (tc.completed.get(0) == 0) {
                if (LibUsb.handleEventsTimeoutCompleted(context, timeout, tc.completed) < 0)
                    break;
            }
        }
        if (tc.transfer != null)
            LibUsb.freeTransfer(tc.transfer);
    }

    public void writeDataSetChunksize(int chunksize) {
        writeBufferChunksize = chunksize;
    }

    public int writeDataGetChunksize() {
        return writeBufferChunksize;
    }

    public void readDataWithTimeout(byte[] data) {
        byte[] buffer = new byte[data.length];
        int reqBytes = data.length;
        int offset = 0;
        long startTime = System.currentTimeMillis();
        while (reqBytes > 0) {
            if (buffer.length != reqBytes)
                buffer = new byte[reqBytes];
            int ct = readData(buffer);
            if (ct > 0) {
                System.arraycopy(buffer, 0, data, offset, ct);
                offset += ct;
                reqBytes -= ct;
            }
            if (System.currentTimeMillis() - startTime > readTimeout)
                throw new LibUsbException("Reading " + data.length + " bytes took longer than 2 seconds!", -1);
        }
    }

    public int readData(byte[] buf) {
        int offset = 0, ret;
        int packet_size;
        IntBuffer actual_length_buf = IntBuffer.allocate(1);
        int actual_length = 1;
        if (device == null)
            throw new LibUsbException("USB device unavailable", -666);
        // Packet size sanity check (avoid division by zero)
        packet_size = maxPacketSize;
        if (packet_size == 0)
            throw new LibUsbException("max_packet_size is bogus (zero)", -1);
        // everything we want is still in the readbuffer?
        if (buf.length <= readBuffer.remaining()) {
            readBuffer.get(buf);
            return buf.length;
        }
        // something still in the readbuffer, but not enough to satisfy 'size'?
        if (readBuffer.remaining() != 0) {
            offset += readBuffer.remaining();
            readBuffer.get(buf, 0, readBuffer.remaining());
        }
        // do the actual USB read
        while (offset < buf.length && actual_length > 0) {
            readBuffer.clear();
            /* returns how much received */
            actual_length_buf.clear();
            ret = LibUsb.bulkTransfer(device, outEndPoint, readBuffer, actual_length_buf, readTimeout);
            actual_length = actual_length_buf.get();
            readBuffer.limit(actual_length);
            if (ret < 0)
                throw new LibUsbException("usb bulk read failed", ret);
            if (actual_length <= 0) {
                // no more data to read?
                resetReadBuffer();
                return offset;
            }
            if (readBuffer.remaining() > 0) {
                // data still fits in buf?
                if (offset + actual_length <= buf.length) {
                    readBuffer.get(buf, offset, actual_length);
                    offset += actual_length;
                    /* Did we read exactly the right amount of bytes? */
                    if (offset == buf.length)
                        return offset;
                } else {
                    // only copy part of the data or size <= readbuffer_chunksize
                    int part_size = buf.length - offset;
                    readBuffer.get(buf, offset, part_size);
                    offset += part_size;
                    return offset;
                }
            }
        }
        // never reached
        return -127;
    }

    public void flushReadBuffer() {
        resetReadBuffer();
        byte[] dummyBuffer = new byte[maxPacketSize];
        int oldTimeout = readTimeout;
        readTimeout = 100;
        try {
            // flush the buffer
            readData(dummyBuffer);
        } catch (LibUsbException e) {
        }
        readTimeout = oldTimeout;
    }

    public void resetReadBuffer() {
        readBuffer.clear();
        readBuffer.limit(0);
    }

    public void readDataSetChunkSize(int chunksize) {
        /*
		 * We can't set readbuffer_chunksize larger than MAX_BULK_BUFFER_LENGTH, which is defined in libusb-1.0. Otherwise, each USB read request will be divided into multiple
		 * URBs. This will cause issues on Linux kernel older than 2.6.32.
		 */
        if (Util.isLinux && chunksize > 16384)
            chunksize = 16384;
        readBuffer = ByteBuffer.allocateDirect(chunksize);
        readBuffer.limit(0);
        readBufferChunksize = chunksize;
    }

    public int readDataGetChunkSize() {
        return readBufferChunksize;
    }
}

16 View Complete Implementation : TransferModule.java
Copyright GNU General Public License v3.0
Author : developersu
public abstract clreplaced TransferModule {

    EFileStatus status = EFileStatus.UNKNOWN;

    LinkedHashMap<String, File> nspMap;

    LogPrinter logPrinter;

    DeviceHandle handlerNS;

    Task<Void> task;

    TransferModule(DeviceHandle handler, LinkedHashMap<String, File> nspMap, Task<Void> task, LogPrinter printer) {
        this.handlerNS = handler;
        this.nspMap = nspMap;
        this.task = task;
        this.logPrinter = printer;
        // Validate split files to be sure that there is no crap
        logPrinter.print("TransferModule: Validating split files ...", EMsgType.INFO);
        Iterator<Map.Entry<String, File>> iterator = nspMap.entrySet().iterator();
        while (iterator.hasNext()) {
            File f = iterator.next().getValue();
            if (f.isDirectory()) {
                File[] subFiles = f.listFiles((file, name) -> name.matches("[0-9]{2}"));
                if (subFiles == null || subFiles.length == 0) {
                    logPrinter.print("TransferModule: Removing empty folder: " + f.getName(), EMsgType.WARNING);
                    iterator.remove();
                } else {
                    Arrays.sort(subFiles, Comparator.comparingInt(file -> Integer.parseInt(file.getName())));
                    for (int i = subFiles.length - 2; i > 0; i--) {
                        if (subFiles[i].length() < subFiles[i - 1].length()) {
                            logPrinter.print("TransferModule: Removing strange split file: " + f.getName() + "\n      (Chunk sizes of the split file are not the same, but has to be.)", EMsgType.WARNING);
                            iterator.remove();
                        }
                    // what
                    }
                // a
                }
            // nice
            }
        // stairway
        }
        // here =)
        logPrinter.print("TransferModule: Validation complete.", EMsgType.INFO);
    }

    public EFileStatus getStatus() {
        return status;
    }
}

16 View Complete Implementation : TransferTest.java
Copyright MIT License
Author : usb4java
/**
 * Sets the device handle pointer via reflection.
 *
 * @param handle
 *            The device handle pointer.
 * @param pointer
 *            The pointer to set.
 */
private void setPointer(final DeviceHandle handle, final long pointer) {
    try {
        final Field field = DeviceHandle.clreplaced.getDeclaredField("deviceHandlePointer");
        field.setAccessible(true);
        field.set(handle, pointer);
    } catch (final Exception e) {
        throw new RuntimeException(e.toString(), e);
    }
}

16 View Complete Implementation : AbstractDevice.java
Copyright MIT License
Author : usb4java
@Override
public final UsbStringDescriptor getUsbStringDescriptor(final byte index) throws UsbException {
    checkConnected();
    final short[] languages = getLanguages();
    final DeviceHandle handle = open();
    final short langId = languages.length == 0 ? 0 : languages[0];
    final ByteBuffer data = ByteBuffer.allocateDirect(256);
    final int result = LibUsb.getStringDescriptor(handle, index, langId, data);
    if (result < 0) {
        throw ExceptionUtils.createPlatformException("Unable to get string descriptor " + index + " from device " + this, result);
    }
    return new SimpleUsbStringDescriptor(data);
}

15 View Complete Implementation : FCDTunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
public abstract clreplaced FCDTunerController extends TunerController {

    private final static Logger mLog = LoggerFactory.getLogger(FCDTunerController.clreplaced);

    public static final double USABLE_BANDWIDTH_PERCENT = 1.0;

    public static final int DC_SPIKE_AVOID_BUFFER = 5000;

    public final static byte FCD_INTERFACE = (byte) 0x2;

    public final static byte FCD_ENDPOINT_IN = (byte) 0x82;

    public final static byte FCD_ENDPOINT_OUT = (byte) 0x2;

    private Device mDevice;

    private DeviceDescriptor mDeviceDescriptor;

    private DeviceHandle mDeviceHandle;

    private FCDConfiguration mConfiguration = new FCDConfiguration();

    protected ComplexMixer mComplexMixer;

    /**
     * Generic FCD tuner controller - contains functionality common across both
     * funcube dongle tuners
     *
     * @param device
     * @param descriptor
     * @param minTunableFrequency
     * @param maxTunableFrequency
     */
    public FCDTunerController(MixerTunerDataLine mixerTDL, Device device, DeviceDescriptor descriptor, String tunerName, int minTunableFrequency, int maxTunableFrequency, AudioFormat audioFormat) {
        super(minTunableFrequency, maxTunableFrequency, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT);
        mDevice = device;
        mDeviceDescriptor = descriptor;
        try {
            mFrequencyController.setSampleRate((int) audioFormat.getSampleRate());
        } catch (SourceException se) {
            mLog.error("Error setting sample rate to [" + audioFormat.getSampleRate() + "]", se);
        }
        mComplexMixer = new ComplexMixer(mixerTDL.getTargetDataLine(), audioFormat, tunerName, new ComplexShortAdapter(mixerTDL.getMixerTunerType().getDisplayString()));
        mComplexMixer.setBufferSize(audioFormat.getFrameSize() * getBufferSampleCount());
        mComplexMixer.setBufferListener(mReusableBufferBroadcaster);
    }

    @Override
    public int getBufferSampleCount() {
        return (int) (mComplexMixer.getAudioFormat().getSampleRate() * 0.1);
    }

    /**
     * Overrides the super clreplaced functionality to auto-start the complex mixer and provide samples to listeners
     */
    @Override
    public void addBufferListener(Listener<ReusableComplexBuffer> listener) {
        boolean hasExistingListeners = hasBufferListeners();
        super.addBufferListener(listener);
        if (!hasExistingListeners) {
            mComplexMixer.start();
        }
    }

    /**
     * Overrides the super clreplaced functionality to auto-stop the complex mixer and stop sample stream when there are no
     * more registered listeners
     */
    @Override
    public void removeBufferListener(Listener<ReusableComplexBuffer> listener) {
        super.removeBufferListener(listener);
        if (!hasBufferListeners()) {
            mComplexMixer.stop();
        }
    }

    /**
     * Initializes the controller by opening the USB device and claiming the
     * HID interface.
     *
     * Invoke this method after constructing this clreplaced to setup the
     * controller.
     *
     * @throws SourceException if cannot open and claim the USB device
     */
    public void init() throws SourceException {
        mDeviceHandle = new DeviceHandle();
        int result = LibUsb.open(mDevice, mDeviceHandle);
        if (result != LibUsb.SUCCESS) {
            mDeviceHandle = null;
            throw new SourceException("libusb couldn't open funcube usb device [" + LibUsb.errorName(result) + "]");
        }
        claimInterface();
    }

    /**
     * Disposes of resources.  Closes the USB device and interface.
     */
    public void dispose() {
        if (mDeviceHandle != null) {
            try {
                LibUsb.close(mDeviceHandle);
            } catch (Exception e) {
                mLog.error("error while closing device handle", e);
            }
            mDeviceHandle = null;
        }
        mDeviceDescriptor = null;
        mDevice = null;
    }

    /**
     * Sample rate of the tuner
     */
    public abstract double getCurrentSampleRate();

    /**
     * Tuner clreplaced
     */
    public abstract TunerClreplaced getTunerClreplaced();

    /**
     * Tuner type
     */
    public abstract TunerType getTunerType();

    /**
     * Applies the settings in the tuner configuration
     */
    public abstract void apply(TunerConfiguration config) throws SourceException;

    /**
     * USB address (bus/port)
     */
    public String getUSBAddress() {
        if (mDevice != null) {
            StringBuilder sb = new StringBuilder();
            sb.append("Bus:");
            int bus = LibUsb.getBusNumber(mDevice);
            sb.append(bus);
            sb.append(" Port:");
            int port = LibUsb.getPortNumber(mDevice);
            sb.append(port);
            return sb.toString();
        }
        return "UNKNOWN";
    }

    /**
     * USB Vendor and Product ID
     */
    public String getUSBID() {
        if (mDeviceDescriptor != null) {
            StringBuilder sb = new StringBuilder();
            sb.append(String.format("%04X", (int) (mDeviceDescriptor.idVendor() & 0xFFFF)));
            sb.append(":");
            sb.append(String.format("%04X", (int) (mDeviceDescriptor.idProduct() & 0xFFFF)));
            return sb.toString();
        }
        return "UNKNOWN";
    }

    /**
     * USB Port Speed.  Should be 2.0 for both types of funcube dongles
     */
    public String getUSBSpeed() {
        if (mDevice != null) {
            int speed = LibUsb.getDeviceSpeed(mDevice);
            switch(speed) {
                case 0:
                    return "1.1 LOW";
                case 1:
                    return "1.1 FULL";
                case 2:
                    return "2.0 HIGH";
                case 3:
                    return "3.0 SUPER";
                default:
            }
        }
        return "UNKNOWN";
    }

    /**
     * Set fcd interface mode
     */
    public void setFCDMode(Mode mode) throws UsbException, UsbClaimException {
        ByteBuffer response = null;
        switch(mode) {
            case APPLICATION:
                response = send(FCDCommand.BL_QUERY);
                break;
            case BOOTLOADER:
                response = send(FCDCommand.APP_RESET);
                break;
            default:
                break;
        }
        if (response != null) {
            mConfiguration.set(response);
        } else {
            mConfiguration.setModeUnknown();
        }
    }

    /**
     * Sets the actual (uncorrected) device frequency
     */
    public void setTunedFrequency(long frequency) throws SourceException {
        try {
            send(FCDCommand.APP_SET_FREQUENCY_HZ, frequency);
        } catch (Exception e) {
            throw new SourceException("Couldn't set FCD Local " + "Oscillator Frequency [" + frequency + "]", e);
        }
    }

    /**
     * Gets the actual (uncorrected) device frequency
     */
    public long getTunedFrequency() throws SourceException {
        try {
            ByteBuffer buffer = send(FCDCommand.APP_GET_FREQUENCY_HZ);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            return (int) (buffer.getInt(2) & 0xFFFFFFFF);
        } catch (Exception e) {
            throw new SourceException("FCDTunerController - " + "couldn't get LO frequency", e);
        }
    }

    /**
     * Returns the FCD device configuration
     */
    public FCDConfiguration getConfiguration() {
        return mConfiguration;
    }

    /**
     * Claims the USB interface.  Attempts to detach the active kernel driver if
     * one is currently attached.
     */
    private void claimInterface() throws SourceException {
        if (mDeviceHandle != null) {
            int result = LibUsb.kernelDriverActive(mDeviceHandle, FCD_INTERFACE);
            if (result == 1) {
                result = LibUsb.detachKernelDriver(mDeviceHandle, FCD_INTERFACE);
                if (result != LibUsb.SUCCESS) {
                    mLog.error("failed attempt to detach kernel driver [" + LibUsb.errorName(result) + "]");
                }
            }
            result = LibUsb.claimInterface(mDeviceHandle, FCD_INTERFACE);
            if (result != LibUsb.SUCCESS) {
                throw new SourceException("couldn't claim usb interface [" + LibUsb.errorName(result) + "]");
            }
        } else {
            throw new SourceException("couldn't claim usb hid interface - no device handle");
        }
    }

    /**
     * Performs an interrupt write to the OUT endpoint.
     *
     * @param buffer - direct allocated buffer.  Must be 64 bytes in length.
     * @throws LibUsbException on error
     */
    private void write(ByteBuffer buffer) throws LibUsbException {
        if (mDeviceHandle != null) {
            IntBuffer transferred = IntBuffer.allocate(1);
            int result = LibUsb.interruptTransfer(mDeviceHandle, FCD_ENDPOINT_OUT, buffer, transferred, 500l);
            if (result != LibUsb.SUCCESS) {
                throw new LibUsbException("error writing byte buffer", result);
            }
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    /**
     * Performs an interrupt write to the OUT endpoint for the FCD command.
     *
     * @param command - no-argument command to write
     * @throws LibUsbException - on error
     */
    private void write(FCDCommand command) throws LibUsbException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(64);
        buffer.put(0, command.getCommand());
        buffer.put(1, (byte) 0x00);
        write(buffer);
    }

    /**
     * Convenience logger for debugging read/write operations
     */
    @SuppressWarnings("unused")
    private void log(String label, ByteBuffer buffer) {
        StringBuilder sb = new StringBuilder();
        sb.append(label);
        sb.append(" ");
        sb.append(buffer.get(0));
        sb.append(" | ");
        for (int x = 0; x < 64; x++) {
            sb.append(String.format("%02X", (int) (buffer.get(x) & 0xFF)));
            sb.append(" ");
        }
        mLog.debug(sb.toString());
    }

    /**
     * Performs an interrupt write to the OUT endpoint for the FCD command.
     *
     * @param command - command to write
     * @param argument - value to write with the command
     * @throws LibUsbException - on error
     */
    private void write(FCDCommand command, long argument) throws LibUsbException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(64);
        /* The FCD expects little-endian formatted values */
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.put(0, command.getCommand());
        buffer.putLong(1, argument);
        write(buffer);
    }

    /**
     * Performs an interrupt read against the endpoint
     *
     * @return buffer read from FCD
     * @throws LibUsbException on error
     */
    private ByteBuffer read() throws LibUsbException {
        if (mDeviceHandle != null) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(64);
            IntBuffer transferred = IntBuffer.allocate(1);
            int result = LibUsb.interruptTransfer(mDeviceHandle, FCD_ENDPOINT_IN, buffer, transferred, 500l);
            if (result != LibUsb.SUCCESS) {
                throw new LibUsbException("error reading byte buffer", result);
            } else if (transferred.get(0) != buffer.capacity()) {
                throw new LibUsbException("received bytes [" + transferred.get(0) + "] didn't match expected length [" + buffer.capacity() + "]", result);
            }
            return buffer;
        }
        throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
    }

    /**
     * Sends the FCD command and argument.  Performs a read to complete the
     * command.
     *
     * @param command - command to send
     * @param argument - command argument to send
     * @throws LibUsbException - on error
     */
    protected void send(FCDCommand command, long argument) throws LibUsbException {
        write(command, argument);
        read();
    }

    /**
     * Sends the no-argument FCD command.  Performs a read to complete the
     * command.
     *
     * @param command - command to send
     * @throws LibUsbException - on error
     */
    protected ByteBuffer send(FCDCommand command) throws LibUsbException {
        write(command);
        return read();
    }

    /**
     * FCD configuration string parsing  clreplaced
     */
    public clreplaced FCDConfiguration {

        private String mConfig;

        private Mode mMode;

        public FCDConfiguration() {
            mConfig = null;
            mMode = Mode.UNKNOWN;
        }

        private void setModeUnknown() {
            mConfig = null;
            mMode = Mode.UNKNOWN;
        }

        /**
         * Extracts the configuration string from the buffer
         */
        public void set(ByteBuffer buffer) {
            if (buffer.capacity() == 64) {
                byte[] data = new byte[64];
                for (int x = 0; x < 64; x++) {
                    data[x] = buffer.get(x);
                }
                mConfig = new String(data);
                mMode = Mode.getMode(mConfig);
            } else {
                mConfig = null;
                mMode = Mode.ERROR;
            }
        }

        public Mode getMode() {
            return mMode;
        }

        public FCDModel getModel() {
            FCDModel retVal = FCDModel.FUNCUBE_UNKNOWN;
            switch(mMode) {
                case APPLICATION:
                    retVal = FCDModel.getFCD(mConfig.substring(15, 22));
                    break;
                case BOOTLOADER:
                case UNKNOWN:
                case ERROR:
                    break;
            }
            return retVal;
        }

        public Block getBandBlocking() {
            Block retVal = Block.UNKNOWN;
            switch(mMode) {
                case APPLICATION:
                    retVal = Block.getBlock(mConfig.substring(23, 33).trim());
                    break;
                case BOOTLOADER:
                case UNKNOWN:
                case ERROR:
                    break;
            }
            return retVal;
        }

        public String getFirmware() {
            String retVal = null;
            switch(mMode) {
                case APPLICATION:
                    retVal = mConfig.substring(9, 14);
                    break;
                case BOOTLOADER:
                case UNKNOWN:
                case ERROR:
                    break;
            }
            return retVal;
        }

        public String toString() {
            return getModel().getLabel();
        }
    }

    public enum Mode {

        APPLICATION, BOOTLOADER, ERROR, UNKNOWN;

        public static Mode getMode(String config) {
            Mode retVal = UNKNOWN;
            if (config == null) {
                retVal = ERROR;
            } else {
                if (config.length() >= 8) {
                    String mode = config.substring(2, 8).trim();
                    if (mode.equalsIgnoreCase("FCDAPP")) {
                        retVal = APPLICATION;
                    } else if (mode.equalsIgnoreCase("FCDBL")) {
                        retVal = BOOTLOADER;
                    }
                }
            }
            return retVal;
        }
    }

    public enum Block {

        CELLULAR_BAND_BLOCKED("Blocked"), NO_BAND_BLOCK("Unblocked"), UNKNOWN("Unknown");

        private String mLabel;

        private Block(String label) {
            mLabel = label;
        }

        public String getLabel() {
            return mLabel;
        }

        public static Block getBlock(String block) {
            Block retVal = UNKNOWN;
            if (block.equalsIgnoreCase("No blk")) {
                retVal = NO_BAND_BLOCK;
            } else if (block.equalsIgnoreCase("Cell blk")) {
                retVal = CELLULAR_BAND_BLOCKED;
            }
            return retVal;
        }
    }
}

15 View Complete Implementation : AbstractDevice.java
Copyright MIT License
Author : usb4java
/**
 * A Usb device.
 *
 * @author Klaus Reimer ([email protected])
 */
abstract clreplaced AbstractDevice implements UsbDevice {

    /**
     * The USB device manager.
     */
    private final DeviceManager manager;

    /**
     * The device id.
     */
    private final DeviceId id;

    /**
     * The parent id. Null if no parent exists.
     */
    private final DeviceId parentId;

    /**
     * The device speed.
     */
    private final int speed;

    /**
     * The device configurations.
     */
    private List<Configuration> configurations;

    /**
     * Mapping from configuration value to configuration.
     */
    private Map<Byte, Configuration> configMapping = new HashMap<Byte, Configuration>();

    /**
     * The USB device listener list.
     */
    private final DeviceListenerList listeners = new DeviceListenerList();

    /**
     * The device handle. Null if not open.
     */
    private DeviceHandle handle;

    /**
     * The number of the currently active configuration.
     */
    private byte activeConfigurationNumber = 0;

    /**
     * The numbers of the currently claimed interface.
     */
    private Set<Byte> claimedInterfaceNumbers = new HashSet<Byte>();

    /**
     * The port this device is connected to.
     */
    private UsbPort port;

    /**
     * The IRP queue.
     */
    private final ControlIrpQueue queue = new ControlIrpQueue(this, this.listeners);

    /**
     * If kernel driver was detached when interface was claimed.
     */
    private boolean detachedKernelDriver;

    /**
     * Constructs a new device.
     *
     * @param manager
     *            The USB device manager which is responsible for this device.
     * @param id
     *            The device id. Must not be null.
     * @param parentId
     *            The parent device id. May be null if this device has no parent
     *            (Because it is a root device).
     * @param speed
     *            The device speed.
     * @param device
     *            The libusb device. This reference is only valid during the
     *            constructor execution, so don't store it in a property or
     *            something like that.
     * @throws UsbPlatformException
     *             When device configuration could not be read.
     */
    AbstractDevice(final DeviceManager manager, final DeviceId id, final DeviceId parentId, final int speed, final Device device) throws UsbPlatformException {
        if (manager == null)
            throw new IllegalArgumentException("manager must be set");
        if (id == null)
            throw new IllegalArgumentException("id must be set");
        this.manager = manager;
        this.id = id;
        this.parentId = parentId;
        this.speed = speed;
        // Read device configurations
        final int numConfigurations = id.getDeviceDescriptor().bNumConfigurations() & 0xff;
        final List<Configuration> configurations = new ArrayList<Configuration>(numConfigurations);
        for (int i = 0; i < numConfigurations; i += 1) {
            final ConfigDescriptor configDescriptor = new ConfigDescriptor();
            final int result = LibUsb.getConfigDescriptor(device, (byte) i, configDescriptor);
            if (result < 0) {
                throw ExceptionUtils.createPlatformException("Unable to get configuration " + i + " for device " + id, result);
            }
            try {
                final Configuration config = new Configuration(this, configDescriptor);
                configurations.add(config);
                this.configMapping.put(configDescriptor.bConfigurationValue(), config);
            } finally {
                LibUsb.freeConfigDescriptor(configDescriptor);
            }
        }
        this.configurations = Collections.unmodifiableList(configurations);
        // Determine the active configuration number
        final ConfigDescriptor configDescriptor = new ConfigDescriptor();
        final int result = LibUsb.getActiveConfigDescriptor(device, configDescriptor);
        // ERROR_NOT_FOUND is returned when device is in unconfigured state.
        // On OSX it may return INVALID_PARAM in this case because of a bug
        // in libusb
        if (result == LibUsb.ERROR_NOT_FOUND || result == LibUsb.ERROR_INVALID_PARAM) {
            this.activeConfigurationNumber = 0;
        } else if (result < 0) {
            throw ExceptionUtils.createPlatformException("Unable to read active config descriptor from device " + id, result);
        } else {
            this.activeConfigurationNumber = configDescriptor.bConfigurationValue();
            LibUsb.freeConfigDescriptor(configDescriptor);
        }
    }

    /**
     * Returns the device id.
     *
     * @return The device id.
     */
    public final DeviceId getId() {
        return this.id;
    }

    /**
     * Returns the parent device id.
     *
     * @return The parent device id or null of there is no parent.
     */
    public final DeviceId getParentId() {
        return this.parentId;
    }

    /**
     * Ensures the device is connected.
     *
     * @throws UsbDisconnectedException
     *             When device is disconnected.
     */
    final void checkConnected() {
        if (this.port == null)
            throw new UsbDisconnectedException();
    }

    /**
     * Opens the USB device and returns the USB device handle. If device was
     * already open then the old handle is returned.
     *
     * @return The USB device handle.
     * @throws UsbException
     *             When USB device could not be opened.
     */
    public final DeviceHandle open() throws UsbException {
        if (this.handle == null) {
            final Device device = this.manager.getLibUsbDevice(this.id);
            try {
                final DeviceHandle handle = new DeviceHandle();
                final int result = LibUsb.open(device, handle);
                if (result < 0) {
                    throw ExceptionUtils.createPlatformException("Can't open device " + this.id, result);
                }
                this.handle = handle;
            } finally {
                this.manager.releaseDevice(device);
            }
        }
        return this.handle;
    }

    /**
     * Closes the device. If device is not open then nothing is done.
     */
    public final void close() {
        if (this.handle != null) {
            LibUsb.close(this.handle);
            this.handle = null;
        }
    }

    @Override
    public final UsbPort getParentUsbPort() {
        checkConnected();
        return this.port;
    }

    /**
     * Sets the parent USB port. If port is unset then a usbDeviceDetached event
     * is send.
     *
     * @param port
     *            The port to set. Null to unset.
     */
    final void setParentUsbPort(final UsbPort port) {
        if (this.port == null && port == null)
            throw new IllegalStateException("Device already detached");
        if (this.port != null && port != null)
            throw new IllegalStateException("Device already attached");
        // Disconnect client devices
        if (port == null && isUsbHub()) {
            final Hub hub = (Hub) this;
            for (final AbstractDevice device : hub.getAttachedUsbDevices()) {
                hub.disconnectUsbDevice(device);
            }
        }
        this.port = port;
        final Services services = Services.getInstance();
        if (port == null) {
            this.listeners.usbDeviceDetached(new UsbDeviceEvent(this));
            services.usbDeviceDetached(this);
        } else {
            services.usbDeviceAttached(this);
        }
    }

    @Override
    public final String getManufacturerString() throws UsbException, UnsupportedEncodingException {
        checkConnected();
        final byte index = getUsbDeviceDescriptor().iManufacturer();
        if (index == 0)
            return null;
        return getString(index);
    }

    @Override
    public final String getSerialNumberString() throws UsbException, UnsupportedEncodingException {
        checkConnected();
        final byte index = getUsbDeviceDescriptor().iSerialNumber();
        if (index == 0)
            return null;
        return getString(index);
    }

    @Override
    public final String getProductString() throws UsbException, UnsupportedEncodingException {
        checkConnected();
        final byte index = getUsbDeviceDescriptor().iProduct();
        if (index == 0)
            return null;
        return getString(index);
    }

    @Override
    public final Object getSpeed() {
        switch(this.speed) {
            case LibUsb.SPEED_FULL:
                return UsbConst.DEVICE_SPEED_FULL;
            case LibUsb.SPEED_LOW:
                return UsbConst.DEVICE_SPEED_LOW;
            default:
                return UsbConst.DEVICE_SPEED_UNKNOWN;
        }
    }

    @Override
    public final List<Configuration> getUsbConfigurations() {
        return this.configurations;
    }

    @Override
    public final Configuration getUsbConfiguration(final byte number) {
        return this.configMapping.get(number);
    }

    @Override
    public final boolean containsUsbConfiguration(final byte number) {
        return this.configMapping.containsKey(number);
    }

    @Override
    public final byte getActiveUsbConfigurationNumber() {
        return this.activeConfigurationNumber;
    }

    /**
     * Sets the active USB configuration.
     *
     * @param number
     *            The number of the USB configuration to activate.
     * @throws UsbException
     *             When configuration could not be activated.
     */
    final void setActiveUsbConfigurationNumber(final byte number) throws UsbException {
        if (number != this.activeConfigurationNumber) {
            if (!this.claimedInterfaceNumbers.isEmpty())
                throw new UsbException("Can't change configuration while an " + "interface is still claimed");
            final int result = LibUsb.setConfiguration(open(), number & 0xff);
            if (result < 0)
                throw ExceptionUtils.createPlatformException("Unable to set configuration", result);
            this.activeConfigurationNumber = number;
        }
    }

    /**
     * Claims the specified interface.
     *
     * @param number
     *            The number of the interface to claim.
     * @param force
     *            If claim should be forces if possible.
     * @throws UsbException
     *             When interface could not be claimed.
     */
    final void claimInterface(final byte number, final boolean force) throws UsbException {
        if (this.claimedInterfaceNumbers.contains(number))
            throw new UsbClaimException("An interface is already claimed");
        final DeviceHandle handle = open();
        // Detach existing driver from the device if requested and
        // libusb supports it.
        if (force) {
            int result = LibUsb.kernelDriverActive(handle, number);
            if (result == LibUsb.ERROR_NO_DEVICE)
                throw new UsbDisconnectedException();
            if (result == 1) {
                result = LibUsb.detachKernelDriver(handle, number);
                if (result < 0) {
                    throw ExceptionUtils.createPlatformException("Unable to detach kernel driver", result);
                }
                this.detachedKernelDriver = true;
            }
        }
        final int result = LibUsb.claimInterface(handle, number & 0xff);
        if (result < 0) {
            throw ExceptionUtils.createPlatformException("Unable to claim interface", result);
        }
        this.claimedInterfaceNumbers.add(number);
    }

    /**
     * Releases a claimed interface.
     *
     * @param number
     *            The number of the interface to release.
     * @throws UsbException
     *             When interface could not be claimed.
     */
    final void releaseInterface(final byte number) throws UsbException {
        if (this.claimedInterfaceNumbers.isEmpty())
            throw new UsbClaimException("No interface is claimed");
        if (!this.claimedInterfaceNumbers.contains(number))
            throw new UsbClaimException("Interface not claimed");
        final DeviceHandle handle = open();
        int result = LibUsb.releaseInterface(handle, number & 0xff);
        if (result < 0) {
            throw ExceptionUtils.createPlatformException("Unable to release interface", result);
        }
        if (this.detachedKernelDriver) {
            result = LibUsb.attachKernelDriver(handle, number & 0xff);
            if (result < 0) {
                throw ExceptionUtils.createPlatformException("Unable to re-attach kernel driver", result);
            }
        }
        this.claimedInterfaceNumbers.remove(number);
    }

    /**
     * Checks if the specified interface is claimed.
     *
     * @param number
     *            The number of the interface to check.
     * @return True if interface is claimed, false if not.
     */
    final boolean isInterfaceClaimed(final byte number) {
        return this.claimedInterfaceNumbers.contains(number);
    }

    @Override
    public final Configuration getActiveUsbConfiguration() {
        return getUsbConfiguration(getActiveUsbConfigurationNumber());
    }

    @Override
    public final boolean isConfigured() {
        return getActiveUsbConfigurationNumber() != 0;
    }

    @Override
    public final UsbDeviceDescriptor getUsbDeviceDescriptor() {
        return this.id.getDeviceDescriptor();
    }

    @Override
    public final UsbStringDescriptor getUsbStringDescriptor(final byte index) throws UsbException {
        checkConnected();
        final short[] languages = getLanguages();
        final DeviceHandle handle = open();
        final short langId = languages.length == 0 ? 0 : languages[0];
        final ByteBuffer data = ByteBuffer.allocateDirect(256);
        final int result = LibUsb.getStringDescriptor(handle, index, langId, data);
        if (result < 0) {
            throw ExceptionUtils.createPlatformException("Unable to get string descriptor " + index + " from device " + this, result);
        }
        return new SimpleUsbStringDescriptor(data);
    }

    @Override
    public final String getString(final byte index) throws UsbException, UnsupportedEncodingException {
        return getUsbStringDescriptor(index).getString();
    }

    /**
     * Returns the languages the specified device supports.
     *
     * @return Array with supported language codes. Never null. May be empty.
     * @throws UsbException
     *             When string descriptor languages could not be read.
     */
    private short[] getLanguages() throws UsbException {
        final DeviceHandle handle = open();
        final ByteBuffer buffer = ByteBuffer.allocateDirect(256);
        final int result = LibUsb.getDescriptor(handle, LibUsb.DT_STRING, (byte) 0, buffer);
        if (result < 0) {
            throw ExceptionUtils.createPlatformException("Unable to get string descriptor languages", result);
        }
        if (result < 2)
            throw new UsbException("Received illegal descriptor length: " + result);
        final short[] languages = new short[(result - 2) / 2];
        if (languages.length == 0)
            return languages;
        buffer.position(2);
        buffer.order(ByteOrder.LITTLE_ENDIAN).replacedhortBuffer().get(languages);
        return languages;
    }

    @Override
    public final void syncSubmit(final UsbControlIrp irp) throws UsbException {
        if (irp == null)
            throw new IllegalArgumentException("irp must not be null");
        checkConnected();
        this.queue.add(irp);
        irp.waitUntilComplete();
        if (irp.isUsbException())
            throw irp.getUsbException();
    }

    @Override
    public final void asyncSubmit(final UsbControlIrp irp) {
        if (irp == null)
            throw new IllegalArgumentException("irp must not be null");
        checkConnected();
        this.queue.add(irp);
    }

    @Override
    public final void syncSubmit(final List list) throws UsbException {
        if (list == null)
            throw new IllegalArgumentException("list must not be null");
        checkConnected();
        for (final Object item : list) {
            if (!(item instanceof UsbControlIrp))
                throw new IllegalArgumentException("List contains non-UsbControlIrp objects");
            syncSubmit((UsbControlIrp) item);
        }
    }

    @Override
    public final void asyncSubmit(final List list) {
        if (list == null)
            throw new IllegalArgumentException("list must not be null");
        checkConnected();
        for (final Object item : list) {
            if (!(item instanceof UsbControlIrp))
                throw new IllegalArgumentException("List contains non-UsbControlIrp objects");
            asyncSubmit((UsbControlIrp) item);
        }
    }

    @Override
    public final UsbControlIrp createUsbControlIrp(final byte bmRequestType, final byte bRequest, final short wValue, final short wIndex) {
        return new DefaultUsbControlIrp(bmRequestType, bRequest, wValue, wIndex);
    }

    @Override
    public final void addUsbDeviceListener(final UsbDeviceListener listener) {
        this.listeners.add(listener);
    }

    @Override
    public final void removeUsbDeviceListener(final UsbDeviceListener listener) {
        this.listeners.remove(listener);
    }

    @Override
    public final String toString() {
        return this.id.toString();
    }
}

15 View Complete Implementation : IrpQueue.java
Copyright MIT License
Author : usb4java
/**
 * Transfers interrupt data from or to the device.
 *
 * @param handle
 *            The device handle.
 * @param address
 *            The endpoint address.
 * @param in
 *            If interrupt-in transfer.
 * @param buffer
 *            The data buffer.
 * @return The number of transferred bytes.
 * @throws UsbException
 *             When data transfer fails.
 */
private int transferInterrupt(final DeviceHandle handle, final byte address, final boolean in, final ByteBuffer buffer) throws UsbException {
    final IntBuffer transferred = IntBuffer.allocate(1);
    int result;
    do {
        result = LibUsb.interruptTransfer(handle, address, buffer, transferred, getConfig().getTimeout());
        if (result == LibUsb.ERROR_TIMEOUT && isAborting())
            throw new UsbAbortException();
    } while (in && result == LibUsb.ERROR_TIMEOUT);
    if (result < 0) {
        throw ExceptionUtils.createPlatformException("Transfer error on interrupt endpoint", result);
    }
    return transferred.get(0);
}

15 View Complete Implementation : IrpQueue.java
Copyright MIT License
Author : usb4java
/**
 * Transfers bulk data from or to the device.
 *
 * @param handle
 *            The device handle.
 * @param address
 *            The endpoint address.
 * @param in
 *            If bulk-in transfer.
 * @param buffer
 *            The data buffer.
 * @return The number of transferred bytes.
 * @throws UsbException
 *             When data transfer fails.
 */
private int transferBulk(final DeviceHandle handle, final byte address, final boolean in, final ByteBuffer buffer) throws UsbException {
    final IntBuffer transferred = IntBuffer.allocate(1);
    int result;
    do {
        result = LibUsb.bulkTransfer(handle, address, buffer, transferred, getConfig().getTimeout());
        if (result == LibUsb.ERROR_TIMEOUT && isAborting())
            throw new UsbAbortException();
    } while (in && result == LibUsb.ERROR_TIMEOUT);
    if (result < 0) {
        throw ExceptionUtils.createPlatformException("Transfer error on bulk endpoint", result);
    }
    return transferred.get(0);
}

14 View Complete Implementation : URBDesc.java
Copyright MIT License
Author : diwi
protected boolean start_transfers(DeviceHandle handle, int curr_frame_size) {
    // Initialize the frame queue
    frame_size = curr_frame_size;
    frame_queue.resize(frame_size);
    // Initialize the current frame pointer to the start of the buffer; it will
    // be updated as frames are completed and pushed onto the frame queue
    cur_frame_start = frame_queue.GetFrameBufferStart();
    cur_frame_data_len = 0;
    // Find the bulk transfer endpoint
    byte bulk_endpoint = find_ep(LibUsb.getDevice(handle));
    LibUsb.clearHalt(handle, bulk_endpoint);
    int res = 0;
    for (int index = 0; index < NUM_TRANSFERS; ++index) {
        // Create & submit the transfer
        TranferUserData user_data = new TranferUserData(this, index);
        xfr[index] = LibUsb.allocTransfer(0);
        // Java GC takes care of memory freeing
        ByteBuffer transfer_buffer = ByteBuffer.allocateDirect(TRANSFER_SIZE);
        LibUsb.fillBulkTransfer(xfr[index], handle, bulk_endpoint, transfer_buffer, transfer_completed_callback, user_data, 0);
        res |= LibUsb.submitTransfer(xfr[index]);
        num_active_transfers++;
    }
    last_pts = 0;
    last_fid = 0;
    PS3Eye.usb.cameraStarted();
    return res == 0;
}

14 View Complete Implementation : AirspyTunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
/**
 * SDR Trunk
 * Copyright (C) 2015-2018 Dennis Sheirer
 *
 * -----------------------------------------------------------------------------
 * Ported from libairspy at:
 * https://github.com/airspy/host/tree/master/libairspy
 *
 * Copyright (c) 2013, Michael Ossmann <[email protected]>
 * Copyright (c) 2012, Jared Boone <[email protected]>
 * Copyright (c) 2014, Youssef Touil <[email protected]>
 * Copyright (c) 2014, Benjamin Vernoux <[email protected]>
 * Copyright (c) 2015, Ian Gilmour <[email protected]>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the doreplacedentation
 * and/or other materials provided with the distribution.
 * Neither the name of AirSpy nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific prior
 * written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSreplacedUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
public clreplaced AirspyTunerController extends USBTunerController {

    public static final Gain LINEARITY_GAIN_DEFAULT = Gain.LINEARITY_14;

    public static final Gain SENSITIVITY_GAIN_DEFAULT = Gain.SENSITIVITY_10;

    public static final int GAIN_MIN = 1;

    public static final int GAIN_MAX = 22;

    public static final int LNA_GAIN_MIN = 0;

    public static final int LNA_GAIN_MAX = 14;

    public static final int LNA_GAIN_DEFAULT = 7;

    public static final int MIXER_GAIN_MIN = 0;

    public static final int MIXER_GAIN_MAX = 15;

    public static final int MIXER_GAIN_DEFAULT = 9;

    public static final int IF_GAIN_MIN = 0;

    public static final int IF_GAIN_MAX = 15;

    public static final int IF_GAIN_DEFAULT = 9;

    public static final long FREQUENCY_MIN = 24000000l;

    public static final long FREQUENCY_MAX = 1800000000l;

    public static final long FREQUENCY_DEFAULT = 101100000;

    public static final double USABLE_BANDWIDTH_PERCENT = 0.90;

    public static final AirspySampleRate DEFAULT_SAMPLE_RATE = new AirspySampleRate(0, 10000000, "10.00 MHz");

    // milliseconds
    private static final long USB_TIMEOUT_MS = 2000l;

    private static final byte USB_INTERFACE = (byte) 0x0;

    private static final int USB_TRANSFER_BUFFER_SIZE = 262144;

    private static final byte USB_REQUEST_IN = (byte) (LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);

    private static final byte USB_REQUEST_OUT = (byte) (LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);

    public static final DecimalFormat MHZ_FORMATTER = new DecimalFormat("#.00 MHz");

    private final static Logger mLog = LoggerFactory.getLogger(AirspyTunerController.clreplaced);

    private Device mDevice;

    private DeviceHandle mDeviceHandle;

    private AirspySampleConverter mSampleAdapter = new AirspySampleConverter();

    private AirspyDeviceInformation mDeviceInfo;

    private List<AirspySampleRate> mSampleRates = new ArrayList<>();

    private int mSampleRate = 0;

    private USBTransferProcessor mUSBTransferProcessor;

    public AirspyTunerController(Device device) throws SourceException {
        super(FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT);
        mDevice = device;
    }

    @Override
    public int getBufferSampleCount() {
        // Each airspy complex sample is 4 bytes, so sample count is buffer size / 4
        return USB_TRANSFER_BUFFER_SIZE / 4;
    }

    public void init() throws SourceException {
        mDeviceHandle = new DeviceHandle();
        int result = LibUsb.open(mDevice, mDeviceHandle);
        if (result != LibUsb.SUCCESS) {
            if (result == LibUsb.ERROR_ACCESS) {
                mLog.error("Unable to access Airspy - insufficient permissions." + "  If you are running a Linux OS, have you installed the " + "airspy rules file in \\etc\\udev\\rules.d ??");
            }
            throw new SourceException("Couldn't open airspy device - " + LibUsb.strError(result));
        }
        try {
            claimInterface();
        } catch (Exception e) {
            throw new SourceException("Airspy Tuner Controller - error while " + "setting USB configuration, claiming USB interface or " + "reset the kernel mode driver", e);
        }
        try {
            setSamplePacking(false);
        } catch (LibUsbException | UsbException | UnsupportedOperationException e) {
            mLog.info("Sample packing is not supported by airspy firmware");
        }
        try {
            setReceiverMode(true);
        } catch (Exception e) {
            mLog.error("Couldn't enable airspy receiver mode", e);
        }
        setFrequency(FREQUENCY_DEFAULT);
        try {
            determineAvailableSampleRates();
        } catch (LibUsbException | UsbException e) {
            mLog.error("Error identifying available samples rates", e);
        }
        try {
            setSampleRate(mSampleRates.get(0));
        } catch (IllegalArgumentException | LibUsbException | UsbException e) {
            mLog.error("Setting sample rate is not supported by firmware", e);
        }
        String deviceName = "Airspy " + getDeviceInfo().getSerialNumber();
        mUSBTransferProcessor = new USBTransferProcessor(deviceName, mDeviceHandle, mSampleAdapter, USB_TRANSFER_BUFFER_SIZE);
    }

    @Override
    public void dispose() {
        if (mDeviceHandle != null) {
            mLog.info("Releasing Airspy Tuner - " + getDeviceInfo().getSerialNumber());
            try {
                LibUsb.close(mDeviceHandle);
            } catch (Exception e) {
                mLog.error("error while closing device handle", e);
            }
            mDeviceHandle = null;
        }
    }

    @Override
    protected USBTransferProcessor getUSBTransferProcessor() {
        return mUSBTransferProcessor;
    }

    /**
     * Claims the USB interface.  If another application currently has
     * the interface claimed, the USB_FORCE_CLAIM_INTERFACE setting
     * will dictate if the interface is forcibly claimed from the other
     * application
     */
    private void claimInterface() throws SourceException {
        if (mDeviceHandle != null) {
            int result = LibUsb.kernelDriverActive(mDeviceHandle, USB_INTERFACE);
            if (result == 1) {
                result = LibUsb.detachKernelDriver(mDeviceHandle, USB_INTERFACE);
                if (result != LibUsb.SUCCESS) {
                    mLog.error("failed attempt to detach kernel driver [" + LibUsb.errorName(result) + "]");
                    throw new SourceException("couldn't detach kernel driver " + "from device");
                }
            }
            result = LibUsb.setConfiguration(mDeviceHandle, 1);
            if (result != LibUsb.SUCCESS) {
                throw new SourceException("couldn't set USB configuration 1 [" + LibUsb.errorName(result) + "]");
            }
            result = LibUsb.claimInterface(mDeviceHandle, USB_INTERFACE);
            if (result != LibUsb.SUCCESS) {
                throw new SourceException("couldn't claim usb interface [" + LibUsb.errorName(result) + "]");
            }
        } else {
            throw new SourceException("couldn't claim usb interface - no " + "device handle");
        }
    }

    public static String getTransferStatus(int status) {
        switch(status) {
            case 0:
                return "TRANSFER COMPLETED (0)";
            case 1:
                return "TRANSFER ERROR (1)";
            case 2:
                return "TRANSFER TIMED OUT (2)";
            case 3:
                return "TRANSFER CANCELLED (3)";
            case 4:
                return "TRANSFER STALL (4)";
            case 5:
                return "TRANSFER NO DEVICE (5)";
            case 6:
                return "TRANSFER OVERFLOW (6)";
            default:
                return "UNKNOWN TRANSFER STATUS (" + status + ")";
        }
    }

    @Override
    public void apply(TunerConfiguration config) throws SourceException {
        if (config instanceof AirspyTunerConfiguration) {
            AirspyTunerConfiguration airspy = (AirspyTunerConfiguration) config;
            int sampleRate = airspy.getSampleRate();
            AirspySampleRate rate = getSampleRate(sampleRate);
            if (rate == null) {
                if (!mSampleRates.isEmpty()) {
                    rate = mSampleRates.get(0);
                } else {
                    rate = DEFAULT_SAMPLE_RATE;
                }
            }
            try {
                setSampleRate(rate);
            } catch (UsbException e) {
                throw new SourceException("Couldn't set sample rate [" + rate.toString() + "]", e);
            }
            try {
                setIFGain(airspy.getIFGain());
                setMixerGain(airspy.getMixerGain());
                setLNAGain(airspy.getLNAGain());
                setMixerAGC(airspy.isMixerAGC());
                setLNAAGC(airspy.isLNAAGC());
                // Set the gain mode last, so custom values are already set, and
                // linearity and sensitivity modes will automatically override
                // the custom values.
                setGain(airspy.getGain());
                setFrequencyCorrection(airspy.getFrequencyCorrection());
            } catch (Exception e) {
                throw new SourceException("Couldn't apply gain settings from airspy config", e);
            }
            try {
                setFrequency(airspy.getFrequency());
            } catch (SourceException se) {
            // Do nothing, we couldn't set the frequency
            }
        } else {
            throw new IllegalArgumentException("Invalid tuner config:" + config.getClreplaced());
        }
    }

    @Override
    public long getTunedFrequency() throws SourceException {
        return mFrequencyController.getTunedFrequency();
    }

    @Override
    public void setTunedFrequency(long frequency) throws SourceException {
        if (FREQUENCY_MIN <= frequency && frequency <= FREQUENCY_MAX) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(4);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            buffer.putInt((int) frequency);
            buffer.rewind();
            try {
                write(Command.SET_FREQUENCY, 0, 0, buffer);
            } catch (UsbException e) {
                mLog.error("error setting frequency [" + frequency + "]", e);
                throw new SourceException("error setting frequency [" + frequency + "]", e);
            }
        } else {
            throw new SourceException("Frequency [" + frequency + "] outside " + "of tunable range " + FREQUENCY_MIN + "-" + FREQUENCY_MAX);
        }
    }

    @Override
    public double getCurrentSampleRate() {
        return mSampleRate;
    }

    /**
     * Sets the sample rate to the rate specified by the index value in the
     * available sample rates map
     *
     * @param rate to a sample rate in the available samples rates map.
     * @throws IllegalArgumentException if index is not a valid rate index
     * @throws LibUsbException          if there was a read error or if this operation
     *                                  is not supported by the current firmware
     * @throws UsbException             if there was a USB error
     */
    public void setSampleRate(AirspySampleRate rate) throws LibUsbException, UsbException, SourceException {
        if (rate.getRate() != mSampleRate) {
            int result = readByte(Command.SET_SAMPLE_RATE, 0, rate.getIndex(), true);
            if (result != 1) {
                throw new UsbException("Error setting sample rate [" + rate + "] rate - return value [" + result + "]");
            } else {
                mSampleRate = rate.getRate();
                mFrequencyController.setSampleRate(mSampleRate);
            }
        }
    }

    /**
     * Returns a list of sample rates supported by the firmware version
     */
    public List<AirspySampleRate> getSampleRates() {
        return mSampleRates;
    }

    /**
     * Airspy sample rate object that matches the current sample rate setting.
     */
    public AirspySampleRate getAirspySampleRate() {
        return getSampleRate(mSampleRate);
    }

    /**
     * Airspy sample rate object that matches the specified rate in hertz, or
     * null if there are no available sample rates for the tuner that match the
     * argument value.
     */
    public AirspySampleRate getSampleRate(int rate) {
        for (AirspySampleRate sampleRate : mSampleRates) {
            if (sampleRate.getRate() == rate) {
                return sampleRate;
            }
        }
        // We should never get to here ...
        return null;
    }

    /**
     * Enables/Disables sample packing to allow two 12-bit samples to be packed
     * into 3 bytes (enabled) or 4 bytes (disabled).
     *
     * @param enabled
     * @throws UsbException if sample packing is not supported by the current
     *                      device firmware or if there were usb communication issues
     */
    public void setSamplePacking(boolean enabled) throws LibUsbException, UsbException {
        int result = readByte(Command.SET_PACKING, 0, (enabled ? 1 : 0), true);
        if (result != 1) {
            throw new UsbException("Couldnt set sample packing enabled: " + enabled);
        }
        /* If we didn't throw an exception above, then update the sample adapter
         * to process samples accordingly */
        mSampleAdapter.setSamplePacking(enabled);
    }

    /**
     * Enables/disables the mixer automatic gain setting
     *
     * @param enabled
     * @throws LibUsbException on unsuccessful read operation
     * @throws UsbException    on USB error
     */
    public void setMixerAGC(boolean enabled) throws LibUsbException, UsbException {
        int result = readByte(Command.SET_MIXER_AGC, 0, (enabled ? 1 : 0), true);
        if (result != LibUsb.SUCCESS) {
            throw new UsbException("Couldnt set mixer AGC enabled: " + enabled);
        }
    }

    /**
     * Enables/disables the low noise amplifier automatic gain setting
     *
     * @param enabled
     * @throws LibUsbException on unsuccessful read operation
     * @throws UsbException    on USB error
     */
    public void setLNAAGC(boolean enabled) throws LibUsbException, UsbException {
        int result = readByte(Command.SET_LNA_AGC, 0, (enabled ? 1 : 0), true);
        if (result != LibUsb.SUCCESS) {
            throw new UsbException("Couldnt set LNA AGC enabled: " + enabled);
        }
    }

    public void setGain(Gain gain) throws UsbException {
        if (gain != Gain.CUSTOM) {
            setMixerAGC(false);
            setLNAAGC(false);
            setLNAGain(gain.getLNA());
            setMixerGain(gain.getMixer());
            setIFGain(gain.getIF());
        }
    }

    /**
     * Sets LNA gain
     *
     * @param gain - value within range of LNA_GAIN_MIN to LNA_GAIN_MAX
     * @throws LibUsbException          on error in java USB wrapper
     * @throws UsbException             on error in USB transfer
     * @throws IllegalArgumentException if gain value is invalid
     */
    public void setLNAGain(int gain) throws LibUsbException, UsbException, IllegalArgumentException {
        if (LNA_GAIN_MIN <= gain && gain <= LNA_GAIN_MAX) {
            int result = readByte(Command.SET_LNA_GAIN, 0, gain, true);
            if (result != LibUsb.SUCCESS) {
                throw new UsbException("Couldnt set LNA gain to: " + gain);
            }
        } else {
            throw new IllegalArgumentException("LNA gain value [" + gain + "] is outside value range: " + LNA_GAIN_MIN + "-" + LNA_GAIN_MAX);
        }
    }

    /**
     * Sets Mixer gain
     *
     * @param gain - value within range of MIXER_GAIN_MIN to MIXER_GAIN_MAX
     * @throws LibUsbException          on error in java USB wrapper
     * @throws UsbException             on error in USB transfer
     * @throws IllegalArgumentException if gain value is invalid
     */
    public void setMixerGain(int gain) throws LibUsbException, UsbException, IllegalArgumentException {
        if (MIXER_GAIN_MIN <= gain && gain <= MIXER_GAIN_MAX) {
            int result = readByte(Command.SET_MIXER_GAIN, 0, gain, true);
            if (result != LibUsb.SUCCESS) {
                throw new UsbException("Couldnt set mixer gain to: " + gain);
            }
        } else {
            throw new IllegalArgumentException("Mixer gain value [" + gain + "] is outside value range: " + MIXER_GAIN_MIN + "-" + MIXER_GAIN_MAX);
        }
    }

    /**
     * Sets IF (VGA) gain
     *
     * @param gain - value within range of VGA_GAIN_MIN to VGA_GAIN_MAX
     * @throws LibUsbException          on error in java USB wrapper
     * @throws UsbException             on error in USB transfer
     * @throws IllegalArgumentException if gain value is invalid
     */
    public void setIFGain(int gain) throws LibUsbException, UsbException, IllegalArgumentException {
        if (IF_GAIN_MIN <= gain && gain <= IF_GAIN_MAX) {
            int result = readByte(Command.SET_VGA_GAIN, 0, gain, true);
            if (result != LibUsb.SUCCESS) {
                throw new UsbException("Couldnt set VGA gain to: " + gain);
            }
        } else {
            throw new IllegalArgumentException("VGA gain value [" + gain + "] is outside value range: " + IF_GAIN_MIN + "-" + IF_GAIN_MAX);
        }
    }

    public void setReceiverMode(boolean enabled) throws LibUsbException, UsbException {
        // Empty buffer to throw away
        ByteBuffer buffer = ByteBuffer.allocateDirect(0);
        write(Command.RECEIVER_MODE, (enabled ? 1 : 0), 0, buffer);
    }

    /**
     * Queries the device for available sample rates.  Will always provide at
     * least the default 10 MHz sample rate.
     */
    private void determineAvailableSampleRates() throws LibUsbException, UsbException {
        mSampleRates.clear();
        // Get a count of available sample rates.  If we get an exception, then
        // we're using an older firmware revision and only the default 10 MHz
        // rate is supported
        try {
            byte[] rawCount = readArray(Command.GET_SAMPLE_RATES, 0, 0, 4);
            if (rawCount != null) {
                int count = EndianUtils.readSwappedInteger(rawCount, 0);
                byte[] rawRates = readArray(Command.GET_SAMPLE_RATES, 0, count, (count * 4));
                for (int x = 0; x < count; x++) {
                    int rate = EndianUtils.readSwappedInteger(rawRates, (x * 4));
                    mSampleRates.add(new AirspySampleRate(x, rate, formatSampleRate(rate)));
                }
            }
        } catch (LibUsbException e) {
        // Press on, nothing else to do here ..
        }
        if (mSampleRates.isEmpty()) {
            mSampleRates.add(DEFAULT_SAMPLE_RATE);
        }
    }

    /**
     * Formats the rate in hertz for display as megahertz
     */
    private static String formatSampleRate(int rate) {
        return MHZ_FORMATTER.format((double) rate / 1E6d);
    }

    /**
     * Device information
     */
    public AirspyDeviceInformation getDeviceInfo() {
        // Lazy initialization
        if (mDeviceInfo == null) {
            readDeviceInfo();
        }
        return mDeviceInfo;
    }

    /**
     * Reads version information from the device and populates the info object
     */
    private void readDeviceInfo() {
        if (mDeviceInfo == null) {
            mDeviceInfo = new AirspyDeviceInformation();
        }
        /* Board ID */
        try {
            int boardID = readByte(Command.BOARD_ID_READ, 0, 0, true);
            mDeviceInfo.setBoardID(boardID);
        } catch (LibUsbException | UsbException e) {
            mLog.error("Error reading airspy board ID", e);
        }
        /* Version String */
        try {
            // NOTE: libairspy is internally reading 127 bytes, however airspy_info
            // script is telling it to read 255 bytes ... things that make you go hmmmm
            byte[] version = readArray(Command.VERSION_STRING_READ, 0, 0, 127);
            mDeviceInfo.setVersion(version);
        } catch (LibUsbException | UsbException e) {
            mLog.error("Error reading airspy version string", e);
        }
        /* Part ID and Serial Number */
        try {
            // Read 6 x 32-bit integers = 24 bytes
            byte[] serial = readArray(Command.BOARD_PART_ID_SERIAL_NUMBER_READ, 0, 0, 24);
            mDeviceInfo.setPartAndSerialNumber(serial);
        } catch (LibUsbException | UsbException e) {
            mLog.error("Error reading airspy version string", e);
        }
    }

    /**
     * Reads a single byte value from the device.
     *
     * @param command - airspy command
     * @param value - value field for usb setup packet
     * @param index - index field for usb setup packet
     * @return - byte value as an integer
     * @throws LibUsbException if the operation is unsuccesful
     * @throws UsbException    on any usb errors
     */
    private int readByte(Command command, int value, int index, boolean signed) throws LibUsbException, UsbException {
        if (mDeviceHandle != null) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(1);
            int transferred = LibUsb.controlTransfer(mDeviceHandle, USB_REQUEST_IN, command.getValue(), (short) value, (short) index, buffer, USB_TIMEOUT_MS);
            if (transferred < 0) {
                throw new LibUsbException("read error", transferred);
            }
            byte result = buffer.get(0);
            if (signed) {
                return (result & 0xFF);
            } else {
                return result;
            }
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    /**
     * Reads a multi-byte value from the device
     *
     * @param command - airspy command
     * @param value - usb packet value
     * @param index - usb packet index
     * @param length - number of bytes to read
     * @return - bytes read from the device
     * @throws LibUsbException if quanreplacedy of bytes read doesn't equal the
     *                         requested number of bytes
     * @throws UsbException    on error communicating with the device
     */
    private byte[] readArray(Command command, int value, int index, int length) throws LibUsbException, UsbException {
        if (mDeviceHandle != null) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(length);
            int transferred = LibUsb.controlTransfer(mDeviceHandle, USB_REQUEST_IN, command.getValue(), (short) value, (short) index, buffer, USB_TIMEOUT_MS);
            if (transferred < 0) {
                throw new LibUsbException("read error", transferred);
            }
            byte[] results = new byte[transferred];
            buffer.get(results);
            return results;
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    /**
     * Writes the buffer contents to the device
     *
     * @param command - airspy command
     * @param value - usb packet value
     * @param index - usb packet index
     * @param buffer - data to write to the device
     * @throws UsbException on error
     */
    public void write(Command command, int value, int index, ByteBuffer buffer) throws UsbException {
        if (mDeviceHandle != null) {
            int transferred = LibUsb.controlTransfer(mDeviceHandle, USB_REQUEST_OUT, command.getValue(), (short) value, (short) index, buffer, USB_TIMEOUT_MS);
            if (transferred < 0) {
                throw new LibUsbException("error writing byte buffer", transferred);
            } else if (transferred != buffer.capacity()) {
                throw new LibUsbException("transferred bytes [" + transferred + "] is not what was expected [" + buffer.capacity() + "]", transferred);
            }
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    public enum GainMode {

        LINEARITY, SENSITIVITY, CUSTOM
    }

    public enum Gain {

        LINEARITY_1(1, 4, 0, 0),
        LINEARITY_2(2, 5, 0, 0),
        LINEARITY_3(3, 6, 1, 0),
        LINEARITY_4(4, 7, 1, 0),
        LINEARITY_5(5, 8, 1, 0),
        LINEARITY_6(6, 9, 1, 0),
        LINEARITY_7(7, 10, 2, 0),
        LINEARITY_8(8, 10, 2, 1),
        LINEARITY_9(9, 10, 0, 3),
        LINEARITY_10(10, 10, 0, 5),
        LINEARITY_11(11, 10, 1, 6),
        LINEARITY_12(12, 10, 0, 8),
        LINEARITY_13(13, 10, 0, 9),
        LINEARITY_14(14, 10, 5, 8),
        LINEARITY_15(15, 10, 6, 9),
        LINEARITY_16(16, 11, 6, 9),
        LINEARITY_17(17, 11, 7, 10),
        LINEARITY_18(18, 11, 8, 12),
        LINEARITY_19(19, 11, 9, 13),
        LINEARITY_20(20, 11, 11, 14),
        LINEARITY_21(21, 12, 12, 14),
        LINEARITY_22(22, 13, 12, 14),
        SENSITIVITY_1(1, 4, 0, 0),
        SENSITIVITY_2(2, 4, 0, 1),
        SENSITIVITY_3(3, 4, 0, 2),
        SENSITIVITY_4(4, 4, 0, 3),
        SENSITIVITY_5(5, 4, 1, 5),
        SENSITIVITY_6(6, 4, 2, 6),
        SENSITIVITY_7(7, 4, 2, 7),
        SENSITIVITY_8(8, 4, 3, 8),
        SENSITIVITY_9(9, 4, 4, 9),
        SENSITIVITY_10(10, 5, 4, 9),
        SENSITIVITY_11(11, 5, 4, 12),
        SENSITIVITY_12(12, 5, 7, 12),
        SENSITIVITY_13(13, 5, 8, 13),
        SENSITIVITY_14(14, 5, 9, 14),
        SENSITIVITY_15(15, 6, 9, 14),
        SENSITIVITY_16(16, 7, 10, 14),
        SENSITIVITY_17(17, 8, 10, 14),
        SENSITIVITY_18(18, 9, 11, 14),
        SENSITIVITY_19(19, 10, 12, 14),
        SENSITIVITY_20(20, 11, 12, 14),
        SENSITIVITY_21(21, 12, 12, 14),
        SENSITIVITY_22(22, 13, 12, 14),
        CUSTOM(1, 0, 0, 0);

        private int mValue;

        private int mIF;

        private int mMixer;

        private int mLNA;

        private Gain(int value, int ifGain, int mixer, int lna) {
            mValue = value;
            mIF = ifGain;
            mMixer = mixer;
            mLNA = lna;
        }

        public int getValue() {
            return mValue;
        }

        public int getIF() {
            return mIF;
        }

        public int getMixer() {
            return mMixer;
        }

        public int getLNA() {
            return mLNA;
        }

        public static Gain getGain(GainMode mode, int value) {
            replacedert (GAIN_MIN <= value && value <= GAIN_MAX);
            switch(mode) {
                case LINEARITY:
                    for (Gain gain : getLinearityGains()) {
                        if (gain.getValue() == value) {
                            return gain;
                        }
                    }
                    return LINEARITY_GAIN_DEFAULT;
                case SENSITIVITY:
                    for (Gain gain : getSensitivityGains()) {
                        if (gain.getValue() == value) {
                            return gain;
                        }
                    }
                    return SENSITIVITY_GAIN_DEFAULT;
                case CUSTOM:
                default:
                    return Gain.CUSTOM;
            }
        }

        public static GainMode getGainMode(Gain gain) {
            if (gain == CUSTOM) {
                return GainMode.CUSTOM;
            } else if (getLinearityGains().contains(gain)) {
                return GainMode.LINEARITY;
            } else if (getSensitivityGains().contains(gain)) {
                return GainMode.SENSITIVITY;
            }
            return GainMode.CUSTOM;
        }

        public static EnumSet<Gain> getLinearityGains() {
            return EnumSet.range(LINEARITY_1, LINEARITY_22);
        }

        public static EnumSet<Gain> getSensitivityGains() {
            return EnumSet.range(SENSITIVITY_1, SENSITIVITY_22);
        }
    }

    /**
     * Airspy Board Identifier
     */
    public enum BoardID {

        AIRSPY(0, "Airspy"), UNKNOWN(-1, "Unknown");

        private int mValue;

        private String mLabel;

        private BoardID(int value, String label) {
            mValue = value;
            mLabel = label;
        }

        public int getValue() {
            return mValue;
        }

        public String getLabel() {
            return mLabel;
        }

        public static BoardID fromValue(int value) {
            if (value == 0) {
                return AIRSPY;
            }
            return UNKNOWN;
        }
    }

    /**
     * Airspy Commands
     */
    public enum Command {

        INVALID(0),
        RECEIVER_MODE(1),
        SI5351C_WRITE(2),
        SI5351C_READ(3),
        R820T_WRITE(4),
        R820T_READ(5),
        SPIFLASH_ERASE(6),
        SPIFLASH_WRITE(7),
        SPIFLASH_READ(8),
        BOARD_ID_READ(9),
        VERSION_STRING_READ(10),
        BOARD_PART_ID_SERIAL_NUMBER_READ(11),
        SET_SAMPLE_RATE(12),
        SET_FREQUENCY(13),
        SET_LNA_GAIN(14),
        SET_MIXER_GAIN(15),
        SET_VGA_GAIN(16),
        SET_LNA_AGC(17),
        SET_MIXER_AGC(18),
        MS_VENDOR_COMMAND(19),
        SET_RF_BIAS_COMMAND(20),
        GPIO_WRITE(21),
        GPIO_READ(22),
        GPIO_DIR__WRITE(23),
        GPIO_DIR_READ(24),
        GET_SAMPLE_RATES(25),
        SET_PACKING(26);

        private int mValue;

        private Command(int value) {
            mValue = value;
        }

        public byte getValue() {
            return (byte) mValue;
        }

        public static Command fromValue(int value) {
            if (0 <= value && value <= 25) {
                return Command.values()[value];
            }
            return INVALID;
        }
    }

    public enum ReceiverMode {

        OFF(0), ON(1);

        private int mValue;

        private ReceiverMode(int value) {
            mValue = value;
        }

        public int getValue() {
            return mValue;
        }
    }

    /**
     * General Purpose Input/Output Ports (accessible on the airspy board)
     */
    public enum GPIOPort {

        PORT_0(0),
        PORT_1(1),
        PORT_2(2),
        PORT_3(3),
        PORT_4(4),
        PORT_5(5),
        PORT_6(6),
        PORT_7(7);

        private int mValue;

        private GPIOPort(int value) {
            mValue = value;
        }

        public int getValue() {
            return mValue;
        }
    }

    /**
     * General Purpose Input/Output Pins (accessible on the airspy board)
     */
    public enum GPIOPin {

        PIN_0(0),
        PIN_1(1),
        PIN_2(2),
        PIN_3(3),
        PIN_4(4),
        PIN_5(5),
        PIN_6(6),
        PIN_7(7),
        PIN_8(8),
        PIN_9(9),
        PIN_10(10),
        PIN_11(11),
        PIN_12(12),
        PIN_13(13),
        PIN_14(14),
        PIN_15(15),
        PIN_16(16),
        PIN_17(17),
        PIN_18(18),
        PIN_19(19),
        PIN_20(20),
        PIN_21(21),
        PIN_22(22),
        PIN_23(23),
        PIN_24(24),
        PIN_25(25),
        PIN_26(26),
        PIN_27(27),
        PIN_28(28),
        PIN_29(29),
        PIN_30(30),
        PIN_31(31);

        private int mValue;

        private GPIOPin(int value) {
            mValue = value;
        }

        public int getValue() {
            return mValue;
        }
    }
}

14 View Complete Implementation : HackRFTunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
public clreplaced HackRFTunerController extends USBTunerController {

    private final static Logger mLog = LoggerFactory.getLogger(HackRFTunerController.clreplaced);

    // uSeconds
    public final static long USB_TIMEOUT_US = 1000000l;

    public static final byte USB_ENDPOINT = (byte) 0x81;

    public static final byte USB_INTERFACE = (byte) 0x0;

    public static final int USB_TRANSFER_BUFFER_SIZE = 262144;

    public static final byte REQUEST_TYPE_IN = (byte) (LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);

    public static final byte REQUEST_TYPE_OUT = (byte) (LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);

    public static final long MIN_FREQUENCY = 10000000l;

    public static final long MAX_FREQUENCY = 6000000000l;

    public static final long DEFAULT_FREQUENCY = 101100000;

    public static final double USABLE_BANDWIDTH_PERCENT = 0.95;

    public static final int DC_SPIKE_AVOID_BUFFER = 5000;

    private NativeBufferConverter mNativeBufferConverter = new ByteSampleConverter();

    private USBTransferProcessor mUSBTransferProcessor;

    private HackRFSampleRate mSampleRate = HackRFSampleRate.RATE2_016MHZ;

    private boolean mAmplifierEnabled = false;

    private Device mDevice;

    private DeviceDescriptor mDeviceDescriptor;

    private DeviceHandle mDeviceHandle;

    public HackRFTunerController(Device device, DeviceDescriptor descriptor) throws SourceException {
        super(MIN_FREQUENCY, MAX_FREQUENCY, DC_SPIKE_AVOID_BUFFER, USABLE_BANDWIDTH_PERCENT);
        mDevice = device;
        mDeviceDescriptor = descriptor;
    }

    @Override
    public int getBufferSampleCount() {
        return USB_TRANSFER_BUFFER_SIZE / 2;
    }

    public void init() throws SourceException {
        mDeviceHandle = new DeviceHandle();
        int result = LibUsb.open(mDevice, mDeviceHandle);
        if (result != 0) {
            if (result == LibUsb.ERROR_ACCESS) {
                mLog.error("Unable to access HackRF - insufficient permissions.  " + "If you are running a Linux OS, have you installed the " + "hackRF rules file in \\etc\\udev\\rules.d ??");
            }
            throw new SourceException("Couldn't open hackrf device - " + LibUsb.strError(result));
        }
        try {
            claimInterface();
            setMode(Mode.RECEIVE);
            setFrequency(DEFAULT_FREQUENCY);
        } catch (Exception e) {
            throw new SourceException("HackRF Tuner Controller - couldn't " + "claim USB interface or get endpoint or pipe", e);
        }
        String name;
        try {
            name = "HackRF " + getSerial().getSerialNumber();
        } catch (UsbException ue) {
            // Do nothing, we couldn't determine the serial number
            name = "HackRF - Unidentified Serial";
        }
        mUSBTransferProcessor = new USBTransferProcessor(name, mDeviceHandle, mNativeBufferConverter, USB_TRANSFER_BUFFER_SIZE);
    }

    @Override
    public void dispose() {
        if (mDeviceHandle != null) {
            mLog.info("Releasing HackRF Tuner");
            try {
                LibUsb.close(mDeviceHandle);
            } catch (Exception e) {
                mLog.error("error while closing device handle", e);
            }
            mDeviceHandle = null;
        }
    }

    @Override
    protected USBTransferProcessor getUSBTransferProcessor() {
        return mUSBTransferProcessor;
    }

    /**
     * Claims the USB interface.  If another application currently has
     * the interface claimed, the USB_FORCE_CLAIM_INTERFACE setting
     * will dictate if the interface is forcibly claimed from the other
     * application
     */
    private void claimInterface() throws SourceException {
        if (mDeviceHandle != null) {
            int result = LibUsb.kernelDriverActive(mDeviceHandle, USB_INTERFACE);
            if (result == 1) {
                result = LibUsb.detachKernelDriver(mDeviceHandle, USB_INTERFACE);
                if (result != LibUsb.SUCCESS) {
                    mLog.error("failed attempt to detach kernel driver [" + LibUsb.errorName(result) + "]");
                    throw new SourceException("couldn't detach kernel driver " + "from device");
                }
            }
            result = LibUsb.claimInterface(mDeviceHandle, USB_INTERFACE);
            if (result != LibUsb.SUCCESS) {
                throw new SourceException("couldn't claim usb interface [" + LibUsb.errorName(result) + "]");
            }
        } else {
            throw new SourceException("couldn't claim usb interface - no " + "device handle");
        }
    }

    /**
     * HackRF board identifier/type
     */
    public BoardID getBoardID() throws UsbException {
        int id = readByte(Request.BOARD_ID_READ, (byte) 0, (byte) 0, false);
        return BoardID.lookup(id);
    }

    /**
     * HackRF firmware version string
     */
    public String getFirmwareVersion() throws UsbException {
        ByteBuffer buffer = readArray(Request.VERSION_STRING_READ, 0, 0, 255);
        byte[] data = new byte[255];
        buffer.get(data);
        return new String(data);
    }

    /**
     * HackRF part id number and serial number
     */
    public Serial getSerial() throws UsbException {
        ByteBuffer buffer = readArray(Request.BOARD_PARTID_SERIALNO_READ, 0, 0, 24);
        return new Serial(buffer);
    }

    /**
     * Sets the HackRF transceiver mode
     */
    public void setMode(Mode mode) throws UsbException {
        write(Request.SET_TRANSCEIVER_MODE, mode.getNumber(), 0);
    }

    /**
     * Sets the HackRF baseband filter
     */
    public void setBasebandFilter(BasebandFilter filter) throws UsbException {
        write(Request.BASEBAND_FILTER_BANDWIDTH_SET, filter.getLowValue(), filter.getHighValue());
    }

    /**
     * Enables (true) or disables (false) the amplifier
     */
    public void setAmplifierEnabled(boolean enabled) throws UsbException {
        write(Request.AMP_ENABLE, (enabled ? 1 : 0), 0);
        mAmplifierEnabled = enabled;
    }

    public boolean getAmplifier() {
        return mAmplifierEnabled;
    }

    /**
     * Sets the IF LNA Gain
     */
    public void setLNAGain(HackRFLNAGain gain) throws UsbException {
        int result = readByte(Request.SET_LNA_GAIN, 0, gain.getValue(), true);
        if (result != 1) {
            throw new UsbException("couldn't set lna gain to " + gain);
        }
    }

    /**
     * Sets the Baseband VGA Gain
     */
    public void setVGAGain(HackRFVGAGain gain) throws UsbException {
        int result = readByte(Request.SET_VGA_GAIN, 0, gain.getValue(), true);
        if (result != 1) {
            throw new UsbException("couldn't set vga gain to " + gain);
        }
    }

    /**
     * Not implemented
     */
    public long getTunedFrequency() throws SourceException {
        return mFrequencyController.getTunedFrequency();
    }

    @Override
    public void setTunedFrequency(long frequency) throws SourceException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(8);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        int mhz = (int) (frequency / 1E6);
        int hz = (int) (frequency - (mhz * 1E6));
        buffer.putInt(mhz);
        buffer.putInt(hz);
        buffer.rewind();
        try {
            write(Request.SET_FREQUENCY, 0, 0, buffer);
        } catch (UsbException e) {
            mLog.error("error setting frequency [" + frequency + "]", e);
            throw new SourceException("error setting frequency [" + frequency + "]", e);
        }
    }

    @Override
    public double getCurrentSampleRate() {
        return mSampleRate.getRate();
    }

    @Override
    public void apply(TunerConfiguration config) throws SourceException {
        if (config instanceof HackRFTunerConfiguration) {
            HackRFTunerConfiguration hackRFConfig = (HackRFTunerConfiguration) config;
            try {
                setSampleRate(hackRFConfig.getSampleRate());
                setFrequencyCorrection(hackRFConfig.getFrequencyCorrection());
                setAmplifierEnabled(hackRFConfig.getAmplifierEnabled());
                setLNAGain(hackRFConfig.getLNAGain());
                setVGAGain(hackRFConfig.getVGAGain());
                setFrequency(getFrequency());
            } catch (UsbException e) {
                throw new SourceException("Error while applying tuner " + "configuration", e);
            }
            try {
                setFrequency(hackRFConfig.getFrequency());
            } catch (SourceException se) {
            // Do nothing, we couldn't set the frequency
            }
        } else {
            throw new IllegalArgumentException("Invalid tuner configuration " + "type [" + config.getClreplaced() + "]");
        }
    }

    public ByteBuffer readArray(Request request, int value, int index, int length) throws UsbException {
        if (mDeviceHandle != null) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(length);
            int transferred = LibUsb.controlTransfer(mDeviceHandle, REQUEST_TYPE_IN, request.getRequestNumber(), (short) value, (short) index, buffer, USB_TIMEOUT_US);
            if (transferred < 0) {
                throw new LibUsbException("read error", transferred);
            }
            return buffer;
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    public int read(Request request, int value, int index, int length) throws UsbException {
        if (!(length == 1 || length == 2 || length == 4)) {
            throw new IllegalArgumentException("invalid length [" + length + "] must be: byte=1, short=2, int=4 to read a primitive");
        }
        ByteBuffer buffer = readArray(request, value, index, length);
        byte[] data = new byte[buffer.capacity()];
        buffer.get(data);
        switch(data.length) {
            case 1:
                return data[0];
            case 2:
                return EndianUtils.readSwappedShort(data, 0);
            case 4:
                return EndianUtils.readSwappedInteger(data, 0);
            default:
                throw new UsbException("read() primitive returned an " + "unrecognized byte array " + Arrays.toString(data));
        }
    }

    public int readByte(Request request, int value, int index, boolean signed) throws UsbException {
        ByteBuffer buffer = readArray(request, value, index, 1);
        if (signed) {
            return (int) (buffer.get());
        } else {
            return (int) (buffer.get() & 0xFF);
        }
    }

    public void write(Request request, int value, int index, ByteBuffer buffer) throws UsbException {
        if (mDeviceHandle != null) {
            int transferred = LibUsb.controlTransfer(mDeviceHandle, REQUEST_TYPE_OUT, request.getRequestNumber(), (short) value, (short) index, buffer, USB_TIMEOUT_US);
            if (transferred < 0) {
                throw new LibUsbException("error writing byte buffer", transferred);
            } else if (transferred != buffer.capacity()) {
                throw new LibUsbException("transferred bytes [" + transferred + "] is not what was expected [" + buffer.capacity() + "]", transferred);
            }
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    /**
     * Sends a request that doesn't have a data payload
     */
    public void write(Request request, int value, int index) throws UsbException {
        write(request, value, index, ByteBuffer.allocateDirect(0));
    }

    /**
     * Sample Rate
     *
     * Note: the libhackrf set sample rate method is designed to allow fractional
     * sample rates.  However, since we're only using integral sample rates, we
     * simply invoke the setSampleRateManual method directly.
     */
    public void setSampleRate(HackRFSampleRate rate) throws UsbException, SourceException {
        setSampleRateManual(rate.getRate(), 1);
        mFrequencyController.setSampleRate(rate.getRate());
        setBasebandFilter(rate.getFilter());
        mSampleRate = rate;
    }

    public void setSampleRateManual(int frequency, int divider) throws UsbException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(8);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putInt(frequency);
        buffer.putInt(divider);
        write(Request.SET_SAMPLE_RATE, 0, 0, buffer);
    }

    public double getSampleRate() {
        return mSampleRate.getRate();
    }

    public enum Request {

        SET_TRANSCEIVER_MODE(1),
        MAX2837_TRANSCEIVER_WRITE(2),
        MAX2837_TRANSCEIVER_READ(3),
        SI5351C_CLOCK_GENERATOR_WRITE(4),
        SI5351C_CLOCK_GENERATOR_READ(5),
        SET_SAMPLE_RATE(6),
        BASEBAND_FILTER_BANDWIDTH_SET(7),
        RFFC5071_MIXER_WRITE(8),
        RFFC5071_MIXER_READ(9),
        SPIFLASH_ERASE(10),
        SPIFLASH_WRITE(11),
        SPIFLASH_READ(12),
        BOARD_ID_READ(14),
        VERSION_STRING_READ(15),
        SET_FREQUENCY(16),
        AMP_ENABLE(17),
        BOARD_PARTID_SERIALNO_READ(18),
        SET_LNA_GAIN(19),
        SET_VGA_GAIN(20),
        SET_TXVGA_GAIN(21),
        ANTENNA_ENABLE(23),
        SET_FREQUENCY_EXPLICIT(24);

        private byte mRequestNumber;

        private Request(int number) {
            mRequestNumber = (byte) number;
        }

        public byte getRequestNumber() {
            return mRequestNumber;
        }
    }

    public enum HackRFSampleRate {

        RATE2_016MHZ(2016000, "2.016 MHz", BasebandFilter.F3_50),
        RATE3_024MHZ(3024000, "3.024 MHz", BasebandFilter.F5_00),
        RATE4_464MHZ(4464000, "4.464 MHz", BasebandFilter.F6_00),
        RATE5_376MHZ(5376000, "5.376 MHz", BasebandFilter.F7_00),
        RATE7_488MHZ(7488000, "7.488 MHz", BasebandFilter.F9_00),
        RATE10_080MHZ(10080000, "10.080 MHz", BasebandFilter.F12_00),
        RATE12_000MHZ(12000000, "12.000 MHz", BasebandFilter.F14_00),
        RATE13_440MHZ(13440000, "13.440 MHz", BasebandFilter.F15_00),
        RATE14_976MHZ(14976000, "14.976 MHz", BasebandFilter.F20_00),
        RATE19_968MHZ(19968000, "19.968 MHz", BasebandFilter.F24_00);

        private int mRate;

        private String mLabel;

        private BasebandFilter mFilter;

        private HackRFSampleRate(int rate, String label, BasebandFilter filter) {
            mRate = rate;
            mLabel = label;
            mFilter = filter;
        }

        public int getRate() {
            return mRate;
        }

        public String getLabel() {
            return mLabel;
        }

        public String toString() {
            return mLabel;
        }

        public BasebandFilter getFilter() {
            return mFilter;
        }
    }

    public enum BasebandFilter {

        FAUTO(0, "AUTO"),
        F1_75(1750000, "1.75 MHz"),
        F2_50(2500000, "2.50 MHz"),
        F3_50(3500000, "3.50 MHz"),
        F5_00(5000000, "5.00 MHz"),
        F5_50(5500000, "5.50 MHz"),
        F6_00(6000000, "6.00 MHz"),
        F7_00(7000000, "7.00 MHz"),
        F8_00(8000000, "8.00 MHz"),
        F9_00(9000000, "9.00 MHz"),
        F10_00(10000000, "10.00 MHz"),
        F12_00(12000000, "12.00 MHz"),
        F14_00(14000000, "14.00 MHz"),
        F15_00(15000000, "15.00 MHz"),
        F20_00(20000000, "20.00 MHz"),
        F24_00(24000000, "24.00 MHz"),
        F28_00(28000000, "28.00 MHz");

        private int mBandwidth;

        private String mLabel;

        private BasebandFilter(int bandwidth, String label) {
            mBandwidth = bandwidth;
            mLabel = label;
        }

        public int getBandwidth() {
            return mBandwidth;
        }

        public int getHighValue() {
            return mBandwidth >> 16;
        }

        public int getLowValue() {
            return mBandwidth & 0xFFFF;
        }

        public String getLabel() {
            return mLabel;
        }
    }

    public enum BoardID {

        JELLYBEAN(0x00, "HackRF Jelly Bean"), JAWBREAKER(0x01, "HackRF Jaw Breaker"), HACKRF_ONE(0x02, "HackRF One"), INVALID(0xFF, "HackRF Unknown Board");

        private byte mIDNumber;

        private String mLabel;

        private BoardID(int number, String label) {
            mIDNumber = (byte) number;
            mLabel = label;
        }

        public String toString() {
            return mLabel;
        }

        public String getLabel() {
            return mLabel;
        }

        public byte getNumber() {
            return mIDNumber;
        }

        public static BoardID lookup(int value) {
            switch(value) {
                case 0:
                    return JELLYBEAN;
                case 1:
                    return JAWBREAKER;
                case 2:
                    return HACKRF_ONE;
                default:
                    return INVALID;
            }
        }
    }

    public enum Mode {

        OFF(0, "Off"), RECEIVE(1, "Receive"), TRANSMIT(2, "Transmit"), SS(3, "SS");

        private byte mNumber;

        private String mLabel;

        private Mode(int number, String label) {
            mNumber = (byte) number;
            mLabel = label;
        }

        public byte getNumber() {
            return mNumber;
        }

        public String getLabel() {
            return mLabel;
        }

        public String toString() {
            return mLabel;
        }
    }

    public enum HackRFLNAGain {

        GAIN_0(0),
        GAIN_8(8),
        GAIN_16(16),
        GAIN_24(24),
        GAIN_32(32),
        GAIN_40(40);

        private int mValue;

        private HackRFLNAGain(int value) {
            mValue = value;
        }

        public int getValue() {
            return mValue;
        }

        public String toString() {
            return String.valueOf(mValue) + " dB";
        }
    }

    /**
     * Receive (baseband) VGA Gain values
     */
    public enum HackRFVGAGain {

        GAIN_0(0),
        GAIN_2(2),
        GAIN_4(4),
        GAIN_6(6),
        GAIN_8(8),
        GAIN_10(10),
        GAIN_12(12),
        GAIN_14(14),
        GAIN_16(16),
        GAIN_18(18),
        GAIN_20(20),
        GAIN_22(22),
        GAIN_23(24),
        GAIN_26(26),
        GAIN_28(28),
        GAIN_30(30),
        GAIN_32(32),
        GAIN_34(34),
        GAIN_36(36),
        GAIN_38(38),
        GAIN_40(40),
        GAIN_42(42),
        GAIN_44(44),
        GAIN_46(46),
        GAIN_48(48),
        GAIN_50(50),
        GAIN_52(52),
        GAIN_54(54),
        GAIN_56(56),
        GAIN_58(58),
        GAIN_60(60),
        GAIN_62(62);

        private int mValue;

        private HackRFVGAGain(int value) {
            mValue = value;
        }

        public int getValue() {
            return mValue;
        }

        public String toString() {
            return String.valueOf(mValue) + " dB";
        }
    }

    /**
     * HackRF part id and serial number parsing clreplaced
     */
    public clreplaced Serial {

        private byte[] mData;

        public Serial(ByteBuffer buffer) {
            mData = new byte[buffer.capacity()];
            buffer.get(mData);
        }

        public String getPartID() {
            int part0 = EndianUtils.readSwappedInteger(mData, 0);
            int part1 = EndianUtils.readSwappedInteger(mData, 4);
            StringBuilder sb = new StringBuilder();
            sb.append(String.format("%08X", part0));
            sb.append("-");
            sb.append(String.format("%08X", part1));
            return sb.toString();
        }

        public String getSerialNumber() {
            int serial0 = EndianUtils.readSwappedInteger(mData, 8);
            int serial1 = EndianUtils.readSwappedInteger(mData, 12);
            int serial2 = EndianUtils.readSwappedInteger(mData, 16);
            int serial3 = EndianUtils.readSwappedInteger(mData, 20);
            StringBuilder sb = new StringBuilder();
            sb.append(String.format("%08X", serial0));
            sb.append("-");
            sb.append(String.format("%08X", serial1));
            sb.append("-");
            sb.append(String.format("%08X", serial2));
            sb.append("-");
            sb.append(String.format("%08X", serial3));
            return sb.toString();
        }
    }
}

14 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
public static void initBaseband(DeviceHandle handle) throws LibUsbException {
    /* Initialize USB */
    writeRegister(handle, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1);
    writeRegister(handle, Block.USB, Address.USB_EPA_MAXPKT.getAddress(), 0x0002, 2);
    writeRegister(handle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2);
    /* Power on demod */
    writeRegister(handle, Block.SYS, Address.DEMOD_CTL_1.getAddress(), 0x22, 1);
    writeRegister(handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0xE8, 1);
    /* Reset demod */
    // Bit 3 = soft reset
    writeDemodRegister(handle, Page.ONE, (short) 0x01, 0x14, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x01, 0x10, 1);
    /* Disable spectrum inversion and adjacent channel rejection */
    writeDemodRegister(handle, Page.ONE, (short) 0x15, 0x00, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x16, 0x0000, 2);
    /* Clear DDC shift and IF frequency registers */
    writeDemodRegister(handle, Page.ONE, (short) 0x16, 0x00, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x17, 0x00, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x18, 0x00, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x19, 0x00, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x1A, 0x00, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x1B, 0x00, 1);
    /* Set FIR coefficients */
    for (int x = 0; x < sFIR_COEFFICIENTS.length; x++) {
        writeDemodRegister(handle, Page.ONE, (short) (0x1C + x), sFIR_COEFFICIENTS[x], 1);
    }
    /* Enable SDR mode, disable DAGC (bit 5) */
    writeDemodRegister(handle, Page.ZERO, (short) 0x19, 0x05, 1);
    /* Init FSM state-holding register */
    writeDemodRegister(handle, Page.ONE, (short) 0x93, 0xF0, 1);
    writeDemodRegister(handle, Page.ONE, (short) 0x94, 0x0F, 1);
    /* Disable AGC (en_dagc, bit 0) (seems to have no effect) */
    writeDemodRegister(handle, Page.ONE, (short) 0x11, 0x00, 1);
    /* Disable RF and IF AGC loop */
    writeDemodRegister(handle, Page.ONE, (short) 0x04, 0x00, 1);
    /* Disable PID filter */
    writeDemodRegister(handle, Page.ZERO, (short) 0x61, 0x60, 1);
    /* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */
    writeDemodRegister(handle, Page.ZERO, (short) 0x06, 0x80, 1);
    /* Enable Zero-if mode (en_bbin bit),
         *        DC cancellation (en_dc_est),
         *        IQ estimation/compensation (en_iq_comp, en_iq_est) */
    writeDemodRegister(handle, Page.ONE, (short) 0xB1, 0x1B, 1);
    /* Disable 4.096 MHz clock output on pin TP_CK0 */
    writeDemodRegister(handle, Page.ZERO, (short) 0x0D, 0x83, 1);
}

14 View Complete Implementation : RTL2832TunerController.java
Copyright GNU General Public License v3.0
Author : DSheirer
public abstract clreplaced RTL2832TunerController extends USBTunerController {

    private final static Logger mLog = LoggerFactory.getLogger(RTL2832TunerController.clreplaced);

    public final static int TWO_TO_22_POWER = 4194304;

    public final static int USB_TRANSFER_BUFFER_SIZE_HIGH_SAMPLE_RATE = 131072;

    public final static int USB_TRANSFER_BUFFER_SIZE_LOW_SAMPLE_RATE = 8192;

    public final static byte USB_INTERFACE = (byte) 0x0;

    public final static byte CONTROL_ENDPOINT_IN = (byte) (LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR);

    public final static byte CONTROL_ENDPOINT_OUT = (byte) (LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR);

    // uSeconds
    public final static long TIMEOUT_US = 1000000l;

    public final static byte REQUEST_ZERO = (byte) 0;

    public final static byte EEPROM_ADDRESS = (byte) 0xA0;

    public final static byte[] sFIR_COEFFICIENTS = { (byte) 0xCA, (byte) 0xDC, (byte) 0xD7, (byte) 0xD8, (byte) 0xE0, (byte) 0xF2, (byte) 0x0E, (byte) 0x35, (byte) 0x06, (byte) 0x50, (byte) 0x9C, (byte) 0x0D, (byte) 0x71, (byte) 0x11, (byte) 0x14, (byte) 0x71, (byte) 0x74, (byte) 0x19, (byte) 0x41, (byte) 0xA5 };

    public static final SampleRate DEFAULT_SAMPLE_RATE = SampleRate.RATE_2_400MHZ;

    protected Device mDevice;

    protected DeviceDescriptor mDeviceDescriptor;

    protected DeviceHandle mDeviceHandle;

    private SampleRate mSampleRate = DEFAULT_SAMPLE_RATE;

    protected NativeBufferConverter mNativeBufferConverter = new ByteSampleConverter();

    // 28.8 MHz
    protected int mOscillatorFrequency = 28800000;

    protected USBTransferProcessor mUSBTransferProcessor;

    protected Descriptor mDescriptor;

    /**
     * Abstract tuner controller device.  Use the static getTunerClreplaced() method
     * to determine the tuner type, and construct the corresponding child
     * tuner controller clreplaced for that tuner type.
     */
    public RTL2832TunerController(Device device, DeviceDescriptor deviceDescriptor, long minTunableFrequency, long maxTunableFrequency, int centerUnusableBandwidth, double usableBandwidthPercentage) throws SourceException {
        super(minTunableFrequency, maxTunableFrequency, centerUnusableBandwidth, usableBandwidthPercentage);
        mDevice = device;
        mDeviceDescriptor = deviceDescriptor;
    }

    @Override
    public int getBufferSampleCount() {
        // 2 bytes per complex sample
        return getUSBTransferBufferSize(getSampleRate()) / 2;
    }

    public void init() throws SourceException {
        mDeviceHandle = new DeviceHandle();
        int result = LibUsb.open(mDevice, mDeviceHandle);
        if (result != LibUsb.SUCCESS) {
            mDeviceHandle = null;
            throw new SourceException("libusb couldn't open RTL2832 usb " + "device [" + LibUsb.errorName(result) + "]");
        }
        claimInterface(mDeviceHandle);
        try {
            setSampleRate(DEFAULT_SAMPLE_RATE);
        } catch (Exception e) {
            throw new SourceException("RTL2832 Tuner Controller - couldn't " + "set default sample rate", e);
        }
        byte[] eeprom = null;
        try {
            /* Read the contents of the 256-byte EEPROM */
            eeprom = readEEPROM(mDeviceHandle, (short) 0, 256);
        } catch (Exception e) {
            mLog.error("error while reading the EEPROM device descriptor", e);
        }
        try {
            mDescriptor = new Descriptor(eeprom);
            if (eeprom == null) {
                mLog.error("eeprom byte array was null - constructed " + "empty descriptor object");
            }
        } catch (Exception e) {
            mLog.error("error while constructing device descriptor using " + "descriptor byte array " + (eeprom == null ? "[null]" : Arrays.toString(eeprom)), e);
        }
        String deviceName = getTunerType().getLabel() + " " + getUniqueID();
        mUSBTransferProcessor = new RTL2832USBTransferProcessor(deviceName, mDeviceHandle, mNativeBufferConverter, USB_TRANSFER_BUFFER_SIZE_HIGH_SAMPLE_RATE);
    }

    @Override
    protected USBTransferProcessor getUSBTransferProcessor() {
        return mUSBTransferProcessor;
    }

    /**
     * Claims the USB interface.  Attempts to detach the active kernel driver
     * if one is currently attached.
     */
    public static void claimInterface(DeviceHandle handle) throws SourceException {
        if (handle != null) {
            int result = LibUsb.kernelDriverActive(handle, USB_INTERFACE);
            if (result == 1) {
                result = LibUsb.detachKernelDriver(handle, USB_INTERFACE);
                if (result != LibUsb.SUCCESS) {
                    mLog.error("failed attempt to detach kernel driver [" + LibUsb.errorName(result) + "]");
                    throw new SourceException("couldn't detach kernel driver " + "from device");
                }
            }
            result = LibUsb.claimInterface(handle, USB_INTERFACE);
            if (result != LibUsb.SUCCESS) {
                throw new SourceException("couldn't claim usb interface [" + LibUsb.errorName(result) + "]");
            }
        } else {
            throw new SourceException("couldn't claim usb interface - no " + "device handle");
        }
    }

    public static void releaseInterface(DeviceHandle handle) throws SourceException {
        int result = LibUsb.releaseInterface(handle, USB_INTERFACE);
        if (result != LibUsb.SUCCESS) {
            throw new SourceException("couldn't release interface [" + LibUsb.errorName(result) + "]");
        }
    }

    /**
     * Descriptor contains all identifiers and labels parsed from the EEPROM.
     *
     * May return null if unable to get 256 byte eeprom descriptor from tuner
     * or if the descriptor doesn't begin with byte values of 0x28 and 0x32
     * meaning it is a valid (and can be parsed) RTL2832 descriptor
     */
    public Descriptor getDescriptor() {
        if (mDescriptor != null && mDescriptor.isValid()) {
            return mDescriptor;
        }
        return null;
    }

    public void setSamplingMode(SampleMode mode) throws LibUsbException {
        switch(mode) {
            case QUADRATURE:
                /* Set intermediate frequency to 0 Hz */
                setIFFrequency(0);
                /* Enable I/Q ADC Input */
                writeDemodRegister(mDeviceHandle, Page.ZERO, (short) 0x08, (short) 0xCD, 1);
                /* Enable zero-IF mode */
                writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0xB1, (short) 0x1B, 1);
                /* Set default i/q path */
                writeDemodRegister(mDeviceHandle, Page.ZERO, (short) 0x06, (short) 0x80, 1);
                break;
            case DIRECT:
            default:
                throw new LibUsbException("QUADRATURE mode is the only mode " + "currently supported", LibUsb.ERROR_NOT_SUPPORTED);
        }
    }

    public void setIFFrequency(int frequency) throws LibUsbException {
        long ifFrequency = ((long) TWO_TO_22_POWER * (long) frequency) / (long) mOscillatorFrequency * -1;
        /* Write byte 2 (high) */
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x19, (short) (Long.rotateRight(ifFrequency, 16) & 0x3F), 1);
        /* Write byte 1 (middle) */
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x1A, (short) (Long.rotateRight(ifFrequency, 8) & 0xFF), 1);
        /* Write byte 0 (low) */
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x1B, (short) (ifFrequency & 0xFF), 1);
    }

    public abstract void initTuner(boolean controlI2CRepeater) throws UsbException;

    /**
     * Provides a unique identifier to use in distinctly identifying this
     * tuner from among other tuners of the same type, so that we can fetch a
     * tuner configuration from the settings manager for this specific tuner.
     *
     * @return serial number of the device
     */
    public String getUniqueID() {
        if (mDescriptor != null && mDescriptor.hreplacederial()) {
            return mDescriptor.getSerial();
        } else {
            int serial = (0xFF & mDeviceDescriptor.iSerialNumber());
            return "SER#" + serial;
        }
    }

    public abstract void setSampleRateFilters(int sampleRate) throws SourceException;

    public abstract TunerType getTunerType();

    public static TunerType identifyTunerType(Device device) throws SourceException {
        DeviceHandle handle = new DeviceHandle();
        int reason = LibUsb.open(device, handle);
        if (reason != LibUsb.SUCCESS) {
            throw new SourceException("couldn't open device - check permissions" + " Linux: udev.rule? , or Windows: reinstall Zadig? [" + LibUsb.errorName(reason) + "]");
        }
        TunerType tunerClreplaced = TunerType.UNKNOWN;
        try {
            claimInterface(handle);
            /* Perform a dummy write to see if the device needs reset */
            boolean resetRequired = false;
            try {
                writeRegister(handle, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1);
            } catch (LibUsbException e) {
                if (e.getErrorCode() < 0) {
                    mLog.error("error performing dummy write - attempting " + "device reset", e);
                    resetRequired = true;
                } else {
                    throw new SourceException("error performing dummy write " + "to device [" + LibUsb.errorName(e.getErrorCode()) + "]", e);
                }
            }
            if (resetRequired) {
                reason = LibUsb.resetDevice(handle);
                try {
                    writeRegister(handle, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1);
                } catch (LibUsbException e2) {
                    mLog.error("device reset attempted, but lost device handle.  " + "Try restarting the application to use this device");
                    throw new SourceException("couldn't reset device");
                }
            }
            /* Initialize the baseband */
            initBaseband(handle);
            enableI2CRepeater(handle, true);
            boolean controlI2CRepeater = false;
            /* Test for each tuner type until we find the correct one */
            if (isTuner(TunerTypeCheck.E4K, handle, controlI2CRepeater)) {
                tunerClreplaced = TunerType.ELONICS_E4000;
            } else if (isTuner(TunerTypeCheck.FC0013, handle, controlI2CRepeater)) {
                tunerClreplaced = TunerType.FITIPOWER_FC0013;
            } else if (isTuner(TunerTypeCheck.R820T, handle, controlI2CRepeater)) {
                tunerClreplaced = TunerType.RAFAELMICRO_R820T;
            } else if (isTuner(TunerTypeCheck.R828D, handle, controlI2CRepeater)) {
                tunerClreplaced = TunerType.RAFAELMICRO_R828D;
            } else if (isTuner(TunerTypeCheck.FC2580, handle, controlI2CRepeater)) {
                tunerClreplaced = TunerType.FCI_FC2580;
            } else if (isTuner(TunerTypeCheck.FC0012, handle, controlI2CRepeater)) {
                tunerClreplaced = TunerType.FITIPOWER_FC0012;
            }
            enableI2CRepeater(handle, false);
            releaseInterface(handle);
            LibUsb.close(handle);
        } catch (Exception e) {
            mLog.error("error while determining tuner type", e);
        }
        return tunerClreplaced;
    }

    /**
     * Releases the USB interface
     */
    public void release() {
        try {
            if (mUSBTransferProcessor != null) {
                mUSBTransferProcessor.removeListener();
                TunerManager.LIBUSB_TRANSFER_PROCESSOR.unregisterTransferProcessor(mUSBTransferProcessor);
            }
            LibUsb.releaseInterface(mDeviceHandle, USB_INTERFACE);
        } catch (Exception e) {
            mLog.error("attempt to release USB interface failed", e);
        }
    }

    public void resetUSBBuffer() throws LibUsbException {
        writeRegister(mDeviceHandle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2);
        writeRegister(mDeviceHandle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x0000, 2);
    }

    public static void initBaseband(DeviceHandle handle) throws LibUsbException {
        /* Initialize USB */
        writeRegister(handle, Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1);
        writeRegister(handle, Block.USB, Address.USB_EPA_MAXPKT.getAddress(), 0x0002, 2);
        writeRegister(handle, Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2);
        /* Power on demod */
        writeRegister(handle, Block.SYS, Address.DEMOD_CTL_1.getAddress(), 0x22, 1);
        writeRegister(handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0xE8, 1);
        /* Reset demod */
        // Bit 3 = soft reset
        writeDemodRegister(handle, Page.ONE, (short) 0x01, 0x14, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x01, 0x10, 1);
        /* Disable spectrum inversion and adjacent channel rejection */
        writeDemodRegister(handle, Page.ONE, (short) 0x15, 0x00, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x16, 0x0000, 2);
        /* Clear DDC shift and IF frequency registers */
        writeDemodRegister(handle, Page.ONE, (short) 0x16, 0x00, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x17, 0x00, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x18, 0x00, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x19, 0x00, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x1A, 0x00, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x1B, 0x00, 1);
        /* Set FIR coefficients */
        for (int x = 0; x < sFIR_COEFFICIENTS.length; x++) {
            writeDemodRegister(handle, Page.ONE, (short) (0x1C + x), sFIR_COEFFICIENTS[x], 1);
        }
        /* Enable SDR mode, disable DAGC (bit 5) */
        writeDemodRegister(handle, Page.ZERO, (short) 0x19, 0x05, 1);
        /* Init FSM state-holding register */
        writeDemodRegister(handle, Page.ONE, (short) 0x93, 0xF0, 1);
        writeDemodRegister(handle, Page.ONE, (short) 0x94, 0x0F, 1);
        /* Disable AGC (en_dagc, bit 0) (seems to have no effect) */
        writeDemodRegister(handle, Page.ONE, (short) 0x11, 0x00, 1);
        /* Disable RF and IF AGC loop */
        writeDemodRegister(handle, Page.ONE, (short) 0x04, 0x00, 1);
        /* Disable PID filter */
        writeDemodRegister(handle, Page.ZERO, (short) 0x61, 0x60, 1);
        /* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */
        writeDemodRegister(handle, Page.ZERO, (short) 0x06, 0x80, 1);
        /* Enable Zero-if mode (en_bbin bit),
         *        DC cancellation (en_dc_est),
         *        IQ estimation/compensation (en_iq_comp, en_iq_est) */
        writeDemodRegister(handle, Page.ONE, (short) 0xB1, 0x1B, 1);
        /* Disable 4.096 MHz clock output on pin TP_CK0 */
        writeDemodRegister(handle, Page.ZERO, (short) 0x0D, 0x83, 1);
    }

    protected void deinitBaseband(DeviceHandle handle) throws IllegalArgumentException, UsbDisconnectedException, UsbException {
        writeRegister(handle, Block.SYS, Address.DEMOD_CTL.getAddress(), 0x20, 1);
    }

    /**
     * Sets the General Purpose Input/Output (GPIO) register bit
     *
     * @param handle - USB tuner device
     * @param bitMask - bit mask with one for targeted register bits and zero
     * for the non-targeted register bits
     * @param enabled - true to set the bit and false to clear the bit
     * @throws UsbDisconnectedException - if the tuner device is disconnected
     * @throws UsbException             - if there is a USB error while communicating with
     *                                  the device
     */
    protected static void setGPIOBit(DeviceHandle handle, byte bitMask, boolean enabled) throws LibUsbException {
        // Get current register value
        int value = readRegister(handle, Block.SYS, Address.GPO.getAddress(), 1);
        // Update the masked bits
        if (enabled) {
            value |= bitMask;
        } else {
            value &= ~bitMask;
        }
        // Write the change back to the device
        writeRegister(handle, Block.SYS, Address.GPO.getAddress(), value, 1);
    }

    /**
     * Enables GPIO Output
     *
     * @param handle - usb tuner device
     * @param bitMask - mask containing one bit value in targeted bit field(s)
     * @throws UsbDisconnectedException
     * @throws UsbException
     */
    protected static void setGPIOOutput(DeviceHandle handle, byte bitMask) throws LibUsbException {
        // Get current register value
        int value = readRegister(handle, Block.SYS, Address.GPD.getAddress(), 1);
        // Mask the value and rewrite it
        writeRegister(handle, Block.SYS, Address.GPO.getAddress(), value & ~bitMask, 1);
        // Get current register value
        value = readRegister(handle, Block.SYS, Address.GPOE.getAddress(), 1);
        // Mask the value and rewrite it
        writeRegister(handle, Block.SYS, Address.GPOE.getAddress(), value | bitMask, 1);
    }

    protected static void enableI2CRepeater(DeviceHandle handle, boolean enabled) throws LibUsbException {
        Page page = Page.ONE;
        short address = 1;
        int value;
        if (enabled) {
            // ON
            value = 0x18;
        } else {
            // OFF
            value = 0x10;
        }
        writeDemodRegister(handle, page, address, value, 1);
    }

    protected boolean isI2CRepeaterEnabled() throws SourceException {
        int register = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x1, 1);
        return register == 0x18;
    }

    protected static int readI2CRegister(DeviceHandle handle, byte i2CAddress, byte i2CRegister, boolean controlI2CRepeater) throws LibUsbException {
        short address = (short) (i2CAddress & 0xFF);
        ByteBuffer buffer = ByteBuffer.allocateDirect(1);
        buffer.put(i2CRegister);
        buffer.rewind();
        ByteBuffer data = ByteBuffer.allocateDirect(1);
        if (controlI2CRepeater) {
            enableI2CRepeater(handle, true);
            write(handle, address, Block.I2C, buffer);
            read(handle, address, Block.I2C, data);
            enableI2CRepeater(handle, false);
        } else {
            write(handle, address, Block.I2C, buffer);
            read(handle, address, Block.I2C, data);
        }
        return (int) (data.get() & 0xFF);
    }

    protected void writeI2CRegister(DeviceHandle handle, byte i2CAddress, byte i2CRegister, byte value, boolean controlI2CRepeater) throws LibUsbException {
        short address = (short) (i2CAddress & 0xFF);
        ByteBuffer buffer = ByteBuffer.allocateDirect(2);
        buffer.put(i2CRegister);
        buffer.put(value);
        buffer.rewind();
        if (controlI2CRepeater) {
            enableI2CRepeater(handle, true);
            write(handle, address, Block.I2C, buffer);
            enableI2CRepeater(handle, false);
        } else {
            write(handle, address, Block.I2C, buffer);
        }
    }

    protected static void writeDemodRegister(DeviceHandle handle, Page page, short address, int value, int length) throws LibUsbException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(length);
        buffer.order(ByteOrder.BIG_ENDIAN);
        if (length == 1) {
            buffer.put((byte) (value & 0xFF));
        } else if (length == 2) {
            buffer.putShort((short) (value & 0xFFFF));
        } else {
            throw new IllegalArgumentException("Cannot write value greater " + "than 16 bits to the register - length [" + length + "]");
        }
        short index = (short) (0x10 | page.getPage());
        short newAddress = (short) (address << 8 | 0x20);
        write(handle, newAddress, index, buffer);
        readDemodRegister(handle, Page.TEN, (short) 1, length);
    }

    protected static int readDemodRegister(DeviceHandle handle, Page page, short address, int length) throws LibUsbException {
        short index = page.getPage();
        short newAddress = (short) ((address << 8) | 0x20);
        ByteBuffer buffer = ByteBuffer.allocateDirect(length);
        read(handle, newAddress, index, buffer);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        if (length == 2) {
            return (int) (buffer.getShort() & 0xFFFF);
        } else {
            return (int) (buffer.get() & 0xFF);
        }
    }

    protected static void writeRegister(DeviceHandle handle, Block block, short address, int value, int length) throws LibUsbException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(length);
        buffer.order(ByteOrder.BIG_ENDIAN);
        if (length == 1) {
            buffer.put((byte) (value & 0xFF));
        } else if (length == 2) {
            buffer.putShort((short) value);
        } else {
            throw new IllegalArgumentException("Cannot write value greater " + "than 16 bits to the register - length [" + length + "]");
        }
        buffer.rewind();
        write(handle, address, block, buffer);
    }

    protected static int readRegister(DeviceHandle handle, Block block, short address, int length) throws LibUsbException {
        ByteBuffer buffer = ByteBuffer.allocateDirect(2);
        read(handle, address, block, buffer);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        if (length == 2) {
            return (int) (buffer.getShort() & 0xFFFF);
        } else {
            return (int) (buffer.get() & 0xFF);
        }
    }

    /**
     */
    protected static void write(DeviceHandle handle, short address, Block block, ByteBuffer buffer) throws LibUsbException {
        write(handle, address, block.getWriteIndex(), buffer);
    }

    protected static void write(DeviceHandle handle, short value, short index, ByteBuffer buffer) throws LibUsbException {
        if (handle != null) {
            int transferred = LibUsb.controlTransfer(handle, CONTROL_ENDPOINT_OUT, REQUEST_ZERO, value, index, buffer, TIMEOUT_US);
            if (transferred < 0) {
                throw new LibUsbException("error writing byte buffer", transferred);
            } else if (transferred != buffer.capacity()) {
                throw new LibUsbException("transferred bytes [" + transferred + "] is not what was expected [" + buffer.capacity() + "]", transferred);
            }
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    /**
     * Performs a control type read
     */
    protected static void read(DeviceHandle handle, short address, short index, ByteBuffer buffer) throws LibUsbException {
        if (handle != null) {
            int transferred = LibUsb.controlTransfer(handle, CONTROL_ENDPOINT_IN, REQUEST_ZERO, address, index, buffer, TIMEOUT_US);
            if (transferred < 0) {
                throw new LibUsbException("read error", transferred);
            } else if (transferred != buffer.capacity()) {
                throw new LibUsbException("transferred bytes [" + transferred + "] is not what was expected [" + buffer.capacity() + "]", transferred);
            }
        } else {
            throw new LibUsbException("device handle is null", LibUsb.ERROR_NO_DEVICE);
        }
    }

    /**
     * Reads byte array from index at the address.
     *
     * @return big-endian byte array (needs to be swapped to be usable)
     */
    protected static void read(DeviceHandle handle, short address, Block block, ByteBuffer buffer) throws LibUsbException {
        read(handle, address, block.getReadIndex(), buffer);
    }

    /**
     * Tests if the specified tuner type is contained in the usb tuner device.
     *
     * @param type - tuner type to test for
     * @param handle - handle to the usb tuner device
     * @param controlI2CRepeater - indicates if the method should control the
     * I2C repeater independently
     * @return - true if the device is the specified tuner type
     */
    protected static boolean isTuner(TunerTypeCheck type, DeviceHandle handle, boolean controlI2CRepeater) {
        try {
            if (type == TunerTypeCheck.FC0012 || type == TunerTypeCheck.FC2580) {
                /* Initialize the GPIOs */
                setGPIOOutput(handle, (byte) 0x20);
                /* Reset tuner before probing */
                setGPIOBit(handle, (byte) 0x20, true);
                setGPIOBit(handle, (byte) 0x20, false);
            }
            int value = readI2CRegister(handle, type.getI2CAddress(), type.getCheckAddress(), controlI2CRepeater);
            if (type == TunerTypeCheck.FC2580) {
                return ((value & 0x7F) == type.getCheckValue());
            } else {
                return (value == type.getCheckValue());
            }
        } catch (LibUsbException e) {
        // Do nothing ... it's not the specified tuner
        }
        return false;
    }

    public double getCurrentSampleRate() {
        return mSampleRate.getRate();
    }

    public int getSampleRateFromTuner() throws SourceException {
        try {
            int high = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x9F, 2);
            int low = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0xA1, 2);
            int ratio = Integer.rotateLeft(high, 16) | low;
            int rate = (int) (mOscillatorFrequency * TWO_TO_22_POWER / ratio);
            SampleRate sampleRate = SampleRate.getClosest(rate);
            /* If we're not currently set to this rate, set it as the current rate */
            if (sampleRate.getRate() != rate) {
                setSampleRate(sampleRate);
                return sampleRate.getRate();
            }
        } catch (Exception e) {
            throw new SourceException("RTL2832 Tuner Controller - cannot get " + "current sample rate", e);
        }
        return DEFAULT_SAMPLE_RATE.getRate();
    }

    public void setSampleRate(SampleRate sampleRate) throws SourceException {
        /* Write high-order 16-bits of sample rate ratio to demod register */
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x9F, sampleRate.getRatioHighBits(), 2);
        /* Write low-order 16-bits of sample rate ratio to demod register.
         * Note: none of the defined rates have a low order ratio value, so we
         * simply write a zero to the register */
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0xA1, 0, 2);
        /* Set sample rate correction to 0 */
        setSampleRateFrequencyCorrection(0);
        /* Reset the demod for the changes to take effect */
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x01, 0x14, 1);
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x01, 0x10, 1);
        /* Apply any tuner specific sample rate filter settings */
        setSampleRateFilters(sampleRate.getRate());
        mSampleRate = sampleRate;
        mFrequencyController.setSampleRate(sampleRate.getRate());
        if (mUSBTransferProcessor != null) {
            mUSBTransferProcessor.setBufferSize(getUSBTransferBufferSize(sampleRate.getRate()));
        }
    }

    /**
     * Determines the size of USB transfer buffers according to the sample rate
     */
    private int getUSBTransferBufferSize(double sampleRate) {
        if (sampleRate > 300000) {
            return USB_TRANSFER_BUFFER_SIZE_HIGH_SAMPLE_RATE;
        }
        return USB_TRANSFER_BUFFER_SIZE_LOW_SAMPLE_RATE;
    }

    public void setSampleRateFrequencyCorrection(int ppm) throws SourceException {
        int offset = -ppm * TWO_TO_22_POWER / 1000000;
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x3F, (offset & 0xFF), 1);
        writeDemodRegister(mDeviceHandle, Page.ONE, (short) 0x3E, (Integer.rotateRight(offset, 8) & 0xFF), 1);
        /* Test to retune controller to apply frequency correction */
        try {
            mFrequencyController.setFrequency(mFrequencyController.getFrequency());
        } catch (Exception e) {
            throw new SourceException("couldn't set sample rate frequency correction", e);
        }
    }

    public int getSampleRateFrequencyCorrection() throws UsbException {
        int high = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x3E, 1);
        int low = readDemodRegister(mDeviceHandle, Page.ONE, (short) 0x3F, 1);
        return (Integer.rotateLeft(high, 8) | low);
    }

    /**
     * Returns contents of the 256-byte EEPROM.  The contents are as follows:
     *
     * 256-byte EEPROM (in hex):
     * 00/01 - 2832 Signature
     * 03/02 - 0BDA Vendor ID
     * 05/04 - 2832 Product ID
     * 06 - A5 (has serial id?)
     * 07 - 16 (bit field - bit 0 = remote wakeup, bit 1 = IR enabled
     * 08 - 02 or 12
     * 10/09 0310 ETX(0x03) plus label length (includes length and ETX bytes)
     * 12/11 First UTF-16 character
     * 14/13 Second UTF-16 character ...
     *
     * Label 1: vendor
     * Label 2: product
     * Label 3: serial
     * Label 4,5 ... (user defined)
     */
    public byte[] readEEPROM(DeviceHandle handle, short offset, int length) throws IllegalArgumentException {
        if (offset + length > 256) {
            throw new IllegalArgumentException("cannot read more than 256 " + "bytes from EEPROM - requested to read to byte [" + (offset + length) + "]");
        }
        byte[] data = new byte[length];
        ByteBuffer buffer = ByteBuffer.allocateDirect(1);
        try {
            /* Tell the RTL-2832 to address the EEPROM */
            writeRegister(handle, Block.I2C, EEPROM_ADDRESS, (byte) offset, 1);
        } catch (LibUsbException e) {
            mLog.error("usb error while attempting to set read address to " + "EEPROM register, prior to reading the EEPROM device " + "descriptor", e);
        }
        for (int x = 0; x < length; x++) {
            try {
                read(handle, EEPROM_ADDRESS, Block.I2C, buffer);
                data[x] = buffer.get();
                buffer.rewind();
            } catch (Exception e) {
                mLog.error("error while reading eeprom byte [" + x + "/" + length + "] aborting eeprom read and returning partially " + "filled descriptor byte array", e);
                x = length;
            }
        }
        return data;
    }

    /**
     * Writes a single byte to the 256-byte EEPROM using the specified offset.
     *
     * Note: introduce a 5 millisecond delay between each successive write to
     * the EEPROM or subsequent writes may fail.
     */
    public void writeEEPROMByte(DeviceHandle handle, byte offset, byte value) throws IllegalArgumentException, UsbDisconnectedException, UsbException {
        if (offset < 0 || offset > 255) {
            throw new IllegalArgumentException("RTL2832 Tuner Controller - " + "EEPROM offset must be within range of 0 - 255");
        }
        int offsetAndValue = Integer.rotateLeft((0xFF & offset), 8) | (0xFF & value);
        writeRegister(handle, Block.I2C, EEPROM_ADDRESS, offsetAndValue, 2);
    }

    public enum Address {

        USB_SYSCTL(0x2000),
        USB_CTRL(0x2010),
        USB_STAT(0x2014),
        USB_EPA_CFG(0x2144),
        USB_EPA_CTL(0x2148),
        USB_EPA_MAXPKT(0x2158),
        USB_EPA_MAXPKT_2(0x215A),
        USB_EPA_FIFO_CFG(0x2160),
        DEMOD_CTL(0x3000),
        GPO(0x3001),
        GPI(0x3002),
        GPOE(0x3003),
        GPD(0x3004),
        SYSINTE(0x3005),
        SYSINTS(0x3006),
        GP_CFG0(0x3007),
        GP_CFG1(0x3008),
        SYSINTE_1(0x3009),
        SYSINTS_1(0x300A),
        DEMOD_CTL_1(0x300B),
        IR_SUSPEND(0x300C);

        private int mAddress;

        private Address(int address) {
            mAddress = address;
        }

        public short getAddress() {
            return (short) mAddress;
        }
    }

    public enum Page {

        ZERO(0x0), ONE(0x1), TEN(0xA);

        private int mPage;

        private Page(int page) {
            mPage = page;
        }

        public byte getPage() {
            return (byte) (mPage & 0xFF);
        }
    }

    public enum SampleMode {

        QUADRATURE, DIRECT
    }

    public enum Block {

        DEMOD(0),
        USB(1),
        SYS(2),
        TUN(3),
        ROM(4),
        IR(5),
        // I2C controller
        I2C(6);

        private int mValue;

        private Block(int value) {
            mValue = value;
        }

        public int getValue() {
            return mValue;
        }

        /**
         * Returns the value left shifted 8 bits
         */
        public short getReadIndex() {
            return (short) Integer.rotateLeft(mValue, 8);
        }

        public short getWriteIndex() {
            return (short) (getReadIndex() | 0x10);
        }
    }

    /**
     * Sample rates supported by the RTL-2832.
     *
     * Formula to calculate the ratio value:
     *
     * ratio = ( ( crystal_frequency * 2^22 ) / sample_rate ) & ~3
     *
     * Default crystal_frequency is 28,800,000
     *
     * This produces a 32-bit value that has to be set in 2 x 16-bit registers.
     * Place the high 16-bit value in ratioMSB and the low 16-bit value in
     * ratioLSB.  Use integer for these values to avoid sign-extension issues.
     *
     * Mask the value with 0xFFFF when setting the register.
     */
    public enum SampleRate {

        /* Note: sample rates below 1.0MHz are subject to aliasing */
        RATE_0_230MHZ(0x1F40, 230400, "0.230 MHz"),
        RATE_0_240MHZ(0x1E00, 240000, "0.240 MHz"),
        RATE_0_256MHZ(0x1C20, 256000, "0.256 MHz"),
        RATE_0_288MHZ(0x1900, 288000, "0.288 MHz"),
        RATE_0_300MHZ(0x1800, 300000, "0.300 MHz"),
        RATE_0_960MHZ(0x0780, 960000, "0.960 MHz"),
        RATE_1_024MHZ(0x0708, 1024000, "1.024 MHz"),
        RATE_1_200MHZ(0x0600, 1200000, "1.200 MHz"),
        RATE_1_440MHZ(0x0500, 1440000, "1.440 MHz"),
        RATE_1_600MHZ(0x0480, 1600000, "1.600 MHz"),
        RATE_1_800MHZ(0x0400, 1800000, "1.800 MHz"),
        RATE_1_920MHZ(0x03C0, 1920000, "1.920 MHz"),
        RATE_2_048MHZ(0x0384, 2048000, "2.048 MHz"),
        RATE_2_304MHZ(0x0320, 2304000, "2.304 MHz"),
        RATE_2_400MHZ(0x0300, 2400000, "2.400 MHz"),
        RATE_2_560MHZ(0x02D0, 2560000, "2.560 MHz"),
        RATE_2_880MHZ(0x0280, 2880000, "2.880 MHz");

        private int mRatioHigh;

        private int mRate;

        private String mLabel;

        private SampleRate(int ratioHigh, int rate, String label) {
            mRatioHigh = ratioHigh;
            mRate = rate;
            mLabel = label;
        }

        public int getRatioHighBits() {
            return mRatioHigh;
        }

        public int getRate() {
            return mRate;
        }

        public String getLabel() {
            return mLabel;
        }

        public String toString() {
            return mLabel;
        }

        /**
         * Returns the sample rate that is equal to the argument or the next
         * higher sample rate
         *
         * @param sampleRate
         * @return
         */
        public static SampleRate getClosest(int sampleRate) {
            for (SampleRate rate : values()) {
                if (rate.getRate() >= sampleRate) {
                    return rate;
                }
            }
            return DEFAULT_SAMPLE_RATE;
        }
    }

    public enum TunerTypeCheck {

        E4K(0xC8, 0x02, 0x40),
        FC0012(0xC6, 0x00, 0xA1),
        FC0013(0xC6, 0x00, 0xA3),
        FC2580(0xAC, 0x01, 0x56),
        R820T(0x34, 0x00, 0x69),
        R828D(0x74, 0x00, 0x69);

        private int mI2CAddress;

        private int mCheckAddress;

        private int mCheckValue;

        TunerTypeCheck(int i2c, int address, int value) {
            mI2CAddress = i2c;
            mCheckAddress = address;
            mCheckValue = value;
        }

        public byte getI2CAddress() {
            return (byte) mI2CAddress;
        }

        public byte getCheckAddress() {
            return (byte) mCheckAddress;
        }

        public byte getCheckValue() {
            return (byte) mCheckValue;
        }
    }

    /**
     * RTL2832 EEPROM byte array descriptor parsing clreplaced
     */
    public clreplaced Descriptor {

        private byte[] mData;

        private ArrayList<String> mLabels = new ArrayList<String>();

        public Descriptor(byte[] data) {
            if (data != null) {
                mData = data;
            } else {
                data = new byte[256];
            }
            getLabels();
        }

        public boolean isValid() {
            return mData[0] == (byte) 0x28 && mData[1] == (byte) 0x32;
        }

        public String getVendorID() {
            int id = Integer.rotateLeft((0xFF & mData[3]), 8) | (0xFF & mData[2]);
            return String.format("%04X", id);
        }

        public String getVendorLabel() {
            return mLabels.get(0);
        }

        public String getProductID() {
            int id = Integer.rotateLeft((0xFF & mData[5]), 8) | (0xFF & mData[4]);
            return String.format("%04X", id);
        }

        public String getProductLabel() {
            return mLabels.get(1);
        }

        public boolean hreplacederial() {
            return mData[6] == (byte) 0xA5;
        }

        public String getSerial() {
            return mLabels.get(2);
        }

        public boolean remoteWakeupEnabled() {
            byte mask = (byte) 0x01;
            return (mData[7] & mask) == mask;
        }

        public boolean irEnabled() {
            byte mask = (byte) 0x02;
            return (mData[7] & mask) == mask;
        }

        private void getLabels() {
            mLabels.clear();
            int start = 0x09;
            while (start < 256) {
                start = getLabel(start);
            }
        }

        private int getLabel(int start) {
            /* Validate length and check second byte for ETX (0x03) */
            if (start > 254 || mData[start + 1] != (byte) 0x03) {
                return 256;
            }
            /* Get label length, including the length and ETX bytes */
            int length = 0xFF & mData[start];
            if (start + length > 255) {
                return 256;
            }
            /* Get the label bytes */
            byte[] data = Arrays.copyOfRange(mData, start + 2, start + length);
            /* Translate the bytes as UTF-16 Little Endian and store the label */
            String label = new String(data, Charset.forName("UTF-16LE"));
            mLabels.add(label);
            return start + length;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("RTL-2832 EEPROM Descriptor\n");
            sb.append("Vendor: ");
            sb.append(getVendorID());
            sb.append(" [");
            sb.append(getVendorLabel());
            sb.append("]\n");
            sb.append("Product: ");
            sb.append(getProductID());
            sb.append(" [");
            sb.append(getProductLabel());
            sb.append("]\n");
            sb.append("Serial: ");
            if (hreplacederial()) {
                sb.append("yes [");
                sb.append(getSerial());
                sb.append("]\n");
            } else {
                sb.append("no\n");
            }
            sb.append("Remote Wakeup Enabled: ");
            sb.append((remoteWakeupEnabled() ? "yes" : "no"));
            sb.append("\n");
            sb.append("IR Enabled: ");
            sb.append((irEnabled() ? "yes" : "no"));
            sb.append("\n");
            if (mLabels.size() > 3) {
                sb.append("Additional Labels: ");
                for (int x = 3; x < mLabels.size(); x++) {
                    sb.append(" [");
                    sb.append(mLabels.get(x));
                    sb.append("\n");
                }
            }
            return sb.toString();
        }
    }

    /**
     * Adds the IQ buffer listener and automatically starts buffer transfer processing, if not already started.
     */
    @Override
    public void addBufferListener(Listener<ReusableComplexBuffer> listener) {
        boolean hasExistingListeners = hasBufferListeners();
        super.addBufferListener(listener);
        if (!hasExistingListeners) {
            mUSBTransferProcessor.setListener(this);
        }
    }

    /**
     * Removes the IQ buffer listener and stops buffer transfer processing if there are no more listeners.
     */
    @Override
    public void removeBufferListener(Listener<ReusableComplexBuffer> listener) {
        super.removeBufferListener(listener);
        if (!hasBufferListeners()) {
            mUSBTransferProcessor.removeListener();
        }
    }

    /**
     * RTL-2832 USB transfer processor.  Extends USB transfer processor and allows resetting the device USB
     * buffer prior to starting streaming.
     */
    public clreplaced RTL2832USBTransferProcessor extends USBTransferProcessor {

        /**
         * Manages stream of USB transfer buffers and converts buffers to complex buffer samples for distribution to
         * any registered listeners.
         *
         * @param deviceName to use when logging information or errors
         * @param deviceHandle to the USB bulk transfer device
         * @param nativeBufferConverter specific to the tuner's byte buffer format for converting to floating point I/Q samples
         * @param bufferSize in bytes.  Should be a multiple of two: 65536, 131072 or 262144.
         */
        public RTL2832USBTransferProcessor(String deviceName, DeviceHandle deviceHandle, NativeBufferConverter nativeBufferConverter, int bufferSize) {
            super(deviceName, deviceHandle, nativeBufferConverter, bufferSize);
        }

        @Override
        protected void prepareDeviceStart() {
            resetUSBBuffer();
        }
    }
}

14 View Complete Implementation : MissileLauncher.java
Copyright The Unlicense
Author : usb4java
/**
 * Sends a message to the missile launcher.
 *
 * @param handle
 *            The USB device handle.
 * @param message
 *            The message to send.
 */
public static void sendMessage(DeviceHandle handle, byte[] message) {
    ByteBuffer buffer = ByteBuffer.allocateDirect(message.length);
    buffer.put(message);
    buffer.rewind();
    int transfered = LibUsb.controlTransfer(handle, (byte) (LibUsb.REQUEST_TYPE_CLreplaced | LibUsb.RECIPIENT_INTERFACE), (byte) 0x09, (short) 2, (short) 1, buffer, TIMEOUT);
    if (transfered < 0)
        throw new LibUsbException("Control transfer failed", transfered);
    if (transfered != message.length)
        throw new RuntimeException("Not all data was sent to device");
}

14 View Complete Implementation : AbstractDevice.java
Copyright MIT License
Author : usb4java
/**
 * Returns the languages the specified device supports.
 *
 * @return Array with supported language codes. Never null. May be empty.
 * @throws UsbException
 *             When string descriptor languages could not be read.
 */
private short[] getLanguages() throws UsbException {
    final DeviceHandle handle = open();
    final ByteBuffer buffer = ByteBuffer.allocateDirect(256);
    final int result = LibUsb.getDescriptor(handle, LibUsb.DT_STRING, (byte) 0, buffer);
    if (result < 0) {
        throw ExceptionUtils.createPlatformException("Unable to get string descriptor languages", result);
    }
    if (result < 2)
        throw new UsbException("Received illegal descriptor length: " + result);
    final short[] languages = new short[(result - 2) / 2];
    if (languages.length == 0)
        return languages;
    buffer.position(2);
    buffer.order(ByteOrder.LITTLE_ENDIAN).replacedhortBuffer().get(languages);
    return languages;
}

14 View Complete Implementation : IrpQueue.java
Copyright MIT License
Author : usb4java
/**
 * Reads bytes from an interrupt endpoint into the specified data array.
 *
 * @param data
 *            The data array to write the read bytes to.
 * @param offset
 *            The offset in the data array to write the read bytes to.
 * @param len
 *            The number of bytes to read.
 * @throws UsbException
 *             When transfer fails.
 * @return The number of read bytes.
 */
private int read(final byte[] data, final int offset, final int len) throws UsbException {
    final UsbEndpointDescriptor descriptor = getEndpointDescriptor();
    final byte type = this.pipe.getUsbEndpoint().getType();
    final DeviceHandle handle = getDevice().open();
    int read = 0;
    while (read < len) {
        final int size = Math.min(len - read, descriptor.wMaxPacketSize() & 0xffff);
        final ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        final int result = transfer(handle, descriptor, type, buffer);
        buffer.rewind();
        buffer.get(data, offset + read, result);
        read += result;
        // Short packet detected, aborting
        if (result < size)
            break;
    }
    return read;
}

14 View Complete Implementation : IrpQueue.java
Copyright MIT License
Author : usb4java
/**
 * Writes the specified bytes to a interrupt endpoint.
 *
 * @param data
 *            The data array with the bytes to write.
 * @param offset
 *            The offset in the data array to write.
 * @param len
 *            The number of bytes to write.
 * @throws UsbException
 *             When transfer fails.
 * @return The number of written bytes.
 */
private int write(final byte[] data, final int offset, final int len) throws UsbException {
    final UsbEndpointDescriptor descriptor = getEndpointDescriptor();
    final byte type = this.pipe.getUsbEndpoint().getType();
    final DeviceHandle handle = getDevice().open();
    int written = 0;
    while (written < len) {
        final int size = Math.min(len - written, descriptor.wMaxPacketSize() & 0xffff);
        final ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        buffer.put(data, offset + written, size);
        buffer.rewind();
        final int result = transfer(handle, descriptor, type, buffer);
        written += result;
        // Short packet detected, aborting
        if (result < size)
            break;
    }
    return written;
}