package com.sunvote.xpadcomm.usb; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Handler; import android.os.HandlerThread; import com.sunvote.util.LogUtil; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /*** * @Auther Elvis */ public class UsbTransferManager { public interface OnUsbConnectListener{ boolean onConnect(boolean isConnected); } public static final String TAG = UsbTransferManager.class.getSimpleName(); private static UsbTransferManager instance = null ; private HandlerThread workThread = new HandlerThread("usb workThread"); private Handler workHandler = null; private boolean stop = false; private OnUsbConnectListener onUsbConnectListener; public void setOnUsbConnectListener(OnUsbConnectListener onUsbConnectListener) { this.onUsbConnectListener = onUsbConnectListener; } private UsbTransferManager(){ workThread.start(); workHandler = new Handler(workThread.getLooper()); } public static UsbTransferManager getInstance(){ if(instance == null){ synchronized(UsbTransferManager.class){ if(instance == null){ instance = new UsbTransferManager(); } } } return instance; } public void startWork(){ stop = false; workHandler.post(usbConnectInit); } public void stopWork(){ mUsbDevice = null; mUsbConnection = null; epIn = null; epOut = null; workHandler.removeCallbacks(usbConnectInit); workHandler.removeCallbacks(usbConnect); workHandler.removeCallbacks(usbConnectionReceiverTask); stop = true; } private UsbOutputStream outputStream = new UsbOutputStream(); private UsbInputStream inputStream = new UsbInputStream(); public UsbInputStream getInputStream() { return inputStream; } public UsbOutputStream getOutputStream() { return outputStream; } private long lastOpenTime; private class UsbPermissionReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (device.getDeviceName().equals(mUsbDevice.getDeviceName())) { if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { // 授权成功,在这里进行打开设备操作 if (System.currentTimeMillis() - lastOpenTime > 1000) { lastOpenTime = System.currentTimeMillis(); workHandler.removeCallbacks(usbConnectInit); workHandler.removeCallbacks(usbConnect); if(!stop){ workHandler.postDelayed(usbConnect,0); } } }else{ if(!stop){ workHandler.postDelayed(usbConnectInit,20000); } } } } } } } private Runnable usbConnectionReceiverTask = new Runnable() { @Override public void run() { if (usbManager != null) { HashMap map = usbManager.getDeviceList(); boolean find = false; for (UsbDevice device : map.values()) { LogUtil.d(TAG, "找到基站: Vid:" + device.getVendorId() + " Pid:" + device.getProductId()); if (device.getVendorId() == VendorID && device.getProductId() == ProductID || device.getVendorId() == VendorID_2 && device.getProductId() == ProductID_2 || device.getVendorId() == VendorID_3 && device.getProductId() == ProductID_3) { find = true; workHandler.postDelayed(usbConnectionReceiverTask, 1000); break; } } if (!find) { stopWork(); startWork(); } } } }; private Runnable usbConnectInit = new Runnable() { @Override public void run() { LogUtil.i(TAG, "发起USB初始化!"); boolean find = false; workHandler.removeCallbacks(usbConnectionReceiverTask); if(usbManager != null) { HashMap map = usbManager.getDeviceList(); for (UsbDevice device : map.values()) { LogUtil.d(TAG, "找到基站: Vid:" + device.getVendorId() + " Pid:" + device.getProductId()); if (device.getVendorId() == VendorID && device.getProductId() == ProductID || device.getVendorId() == VendorID_2 && device.getProductId() == ProductID_2 || device.getVendorId() == VendorID_3 && device.getProductId() == ProductID_3) { mUsbDevice = device; find = true; if (!usbManager.hasPermission(device)) { if (usbPermissionReceiver == null) { usbPermissionReceiver = new UsbPermissionReceiver(); } // 申请权限 Intent intent = new Intent(ACTION_USB_PERMISSION); PendingIntent mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); IntentFilter permissionFilter = new IntentFilter(ACTION_USB_PERMISSION); mContext.registerReceiver(usbPermissionReceiver, permissionFilter); usbManager.requestPermission(device, mPermissionIntent); if(!stop){ workHandler.postDelayed(usbConnectInit,20 * 1000); } } else { if(!stop){ workHandler.postDelayed(usbConnect,10); } } } } } if(!find){ workHandler.removeCallbacks(usbConnectInit); if(!stop){ workHandler.postDelayed(usbConnectInit,2000); } } } }; private Runnable usbConnect = new Runnable() { @Override public void run() { LogUtil.i(TAG, "发起USB键盘连接!"); if(openUsbDevice()){ if(onUsbConnectListener != null){ onUsbConnectListener.onConnect(true); } workHandler.postDelayed(usbConnectionReceiverTask,2000); }; } }; private Runnable readData = new Runnable() { @Override public void run() { byte[] datas = receiveUsbRequestData(); LogUtil.i(TAG, "RECEIVEA DATA:", datas); if(datas != null) { int length = datas.length; try { try { lock.lock(); if (linkedList.size() < MAX_CACHE_SIZE) { for (int i = length - 1; i >= 0; i--) { linkedList.push(datas[i]); } } } finally { empty.signal(); lock.unlock(); } } catch (Exception e) { LogUtil.e(TAG, "UDP receiver message", e); close = true; } if(!stop){ workHandler.post(readData); } }else{ stopWork(); startWork(); } } }; /** * 打开连接 * * @paramdevice */ private boolean openUsbDevice() { if (mUsbDevice == null) return false; if(mUsbDevice.getInterfaceCount() == 0){ return false; } mUsbInterface = mUsbDevice.getInterface(0); setEndpoint(mUsbInterface); mUsbConnection = usbManager.openDevice(mUsbDevice); LogUtil.i(TAG,"打开USB连接"); if (mUsbConnection != null) { return mUsbConnection.claimInterface(mUsbInterface, true); } return false; } private int sendDataBulkTransfer(byte[] buffer) { final int length = buffer.length; int ref = -100; if (epOut != null && mUsbConnection != null) { ref = mUsbConnection.bulkTransfer(epOut, buffer, length, 100); mUsbConnection.claimInterface(mUsbInterface, true); LogUtil.d(TAG, "发送数据成功有:" + ref); if(ref <0 ){ if(onUsbConnectListener != null){ onUsbConnectListener.onConnect(false); } workHandler.removeCallbacks(usbConnectionReceiverTask); workHandler.post(usbConnectionReceiverTask); } }else{ if(onUsbConnectListener != null){ onUsbConnectListener.onConnect(false); } LogUtil.d(TAG, "未连接:" + ref); } return ref; } public byte[] receiveUsbRequestData() { if(epIn != null && mUsbConnection != null) { byte[] bytes = new byte[epIn.getMaxPacketSize()]; int ret = mUsbConnection.bulkTransfer(epIn, bytes, bytes.length, 100); if (ret > 0) { return bytes; } } return null; } /** * UsbInterface 进行端点设置和通讯 * * @param intf */ private void setEndpoint(UsbInterface intf) { if (intf == null) return; // 设置接收数据的端点 if (intf.getEndpoint(0) != null) { epIn = intf.getEndpoint(0); } // 当端点为2的时候 if (intf.getEndpointCount() == 2) { // 设置发送数据的断点 if (intf.getEndpoint(1) != null) epOut = intf.getEndpoint(1); } } public void setUsbManager(UsbManager usbManager) { this.usbManager = usbManager; } public void setContext(Context mContext) { this.mContext = mContext; } public class UsbOutputStream extends OutputStream{ @Override public void write(int b) throws IOException { sendDataBulkTransfer(new byte[]{(byte)b}); } @Override public void write(byte[] b) throws IOException { sendDataBulkTransfer(b); } @Override public void write(byte[] b, int off, int len) throws IOException { byte[] temp = new byte[len]; System.arraycopy(b, off, temp, 0, len); sendDataBulkTransfer(temp); } } private LinkedList linkedList = new LinkedList(); public long MAX_CACHE_SIZE = 4 * 1024; private Lock lock = new ReentrantLock(); private Condition empty = lock.newCondition(); private boolean close = false; public class UsbInputStream extends InputStream{ @Override public int read() throws IOException { if (close) { throw new IOException("the stream has closed"); } try { lock.lock(); while (linkedList.isEmpty()) { try { empty.await(); } catch (InterruptedException e) { LogUtil.e(TAG,e); } } return linkedList.pop(); } finally { lock.unlock(); } } public boolean isClose() { return close; } @Override public void close() throws IOException { close = true; super.close(); } @Override public int read(byte[] buffer) throws IOException { try { lock.lock(); if (buffer == null) { throw new IOException("buffer is empty"); } if (close) { throw new IOException("the stream has closed"); } while (linkedList.isEmpty()) { try { empty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } int index = 0; while (index < buffer.length && !linkedList.isEmpty()) { buffer[index++] = linkedList.pop(); } return index; } finally { lock.unlock(); } } @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { try { lock.lock(); if (buffer == null) { throw new IOException("buffer is empty"); } if (close) { throw new IOException("the stream has closed"); } while (linkedList.isEmpty()) { try { empty.await(); } catch (InterruptedException e) { e.printStackTrace(); } } int index = 0; while (index < byteCount && !linkedList.isEmpty()) { index++; buffer[byteOffset++] = linkedList.pop(); } return index; } finally { lock.unlock(); } } } private UsbManager usbManager ; private UsbDevice mUsbDevice; private UsbDeviceConnection mUsbConnection; private UsbInterface mUsbInterface; private UsbEndpoint epOut, epIn; private UsbPermissionReceiver usbPermissionReceiver; private Context mContext ; private static final int VendorID = 0x03eb; private static final int ProductID = 0x6201; private static final int VendorID_2 = 0x0d8c; private static final int ProductID_2 = 0xEA10; private static final int VendorID_3 = 0x2F70; private static final int ProductID_3 = 0xEA10; private final String ACTION_USB_PERMISSION = "com.hhd.USB_PERMISSION"; private boolean isUsbReceiver = false; }