This commit is contained in:
2026-03-31 08:51:33 +08:00
commit e9f4844352
63 changed files with 8950 additions and 0 deletions

9
android/.gitignore vendored Normal file
View File

@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.cxx

60
android/build.gradle Normal file
View File

@@ -0,0 +1,60 @@
group = "com.xiarui.zhiwen"
version = "1.0"
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.0")
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: "com.android.library"
android {
if (project.android.hasProperty("namespace")) {
namespace = "com.xiarui.zhiwen"
}
compileSdk = 34
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
defaultConfig {
minSdk = 21
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
dependencies {
testImplementation("junit:junit:4.13.2")
testImplementation("org.mockito:mockito-core:5.0.0")
}
testOptions {
unitTests.all {
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen {false}
showStandardStreams = true
}
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
android/settings.gradle Normal file
View File

@@ -0,0 +1 @@
rootProject.name = 'zhiwen'

View File

@@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiarui.zhiwen">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
</manifest>

View File

@@ -0,0 +1,21 @@
package android_serialport_api;
import java.text.SimpleDateFormat;
/**
* @author benjaminwan
*/
public class ComBean {
public byte[] bRec=null;
public String sRecTime="";
public String sComPort="";
public int nSize = 0;
public ComBean(String sPort,byte[] buffer,int size){
sComPort=sPort;
bRec=new byte[size];
System.arraycopy(buffer, 0, bRec, 0, size);
nSize = size;
SimpleDateFormat sDateFormat = new SimpleDateFormat("hh:mm:ss");
sRecTime = sDateFormat.format(new java.util.Date());
}
}

View File

@@ -0,0 +1,231 @@
package android_serialport_api;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import com.xiarui.zhiwen.DevComm;
import android_serialport_api.ComBean;
import android_serialport_api.SerialPort;
public abstract class SerialHelper{
private SerialPort mSerialPort;
private OutputStream mOutputStream;
private InputStream mInputStream;
private ReadThread mReadThread;
private SendThread mSendThread;
private String sPort="/dev/s3c2410_serial0";
private int iBaudRate=9600;
private boolean _isOpen=false;
private byte[] _bLoopData=new byte[]{0x30};
private int iDelay=500;
//----------------------------------------------------
public SerialHelper(String sPort,int iBaudRate){
this.sPort = sPort;
this.iBaudRate=iBaudRate;
}
public SerialHelper(){
this("/dev/s3c2410_serial0",9600);
}
public SerialHelper(String sPort){
this(sPort,9600);
}
public SerialHelper(String sPort,String sBaudRate){
this(sPort,Integer.parseInt(sBaudRate));
}
//----------------------------------------------------
public void open() throws SecurityException, IOException,InvalidParameterException{
mSerialPort = new SerialPort(new File(sPort), iBaudRate, 0);
mOutputStream = mSerialPort.getOutputStream();
mInputStream = mSerialPort.getInputStream();
mReadThread = new ReadThread();
mReadThread.start();
mSendThread = new SendThread();
mSendThread.setSuspendFlag();
mSendThread.start();
_isOpen=true;
}
//----------------------------------------------------
public void close(){
if (mReadThread != null)
mReadThread.interrupt();
if (mSerialPort != null) {
mSerialPort.close();
mSerialPort = null;
}
_isOpen=false;
}
//----------------------------------------------------
public void send(byte[] bOutArray, int nSize){
try
{
mOutputStream.write(bOutArray, 0, nSize);
} catch (IOException e)
{
e.printStackTrace();
}
}
//----------------------------------------------------
public void sendTxt(String sTxt){
byte[] bOutArray =sTxt.getBytes();
send(bOutArray, sTxt.length());
}
//----------------------------------------------------
private class ReadThread extends Thread {
@Override
public void run() {
super.run();
while(!isInterrupted()) {
try
{
if (mInputStream == null) return;
byte[] buffer=new byte[DevComm.MAX_DATA_LEN];
int size = mInputStream.read(buffer);
if (size > 0){
ComBean ComRecData = new ComBean(sPort,buffer,size);
onDataReceived(ComRecData);
}
try
{
Thread.sleep(50);
} catch (InterruptedException e)
{
e.printStackTrace();
}
} catch (Throwable e)
{
e.printStackTrace();
return;
}
}
}
}
//----------------------------------------------------
private class SendThread extends Thread{
public boolean suspendFlag = true;
@Override
public void run() {
super.run();
while(!isInterrupted()) {
synchronized (this)
{
while (suspendFlag)
{
try
{
wait();
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
send(getbLoopData(), 1);
try
{
Thread.sleep(iDelay);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void setSuspendFlag() {
this.suspendFlag = true;
}
public synchronized void setResume() {
this.suspendFlag = false;
notify();
}
}
//----------------------------------------------------
public int getBaudRate()
{
return iBaudRate;
}
public boolean setBaudRate(int iBaud)
{
if (_isOpen)
{
return false;
} else
{
iBaudRate = iBaud;
return true;
}
}
public boolean setBaudRate(String sBaud)
{
int iBaud = Integer.parseInt(sBaud);
return setBaudRate(iBaud);
}
//----------------------------------------------------
public String getPort()
{
return sPort;
}
public boolean setPort(String sPort)
{
if (_isOpen)
{
return false;
} else
{
this.sPort = sPort;
return true;
}
}
//----------------------------------------------------
public boolean isOpen()
{
return _isOpen;
}
//----------------------------------------------------
public byte[] getbLoopData()
{
return _bLoopData;
}
//----------------------------------------------------
public void setbLoopData(byte[] bLoopData)
{
this._bLoopData = bLoopData;
}
//----------------------------------------------------
public void setTxtLoopData(String sTxt){
this._bLoopData = sTxt.getBytes();
}
//----------------------------------------------------
public int getiDelay()
{
return iDelay;
}
//----------------------------------------------------
public void setiDelay(int iDelay)
{
this.iDelay = iDelay;
}
//----------------------------------------------------
public void startSend()
{
if (mSendThread != null)
{
mSendThread.setResume();
}
}
//----------------------------------------------------
public void stopSend()
{
if (mSendThread != null)
{
mSendThread.setSuspendFlag();
}
}
//----------------------------------------------------
protected abstract void onDataReceived(ComBean ComRecData);
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2009 Cedric Priscal
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android_serialport_api;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.util.Log;
public class SerialPort {
private static final String TAG = "SerialPort";
/*
* Do not remove or rename the field mFd: it is used by native method close();
*/
private final FileDescriptor mFd;
private final FileInputStream mFileInputStream;
private final FileOutputStream mFileOutputStream;
public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
/* Check access permission */
if (!device.canRead() || !device.canWrite()) {
try {
/* Missing read/write permission, trying to chmod the file */
Process su;
su = Runtime.getRuntime().exec("/system/bin/su");
String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ "exit\n";
su.getOutputStream().write(cmd.getBytes());
if ((su.waitFor() != 0) || !device.canRead()
|| !device.canWrite()) {
throw new SecurityException();
}
} catch (Exception e) {
e.printStackTrace();
throw new SecurityException();
}
}
mFd = open(device.getAbsolutePath(), baudrate, flags);
if (mFd == null) {
Log.e(TAG, "native open returns null");
throw new IOException();
}
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
}
// Getters and setters
public InputStream getInputStream() {
return mFileInputStream;
}
public OutputStream getOutputStream() {
return mFileOutputStream;
}
// JNI
private native static FileDescriptor open(String path, int baudrate, int flags);
public native void close();
static {
try {
System.loadLibrary("serial_port");
} catch (UnsatisfiedLinkError err) {
err.printStackTrace();
}
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2009 Cedric Priscal
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android_serialport_api;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.Iterator;
import java.util.Vector;
import android.util.Log;
public class SerialPortFinder {
public class Driver {
public Driver(String name, String root) {
mDriverName = name;
mDeviceRoot = root;
}
private final String mDriverName;
private final String mDeviceRoot;
Vector<File> mDevices = null;
public Vector<File> getDevices() {
if (mDevices == null) {
mDevices = new Vector<File>();
File dev = new File("/dev");
File[] files = dev.listFiles();
int i;
for (i=0; i<files.length; i++) {
if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
Log.d(TAG, "Found new device: " + files[i]);
mDevices.add(files[i]);
}
}
}
return mDevices;
}
public String getName() {
return mDriverName;
}
}
private static final String TAG = "SerialPort";
private Vector<Driver> mDrivers = null;
Vector<Driver> getDrivers() throws IOException {
if (mDrivers == null) {
mDrivers = new Vector<Driver>();
LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
String l;
while((l = r.readLine()) != null) {
// Issue 3:
// Since driver name may contain spaces, we do not extract driver name with split()
String drivername = l.substring(0, 0x15).trim();
String[] w = l.split(" +");
if ((w.length >= 5) && (w[w.length-1].equals("serial"))) {
Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length-4]);
mDrivers.add(new Driver(drivername, w[w.length-4]));
}
}
r.close();
}
return mDrivers;
}
public String[] getAllDevices() {
Vector<String> devices = new Vector<String>();
// Parse each driver
Iterator<Driver> itdriv;
try {
itdriv = getDrivers().iterator();
while(itdriv.hasNext()) {
Driver driver = itdriv.next();
Iterator<File> itdev = driver.getDevices().iterator();
while(itdev.hasNext()) {
String device = itdev.next().getName();
String value = String.format("%s (%s)", device, driver.getName());
devices.add(value);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return devices.toArray(new String[devices.size()]);
}
public String[] getAllDevicesPath() {
Vector<String> devices = new Vector<String>();
// Parse each driver
Iterator<Driver> itdriv;
try {
itdriv = getDrivers().iterator();
while(itdriv.hasNext()) {
Driver driver = itdriv.next();
Iterator<File> itdev = driver.getDevices().iterator();
while(itdev.hasNext()) {
String device = itdev.next().getAbsolutePath();
devices.add(device);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return devices.toArray(new String[devices.size()]);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
package com.idworld.noemhost_and;
/**
* Created by KMS on 2016/8/23.
*/
public interface IUsbConnState {
void onUsbConnected();
void onUsbPermissionDenied();
void onDeviceNotFound();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,440 @@
package com.idworld.noemhost_and;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
/**
* Created by KMS on 2016/8/23.
*/
public class UsbController {
private final Context mApplicationContext;
private final UsbManager mUsbManager;
private final int VID;
private final int PID;
private int m_nEPInSize, m_nEPOutSize;
private final byte[] m_abyTransferBuf;
private boolean m_bInit = false;
private UsbDeviceConnection m_usbConn = null;
private UsbInterface m_usbIf = null;
private UsbEndpoint m_epIN = null;
private UsbEndpoint m_epOUT = null;
private final IUsbConnState mConnectionHandler;
protected static final String ACTION_USB_PERMISSION = "ch.serverbox.android.USB";
/**
* Activity is needed for onResult
*
* @param parentActivity
*/
public UsbController(Activity parentActivity, IUsbConnState connectionHandler, int vid, int pid){
mConnectionHandler = connectionHandler;
mApplicationContext = parentActivity.getApplicationContext();
mUsbManager = (UsbManager) mApplicationContext.getSystemService(Context.USB_SERVICE);
VID = vid;
PID = pid;
m_abyTransferBuf = new byte[512];
//init();
}
public void init(){
enumerate(new IPermissionListener() {
@Override
public void onPermissionDenied(UsbDevice d) {
UsbManager usbman = (UsbManager) mApplicationContext.getSystemService(Context.USB_SERVICE);
PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext, 0, new Intent(ACTION_USB_PERMISSION), FLAG_IMMUTABLE);
mApplicationContext.registerReceiver(mPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION));
usbman.requestPermission(d, pi);
}
});
}
public void uninit(){
if (m_usbConn != null)
{
m_usbConn.releaseInterface(m_usbIf);
m_usbConn.close();
m_usbConn = null;
m_bInit = false;
}
//stop();
}
public void stop()
{
try{
mApplicationContext.unregisterReceiver(mPermissionReceiver);
}catch(IllegalArgumentException e){}//bravo
}
public boolean IsInit(){
return m_bInit;
}
private void enumerate(IPermissionListener listener) {
boolean bFound = false;
l("enumerating");
HashMap<String, UsbDevice> devlist = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviter = devlist.values().iterator();
while (deviter.hasNext()) {
UsbDevice d = deviter.next();
l("Found device: " + String.format("%04X:%04X", d.getVendorId(), d.getProductId()));
Toast.makeText(mApplicationContext, "Found device: " + String.format("%04X:%04X", d.getVendorId(), d.getProductId()), Toast.LENGTH_SHORT).show();
if (d.getVendorId() == VID && d.getProductId() == PID) {
bFound = true;
l("Device under: " + d.getDeviceName());
if (!mUsbManager.hasPermission(d))
{
Toast.makeText(mApplicationContext, "enumerate, hasPermission return false" , Toast.LENGTH_SHORT).show();
listener.onPermissionDenied(d);
}
else{
Toast.makeText(mApplicationContext, "enumerate, GetConnInerface start" , Toast.LENGTH_SHORT).show();
//startHandler(d);
GetConnInerface(d);
//TestComm(d);
return;
}
break;
}
}
if (!bFound)
{
Toast.makeText(mApplicationContext, "no more devices found" , Toast.LENGTH_SHORT).show();
mConnectionHandler.onDeviceNotFound();
}
}
private class PermissionReceiver extends BroadcastReceiver {
private final IPermissionListener mPermissionListener;
public PermissionReceiver(IPermissionListener permissionListener) {
mPermissionListener = permissionListener;
}
@Override
public void onReceive(Context context, Intent intent) {
mApplicationContext.unregisterReceiver(this);
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
if (!intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
mPermissionListener.onPermissionDenied(intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE));
mConnectionHandler.onUsbPermissionDenied();
} else {
l("Permission granted");
UsbDevice dev = intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (dev != null) {
if (dev.getVendorId() == VID
&& dev.getProductId() == PID) {
//startHandler(dev);// has new thread
GetConnInerface(dev);
//TestComm(dev);
}
} else {
mConnectionHandler.onDeviceNotFound();
}
}
}
}
}
private void GetConnInerface(UsbDevice dev){
int n;
m_usbConn = mUsbManager.openDevice(dev);
n = dev.getInterfaceCount();
if (n <= 0)
return;
if (!m_usbConn.claimInterface(dev.getInterface(0), true)) {
return;
}
m_usbIf = dev.getInterface(0);
n = m_usbIf.getEndpointCount();
if (n < 2)
return;
for (int i = 0; i < n; i++) {
if (m_usbIf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (m_usbIf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
m_epIN = m_usbIf.getEndpoint(i);
else
m_epOUT = m_usbIf.getEndpoint(i);
}
}
m_nEPInSize = m_epIN.getMaxPacketSize();
m_nEPOutSize = m_epOUT.getMaxPacketSize();
m_bInit = true;
//m_epOUT.getMaxPacketSize();
//Toast.makeText(mApplicationContext, "GetConnInerface OK, Out Max Size="+m_nEPOutSize+" In Max Size=" + m_nEPInSize, Toast.LENGTH_SHORT).show();
mConnectionHandler.onUsbConnected();
}
public boolean OperationInternal(byte[] pData, int nDataLen, int nTimeOut, boolean bRead)
{
byte[] w_abyTmp = new byte[31];
byte[] w_abyCSW = new byte[13];
boolean w_bRet;
Arrays.fill(w_abyTmp, (byte)0);
w_abyTmp[0] = 0x55;
w_abyTmp[1] = 0x53;
w_abyTmp[2] = 0x42;
w_abyTmp[3] = 0x43;
w_abyTmp[4] = 0x28;
w_abyTmp[5] = 0x2b;
w_abyTmp[6] = 0x18;
w_abyTmp[7] = (byte)0x89;
w_abyTmp[8] = (byte)(nDataLen & 0xFF);
w_abyTmp[9] = (byte)((nDataLen >> 8)& 0xFF);
w_abyTmp[10] = (byte)((nDataLen >> 16)& 0xFF);
w_abyTmp[11] = (byte)((nDataLen >> 24)& 0xFF);
if(bRead)
w_abyTmp[12] = (byte)0x80;
else
w_abyTmp[12] = 0x00; //cCBWFlags
w_abyTmp[13] = 0x00; //cCBWlun
w_abyTmp[14] = 0x0a; //cCBWCBLength
w_abyTmp[15] = (byte)0xef;
if (bRead)
w_abyTmp[16] = (byte)0xff;
else
w_abyTmp[16] = (byte)0xfe;
// send 31bytes
w_bRet = UsbBulkSend(w_abyTmp, 31, nTimeOut);
if (!w_bRet)
return false;
// read or write real data
if (bRead)
w_bRet = UsbBulkReceive(pData, nDataLen, nTimeOut);
else
w_bRet = UsbBulkSend(pData, nDataLen, nTimeOut);
if (!w_bRet)
return false;
// receive csw
w_bRet = UsbBulkReceive(w_abyCSW, 13, nTimeOut);
return w_bRet;
}
public boolean UsbSCSIWrite(byte[] pCDB, int nCDBLen, byte[] pData, int nDataLen, int nTimeOut)
{
byte[] w_abyTmp = new byte[31];
byte[] w_abyCSW = new byte[13];
boolean w_bRet;
//Arrays.fill(w_abyTmp, (byte)0);
w_abyTmp[0] = 0x55;
w_abyTmp[1] = 0x53;
w_abyTmp[2] = 0x42;
w_abyTmp[3] = 0x43;
w_abyTmp[4] = 0x28;
w_abyTmp[5] = 0x2b;
w_abyTmp[6] = 0x18;
w_abyTmp[7] = (byte)0x89;
w_abyTmp[8] = 0x00;
w_abyTmp[9] = 0x00;
w_abyTmp[10] = 0x00;
w_abyTmp[11] = 0x00;
w_abyTmp[12] = 0x00; //cCBWFlags
w_abyTmp[13] = 0x00; //cCBWlun
w_abyTmp[14] = 0x0a; //cCBWCBLength
System.arraycopy(pCDB, 0, w_abyTmp, 15, nCDBLen);
//System.arraycopy(pData, 0, w_abyTmp, 31, nDataLen);
w_bRet = UsbBulkSend(w_abyTmp, 31, nTimeOut);
if (!w_bRet)
return false;
w_bRet = UsbBulkSend(pData, nDataLen, nTimeOut);
if (!w_bRet)
return false;
// receive csw
w_bRet = UsbBulkReceive(w_abyCSW, 13, nTimeOut);
return w_bRet;
}
public boolean UsbSCSIRead(byte[] pCDB, int nCDBLen, byte[] pData, int nDataLen, int nTimeOut)
{
long w_nTime;
byte[] w_abyTmp = new byte[31];
byte[] w_abyCSW = new byte[13];
boolean w_bRet;
//Arrays.fill(w_abyTmp, (byte)0);
w_abyTmp[0] = 0x55;
w_abyTmp[1] = 0x53;
w_abyTmp[2] = 0x42;
w_abyTmp[3] = 0x43;
w_abyTmp[4] = 0x28;
w_abyTmp[5] = 0x2b;
w_abyTmp[6] = 0x18;
w_abyTmp[7] = (byte)0x89;
w_abyTmp[8] = 0x00;
w_abyTmp[9] = 0x00;
w_abyTmp[10] = 0x00;
w_abyTmp[11] = 0x00;
w_abyTmp[12] = (byte)0x80; //cCBWFlags
w_abyTmp[13] = 0x00; //cCBWlun
w_abyTmp[14] = 0x0a; //cCBWCBLength
System.arraycopy(pCDB, 0, w_abyTmp, 15, nCDBLen);
w_bRet = UsbBulkSend(w_abyTmp, 31, nTimeOut);
if (!w_bRet)
return false;
w_nTime = SystemClock.elapsedRealtime();
w_bRet = UsbBulkReceive(pData, nDataLen, nTimeOut);
w_nTime = SystemClock.elapsedRealtime() - w_nTime;
//Toast.makeText(mApplicationContext, "UsbSCSIRead, UsbBulkReceive Time : " + w_nTime , Toast.LENGTH_SHORT).show();
if (!w_bRet)
return false;
// receive csw
w_bRet = UsbBulkReceive(w_abyCSW, 13, nTimeOut);
return w_bRet;
}
private boolean UsbBulkSend(byte[] pBuf, int nLen, int nTimeOut)
{
int i, n, r, w_nRet;
//byte[] w_abyTmp = new byte[m_nEPOutSize];
n = nLen / m_nEPOutSize;
r = nLen % m_nEPOutSize;
for(i=0; i<n; i++)
{
System.arraycopy(pBuf, i*m_nEPOutSize, m_abyTransferBuf, 0, m_nEPOutSize);
w_nRet = m_usbConn.bulkTransfer(m_epOUT, m_abyTransferBuf, m_nEPOutSize, nTimeOut);
if (w_nRet != m_nEPOutSize)
return false;
}
if (r > 0)
{
System.arraycopy(pBuf, i*m_nEPOutSize, m_abyTransferBuf, 0, r);
w_nRet = m_usbConn.bulkTransfer(m_epOUT, m_abyTransferBuf, r, nTimeOut);
return w_nRet == r;
}
return true;
}
private boolean UsbBulkReceive(byte[] pBuf, int nLen, int nTimeOut)
{
int i, n, r, w_nRet;
//byte[] w_abyTmp = new byte[m_nEPInSize];
//w_nRet = m_usbConn.bulkTransfer(m_epIN, pBuf, nLen, nTimeOut);
//if (w_nRet != nLen)
// return false;
n = nLen / m_nEPInSize;
r = nLen % m_nEPInSize;
//Toast.makeText(mApplicationContext, "UsbBulkReceive, Buf Len = " + pBuf.length, Toast.LENGTH_SHORT).show();
for(i=0; i<n; i++)
{
w_nRet = m_usbConn.bulkTransfer(m_epIN, m_abyTransferBuf, m_nEPInSize, nTimeOut);
if (w_nRet != m_nEPInSize)
return false;
System.arraycopy(m_abyTransferBuf, 0, pBuf, i*m_nEPInSize, m_nEPInSize);
}
if (r > 0)
{
w_nRet = m_usbConn.bulkTransfer(m_epIN, m_abyTransferBuf, r, nTimeOut);
if (w_nRet != r)
return false;
System.arraycopy(m_abyTransferBuf, 0, pBuf, i*m_nEPInSize, r);
}
return true;
}
// END MAIN LOOP
private final BroadcastReceiver mPermissionReceiver = new PermissionReceiver(
new IPermissionListener() {
@Override
public void onPermissionDenied(UsbDevice d) {
l("Permission denied on " + d.getDeviceId());
}
});
private interface IPermissionListener {
void onPermissionDenied(UsbDevice d);
}
public final static String TAG = "USBController";
private void l(Object msg) {
Log.d(TAG, ">==< " + msg.toString() + " >==<");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
package com.xiarui.zhiwen;
/**
* Created by KMS on 2016/8/23.
*/
public interface IUsbConnState {
void onUsbConnected();
void onUsbPermissionDenied();
void onDeviceNotFound();
}

View File

@@ -0,0 +1,440 @@
package com.xiarui.zhiwen;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
/**
* Created by KMS on 2016/8/23.
*/
public class UsbController {
private final Context mApplicationContext;
private final UsbManager mUsbManager;
private final int VID;
private final int PID;
private int m_nEPInSize, m_nEPOutSize;
private final byte[] m_abyTransferBuf;
private boolean m_bInit = false;
private UsbDeviceConnection m_usbConn = null;
private UsbInterface m_usbIf = null;
private UsbEndpoint m_epIN = null;
private UsbEndpoint m_epOUT = null;
private final IUsbConnState mConnectionHandler;
protected static final String ACTION_USB_PERMISSION = "ch.serverbox.android.USB";
/**
* Activity is needed for onResult
*
* @param parentActivity
*/
public UsbController(Activity parentActivity, IUsbConnState connectionHandler, int vid, int pid){
mConnectionHandler = connectionHandler;
mApplicationContext = parentActivity.getApplicationContext();
mUsbManager = (UsbManager) mApplicationContext.getSystemService(Context.USB_SERVICE);
VID = vid;
PID = pid;
m_abyTransferBuf = new byte[512];
//init();
}
public void init(){
enumerate(new IPermissionListener() {
@Override
public void onPermissionDenied(UsbDevice d) {
UsbManager usbman = (UsbManager) mApplicationContext.getSystemService(Context.USB_SERVICE);
PendingIntent pi = PendingIntent.getBroadcast(mApplicationContext, 0, new Intent(ACTION_USB_PERMISSION), FLAG_IMMUTABLE);
mApplicationContext.registerReceiver(mPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION));
usbman.requestPermission(d, pi);
}
});
}
public void uninit(){
if (m_usbConn != null)
{
m_usbConn.releaseInterface(m_usbIf);
m_usbConn.close();
m_usbConn = null;
m_bInit = false;
}
//stop();
}
public void stop()
{
try{
mApplicationContext.unregisterReceiver(mPermissionReceiver);
}catch(IllegalArgumentException e){}//bravo
}
public boolean IsInit(){
return m_bInit;
}
private void enumerate(IPermissionListener listener) {
boolean bFound = false;
l("enumerating");
HashMap<String, UsbDevice> devlist = mUsbManager.getDeviceList();
Iterator<UsbDevice> deviter = devlist.values().iterator();
while (deviter.hasNext()) {
UsbDevice d = deviter.next();
l("Found device: " + String.format("%04X:%04X", d.getVendorId(), d.getProductId()));
// Toast.makeText(mApplicationContext, "Found device: " + String.format("%04X:%04X", d.getVendorId(), d.getProductId()), Toast.LENGTH_SHORT).show();
if (d.getVendorId() == VID && d.getProductId() == PID) {
bFound = true;
l("Device under: " + d.getDeviceName());
if (!mUsbManager.hasPermission(d))
{
Toast.makeText(mApplicationContext, "enumerate, hasPermission return false" , Toast.LENGTH_SHORT).show();
listener.onPermissionDenied(d);
}
else{
// Toast.makeText(mApplicationContext, "enumerate, GetConnInerface start" , Toast.LENGTH_SHORT).show();
//startHandler(d);
GetConnInerface(d);
//TestComm(d);
return;
}
break;
}
}
if (!bFound)
{
Toast.makeText(mApplicationContext, "no more devices found" , Toast.LENGTH_SHORT).show();
mConnectionHandler.onDeviceNotFound();
}
}
private class PermissionReceiver extends BroadcastReceiver {
private final IPermissionListener mPermissionListener;
public PermissionReceiver(IPermissionListener permissionListener) {
mPermissionListener = permissionListener;
}
@Override
public void onReceive(Context context, Intent intent) {
mApplicationContext.unregisterReceiver(this);
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
if (!intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
mPermissionListener.onPermissionDenied(intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE));
mConnectionHandler.onUsbPermissionDenied();
} else {
l("Permission granted");
UsbDevice dev = intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (dev != null) {
if (dev.getVendorId() == VID
&& dev.getProductId() == PID) {
//startHandler(dev);// has new thread
GetConnInerface(dev);
//TestComm(dev);
}
} else {
mConnectionHandler.onDeviceNotFound();
}
}
}
}
}
private void GetConnInerface(UsbDevice dev){
int n;
m_usbConn = mUsbManager.openDevice(dev);
n = dev.getInterfaceCount();
if (n <= 0)
return;
if (!m_usbConn.claimInterface(dev.getInterface(0), true)) {
return;
}
m_usbIf = dev.getInterface(0);
n = m_usbIf.getEndpointCount();
if (n < 2)
return;
for (int i = 0; i < n; i++) {
if (m_usbIf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
if (m_usbIf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
m_epIN = m_usbIf.getEndpoint(i);
else
m_epOUT = m_usbIf.getEndpoint(i);
}
}
m_nEPInSize = m_epIN.getMaxPacketSize();
m_nEPOutSize = m_epOUT.getMaxPacketSize();
m_bInit = true;
//m_epOUT.getMaxPacketSize();
//Toast.makeText(mApplicationContext, "GetConnInerface OK, Out Max Size="+m_nEPOutSize+" In Max Size=" + m_nEPInSize, Toast.LENGTH_SHORT).show();
mConnectionHandler.onUsbConnected();
}
public boolean OperationInternal(byte[] pData, int nDataLen, int nTimeOut, boolean bRead)
{
byte[] w_abyTmp = new byte[31];
byte[] w_abyCSW = new byte[13];
boolean w_bRet;
Arrays.fill(w_abyTmp, (byte)0);
w_abyTmp[0] = 0x55;
w_abyTmp[1] = 0x53;
w_abyTmp[2] = 0x42;
w_abyTmp[3] = 0x43;
w_abyTmp[4] = 0x28;
w_abyTmp[5] = 0x2b;
w_abyTmp[6] = 0x18;
w_abyTmp[7] = (byte)0x89;
w_abyTmp[8] = (byte)(nDataLen & 0xFF);
w_abyTmp[9] = (byte)((nDataLen >> 8)& 0xFF);
w_abyTmp[10] = (byte)((nDataLen >> 16)& 0xFF);
w_abyTmp[11] = (byte)((nDataLen >> 24)& 0xFF);
if(bRead)
w_abyTmp[12] = (byte)0x80;
else
w_abyTmp[12] = 0x00; //cCBWFlags
w_abyTmp[13] = 0x00; //cCBWlun
w_abyTmp[14] = 0x0a; //cCBWCBLength
w_abyTmp[15] = (byte)0xef;
if (bRead)
w_abyTmp[16] = (byte)0xff;
else
w_abyTmp[16] = (byte)0xfe;
// send 31bytes
w_bRet = UsbBulkSend(w_abyTmp, 31, nTimeOut);
if (!w_bRet)
return false;
// read or write real data
if (bRead)
w_bRet = UsbBulkReceive(pData, nDataLen, nTimeOut);
else
w_bRet = UsbBulkSend(pData, nDataLen, nTimeOut);
if (!w_bRet)
return false;
// receive csw
w_bRet = UsbBulkReceive(w_abyCSW, 13, nTimeOut);
return w_bRet;
}
public boolean UsbSCSIWrite(byte[] pCDB, int nCDBLen, byte[] pData, int nDataLen, int nTimeOut)
{
byte[] w_abyTmp = new byte[31];
byte[] w_abyCSW = new byte[13];
boolean w_bRet;
//Arrays.fill(w_abyTmp, (byte)0);
w_abyTmp[0] = 0x55;
w_abyTmp[1] = 0x53;
w_abyTmp[2] = 0x42;
w_abyTmp[3] = 0x43;
w_abyTmp[4] = 0x28;
w_abyTmp[5] = 0x2b;
w_abyTmp[6] = 0x18;
w_abyTmp[7] = (byte)0x89;
w_abyTmp[8] = 0x00;
w_abyTmp[9] = 0x00;
w_abyTmp[10] = 0x00;
w_abyTmp[11] = 0x00;
w_abyTmp[12] = 0x00; //cCBWFlags
w_abyTmp[13] = 0x00; //cCBWlun
w_abyTmp[14] = 0x0a; //cCBWCBLength
System.arraycopy(pCDB, 0, w_abyTmp, 15, nCDBLen);
//System.arraycopy(pData, 0, w_abyTmp, 31, nDataLen);
w_bRet = UsbBulkSend(w_abyTmp, 31, nTimeOut);
if (!w_bRet)
return false;
w_bRet = UsbBulkSend(pData, nDataLen, nTimeOut);
if (!w_bRet)
return false;
// receive csw
w_bRet = UsbBulkReceive(w_abyCSW, 13, nTimeOut);
return w_bRet;
}
public boolean UsbSCSIRead(byte[] pCDB, int nCDBLen, byte[] pData, int nDataLen, int nTimeOut)
{
long w_nTime;
byte[] w_abyTmp = new byte[31];
byte[] w_abyCSW = new byte[13];
boolean w_bRet;
//Arrays.fill(w_abyTmp, (byte)0);
w_abyTmp[0] = 0x55;
w_abyTmp[1] = 0x53;
w_abyTmp[2] = 0x42;
w_abyTmp[3] = 0x43;
w_abyTmp[4] = 0x28;
w_abyTmp[5] = 0x2b;
w_abyTmp[6] = 0x18;
w_abyTmp[7] = (byte)0x89;
w_abyTmp[8] = 0x00;
w_abyTmp[9] = 0x00;
w_abyTmp[10] = 0x00;
w_abyTmp[11] = 0x00;
w_abyTmp[12] = (byte)0x80; //cCBWFlags
w_abyTmp[13] = 0x00; //cCBWlun
w_abyTmp[14] = 0x0a; //cCBWCBLength
System.arraycopy(pCDB, 0, w_abyTmp, 15, nCDBLen);
w_bRet = UsbBulkSend(w_abyTmp, 31, nTimeOut);
if (!w_bRet)
return false;
w_nTime = SystemClock.elapsedRealtime();
w_bRet = UsbBulkReceive(pData, nDataLen, nTimeOut);
w_nTime = SystemClock.elapsedRealtime() - w_nTime;
//Toast.makeText(mApplicationContext, "UsbSCSIRead, UsbBulkReceive Time : " + w_nTime , Toast.LENGTH_SHORT).show();
if (!w_bRet)
return false;
// receive csw
w_bRet = UsbBulkReceive(w_abyCSW, 13, nTimeOut);
return w_bRet;
}
private boolean UsbBulkSend(byte[] pBuf, int nLen, int nTimeOut)
{
int i, n, r, w_nRet;
//byte[] w_abyTmp = new byte[m_nEPOutSize];
n = nLen / m_nEPOutSize;
r = nLen % m_nEPOutSize;
for(i=0; i<n; i++)
{
System.arraycopy(pBuf, i*m_nEPOutSize, m_abyTransferBuf, 0, m_nEPOutSize);
w_nRet = m_usbConn.bulkTransfer(m_epOUT, m_abyTransferBuf, m_nEPOutSize, nTimeOut);
if (w_nRet != m_nEPOutSize)
return false;
}
if (r > 0)
{
System.arraycopy(pBuf, i*m_nEPOutSize, m_abyTransferBuf, 0, r);
w_nRet = m_usbConn.bulkTransfer(m_epOUT, m_abyTransferBuf, r, nTimeOut);
return w_nRet == r;
}
return true;
}
private boolean UsbBulkReceive(byte[] pBuf, int nLen, int nTimeOut)
{
int i, n, r, w_nRet;
//byte[] w_abyTmp = new byte[m_nEPInSize];
//w_nRet = m_usbConn.bulkTransfer(m_epIN, pBuf, nLen, nTimeOut);
//if (w_nRet != nLen)
// return false;
n = nLen / m_nEPInSize;
r = nLen % m_nEPInSize;
//Toast.makeText(mApplicationContext, "UsbBulkReceive, Buf Len = " + pBuf.length, Toast.LENGTH_SHORT).show();
for(i=0; i<n; i++)
{
w_nRet = m_usbConn.bulkTransfer(m_epIN, m_abyTransferBuf, m_nEPInSize, nTimeOut);
if (w_nRet != m_nEPInSize)
return false;
System.arraycopy(m_abyTransferBuf, 0, pBuf, i*m_nEPInSize, m_nEPInSize);
}
if (r > 0)
{
w_nRet = m_usbConn.bulkTransfer(m_epIN, m_abyTransferBuf, r, nTimeOut);
if (w_nRet != r)
return false;
System.arraycopy(m_abyTransferBuf, 0, pBuf, i*m_nEPInSize, r);
}
return true;
}
// END MAIN LOOP
private final BroadcastReceiver mPermissionReceiver = new PermissionReceiver(
new IPermissionListener() {
@Override
public void onPermissionDenied(UsbDevice d) {
l("Permission denied on " + d.getDeviceId());
}
});
private interface IPermissionListener {
void onPermissionDenied(UsbDevice d);
}
public final static String TAG = "USBController";
private void l(Object msg) {
Log.d(TAG, ">==< " + msg.toString() + " >==<");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<resource>
<usb-device product-id="29987" vendor-id="6790" />
<usb-device product-id="21795" vendor-id="6790" />
<usb-device product-id="30264" vendor-id="8201" />
</resource>

View File

@@ -0,0 +1,29 @@
package com.xiarui.zhiwen;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import org.junit.Test;
/**
* This demonstrates a simple unit test of the Java portion of this plugin's implementation.
*
* Once you have built the plugin's example app, you can run these tests from the command
* line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or
* you can run them directly from IDEs that support JUnit such as Android Studio.
*/
public class ZhiwenPluginTest {
@Test
public void onMethodCall_getPlatformVersion_returnsExpectedValue() {
ZhiwenPlugin plugin = new ZhiwenPlugin();
final MethodCall call = new MethodCall("getPlatformVersion", null);
MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
plugin.onMethodCall(call, mockResult);
verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE);
}
}