commit e9f484435240e32139145a44815eb0306d4f26f0
Author: leon <916117771@qq.com>
Date: Tue Mar 31 08:51:33 2026 +0800
init
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ac5aa98
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,29 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+build/
diff --git a/.metadata b/.metadata
new file mode 100644
index 0000000..a77bebb
--- /dev/null
+++ b/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49"
+ channel: "stable"
+
+project_type: plugin
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
+ base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
+ - platform: android
+ create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
+ base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..41cc7d8
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.0.1
+
+* TODO: Describe initial release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ba75c69
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+TODO: Add your license here.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6c2b3b2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# zhiwen
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter
+[plug-in package](https://flutter.dev/developing-packages/),
+a specialized package that includes platform-specific implementation code for
+Android and/or iOS.
+
+For help getting started with Flutter development, view the
+[online documentation](https://flutter.dev/docs), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
+
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..a5744c1
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..161bdcd
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..aa75089
--- /dev/null
+++ b/android/build.gradle
@@ -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
+ }
+ }
+ }
+}
diff --git a/android/libs/arm64-v8a/libserial_port.so b/android/libs/arm64-v8a/libserial_port.so
new file mode 100644
index 0000000..3659c4c
Binary files /dev/null and b/android/libs/arm64-v8a/libserial_port.so differ
diff --git a/android/libs/armeabi-v7a/libserial_port.so b/android/libs/armeabi-v7a/libserial_port.so
new file mode 100644
index 0000000..9a5aeb9
Binary files /dev/null and b/android/libs/armeabi-v7a/libserial_port.so differ
diff --git a/android/libs/armeabi/libserial_port.so b/android/libs/armeabi/libserial_port.so
new file mode 100644
index 0000000..15417c6
Binary files /dev/null and b/android/libs/armeabi/libserial_port.so differ
diff --git a/android/libs/x86/libserial_port.so b/android/libs/x86/libserial_port.so
new file mode 100644
index 0000000..6a1ce79
Binary files /dev/null and b/android/libs/x86/libserial_port.so differ
diff --git a/android/libs/x86_64/libserial_port.so b/android/libs/x86_64/libserial_port.so
new file mode 100644
index 0000000..bc31e32
Binary files /dev/null and b/android/libs/x86_64/libserial_port.so differ
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..bd3eb06
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'zhiwen'
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..026ef5e
--- /dev/null
+++ b/android/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/android/src/main/java/android_serialport_api/ComBean.java b/android/src/main/java/android_serialport_api/ComBean.java
new file mode 100644
index 0000000..48b1f89
--- /dev/null
+++ b/android/src/main/java/android_serialport_api/ComBean.java
@@ -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());
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/java/android_serialport_api/SerialHelper.java b/android/src/main/java/android_serialport_api/SerialHelper.java
new file mode 100644
index 0000000..ba21b94
--- /dev/null
+++ b/android/src/main/java/android_serialport_api/SerialHelper.java
@@ -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);
+}
\ No newline at end of file
diff --git a/android/src/main/java/android_serialport_api/SerialPort.java b/android/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..814d175
--- /dev/null
+++ b/android/src/main/java/android_serialport_api/SerialPort.java
@@ -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();
+ }
+ }
+}
diff --git a/android/src/main/java/android_serialport_api/SerialPortFinder.java b/android/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..b8c377e
--- /dev/null
+++ b/android/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -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 mDevices = null;
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ File[] files = dev.listFiles();
+ int i;
+ for (i=0; i mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ 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 devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while(itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator 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 devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while(itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator 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()]);
+ }
+}
diff --git a/android/src/main/java/com/idworld/noemhost_and/DevComm.java b/android/src/main/java/com/idworld/noemhost_and/DevComm.java
new file mode 100644
index 0000000..c52e13c
--- /dev/null
+++ b/android/src/main/java/com/idworld/noemhost_and/DevComm.java
@@ -0,0 +1,1840 @@
+package com.idworld.noemhost_and;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Log;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import java.io.IOException;
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import android_serialport_api.ComBean;
+import android_serialport_api.SerialHelper;
+
+/**
+ * Created by KMS on 2016/8/23.
+ */
+public class DevComm {
+ public static final int MAX_DATA_LEN = 2048;
+ public static final int IMAGE_DATA_UNIT = 496;
+ public static final int ID_NOTE_SIZE = 64;
+ public static final int MODULE_SN_LEN = 16;
+ public static final int CHAR_SPLIT_UNIT = 496;
+ public static final int CHAR_SPLIT_THR = 1024;
+ public static final int UART_MAX_BUF_SIZE = (500 * 1024);
+ public static final int UART_READ_TIMEOUT = 5000;
+
+ private static final int SCSI_TIMEOUT = 5000; //ms
+ private static final int COMM_SLEEP_TIME = 40; //ms
+
+ private static final int CMD_PACKET_LEN = 26;
+ private static final int RCM_PACKET_LEN = 26;
+ private static final int RCM_DATA_OFFSET = 10;
+
+ /***************************************************************************/
+ /***************************************************************************/
+ private static final int CMD_PREFIX_CODE = 0xAA55;
+ private static final int CMD_DATA_PREFIX_CODE = 0xA55A;
+ private static final int RCM_PREFIX_CODE = 0x55AA;
+ private static final int RCM_DATA_PREFIX_CODE = 0x5AA5;
+
+ /***************************************************************************
+ * System Code (0x0000 ~ 0x001F, 0x0000 : Reserved)
+ ***************************************************************************/
+ private static final short CMD_TEST_CONNECTION = 0x0001;
+ private static final short CMD_SET_PARAM = 0x0002;
+ private static final short CMD_GET_PARAM = 0x0003;
+ private static final short CMD_GET_DEVICE_INFO = 0x0004;
+ private static final short CMD_ENTER_ISPMODE = 0x0005;
+ private static final short CMD_SET_ID_NOTE = 0x0006;
+ private static final short CMD_GET_ID_NOTE = 0x0007;
+ private static final short CMD_SET_MODULE_SN = 0x0008;
+ private static final short CMD_GET_MODULE_SN = 0x0009;
+
+ /***************************************************************************
+ * Sensor Code (0x0020 ~ 0x003F)
+ ***************************************************************************/
+ private static final short CMD_GET_IMAGE = 0x0020;
+ private static final short CMD_FINGER_DETECT = 0x0021;
+ private static final short CMD_UP_IMAGE = 0x0022;
+ private static final short CMD_DOWN_IMAGE = 0x0023;
+ private static final short CMD_SLED_CTRL = 0x0024;
+
+ /***************************************************************************
+ * Template Code (0x0040 ~ 0x005F)
+ ***************************************************************************/
+ private static final short CMD_STORE_CHAR = 0x0040;
+ private static final short CMD_LOAD_CHAR = 0x0041;
+ private static final short CMD_UP_CHAR = 0x0042;
+ private static final short CMD_DOWN_CHAR = 0x0043;
+ private static final short CMD_DEL_CHAR = 0x0044;
+ private static final short CMD_GET_EMPTY_ID = 0x0045;
+ private static final short CMD_GET_STATUS = 0x0046;
+ private static final short CMD_GET_BROKEN_ID = 0x0047;
+ private static final short CMD_GET_ENROLL_COUNT = 0x0048;
+
+ /***************************************************************************
+ * FingerPrint Alagorithm Code (0x0060 ~ 0x007F)
+ ***************************************************************************/
+ private static final short CMD_GENERATE = 0x0060;
+ private static final short CMD_MERGE = 0x0061;
+ private static final short CMD_MATCH = 0x0062;
+ private static final short CMD_SEARCH = 0x0063;
+ private static final short CMD_VERIFY = 0x0064;
+
+ /***************************************************************************
+ * Unknown Command
+ ***************************************************************************/
+ private static final short RCM_INCORRECT_COMMAND = 0x00FF;
+
+ /***************************************************************************
+ * Error Code
+ ***************************************************************************/
+ public static final int ERR_SUCCESS = 0;
+ public static final int ERR_FAIL = 1;
+ public static final int ERR_CONNECTION = 2;
+ public static final int ERR_VERIFY = 0x10;
+ public static final int ERR_IDENTIFY = 0x11;
+ public static final int ERR_TMPL_EMPTY = 0x12;
+ public static final int ERR_TMPL_NOT_EMPTY = 0x13;
+ public static final int ERR_ALL_TMPL_EMPTY = 0x14;
+ public static final int ERR_EMPTY_ID_NOEXIST = 0x15;
+ public static final int ERR_BROKEN_ID_NOEXIST = 0x16;
+ public static final int ERR_INVALID_TMPL_DATA = 0x17;
+ public static final int ERR_DUPLICATION_ID = 0x18;
+ public static final int ERR_BAD_QUALITY = 0x19;
+ public static final int ERR_MERGE_FAIL = 0x1A;
+ public static final int ERR_NOT_AUTHORIZED = 0x1B;
+ public static final int ERR_MEMORY = 0x1C;
+ public static final int ERR_INVALID_TMPL_NO = 0x1D;
+ public static final int ERR_INVALID_PARAM = 0x22;
+ public static final int ERR_GEN_COUNT = 0x25;
+ public static final int ERR_INVALID_BUFFER_ID = 0x26;
+ public static final int ERR_INVALID_OPERATION_MODE = 0x27;
+ public static final int ERR_FP_NOT_DETECTED = 0x28;
+
+ /***************************************************************************
+ * Parameter Index
+ ***************************************************************************/
+ public static final int DP_DEVICE_ID = 0;
+ public static final int DP_SECURITY_LEVEL = 1;
+ public static final int DP_DUP_CHECK = 2;
+ public static final int DP_BAUDRATE = 3;
+ public static final int DP_AUTO_LEARN = 4;
+
+ /***************************************************************************
+ * Device ID, Security Level
+ ***************************************************************************/
+ public static final int MIN_DEVICE_ID = 1;
+ public static final int MAX_DEVICE_ID = 255;
+ public static final int MIN_SECURITY_LEVEL = 1;
+ public static final int MAX_SECURITY_LEVEL = 5;
+
+ public static final int GD_TEMPLATE_NOT_EMPTY = 0x01;
+ public static final int GD_TEMPLATE_EMPTY = 0x00;
+
+ //--------------- For Usb Communication ------------//
+ public int m_nPacketSize;
+ public byte m_bySrcDeviceID = 1, m_byDstDeviceID = 1;
+ public byte[] m_abyPacket = new byte[64 * 1024];
+ public byte[] m_abyPacket2 = new byte[64 * 1024];
+ //--------------------------------------------------//
+
+ private final Context mApplicationContext;
+ private final Activity m_parentAcitivity;
+ private static final int VID = 0x2009;
+ private static final int PID = 0x7638;
+
+ private final UsbController m_usbBase;
+
+ // Serial Port
+ private final DispQueueThread DispQueue;
+ private final SerialControl m_SerialPort;
+
+ // uart variables
+ public byte[] m_pWriteBuffer;
+ public byte[] m_pReadBuffer;
+ public byte[] m_pUARTReadBuf;
+ public int m_nUARTReadPos = 0;
+ public int m_nUARTReceivePos = 0;
+
+ // Connection
+ public byte m_nConnected; // 0 : Not Connected, 1 : ttyUART, 2 : USB
+
+ public DevComm(Activity parentActivity, IUsbConnState usbConnState){
+ m_parentAcitivity = parentActivity;
+ mApplicationContext = parentActivity.getApplicationContext();
+
+ // usb init
+ m_usbBase = new UsbController(parentActivity, usbConnState, VID, PID);
+
+ // init variables
+ m_nConnected = 0;
+ m_nUARTReadPos = 0;
+ m_nUARTReceivePos = 0;
+ m_pWriteBuffer = new byte[DevComm.MAX_DATA_LEN];
+ m_pReadBuffer = new byte[DevComm.MAX_DATA_LEN];
+ m_pUARTReadBuf = new byte[DevComm.UART_MAX_BUF_SIZE];
+
+ // uart thread initialize
+ DispQueue = new DispQueueThread();
+ DispQueue.start();
+ m_SerialPort = new SerialControl();
+ }
+
+ public boolean IsInit(){
+ if (m_nConnected == 0)
+ return false;
+ else if (m_nConnected == 1)
+ return true;
+ else if (m_nConnected == 2)
+ return m_usbBase.IsInit();
+
+ return false;
+ }
+
+ public boolean OpenComm(String p_szDevice, int p_nBaudrate){
+ if (m_nConnected != 0)
+ return false;
+
+ if (p_szDevice == "USB") // usb mode
+ {
+ if (!m_usbBase.IsInit())
+ m_usbBase.init();
+ if (!m_usbBase.IsInit())
+ return false;
+ m_nConnected = 2;
+ }
+ else // tty uart mode
+ {
+ m_SerialPort.setPort(p_szDevice);
+ m_SerialPort.setBaudRate(p_nBaudrate);
+ try
+ {
+ m_SerialPort.open();
+ } catch (SecurityException e) {
+ Toast.makeText(mApplicationContext, "Open ttyUART device failed!", Toast.LENGTH_SHORT).show();
+ return false;
+ } catch (IOException e) {
+ Toast.makeText(mApplicationContext, "Open ttyUART device failed!", Toast.LENGTH_SHORT).show();
+ return false;
+ } catch (InvalidParameterException e) {
+ Toast.makeText(mApplicationContext, "Open ttyUART device failed!", Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ m_nConnected = 1;
+ }
+
+ return true;
+ }
+
+ public boolean CloseComm(){
+ if (m_nConnected == 0) {
+ return false;
+ }
+ else if (m_nConnected == 1) { // tty uart mode
+ m_SerialPort.stopSend();
+ m_SerialPort.close();
+ }
+ else { // usb mode
+ m_usbBase.uninit();
+ }
+
+ m_nConnected = 0;
+ return true;
+ }
+
+ /************************************************************************/
+ /************************************************************************/
+ int Run_TestConnection()
+ {
+ boolean w_bRet;
+
+ InitCmdPacket(CMD_TEST_CONNECTION, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, (short)0);
+
+ w_bRet = Send_Command(CMD_TEST_CONNECTION);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SetParam(int p_nParamIndex, int p_nParamValue)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[5];
+
+ w_abyData[0] = (byte)p_nParamIndex;
+
+ //memcpy(&w_abyData[1], &p_nParamValue, 4);
+ w_abyData[1] = (byte)(p_nParamValue & 0x000000ff);
+ w_abyData[2] = (byte)((p_nParamValue & 0x0000ff00) >> 8);
+ w_abyData[3] = (byte)((p_nParamValue & 0x00ff0000) >> 16);
+ w_abyData[4] = (byte)((p_nParamValue & 0xff000000) >> 24);
+
+ InitCmdPacket(CMD_SET_PARAM, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, (short)5);
+
+ w_bRet = Send_Command(CMD_SET_PARAM);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetParam(int p_nParamIndex, int[] p_pnParamValue)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[1];
+
+ w_abyData[0] = (byte)p_nParamIndex;
+
+ InitCmdPacket(CMD_GET_PARAM, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, (short)1);
+
+ w_bRet = Send_Command(CMD_GET_PARAM);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //memcpy(p_pnParamValue, g_pRcmPacket->m_abyData, 4);
+ p_pnParamValue[0] = ((m_abyPacket[RCM_DATA_OFFSET+3] << 24) & 0xFF000000) |
+ ((m_abyPacket[RCM_DATA_OFFSET+2] << 16) & 0x00FF0000) |
+ ((m_abyPacket[RCM_DATA_OFFSET+1] << 8) & 0x0000FF00) |
+ (m_abyPacket[RCM_DATA_OFFSET] & 0x000000FF);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetDeviceInfo(String[] p_szDevInfo)
+ {
+ int w_nDevInfoLen;
+ boolean w_bRet;
+ String w_strTmp;
+ byte[] w_szDevInfo;
+
+ InitCmdPacket(CMD_GET_DEVICE_INFO, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ w_bRet = Send_Command(CMD_GET_DEVICE_INFO);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_nDevInfoLen = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ w_bRet = Receive_DataPacket(CMD_GET_DEVICE_INFO);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if ( GetRetCode() != ERR_SUCCESS )
+ return GetRetCode();
+
+ //memcpy(p_szDevInfo, g_pRcmPacket->m_abyData, w_wDevInfoLen);
+ w_szDevInfo = new byte[w_nDevInfoLen];
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, w_szDevInfo, 0, w_nDevInfoLen);
+ w_strTmp = new String(w_szDevInfo);
+ p_szDevInfo[0] = w_strTmp;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SetIDNote(int p_nTmplNo, String p_pstrNote)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[ID_NOTE_SIZE+2];
+ byte[] w_abyData2 = new byte[2];
+ byte[] w_abyNoteBuf = p_pstrNote.getBytes();
+
+ //. Assemble command packet
+ w_abyData2[0] = LOBYTE((short)(ID_NOTE_SIZE + 2));
+ w_abyData2[1] = HIBYTE((short)(ID_NOTE_SIZE + 2));
+
+ InitCmdPacket(CMD_SET_ID_NOTE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData2, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_SET_ID_NOTE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if( GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //. Assemble data packet
+ memset(w_abyData, (byte)0, ID_NOTE_SIZE+2);
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ System.arraycopy(w_abyNoteBuf, 0, w_abyData, 2, w_abyNoteBuf.length);
+
+ InitCmdDataPacket(CMD_SET_ID_NOTE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, ID_NOTE_SIZE+2);
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_SET_ID_NOTE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetIDNote(int p_nTmplNo, String[] p_pstrNote)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[2];
+ String w_strTmp;
+
+ //. Assemble command packet
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ InitCmdPacket(CMD_GET_ID_NOTE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_GET_ID_NOTE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_bRet = Receive_DataPacket(CMD_GET_ID_NOTE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //memset(m_abyPacket2, (byte)0, ID_NOTE_SIZE+1);
+ memset(m_abyPacket2, (byte)0, 512);
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, m_abyPacket2, 0, ID_NOTE_SIZE);
+
+ w_strTmp = new String(m_abyPacket2);
+ p_pstrNote[0] = w_strTmp;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SetModuleSN(String p_pstrModuleSN)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = p_pstrModuleSN.getBytes();
+ byte[] w_abyModuleSN = new byte[MODULE_SN_LEN];
+ byte[] w_abyData2 = new byte[2];
+
+ memset(w_abyModuleSN, (byte)0, MODULE_SN_LEN);
+ System.arraycopy(w_abyData, 0, w_abyModuleSN, 0, w_abyData.length);
+
+ //. Assemble command packet
+ w_abyData2[0] = LOBYTE((short)(MODULE_SN_LEN));
+ w_abyData2[1] = HIBYTE((short)(MODULE_SN_LEN));
+
+ InitCmdPacket(CMD_SET_MODULE_SN, m_bySrcDeviceID, m_byDstDeviceID, w_abyData2, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_SET_MODULE_SN);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if( GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //. Assemble data packet
+ InitCmdDataPacket(CMD_SET_MODULE_SN, m_bySrcDeviceID, m_byDstDeviceID, w_abyModuleSN, MODULE_SN_LEN);
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_SET_MODULE_SN);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetModuleSN(String[] p_pstrModuleSN)
+ {
+ boolean w_bRet = false;
+ String w_strTmp;
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_MODULE_SN, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_GET_MODULE_SN);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_bRet = Receive_DataPacket(CMD_GET_MODULE_SN);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //memset(m_abyPacket2, (byte)0, MODULE_SN_LEN+1);
+ memset(m_abyPacket2, (byte)0, 512);
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, m_abyPacket2, 0, MODULE_SN_LEN);
+
+ w_strTmp = new String(m_abyPacket2);
+ p_pstrModuleSN[0] = w_strTmp;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetImage()
+ {
+ boolean w_bRet;
+
+ InitCmdPacket(CMD_GET_IMAGE, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ w_bRet = Send_Command(CMD_GET_IMAGE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_FingerDetect(int[] p_pnDetectResult)
+ {
+ boolean w_bRet;
+
+ InitCmdPacket(CMD_FINGER_DETECT, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ w_bRet = Send_Command(CMD_FINGER_DETECT);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnDetectResult[0] = m_abyPacket[RCM_DATA_OFFSET];
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_UpImage(int p_nType, byte[] p_pFpData, int[] p_pnImgWidth, int[] p_pnImgHeight)
+ {
+ int i, n, r, w, h, size;
+ boolean w_bRet;
+ byte[] w_abyData = new byte[1];
+
+ w_abyData[0] = (byte)p_nType;
+
+ InitCmdPacket(CMD_UP_IMAGE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 1);
+
+ w_bRet = Send_Command(CMD_UP_IMAGE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+ h = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET+2], m_abyPacket[RCM_DATA_OFFSET+3]);
+
+ size = w * h;
+ n = size / IMAGE_DATA_UNIT;
+ r = size % IMAGE_DATA_UNIT;
+
+ if (m_nConnected == 1) {
+ for (i=0; i 0)
+ {
+ w_bRet = Receive_DataPacket(CMD_UP_IMAGE);
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET + 2, p_pFpData, i * IMAGE_DATA_UNIT, r);
+ }
+ }
+ else if (m_nConnected == 2) {
+ w_bRet = USB_ReceiveImage(p_pFpData, w * h);
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ }
+ else {
+ return ERR_CONNECTION;
+ }
+
+ p_pnImgWidth[0] = w;
+ p_pnImgHeight[0] = h;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_DownImage(byte[] p_pData, int p_nWidth, int p_nHeight)
+ {
+ /*
+ int i, n, r, w, h;
+ boolean w_bRet;
+ BYTE w_abyData[840];
+
+ w = p_nWidth;
+ h = p_nHeight;
+
+ w_abyData[0] = LOBYTE(p_nWidth);
+ w_abyData[1] = HIBYTE(p_nWidth);
+ w_abyData[2] = LOBYTE(p_nHeight);
+ w_abyData[3] = HIBYTE(p_nHeight);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_DOWN_IMAGE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ Send_Command(CMD_DOWN_IMAGE, w_bRet, m_bySrcDeviceID, m_byDstDeviceID);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ n = (w*h)/DOWN_IMAGE_DATA_UINT;
+ r = (w*h)%DOWN_IMAGE_DATA_UINT;
+
+ w_bRet = USB_DownImage(m_hUsbHandle, p_pData, p_nWidth*p_nHeight);
+
+ if(w_bRet == false)
+ return ERR_CONNECTION;
+ */
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SLEDControl(int p_nState)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[2];
+
+ w_abyData[0] = LOBYTE((short)p_nState);
+ w_abyData[1] = HIBYTE((short)p_nState);
+
+ InitCmdPacket(CMD_SLED_CTRL, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ w_bRet = Send_Command(CMD_SLED_CTRL);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_StoreChar(int p_nTmplNo, int p_nRamBufferID, int[] p_pnDupTmplNo)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID);
+
+ InitCmdPacket(CMD_STORE_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_STORE_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ {
+ if (GetRetCode() == ERR_DUPLICATION_ID)
+ p_pnDupTmplNo[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ return GetRetCode();
+ }
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_LoadChar(int p_nTmplNo, int p_nRamBufferID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID);
+
+ InitCmdPacket(CMD_LOAD_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_LOAD_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_UpChar(int p_nRamBufferID, byte[] p_pbyTemplate, int[] p_nSize)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[2];
+ short w_nTemplateSize = 0;
+ int w_nRemainSize = 0;
+
+ //. Assemble command packet
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ InitCmdPacket(CMD_UP_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_UP_CHAR);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_nTemplateSize = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ if (w_nTemplateSize < CHAR_SPLIT_THR) {
+ w_bRet = Receive_DataPacket(CMD_UP_CHAR);
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+ //memcpy(p_pbyTemplate, &g_pRcmPacket->m_abyData[0], GD_RECORD_SIZE);
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, p_pbyTemplate, 0, w_nTemplateSize);
+ }
+ else {
+ w_nRemainSize = w_nTemplateSize;
+ while (w_nRemainSize > 0) {
+ w_bRet = Receive_DataPacket(CMD_UP_CHAR);
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+ if (w_nRemainSize > CHAR_SPLIT_UNIT) {
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, p_pbyTemplate, w_nTemplateSize - w_nRemainSize, CHAR_SPLIT_UNIT);
+ w_nRemainSize -= CHAR_SPLIT_UNIT;
+ }
+ else {
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, p_pbyTemplate, w_nTemplateSize - w_nRemainSize, w_nRemainSize);
+ w_nRemainSize -= 0;
+ }
+ }
+ }
+
+ p_nSize[0] = w_nTemplateSize;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_DownChar(int p_nRamBufferID, byte[] p_pbyTemplate, int p_nSize)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[MAX_DATA_LEN+2];
+ byte[] w_abyData2 = new byte[2];
+ int w_nRemainSize = 0;
+ int i;
+
+ //. Assemble command packet
+ if (p_nSize < CHAR_SPLIT_THR) {
+ w_abyData2[0] = LOBYTE((short)(p_nSize + 2));
+ w_abyData2[1] = HIBYTE((short)(p_nSize + 2));
+ }
+ else {
+ w_abyData2[0] = LOBYTE((short)(p_nSize + 4));
+ w_abyData2[1] = HIBYTE((short)(p_nSize + 4));
+ }
+
+ InitCmdPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData2, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_DOWN_CHAR);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if( GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ SystemClock.sleep(10);
+
+ //. Assemble data packet
+ if (p_nSize < CHAR_SPLIT_THR) {
+ w_abyData[0] = LOBYTE((short) p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short) p_nRamBufferID);
+ //memcpy(&w_abyData[2], p_pbyTemplate, GD_RECORD_SIZE);
+ System.arraycopy(p_pbyTemplate, 0, w_abyData, 2, p_nSize);
+
+ InitCmdDataPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, p_nSize + 2);
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_DOWN_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ }
+ else {
+ w_nRemainSize = p_nSize;
+ i = 0;
+ while (w_nRemainSize > 0) {
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ w_abyData[2] = LOBYTE((short)i);
+ w_abyData[3] = HIBYTE((short)i);
+ if (w_nRemainSize > CHAR_SPLIT_UNIT) {
+ System.arraycopy(p_pbyTemplate, i * CHAR_SPLIT_UNIT, w_abyData, 4, CHAR_SPLIT_UNIT);
+ InitCmdDataPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, CHAR_SPLIT_UNIT + 4);
+ w_nRemainSize -= CHAR_SPLIT_UNIT;
+ }
+ else {
+ System.arraycopy(p_pbyTemplate, i * CHAR_SPLIT_UNIT, w_abyData, 4, w_nRemainSize);
+ InitCmdDataPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, w_nRemainSize + 4);
+ w_nRemainSize -= 0;
+ }
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_DOWN_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ i++;
+ }
+ }
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_DelChar(int p_nSTmplNo, int p_nETmplNo)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_DEL_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_DEL_CHAR);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetEmptyID(int p_nSTmplNo, int p_nETmplNo, int[] p_pnEmptyID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_EMPTY_ID, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_GET_EMPTY_ID);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if ( GetRetCode() != ERR_SUCCESS )
+ return GetRetCode();
+
+ p_pnEmptyID[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetStatus(int p_nTmplNo, int[] p_pnStatus)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[2];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+
+ InitCmdPacket(CMD_GET_STATUS, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ w_bRet = Send_Command(CMD_GET_STATUS);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if ( GetRetCode() != ERR_SUCCESS )
+ return GetRetCode();
+
+ p_pnStatus[0] = m_abyPacket[RCM_DATA_OFFSET];
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetBrokenID(int p_nSTmplNo, int p_nETmplNo, int[] p_pnCount, int[] p_pnFirstID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_BROKEN_ID, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_GET_BROKEN_ID);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnCount[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+ p_pnFirstID[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET+2], m_abyPacket[RCM_DATA_OFFSET+3]);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetEnrollCount(int p_nSTmplNo, int p_nETmplNo, int[] p_pnEnrollCount)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_ENROLL_COUNT, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_GET_ENROLL_COUNT);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if(GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnEnrollCount[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Generate(int p_nRamBufferID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[2];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+
+ InitCmdPacket(CMD_GENERATE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_GENERATE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Merge(int p_nRamBufferID, int p_nMergeCount)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[3];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ w_abyData[2] = (byte)p_nMergeCount;
+
+ InitCmdPacket(CMD_MERGE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 3);
+
+ w_bRet = Send_Command(CMD_MERGE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Match(int p_nRamBufferID0, int p_nRamBufferID1)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID0);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID0);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID1);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID1);
+
+ InitCmdPacket(CMD_MATCH, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_MATCH);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Search(int p_nRamBufferID, int p_nStartID, int p_nSearchCount, int[] p_pnTmplNo, int[] p_pnLearnResult)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[6];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ w_abyData[2] = LOBYTE((short)p_nStartID);
+ w_abyData[3] = HIBYTE((short)p_nStartID);
+ w_abyData[4] = LOBYTE((short)p_nSearchCount);
+ w_abyData[5] = HIBYTE((short)p_nSearchCount);
+
+ InitCmdPacket(CMD_SEARCH, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 6);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_SEARCH);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if(GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnTmplNo[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+ p_pnLearnResult[0] = m_abyPacket[RCM_DATA_OFFSET+2];
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Verify(int p_nTmplNo, int p_nRamBufferID, int[] p_pnLearnResult)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_VERIFY, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_VERIFY);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ p_pnLearnResult[0] = m_abyPacket[RCM_DATA_OFFSET+2];
+
+ return GetRetCode();
+ }
+
+ public boolean GetDeviceInformation(String[] deviceInfo)
+ {
+ int[] w_nRecvLen = new int[1];
+ byte[] w_abyPCCmd = new byte[6];
+ byte[] w_abyData = new byte[32];
+
+ String w_strTmp;
+ boolean w_bRet;
+
+ Arrays.fill(w_abyPCCmd, (byte) 0);
+
+ w_abyPCCmd[2] = 0x04;
+
+ w_bRet = SendPackage(w_abyPCCmd, w_abyData);
+
+ //Toast.makeText(mApplicationContext, "GetDeviceInformation, SendPackage ret = " + w_bRet, Toast.LENGTH_SHORT).show();
+
+ if (!w_bRet)
+ {
+ return false;
+ }
+
+ w_bRet = RecvPackage(w_abyData, w_nRecvLen);
+
+ //Toast.makeText(mApplicationContext, "GetDeviceInformation, RecvPackage : " + w_bRet, Toast.LENGTH_SHORT).show();
+
+ if (!w_bRet)
+ {
+ return false;
+ }
+
+ w_strTmp = new String(w_abyData);
+ deviceInfo[0] = w_strTmp;
+
+ //Toast.makeText(mApplicationContext, "GetDeviceInformation, Recv Data : " + w_strTmp, Toast.LENGTH_SHORT).show();
+
+ return true;
+ }
+
+
+
+ private boolean SendPackage(byte[] pPCCmd, byte[] pData)
+ {
+ int nDataLen;
+
+ pPCCmd[0] = (byte)0xEF;
+ pPCCmd[1] = 0x01;
+
+ nDataLen = ((pPCCmd[5] << 8) & 0x0000FF00) | (pPCCmd[4] & 0x000000FF);
+
+ return m_usbBase.UsbSCSIWrite(pPCCmd, 6, pData, nDataLen, 5000);
+ }
+
+ private boolean RecvPackage(byte[] pData, int[] pLevRen)
+ {
+ int w_nLen;
+ byte[] w_abyPCCmd = new byte[6];
+ byte[] w_abyRespond = new byte[4];
+ boolean w_bRet;
+
+ w_abyPCCmd[0] = (byte)0xEF;
+ w_abyPCCmd[1] = 0x02;
+ w_abyPCCmd[2] = 0;
+ w_abyPCCmd[3] = 0;
+ w_abyPCCmd[4] = 0;
+ w_abyPCCmd[5] = 0;
+
+ // receive status
+ w_bRet = m_usbBase.UsbSCSIRead(w_abyPCCmd, 6, w_abyRespond, 4, 5000);
+
+ if (!w_bRet)
+ return false;
+
+ // receive data
+ //w_nLen = (int)((w_abyRespond[3] << 8) | w_abyRespond[2]);
+ w_nLen = ((w_abyRespond[3] << 8) & 0x0000FF00) | (w_abyRespond[2] & 0x000000FF);
+
+ if (w_nLen > 0)
+ {
+ //w_nTime = SystemClock.elapsedRealtime();
+
+ w_abyPCCmd[1] = 0x03;
+ w_bRet = m_usbBase.UsbSCSIRead(w_abyPCCmd, 6, pData, w_nLen, 5000);
+
+ //w_nTime = SystemClock.elapsedRealtime() - w_nTime;
+
+ if (!w_bRet)
+ return false;
+
+ pLevRen[0] = w_nLen;
+ }
+
+ return true;
+ }
+
+ /***************************************************************************
+ * Get Return Code
+ ***************************************************************************/
+ private short GetRetCode()
+ {
+ return (short)(((m_abyPacket[9] << 8) & 0x0000FF00) | (m_abyPacket[8] & 0x000000FF));
+ }
+
+ /***************************************************************************
+ * Get Data Length
+ ***************************************************************************/
+ private short GetDataLen()
+ {
+ return (short)(((m_abyPacket[7] << 8) & 0x0000FF00) | (m_abyPacket[6] & 0x000000FF));
+ }
+
+ /***************************************************************************
+ * Set Data Length
+ ***************************************************************************/
+ private void SetDataLen(short p_wDataLen)
+ {
+ m_abyPacket[6] = (byte)(p_wDataLen & 0xFF);
+ m_abyPacket[7] = (byte)(((p_wDataLen & 0xFF00) >> 8) & 0xFF);
+ }
+
+ /***************************************************************************
+ * Set Command Data
+ ***************************************************************************/
+ private void SetCmdData(short p_wData, boolean p_bFirst)
+ {
+ if (p_bFirst)
+ {
+ m_abyPacket[8] = (byte)(p_wData & 0xFF);
+ m_abyPacket[9] = (byte)(((p_wData & 0xFF00) >> 8) & 0xFF);
+ }
+ else
+ {
+ m_abyPacket[10] = (byte)(p_wData & 0xFF);
+ m_abyPacket[11] = (byte)(((p_wData & 0xFF00) >> 8) & 0xFF);
+ }
+ }
+
+ /***************************************************************************
+ * Get Command Data
+ ***************************************************************************/
+ private short GetCmdData(boolean p_bFirst)
+ {
+ if (p_bFirst)
+ {
+ return (short)(((m_abyPacket[9] << 8) & 0x0000FF00) | (m_abyPacket[8] & 0x000000FF));
+ }
+ else
+ {
+ return (short)(((m_abyPacket[11] << 8) & 0x0000FF00) | (m_abyPacket[10] & 0x000000FF));
+ }
+ }
+
+ /***************************************************************************
+ * Get 2bytes packet checksum(pDataPkt[0] + pDataPkt[1] + ....)
+ ***************************************************************************/
+ private short CalcChkSumOfPkt(byte[] pDataPkt, int nSize)
+ {
+ int i, nChkSum = 0;
+
+ for(i=0;im_wPrefix = CMD_PREFIX_CODE;
+ m_abyPacket[0] = (byte)(CMD_PREFIX_CODE & 0xFF);
+ m_abyPacket[1] = (byte)((CMD_PREFIX_CODE >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_bySrcDeviceID = p_bySrcDeviceID;
+ m_abyPacket[2] = bySrcDeviceID;
+
+ //g_pCmdPacket->m_byDstDeviceID = p_byDstDeviceID;
+ m_abyPacket[3] = byDstDeviceID;
+
+ //g_pCmdPacket->m_wCMDCode = p_wCMDCode;
+ m_abyPacket[4] = (byte)(wCMDCode & 0xFF);
+ m_abyPacket[5] = (byte)((wCMDCode >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_wDataLen = p_wDataLen;
+ m_abyPacket[6] = (byte)(nDataLen & 0xFF);
+ m_abyPacket[7] = (byte)((nDataLen >> 8) & 0xFF);
+
+ if (nDataLen > 0)
+ //memcpy(g_pCmdPacket->m_abyData, p_pbyData, wDataLen);
+ System.arraycopy(pbyData, 0, m_abyPacket, 8, nDataLen);
+
+ w_wCheckSum = CalcChkSumOfPkt(m_abyPacket, CMD_PACKET_LEN-2);
+
+ //g_pCmdPacket->m_wCheckSum = w_wCheckSum;
+ m_abyPacket[24] = (byte)(w_wCheckSum & 0xFF);
+ m_abyPacket[25] = (byte)((w_wCheckSum >> 8) & 0xFF);
+
+ m_nPacketSize = CMD_PACKET_LEN;
+ }
+ /***************************************************************************
+ * Make Data Packet
+ ***************************************************************************/
+ void InitCmdDataPacket(short wCMDCode, byte bySrcDeviceID, byte byDstDeviceID, byte[] pbyData, int nDataLen)
+ {
+ short w_wCheckSum;
+
+ //g_pCmdPacket->m_wPrefix = CMD_DATA_PREFIX_CODE;
+ m_abyPacket[0] = (byte)(CMD_DATA_PREFIX_CODE & 0xFF);
+ m_abyPacket[1] = (byte)((CMD_DATA_PREFIX_CODE >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_bySrcDeviceID = p_bySrcDeviceID;
+ m_abyPacket[2] = bySrcDeviceID;
+
+ //g_pCmdPacket->m_byDstDeviceID = p_byDstDeviceID;
+ m_abyPacket[3] = byDstDeviceID;
+
+ //g_pCmdPacket->m_wCMDCode = p_wCMDCode;
+ m_abyPacket[4] = (byte)(wCMDCode & 0xFF);
+ m_abyPacket[5] = (byte)((wCMDCode >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_wDataLen = p_wDataLen;
+ m_abyPacket[6] = (byte)(nDataLen & 0xFF);
+ m_abyPacket[7] = (byte)((nDataLen >> 8) & 0xFF);
+
+ //memcpy(&g_pCmdPacket->m_abyData[0], p_pbyData, p_wDataLen);
+ System.arraycopy(pbyData, 0, m_abyPacket, 8, nDataLen);
+
+ //. Set checksum
+ w_wCheckSum = CalcChkSumOfPkt(m_abyPacket, nDataLen + 8);
+
+ m_abyPacket[nDataLen+8] = (byte)(w_wCheckSum & 0xFF);
+ m_abyPacket[nDataLen+9] = (byte)((w_wCheckSum >> 8) & 0xFF);
+
+ m_nPacketSize = nDataLen + 10;
+ }
+ /***************************************************************************
+ * Check Packet
+ ***************************************************************************/
+ boolean CheckReceive( byte[] pbyPacket, int nPacketLen, short wPrefix, short wCMDCode )
+ {
+ short w_wCalcCheckSum, w_wCheckSum, w_wTmp;
+
+ //. Check prefix code
+ w_wTmp = (short)(((pbyPacket[1] << 8) & 0x0000FF00) | (pbyPacket[0] & 0x000000FF));
+
+ if (wPrefix != w_wTmp)
+ {
+ return false;
+ }
+
+ //. Check checksum
+ w_wCheckSum = (short)(((pbyPacket[nPacketLen-1] << 8) & 0x0000FF00) | (pbyPacket[nPacketLen-2] & 0x000000FF));
+
+ w_wCalcCheckSum = CalcChkSumOfPkt(pbyPacket, nPacketLen-2);
+
+ if (w_wCheckSum != w_wCalcCheckSum)
+ {
+ return false;
+ }
+
+ //. Check Command Code
+ w_wTmp = (short)(((pbyPacket[5] << 8) & 0x0000FF00) | (pbyPacket[4] & 0x000000FF));
+ return wCMDCode == w_wTmp;
+ }
+
+ //--------------------------- Send, Receive Communication Packet Functions ---------------------//
+ public boolean Send_Command(short p_wCmd)
+ {
+ if (m_nConnected == 1)
+ return UART_SendCommand(p_wCmd);
+ else if (m_nConnected == 2)
+ return USB_SendPacket(p_wCmd);
+ else
+ return false;
+ }
+
+ public boolean Send_DataPacket(short p_wCmd)
+ {
+ if (m_nConnected == 1)
+ return UART_SendDataPacket(p_wCmd);
+ else if (m_nConnected == 2)
+ return USB_SendDataPacket(p_wCmd);
+ else
+ return false;
+ }
+
+ public boolean Receive_DataPacket(short p_wCmd)
+ {
+ if (m_nConnected == 1)
+ return UART_ReceiveDataPacket(p_wCmd);
+ else if (m_nConnected == 2)
+ return USB_ReceiveDataPacket(p_wCmd);
+ else
+ return false;
+ }
+
+ //-------------------------------- USB Communication Functions --------------------------------//
+ private boolean USB_SendPacket(short wCMD)
+ {
+ byte[] btCDB = new byte[8];
+ boolean w_bRet;
+
+ Arrays.fill(btCDB, (byte)0);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x11; btCDB[4] = (byte)m_nPacketSize;
+
+ w_bRet = m_usbBase.UsbSCSIWrite(btCDB, 8, m_abyPacket, m_nPacketSize, SCSI_TIMEOUT);
+
+ if (!w_bRet)
+ {
+ return false;
+ }
+
+ return USB_ReceiveAck( wCMD );
+ }
+
+ private boolean USB_ReceiveAck(short wCMD)
+ {
+ int c, w_nLen, w_nReadCount = 0;
+ byte[] btCDB = new byte[8];
+ byte[] w_abyWaitPacket = new byte[CMD_PACKET_LEN];
+
+ Arrays.fill(btCDB, (byte)0);
+
+ //w_nReadCount = GetReadWaitTime(p_byCMD);
+
+ c = 0;
+ Arrays.fill(w_abyWaitPacket, (byte)0xAF);
+
+ do
+ {
+ Arrays.fill(m_abyPacket, (byte)0);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = (byte)0x12;
+
+ w_nLen = RCM_PACKET_LEN;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, m_abyPacket, w_nLen, SCSI_TIMEOUT))
+ {
+ return false;
+ }
+
+ SystemClock.sleep(COMM_SLEEP_TIME);
+
+ c++;
+
+ //if ( c > w_nReadCount)
+ //{
+ // return false;
+ //}
+ } while (memcmp(m_abyPacket, w_abyWaitPacket, CMD_PACKET_LEN));
+
+ m_nPacketSize = w_nLen;
+
+ return CheckReceive(m_abyPacket, m_nPacketSize, (short) RCM_PREFIX_CODE, wCMD);
+ }
+
+ boolean USB_ReceiveDataAck(short wCMD)
+ {
+ byte[] btCDB = new byte[8];
+ byte[] w_WaitPacket = new byte[10];
+ int w_nLen;
+
+ memset(btCDB, (byte)0, 8);
+ memset(w_WaitPacket, (byte)0xAF, 10);
+
+ do
+ {
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x15;
+ w_nLen = 8;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, m_abyPacket, w_nLen, SCSI_TIMEOUT))
+ {
+ return false;
+ }
+
+ SystemClock.sleep(COMM_SLEEP_TIME);
+
+ }while(memcmp(m_abyPacket, w_WaitPacket, 8));
+
+ //w_nLen = g_pRcmPacket->m_wDataLen + 2;
+ w_nLen = (short)(((m_abyPacket[7] << 8) & 0x0000FF00) | (m_abyPacket[6] & 0x000000FF)) + 2;
+
+ if (!USB_ReceiveRawData(m_abyPacket2, w_nLen))
+ {
+ return false;
+ }
+
+ System.arraycopy(m_abyPacket2, 0, m_abyPacket, 8, w_nLen);
+
+ m_nPacketSize = 8 + w_nLen;
+
+ return CheckReceive(m_abyPacket, m_nPacketSize, (short) RCM_DATA_PREFIX_CODE, wCMD);
+ }
+
+ boolean USB_SendDataPacket(short wCMD)
+ {
+ byte[] btCDB = new byte[8];
+
+ memset(btCDB, (byte)0, 8);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x13;
+
+ btCDB[4] = (byte)(m_nPacketSize & 0xFF);
+ btCDB[5] = (byte)((m_nPacketSize >> 8) & 0xFF);
+
+ if (!m_usbBase.UsbSCSIWrite(btCDB, 8, m_abyPacket, m_nPacketSize, SCSI_TIMEOUT ) )
+ return false;
+
+ return USB_ReceiveDataAck(wCMD);
+ }
+
+ boolean USB_ReceiveDataPacket(short wCMD)
+ {
+ return USB_ReceiveDataAck(wCMD);
+ }
+
+ boolean USB_ReceiveRawData(byte[] pBuffer, int nDataLen)
+ {
+ byte[] btCDB = new byte[8];
+
+ memset(btCDB, (byte)0, 8);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x14;
+
+ return m_usbBase.UsbSCSIRead(btCDB, 8, pBuffer, nDataLen, SCSI_TIMEOUT);
+ }
+
+ boolean USB_ReceiveImage(byte[] p_pBuffer, int nDataLen )
+ {
+ byte[] btCDB = new byte[8];
+ byte[] w_WaitPacket = new byte[8];
+
+ memset( btCDB, (byte)0, 8 );
+ memset( w_WaitPacket, (byte)0xAF, 8 );
+
+ if (nDataLen < 1024*64)
+ {
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x16;
+
+ return m_usbBase.UsbSCSIRead(btCDB, 8, p_pBuffer, nDataLen, SCSI_TIMEOUT);
+ }
+ else if (nDataLen == 256*288)
+ {
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x16; btCDB[2] = 0x00;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, p_pBuffer, nDataLen/2, SCSI_TIMEOUT))
+ return false;
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x16; btCDB[2] = 0x01;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, m_abyPacket2, nDataLen/2, SCSI_TIMEOUT ))
+ return false;
+
+ System.arraycopy(m_abyPacket2, 0, p_pBuffer, nDataLen/2, nDataLen/2);
+ }
+
+ return true;
+ }
+
+ //-------------------------------- UART Communication Functions --------------------------------//
+ public boolean UART_SendCommand(short p_wCmd)
+ {
+ int w_nResult = 0;
+ boolean w_bRet = false;
+ int w_nRetry = 0;
+
+ if (m_nConnected == 1)
+ {
+ byte[] w_pData = new byte[m_nPacketSize];
+ System.arraycopy(m_abyPacket, 0, w_pData, 0, m_nPacketSize);
+ m_SerialPort.send(w_pData, m_nPacketSize);
+ }
+
+// do {
+// w_bRet = UART_ReceiveAck(p_wCmd);
+// if (m_nUARTReceivePos == m_nUARTReadPos) {
+// if (w_bRet == true) {
+// break;
+// }
+// else {
+// if (w_nRetry > 0)
+// break;
+// else
+// w_nRetry += 1;
+// }
+// }
+// } while (w_bRet == false);
+ w_bRet = UART_ReceiveAck(p_wCmd);
+ return w_bRet;
+ }
+
+ public boolean UART_ReceiveAck(short p_wCmd)
+ {
+ if (!UART_ReadDataN(m_abyPacket, 0, CMD_PACKET_LEN))
+ return false;
+
+ return CheckReceive(m_abyPacket, CMD_PACKET_LEN, (short) RCM_PREFIX_CODE, p_wCmd);
+ }
+
+ public boolean UART_ReceiveDataAck(short p_wCmd)
+ {
+ if (!UART_ReadDataN(m_abyPacket, 0, 8))
+ return false;
+
+ if (!UART_ReadDataN(m_abyPacket, 8, GetDataLen() + 2))
+ return false;
+
+ return CheckReceive(m_abyPacket, GetDataLen() + 10, (short)RCM_DATA_PREFIX_CODE, p_wCmd);
+ }
+
+ public boolean UART_SendDataPacket(short p_wCmd)
+ {
+ int w_nSendCnt = 0;
+
+ if (m_nConnected == 1)
+ {
+ byte[] w_pData = new byte[m_nPacketSize];
+ System.arraycopy(m_abyPacket, 0, w_pData, 0, m_nPacketSize);
+ m_SerialPort.send(w_pData, m_nPacketSize);
+ }
+
+ return UART_ReceiveDataAck(p_wCmd);
+ }
+ /***************************************************************************/
+ /***************************************************************************/
+ public boolean UART_ReceiveDataPacket(short p_wCmd)
+ {
+ return UART_ReceiveDataAck(p_wCmd);
+ }
+ /***************************************************************************/
+ /***************************************************************************/
+ public boolean UART_ReceiveData(short p_wCmd, int p_nDataLen, byte[] p_pBuffer)
+ {
+ int w_nReceivedCnt;
+ int w_wPacketDataLen = 0;
+
+ for (w_nReceivedCnt = 0; w_nReceivedCnt < p_nDataLen; w_nReceivedCnt += w_wPacketDataLen)
+ {
+ w_wPacketDataLen = p_nDataLen - w_nReceivedCnt;
+ if (w_wPacketDataLen > MAX_DATA_LEN) w_wPacketDataLen = MAX_DATA_LEN;
+ if (!UART_ReceiveDataPacket(p_wCmd))
+ return false;
+ System.arraycopy(m_abyPacket, 8, p_pBuffer, w_nReceivedCnt, GetDataLen() + 4);
+ }
+ return true;
+ }
+ /***************************************************************************/
+ /***************************************************************************/
+ boolean UART_ReadDataN(byte[] p_pData, int p_nStart, int p_nLen)
+ {
+ int w_nTotalRecvLen;
+ int w_nTmpLen;
+ int w_nStartPos = 0;
+ int w_nHeader;
+ boolean w_bFirstPacket = true;
+ int w_nReceivedLen = 0;
+
+ int wm_nUARTReceivePos = 0;
+ int wm_nUARTReadPos = 0;
+
+ long w_nEllapsedTime = 0;
+
+ w_nTotalRecvLen = 0;
+ w_nEllapsedTime = SystemClock.uptimeMillis();
+
+ while (w_nTotalRecvLen < p_nLen)
+ {
+ wm_nUARTReceivePos = m_nUARTReceivePos;
+ wm_nUARTReadPos = m_nUARTReadPos;
+
+ if ((wm_nUARTReceivePos <= wm_nUARTReadPos) && (wm_nUARTReadPos - wm_nUARTReceivePos < DevComm.MAX_DATA_LEN)) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ if (SystemClock.uptimeMillis() - w_nEllapsedTime > UART_READ_TIMEOUT)
+ return false;
+ continue;
+ }
+
+ if (wm_nUARTReceivePos < wm_nUARTReadPos) {
+ w_nReceivedLen = DevComm.UART_MAX_BUF_SIZE + wm_nUARTReceivePos - wm_nUARTReadPos;
+ System.arraycopy(m_pUARTReadBuf, wm_nUARTReadPos, m_abyPacket2, 0, DevComm.UART_MAX_BUF_SIZE - wm_nUARTReadPos);
+ System.arraycopy(m_pUARTReadBuf, 0, m_abyPacket2, DevComm.UART_MAX_BUF_SIZE - wm_nUARTReadPos, wm_nUARTReceivePos);
+ }
+ else {
+ w_nReceivedLen = wm_nUARTReceivePos - wm_nUARTReadPos;
+ System.arraycopy(m_pUARTReadBuf, wm_nUARTReadPos, m_abyPacket2, 0, w_nReceivedLen);
+ }
+
+ if (w_bFirstPacket && (p_nLen == 6) && (p_nStart == 0)) {
+ for (w_nStartPos = 0; w_nStartPos < w_nReceivedLen; w_nStartPos++) {
+ w_nHeader = MAKEWORD(m_abyPacket2[w_nStartPos], m_abyPacket2[w_nStartPos + 1]);
+ if ((w_nHeader == CMD_PREFIX_CODE) || (w_nHeader == RCM_PREFIX_CODE) ||
+ (w_nHeader == CMD_DATA_PREFIX_CODE) || (w_nHeader == RCM_DATA_PREFIX_CODE))
+ break;
+ }
+
+ m_nUARTReadPos += w_nStartPos;
+ w_nReceivedLen -= w_nStartPos;
+
+ w_bFirstPacket = false;
+ }
+ else {
+ w_nStartPos = 0;
+ }
+
+ if (p_nLen - w_nTotalRecvLen < w_nReceivedLen) {
+ w_nTmpLen = p_nLen - w_nTotalRecvLen;
+ }
+ else {
+ w_nTmpLen = w_nReceivedLen;
+ }
+
+ System.arraycopy(m_abyPacket2, w_nStartPos, p_pData, p_nStart + w_nTotalRecvLen, w_nTmpLen);
+ w_nTotalRecvLen += w_nTmpLen;
+ m_nUARTReadPos += w_nTmpLen;
+
+ if (m_nUARTReadPos >= DevComm.UART_MAX_BUF_SIZE)
+ m_nUARTReadPos -= DevComm.UART_MAX_BUF_SIZE;
+
+ w_nEllapsedTime = SystemClock.uptimeMillis();
+ }
+
+ return true;
+ }
+
+ private boolean memcmp(byte[] p1, byte[] p2, int nLen)
+ {
+ int i;
+
+ for (i=0; i> 8) & 0xFF);
+ }
+
+
+ // uart control classes ======================================================
+ private class SerialControl extends SerialHelper{
+
+ public SerialControl(){
+ }
+
+ @Override
+ protected void onDataReceived(final ComBean ComRecData)
+ {
+ int w_nProcLen = 0;
+
+// DispQueue.AddQueue(ComRecData);
+
+ // save to receive buffer
+ if (m_nUARTReceivePos + ComRecData.nSize > DevComm.UART_MAX_BUF_SIZE) {
+ w_nProcLen = DevComm.UART_MAX_BUF_SIZE - m_nUARTReceivePos;
+ System.arraycopy(ComRecData.bRec, 0, m_pUARTReadBuf, m_nUARTReceivePos, w_nProcLen);
+ System.arraycopy(ComRecData.bRec, w_nProcLen, m_pUARTReadBuf, 0, ComRecData.nSize - w_nProcLen);
+ m_nUARTReceivePos = ComRecData.nSize - w_nProcLen;
+ } else {
+ System.arraycopy(ComRecData.bRec, 0, m_pUARTReadBuf, m_nUARTReceivePos, ComRecData.nSize);
+ m_nUARTReceivePos += ComRecData.nSize;
+ }
+ }
+ }
+
+ private class DispQueueThread extends Thread{
+ private final Queue QueueList = new LinkedList();
+ @Override
+ public void run() {
+ super.run();
+// while(!isInterrupted()) {
+// int i;
+// i = 0;
+// while (m_bBufferHandle)
+// {
+// i++;
+// if (i > 10000)
+// break;
+// }
+// m_bBufferHandle = true;
+// while(true)
+// {
+// final ComBean ComData;
+// if ((ComData=QueueList.poll())==null)
+// break;
+//
+// Log.d("NOEM_DEBUG", String.format("DispQueueThread: ComData.nSize = %d, m_nUARTReadLen = %d",
+// ComData.nSize, m_nUARTReadLen));
+// System.arraycopy(ComData.bRec, 0, m_pUARTReadBuf, m_nUARTReadLen, ComData.nSize);
+// m_nUARTReadLen = m_nUARTReadLen + ComData.nSize;
+//// break;
+// }
+// m_bBufferHandle = false;
+// }
+ }
+
+ public synchronized void AddQueue(ComBean ComData){
+ QueueList.add(ComData);
+ }
+ }
+ // ! uart control classes ====================================================
+}
diff --git a/android/src/main/java/com/idworld/noemhost_and/IUsbConnState.java b/android/src/main/java/com/idworld/noemhost_and/IUsbConnState.java
new file mode 100644
index 0000000..98cffd3
--- /dev/null
+++ b/android/src/main/java/com/idworld/noemhost_and/IUsbConnState.java
@@ -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();
+}
diff --git a/android/src/main/java/com/idworld/noemhost_and/MainActivity.java b/android/src/main/java/com/idworld/noemhost_and/MainActivity.java
new file mode 100644
index 0000000..38aaf7f
--- /dev/null
+++ b/android/src/main/java/com/idworld/noemhost_and/MainActivity.java
@@ -0,0 +1,1533 @@
+//package com.idworld.noemhost_and;
+//
+//import android.Manifest;
+//import android.content.Intent;
+//import android.content.pm.PackageManager;
+//import android.graphics.Bitmap;
+//import android.graphics.BitmapFactory;
+//import android.os.Build;
+//import android.os.Environment;
+//import android.os.SystemClock;
+//import android.support.annotation.Nullable;
+//import android.support.v4.app.ActivityCompat;
+//import android.support.v4.content.ContextCompat;
+//import android.support.v7.app.AppCompatActivity;
+//import android.os.Bundle;
+//import android.view.KeyEvent;
+//import android.view.View;
+//import android.widget.AdapterView;
+//import android.widget.ArrayAdapter;
+//import android.widget.Button;
+//import android.widget.EditText;
+//import android.widget.ImageView;
+//import android.widget.Spinner;
+//import android.widget.TextView;
+//import android.widget.Toast;
+//
+//import java.io.File;
+//import java.io.FileInputStream;
+//import java.io.FileOutputStream;
+//import java.io.IOException;
+//import java.util.ArrayList;
+//import java.util.Arrays;
+//import java.util.Collections;
+//import java.util.List;
+//
+//import android_serialport_api.SerialPortFinder;
+//
+//public class MainActivity extends AppCompatActivity implements View.OnClickListener {
+//
+// // global variables
+// int m_nMaxFpCount;
+// int m_nUserID, m_nParam, m_nImgWidth, m_nImgHeight;
+// long m_nPassedTime;
+// String m_strPost;
+// boolean m_bCancel = true;
+// boolean m_bConCapture;
+//
+// // communication device variables
+// private static DevComm m_devComm;
+// int m_nBaudrate;
+// String m_szDevice;
+//
+// // serial port
+// SerialPortFinder mSerialPortFinder;
+//
+// // image variables
+// byte[] m_binImage;
+// byte[] m_bmpImage;
+//
+// // control variables
+// Button m_btnOpenDevice;
+// Button m_btnCloseDevice;
+// Button m_btnEnroll;
+// Button m_btnVerify;
+// Button m_btnIdentify;
+// Button m_btnCaptureImage;
+// Button m_btnCancel;
+// Button m_btnGetUserCount;
+// Button m_btnGetEmptyID;
+// Button m_btnDeleteID;
+// Button m_btnDeleteAll;
+// Button m_btnGetTemplate;
+// Button m_btnSetTemplate;
+// Button m_btnGetMultiTemplate;
+// Button m_btnSetMultiTemplate;
+// EditText m_editUserID;
+// EditText m_editParam;
+// TextView m_txtStatus;
+// ImageView m_FpImageViewer;
+// Spinner m_spFpCount;
+// Spinner m_spBaudrate;
+// Spinner m_spDevice;
+//
+// @Override
+// protected void onCreate(Bundle savedInstanceState) {
+// super.onCreate(savedInstanceState);
+// setContentView(R.layout.activity_main);
+//
+// // init variables
+// m_nMaxFpCount = 80;
+//
+// // init ui
+// InitWidget();
+// SetInitialState();
+// InitDeviceList();
+//
+// // request permission
+// if (!requestPermission(PERMISSIONS)) {
+//// Toast.makeText(this, "Can not work correctly without permissions", Toast.LENGTH_LONG).show();
+// }
+//
+// // get device name
+// m_spDevice.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+// public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+// m_szDevice = m_spDevice.getItemAtPosition(position).toString();
+// }
+// public void onNothingSelected(AdapterView> parent) {
+// }
+// });
+//
+// // get baudrate
+// m_spBaudrate.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+// public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+// if (position == 0)
+// m_nBaudrate = 9600;
+// else if (position == 1)
+// m_nBaudrate = 19200;
+// else if (position == 2)
+// m_nBaudrate = 38400;
+// else if (position == 3)
+// m_nBaudrate = 57600;
+// else// if (position == 4)
+// m_nBaudrate = 115200;
+// }
+// public void onNothingSelected(AdapterView> parent) {
+// }
+// });
+//
+// // calculate max fp count
+// m_spFpCount.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+// public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+// if (position == 0)
+// m_nMaxFpCount = 80;
+// else if (position == 1)
+// m_nMaxFpCount = 170;
+// else if (position == 2)
+// m_nMaxFpCount = 200;
+// else if (position == 3)
+// m_nMaxFpCount = 500;
+// else if (position == 4)
+// m_nMaxFpCount = 1000;
+// else if (position == 5)
+// m_nMaxFpCount = 1700;
+// else if (position == 6)
+// m_nMaxFpCount = 2000;
+// else// if (position == 7)
+// m_nMaxFpCount = 3000;
+// }
+// public void onNothingSelected(AdapterView> parent) {
+// }
+// });
+// }
+//
+// @Override
+// protected void onDestroy() {
+// super.onDestroy();
+// }
+//
+// @Override
+// protected void onSaveInstanceState(Bundle outState) {
+// super.onSaveInstanceState(outState);
+// }
+//
+// @Override
+// public void onClick(View view) {
+// if(view == m_btnOpenDevice)
+// OnOpenDeviceBtn();
+// else if(view == m_btnCloseDevice)
+// OnCloseDeviceBtn();
+// else if(view == m_btnEnroll)
+// OnEnrollBtn();
+// else if(view == m_btnVerify)
+// OnVerifyBtn();
+// else if(view == m_btnIdentify)
+// OnIdentifyBtn();
+// else if(view == m_btnCaptureImage)
+// OnGetImageBtn();
+// else if(view == m_btnCancel)
+// OnCancelBtn();
+// else if(view == m_btnGetUserCount)
+// OnGetUserCount();
+// else if(view == m_btnGetEmptyID)
+// OnGetEmptyID();
+// else if(view == m_btnDeleteID)
+// OnDeleteIDBtn();
+// else if(view == m_btnDeleteAll)
+// OnDeleteAllBtn();
+// else if(view == m_btnGetTemplate)
+// OnGetTemplate();
+// else if(view == m_btnSetTemplate)
+// OnSetTemplate();
+// else if(view == m_btnGetMultiTemplate)
+// OnGetMultiTemplate();
+// else if(view == m_btnSetMultiTemplate)
+// OnSetMultiTemplate();
+// }
+//
+// @Override
+// public boolean onKeyDown(int KeyCode, KeyEvent event) {
+// if (KeyCode == KeyEvent.KEYCODE_BACK) {
+// if (event.getRepeatCount() == 0) {
+// if (!m_bCancel) {
+// Toast toast = Toast.makeText(getApplicationContext(), "Please cancel your command first", 5);
+// toast.show();
+// return true;
+// }
+// if (m_btnCloseDevice.isEnabled())
+// OnCloseDeviceBtn();
+// }
+// }
+//
+// return super.onKeyDown(KeyCode, event);
+// }
+//
+// private void InitWidget()
+// {
+// m_FpImageViewer = findViewById(R.id.imvImgViewer);
+// m_btnOpenDevice = findViewById(R.id.btnOpenDevice);
+// m_btnCloseDevice = findViewById(R.id.btnCloseDevice);
+// m_btnEnroll = findViewById(R.id.btnEnroll);
+// m_btnVerify = findViewById(R.id.btnVerify);
+// m_btnIdentify = findViewById(R.id.btnIdentify);
+// m_btnCaptureImage = findViewById(R.id.btnCaptureImage);
+// m_btnCancel = findViewById(R.id.btnCancel);
+// m_btnGetUserCount = findViewById(R.id.btnGetEnrollCount);
+// m_btnGetEmptyID = findViewById(R.id.btnGetEmptyID);
+// m_btnDeleteID = findViewById(R.id.btnRemoveTemplate);
+// m_btnDeleteAll = findViewById(R.id.btnRemoveAll);
+// m_btnGetTemplate = findViewById(R.id.btnGetTemplate);
+// m_btnSetTemplate = findViewById(R.id.btnSetTemplate);
+// m_btnGetMultiTemplate = findViewById(R.id.btnGetMultiTemplate);
+// m_btnSetMultiTemplate = findViewById(R.id.btnSetMultiTemplate);
+// m_txtStatus = findViewById(R.id.txtStatus);
+// m_editUserID = findViewById(R.id.edtUserID);
+// m_spFpCount = findViewById(R.id.spnFpCount);
+// m_spBaudrate = findViewById(R.id.spnBaudrate);
+// m_spDevice = findViewById(R.id.spnDevice);
+//
+// m_btnOpenDevice.setOnClickListener(this);
+// m_btnCloseDevice.setOnClickListener(this);
+// m_btnEnroll.setOnClickListener(this);
+// m_btnVerify.setOnClickListener(this);
+// m_btnIdentify.setOnClickListener(this);
+// m_btnCaptureImage.setOnClickListener(this);
+// m_btnCancel.setOnClickListener(this);
+// m_btnGetUserCount.setOnClickListener(this);
+// m_btnGetEmptyID.setOnClickListener(this);
+// m_btnDeleteID.setOnClickListener(this);
+// m_btnDeleteAll.setOnClickListener(this);
+// m_btnGetTemplate.setOnClickListener(this);
+// m_btnSetTemplate.setOnClickListener(this);
+// m_btnGetMultiTemplate.setOnClickListener(this);
+// m_btnSetMultiTemplate.setOnClickListener(this);
+//
+// if(m_devComm == null){
+// m_devComm = new DevComm(this, m_IConnectionHandler);
+// }
+//
+// m_binImage = new byte[1024*100];
+// m_bmpImage = new byte[1024*100];
+// }
+//
+// private void EnableCtrl(boolean bEnable)
+// {
+// m_btnEnroll.setEnabled(bEnable);
+// m_btnVerify.setEnabled(bEnable);
+// m_btnIdentify.setEnabled(bEnable);
+// m_btnCancel.setEnabled(bEnable);
+// m_btnGetUserCount.setEnabled(bEnable);
+// m_btnGetEmptyID.setEnabled(bEnable);
+// m_btnDeleteID.setEnabled(bEnable);
+// m_btnDeleteAll.setEnabled(bEnable);
+// m_btnCaptureImage.setEnabled(bEnable);
+// m_btnGetTemplate.setEnabled(bEnable);
+// m_btnSetTemplate.setEnabled(bEnable);
+// m_btnGetMultiTemplate.setEnabled(bEnable);
+// m_btnSetMultiTemplate.setEnabled(bEnable);
+//
+// //m_editUserID.setEnabled(bEnable);
+// }
+//
+// private void SetInitialState()
+// {
+// m_txtStatus.setText("Please open device!");
+// m_btnOpenDevice.setEnabled(true);
+// m_btnCloseDevice.setEnabled(false);
+// EnableCtrl(false);
+// }
+//
+// private void InitDeviceList()
+// {
+// // get device list
+// mSerialPortFinder= new SerialPortFinder();
+// String[] entryValues = mSerialPortFinder.getAllDevicesPath();
+// List allDevices = new ArrayList();
+// allDevices.add("USB");
+// Collections.addAll(allDevices, entryValues);
+// ArrayAdapter aspnDevices = new ArrayAdapter(this, android.R.layout.simple_spinner_item, allDevices);
+// m_spDevice.setAdapter(aspnDevices);
+// }
+//
+// private void OnOpenDeviceBtn() {
+// String[] w_strInfo = new String[1];
+//
+// if(m_devComm != null)
+// {
+// if (!m_devComm.IsInit())
+// {
+// if (!m_devComm.OpenComm(m_szDevice, m_nBaudrate)) {
+// m_txtStatus.setText("Failed init device!");
+// return;
+// }
+// }
+// if (m_devComm.Run_TestConnection() == DevComm.ERR_SUCCESS) {
+// if (m_devComm.Run_GetDeviceInfo(w_strInfo) == DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText("Open Success!\r\nDevice Info : " + w_strInfo[0]);
+// EnableCtrl(true);
+// m_btnOpenDevice.setEnabled(false);
+// m_btnCloseDevice.setEnabled(true);
+// }
+// else
+// m_txtStatus.setText("Can not connect to device!");
+// }
+// else {
+// m_txtStatus.setText("Can not connect to device!");
+// m_devComm.CloseComm();
+// }
+// }
+// }
+//
+// private void OnCloseDeviceBtn() {
+// m_devComm.CloseComm();
+// m_bCancel = true;
+//
+// SetInitialState();
+// }
+//
+// private void OnEnrollBtn() {
+// int w_nRet;
+// int[] w_nState = new int[1];
+//
+// if (!m_devComm.IsInit())
+// return;
+//
+// if (!CheckUserID())
+// return;
+//
+// // Check if fp is exist
+// w_nRet = m_devComm.Run_GetStatus(m_nUserID, w_nState);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// return;
+// }
+//
+// if (w_nState[0] == DevComm.GD_TEMPLATE_NOT_EMPTY)
+// {
+// m_txtStatus.setText("Template is already exist");
+// return;
+// }
+//
+// m_txtStatus.setText("Press finger : " + m_nUserID);
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// m_devComm.Run_SLEDControl(1);
+// m_bCancel = false;
+//
+// new Thread(new Runnable() {
+// int w_nRet;
+// int w_nUserID;
+// int w_nEnrollStep = 0;
+// final int w_nGenCount = 3;
+// final int[] w_nDupID = new int[1];
+// final int[] w_nWidth = new int[1];
+// final int[] w_nHeight = new int[1];
+//
+// @Override
+// public void run() {
+//
+// w_nUserID = m_nUserID;
+//
+// while (w_nEnrollStep < w_nGenCount)
+// {
+// m_strPost = String.format("Input finger #%d!", w_nEnrollStep+1);
+// m_FpImageViewer.post(runShowStatus);
+//
+// // Capture
+// if (Capturing() < 0)
+// return;
+//
+// m_strPost = "Release your finger.";
+// m_FpImageViewer.post(runShowStatus);
+//
+// // Up Cpatured Image
+// if (m_devComm.m_nConnected == 2) {
+// w_nRet = m_devComm.Run_UpImage(0, m_binImage, w_nWidth, w_nHeight);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS) {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+//
+// // Draw image
+// m_nImgWidth = w_nWidth[0];
+// m_nImgHeight = w_nHeight[0];
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runDrawImage);
+// }
+//
+// // Create Template
+// w_nRet = m_devComm.Run_Generate(w_nEnrollStep);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// if (w_nRet == DevComm.ERR_BAD_QUALITY)
+// {
+// m_strPost = "Bad quality. Try Again!";
+// m_FpImageViewer.post(runShowStatus);
+// continue;
+// }
+// else
+// {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+// }
+//
+// /*
+// if(w_nEnrollStep == 0)
+// {
+// if (w_nGenCount == 3)
+// m_strPost = "Two More";
+// else
+// m_strPost = "One More";
+// }
+// else if(w_nEnrollStep == 1)
+// m_strPost = "One More";
+//
+// m_FpImageViewer.post(runShowStatus);
+// */
+//
+// w_nEnrollStep++;
+// }
+//
+// //m_strPost = "Release Finger";
+// //m_FpImageViewer.post(runShowStatus);
+//
+// // Merge
+// if (w_nGenCount != 1)
+// {
+// //. Merge Template
+// w_nRet = m_devComm.Run_Merge(0, w_nGenCount);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+// }
+//
+// //. Store template
+// w_nRet = m_devComm.Run_StoreChar(w_nUserID, 0, w_nDupID);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// if (w_nRet == DevComm.ERR_DUPLICATION_ID)
+// m_strPost = String.format("Result : Fail\r\nDuplication ID = %d", w_nDupID[0]);
+// else
+// m_strPost = GetErrorMsg(w_nRet);
+// }
+// else
+// m_strPost = String.format("Result : Success\r\nTemplate No : %d", m_nUserID);
+//
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// }
+// }).start();
+// }
+//
+// private void OnVerifyBtn() {
+// int w_nRet;
+// int[] w_nState = new int[1];
+//
+// if (!m_devComm.IsInit())
+// return;
+//
+// if (!CheckUserID())
+// return;
+//
+// w_nRet = m_devComm.Run_GetStatus(m_nUserID, w_nState);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// return;
+// }
+//
+// if (w_nState[0] == DevComm.GD_TEMPLATE_EMPTY )
+// {
+// m_txtStatus.setText("Template is empty");
+// return;
+// }
+//
+// m_txtStatus.setText("Press finger");
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// m_devComm.Run_SLEDControl(1);
+// m_bCancel = false;
+//
+// new Thread(new Runnable() {
+// int w_nRet;
+// final int[] w_nLearned = new int[1];
+// final int[] w_nWidth = new int[1];
+// final int[] w_nHeight = new int[1];
+//
+// @Override
+// public void run() {
+//
+// if (Capturing() < 0)
+// return;
+//
+// m_strPost = "Release your finger.";
+// m_FpImageViewer.post(runShowStatus);
+//
+// // Up Cpatured Image
+// if (m_devComm.m_nConnected == 2) {
+// w_nRet = m_devComm.Run_UpImage(0, m_binImage, w_nWidth, w_nHeight);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS) {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+//
+// // Draw image
+// m_nImgWidth = w_nWidth[0];
+// m_nImgHeight = w_nHeight[0];
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runDrawImage);
+// }
+//
+// // Create template
+// m_nPassedTime = SystemClock.elapsedRealtime();
+// w_nRet = m_devComm.Run_Generate(0);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+//
+// // Verify
+// w_nRet = m_devComm.Run_Verify(m_nUserID, 0, w_nLearned);
+// m_nPassedTime = SystemClock.elapsedRealtime() - m_nPassedTime;
+//
+// if (w_nRet == DevComm.ERR_SUCCESS)
+// m_strPost = String.format("Result : Success\r\nTemplate No : %d, Learn Result : %d\r\nMatch Time : %dms", m_nUserID, w_nLearned[0], m_nPassedTime);
+// else
+// m_strPost = GetErrorMsg(w_nRet);
+//
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// }
+// }).start();
+// }
+//
+// private void OnIdentifyBtn() {
+// if (!m_devComm.IsInit())
+// return;
+//
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// m_devComm.Run_SLEDControl(1);
+// m_bCancel = false;
+//
+// m_strPost = "";
+//
+// new Thread(new Runnable() {
+// int w_nRet;
+// final int[] w_nID = new int[1];
+// final int[] w_nLearned = new int[1];
+// final int[] w_nWidth = new int[1];
+// final int[] w_nHeight = new int[1];
+//
+// @Override
+// public void run() {
+//
+// while(true)
+// {
+// if (m_strPost.isEmpty())
+// m_strPost = "Input your finger.";
+// else
+// m_strPost = m_strPost + "\r\nInput your finger.";
+// m_FpImageViewer.post(runShowStatus);
+//
+// if (Capturing() < 0)
+// return;
+//
+// m_strPost = "Release your finger.";
+// m_FpImageViewer.post(runShowStatus);
+//
+// // Up Cpatured Image
+// if (m_devComm.m_nConnected == 2) {
+// w_nRet = m_devComm.Run_UpImage(0, m_binImage, w_nWidth, w_nHeight);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS) {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+//
+// // Draw image
+// m_nImgWidth = w_nWidth[0];
+// m_nImgHeight = w_nHeight[0];
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runDrawImage);
+// }
+//
+// // Create template
+// m_nPassedTime = SystemClock.elapsedRealtime();
+// w_nRet = m_devComm.Run_Generate(0);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+//
+// if (w_nRet == DevComm.ERR_CONNECTION)
+// {
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+// else
+// {
+// SystemClock.sleep(1000);
+// continue;
+// }
+// }
+//
+// // Identify
+// w_nRet = m_devComm.Run_Search(0, 1, m_nMaxFpCount, w_nID, w_nLearned);
+// m_nPassedTime = SystemClock.elapsedRealtime() - m_nPassedTime;
+//
+// if (w_nRet == DevComm.ERR_SUCCESS) {
+// m_strPost = String.format("Result : Success\r\nTemplate No : %d, Learn Result : %d\r\nMatch Time : %dms", w_nID[0], w_nLearned[0], m_nPassedTime);
+// }
+// else
+// {
+// m_strPost = String.format("\r\nMatch Time : %dms", m_nPassedTime);
+// m_strPost = GetErrorMsg(w_nRet) + m_strPost;
+// }
+// }
+// }
+// }).start();
+// }
+//
+// public void OnDetectFingerBtn(){
+// /*
+// if (!m_devComm.IsInit())
+// return;
+// m_devComm.oem_cmos_led(true);
+// if (m_devComm.oem_is_press_finger() < 0 ){
+// m_txtStatus.setText("Communication error!");
+// return;
+// }
+// if (m_devComm.m_wLastAck == DevComm.NACK_INFO ){
+// m_txtStatus.setText(DisplayErr( m_devComm.m_nLastAckParam, 0 ));
+// return;
+// }
+// if( m_devComm.m_nLastAckParam != 0 ){
+// m_txtStatus.setText("Finger is not pressed!");
+// m_devComm.oem_cmos_led(false);
+// return;
+// }
+//
+// m_txtStatus.setText("Finger is pressed!");
+//
+// m_devComm.oem_cmos_led(false);
+// */
+// }
+//
+// private void OnGetImageBtn() {
+// GetConCaptureState();
+//
+// if (m_bConCapture){
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// }
+//
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// m_devComm.Run_SLEDControl(1);
+// m_bCancel = false;
+// m_txtStatus.setText("Input finger!");
+//
+// new Thread(new Runnable() {
+// int w_nRet;
+// final int[] width = new int[1];
+// final int[] height = new int[1];
+//
+// @Override
+// public void run() {
+//
+// if (Capturing() < 0)
+// return;
+//
+// m_strPost = "Release Finger\nUploading Image...";
+// m_FpImageViewer.post(runShowStatus);
+//
+// w_nRet = m_devComm.Run_UpImage(0, m_binImage, width, height);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_strPost = GetErrorMsg(w_nRet);
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return;
+// }
+//
+// m_nImgWidth = width[0]; m_nImgHeight = height[0];
+// m_strPost = "Get Image OK !";
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runDrawImage);
+// m_FpImageViewer.post(runEnableCtrl);
+// }
+// }).start();
+// }
+//
+// private void OnCancelBtn() {
+// m_bCancel = true;
+// }
+//
+// private void OnGetUserCount() {
+// int w_nRet;
+// int[] w_nEnrollCount = new int[1];
+//
+// if (!m_devComm.IsInit())
+// return;
+//
+// w_nRet = m_devComm.Run_GetEnrollCount(1, m_nMaxFpCount, w_nEnrollCount);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// return;
+// }
+//
+// m_txtStatus.setText(String.format("Result : Success\r\nEnroll Count = %d", w_nEnrollCount[0]));
+// }
+//
+// private void OnGetEmptyID() {
+// int w_nRet;
+// int[] w_nEmptyID = new int[1];
+//
+// if (!m_devComm.IsInit())
+// return;
+//
+// w_nRet = m_devComm.Run_GetEmptyID(1, m_nMaxFpCount, w_nEmptyID);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// return;
+// }
+//
+// m_txtStatus.setText(String.format("Result : Success\r\nEmpty ID = %d", w_nEmptyID[0]));
+// m_editUserID.setText(String.format("%d", w_nEmptyID[0]));
+// }
+//
+// private void OnDeleteIDBtn() {
+// int w_nRet;
+//
+// if (!m_devComm.IsInit())
+// return;
+//
+// if (!CheckUserID())
+// return;
+//
+// w_nRet = m_devComm.Run_DelChar(m_nUserID, m_nUserID);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// return;
+// }
+//
+// m_txtStatus.setText("Delete OK !");
+// }
+//
+// private void OnDeleteAllBtn() {
+// int w_nRet;
+//
+// if (!m_devComm.IsInit())
+// return;
+//
+// w_nRet = m_devComm.Run_DelChar(1, m_nMaxFpCount);
+//
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// return;
+// }
+//
+// m_txtStatus.setText("Delete all OK !");
+// }
+//
+// private void OnGetTemplate() {
+// int w_nRet;
+// byte[] w_pTemplate = new byte[DevComm.MAX_DATA_LEN];
+// int[] w_nSize = new int[1];
+//
+// // Check Device Connection
+// if (!m_devComm.IsInit())
+// return;
+//
+// // Check User ID
+// if (!CheckUserID())
+// return;
+//
+// // check permission
+// if (!permissionGranted()) {
+// requestPermission();
+// return;
+// }
+//
+// do
+// {
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+//
+// // Load Template to Buffer
+// w_nRet = m_devComm.Run_LoadChar((short)m_nUserID, 0);
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// break;
+// }
+//
+// // Up Template
+// w_nRet = m_devComm.Run_UpChar(0, w_pTemplate, w_nSize);
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet));
+// break;
+// }
+//
+// ////////////////////////////////////////////////////////////////////
+// // Save Template (/FPData/01.fpt)
+// // Create Directory
+// String w_szSaveDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FPData";
+// File w_fpDir = new File(w_szSaveDirPath);
+// if (!w_fpDir.exists())
+// w_fpDir.mkdirs();
+//
+// // Create Template File
+// File w_fpTemplate = new File(w_szSaveDirPath + "/" + m_nUserID + ".fpt");
+// if (!w_fpTemplate.exists())
+// {
+// try
+// {
+// w_fpTemplate.createNewFile();
+// } catch (IOException e)
+// {
+// e.printStackTrace();
+// }
+// }
+//
+// // Save Template Data
+// FileOutputStream w_foTemplate = null;
+// try
+// {
+// w_foTemplate = new FileOutputStream(w_fpTemplate);
+// w_foTemplate.write(w_pTemplate, 0, w_nSize[0]);
+// w_foTemplate.close();
+// // Show Status
+// m_txtStatus.setText(String.format("Result : Get Template Success.\r\nDir : %s", w_szSaveDirPath + "/" + m_nUserID + ".fpt"));
+// break;
+// } catch (Exception e)
+// {
+// e.printStackTrace();
+// }
+// ////////////////////////////////////////////////////////////////////
+//
+// m_txtStatus.setText("Result : Get Template Success.\r\nSave Template Failed.");
+// } while (false);
+//
+// EnableCtrl(true);
+// m_btnCloseDevice.setEnabled(true);
+// m_btnCancel.setEnabled(false);
+// }
+//
+// private void OnSetTemplate() {
+// int w_nRet;
+// int[] w_nDupTmplNo = new int[1];
+// byte[] w_pTemplate = new byte[DevComm.MAX_DATA_LEN];
+// int w_nTemplateSize = 0;
+//
+// // Check Device Connection
+// if (!m_devComm.IsInit())
+// return;
+//
+// // Check User ID
+// if (!CheckUserID())
+// return;
+//
+// // check permission
+// if (!permissionGranted()) {
+// requestPermission();
+// return;
+// }
+//
+// ////////////////////////////////////////////////////////////////////
+// // Load Template (/FPData/01.fpt)
+// // Check Directory
+// String w_szLoadDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FPData";
+// File w_fpDir = new File(w_szLoadDirPath);
+// if (!w_fpDir.exists())
+// {
+// m_txtStatus.setText(String.format("Result : Can't load template data.\r\nDir : %s", w_szLoadDirPath + "/" + m_nUserID + ".fpt"));
+// return;
+// }
+//
+// // Check Template File
+// File w_fpTemplate = new File(w_szLoadDirPath + "/" + m_nUserID + ".fpt");
+// if (!w_fpTemplate.exists())
+// {
+// m_txtStatus.setText(String.format("Result : Can't load template data.\r\nDir : %s", w_szLoadDirPath + "/" + m_nUserID + ".fpt"));
+// return;
+// }
+//
+// // Load Template Data
+// FileInputStream w_fiTemplate = null;
+//
+// try
+// {
+// w_fiTemplate = new FileInputStream(w_fpTemplate);
+// w_nTemplateSize = w_fiTemplate.available();
+// w_fiTemplate.read(w_pTemplate, 0, w_nTemplateSize);
+// w_fiTemplate.close();
+// } catch (Exception e)
+// {
+// e.printStackTrace();
+// m_txtStatus.setText(String.format("Result : Can't load template data.\r\nDir : %s", w_szLoadDirPath + "/" + m_nUserID + ".fpt"));
+// return;
+// }
+// ////////////////////////////////////////////////////////////////////
+//
+// do
+// {
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+//
+// // Download Template to Buffer
+// w_nRet = m_devComm.Run_DownChar(0, w_pTemplate, w_nTemplateSize);
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet) + "Run_DownChar");
+// break;
+// }
+//
+// // Store Template
+// w_nRet = m_devComm.Run_StoreChar(m_nUserID, 0, w_nDupTmplNo);
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// {
+// if(w_nRet == DevComm.ERR_DUPLICATION_ID)
+// {
+// m_txtStatus.setText(String.format("Result : Fail\r\nDuplication ID = %d", w_nDupTmplNo[0]));
+// }
+// else
+// {
+// m_txtStatus.setText(GetErrorMsg(w_nRet) + "Run_StoreChar");
+// }
+// break;
+// }
+//
+// m_txtStatus.setText(String.format("Result : Set Template Success.\r\nUserID = %d", m_nUserID));
+// } while (false);
+//
+// EnableCtrl(true);
+// m_btnCloseDevice.setEnabled(true);
+// m_btnCancel.setEnabled(false);
+// }
+//
+// private void OnGetMultiTemplate() {
+// // Check Device Connection
+// if (!m_devComm.IsInit())
+// return;
+//
+// // check permission
+// if (!permissionGranted()) {
+// requestPermission();
+// return;
+// }
+//
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// m_bCancel = false;
+// m_strPost = "";
+//
+// new Thread(new Runnable() {
+// @Override
+// public void run() {
+// int w_nRet;
+// byte[] w_pTemplate = new byte[DevComm.MAX_DATA_LEN];
+// int[] w_nSize = new int[1];
+// int w_nUserId;
+//
+// for (w_nUserId = 1; w_nUserId <= m_nMaxFpCount; w_nUserId++)
+// {
+// // Load Template to Buffer
+// w_nRet = m_devComm.Run_LoadChar((short)w_nUserId, 0);
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// continue;
+//
+// // Up Template
+// w_nRet = m_devComm.Run_UpChar(0, w_pTemplate, w_nSize);
+// if (w_nRet != DevComm.ERR_SUCCESS)
+// continue;
+//
+// ////////////////////////////////////////////////////////////////////
+// // Save Template (/FPData/01.fpt)
+// // Create Directory
+// String w_szSaveDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FPData";
+// File w_fpDir = new File(w_szSaveDirPath);
+// if (!w_fpDir.exists())
+// w_fpDir.mkdirs();
+//
+// // Create Template File
+// File w_fpTemplate = new File(w_szSaveDirPath + "/" + w_nUserId + ".fpt");
+// if (!w_fpTemplate.exists())
+// {
+// try
+// {
+// w_fpTemplate.createNewFile();
+// } catch (IOException e)
+// {
+// e.printStackTrace();
+// }
+// }
+//
+// // Save Template Data
+// FileOutputStream w_foTemplate = null;
+// try
+// {
+// w_foTemplate = new FileOutputStream(w_fpTemplate);
+// w_foTemplate.write(w_pTemplate, 0, w_nSize[0]);
+// w_foTemplate.close();
+// // Show Status
+// m_strPost = String.format("Result : Get Template Success.\r\nDir : %s",
+// w_szSaveDirPath + "/" + w_nUserId + ".fpt");
+// m_FpImageViewer.post(runShowStatus);
+// continue;
+// } catch (Exception e)
+// {
+// e.printStackTrace();
+// }
+// ////////////////////////////////////////////////////////////////////
+//
+// m_strPost = "Result : Get Template Success.\r\nSave Template Failed.";
+// m_FpImageViewer.post(runShowStatus);
+//
+// if (m_bCancel){
+// StopOperation();
+// return;
+// }
+// }
+//
+// m_strPost = "Get multiple template is finished";
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// }
+// }).start();
+// }
+//
+// private void OnSetMultiTemplate() {
+// // Check Device Connection
+// if (!m_devComm.IsInit())
+// return;
+//
+// // check permission
+// if (!permissionGranted()) {
+// requestPermission();
+// return;
+// }
+//
+// EnableCtrl(false);
+// m_btnCloseDevice.setEnabled(false);
+// m_btnCancel.setEnabled(true);
+// m_bCancel = false;
+// m_strPost = "";
+//
+// new Thread(new Runnable() {
+// @Override
+// public void run() {
+// int w_nRet;
+// int[] w_nDupTmplNo = new int[1];
+// byte[] w_pTemplate = new byte[DevComm.MAX_DATA_LEN];
+// int w_nTemplateSize = 0;
+// int w_nUserId;
+//
+// for (w_nUserId = 1; w_nUserId <= m_nMaxFpCount; w_nUserId++) {
+// ////////////////////////////////////////////////////////////////////
+// // Load Template (/FPData/01.fpt)
+// // Check Directory
+// String w_szLoadDirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/FPData";
+// File w_fpDir = new File(w_szLoadDirPath);
+// if (!w_fpDir.exists())
+// continue;
+//
+// // Check Template File
+// File w_fpTemplate = new File(w_szLoadDirPath + "/" + w_nUserId + ".fpt");
+// if (!w_fpTemplate.exists()) {
+// continue;
+// }
+//
+// // Load Template Data
+// FileInputStream w_fiTemplate = null;
+//
+// try {
+// w_fiTemplate = new FileInputStream(w_fpTemplate);
+// w_nTemplateSize = w_fiTemplate.available();
+// w_fiTemplate.read(w_pTemplate, 0, w_nTemplateSize);
+// w_fiTemplate.close();
+// } catch (Exception e) {
+// e.printStackTrace();
+// continue;
+// }
+// ////////////////////////////////////////////////////////////////////
+//
+// // Download Template to Buffer
+// w_nRet = m_devComm.Run_DownChar(0, w_pTemplate, w_nTemplateSize);
+// if (w_nRet != DevComm.ERR_SUCCESS) {
+// m_txtStatus.setText(GetErrorMsg(w_nRet) + "Run_DownChar");
+// break;
+// }
+//
+// // Store Template
+// w_nRet = m_devComm.Run_StoreChar(w_nUserId, 0, w_nDupTmplNo);
+// if (w_nRet != DevComm.ERR_SUCCESS) {
+// if (w_nRet == DevComm.ERR_DUPLICATION_ID) {
+// m_strPost = String.format("Result : Fail\r\nDuplication ID = %d", w_nDupTmplNo[0]);
+// } else {
+// m_strPost = GetErrorMsg(w_nRet) + "Run_StoreChar";
+// }
+// m_FpImageViewer.post(runShowStatus);
+// break;
+// }
+//
+// m_strPost = String.format("Result : Set Template Success.\r\nUserID = %d", m_nUserID);
+// m_FpImageViewer.post(runShowStatus);
+//
+// if (m_bCancel){
+// StopOperation();
+// return;
+// }
+// }
+//
+// m_strPost = "Set multiple template is finished";
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// }
+// }).start();
+// }
+//
+// public boolean CheckUserID(){
+// String str;
+//
+// str = m_editUserID.getText().toString();
+//
+// if(str == "" )
+// {
+// m_txtStatus.setText("Please input user id");
+// return false;
+// }
+//
+// try {
+// m_nUserID = Integer.parseInt(str);
+// } catch (NumberFormatException e) {
+// m_txtStatus.setText("Please input correct user id(1~" + m_nMaxFpCount + ")");
+// return false;
+// }
+//
+// if(m_nUserID > (m_nMaxFpCount) || m_nUserID < 1)
+// {
+// m_txtStatus.setText("Please input correct user id(1~" + m_nMaxFpCount + ")");
+// return false;
+// }
+//
+// return true;
+// }
+//
+// public boolean CheckParam(int nMin, int nMax){
+// String str;
+//
+// str = m_editParam.getText().toString();
+//
+// if(str == "" )
+// {
+// m_txtStatus.setText("Please input parameter!");
+// return false;
+// }
+//
+// try {
+// m_nParam = Integer.parseInt(str);
+// } catch (NumberFormatException e) {
+// m_txtStatus.setText(String.format("Please input parameter (%d~%d)!", nMin, nMax));
+// return false;
+// }
+//
+// if (m_nParam > nMax || m_nParam < nMin)
+// {
+// m_txtStatus.setText(String.format("Please input correct parameter (%d~%d)!", nMin, nMax));
+// return false;
+// }
+//
+// return true;
+// }
+//
+// private void GetConCaptureState(){
+// }
+//
+// private int Capturing(){
+// int w_nRet;
+// while(true){
+//
+// w_nRet = m_devComm.Run_GetImage();
+//
+// if (w_nRet == DevComm.ERR_CONNECTION)
+// {
+// m_strPost = "Communication error!";
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// return -1;
+// }
+// else if (w_nRet == DevComm.ERR_SUCCESS)
+// break;
+//
+// if (m_bCancel){
+// StopOperation();
+// return -1;
+// }
+// }
+//
+// return 0;
+// }
+//
+// private void StopOperation(){
+// m_strPost = "Canceled";
+// m_FpImageViewer.post(runShowStatus);
+// m_FpImageViewer.post(runEnableCtrl);
+// }
+//
+// private String GetErrorMsg(int nErrorCode)
+// {
+// String str = "";
+//
+// switch(nErrorCode)
+// {
+// case DevComm.ERR_SUCCESS:
+// str = "Succcess";
+// break;
+// case DevComm.ERR_VERIFY:
+// str = "Verify NG";
+// break;
+// case DevComm.ERR_IDENTIFY:
+// str = "Identify NG";
+// break;
+// case DevComm.ERR_EMPTY_ID_NOEXIST:
+// str = "Empty Template no Exist";
+// break;
+// case DevComm.ERR_BROKEN_ID_NOEXIST:
+// str = "Broken Template no Exist";
+// break;
+// case DevComm.ERR_TMPL_NOT_EMPTY:
+// str = "Template of this ID Already Exist";
+// break;
+// case DevComm.ERR_TMPL_EMPTY:
+// str = "This Template is Already Empty";
+// break;
+// case DevComm.ERR_INVALID_TMPL_NO:
+// str = "Invalid Template No";
+// break;
+// case DevComm.ERR_ALL_TMPL_EMPTY:
+// str = "All Templates are Empty";
+// break;
+// case DevComm.ERR_INVALID_TMPL_DATA:
+// str = "Invalid Template Data";
+// break;
+// case DevComm.ERR_DUPLICATION_ID:
+// str = "Duplicated ID : ";
+// break;
+// case DevComm.ERR_BAD_QUALITY:
+// str = "Bad Quality Image";
+// break;
+// case DevComm.ERR_MERGE_FAIL:
+// str = "Merge failed";
+// break;
+// case DevComm.ERR_NOT_AUTHORIZED:
+// str = "Device not authorized.";
+// break;
+// case DevComm.ERR_MEMORY:
+// str = "Memory Error ";
+// break;
+// case DevComm.ERR_INVALID_PARAM:
+// str = "Invalid Parameter";
+// break;
+// case DevComm.ERR_GEN_COUNT:
+// str = "Generation Count is invalid";
+// break;
+// case DevComm.ERR_INVALID_BUFFER_ID:
+// str = "Ram Buffer ID is invalid.";
+// break;
+// case DevComm.ERR_INVALID_OPERATION_MODE:
+// str = "Invalid Operation Mode!";
+// break;
+// case DevComm.ERR_FP_NOT_DETECTED:
+// str = "Finger is not detected.";
+// break;
+// default:
+// str = String.format("Fail, error code=%d", nErrorCode);
+// break;
+// }
+//
+// return str;
+// }
+//
+// Runnable runShowStatus = new Runnable() {
+// public void run()
+// {
+// m_txtStatus.setText(m_strPost);
+// }
+// };
+//
+// Runnable runDrawImage = new Runnable() {
+// public void run()
+// {
+// int nSize;
+//
+// MakeBMPBuf(m_binImage, m_bmpImage, m_nImgWidth, m_nImgHeight);
+//
+// if ((m_nImgWidth % 4) != 0)
+// nSize = m_nImgWidth + (4 - (m_nImgWidth % 4));
+// else
+// nSize = m_nImgWidth;
+//
+// nSize = 1078 + nSize * m_nImgHeight;
+//
+// //DebugManage.WriteBmp(m_bmpImage, nSize);
+//
+// Bitmap image = BitmapFactory.decodeByteArray(m_bmpImage, 0, nSize);
+//
+// m_FpImageViewer.setImageBitmap(image);
+// }
+// };
+//
+// Runnable runEnableCtrl = new Runnable() {
+// public void run()
+// {
+// EnableCtrl(true);
+// m_btnOpenDevice.setEnabled(false);
+// m_btnCloseDevice.setEnabled(true);
+// m_devComm.Run_SLEDControl(0);
+// }
+// };
+//
+// private void MakeBMPBuf(byte[] Input, byte[] Output, int iImageX, int iImageY)
+// {
+//
+// byte[] w_bTemp = new byte[4];
+// byte[] head = new byte[1078];
+// byte[] head2={
+// /***************************/
+// //file header
+// 0x42,0x4d,//file type
+// //0x36,0x6c,0x01,0x00, //file size***
+// 0x0,0x0,0x0,0x00, //file size***
+// 0x00,0x00, //reserved
+// 0x00,0x00,//reserved
+// 0x36,0x4,0x00,0x00,//head byte***
+// /***************************/
+// //infoheader
+// 0x28,0x00,0x00,0x00,//struct size
+//
+// //0x00,0x01,0x00,0x00,//map width***
+// 0x00,0x00,0x0,0x00,//map width***
+// //0x68,0x01,0x00,0x00,//map height***
+// 0x00,0x00,0x00,0x00,//map height***
+//
+// 0x01,0x00,//must be 1
+// 0x08,0x00,//color count***
+// 0x00,0x00,0x00,0x00, //compression
+// //0x00,0x68,0x01,0x00,//data size***
+// 0x00,0x00,0x00,0x00,//data size***
+// 0x00,0x00,0x00,0x00, //dpix
+// 0x00,0x00,0x00,0x00, //dpiy
+// 0x00,0x00,0x00,0x00,//color used
+// 0x00,0x00,0x00,0x00,//color important
+// };
+//
+// int i,j, num, iImageStep;
+//
+// Arrays.fill(w_bTemp, (byte)0);
+//
+// System.arraycopy(head2, 0, head, 0, head2.length);
+//
+// if ((iImageX % 4) != 0)
+// iImageStep = iImageX + (4 - (iImageX % 4));
+// else
+// iImageStep = iImageX;
+//
+// num=iImageX; head[18]= (byte)(num & (byte)0xFF);
+// num=num>>8; head[19]= (byte)(num & (byte)0xFF);
+// num=num>>8; head[20]= (byte)(num & (byte)0xFF);
+// num=num>>8; head[21]= (byte)(num & (byte)0xFF);
+//
+// num=iImageY; head[22]= (byte)(num & (byte)0xFF);
+// num=num>>8; head[23]= (byte)(num & (byte)0xFF);
+// num=num>>8; head[24]= (byte)(num & (byte)0xFF);
+// num=num>>8; head[25]= (byte)(num & (byte)0xFF);
+//
+// j=0;
+// for (i=54;i<1078;i=i+4)
+// {
+// head[i]=head[i+1]=head[i+2]=(byte)j;
+// head[i+3]=0;
+// j++;
+// }
+//
+// System.arraycopy(head, 0, Output, 0, 1078);
+//
+// if (iImageStep == iImageX){
+// for( i = 0; i < iImageY; i ++){
+// System.arraycopy(Input, i*iImageX, Output, 1078+i*iImageX, iImageX);
+// }
+// }
+// else{
+// iImageStep = iImageStep - iImageX;
+//
+// for( i = 0; i < iImageY; i ++){
+// System.arraycopy(Input, i*iImageX, Output, 1078+i*(iImageX+iImageStep), iImageX);
+// System.arraycopy(w_bTemp, 0, Output, 1078+i*(iImageX+iImageStep)+iImageX, iImageStep);
+// }
+// }
+// }
+//
+// private final IUsbConnState m_IConnectionHandler = new IUsbConnState() {
+// @Override
+// public void onUsbConnected() {
+// String[] w_strInfo = new String[1];
+//
+// if (m_devComm.Run_TestConnection() == DevComm.ERR_SUCCESS)
+// {
+// if (m_devComm.Run_GetDeviceInfo(w_strInfo) == DevComm.ERR_SUCCESS)
+// {
+// EnableCtrl(true);
+// m_btnOpenDevice.setEnabled(false);
+// m_btnCloseDevice.setEnabled(true);
+// m_txtStatus.setText("Open Success!\r\nDevice Info : " + w_strInfo[0]);
+// }
+// }
+// else
+// m_txtStatus.setText("Can not connect to device!");
+// }
+//
+// @Override
+// public void onUsbPermissionDenied() {
+// m_txtStatus.setText("Permission denied!");
+// }
+//
+// @Override
+// public void onDeviceNotFound() {
+// m_txtStatus.setText("Can not find usb device!");
+// }
+// };
+//
+// private final static String[] PERMISSIONS = new String[] {
+// Manifest.permission.WRITE_EXTERNAL_STORAGE,
+// Manifest.permission.READ_EXTERNAL_STORAGE
+// };
+// private final static int REQUEST_CODE_PERMISSION = 1;
+//
+// private boolean requestPermission(String[] permissions){
+// boolean valid = true;
+// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+// List requestPermissions = new ArrayList<>();
+// for (String permission : permissions) {
+// if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
+// requestPermissions.add(permission);
+// valid = false;
+// }
+// }
+// if (requestPermissions.size() > 0) {
+// ActivityCompat.requestPermissions(this, requestPermissions.toArray(new String[requestPermissions.size()]), REQUEST_CODE_PERMISSION);
+// }
+// }
+// return valid;
+// }
+//
+// @Override
+// protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+// super.onActivityResult(requestCode, resultCode, data);
+// }
+//
+// private boolean permissionGranted(){
+// return ContextCompat.checkSelfPermission(
+// this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
+// && ContextCompat.checkSelfPermission(
+// this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+// }
+// private void requestPermission(){
+// ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
+// }
+//}
diff --git a/android/src/main/java/com/idworld/noemhost_and/UsbController.java b/android/src/main/java/com/idworld/noemhost_and/UsbController.java
new file mode 100644
index 0000000..2881294
--- /dev/null
+++ b/android/src/main/java/com/idworld/noemhost_and/UsbController.java
@@ -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 devlist = mUsbManager.getDeviceList();
+ Iterator 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 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 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() + " >==<");
+ }
+}
diff --git a/android/src/main/java/com/xiarui/zhiwen/DevComm.java b/android/src/main/java/com/xiarui/zhiwen/DevComm.java
new file mode 100644
index 0000000..b5f136d
--- /dev/null
+++ b/android/src/main/java/com/xiarui/zhiwen/DevComm.java
@@ -0,0 +1,1842 @@
+package com.xiarui.zhiwen;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Log;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import java.io.IOException;
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.Queue;
+
+import android_serialport_api.ComBean;
+import android_serialport_api.SerialHelper;
+
+import android.util.Log;
+
+/**
+ * Created by KMS on 2016/8/23.
+ */
+public class DevComm {
+ public static final int MAX_DATA_LEN = 2048;
+ public static final int IMAGE_DATA_UNIT = 496;
+ public static final int ID_NOTE_SIZE = 64;
+ public static final int MODULE_SN_LEN = 16;
+ public static final int CHAR_SPLIT_UNIT = 496;
+ public static final int CHAR_SPLIT_THR = 1024;
+ public static final int UART_MAX_BUF_SIZE = (500 * 1024);
+ public static final int UART_READ_TIMEOUT = 5000;
+
+ private static final int SCSI_TIMEOUT = 5000; //ms
+ private static final int COMM_SLEEP_TIME = 40; //ms
+
+ private static final int CMD_PACKET_LEN = 26;
+ private static final int RCM_PACKET_LEN = 26;
+ private static final int RCM_DATA_OFFSET = 10;
+
+ /***************************************************************************/
+ /***************************************************************************/
+ private static final int CMD_PREFIX_CODE = 0xAA55;
+ private static final int CMD_DATA_PREFIX_CODE = 0xA55A;
+ private static final int RCM_PREFIX_CODE = 0x55AA;
+ private static final int RCM_DATA_PREFIX_CODE = 0x5AA5;
+
+ /***************************************************************************
+ * System Code (0x0000 ~ 0x001F, 0x0000 : Reserved)
+ ***************************************************************************/
+ private static final short CMD_TEST_CONNECTION = 0x0001;
+ private static final short CMD_SET_PARAM = 0x0002;
+ private static final short CMD_GET_PARAM = 0x0003;
+ private static final short CMD_GET_DEVICE_INFO = 0x0004;
+ private static final short CMD_ENTER_ISPMODE = 0x0005;
+ private static final short CMD_SET_ID_NOTE = 0x0006;
+ private static final short CMD_GET_ID_NOTE = 0x0007;
+ private static final short CMD_SET_MODULE_SN = 0x0008;
+ private static final short CMD_GET_MODULE_SN = 0x0009;
+
+ /***************************************************************************
+ * Sensor Code (0x0020 ~ 0x003F)
+ ***************************************************************************/
+ private static final short CMD_GET_IMAGE = 0x0020;
+ private static final short CMD_FINGER_DETECT = 0x0021;
+ private static final short CMD_UP_IMAGE = 0x0022;
+ private static final short CMD_DOWN_IMAGE = 0x0023;
+ private static final short CMD_SLED_CTRL = 0x0024;
+
+ /***************************************************************************
+ * Template Code (0x0040 ~ 0x005F)
+ ***************************************************************************/
+ private static final short CMD_STORE_CHAR = 0x0040;
+ private static final short CMD_LOAD_CHAR = 0x0041;
+ private static final short CMD_UP_CHAR = 0x0042;
+ private static final short CMD_DOWN_CHAR = 0x0043;
+ private static final short CMD_DEL_CHAR = 0x0044;
+ private static final short CMD_GET_EMPTY_ID = 0x0045;
+ private static final short CMD_GET_STATUS = 0x0046;
+ private static final short CMD_GET_BROKEN_ID = 0x0047;
+ private static final short CMD_GET_ENROLL_COUNT = 0x0048;
+
+ /***************************************************************************
+ * FingerPrint Alagorithm Code (0x0060 ~ 0x007F)
+ ***************************************************************************/
+ private static final short CMD_GENERATE = 0x0060;
+ private static final short CMD_MERGE = 0x0061;
+ private static final short CMD_MATCH = 0x0062;
+ private static final short CMD_SEARCH = 0x0063;
+ private static final short CMD_VERIFY = 0x0064;
+
+ /***************************************************************************
+ * Unknown Command
+ ***************************************************************************/
+ private static final short RCM_INCORRECT_COMMAND = 0x00FF;
+
+ /***************************************************************************
+ * Error Code
+ ***************************************************************************/
+ public static final int ERR_SUCCESS = 0;
+ public static final int ERR_FAIL = 1;
+ public static final int ERR_CONNECTION = 2;
+ public static final int ERR_VERIFY = 0x10;
+ public static final int ERR_IDENTIFY = 0x11;
+ public static final int ERR_TMPL_EMPTY = 0x12;
+ public static final int ERR_TMPL_NOT_EMPTY = 0x13;
+ public static final int ERR_ALL_TMPL_EMPTY = 0x14;
+ public static final int ERR_EMPTY_ID_NOEXIST = 0x15;
+ public static final int ERR_BROKEN_ID_NOEXIST = 0x16;
+ public static final int ERR_INVALID_TMPL_DATA = 0x17;
+ public static final int ERR_DUPLICATION_ID = 0x18;
+ public static final int ERR_BAD_QUALITY = 0x19;
+ public static final int ERR_MERGE_FAIL = 0x1A;
+ public static final int ERR_NOT_AUTHORIZED = 0x1B;
+ public static final int ERR_MEMORY = 0x1C;
+ public static final int ERR_INVALID_TMPL_NO = 0x1D;
+ public static final int ERR_INVALID_PARAM = 0x22;
+ public static final int ERR_GEN_COUNT = 0x25;
+ public static final int ERR_INVALID_BUFFER_ID = 0x26;
+ public static final int ERR_INVALID_OPERATION_MODE = 0x27;
+ public static final int ERR_FP_NOT_DETECTED = 0x28;
+
+ /***************************************************************************
+ * Parameter Index
+ ***************************************************************************/
+ public static final int DP_DEVICE_ID = 0;
+ public static final int DP_SECURITY_LEVEL = 1;
+ public static final int DP_DUP_CHECK = 2;
+ public static final int DP_BAUDRATE = 3;
+ public static final int DP_AUTO_LEARN = 4;
+
+ /***************************************************************************
+ * Device ID, Security Level
+ ***************************************************************************/
+ public static final int MIN_DEVICE_ID = 1;
+ public static final int MAX_DEVICE_ID = 255;
+ public static final int MIN_SECURITY_LEVEL = 1;
+ public static final int MAX_SECURITY_LEVEL = 5;
+
+ public static final int GD_TEMPLATE_NOT_EMPTY = 0x01;
+ public static final int GD_TEMPLATE_EMPTY = 0x00;
+
+ //--------------- For Usb Communication ------------//
+ public int m_nPacketSize;
+ public byte m_bySrcDeviceID = 1, m_byDstDeviceID = 1;
+ public byte[] m_abyPacket = new byte[64 * 1024];
+ public byte[] m_abyPacket2 = new byte[64 * 1024];
+ //--------------------------------------------------//
+
+ private final Context mApplicationContext;
+ private final Activity m_parentAcitivity;
+ private static final int VID = 0x2009;
+ private static final int PID = 0x7638;
+
+ private final UsbController m_usbBase;
+
+ // Serial Port
+ private final DispQueueThread DispQueue;
+ private final SerialControl m_SerialPort;
+
+ // uart variables
+ public byte[] m_pWriteBuffer;
+ public byte[] m_pReadBuffer;
+ public byte[] m_pUARTReadBuf;
+ public int m_nUARTReadPos = 0;
+ public int m_nUARTReceivePos = 0;
+
+ // Connection
+ public byte m_nConnected; // 0 : Not Connected, 1 : ttyUART, 2 : USB
+
+ public DevComm(Activity parentActivity, IUsbConnState usbConnState){
+ m_parentAcitivity = parentActivity;
+ mApplicationContext = parentActivity.getApplicationContext();
+
+ // usb init
+ m_usbBase = new UsbController(parentActivity, usbConnState, VID, PID);
+
+ // init variables
+ m_nConnected = 0;
+ m_nUARTReadPos = 0;
+ m_nUARTReceivePos = 0;
+ m_pWriteBuffer = new byte[DevComm.MAX_DATA_LEN];
+ m_pReadBuffer = new byte[DevComm.MAX_DATA_LEN];
+ m_pUARTReadBuf = new byte[DevComm.UART_MAX_BUF_SIZE];
+
+ // uart thread initialize
+ DispQueue = new DispQueueThread();
+ DispQueue.start();
+ m_SerialPort = new SerialControl();
+ }
+
+ public boolean IsInit(){
+ if (m_nConnected == 0)
+ return false;
+ else if (m_nConnected == 1)
+ return true;
+ else if (m_nConnected == 2)
+ return m_usbBase.IsInit();
+
+ return false;
+ }
+
+ public boolean OpenComm(String p_szDevice, int p_nBaudrate){
+ if (m_nConnected != 0)
+ return false;
+
+ if (p_szDevice.equals("USB")) // usb mode
+ {
+ if (!m_usbBase.IsInit())
+ m_usbBase.init();
+ if (!m_usbBase.IsInit())
+ return false;
+ m_nConnected = 2;
+ }
+ else // tty uart mode
+ {
+ m_SerialPort.setPort(p_szDevice);
+ m_SerialPort.setBaudRate(p_nBaudrate);
+ try
+ {
+ m_SerialPort.open();
+ } catch (SecurityException e) {
+ Toast.makeText(mApplicationContext, "Open ttyUART device failed!", Toast.LENGTH_SHORT).show();
+ return false;
+ } catch (IOException e) {
+ Toast.makeText(mApplicationContext, "Open ttyUART device failed!", Toast.LENGTH_SHORT).show();
+ return false;
+ } catch (InvalidParameterException e) {
+ Toast.makeText(mApplicationContext, "Open ttyUART device failed!", Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ m_nConnected = 1;
+ }
+
+ return true;
+ }
+
+ public boolean CloseComm(){
+ if (m_nConnected == 0) {
+ return false;
+ }
+ else if (m_nConnected == 1) { // tty uart mode
+ m_SerialPort.stopSend();
+ m_SerialPort.close();
+ }
+ else { // usb mode
+ m_usbBase.uninit();
+ }
+
+ m_nConnected = 0;
+ return true;
+ }
+
+ /************************************************************************/
+ /************************************************************************/
+ int Run_TestConnection()
+ {
+ boolean w_bRet;
+
+ InitCmdPacket(CMD_TEST_CONNECTION, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, (short)0);
+
+ w_bRet = Send_Command(CMD_TEST_CONNECTION);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SetParam(int p_nParamIndex, int p_nParamValue)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[5];
+
+ w_abyData[0] = (byte)p_nParamIndex;
+
+ //memcpy(&w_abyData[1], &p_nParamValue, 4);
+ w_abyData[1] = (byte)(p_nParamValue & 0x000000ff);
+ w_abyData[2] = (byte)((p_nParamValue & 0x0000ff00) >> 8);
+ w_abyData[3] = (byte)((p_nParamValue & 0x00ff0000) >> 16);
+ w_abyData[4] = (byte)((p_nParamValue & 0xff000000) >> 24);
+
+ InitCmdPacket(CMD_SET_PARAM, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, (short)5);
+
+ w_bRet = Send_Command(CMD_SET_PARAM);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetParam(int p_nParamIndex, int[] p_pnParamValue)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[1];
+
+ w_abyData[0] = (byte)p_nParamIndex;
+
+ InitCmdPacket(CMD_GET_PARAM, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, (short)1);
+
+ w_bRet = Send_Command(CMD_GET_PARAM);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //memcpy(p_pnParamValue, g_pRcmPacket->m_abyData, 4);
+ p_pnParamValue[0] = ((m_abyPacket[RCM_DATA_OFFSET+3] << 24) & 0xFF000000) |
+ ((m_abyPacket[RCM_DATA_OFFSET+2] << 16) & 0x00FF0000) |
+ ((m_abyPacket[RCM_DATA_OFFSET+1] << 8) & 0x0000FF00) |
+ (m_abyPacket[RCM_DATA_OFFSET] & 0x000000FF);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetDeviceInfo(String[] p_szDevInfo)
+ {
+ int w_nDevInfoLen;
+ boolean w_bRet;
+ String w_strTmp;
+ byte[] w_szDevInfo;
+
+ InitCmdPacket(CMD_GET_DEVICE_INFO, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ w_bRet = Send_Command(CMD_GET_DEVICE_INFO);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_nDevInfoLen = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ w_bRet = Receive_DataPacket(CMD_GET_DEVICE_INFO);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if ( GetRetCode() != ERR_SUCCESS )
+ return GetRetCode();
+
+ //memcpy(p_szDevInfo, g_pRcmPacket->m_abyData, w_wDevInfoLen);
+ w_szDevInfo = new byte[w_nDevInfoLen];
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, w_szDevInfo, 0, w_nDevInfoLen);
+ w_strTmp = new String(w_szDevInfo);
+ p_szDevInfo[0] = w_strTmp;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SetIDNote(int p_nTmplNo, String p_pstrNote)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[ID_NOTE_SIZE+2];
+ byte[] w_abyData2 = new byte[2];
+ byte[] w_abyNoteBuf = p_pstrNote.getBytes();
+
+ //. Assemble command packet
+ w_abyData2[0] = LOBYTE((short)(ID_NOTE_SIZE + 2));
+ w_abyData2[1] = HIBYTE((short)(ID_NOTE_SIZE + 2));
+
+ InitCmdPacket(CMD_SET_ID_NOTE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData2, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_SET_ID_NOTE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if( GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //. Assemble data packet
+ memset(w_abyData, (byte)0, ID_NOTE_SIZE+2);
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ System.arraycopy(w_abyNoteBuf, 0, w_abyData, 2, w_abyNoteBuf.length);
+
+ InitCmdDataPacket(CMD_SET_ID_NOTE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, ID_NOTE_SIZE+2);
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_SET_ID_NOTE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetIDNote(int p_nTmplNo, String[] p_pstrNote)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[2];
+ String w_strTmp;
+
+ //. Assemble command packet
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ InitCmdPacket(CMD_GET_ID_NOTE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_GET_ID_NOTE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_bRet = Receive_DataPacket(CMD_GET_ID_NOTE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //memset(m_abyPacket2, (byte)0, ID_NOTE_SIZE+1);
+ memset(m_abyPacket2, (byte)0, 512);
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, m_abyPacket2, 0, ID_NOTE_SIZE);
+
+ w_strTmp = new String(m_abyPacket2);
+ p_pstrNote[0] = w_strTmp;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SetModuleSN(String p_pstrModuleSN)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = p_pstrModuleSN.getBytes();
+ byte[] w_abyModuleSN = new byte[MODULE_SN_LEN];
+ byte[] w_abyData2 = new byte[2];
+
+ memset(w_abyModuleSN, (byte)0, MODULE_SN_LEN);
+ System.arraycopy(w_abyData, 0, w_abyModuleSN, 0, w_abyData.length);
+
+ //. Assemble command packet
+ w_abyData2[0] = LOBYTE((short)(MODULE_SN_LEN));
+ w_abyData2[1] = HIBYTE((short)(MODULE_SN_LEN));
+
+ InitCmdPacket(CMD_SET_MODULE_SN, m_bySrcDeviceID, m_byDstDeviceID, w_abyData2, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_SET_MODULE_SN);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if( GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //. Assemble data packet
+ InitCmdDataPacket(CMD_SET_MODULE_SN, m_bySrcDeviceID, m_byDstDeviceID, w_abyModuleSN, MODULE_SN_LEN);
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_SET_MODULE_SN);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetModuleSN(String[] p_pstrModuleSN)
+ {
+ boolean w_bRet = false;
+ String w_strTmp;
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_MODULE_SN, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_GET_MODULE_SN);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_bRet = Receive_DataPacket(CMD_GET_MODULE_SN);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ //memset(m_abyPacket2, (byte)0, MODULE_SN_LEN+1);
+ memset(m_abyPacket2, (byte)0, 512);
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, m_abyPacket2, 0, MODULE_SN_LEN);
+
+ w_strTmp = new String(m_abyPacket2);
+ p_pstrModuleSN[0] = w_strTmp;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetImage()
+ {
+ boolean w_bRet;
+
+ InitCmdPacket(CMD_GET_IMAGE, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ w_bRet = Send_Command(CMD_GET_IMAGE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_FingerDetect(int[] p_pnDetectResult)
+ {
+ boolean w_bRet;
+
+ InitCmdPacket(CMD_FINGER_DETECT, m_bySrcDeviceID, m_byDstDeviceID, m_abyPacket2, 0);
+
+ w_bRet = Send_Command(CMD_FINGER_DETECT);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnDetectResult[0] = m_abyPacket[RCM_DATA_OFFSET];
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_UpImage(int p_nType, byte[] p_pFpData, int[] p_pnImgWidth, int[] p_pnImgHeight)
+ {
+ int i, n, r, w, h, size;
+ boolean w_bRet;
+ byte[] w_abyData = new byte[1];
+
+ w_abyData[0] = (byte)p_nType;
+
+ InitCmdPacket(CMD_UP_IMAGE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 1);
+
+ w_bRet = Send_Command(CMD_UP_IMAGE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+ h = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET+2], m_abyPacket[RCM_DATA_OFFSET+3]);
+
+ size = w * h;
+ n = size / IMAGE_DATA_UNIT;
+ r = size % IMAGE_DATA_UNIT;
+
+ if (m_nConnected == 1) {
+ for (i=0; i 0)
+ {
+ w_bRet = Receive_DataPacket(CMD_UP_IMAGE);
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET + 2, p_pFpData, i * IMAGE_DATA_UNIT, r);
+ }
+ }
+ else if (m_nConnected == 2) {
+ w_bRet = USB_ReceiveImage(p_pFpData, w * h);
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ }
+ else {
+ return ERR_CONNECTION;
+ }
+
+ p_pnImgWidth[0] = w;
+ p_pnImgHeight[0] = h;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_DownImage(byte[] p_pData, int p_nWidth, int p_nHeight)
+ {
+ /*
+ int i, n, r, w, h;
+ boolean w_bRet;
+ BYTE w_abyData[840];
+
+ w = p_nWidth;
+ h = p_nHeight;
+
+ w_abyData[0] = LOBYTE(p_nWidth);
+ w_abyData[1] = HIBYTE(p_nWidth);
+ w_abyData[2] = LOBYTE(p_nHeight);
+ w_abyData[3] = HIBYTE(p_nHeight);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_DOWN_IMAGE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ Send_Command(CMD_DOWN_IMAGE, w_bRet, m_bySrcDeviceID, m_byDstDeviceID);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ n = (w*h)/DOWN_IMAGE_DATA_UINT;
+ r = (w*h)%DOWN_IMAGE_DATA_UINT;
+
+ w_bRet = USB_DownImage(m_hUsbHandle, p_pData, p_nWidth*p_nHeight);
+
+ if(w_bRet == false)
+ return ERR_CONNECTION;
+ */
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_SLEDControl(int p_nState)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[2];
+
+ w_abyData[0] = LOBYTE((short)p_nState);
+ w_abyData[1] = HIBYTE((short)p_nState);
+
+ InitCmdPacket(CMD_SLED_CTRL, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ w_bRet = Send_Command(CMD_SLED_CTRL);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_StoreChar(int p_nTmplNo, int p_nRamBufferID, int[] p_pnDupTmplNo)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID);
+
+ InitCmdPacket(CMD_STORE_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_STORE_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ {
+ if (GetRetCode() == ERR_DUPLICATION_ID)
+ p_pnDupTmplNo[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ return GetRetCode();
+ }
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_LoadChar(int p_nTmplNo, int p_nRamBufferID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID);
+
+ InitCmdPacket(CMD_LOAD_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_LOAD_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_UpChar(int p_nRamBufferID, byte[] p_pbyTemplate, int[] p_nSize)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[2];
+ short w_nTemplateSize = 0;
+ int w_nRemainSize = 0;
+
+ //. Assemble command packet
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ InitCmdPacket(CMD_UP_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_UP_CHAR);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ w_nTemplateSize = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ if (w_nTemplateSize < CHAR_SPLIT_THR) {
+ w_bRet = Receive_DataPacket(CMD_UP_CHAR);
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+ //memcpy(p_pbyTemplate, &g_pRcmPacket->m_abyData[0], GD_RECORD_SIZE);
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, p_pbyTemplate, 0, w_nTemplateSize);
+ }
+ else {
+ w_nRemainSize = w_nTemplateSize;
+ while (w_nRemainSize > 0) {
+ w_bRet = Receive_DataPacket(CMD_UP_CHAR);
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+ if (w_nRemainSize > CHAR_SPLIT_UNIT) {
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, p_pbyTemplate, w_nTemplateSize - w_nRemainSize, CHAR_SPLIT_UNIT);
+ w_nRemainSize -= CHAR_SPLIT_UNIT;
+ }
+ else {
+ System.arraycopy(m_abyPacket, RCM_DATA_OFFSET, p_pbyTemplate, w_nTemplateSize - w_nRemainSize, w_nRemainSize);
+ w_nRemainSize -= 0;
+ }
+ }
+ }
+
+ p_nSize[0] = w_nTemplateSize;
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_DownChar(int p_nRamBufferID, byte[] p_pbyTemplate, int p_nSize)
+ {
+ boolean w_bRet = false;
+ byte[] w_abyData = new byte[MAX_DATA_LEN+2];
+ byte[] w_abyData2 = new byte[2];
+ int w_nRemainSize = 0;
+ int i;
+
+ //. Assemble command packet
+ if (p_nSize < CHAR_SPLIT_THR) {
+ w_abyData2[0] = LOBYTE((short)(p_nSize + 2));
+ w_abyData2[1] = HIBYTE((short)(p_nSize + 2));
+ }
+ else {
+ w_abyData2[0] = LOBYTE((short)(p_nSize + 4));
+ w_abyData2[1] = HIBYTE((short)(p_nSize + 4));
+ }
+
+ InitCmdPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData2, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_DOWN_CHAR);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if( GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ SystemClock.sleep(10);
+
+ //. Assemble data packet
+ if (p_nSize < CHAR_SPLIT_THR) {
+ w_abyData[0] = LOBYTE((short) p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short) p_nRamBufferID);
+ //memcpy(&w_abyData[2], p_pbyTemplate, GD_RECORD_SIZE);
+ System.arraycopy(p_pbyTemplate, 0, w_abyData, 2, p_nSize);
+
+ InitCmdDataPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, p_nSize + 2);
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_DOWN_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+ }
+ else {
+ w_nRemainSize = p_nSize;
+ i = 0;
+ while (w_nRemainSize > 0) {
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ w_abyData[2] = LOBYTE((short)i);
+ w_abyData[3] = HIBYTE((short)i);
+ if (w_nRemainSize > CHAR_SPLIT_UNIT) {
+ System.arraycopy(p_pbyTemplate, i * CHAR_SPLIT_UNIT, w_abyData, 4, CHAR_SPLIT_UNIT);
+ InitCmdDataPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, CHAR_SPLIT_UNIT + 4);
+ w_nRemainSize -= CHAR_SPLIT_UNIT;
+ }
+ else {
+ System.arraycopy(p_pbyTemplate, i * CHAR_SPLIT_UNIT, w_abyData, 4, w_nRemainSize);
+ InitCmdDataPacket(CMD_DOWN_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, w_nRemainSize + 4);
+ w_nRemainSize -= 0;
+ }
+
+ //. Send data packet to target
+ w_bRet = Send_DataPacket(CMD_DOWN_CHAR);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ i++;
+ }
+ }
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_DelChar(int p_nSTmplNo, int p_nETmplNo)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_DEL_CHAR, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_DEL_CHAR);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetEmptyID(int p_nSTmplNo, int p_nETmplNo, int[] p_pnEmptyID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_EMPTY_ID, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_GET_EMPTY_ID);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if ( GetRetCode() != ERR_SUCCESS )
+ return GetRetCode();
+
+ p_pnEmptyID[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetStatus(int p_nTmplNo, int[] p_pnStatus)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[2];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+
+ InitCmdPacket(CMD_GET_STATUS, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ w_bRet = Send_Command(CMD_GET_STATUS);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if ( GetRetCode() != ERR_SUCCESS )
+ return GetRetCode();
+
+ p_pnStatus[0] = m_abyPacket[RCM_DATA_OFFSET];
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetBrokenID(int p_nSTmplNo, int p_nETmplNo, int[] p_pnCount, int[] p_pnFirstID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_BROKEN_ID, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_GET_BROKEN_ID);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ if (GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnCount[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+ p_pnFirstID[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET+2], m_abyPacket[RCM_DATA_OFFSET+3]);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_GetEnrollCount(int p_nSTmplNo, int p_nETmplNo, int[] p_pnEnrollCount)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nSTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nSTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nETmplNo);
+ w_abyData[3] = HIBYTE((short)p_nETmplNo);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_GET_ENROLL_COUNT, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_GET_ENROLL_COUNT);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if(GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnEnrollCount[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+
+ return ERR_SUCCESS;
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Generate(int p_nRamBufferID)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[2];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+
+ InitCmdPacket(CMD_GENERATE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 2);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_GENERATE);
+
+ if(!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Merge(int p_nRamBufferID, int p_nMergeCount)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[3];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ w_abyData[2] = (byte)p_nMergeCount;
+
+ InitCmdPacket(CMD_MERGE, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 3);
+
+ w_bRet = Send_Command(CMD_MERGE);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Match(int p_nRamBufferID0, int p_nRamBufferID1)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID0);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID0);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID1);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID1);
+
+ InitCmdPacket(CMD_MATCH, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_MATCH);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Search(int p_nRamBufferID, int p_nStartID, int p_nSearchCount, int[] p_pnTmplNo, int[] p_pnLearnResult)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[6];
+
+ w_abyData[0] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[1] = HIBYTE((short)p_nRamBufferID);
+ w_abyData[2] = LOBYTE((short)p_nStartID);
+ w_abyData[3] = HIBYTE((short)p_nStartID);
+ w_abyData[4] = LOBYTE((short)p_nSearchCount);
+ w_abyData[5] = HIBYTE((short)p_nSearchCount);
+
+ InitCmdPacket(CMD_SEARCH, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 6);
+
+ //. Send command packet to target
+ w_bRet = Send_Command(CMD_SEARCH);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ if(GetRetCode() != ERR_SUCCESS)
+ return GetRetCode();
+
+ p_pnTmplNo[0] = MAKEWORD(m_abyPacket[RCM_DATA_OFFSET], m_abyPacket[RCM_DATA_OFFSET+1]);
+ p_pnLearnResult[0] = m_abyPacket[RCM_DATA_OFFSET+2];
+
+ return GetRetCode();
+ }
+ /************************************************************************/
+ /************************************************************************/
+ int Run_Verify(int p_nTmplNo, int p_nRamBufferID, int[] p_pnLearnResult)
+ {
+ boolean w_bRet;
+ byte[] w_abyData = new byte[4];
+
+ w_abyData[0] = LOBYTE((short)p_nTmplNo);
+ w_abyData[1] = HIBYTE((short)p_nTmplNo);
+ w_abyData[2] = LOBYTE((short)p_nRamBufferID);
+ w_abyData[3] = HIBYTE((short)p_nRamBufferID);
+
+ //. Assemble command packet
+ InitCmdPacket(CMD_VERIFY, m_bySrcDeviceID, m_byDstDeviceID, w_abyData, 4);
+
+ w_bRet = Send_Command(CMD_VERIFY);
+
+ if (!w_bRet)
+ return ERR_CONNECTION;
+
+ p_pnLearnResult[0] = m_abyPacket[RCM_DATA_OFFSET+2];
+
+ return GetRetCode();
+ }
+
+ public boolean GetDeviceInformation(String[] deviceInfo)
+ {
+ int[] w_nRecvLen = new int[1];
+ byte[] w_abyPCCmd = new byte[6];
+ byte[] w_abyData = new byte[32];
+
+ String w_strTmp;
+ boolean w_bRet;
+
+ Arrays.fill(w_abyPCCmd, (byte) 0);
+
+ w_abyPCCmd[2] = 0x04;
+
+ w_bRet = SendPackage(w_abyPCCmd, w_abyData);
+
+ //Toast.makeText(mApplicationContext, "GetDeviceInformation, SendPackage ret = " + w_bRet, Toast.LENGTH_SHORT).show();
+
+ if (!w_bRet)
+ {
+ return false;
+ }
+
+ w_bRet = RecvPackage(w_abyData, w_nRecvLen);
+
+ //Toast.makeText(mApplicationContext, "GetDeviceInformation, RecvPackage : " + w_bRet, Toast.LENGTH_SHORT).show();
+
+ if (!w_bRet)
+ {
+ return false;
+ }
+
+ w_strTmp = new String(w_abyData);
+ deviceInfo[0] = w_strTmp;
+
+ //Toast.makeText(mApplicationContext, "GetDeviceInformation, Recv Data : " + w_strTmp, Toast.LENGTH_SHORT).show();
+
+ return true;
+ }
+
+
+
+ private boolean SendPackage(byte[] pPCCmd, byte[] pData)
+ {
+ int nDataLen;
+
+ pPCCmd[0] = (byte)0xEF;
+ pPCCmd[1] = 0x01;
+
+ nDataLen = ((pPCCmd[5] << 8) & 0x0000FF00) | (pPCCmd[4] & 0x000000FF);
+
+ return m_usbBase.UsbSCSIWrite(pPCCmd, 6, pData, nDataLen, 5000);
+ }
+
+ private boolean RecvPackage(byte[] pData, int[] pLevRen)
+ {
+ int w_nLen;
+ byte[] w_abyPCCmd = new byte[6];
+ byte[] w_abyRespond = new byte[4];
+ boolean w_bRet;
+
+ w_abyPCCmd[0] = (byte)0xEF;
+ w_abyPCCmd[1] = 0x02;
+ w_abyPCCmd[2] = 0;
+ w_abyPCCmd[3] = 0;
+ w_abyPCCmd[4] = 0;
+ w_abyPCCmd[5] = 0;
+
+ // receive status
+ w_bRet = m_usbBase.UsbSCSIRead(w_abyPCCmd, 6, w_abyRespond, 4, 5000);
+
+ if (!w_bRet)
+ return false;
+
+ // receive data
+ //w_nLen = (int)((w_abyRespond[3] << 8) | w_abyRespond[2]);
+ w_nLen = ((w_abyRespond[3] << 8) & 0x0000FF00) | (w_abyRespond[2] & 0x000000FF);
+
+ if (w_nLen > 0)
+ {
+ //w_nTime = SystemClock.elapsedRealtime();
+
+ w_abyPCCmd[1] = 0x03;
+ w_bRet = m_usbBase.UsbSCSIRead(w_abyPCCmd, 6, pData, w_nLen, 5000);
+
+ //w_nTime = SystemClock.elapsedRealtime() - w_nTime;
+
+ if (!w_bRet)
+ return false;
+
+ pLevRen[0] = w_nLen;
+ }
+
+ return true;
+ }
+
+ /***************************************************************************
+ * Get Return Code
+ ***************************************************************************/
+ private short GetRetCode()
+ {
+ return (short)(((m_abyPacket[9] << 8) & 0x0000FF00) | (m_abyPacket[8] & 0x000000FF));
+ }
+
+ /***************************************************************************
+ * Get Data Length
+ ***************************************************************************/
+ private short GetDataLen()
+ {
+ return (short)(((m_abyPacket[7] << 8) & 0x0000FF00) | (m_abyPacket[6] & 0x000000FF));
+ }
+
+ /***************************************************************************
+ * Set Data Length
+ ***************************************************************************/
+ private void SetDataLen(short p_wDataLen)
+ {
+ m_abyPacket[6] = (byte)(p_wDataLen & 0xFF);
+ m_abyPacket[7] = (byte)(((p_wDataLen & 0xFF00) >> 8) & 0xFF);
+ }
+
+ /***************************************************************************
+ * Set Command Data
+ ***************************************************************************/
+ private void SetCmdData(short p_wData, boolean p_bFirst)
+ {
+ if (p_bFirst)
+ {
+ m_abyPacket[8] = (byte)(p_wData & 0xFF);
+ m_abyPacket[9] = (byte)(((p_wData & 0xFF00) >> 8) & 0xFF);
+ }
+ else
+ {
+ m_abyPacket[10] = (byte)(p_wData & 0xFF);
+ m_abyPacket[11] = (byte)(((p_wData & 0xFF00) >> 8) & 0xFF);
+ }
+ }
+
+ /***************************************************************************
+ * Get Command Data
+ ***************************************************************************/
+ private short GetCmdData(boolean p_bFirst)
+ {
+ if (p_bFirst)
+ {
+ return (short)(((m_abyPacket[9] << 8) & 0x0000FF00) | (m_abyPacket[8] & 0x000000FF));
+ }
+ else
+ {
+ return (short)(((m_abyPacket[11] << 8) & 0x0000FF00) | (m_abyPacket[10] & 0x000000FF));
+ }
+ }
+
+ /***************************************************************************
+ * Get 2bytes packet checksum(pDataPkt[0] + pDataPkt[1] + ....)
+ ***************************************************************************/
+ private short CalcChkSumOfPkt(byte[] pDataPkt, int nSize)
+ {
+ int i, nChkSum = 0;
+
+ for(i=0;im_wPrefix = CMD_PREFIX_CODE;
+ m_abyPacket[0] = (byte)(CMD_PREFIX_CODE & 0xFF);
+ m_abyPacket[1] = (byte)((CMD_PREFIX_CODE >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_bySrcDeviceID = p_bySrcDeviceID;
+ m_abyPacket[2] = bySrcDeviceID;
+
+ //g_pCmdPacket->m_byDstDeviceID = p_byDstDeviceID;
+ m_abyPacket[3] = byDstDeviceID;
+
+ //g_pCmdPacket->m_wCMDCode = p_wCMDCode;
+ m_abyPacket[4] = (byte)(wCMDCode & 0xFF);
+ m_abyPacket[5] = (byte)((wCMDCode >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_wDataLen = p_wDataLen;
+ m_abyPacket[6] = (byte)(nDataLen & 0xFF);
+ m_abyPacket[7] = (byte)((nDataLen >> 8) & 0xFF);
+
+ if (nDataLen > 0)
+ //memcpy(g_pCmdPacket->m_abyData, p_pbyData, wDataLen);
+ System.arraycopy(pbyData, 0, m_abyPacket, 8, nDataLen);
+
+ w_wCheckSum = CalcChkSumOfPkt(m_abyPacket, CMD_PACKET_LEN-2);
+
+ //g_pCmdPacket->m_wCheckSum = w_wCheckSum;
+ m_abyPacket[24] = (byte)(w_wCheckSum & 0xFF);
+ m_abyPacket[25] = (byte)((w_wCheckSum >> 8) & 0xFF);
+
+ m_nPacketSize = CMD_PACKET_LEN;
+ }
+ /***************************************************************************
+ * Make Data Packet
+ ***************************************************************************/
+ void InitCmdDataPacket(short wCMDCode, byte bySrcDeviceID, byte byDstDeviceID, byte[] pbyData, int nDataLen)
+ {
+ short w_wCheckSum;
+
+ //g_pCmdPacket->m_wPrefix = CMD_DATA_PREFIX_CODE;
+ m_abyPacket[0] = (byte)(CMD_DATA_PREFIX_CODE & 0xFF);
+ m_abyPacket[1] = (byte)((CMD_DATA_PREFIX_CODE >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_bySrcDeviceID = p_bySrcDeviceID;
+ m_abyPacket[2] = bySrcDeviceID;
+
+ //g_pCmdPacket->m_byDstDeviceID = p_byDstDeviceID;
+ m_abyPacket[3] = byDstDeviceID;
+
+ //g_pCmdPacket->m_wCMDCode = p_wCMDCode;
+ m_abyPacket[4] = (byte)(wCMDCode & 0xFF);
+ m_abyPacket[5] = (byte)((wCMDCode >> 8) & 0xFF);
+
+ //g_pCmdPacket->m_wDataLen = p_wDataLen;
+ m_abyPacket[6] = (byte)(nDataLen & 0xFF);
+ m_abyPacket[7] = (byte)((nDataLen >> 8) & 0xFF);
+
+ //memcpy(&g_pCmdPacket->m_abyData[0], p_pbyData, p_wDataLen);
+ System.arraycopy(pbyData, 0, m_abyPacket, 8, nDataLen);
+
+ //. Set checksum
+ w_wCheckSum = CalcChkSumOfPkt(m_abyPacket, nDataLen + 8);
+
+ m_abyPacket[nDataLen+8] = (byte)(w_wCheckSum & 0xFF);
+ m_abyPacket[nDataLen+9] = (byte)((w_wCheckSum >> 8) & 0xFF);
+
+ m_nPacketSize = nDataLen + 10;
+ }
+ /***************************************************************************
+ * Check Packet
+ ***************************************************************************/
+ boolean CheckReceive( byte[] pbyPacket, int nPacketLen, short wPrefix, short wCMDCode )
+ {
+ short w_wCalcCheckSum, w_wCheckSum, w_wTmp;
+
+ //. Check prefix code
+ w_wTmp = (short)(((pbyPacket[1] << 8) & 0x0000FF00) | (pbyPacket[0] & 0x000000FF));
+
+ if (wPrefix != w_wTmp)
+ {
+ return false;
+ }
+
+ //. Check checksum
+ w_wCheckSum = (short)(((pbyPacket[nPacketLen-1] << 8) & 0x0000FF00) | (pbyPacket[nPacketLen-2] & 0x000000FF));
+
+ w_wCalcCheckSum = CalcChkSumOfPkt(pbyPacket, nPacketLen-2);
+
+ if (w_wCheckSum != w_wCalcCheckSum)
+ {
+ return false;
+ }
+
+ //. Check Command Code
+ w_wTmp = (short)(((pbyPacket[5] << 8) & 0x0000FF00) | (pbyPacket[4] & 0x000000FF));
+ return wCMDCode == w_wTmp;
+ }
+
+ //--------------------------- Send, Receive Communication Packet Functions ---------------------//
+ public boolean Send_Command(short p_wCmd)
+ {
+ if (m_nConnected == 1)
+ return UART_SendCommand(p_wCmd);
+ else if (m_nConnected == 2)
+ return USB_SendPacket(p_wCmd);
+ else
+ return false;
+ }
+
+ public boolean Send_DataPacket(short p_wCmd)
+ {
+ if (m_nConnected == 1)
+ return UART_SendDataPacket(p_wCmd);
+ else if (m_nConnected == 2)
+ return USB_SendDataPacket(p_wCmd);
+ else
+ return false;
+ }
+
+ public boolean Receive_DataPacket(short p_wCmd)
+ {
+ if (m_nConnected == 1)
+ return UART_ReceiveDataPacket(p_wCmd);
+ else if (m_nConnected == 2)
+ return USB_ReceiveDataPacket(p_wCmd);
+ else
+ return false;
+ }
+
+ //-------------------------------- USB Communication Functions --------------------------------//
+ private boolean USB_SendPacket(short wCMD)
+ {
+ byte[] btCDB = new byte[8];
+ boolean w_bRet;
+
+ Arrays.fill(btCDB, (byte)0);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x11; btCDB[4] = (byte)m_nPacketSize;
+
+ w_bRet = m_usbBase.UsbSCSIWrite(btCDB, 8, m_abyPacket, m_nPacketSize, SCSI_TIMEOUT);
+
+ if (!w_bRet)
+ {
+ return false;
+ }
+
+ return USB_ReceiveAck( wCMD );
+ }
+
+ private boolean USB_ReceiveAck(short wCMD)
+ {
+ int c, w_nLen, w_nReadCount = 0;
+ byte[] btCDB = new byte[8];
+ byte[] w_abyWaitPacket = new byte[CMD_PACKET_LEN];
+
+ Arrays.fill(btCDB, (byte)0);
+
+ //w_nReadCount = GetReadWaitTime(p_byCMD);
+
+ c = 0;
+ Arrays.fill(w_abyWaitPacket, (byte)0xAF);
+
+ do
+ {
+ Arrays.fill(m_abyPacket, (byte)0);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = (byte)0x12;
+
+ w_nLen = RCM_PACKET_LEN;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, m_abyPacket, w_nLen, SCSI_TIMEOUT))
+ {
+ return false;
+ }
+
+ SystemClock.sleep(COMM_SLEEP_TIME);
+
+ c++;
+
+ //if ( c > w_nReadCount)
+ //{
+ // return false;
+ //}
+ } while (memcmp(m_abyPacket, w_abyWaitPacket, CMD_PACKET_LEN));
+
+ m_nPacketSize = w_nLen;
+
+ return CheckReceive(m_abyPacket, m_nPacketSize, (short) RCM_PREFIX_CODE, wCMD);
+ }
+
+ boolean USB_ReceiveDataAck(short wCMD)
+ {
+ byte[] btCDB = new byte[8];
+ byte[] w_WaitPacket = new byte[10];
+ int w_nLen;
+
+ memset(btCDB, (byte)0, 8);
+ memset(w_WaitPacket, (byte)0xAF, 10);
+
+ do
+ {
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x15;
+ w_nLen = 8;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, m_abyPacket, w_nLen, SCSI_TIMEOUT))
+ {
+ return false;
+ }
+
+ SystemClock.sleep(COMM_SLEEP_TIME);
+
+ }while(memcmp(m_abyPacket, w_WaitPacket, 8));
+
+ //w_nLen = g_pRcmPacket->m_wDataLen + 2;
+ w_nLen = (short)(((m_abyPacket[7] << 8) & 0x0000FF00) | (m_abyPacket[6] & 0x000000FF)) + 2;
+
+ if (!USB_ReceiveRawData(m_abyPacket2, w_nLen))
+ {
+ return false;
+ }
+
+ System.arraycopy(m_abyPacket2, 0, m_abyPacket, 8, w_nLen);
+
+ m_nPacketSize = 8 + w_nLen;
+
+ return CheckReceive(m_abyPacket, m_nPacketSize, (short) RCM_DATA_PREFIX_CODE, wCMD);
+ }
+
+ boolean USB_SendDataPacket(short wCMD)
+ {
+ byte[] btCDB = new byte[8];
+
+ memset(btCDB, (byte)0, 8);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x13;
+
+ btCDB[4] = (byte)(m_nPacketSize & 0xFF);
+ btCDB[5] = (byte)((m_nPacketSize >> 8) & 0xFF);
+
+ if (!m_usbBase.UsbSCSIWrite(btCDB, 8, m_abyPacket, m_nPacketSize, SCSI_TIMEOUT ) )
+ return false;
+
+ return USB_ReceiveDataAck(wCMD);
+ }
+
+ boolean USB_ReceiveDataPacket(short wCMD)
+ {
+ return USB_ReceiveDataAck(wCMD);
+ }
+
+ boolean USB_ReceiveRawData(byte[] pBuffer, int nDataLen)
+ {
+ byte[] btCDB = new byte[8];
+
+ memset(btCDB, (byte)0, 8);
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x14;
+
+ return m_usbBase.UsbSCSIRead(btCDB, 8, pBuffer, nDataLen, SCSI_TIMEOUT);
+ }
+
+ boolean USB_ReceiveImage(byte[] p_pBuffer, int nDataLen )
+ {
+ byte[] btCDB = new byte[8];
+ byte[] w_WaitPacket = new byte[8];
+
+ memset( btCDB, (byte)0, 8 );
+ memset( w_WaitPacket, (byte)0xAF, 8 );
+
+ if (nDataLen < 1024*64)
+ {
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x16;
+
+ return m_usbBase.UsbSCSIRead(btCDB, 8, p_pBuffer, nDataLen, SCSI_TIMEOUT);
+ }
+ else if (nDataLen == 256*288)
+ {
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x16; btCDB[2] = 0x00;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, p_pBuffer, nDataLen/2, SCSI_TIMEOUT))
+ return false;
+
+ btCDB[0] = (byte)0xEF; btCDB[1] = 0x16; btCDB[2] = 0x01;
+
+ if (!m_usbBase.UsbSCSIRead(btCDB, 8, m_abyPacket2, nDataLen/2, SCSI_TIMEOUT ))
+ return false;
+
+ System.arraycopy(m_abyPacket2, 0, p_pBuffer, nDataLen/2, nDataLen/2);
+ }
+
+ return true;
+ }
+
+ //-------------------------------- UART Communication Functions --------------------------------//
+ public boolean UART_SendCommand(short p_wCmd)
+ {
+ int w_nResult = 0;
+ boolean w_bRet = false;
+ int w_nRetry = 0;
+
+ if (m_nConnected == 1)
+ {
+ byte[] w_pData = new byte[m_nPacketSize];
+ System.arraycopy(m_abyPacket, 0, w_pData, 0, m_nPacketSize);
+ m_SerialPort.send(w_pData, m_nPacketSize);
+ }
+
+// do {
+// w_bRet = UART_ReceiveAck(p_wCmd);
+// if (m_nUARTReceivePos == m_nUARTReadPos) {
+// if (w_bRet == true) {
+// break;
+// }
+// else {
+// if (w_nRetry > 0)
+// break;
+// else
+// w_nRetry += 1;
+// }
+// }
+// } while (w_bRet == false);
+ w_bRet = UART_ReceiveAck(p_wCmd);
+ return w_bRet;
+ }
+
+ public boolean UART_ReceiveAck(short p_wCmd)
+ {
+ if (!UART_ReadDataN(m_abyPacket, 0, CMD_PACKET_LEN))
+ return false;
+
+ return CheckReceive(m_abyPacket, CMD_PACKET_LEN, (short) RCM_PREFIX_CODE, p_wCmd);
+ }
+
+ public boolean UART_ReceiveDataAck(short p_wCmd)
+ {
+ if (!UART_ReadDataN(m_abyPacket, 0, 8))
+ return false;
+
+ if (!UART_ReadDataN(m_abyPacket, 8, GetDataLen() + 2))
+ return false;
+
+ return CheckReceive(m_abyPacket, GetDataLen() + 10, (short)RCM_DATA_PREFIX_CODE, p_wCmd);
+ }
+
+ public boolean UART_SendDataPacket(short p_wCmd)
+ {
+ int w_nSendCnt = 0;
+
+ if (m_nConnected == 1)
+ {
+ byte[] w_pData = new byte[m_nPacketSize];
+ System.arraycopy(m_abyPacket, 0, w_pData, 0, m_nPacketSize);
+ m_SerialPort.send(w_pData, m_nPacketSize);
+ }
+
+ return UART_ReceiveDataAck(p_wCmd);
+ }
+ /***************************************************************************/
+ /***************************************************************************/
+ public boolean UART_ReceiveDataPacket(short p_wCmd)
+ {
+ return UART_ReceiveDataAck(p_wCmd);
+ }
+ /***************************************************************************/
+ /***************************************************************************/
+ public boolean UART_ReceiveData(short p_wCmd, int p_nDataLen, byte[] p_pBuffer)
+ {
+ int w_nReceivedCnt;
+ int w_wPacketDataLen = 0;
+
+ for (w_nReceivedCnt = 0; w_nReceivedCnt < p_nDataLen; w_nReceivedCnt += w_wPacketDataLen)
+ {
+ w_wPacketDataLen = p_nDataLen - w_nReceivedCnt;
+ if (w_wPacketDataLen > MAX_DATA_LEN) w_wPacketDataLen = MAX_DATA_LEN;
+ if (!UART_ReceiveDataPacket(p_wCmd))
+ return false;
+ System.arraycopy(m_abyPacket, 8, p_pBuffer, w_nReceivedCnt, GetDataLen() + 4);
+ }
+ return true;
+ }
+ /***************************************************************************/
+ /***************************************************************************/
+ boolean UART_ReadDataN(byte[] p_pData, int p_nStart, int p_nLen)
+ {
+ int w_nTotalRecvLen;
+ int w_nTmpLen;
+ int w_nStartPos = 0;
+ int w_nHeader;
+ boolean w_bFirstPacket = true;
+ int w_nReceivedLen = 0;
+
+ int wm_nUARTReceivePos = 0;
+ int wm_nUARTReadPos = 0;
+
+ long w_nEllapsedTime = 0;
+
+ w_nTotalRecvLen = 0;
+ w_nEllapsedTime = SystemClock.uptimeMillis();
+
+ while (w_nTotalRecvLen < p_nLen)
+ {
+ wm_nUARTReceivePos = m_nUARTReceivePos;
+ wm_nUARTReadPos = m_nUARTReadPos;
+
+ if ((wm_nUARTReceivePos <= wm_nUARTReadPos) && (wm_nUARTReadPos - wm_nUARTReceivePos < DevComm.MAX_DATA_LEN)) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ if (SystemClock.uptimeMillis() - w_nEllapsedTime > UART_READ_TIMEOUT)
+ return false;
+ continue;
+ }
+
+ if (wm_nUARTReceivePos < wm_nUARTReadPos) {
+ w_nReceivedLen = DevComm.UART_MAX_BUF_SIZE + wm_nUARTReceivePos - wm_nUARTReadPos;
+ System.arraycopy(m_pUARTReadBuf, wm_nUARTReadPos, m_abyPacket2, 0, DevComm.UART_MAX_BUF_SIZE - wm_nUARTReadPos);
+ System.arraycopy(m_pUARTReadBuf, 0, m_abyPacket2, DevComm.UART_MAX_BUF_SIZE - wm_nUARTReadPos, wm_nUARTReceivePos);
+ }
+ else {
+ w_nReceivedLen = wm_nUARTReceivePos - wm_nUARTReadPos;
+ System.arraycopy(m_pUARTReadBuf, wm_nUARTReadPos, m_abyPacket2, 0, w_nReceivedLen);
+ }
+
+ if (w_bFirstPacket && (p_nLen == 6) && (p_nStart == 0)) {
+ for (w_nStartPos = 0; w_nStartPos < w_nReceivedLen; w_nStartPos++) {
+ w_nHeader = MAKEWORD(m_abyPacket2[w_nStartPos], m_abyPacket2[w_nStartPos + 1]);
+ if ((w_nHeader == CMD_PREFIX_CODE) || (w_nHeader == RCM_PREFIX_CODE) ||
+ (w_nHeader == CMD_DATA_PREFIX_CODE) || (w_nHeader == RCM_DATA_PREFIX_CODE))
+ break;
+ }
+
+ m_nUARTReadPos += w_nStartPos;
+ w_nReceivedLen -= w_nStartPos;
+
+ w_bFirstPacket = false;
+ }
+ else {
+ w_nStartPos = 0;
+ }
+
+ if (p_nLen - w_nTotalRecvLen < w_nReceivedLen) {
+ w_nTmpLen = p_nLen - w_nTotalRecvLen;
+ }
+ else {
+ w_nTmpLen = w_nReceivedLen;
+ }
+
+ System.arraycopy(m_abyPacket2, w_nStartPos, p_pData, p_nStart + w_nTotalRecvLen, w_nTmpLen);
+ w_nTotalRecvLen += w_nTmpLen;
+ m_nUARTReadPos += w_nTmpLen;
+
+ if (m_nUARTReadPos >= DevComm.UART_MAX_BUF_SIZE)
+ m_nUARTReadPos -= DevComm.UART_MAX_BUF_SIZE;
+
+ w_nEllapsedTime = SystemClock.uptimeMillis();
+ }
+
+ return true;
+ }
+
+ private boolean memcmp(byte[] p1, byte[] p2, int nLen)
+ {
+ int i;
+
+ for (i=0; i> 8) & 0xFF);
+ }
+
+
+ // uart control classes ======================================================
+ private class SerialControl extends SerialHelper{
+
+ public SerialControl(){
+ }
+
+ @Override
+ protected void onDataReceived(final ComBean ComRecData)
+ {
+ int w_nProcLen = 0;
+
+// DispQueue.AddQueue(ComRecData);
+
+ // save to receive buffer
+ if (m_nUARTReceivePos + ComRecData.nSize > DevComm.UART_MAX_BUF_SIZE) {
+ w_nProcLen = DevComm.UART_MAX_BUF_SIZE - m_nUARTReceivePos;
+ System.arraycopy(ComRecData.bRec, 0, m_pUARTReadBuf, m_nUARTReceivePos, w_nProcLen);
+ System.arraycopy(ComRecData.bRec, w_nProcLen, m_pUARTReadBuf, 0, ComRecData.nSize - w_nProcLen);
+ m_nUARTReceivePos = ComRecData.nSize - w_nProcLen;
+ } else {
+ System.arraycopy(ComRecData.bRec, 0, m_pUARTReadBuf, m_nUARTReceivePos, ComRecData.nSize);
+ m_nUARTReceivePos += ComRecData.nSize;
+ }
+ }
+ }
+
+ private class DispQueueThread extends Thread{
+ private final Queue QueueList = new LinkedList();
+ @Override
+ public void run() {
+ super.run();
+// while(!isInterrupted()) {
+// int i;
+// i = 0;
+// while (m_bBufferHandle)
+// {
+// i++;
+// if (i > 10000)
+// break;
+// }
+// m_bBufferHandle = true;
+// while(true)
+// {
+// final ComBean ComData;
+// if ((ComData=QueueList.poll())==null)
+// break;
+//
+// Log.d("NOEM_DEBUG", String.format("DispQueueThread: ComData.nSize = %d, m_nUARTReadLen = %d",
+// ComData.nSize, m_nUARTReadLen));
+// System.arraycopy(ComData.bRec, 0, m_pUARTReadBuf, m_nUARTReadLen, ComData.nSize);
+// m_nUARTReadLen = m_nUARTReadLen + ComData.nSize;
+//// break;
+// }
+// m_bBufferHandle = false;
+// }
+ }
+
+ public synchronized void AddQueue(ComBean ComData){
+ QueueList.add(ComData);
+ }
+ }
+ // ! uart control classes ====================================================
+}
diff --git a/android/src/main/java/com/xiarui/zhiwen/IUsbConnState.java b/android/src/main/java/com/xiarui/zhiwen/IUsbConnState.java
new file mode 100644
index 0000000..aed8d82
--- /dev/null
+++ b/android/src/main/java/com/xiarui/zhiwen/IUsbConnState.java
@@ -0,0 +1,12 @@
+package com.xiarui.zhiwen;
+
+/**
+ * Created by KMS on 2016/8/23.
+ */
+public interface IUsbConnState {
+ void onUsbConnected();
+
+ void onUsbPermissionDenied();
+
+ void onDeviceNotFound();
+}
diff --git a/android/src/main/java/com/xiarui/zhiwen/UsbController.java b/android/src/main/java/com/xiarui/zhiwen/UsbController.java
new file mode 100644
index 0000000..12ada17
--- /dev/null
+++ b/android/src/main/java/com/xiarui/zhiwen/UsbController.java
@@ -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 devlist = mUsbManager.getDeviceList();
+ Iterator 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 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 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() + " >==<");
+ }
+}
diff --git a/android/src/main/java/com/xiarui/zhiwen/ZhiwenPlugin.java b/android/src/main/java/com/xiarui/zhiwen/ZhiwenPlugin.java
new file mode 100644
index 0000000..c67f95b
--- /dev/null
+++ b/android/src/main/java/com/xiarui/zhiwen/ZhiwenPlugin.java
@@ -0,0 +1,1001 @@
+package com.xiarui.zhiwen;
+
+import androidx.annotation.NonNull;
+
+import android.app.Activity;
+import android.widget.Toast;
+import android.util.Log;
+import android.os.Handler;
+import android.os.Looper;
+
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.embedding.engine.plugins.activity.ActivityAware;
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
+import io.flutter.plugin.common.MethodCall;
+import io.flutter.plugin.common.MethodChannel;
+import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
+import io.flutter.plugin.common.MethodChannel.Result;
+
+import android.os.SystemClock;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * 智纹指纹识别插件
+ * 提供指纹设备的连接、录入、验证、识别等功能
+ */
+public class ZhiwenPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, IUsbConnState {
+
+ // 常量定义
+ private static final String TAG = "ZhiwenPlugin";
+ private static final String CHANNEL_NAME = "zhiwen";
+ private static final int DEFAULT_MAX_FP_COUNT = 3000;
+ private static final int ENROLL_STEP_COUNT = 3;
+ private static final int IMAGE_BUFFER_SIZE = 1024 * 100;
+
+ // 响应状态码
+ private static final int RESPONSE_SUCCESS = 1;
+ private static final int RESPONSE_FAIL = -1;
+ private static final int RESPONSE_NOT_FOUND = 0;
+
+ /// Flutter与Android原生通信的MethodChannel
+ /// 用于注册插件到Flutter引擎,并在Activity分离时注销
+ private MethodChannel channel;
+
+ // 设备通信对象,使用static确保全局唯一
+ private static DevComm m_devComm;
+
+ // 设备连接参数
+ private int m_nBaudrate;
+ private String m_szDevice;
+ private final int maxFpCount = DEFAULT_MAX_FP_COUNT;
+
+ // Activity引用和线程管理
+ private Activity activity;
+ private final ExecutorService executorService = Executors.newCachedThreadPool();
+ private final Handler mainHandler = new Handler(Looper.getMainLooper());
+
+ /**
+ * 插件附加到Flutter引擎时的回调
+ * 初始化MethodChannel并设置方法调用处理器
+ */
+ @Override
+ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
+ channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), CHANNEL_NAME);
+ channel.setMethodCallHandler(this);
+ // 注意:这里不应该从ApplicationContext获取Activity,应该等待onAttachedToActivity回调
+ }
+
+ /**
+ * 处理来自Flutter的方法调用
+ * 根据方法名分发到对应的处理函数
+ */
+ @Override
+ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
+ try {
+ switch (call.method) {
+ case "getPlatformVersion":
+ result.success("Android " + android.os.Build.VERSION.RELEASE);
+ break;
+
+ case "openDevice":
+ String devicePath = call.argument("devicePath");
+ Integer baudRate = call.argument("baudRate");
+ if (devicePath == null || baudRate == null) {
+ result.error("INVALID_ARGUMENTS", "devicePath and baudRate are required", null);
+ return;
+ }
+ boolean success = openDevice(devicePath, baudRate);
+ result.success(success);
+ break;
+
+ case "closeDevice":
+ closeDevice();
+ result.success(true);
+ break;
+
+ case "enrollFingerprint":
+ Integer enrollUserId = call.argument("userId");
+ if (enrollUserId == null) {
+ result.error("INVALID_ARGUMENTS", "userId is required", null);
+ return;
+ }
+ enrollFingerprint(enrollUserId, result);
+ break;
+
+ case "verifyFingerprint":
+ Integer verifyUserId = call.argument("userId");
+ if (verifyUserId == null) {
+ result.error("INVALID_ARGUMENTS", "userId is required", null);
+ return;
+ }
+ verifyFingerprint(verifyUserId, result);
+ break;
+
+ case "deleteAllFingerprint":
+ Map deleteAllRes = deleteAllFingerprint();
+ result.success(deleteAllRes);
+ break;
+
+ case "identifyFingerprint":
+ identifyFingerprint(result);
+ break;
+
+ case "deleteOneFingerprint":
+ Integer deleteUserId = call.argument("userId");
+ if (deleteUserId == null) {
+ result.error("INVALID_ARGUMENTS", "userId is required", null);
+ return;
+ }
+ Map deleteOneRes = deleteOneFingerprint(deleteUserId);
+ result.success(deleteOneRes);
+ break;
+
+ case "getUserCount":
+ Map countRes = getUserCount();
+ result.success(countRes);
+ break;
+
+ default:
+ result.notImplemented();
+ break;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Method call error: " + e.getMessage(), e);
+ result.error("PLUGIN_ERROR", "Plugin internal error: " + e.getMessage(), null);
+ }
+ }
+
+ /**
+ * 打开指纹识别设备
+ * @param device 设备路径,如"/dev/ttyS1"或"USB"
+ * @param baudrate 波特率,如9600、115200等
+ * @return 是否成功打开设备
+ */
+ private boolean openDevice(String device, int baudrate) {
+ Log.d(TAG, "尝试打开设备: " + device + ", 波特率: " + baudrate);
+
+ m_szDevice = device;
+ m_nBaudrate = baudrate;
+
+ try {
+ // 检查Activity是否可用
+ if (activity == null) {
+ Log.e(TAG, "Activity未初始化,无法打开设备");
+ return false;
+ }
+
+ // 初始化设备通信对象
+ if (m_devComm == null) {
+ m_devComm = new DevComm(activity, this);
+ Log.d(TAG, "创建DevComm实例");
+ }
+
+ // 如果设备未初始化,则尝试打开通信
+ if (!m_devComm.IsInit()) {
+ if (!m_devComm.OpenComm(m_szDevice, m_nBaudrate)) {
+ Log.e(TAG, "打开设备通信失败: " + device);
+ return false;
+ }
+ Log.d(TAG, "设备通信已建立");
+ }
+
+ // 测试设备连接
+ String[] deviceInfo = new String[1];
+ int testResult = m_devComm.Run_TestConnection();
+
+ if (testResult == DevComm.ERR_SUCCESS) {
+ int infoResult = m_devComm.Run_GetDeviceInfo(deviceInfo);
+ if (infoResult == DevComm.ERR_SUCCESS) {
+ Log.i(TAG, "设备打开成功,设备信息: " + deviceInfo[0]);
+ return true;
+ } else {
+ Log.e(TAG, "获取设备信息失败: " + GetErrorMsg(infoResult));
+ }
+ } else {
+ Log.e(TAG, "设备连接测试失败: " + GetErrorMsg(testResult));
+ }
+
+ // 连接失败,关闭通信
+ m_devComm.CloseComm();
+ Log.w(TAG, "设备连接失败,已关闭通信");
+ return false;
+
+ } catch (Exception e) {
+ Log.e(TAG, "打开设备时发生异常: " + e.getMessage(), e);
+ if (m_devComm != null) {
+ try {
+ m_devComm.CloseComm();
+ } catch (Exception closeEx) {
+ Log.e(TAG, "关闭设备通信时发生异常: " + closeEx.getMessage());
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * 关闭指纹识别设备
+ * 释放设备资源和通信连接
+ */
+ private void closeDevice() {
+ Log.d(TAG, "关闭设备");
+ try {
+ if (m_devComm != null && m_devComm.IsInit()) {
+ m_devComm.CloseComm();
+ Log.i(TAG, "设备已关闭");
+ } else {
+ Log.d(TAG, "设备未初始化或已关闭");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "关闭设备时发生异常: " + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 录入指纹模板
+ * @param userId 用户ID,用于标识指纹模板
+ * @param result Flutter回调结果
+ */
+ private void enrollFingerprint(int userId, Result result) {
+ Log.d(TAG, "开始录入指纹,用户ID: " + userId);
+
+ // 检查设备是否已初始化
+ if (!isDeviceReady()) {
+ Map errorResult = createErrorResponse("设备未初始化");
+ result.success(errorResult);
+ return;
+ }
+
+ // 检查指纹模板是否已存在
+ int[] templateState = new int[1];
+ int statusResult = m_devComm.Run_GetStatus(userId, templateState);
+
+ if (statusResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(statusResult);
+ Log.e(TAG, "获取模板状态失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ result.success(errorResult);
+ return;
+ }
+
+ if (templateState[0] == DevComm.GD_TEMPLATE_NOT_EMPTY) {
+ String errorMsg = "指纹模板已存在,用户ID: " + userId;
+ Log.w(TAG, errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ result.success(errorResult);
+ return;
+ }
+
+ // 开启LED指示灯
+ m_devComm.Run_SLEDControl(1);
+
+ // 在后台线程执行指纹录入
+ executorService.execute(() -> {
+ performFingerprintEnrollment(userId, result);
+ });
+ }
+
+ /**
+ * 执行指纹录入的具体流程
+ * @param userId 用户ID
+ * @param result Flutter回调结果
+ */
+ private void performFingerprintEnrollment(int userId, Result result) {
+ byte[] imageBuffer = new byte[IMAGE_BUFFER_SIZE];
+ int enrollStep = 0;
+ final int[] duplicateId = new int[1];
+ final int[] imageWidth = new int[1];
+ final int[] imageHeight = new int[1];
+
+ try {
+ // 录入指定次数的指纹
+ while (enrollStep < ENROLL_STEP_COUNT) {
+ Log.d(TAG, String.format("请放置手指进行第%d次录入", enrollStep + 1));
+
+ // 显示提示信息
+ showToastOnMainThread(String.format("请放置手指 (%d/%d)", enrollStep + 1, ENROLL_STEP_COUNT));
+
+ // 采集指纹图像
+ if (captureFingerprint() < 0) {
+ Map errorResult = createErrorResponse("指纹采集失败");
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+
+ Log.d(TAG, "请移开手指");
+ showToastOnMainThread("请移开手指");
+
+ // 上传指纹图像(仅USB模式)
+ if (m_devComm.m_nConnected == 2) {
+ int uploadResult = m_devComm.Run_UpImage(0, imageBuffer, imageWidth, imageHeight);
+ if (uploadResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(uploadResult);
+ Log.e(TAG, "上传指纹图像失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+ }
+
+ // 生成指纹特征
+ int generateResult = m_devComm.Run_Generate(enrollStep);
+ if (generateResult != DevComm.ERR_SUCCESS) {
+ if (generateResult == DevComm.ERR_BAD_QUALITY) {
+ Log.w(TAG, "指纹质量不佳,请重试");
+ showToastOnMainThread("指纹质量不佳,请重试");
+ continue; // 重试当前步骤
+ } else {
+ String errorMsg = GetErrorMsg(generateResult);
+ Log.e(TAG, "生成指纹特征失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+ }
+
+ enrollStep++;
+ }
+
+ // 合并多次录入的特征(如果录入次数大于1)
+ if (ENROLL_STEP_COUNT > 1) {
+ int mergeResult = m_devComm.Run_Merge(0, ENROLL_STEP_COUNT);
+ if (mergeResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(mergeResult);
+ Log.e(TAG, "合并指纹特征失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+ }
+
+ // 存储指纹模板
+ int storeResult = m_devComm.Run_StoreChar(userId, 0, duplicateId);
+ if (storeResult != DevComm.ERR_SUCCESS) {
+ String errorMsg;
+ if (storeResult == DevComm.ERR_DUPLICATION_ID) {
+ errorMsg = String.format("指纹重复,重复ID: %d", duplicateId[0]);
+ } else {
+ errorMsg = GetErrorMsg(storeResult);
+ }
+ Log.e(TAG, "存储指纹模板失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+
+ // 录入成功
+ Log.i(TAG, String.format("指纹录入成功,用户ID: %d", userId));
+ Map successResult = createSuccessResponse("指纹录入成功");
+ successResult.put("userId", userId);
+ mainHandler.post(() -> {
+ showToastOnMainThread("指纹录入成功");
+ result.success(successResult);
+ });
+
+ } catch (Exception e) {
+ Log.e(TAG, "指纹录入过程中发生异常: " + e.getMessage(), e);
+ Map errorResult = createErrorResponse("录入过程发生异常: " + e.getMessage());
+ mainHandler.post(() -> result.success(errorResult));
+ } finally {
+ // 关闭LED指示灯
+ try {
+ m_devComm.Run_SLEDControl(0);
+ } catch (Exception e) {
+ Log.e(TAG, "关闭LED失败: " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 验证指纹
+ * @param userId 用户ID,用于验证指定的指纹模板
+ * @param result Flutter回调结果
+ */
+ private void verifyFingerprint(int userId, Result result) {
+ Log.d(TAG, "开始验证指纹,用户ID: " + userId);
+
+ // 检查设备是否已初始化
+ if (!isDeviceReady()) {
+ Map errorResult = createErrorResponse("设备未初始化");
+ result.success(errorResult);
+ return;
+ }
+
+ // 检查指纹模板是否存在
+ int[] templateState = new int[1];
+ int statusResult = m_devComm.Run_GetStatus(userId, templateState);
+
+ if (statusResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(statusResult);
+ Log.e(TAG, "获取模板状态失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ result.success(errorResult);
+ return;
+ }
+
+ if (templateState[0] == DevComm.GD_TEMPLATE_EMPTY) {
+ String errorMsg = "指纹模板不存在,用户ID: " + userId;
+ Log.w(TAG, errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ result.success(errorResult);
+ return;
+ }
+
+ // 开启LED指示灯
+ m_devComm.Run_SLEDControl(1);
+
+ // 在后台线程执行指纹验证
+ executorService.execute(() -> {
+ performFingerprintVerification(userId, result);
+ });
+ }
+
+ /**
+ * 执行指纹验证的具体流程
+ * @param userId 用户ID
+ * @param result Flutter回调结果
+ */
+ private void performFingerprintVerification(int userId, Result result) {
+ byte[] imageBuffer = new byte[IMAGE_BUFFER_SIZE];
+ final int[] imageWidth = new int[1];
+ final int[] imageHeight = new int[1];
+ final int[] matchScore = new int[1];
+
+ try {
+ Log.d(TAG, "请放置手指进行验证");
+ showToastOnMainThread("请放置手指进行验证");
+
+ // 采集指纹图像
+ if (captureFingerprint() < 0) {
+ Map errorResult = createErrorResponse("指纹采集失败");
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+
+ Log.d(TAG, "请移开手指");
+ showToastOnMainThread("请移开手指");
+
+ // 上传指纹图像(仅USB模式)
+ if (m_devComm.m_nConnected == 2) {
+ int uploadResult = m_devComm.Run_UpImage(0, imageBuffer, imageWidth, imageHeight);
+ if (uploadResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(uploadResult);
+ Log.e(TAG, "上传指纹图像失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+ }
+
+ // 生成指纹特征
+ int generateResult = m_devComm.Run_Generate(0);
+ if (generateResult != DevComm.ERR_SUCCESS) {
+ String errorMsg;
+ if (generateResult == DevComm.ERR_BAD_QUALITY) {
+ errorMsg = "指纹质量不佳,请重试";
+ Log.w(TAG, errorMsg);
+ } else {
+ errorMsg = GetErrorMsg(generateResult);
+ Log.e(TAG, "生成指纹特征失败: " + errorMsg);
+ }
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> {
+ showToastOnMainThread(errorMsg);
+ result.success(errorResult);
+ });
+ return;
+ }
+
+ // 执行指纹验证
+ int verifyResult = m_devComm.Run_Verify(userId, 0, matchScore);
+ if (verifyResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(verifyResult);
+ Log.e(TAG, "指纹验证失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> {
+ showToastOnMainThread("指纹验证失败");
+ result.success(errorResult);
+ });
+ return;
+ }
+
+ // 验证成功
+ Log.i(TAG, String.format("指纹验证成功,用户ID: %d,匹配分数: %d", userId, matchScore[0]));
+ Map successResult = createSuccessResponse("指纹验证成功");
+ successResult.put("userId", userId);
+ successResult.put("matchScore", matchScore[0]);
+ mainHandler.post(() -> {
+ showToastOnMainThread("指纹验证成功");
+ result.success(successResult);
+ });
+
+ } catch (Exception e) {
+ Log.e(TAG, "指纹验证过程中发生异常: " + e.getMessage(), e);
+ Map errorResult = createErrorResponse("验证过程发生异常: " + e.getMessage());
+ mainHandler.post(() -> result.success(errorResult));
+ } finally {
+ // 关闭LED指示灯
+ try {
+ m_devComm.Run_SLEDControl(0);
+ } catch (Exception e) {
+ Log.e(TAG, "关闭LED失败: " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 删除所有指纹模板
+ * @return 删除结果
+ */
+ private Map deleteAllFingerprint() {
+ Log.d(TAG, "开始删除所有指纹模板");
+ Map res_data = new HashMap<>();
+
+ if (!isDeviceReady()) {
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", "设备未初始化");
+ return res_data;
+ }
+
+ try {
+ int deleteResult = m_devComm.Run_DelChar(1, maxFpCount);
+ if (deleteResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(deleteResult);
+ Log.e(TAG, "删除所有指纹模板失败: " + errorMsg);
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", errorMsg);
+ return res_data;
+ }
+
+ Log.i(TAG, "所有指纹模板删除成功");
+ res_data.put("code", RESPONSE_SUCCESS);
+ res_data.put("msg", "所有指纹模板删除成功");
+ return res_data;
+
+ } catch (Exception e) {
+ Log.e(TAG, "删除所有指纹模板过程中发生异常: " + e.getMessage(), e);
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", "删除过程发生异常: " + e.getMessage());
+ return res_data;
+ }
+ }
+
+ /**
+ * 删除指定用户的指纹模板
+ * @param userId 用户ID
+ * @return 删除结果
+ */
+ private Map deleteOneFingerprint(int userId) {
+ Log.d(TAG, "开始删除指纹模板,用户ID: " + userId);
+ Map res_data = new HashMap<>();
+
+ if (!isDeviceReady()) {
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", "设备未初始化");
+ return res_data;
+ }
+
+ try {
+ int deleteResult = m_devComm.Run_DelChar(userId, userId);
+ if (deleteResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(deleteResult);
+ Log.e(TAG, "删除指纹模板失败: " + errorMsg);
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", errorMsg);
+ return res_data;
+ }
+
+ Log.i(TAG, String.format("指纹模板删除成功,用户ID: %d", userId));
+ res_data.put("code", RESPONSE_SUCCESS);
+ res_data.put("msg", "指纹模板删除成功");
+ res_data.put("userId", userId);
+ return res_data;
+
+ } catch (Exception e) {
+ Log.e(TAG, "删除指纹模板过程中发生异常: " + e.getMessage(), e);
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", "删除过程发生异常: " + e.getMessage());
+ return res_data;
+ }
+ }
+
+ /**
+ * 识别指纹(1:N搜索)
+ * @param result Flutter回调结果
+ */
+ private void identifyFingerprint(Result result) {
+ Log.d(TAG, "开始识别指纹");
+
+ // 检查设备是否已初始化
+ if (!isDeviceReady()) {
+ Map errorResult = createErrorResponse("设备未初始化");
+ result.success(errorResult);
+ return;
+ }
+
+ // 开启LED指示灯
+ m_devComm.Run_SLEDControl(1);
+
+ // 在后台线程执行指纹识别
+ executorService.execute(() -> {
+ performFingerprintIdentification(result);
+ });
+ }
+
+ /**
+ * 执行指纹识别的具体流程
+ * @param result Flutter回调结果
+ */
+ private void performFingerprintIdentification(Result result) {
+ byte[] imageBuffer = new byte[IMAGE_BUFFER_SIZE];
+ final int[] foundUserId = new int[1];
+ final int[] imageWidth = new int[1];
+ final int[] imageHeight = new int[1];
+ final int[] matchScore = new int[1];
+
+ try {
+ Log.d(TAG, "请放置手指进行识别");
+ showToastOnMainThread("请放置手指进行识别");
+
+ // 采集指纹图像
+ if (captureFingerprint() < 0) {
+ Map errorResult = createErrorResponse("指纹采集失败");
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+
+ Log.d(TAG, "请移开手指");
+ showToastOnMainThread("请移开手指");
+
+ // 上传指纹图像(仅USB模式)
+ if (m_devComm.m_nConnected == 2) {
+ int uploadResult = m_devComm.Run_UpImage(0, imageBuffer, imageWidth, imageHeight);
+ if (uploadResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(uploadResult);
+ Log.e(TAG, "上传指纹图像失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> result.success(errorResult));
+ return;
+ }
+ }
+
+ // 生成指纹特征
+ int generateResult = m_devComm.Run_Generate(0);
+ if (generateResult != DevComm.ERR_SUCCESS) {
+ String errorMsg;
+ if (generateResult == DevComm.ERR_BAD_QUALITY) {
+ errorMsg = "指纹质量不佳,请重试";
+ Log.w(TAG, errorMsg);
+ } else {
+ errorMsg = GetErrorMsg(generateResult);
+ Log.e(TAG, "生成指纹特征失败: " + errorMsg);
+ }
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> {
+ showToastOnMainThread(errorMsg);
+ result.success(errorResult);
+ });
+ return;
+ }
+
+ // 执行指纹搜索
+ int searchResult = m_devComm.Run_Search(0, 1, maxFpCount, foundUserId, matchScore);
+ if (searchResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(searchResult);
+ Log.e(TAG, "指纹识别失败: " + errorMsg);
+ Map errorResult = createErrorResponse(errorMsg);
+ mainHandler.post(() -> {
+ showToastOnMainThread("未找到匹配的指纹");
+ result.success(errorResult);
+ });
+ return;
+ }
+
+ // 识别成功
+ Log.i(TAG, String.format("指纹识别成功,用户ID: %d,匹配分数: %d", foundUserId[0], matchScore[0]));
+ Map successResult = createSuccessResponse("指纹识别成功");
+ successResult.put("userId", foundUserId[0]);
+ successResult.put("matchScore", matchScore[0]);
+ mainHandler.post(() -> {
+ showToastOnMainThread("指纹识别成功");
+ result.success(successResult);
+ });
+
+ } catch (Exception e) {
+ Log.e(TAG, "指纹识别过程中发生异常: " + e.getMessage(), e);
+ Map errorResult = createErrorResponse("识别过程发生异常: " + e.getMessage());
+ mainHandler.post(() -> result.success(errorResult));
+ } finally {
+ // 关闭LED指示灯
+ try {
+ m_devComm.Run_SLEDControl(0);
+ } catch (Exception e) {
+ Log.e(TAG, "关闭LED失败: " + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 获取已注册的指纹模板数量
+ * @return 获取结果
+ */
+ private Map getUserCount() {
+ Log.d(TAG, "开始获取用户数量");
+ Map res_data = new HashMap<>();
+
+ if (!isDeviceReady()) {
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", "设备未初始化");
+ return res_data;
+ }
+
+ try {
+ int[] enrollCount = new int[1];
+ int countResult = m_devComm.Run_GetEnrollCount(1, maxFpCount, enrollCount);
+
+ if (countResult != DevComm.ERR_SUCCESS) {
+ String errorMsg = GetErrorMsg(countResult);
+ Log.e(TAG, "获取用户数量失败: " + errorMsg);
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", errorMsg);
+ return res_data;
+ }
+
+ Log.i(TAG, String.format("获取用户数量成功,注册数量: %d", enrollCount[0]));
+ res_data.put("code", RESPONSE_SUCCESS);
+ res_data.put("msg", "获取用户数量成功");
+ res_data.put("count", enrollCount[0]);
+ return res_data;
+
+ } catch (Exception e) {
+ Log.e(TAG, "获取用户数量过程中发生异常: " + e.getMessage(), e);
+ res_data.put("code", RESPONSE_FAIL);
+ res_data.put("msg", "获取过程发生异常: " + e.getMessage());
+ return res_data;
+ }
+ }
+
+ // ==================== 辅助方法 ====================
+
+ /**
+ * 检查设备是否准备就绪
+ * @return 设备是否已初始化且可用
+ */
+ private boolean isDeviceReady() {
+ return m_devComm != null && m_devComm.IsInit();
+ }
+
+ /**
+ * 创建成功响应
+ * @param message 成功消息
+ * @return 响应Map
+ */
+ private Map createSuccessResponse(String message) {
+ Map response = new HashMap<>();
+ response.put("success", true);
+ response.put("code", RESPONSE_SUCCESS);
+ response.put("message", message);
+ return response;
+ }
+
+ /**
+ * 创建错误响应
+ * @param message 错误消息
+ * @return 响应Map
+ */
+ private Map createErrorResponse(String message) {
+ Map response = new HashMap<>();
+ response.put("success", false);
+ response.put("code", RESPONSE_FAIL);
+ response.put("message", message);
+ return response;
+ }
+
+ /**
+ * 在主线程显示Toast消息
+ * @param message 要显示的消息
+ */
+ private void showToastOnMainThread(String message) {
+ if (activity != null) {
+ mainHandler.post(() -> {
+ try {
+ Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
+ } catch (Exception e) {
+ Log.w(TAG, "显示Toast失败: " + e.getMessage());
+ }
+ });
+ }
+ }
+
+ /**
+ * 采集指纹图像(重命名原Capturing方法)
+ * @return 采集结果,0表示成功,负数表示失败
+ */
+ private int captureFingerprint() {
+ return Capturing();
+ }
+
+ @Override
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+ Log.d(TAG, "插件从引擎分离");
+
+ // 清理资源
+ if (channel != null) {
+ channel.setMethodCallHandler(null);
+ channel = null;
+ }
+
+ // 关闭设备连接
+ if (m_devComm != null && m_devComm.IsInit()) {
+ try {
+ m_devComm.CloseComm();
+ Log.d(TAG, "设备连接已关闭");
+ } catch (Exception e) {
+ Log.e(TAG, "关闭设备连接时发生异常: " + e.getMessage());
+ }
+ }
+
+ // 关闭线程池
+ if (executorService != null && !executorService.isShutdown()) {
+ executorService.shutdown();
+ try {
+ if (!executorService.awaitTermination(5, java.util.concurrent.TimeUnit.SECONDS)) {
+ executorService.shutdownNow();
+ }
+ } catch (InterruptedException e) {
+ executorService.shutdownNow();
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ @Override
+ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
+ Log.d(TAG, "插件附加到Activity");
+ activity = binding.getActivity();
+ }
+
+ @Override
+ public void onDetachedFromActivity() {
+ Log.d(TAG, "插件从Activity分离");
+ activity = null;
+ }
+
+ @Override
+ public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
+ Log.d(TAG, "插件因配置变更重新附加到Activity");
+ onAttachedToActivity(binding);
+ }
+
+ @Override
+ public void onDetachedFromActivityForConfigChanges() {
+ Log.d(TAG, "插件因配置变更从Activity分离");
+ onDetachedFromActivity();
+ }
+
+ private String GetErrorMsg(int nErrorCode) {
+ String str = "";
+
+ switch (nErrorCode) {
+ case DevComm.ERR_SUCCESS:
+ str = "Succcess";
+ break;
+ case DevComm.ERR_VERIFY:
+ str = "Verify NG";
+ break;
+ case DevComm.ERR_IDENTIFY:
+ str = "Identify NG";
+ break;
+ case DevComm.ERR_EMPTY_ID_NOEXIST:
+ str = "Empty Template no Exist";
+ break;
+ case DevComm.ERR_BROKEN_ID_NOEXIST:
+ str = "Broken Template no Exist";
+ break;
+ case DevComm.ERR_TMPL_NOT_EMPTY:
+ str = "Template of this ID Already Exist";
+ break;
+ case DevComm.ERR_TMPL_EMPTY:
+ str = "This Template is Already Empty";
+ break;
+ case DevComm.ERR_INVALID_TMPL_NO:
+ str = "Invalid Template No";
+ break;
+ case DevComm.ERR_ALL_TMPL_EMPTY:
+ str = "All Templates are Empty";
+ break;
+ case DevComm.ERR_INVALID_TMPL_DATA:
+ str = "Invalid Template Data";
+ break;
+ case DevComm.ERR_DUPLICATION_ID:
+ str = "Duplicated ID : ";
+ break;
+ case DevComm.ERR_BAD_QUALITY:
+ str = "Bad Quality Image";
+ break;
+ case DevComm.ERR_MERGE_FAIL:
+ str = "Merge failed";
+ break;
+ case DevComm.ERR_NOT_AUTHORIZED:
+ str = "Device not authorized.";
+ break;
+ case DevComm.ERR_MEMORY:
+ str = "Memory Error ";
+ break;
+ case DevComm.ERR_INVALID_PARAM:
+ str = "Invalid Parameter";
+ break;
+ case DevComm.ERR_GEN_COUNT:
+ str = "Generation Count is invalid";
+ break;
+ case DevComm.ERR_INVALID_BUFFER_ID:
+ str = "Ram Buffer ID is invalid.";
+ break;
+ case DevComm.ERR_INVALID_OPERATION_MODE:
+ str = "Invalid Operation Mode!";
+ break;
+ case DevComm.ERR_FP_NOT_DETECTED:
+ str = "Finger is not detected.";
+ break;
+ default:
+ str = String.format("Fail, error code=%d", nErrorCode);
+ break;
+ }
+
+ return str;
+ }
+
+ private int Capturing() {
+ int w_nRet;
+ while (true) {
+
+ w_nRet = m_devComm.Run_GetImage();
+
+ if (w_nRet == DevComm.ERR_CONNECTION) {
+ Log.i("zhiwenPlugin", "Communication error!");
+ return -1;
+ } else if (w_nRet == DevComm.ERR_SUCCESS)
+ break;
+
+ }
+
+ return 0;
+ }
+
+ // IUsbConnState接口实现
+
+ /**
+ * USB设备连接成功回调
+ * 当USB设备成功连接时被调用
+ */
+ @Override
+ public void onUsbConnected() {
+ Log.d(TAG, "USB设备连接成功");
+ // 可以在这里添加设备连接成功后的处理逻辑
+ }
+
+ /**
+ * USB权限被拒绝回调
+ * 当用户拒绝USB权限请求时被调用
+ */
+ @Override
+ public void onUsbPermissionDenied() {
+ Log.w(TAG, "USB权限被拒绝");
+ // 可以在这里添加权限被拒绝后的处理逻辑
+ }
+
+ /**
+ * 设备未找到回调
+ * 当无法找到指定的USB设备时被调用
+ */
+ @Override
+ public void onDeviceNotFound() {
+ Log.w(TAG, "未找到USB设备");
+ // 可以在这里添加设备未找到后的处理逻辑
+ }
+
+}
diff --git a/android/src/main/res/xml/device_filter.xml b/android/src/main/res/xml/device_filter.xml
new file mode 100644
index 0000000..595d82e
--- /dev/null
+++ b/android/src/main/res/xml/device_filter.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/src/test/java/com/xiarui/zhiwen/ZhiwenPluginTest.java b/android/src/test/java/com/xiarui/zhiwen/ZhiwenPluginTest.java
new file mode 100644
index 0000000..1767acd
--- /dev/null
+++ b/android/src/test/java/com/xiarui/zhiwen/ZhiwenPluginTest.java
@@ -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);
+ }
+}
diff --git a/example/.gitignore b/example/.gitignore
new file mode 100644
index 0000000..29a3a50
--- /dev/null
+++ b/example/.gitignore
@@ -0,0 +1,43 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/example/README.md b/example/README.md
new file mode 100644
index 0000000..5b6e5eb
--- /dev/null
+++ b/example/README.md
@@ -0,0 +1,16 @@
+# zhiwen_example
+
+Demonstrates how to use the zhiwen plugin.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml
new file mode 100644
index 0000000..0d29021
--- /dev/null
+++ b/example/analysis_options.yaml
@@ -0,0 +1,28 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at https://dart.dev/lints.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/example/android/.gitignore b/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
new file mode 100644
index 0000000..3f96b44
--- /dev/null
+++ b/example/android/app/build.gradle
@@ -0,0 +1,58 @@
+plugins {
+ id "com.android.application"
+ id "kotlin-android"
+ // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
+ id "dev.flutter.flutter-gradle-plugin"
+}
+
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file("local.properties")
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader("UTF-8") { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
+if (flutterVersionCode == null) {
+ flutterVersionCode = "1"
+}
+
+def flutterVersionName = localProperties.getProperty("flutter.versionName")
+if (flutterVersionName == null) {
+ flutterVersionName = "1.0"
+}
+
+android {
+ namespace = "com.xiarui.zhiwen_example"
+ compileSdk = flutter.compileSdkVersion
+ ndkVersion = flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId = "com.xiarui.zhiwen_example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
+ minSdk = flutter.minSdkVersion
+ targetSdk = flutter.targetSdkVersion
+ versionCode = flutterVersionCode.toInteger()
+ versionName = flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig = signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source = "../.."
+}
diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d4a363e
--- /dev/null
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/java/com/xiarui/zhiwen_example/MainActivity.java b/example/android/app/src/main/java/com/xiarui/zhiwen_example/MainActivity.java
new file mode 100644
index 0000000..a2c8f5b
--- /dev/null
+++ b/example/android/app/src/main/java/com/xiarui/zhiwen_example/MainActivity.java
@@ -0,0 +1,6 @@
+package com.xiarui.zhiwen_example;
+
+import io.flutter.embedding.android.FlutterActivity;
+
+public class MainActivity extends FlutterActivity {
+}
diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/example/android/app/src/main/res/xml/device_filter.xml b/example/android/app/src/main/res/xml/device_filter.xml
new file mode 100644
index 0000000..595d82e
--- /dev/null
+++ b/example/android/app/src/main/res/xml/device_filter.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..399f698
--- /dev/null
+++ b/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/example/android/build.gradle b/example/android/build.gradle
new file mode 100644
index 0000000..d2ffbff
--- /dev/null
+++ b/example/android/build.gradle
@@ -0,0 +1,18 @@
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = "../build"
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(":app")
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
new file mode 100644
index 0000000..3b5b324
--- /dev/null
+++ b/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..e1ca574
--- /dev/null
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
diff --git a/example/android/settings.gradle b/example/android/settings.gradle
new file mode 100644
index 0000000..536165d
--- /dev/null
+++ b/example/android/settings.gradle
@@ -0,0 +1,25 @@
+pluginManagement {
+ def flutterSdkPath = {
+ def properties = new Properties()
+ file("local.properties").withInputStream { properties.load(it) }
+ def flutterSdkPath = properties.getProperty("flutter.sdk")
+ assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+ return flutterSdkPath
+ }()
+
+ includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
+
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+plugins {
+ id "dev.flutter.flutter-plugin-loader" version "1.0.0"
+ id "com.android.application" version "7.3.0" apply false
+ id "org.jetbrains.kotlin.android" version "1.7.10" apply false
+}
+
+include ":app"
diff --git a/example/integration_test/plugin_integration_test.dart b/example/integration_test/plugin_integration_test.dart
new file mode 100644
index 0000000..14adf64
--- /dev/null
+++ b/example/integration_test/plugin_integration_test.dart
@@ -0,0 +1,25 @@
+// This is a basic Flutter integration test.
+//
+// Since integration tests run in a full Flutter application, they can interact
+// with the host side of a plugin implementation, unlike Dart unit tests.
+//
+// For more information about Flutter integration tests, please see
+// https://docs.flutter.dev/cookbook/testing/integration/introduction
+
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
+import 'package:zhiwen/zhiwen.dart';
+
+void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ testWidgets('getPlatformVersion test', (WidgetTester tester) async {
+ final Zhiwen plugin = Zhiwen();
+ final String? version = await plugin.getPlatformVersion();
+ // The version string depends on the host platform running the test, so
+ // just assert that some non-empty string is returned.
+ expect(version?.isNotEmpty, true);
+ });
+}
diff --git a/example/lib/main.dart b/example/lib/main.dart
new file mode 100644
index 0000000..b7697aa
--- /dev/null
+++ b/example/lib/main.dart
@@ -0,0 +1,130 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+import 'dart:async';
+
+import 'package:flutter/services.dart';
+import 'package:zhiwen/zhiwen.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatefulWidget {
+ const MyApp({super.key});
+
+ @override
+ State createState() => _MyAppState();
+}
+
+class _MyAppState extends State {
+ String _platformVersion = 'Unknown';
+ final _zhiwenPlugin = Zhiwen();
+
+ @override
+ void initState() {
+ super.initState();
+ initPlatformState();
+ }
+
+ // Platform messages are asynchronous, so we initialize in an async method.
+ Future initPlatformState() async {
+ String platformVersion;
+ // Platform messages may fail, so we use a try/catch PlatformException.
+ // We also handle the message potentially returning null.
+ try {
+ platformVersion =
+ await _zhiwenPlugin.getPlatformVersion() ?? 'Unknown platform version';
+ } on PlatformException {
+ platformVersion = 'Failed to get platform version.';
+ }
+
+ // If the widget was removed from the tree while the asynchronous platform
+ // message was in flight, we want to discard the reply rather than calling
+ // setState to update our non-existent appearance.
+ if (!mounted) return;
+
+ setState(() {
+ _platformVersion = platformVersion;
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return ScaffoldMessenger(
+ child: MaterialApp(
+ home: Scaffold(
+ appBar: AppBar(
+ title: const Text('Plugin example app'),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text('Running on: $_platformVersion\n'),
+ ElevatedButton(
+ onPressed: () async {
+ bool result = await _zhiwenPlugin.openDevice("USB", 9600);
+ },
+ child: const Text('打开设备'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ await _zhiwenPlugin.closeDevice();
+ },
+ child: const Text('关闭设备'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ var random = Random();
+ int randomNumber = random.nextInt(100); // 生成 0 到 99 的随机整数
+
+ Map result = await _zhiwenPlugin.enrollFingerprint(randomNumber);
+ print(result);
+ },
+ child: const Text('录入指纹'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ int userId = 24;
+ Map result = await _zhiwenPlugin.verifyFingerprint(userId);
+ print(result);
+ },
+ child: const Text('验证指纹'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ Map result = await _zhiwenPlugin.deleteAllFingerprint();
+ print(result);
+ },
+ child: const Text('删除所有指纹'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ int userId = 2;
+ Map result = await _zhiwenPlugin.deleteOneFingerprint(userId);
+ print(result);
+ },
+ child: const Text('删除单个指纹'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ Map result = await _zhiwenPlugin.identifyFingerprint();
+ print(result);
+ },
+ child: const Text('识别指纹'),
+ ),
+ ElevatedButton(
+ onPressed: () async {
+ Map result = await _zhiwenPlugin.getUserCount();
+ print(result);
+ },
+ child: const Text('获取指纹总数'),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ));
+ }
+}
diff --git a/example/pubspec.lock b/example/pubspec.lock
new file mode 100644
index 0000000..9b2a625
--- /dev/null
+++ b/example/pubspec.lock
@@ -0,0 +1,283 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.11.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.18.0"
+ cupertino_icons:
+ dependency: "direct main"
+ description:
+ name: cupertino_icons
+ sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.8"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.1"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_driver:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_lints:
+ dependency: "direct dev"
+ description:
+ name: flutter_lints
+ sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ fuchsia_remote_debug_protocol:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ integration_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ leak_tracker:
+ dependency: transitive
+ description:
+ name: leak_tracker
+ sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "10.0.4"
+ leak_tracker_flutter_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_flutter_testing
+ sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.3"
+ leak_tracker_testing:
+ dependency: transitive
+ description:
+ name: leak_tracker_testing
+ sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ lints:
+ dependency: transitive
+ description:
+ name: lints
+ sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.12.16+1"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.8.0"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.12.0"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.9.0"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.4"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.8"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.2"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.10.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.11.1"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ sync_http:
+ dependency: transitive
+ description:
+ name: sync_http
+ sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.1"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.0"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
+ url: "https://pub.dev"
+ source: hosted
+ version: "14.2.1"
+ webdriver:
+ dependency: transitive
+ description:
+ name: webdriver
+ sha256: "003d7da9519e1e5f329422b36c4dcdf18d7d2978d1ba099ea4e45ba490ed845e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.3"
+ zhiwen:
+ dependency: "direct main"
+ description:
+ path: ".."
+ relative: true
+ source: path
+ version: "0.0.1"
+sdks:
+ dart: ">=3.4.3 <4.0.0"
+ flutter: ">=3.18.0-18.0.pre.54"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
new file mode 100644
index 0000000..107f0ef
--- /dev/null
+++ b/example/pubspec.yaml
@@ -0,0 +1,85 @@
+name: zhiwen_example
+description: "Demonstrates how to use the zhiwen plugin."
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+environment:
+ sdk: '>=3.4.3 <4.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+
+ zhiwen:
+ # When depending on this package from a real application you should use:
+ # zhiwen: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.6
+
+dev_dependencies:
+ integration_test:
+ sdk: flutter
+ flutter_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^3.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart
new file mode 100644
index 0000000..51b474a
--- /dev/null
+++ b/example/test/widget_test.dart
@@ -0,0 +1,27 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility in the flutter_test package. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:zhiwen_example/main.dart';
+
+void main() {
+ testWidgets('Verify Platform version', (WidgetTester tester) async {
+ // Build our app and trigger a frame.
+ await tester.pumpWidget(const MyApp());
+
+ // Verify that platform version is retrieved.
+ expect(
+ find.byWidgetPredicate(
+ (Widget widget) => widget is Text &&
+ widget.data!.startsWith('Running on:'),
+ ),
+ findsOneWidget,
+ );
+ });
+}
diff --git a/lib/zhiwen.dart b/lib/zhiwen.dart
new file mode 100644
index 0000000..596017f
--- /dev/null
+++ b/lib/zhiwen.dart
@@ -0,0 +1,40 @@
+
+import 'zhiwen_platform_interface.dart';
+
+class Zhiwen {
+ Future getPlatformVersion() {
+ return ZhiwenPlatform.instance.getPlatformVersion();
+ }
+
+ Future openDevice(String devicePath, int baudRate) {
+ return ZhiwenPlatform.instance.openDevice(devicePath, baudRate);
+ }
+
+ Future closeDevice() {
+ return ZhiwenPlatform.instance.closeDevice();
+ }
+
+ Future