package com.example.myapplication.util;

import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;

public class DfuRuntimeDetachRunnable implements Runnable
{

    private final String TAG = this.getClass().getSimpleName();
    private int mIdxInterface;
    private UsbManager mManager = null;
    private UsbDevice mDevice = null;
    private UsbInterface mInterface = null;
    private UsbDeviceConnection mConn = null;

    public DfuRuntimeDetachRunnable(Context context, UsbDevice device)
    {
        this.mIdxInterface = UsbDfuConstants.findDfuRuntimeModeInterface(device);
        if (this.mIdxInterface != -1)
        {
            this.mDevice = device;
            this.mInterface = device.getInterface(mIdxInterface);
            this.mManager = (UsbManager)context.getSystemService(Context.USB_SERVICE);
        }
        else
        {
            Log.e(TAG,"The device does not have a DFU Runtime Mode Interface.");
        }
    }

    @Override
    public void run()
    {

        // Early Exit if a DFU runtime inteface is not found
        if (mDevice == null)
        {
            Log.e(TAG, "run() called with device == null!");
            return;
        }

        // Open a UsbDeviceConnection
        mConn = mManager.openDevice(mDevice);
        if (mConn == null)
        {
            Log.e(TAG, "Could not open device connection!");
            return;
        }

        // Claim interface (may be optional)
        if (!mConn.claimInterface(mInterface, false))
        {
            Log.e(TAG, "Failed to claim DFU runtime mode interface!");
        }

        // =========================================================================================
        // Send DFU_DETACH class request
        int result = mConn.controlTransfer( UsbDfuConstants.DFU_DETACH_bmRequestType, // DFU_DETACH bmRequest
                                            UsbDfuConstants.DFU_DETACH_bRequest, // DFU_DETACH bRequest
                                            UsbDfuConstants.DFU_DETACH_wValue,
                                            mIdxInterface,
                                            null,
                                            0,
                                            UsbDfuConstants.USB_TRANSFER_TIMEOUT);
        // Debug
        if (result < 0)
        {
            Log.e(TAG, "Failed to send DFU_DETACH. Returned: " + result);
        }
        else
        {
            Log.d(TAG, "DFU_DETACH. Sent successfully: " + result);
        }

        // Done. Nothing else to do but wait for device self-reset.
        mConn.releaseInterface(mInterface);
        mConn.close();
    }
}
