diff --git a/.gitignore b/.gitignore index 1f2093e..80ef0dc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ +# General temp. files +*~ +*.tmp + # Eclipse project files #.classpath #.project # built application files -#*.apk +*.apk *.ap_ # files for the dex VM @@ -12,14 +16,18 @@ # Java class files *.class -# generated files +# Generated files bin/ gen/ +out/ lint.xml # Local configuration file (sdk path, etc) local.properties +# Proguard folder generated by Eclipse +proguard/ + # Eclipse project files #.classpath #.project @@ -31,20 +39,34 @@ release.properties pom.xml.* # Ant -build.xml +#build.xml ant.properties local.properties proguard.cfg proguard-project.txt +# Gradle files +.gradle/ +build/ + +# Log Files +*.log + +# Netbeans files +.netbeans.xml + # Intellij project files *.iml *.ipr *.iws .idea/ -out/ gen-external-apklibs/ -# Gradle -.gradle -build +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +# Keystore files +*.jks diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5497bdc --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +language: android +#install: ant deps + +android: + + components: + + # The BuildTools version used by the Physicaloid project + - build-tools-18.0.1 + + # The SDK version used to compile the Physicaloid project + - android-18 + + # List of the specified system images, + # to run emulator(s) during the tests + #- sys-img-armeabi-v7a-android-18 + #- sys-img-armeabi-v7a-android-26 + +before_install: + - wget --no-check-certificate https://www.apache.org/dist/ant/binaries/apache-ant-1.9.13-bin.tar.gz + - tar -xzvf apache-ant-1.9.13-bin.tar.gz + - export PATH=`pwd`/apache-ant-1.9.13/bin:$PATH + - echo $(ant -version) + +script: + - cd ./SampleProjects/PhysicaloidTest + - ant -v debug + +after_success: + - cp bin/PhysicaloidTest-debug.apk ./result.apk + - link=$(curl -F "file=@result.apk" https://file.io?expires=1m | jq --raw-output '.link') + - echo "Uploaded the result to $link" \ No newline at end of file diff --git a/PhysicaloidLibrary/AndroidManifest.xml b/PhysicaloidLibrary/AndroidManifest.xml index d5024fd..01b2cff 100644 --- a/PhysicaloidLibrary/AndroidManifest.xml +++ b/PhysicaloidLibrary/AndroidManifest.xml @@ -1,10 +1,10 @@ + android:versionCode="20000" + android:versionName="02.00.00" > + android:minSdkVersion="19" + android:targetSdkVersion="19" /> \ No newline at end of file diff --git a/PhysicaloidLibrary/bin/physicaloidlibrary.jar b/PhysicaloidLibrary/bin/physicaloidlibrary.jar deleted file mode 100644 index acc510d..0000000 Binary files a/PhysicaloidLibrary/bin/physicaloidlibrary.jar and /dev/null differ diff --git a/PhysicaloidLibrary/build.xml b/PhysicaloidLibrary/build.xml new file mode 100644 index 0000000..adcc7ad --- /dev/null +++ b/PhysicaloidLibrary/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PhysicaloidLibrary/libs/d2xx.jar b/PhysicaloidLibrary/libs/d2xx.jar deleted file mode 100755 index be24cf9..0000000 Binary files a/PhysicaloidLibrary/libs/d2xx.jar and /dev/null differ diff --git a/PhysicaloidLibrary/project.properties b/PhysicaloidLibrary/project.properties index 5f6ad43..1b8c5a3 100644 --- a/PhysicaloidLibrary/project.properties +++ b/PhysicaloidLibrary/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-12 +target=android-18 android.library=true diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/Physicaloid.java b/PhysicaloidLibrary/src/com/physicaloid/lib/Physicaloid.java index 0ea469f..bade21c 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/lib/Physicaloid.java +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/Physicaloid.java @@ -13,418 +13,649 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.physicaloid.lib; import android.content.Context; import android.util.Log; - import com.physicaloid.BuildConfig; import com.physicaloid.lib.framework.AutoCommunicator; import com.physicaloid.lib.framework.SerialCommunicator; import com.physicaloid.lib.framework.Uploader; import com.physicaloid.lib.programmer.avr.UploadErrors; import com.physicaloid.lib.usb.driver.uart.ReadLisener; +import com.physicaloid.lib.usb.driver.uart.ReadListener; import com.physicaloid.lib.usb.driver.uart.UartConfig; - import java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class Physicaloid { - private static final boolean DEBUG_SHOW = true && BuildConfig.DEBUG; - private static final String TAG = Physicaloid.class.getSimpleName(); - - private Context mContext; - private Boards mBoard; - - protected SerialCommunicator mSerial; - private Uploader mUploader; - private Thread mUploadThread; - - private UploadCallBack mCallBack; - private InputStream mFileStream; - - private static final Object LOCK = new Object(); - protected static final Object LOCK_WRITE = new Object(); - protected static final Object LOCK_READ = new Object(); - - public Physicaloid(Context context) { - this.mContext = context; - } - - /** - * Opens a device and communicate USB UART by default settings - * @return true : successful , false : fail - * @throws RuntimeException - */ - public boolean open() throws RuntimeException { - return open(new UartConfig()); - } - - /** - * Opens a device and communicate USB UART - * @param uart UART configuration - * @return true : successful , false : fail - * @throws RuntimeException - */ - public boolean open(UartConfig uart) throws RuntimeException { - synchronized (LOCK) { - if(mSerial == null) { - mSerial = new AutoCommunicator().getSerialCommunicator(mContext); - if(mSerial == null) return false; - } - if(mSerial.open()) { - mSerial.setUartConfig(uart); - return true; - } else { - return false; - } + + /** + * USB physical connection as a number + */ + public static final int USB = 1; + /** + * WIFI physical connection as a number + */ + public static final int WIFI = 2; + /** + * Bluetooth physical connection as a number + */ + public static final int BLUETOOTH = 3; + /** + * USB physical connection as a string + */ + public static final String USB_STRING = "USB"; + /** + * WIFI physical connection as a string + */ + public static final String WIFI_STRING = "WiFi"; + /** + * Bluetooth physical connection as a string + */ + public static final String BLUETOOTH_STRING = "BlueTooth"; + private static final boolean DEBUG_SHOW = true && BuildConfig.DEBUG; + private static final String TAG = Physicaloid.class.getSimpleName(); + private Context mContext; + private Boards mBoard; + protected SerialCommunicator mSerial; + private Uploader mUploader; + private Thread mUploadThread; + private UploadCallBack mCallBack; + private InputStream mFileStream; + private static final Object LOCK = new Object(); + protected static final Object LOCK_WRITE = new Object(); + protected static final Object LOCK_READ = new Object(); + private String mNetdest = null; + private String mBlueName = null; + private int mDport = 9001; + private int mCport = 9002; + private boolean USE_USB = true; + private boolean USE_WIFI = false; + private boolean USE_BLUETOOTH = false; + + /** + * Default, USB only + * + * @param context + */ + public Physicaloid(Context context) { + USE_USB = true; + USE_WIFI = false; + USE_BLUETOOTH = false; + this.mContext = context; + } + + /** + * Bluetooth, optional USB + * + * @param context + * @param u true = use USB + * @param BlueName Name of bluetooth, null for automatic default + */ + public Physicaloid(Context context, boolean u, String BlueName) { + USE_USB = u; + USE_WIFI = false; + USE_BLUETOOTH = true; + mBlueName = BlueName; + this.mContext = context; + } + + // WiFi, optional USB + /** + * + * @param context + * @param u true = use USB + * @param Netdest e.g. "192.168.4.1" or a host name + * @param Dport port number for data + * @param Cport port number for controls + */ + public Physicaloid(Context context, boolean u, String Netdest, int Dport, int Cport) { + USE_USB = u; + USE_WIFI = true; + USE_BLUETOOTH = false; + if(Dport > 0) { + mDport = Dport; + } else { + mDport = 9001; + } + if(Cport > 0) { + mCport = Cport; + } else { + mCport = mDport + 1; + } + if(mNetdest != null) { + mNetdest = Netdest; + } else { + mNetdest = "192.168.4.1"; + } + this.mContext = context; + } + + // WiFi, Bluetooth, optional USB + /** + * + * @param context + * @param u true = use USB + * @param BlueName Name of bluetooth, null for automatic default + * @param Netdest e.g. "192.168.4.1" or a host name, null defaults to + * "192.168.4.1" + * @param Dport port number for data, Zero = 9001 + * @param Cport port number for controls, Zero = Dport + 1 + */ + public Physicaloid(Context context, boolean u, String BlueName, String Netdest, int Dport, int Cport) { + this.mContext = context; + USE_USB = u; + USE_WIFI = true; + USE_BLUETOOTH = true; + if(Dport > 0) { + mDport = Dport; + } else { + mDport = 9001; + } + if(Cport > 0) { + mCport = Cport; + } else { + mCport = mDport + 1; + } + if(mNetdest != null) { + mNetdest = Netdest; + } else { + mNetdest = "192.168.4.1"; + } + mBlueName = BlueName; + } + + /** + * Opens a device and communicate USB UART by default settings + * + * @return true : successful , false : fail + * @throws RuntimeException + */ + public boolean open() throws RuntimeException { + return open(new UartConfig()); + } + + /** + * Opens a device and communicate USB UART + * + * @param uart UART configuration + * @return true : successful , false : fail + * @throws RuntimeException + */ + public boolean open(UartConfig uart) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + mSerial = new AutoCommunicator(USE_USB, USE_WIFI, USE_BLUETOOTH, mDport, mCport, mNetdest, mBlueName).getSerialCommunicator(mContext); + if(mSerial == null) { + return false; + } + } + if(mSerial.open()) { + mSerial.setUartConfig(uart); + return true; + } else { + return false; + } + } } - } - - /** - * Closes a device. - * @return true : successful , false : fail - * @throws RuntimeException - */ - public boolean close() throws RuntimeException { - synchronized (LOCK) { - if(mSerial == null) return true; - if(mSerial.close()) { - mSerial = null; - return true; - } else { - return false; - } + + /** + * Closes a device. + * + * @return true : successful , false : fail + * @throws RuntimeException + */ + public boolean close() throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return true; + } + if(mSerial.close()) { + mSerial = null; + return true; + } else { + return false; + } + } } - } - - /** - * Reads from a device - * @param buf - * @return read byte size - * @throws RuntimeException - */ - public int read(byte[] buf) throws RuntimeException { - if(mSerial == null) return 0; - return read(buf, buf.length); - } - - /** - * Reads from a device - * @param buf - * @param size - * @return read byte size - * @throws RuntimeException - */ - public int read(byte[] buf, int size) throws RuntimeException { - synchronized (LOCK_READ) { - if(mSerial == null) return 0; - return mSerial.read(buf, size); + + /** + * Reads from a device + * + * @param buf + * @return read byte size + * @throws RuntimeException + */ + public int read(byte[] buf) throws RuntimeException { + if(mSerial == null) { + return 0; + } + return read(buf, buf.length); } - } - - /** - * Adds read listener - * @param listener ReadListener - * @return true : successful , false : fail - * @throws RuntimeException - */ - public boolean addReadListener(ReadLisener listener) throws RuntimeException { - synchronized (LOCK_READ) { - if(mSerial == null) return false; - if(listener == null) return false; - mSerial.addReadListener(listener); - return true; + + /** + * Reads from a device + * + * @param buf + * @param size + * @return read byte size + * @throws RuntimeException + */ + public int read(byte[] buf, int size) throws RuntimeException { + synchronized(LOCK_READ) { + if(mSerial == null) { + return 0; + } + return mSerial.read(buf, size); + } } - } - - /** - * Clears read listener - * @throws RuntimeException - */ - public void clearReadListener() throws RuntimeException { - synchronized (LOCK_READ) { - if(mSerial == null) return; - mSerial.clearReadListener(); + + /** + * Adds read listener + * + * @param listener ReadListener + * @return true : successful , false : fail + * @throws RuntimeException + */ + public boolean addReadListener(ReadListener listener) throws RuntimeException { + synchronized(LOCK_READ) { + if(mSerial == null) { + return false; + } + if(listener == null) { + return false; + } + mSerial.addReadListener(listener); + return true; + } } - } - - /** - * Writes to a device. - * @param buf - * @return written byte size - * @throws RuntimeException - */ - public int write(byte[] buf) throws RuntimeException { - if(mSerial == null) return 0; - return write(buf, buf.length); - } - - /** - * Writes to a device. - * @param buf - * @param size - * @return written byte size - * @throws RuntimeException - */ - public int write(byte[] buf, int size) throws RuntimeException { - synchronized (LOCK_WRITE){ - if(mSerial == null) return 0; - return mSerial.write(buf, size); + + /** + * Adds read listener + * + * @param listener ReadListener + * @return true : successful , false : fail + * @throws RuntimeException + */ + public boolean addReadListener(ReadLisener listener) throws RuntimeException { + return addReadListener((ReadListener) listener); } - } - - /** - * Uploads a binary file to a device on background process. No need to open(). - * @param board board profile e.g. Boards.ARDUINO_UNO - * @param filePath a binary file path e.g. /sdcard/arduino/Blink.hex - * @throws RuntimeException - */ - public void upload(Boards board, String filePath) throws RuntimeException { - upload(board, filePath, null); - } - - /** - * Uploads a binary file to a device on background process. No need to open(). - * @param board board profile e.g. Boards.ARDUINO_UNO - * @param filePath a binary file path e.g. /sdcard/arduino/Blink.uno.hex - * @param callback - * @throws RuntimeException - */ - public void upload(Boards board, String filePath, UploadCallBack callback) throws RuntimeException { - if(filePath == null) { - if(callback != null){ callback.onError(UploadErrors.FILE_OPEN); } - return; + /** + * Clears read listener + * + * @throws RuntimeException + */ + public void clearReadListener() throws RuntimeException { + synchronized(LOCK_READ) { + if(mSerial == null) { + return; + } + mSerial.clearReadListener(); + } } - File file = new File(filePath); - if(!file.exists() || !file.isFile() || !file.canRead()) { - if(callback != null){ callback.onError(UploadErrors.FILE_OPEN); } - return; + /** + * Writes to a device. + * + * @param buf + * @return written byte size + * @throws RuntimeException + */ + public int write(byte[] buf) throws RuntimeException { + if(mSerial == null) { + return 0; + } + return write(buf, buf.length); } - InputStream is; - try { - is = new FileInputStream(filePath); - } catch(Exception e) { - if(callback != null){ callback.onError(UploadErrors.FILE_OPEN); } - return; + /** + * Writes to a device. + * + * @param buf + * @param size + * @return written byte size + * @throws RuntimeException + */ + public int write(byte[] buf, int size) throws RuntimeException { + synchronized(LOCK_WRITE) { + if(mSerial == null) { + return 0; + } + return mSerial.write(buf, size); + } } - upload(board, is, callback); - } - - /** - * Uploads a binary file to a device on background process. No need to open(). - * @param board board profile e.g. Boards.ARDUINO_UNO - * @param fileStream a binary stream e.g. getResources().getAssets().open("Blink.uno.hex") - * @throws RuntimeException - */ - public void upload(Boards board, InputStream fileStream) throws RuntimeException { - upload(board, fileStream, null); - } - - boolean serialIsNull = false; - /** - * Uploads a binary file to a device on background process. No need to open(). - * @param board board profile e.g. Boards.ARDUINO_UNO - * @param fileStream a binary stream e.g. getResources().getAssets().open("Blink.uno.hex") - * @param callback - * @throws RuntimeException - */ - public void upload(Boards board, InputStream fileStream, UploadCallBack callback) throws RuntimeException { - mUploader = new Uploader(); - mCallBack = callback; - mFileStream = fileStream; - mBoard = board; - - if (mSerial == null) { // if not open - if(DEBUG_SHOW) { Log.d(TAG, "upload : mSerial is null"); } - mSerial = new AutoCommunicator() - .getSerialCommunicator(mContext); // need to run on non-thread - serialIsNull = true; + + /** + * Uploads a binary file to a device on background process. No need to + * open(). + * + * @param board board profile e.g. Boards.ARDUINO_UNO + * @param filePath a binary file path e.g. /sdcard/arduino/Blink.hex + * @throws RuntimeException + */ + public void upload(Boards board, String filePath) throws RuntimeException { + upload(board, filePath, null); } - mUploadThread = new Thread(new Runnable() { - @Override - public void run() { - synchronized (LOCK) { - synchronized (LOCK_WRITE) { - synchronized (LOCK_READ) { - UartConfig tmpUartConfig = new UartConfig(); + /** + * Uploads a binary file to a device on background process. No need to + * open(). + * + * @param board board profile e.g. Boards.ARDUINO_UNO + * @param filePath a binary file path e.g. /sdcard/arduino/Blink.uno.hex + * @param callback + * @throws RuntimeException + */ + public void upload(Boards board, String filePath, UploadCallBack callback) throws RuntimeException { + if(filePath == null) { + if(callback != null) { + callback.onError(UploadErrors.FILE_OPEN); + } + return; + } + File file = new File(filePath); + if(!file.exists() || !file.isFile() || !file.canRead()) { + if(callback != null) { + callback.onError(UploadErrors.FILE_OPEN); + } + return; + } + + InputStream is; + try { + is = new FileInputStream(filePath); + } catch(Exception e) { + if(callback != null) { + callback.onError(UploadErrors.FILE_OPEN); + } + return; + } + upload(board, is, callback); + } - if (mSerial == null) { // fail - if(DEBUG_SHOW) { Log.d(TAG, "upload : mSerial is null"); } - if (mCallBack != null) { - mCallBack.onError(UploadErrors.OPEN_DEVICE); + /** + * Uploads a binary file to a device on background process. No need to + * open(). + * + * @param board board profile e.g. Boards.ARDUINO_UNO + * @param fileStream a binary stream e.g. + * getResources().getAssets().open("Blink.uno.hex") + * @throws RuntimeException + */ + public void upload(Boards board, InputStream fileStream) throws RuntimeException { + upload(board, fileStream, null); + } + boolean serialIsNull = false; + + /** + * Uploads a binary file to a device on background process. No need to + * open(). + * + * @param board board profile e.g. Boards.ARDUINO_UNO + * @param fileStream a binary stream e.g. + * getResources().getAssets().open("Blink.uno.hex") + * @param callback + * @throws RuntimeException + */ + public void upload(Boards board, InputStream fileStream, UploadCallBack callback) throws RuntimeException { + mUploader = new Uploader(); + mCallBack = callback; + mFileStream = fileStream; + mBoard = board; + + if(mSerial == null) { // if not open + if(DEBUG_SHOW) { + Log.d(TAG, "upload : mSerial is null"); + } + mSerial = new AutoCommunicator(USE_USB, USE_WIFI, USE_BLUETOOTH, mDport, mCport, mNetdest, mBlueName).getSerialCommunicator(mContext); // need to run on non-thread + serialIsNull = true; + } + + mUploadThread = new Thread(new Runnable() { + + @Override + @SuppressWarnings("NestedSynchronizedStatement") + public void run() { + synchronized(LOCK) { + synchronized(LOCK_WRITE) { + synchronized(LOCK_READ) { + UartConfig tmpUartConfig = new UartConfig(); + + + if(mSerial == null) { // fail + if(DEBUG_SHOW) { + Log.d(TAG, "upload : mSerial is null"); + } + if(mCallBack != null) { + mCallBack.onError(UploadErrors.OPEN_DEVICE); + } + mBoard = null; + mFileStream = null; + mCallBack = null; + mUploader = null; + mSerial = null; + return; + } + + if(!mSerial.isOpened()) { + if(!mSerial.open()) { + if(DEBUG_SHOW) { + Log.d(TAG, "upload : cannot mSerial.open"); + } + if(mCallBack != null) { + mCallBack.onError(UploadErrors.OPEN_DEVICE); + } + mBoard = null; + mFileStream = null; + mCallBack = null; + mUploader = null; + mSerial = null; + return; + } + if(DEBUG_SHOW) { + Log.d(TAG, "upload : open successful"); + } + } else { // if already open + UartConfig origUartConfig = mSerial.getUartConfig(); + tmpUartConfig.baudrate = origUartConfig.baudrate; + tmpUartConfig.dataBits = origUartConfig.dataBits; + tmpUartConfig.stopBits = origUartConfig.stopBits; + tmpUartConfig.parity = origUartConfig.parity; + tmpUartConfig.dtrOn = origUartConfig.dtrOn; + tmpUartConfig.rtsOn = origUartConfig.rtsOn; + if(DEBUG_SHOW) { + Log.d(TAG, "upload : already open"); + } + } + + mSerial.stopReadListener(); + mSerial.clearBuffer(); + + mUploader.upload(mFileStream, mBoard, mSerial, mCallBack); + + mSerial.setUartConfig(tmpUartConfig); // recover if already + // open + mSerial.clearBuffer(); + mSerial.startReadListener(); + if(serialIsNull) { + mSerial.close(); + } + + mBoard = null; + mFileStream = null; + mCallBack = null; + mUploader = null; + } + } + } } - mBoard = null; - mFileStream = null; - mCallBack = null; - mUploader = null; - mSerial = null; + }); + + mUploadThread.start(); + } + + public void cancelUpload() { + if(mUploadThread == null) { return; - } - - if(!mSerial.isOpened()){ - if(!mSerial.open()) { - if(DEBUG_SHOW) { Log.d(TAG, "upload : cannot mSerial.open"); } - if (mCallBack != null) { mCallBack.onError(UploadErrors.OPEN_DEVICE); } - mBoard = null; - mFileStream = null; - mCallBack = null; - mUploader = null; - mSerial = null; - return; + } + mUploadThread.interrupt(); + } + + /** + * Callbacks of program process
normal process:
onPreUpload() -> + * onUploading -> onPostUpload
cancel:
onPreUpload() -> + * onUploading -> onCancel -> onPostUpload
error:
onPreUpload + * |
onUploading | -> onError
onPostUpload |
+ * + * @author keisuke + * + */ + public interface UploadCallBack { + /* + * Callback methods + */ + + void onPreUpload(); + + void onUploading(int value); + + void onPostUpload(boolean success); + + void onCancel(); + + void onError(UploadErrors err); + } + + /** + * Gets opened or closed status + * + * @return true : opened, false : closed + * @throws RuntimeException + */ + public boolean isOpened() throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return false; } - if(DEBUG_SHOW) { Log.d(TAG, "upload : open successful"); } - } else { // if already open - UartConfig origUartConfig = mSerial.getUartConfig(); - tmpUartConfig.baudrate = origUartConfig.baudrate; - tmpUartConfig.dataBits = origUartConfig.dataBits; - tmpUartConfig.stopBits = origUartConfig.stopBits; - tmpUartConfig.parity = origUartConfig.parity; - tmpUartConfig.dtrOn = origUartConfig.dtrOn; - tmpUartConfig.rtsOn = origUartConfig.rtsOn; - if(DEBUG_SHOW) { Log.d(TAG, "upload : already open"); } - } - - mSerial.stopReadListener(); - mSerial.clearBuffer(); - - mUploader.upload(mFileStream, mBoard, mSerial, mCallBack); - - mSerial.setUartConfig(tmpUartConfig); // recover if already - // open - mSerial.clearBuffer(); - mSerial.startReadListener(); - if (serialIsNull) { - mSerial.close(); - } - - mBoard = null; - mFileStream = null; - mCallBack = null; - mUploader = null; - }}} - } - }); - - mUploadThread.start(); - } - - public void cancelUpload() { - if(mUploadThread == null){ return; } - mUploadThread.interrupt(); - } - - /** - * Callbacks of program process
- * normal process:
- * onPreUpload() -> onUploading -> onPostUpload
- * cancel:
- * onPreUpload() -> onUploading -> onCancel -> onPostUpload
- * error:
- * onPreUpload |
- * onUploading | -> onError
- * onPostUpload |
- * @author keisuke - * - */ - public interface UploadCallBack{ - /* - * Callback methods - */ - void onPreUpload(); - void onUploading(int value); - void onPostUpload(boolean success); - void onCancel(); - void onError(UploadErrors err); - } - - /** - * Gets opened or closed status - * @return true : opened, false : closed - * @throws RuntimeException - */ - public boolean isOpened() throws RuntimeException { - synchronized (LOCK) { - if(mSerial == null) return false; - return mSerial.isOpened(); + return mSerial.isOpened(); + } } - } - - /** - * Sets Serial Configuration - * @param settings - */ - public void setConfig(UartConfig settings) throws RuntimeException{ - synchronized (LOCK) { - if(mSerial == null) return; - mSerial.setUartConfig(settings); + + /** + * Sets Serial Configuration + * + * @param settings + */ + public void setConfig(UartConfig settings) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return; + } + mSerial.setUartConfig(settings); + } } - } - - /** - * Sets Baud Rate - * @param baudrate any baud-rate e.g. 9600 - * @return true : successful, false : fail - */ - public boolean setBaudrate(int baudrate) throws RuntimeException{ - synchronized (LOCK) { - if(mSerial == null) return false; - return mSerial.setBaudrate(baudrate); + + /** + * Sets Baud Rate + * + * @param baudrate any baud-rate e.g. 9600 + * @return true : successful, false : fail + */ + public boolean setBaudrate(int baudrate) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return false; + } + return mSerial.setBaudrate(baudrate); + } } - } - - /** - * Sets Data Bits - * @param dataBits data bits e.g. UartConfig.DATA_BITS8 - * @return true : successful, false : fail - */ - public boolean setDataBits(int dataBits) throws RuntimeException{ - synchronized (LOCK) { - if(mSerial == null) return false; - return mSerial.setDataBits(dataBits); + + /** + * Sets Data Bits + * + * @param dataBits data bits e.g. UartConfig.DATA_BITS8 + * @return true : successful, false : fail + */ + public boolean setDataBits(int dataBits) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return false; + } + return mSerial.setDataBits(dataBits); + } } - } - - /** - * Sets Parity Bits - * @param parity parity bits e.g. UartConfig.PARITY_NONE - * @return true : successful, false : fail - */ - public boolean setParity(int parity) throws RuntimeException{ - synchronized (LOCK) { - if(mSerial == null) return false; - return mSerial.setParity(parity); + + /** + * Sets Parity Bits + * + * @param parity parity bits e.g. UartConfig.PARITY_NONE + * @return true : successful, false : fail + */ + public boolean setParity(int parity) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return false; + } + return mSerial.setParity(parity); + } } - } - - /** - * Sets Stop bits - * @param stopBits stop bits e.g. UartConfig.STOP_BITS1 - * @return true : successful, false : fail - */ - public boolean setStopBits(int stopBits) throws RuntimeException{ - synchronized (LOCK) { - if(mSerial == null) return false; - return mSerial.setStopBits(stopBits); + + /** + * Sets Stop bits + * + * @param stopBits stop bits e.g. UartConfig.STOP_BITS1 + * @return true : successful, false : fail + */ + public boolean setStopBits(int stopBits) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return false; + } + return mSerial.setStopBits(stopBits); + } + } + + /** + * Sets flow control DTR/RTS + * + * @param dtrOn true then DTR on + * @param rtsOn true then RTS on + * @return true : successful, false : fail + */ + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) throws RuntimeException { + synchronized(LOCK) { + if(mSerial == null) { + return false; + } + return mSerial.setDtrRts(dtrOn, rtsOn); + } + } + + public String getDriverName() { + if(mSerial == null) { + return "None"; + } + return mSerial.getClass().getName(); + } + public String getPhysicalConnectionName() { + if(mSerial == null) { + return "No Physical Connection"; + } + return mSerial.getPhysicalConnectionName(); + } + + public int getPhysicalConnectionType() { + if(mSerial == null) { + return 0; + } + return mSerial.getPhysicalConnectionType(); } - } - - /** - * Sets flow control DTR/RTS - * @param dtrOn true then DTR on - * @param rtsOn true then RTS on - * @return true : successful, false : fail - */ - public boolean setDtrRts(boolean dtrOn, boolean rtsOn) throws RuntimeException{ - synchronized (LOCK) { - if(mSerial == null) return false; - return mSerial.setDtrRts(dtrOn, rtsOn); + public void setDebug(boolean flag) { + if(mSerial != null) { + mSerial.setDebug(flag); + } } - } } diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/UsbVidList.java b/PhysicaloidLibrary/src/com/physicaloid/lib/UsbVidList.java index 951c02d..bad2053 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/lib/UsbVidList.java +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/UsbVidList.java @@ -18,11 +18,13 @@ public enum UsbVidList { ARDUINO (0x2341), + DCCDUINO (0x1A86), FTDI (0x0403), MBED_LPC1768 (0x0d28), MBED_LPC11U24 (0x0d28), MBED_FRDM_KL25Z_OPENSDA_PORT (0x1357), MBED_FRDM_KL25Z_KL25Z_PORT (0x15a2), + WCH (0x4348), CP210X (0x10C4); int vid; diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/bluetooth/driver/uart/UartBluetooth.java b/PhysicaloidLibrary/src/com/physicaloid/lib/bluetooth/driver/uart/UartBluetooth.java new file mode 100644 index 0000000..9b44748 --- /dev/null +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/bluetooth/driver/uart/UartBluetooth.java @@ -0,0 +1,431 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.physicaloid.lib.bluetooth.driver.uart; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothServerSocket; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.util.Log; +import com.physicaloid.BuildConfig; +import com.physicaloid.lib.Physicaloid; +import com.physicaloid.lib.framework.SerialCommunicator; +import com.physicaloid.lib.usb.driver.uart.ReadLisener; +import com.physicaloid.lib.usb.driver.uart.ReadListener; +import com.physicaloid.lib.usb.driver.uart.UartConfig; +import com.physicaloid.misc.RingBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * + * @author root + */ +public class UartBluetooth extends SerialCommunicator { + + private static final String TAG = UartBluetooth.class.getSimpleName(); + private boolean DEBUG_SHOW = false; + private static final int DEFAULT_BAUDRATE = 9600; + private UartConfig mUartConfig; + private static final int RING_BUFFER_SIZE = 1024; + private static final int READ_BUFFER_SIZE = 256; + private static final int WRITE_BUFFER_SIZE = 256; + private RingBuffer mBuffer; + private boolean mReadThreadStop = true; + private boolean isOpened; + private String mBlueName; + private static final UUID uu = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + private BluetoothSocket DATA_socket; + volatile boolean DATA_keep_going = true; + volatile boolean DATA_still_going = true; + private DataOutputStream DATA_OUT; + private DataInputStream DATA_IN; + private BluetoothAdapter mBluetoothAdapter; + private BluetoothServerSocket serverSocket; + + public UartBluetooth(Context context, String BlueName) { + super(context); + mUartConfig = new UartConfig(); + mBuffer = new RingBuffer(RING_BUFFER_SIZE); + mBlueName = BlueName; + isOpened = false; + DATA_socket = null; + DATA_OUT = null; + DATA_IN = null; + } + + @Override + public boolean open() { + if(!init()) { + return false; + } + if(!setBaudrate(DEFAULT_BAUDRATE)) { + return false; + } + mBuffer.clear(); + startRead(); + isOpened = true; + return true; + } + private Runnable connect_DATA = new Runnable() { + + InetAddress serverAddr; + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public void run() { + while(DATA_keep_going) { + try { + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if(mBluetoothAdapter != null) { + if(mBluetoothAdapter.isEnabled()) { + serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(mBlueName, uu); + DATA_socket = serverSocket.accept(); + DATA_OUT = new DataOutputStream(DATA_socket.getOutputStream()); + DATA_IN = new DataInputStream(DATA_socket.getInputStream()); + DATA_still_going = false; + return; + } + } + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + } + DATA_still_going = false; + } + }; + + @SuppressWarnings({"SleepWhileInLoop", "CallToThreadDumpStack"}) + private boolean init() { + DATA_keep_going = true; + DATA_still_going = true; + + Log.d(TAG, "********************* Bluetooth Connecting DATA **************"); + new Thread(connect_DATA).start(); + Log.d(TAG, "********************* Bluetooth WAITING **************"); + // timeout after how many seconds? How about 30? + int timeout = (30 * 1000) / 50; + while(DATA_still_going && (timeout > 0)) { + try { + // STALL APP :-) + Thread.sleep(50); + timeout--; + } catch(InterruptedException ex) { + } + } + if(timeout == 0) { + // did not connect, kill threads. + DATA_keep_going = false; + while(DATA_still_going) { + try { + Thread.sleep(50); + } catch(InterruptedException ex) { + } + } + Log.d(TAG, "********************* Bluetooth Timed out! **************"); + return false; + } + try { + DATA_OUT = new DataOutputStream(DATA_socket.getOutputStream()); + DATA_IN = new DataInputStream(DATA_socket.getInputStream()); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + Log.d(TAG, "********************* Bluetooth Connected! **************"); + return true; + } + + @Override + @SuppressWarnings({"SleepWhileInLoop", "CallToThreadDumpStack"}) + public boolean close() { + stopRead(); + isOpened = false; + if(DATA_OUT != null) { + try { + DATA_OUT.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + } + if(DATA_IN != null) { + try { + DATA_IN.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + } + if(DATA_socket != null) { + try { + DATA_socket.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + } + DATA_keep_going = false; + while(DATA_still_going) { + try { + Thread.sleep(50); + } catch(InterruptedException ex) { + } + } + + return true; + } + + @Override + public int read(byte[] buf, int size) { + return mBuffer.get(buf, size); + } + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public int write(byte[] buf, int size) { + try { + DATA_OUT.write(buf, 0, size); + DATA_OUT.flush(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + return size; + } + + @Override + public boolean setBaudrate(int baudrate) { + // We don't do this... + mUartConfig.baudrate = baudrate; + return true; + } + + @Override + public boolean setDataBits(int dataBits) { + // We don't do this... + mUartConfig.dataBits = dataBits; + return true; + } + + @Override + public boolean setParity(int parity) { + // We don't do this... + mUartConfig.parity = parity; + return true; + } + + @Override + public boolean setStopBits(int stopBits) { + // We don't do this... + mUartConfig.stopBits = stopBits; + return true; + } + + @Override + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { + // We don't do this... + mUartConfig.dtrOn = dtrOn; + mUartConfig.rtsOn = rtsOn; + return true; + } + + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + /** + * Sets Uart configurations + * + * @param config configurations + * @return true : successful, false : fail + */ + public boolean setUartConfig(UartConfig config) { + boolean res; + boolean ret = true; + if(mUartConfig.baudrate != config.baudrate) { + res = setBaudrate(config.baudrate); + ret = ret && res; + } + + if(mUartConfig.dataBits != config.dataBits) { + res = setDataBits(config.dataBits); + ret = ret && res; + } + + if(mUartConfig.parity != config.parity) { + res = setParity(config.parity); + ret = ret && res; + } + + if(mUartConfig.stopBits != config.stopBits) { + res = setStopBits(config.stopBits); + ret = ret && res; + } + + if(mUartConfig.dtrOn != config.dtrOn + || mUartConfig.rtsOn != config.rtsOn) { + res = setDtrRts(config.dtrOn, config.rtsOn); + ret = ret && res; + } + + return ret; + } + + @Override + public boolean isOpened() { + return isOpened; + } + + @Override + public UartConfig getUartConfig() { + return mUartConfig; + } + + @Override + public int getBaudrate() { + return mUartConfig.baudrate; + } + + @Override + public int getDataBits() { + return mUartConfig.dataBits; + } + + @Override + public int getParity() { + return mUartConfig.parity; + } + + @Override + public int getStopBits() { + return mUartConfig.stopBits; + } + + @Override + public boolean getDtr() { + return mUartConfig.dtrOn; + } + + @Override + public boolean getRts() { + return mUartConfig.rtsOn; + } + + @Override + public void clearBuffer() { + mBuffer.clear(); + } + ////////////////////////////////////////////////////////// + // Listener for reading uart + ////////////////////////////////////////////////////////// + private List uartReadListenerList = new ArrayList(); + private boolean mStopReadListener = false; + + @Override + public void addReadListener(ReadListener listener) { + uartReadListenerList.add(listener); + } + + @Override + @Deprecated + public void addReadListener(ReadLisener listener) { + addReadListener((ReadListener) listener); + } + + @Override + public void clearReadListener() { + uartReadListenerList.clear(); + } + + @Override + public void startReadListener() { + mStopReadListener = false; + } + + @Override + public void stopReadListener() { + mStopReadListener = true; + } + + private void onRead(int size) { + if(mStopReadListener) { + return; + } + for(ReadListener listener : uartReadListenerList) { + listener.onRead(size); + } + } + ////////////////////////////////////////////////////////// + + private void stopRead() { + mReadThreadStop = true; + } + + private void startRead() { + if(mReadThreadStop) { + mReadThreadStop = false; + new Thread(mLoop).start(); + } + } + private Runnable mLoop = new Runnable() { + + @Override + public void run() { + int len; + byte[] rbuf = new byte[READ_BUFFER_SIZE]; + android.os.Process.setThreadPriority(-20); + //ByteBuffer buf = ByteBuffer.wrap(rbuf); + for(;;) { + try { + // this is the main loop for transferring + len = 0; + //if (request.queue(buf, rbuf.length)) { + // response = mConnection.requestWait(); + // if (response != null) { + // len = buf.position(); + // } + + while(DATA_IN.available() > 0 && len < READ_BUFFER_SIZE) { + DATA_IN.read(rbuf, len, 1); + len++; + } + if(len > 0) { + mBuffer.add(rbuf, len); + onRead(len); + } + if(mReadThreadStop) { + return; + } + } catch(IOException ex) { + // TO-DO: Needs to broadcast that it has been disconnected.... + } + } + } // end of run() + }; // end of runnable + + @Override + public String getPhysicalConnectionName() { + return Physicaloid.BLUETOOTH_STRING; + } + + @Override + public int getPhysicalConnectionType() { + return Physicaloid.BLUETOOTH; + } + + @Override + public void setDebug(boolean flag) { + DEBUG_SHOW = flag; + } +} diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpga.java b/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpga.java index 3b9a7cc..afac32c 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpga.java +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpga.java @@ -1,9 +1,8 @@ package com.physicaloid.lib.fpga; import android.content.Context; - -import com.physicaloid.lib.Physicaloid; import com.physicaloid.BuildConfig; +import com.physicaloid.lib.Physicaloid; public class PhysicaloidFpga extends Physicaloid { @SuppressWarnings("unused") diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpgaConfigurator.java b/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpgaConfigurator.java index 3cce930..5aae4a2 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpgaConfigurator.java +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/fpga/PhysicaloidFpgaConfigurator.java @@ -1,12 +1,10 @@ package com.physicaloid.lib.fpga; -import java.io.IOException; -import java.io.InputStream; - import android.util.Log; - import com.physicaloid.BuildConfig; import com.physicaloid.lib.framework.SerialCommunicator; +import java.io.IOException; +import java.io.InputStream; public class PhysicaloidFpgaConfigurator { @@ -28,15 +26,15 @@ public PhysicaloidFpgaConfigurator(SerialCommunicator comm) { public boolean configuration(InputStream is) { if(is == null) return false; byte[] rbuf = new byte[1]; - int retlen=0; - boolean readStatus=true; + int retlen; + boolean readStatus=false; ////////////////////////////////////////////////////// // Switch user mode and check PS mode on ////////////////////////////////////////////////////// if(DEBUG_SHOW){Log.d(TAG,"Configuration Step.1 : Switch user mode.");} - for(int i=0; i 0) { - startTime = System.currentTimeMillis(); - if(DEBUG_SHOW_DRAIN) { - Log.d(TAG, "drain("+retval+") : " +toHexStr(buf[0])); - } - } - endTime = System.currentTimeMillis(); - if((endTime - startTime) > 250) {break;} +public class Stk500V2 extends UploadProtocol { + + private static final String TAG = Stk500V2.class.getSimpleName(); + private static final boolean DEBUG_NOT_SHOW = true || !BuildConfig.DEBUG; + private static final boolean DEBUG_SHOW_READ = true && !DEBUG_NOT_SHOW; + private static final boolean DEBUG_SHOW_WRITE = true && !DEBUG_NOT_SHOW; + private static final boolean DEBUG_SHOW_COMMAND = true && !DEBUG_NOT_SHOW; + private static final boolean DEBUG_SHOW_COMMAND_STATUS = true && !DEBUG_NOT_SHOW; + private static final boolean DEBUG_SHOW_RECV = true && !DEBUG_NOT_SHOW; + private static final boolean DEBUG_SHOW_GETSYNC = true && !DEBUG_NOT_SHOW; + private static final boolean DEBUG_SHOW_DRAIN = true && !DEBUG_NOT_SHOW; + private static final int RETRIES = 1; // was 5. Why is it 5? + // *** XPROG command constants *** + private static final int CMD_XPROG = 0x50; + private static final int CMD_XPROG_SETMODE = 0x51; + private static final int XPRG_ERR_OK = 0; + private static final int XPRG_ERR_FAILED = 1; + private static final int XPRG_ERR_COLLISION = 2; + private static final int XPRG_ERR_TIMEOUT = 3; + // *****************[ STK status constants ]*************************** + // Success + private static final int STATUS_CMD_OK = 0x00; + // Warnings + private static final int STATUS_CMD_TOUT = 0x80; + private static final int STATUS_RDY_BSY_TOUT = 0x81; + private static final int STATUS_SET_PARAM_MISSING = 0x82; + // Errors + private static final int STATUS_CMD_FAILED = 0xC0; + @SuppressWarnings("unused") + private static final int STATUS_CKSUM_ERROR = 0xC1; + @SuppressWarnings("unused") + private static final int STATUS_CMD_UNKNOWN = 0xC9; + @SuppressWarnings("unused") + private static final int STATUS_CMD_ILLEGAL_PARAMETER = 0xCA; + // Status + @SuppressWarnings("unused") + private static final int STATUS_ISP_READY = 0x00; + @SuppressWarnings("unused") + private static final int STATUS_CONN_FAIL_MOSI = 0x01; + @SuppressWarnings("unused") + private static final int STATUS_CONN_FAIL_RST = 0x02; + @SuppressWarnings("unused") + private static final int STATUS_CONN_FAIL_SCK = 0x04; + @SuppressWarnings("unused") + private static final int STATUS_TGT_NOT_DETECTED = 0x10; + @SuppressWarnings("unused") + private static final int STATUS_TGT_REVERSE_INSERTED = 0x20; + // hw_status + // Bits in status variable + // Bit 0-3: Slave MCU + // Bit 4-7: Master MCU + @SuppressWarnings("unused") + private static final int STATUS_AREF_ERROR = 0; + // Set to '1' if AREF is short circuited + @SuppressWarnings("unused") + private static final int STATUS_VTG_ERROR = 4; + // Set to '1' if VTG is short circuited + @SuppressWarnings("unused") + private static final int STATUS_RC_CARD_ERROR = 5; + // Set to '1' if board id changes when board is powered + @SuppressWarnings("unused") + private static final int STATUS_PROGMODE = 6; + // Set to '1' if board is in programming mode + @SuppressWarnings("unused") + private static final int STATUS_POWER_SURGE = 7; + // Set to '1' if board draws excessive current + // *****************[ STK message constants ]*************************** + private static final byte MESSAGE_START = 0x1B; //= ESC = 27 decimal + private static final byte TOKEN = 0x0E; + // *****************[ STK general command constants ]************************** + private static final byte CMD_SIGN_ON = 0x01; + @SuppressWarnings("unused") + private static final byte CMD_SET_PARAMETER = 0x02; + @SuppressWarnings("unused") + private static final byte CMD_GET_PARAMETER = 0x03; + @SuppressWarnings("unused") + private static final byte CMD_SET_DEVICE_PARAMETERS = 0x04; + @SuppressWarnings("unused") + private static final byte CMD_OSCCAL = 0x05; + private static final byte CMD_LOAD_ADDRESS = 0x06; + @SuppressWarnings("unused") + private static final byte CMD_FIRMWARE_UPGRADE = 0x07; + @SuppressWarnings("unused") + private static final byte CMD_CHECK_TARGET_CONNECTION = 0x0D; + @SuppressWarnings("unused") + private static final byte CMD_LOAD_RC_ID_TABLE = 0x0E; + @SuppressWarnings("unused") + private static final byte CMD_LOAD_EC_ID_TABLE = 0x0F; + // *****************[ STK ISP command constants ]****************************** + private static final byte CMD_ENTER_PROGMODE_ISP = 0x10; + private static final byte CMD_LEAVE_PROGMODE_ISP = 0x11; + @SuppressWarnings("unused") + private static final byte CMD_CHIP_ERASE_ISP = 0x12; + private static final byte CMD_PROGRAM_FLASH_ISP = 0x13; + @SuppressWarnings("unused") + private static final byte CMD_READ_FLASH_ISP = 0x14; + private static final byte CMD_PROGRAM_EEPROM_ISP = 0x15; + @SuppressWarnings("unused") + private static final byte CMD_READ_EEPROM_ISP = 0x16; + @SuppressWarnings("unused") + private static final byte CMD_PROGRAM_FUSE_ISP = 0x17; + @SuppressWarnings("unused") + private static final byte CMD_READ_FUSE_ISP = 0x18; + @SuppressWarnings("unused") + private static final byte CMD_PROGRAM_LOCK_ISP = 0x19; + @SuppressWarnings("unused") + private static final byte CMD_READ_LOCK_ISP = 0x1A; + @SuppressWarnings("unused") + private static final byte CMD_READ_SIGNATURE_ISP = 0x1B; + @SuppressWarnings("unused") + private static final byte CMD_READ_OSCCAL_ISP = 0x1C; + @SuppressWarnings("unused") + private static final byte CMD_SPI_MULTI = 0x1D; + // *****************[ STK answer constants ]*************************** + private static final int ANSWER_CKSUM_ERROR = 0xB0; + private static final int PGMTYPE_UNKNOWN = 0; + private static final int PGMTYPE_STK500 = 1; + private static final int PGMTYPE_AVRISP = 2; + private static final int PGMTYPE_AVRISP_MKII = 3; + @SuppressWarnings("unused") + private static final int PGMTYPE_JTAGICE_MKII = 4; + private static final int PGMTYPE_STK600 = 5; + private int mCommandSeqNum = 1; + private int mProgrammerType = PGMTYPE_UNKNOWN; + private SerialCommunicator mComm; + private AvrConf mAVRConf; + private AVRMem mAVRMem; + + public Stk500V2() { } - return retval; - } - private int send(byte[] data, int len) { - byte[] buf = new byte[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead - int i; - - /* - * if (PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || PDATA(pgm)->pgmtype - * == PGMTYPE_STK600) return stk500v2_send_mk2(pgm, data, len); else if - * (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) return - * stk500v2_jtagmkII_send(pgm, data, len); - */ - buf[0] = MESSAGE_START; - buf[1] = (byte) mCommandSeqNum; - buf[2] = (byte) (len / 256); - buf[3] = (byte) (len % 256); - buf[4] = TOKEN; - System.arraycopy(data, 0, buf, 5, len); - - // calculate the XOR checksum - buf[5 + len] = 0; - for (i = 0; i < 5 + len; i++) - buf[5 + len] ^= buf[i]; - - return write(buf, len + 6); - - } - - private int command(byte[] buf, int len, int maxlen) { - int i; - int tries = 0; - int status; - boolean bRetry=true; - - if(DEBUG_SHOW_COMMAND) { Log.d(TAG, "STK500V2.command("+toHexStr(buf, len)+", "+len+")"); } - - while (bRetry) { - bRetry = false; - tries++; - - // send the command to the programmer - send(buf, len); - // attempt to read the status back - status = recv(buf, maxlen); - - if (DEBUG_SHOW_COMMAND_STATUS) { - Log.d(TAG, "STK500V2.command(): status:"+status+",buf{"+toHexStr(buf, buf.length)+"}"); - } - - // if we got a successful readback, return - if (status > 0) { - if (DEBUG_SHOW_COMMAND_STATUS) { - Log.d(TAG, "status = " + status); - } - if (status < 2) { - Log.e(TAG, "STK500V2.command(): short reply\n"); - return -1; - } - if (buf[0] == CMD_XPROG_SETMODE || buf[0] == CMD_XPROG) { - /* - * Decode XPROG wrapper errors. - */ - String msg; - - /* - * For CMD_XPROG_SETMODE, the status is returned in buf[1]. - * For CMD_XPROG, buf[1] contains the XPRG_CMD_* command, - * and buf[2] contains the status. - */ - i = (buf[0] == CMD_XPROG_SETMODE) ? 1 : 2; - - if (buf[i] != XPRG_ERR_OK) { - switch (buf[i]) { - case XPRG_ERR_FAILED: - msg = "Failed"; - break; - case XPRG_ERR_COLLISION: - msg = "Collision"; - break; - case XPRG_ERR_TIMEOUT: - msg = "Timeout"; - break; - default: - msg = "Unknown"; - break; - } - Log.e(TAG, "STK500V2.command(): error in " + - (buf[0] == CMD_XPROG_SETMODE ? "CMD_XPROG_SETMODE" : "CMD_XPROG") - + ": " + msg); - return -1; - } - return 0; - } else { - /* - * Decode STK500v2 errors. - */ - if (buf[1] >= STATUS_CMD_TOUT && buf[1] < 0xa0) { - String msg; -// byte[] msgbuf = new byte[30]; - switch (buf[1]) { - case (byte) STATUS_CMD_TOUT: - msg = "Command timed out"; - break; + public void setSerial(SerialCommunicator comm) { + mComm = comm; + } + // Warning exporting non-public type through public API - case (byte) STATUS_RDY_BSY_TOUT: - msg = "Sampling of the RDY/nBSY pin timed out"; - break; + public void setConfig(AvrConf avrConf, AVRMem avrMem) { + mAVRConf = avrConf; + mAVRMem = avrMem; + } - case (byte) STATUS_SET_PARAM_MISSING: - msg = "The `Set Device Parameters' have not been " - + "executed in advance of this command"; + @SuppressWarnings("unused") + private void init() { + mCommandSeqNum = 1; + } - default: - msg = "unknown, code " + Integer.toHexString((int) buf[1]); - break; + // リードバッファをカラにする Empty the read buffer + private int drain() { + byte[] buf = new byte[1]; + int retval = 0; + long endTime; + long startTime = System.currentTimeMillis(); + while(true) { + retval = mComm.read(buf, 1); + if(retval > 0) { + startTime = System.currentTimeMillis(); + if(DEBUG_SHOW_DRAIN) { + Log.d(TAG, "drain(" + retval + ") : " + toHexStr(buf[0])); + } } - if (DEBUG_SHOW_COMMAND_STATUS) { - Log.v(TAG, "STK500V2.command(): warning: " + msg); + endTime = System.currentTimeMillis(); + if((endTime - startTime) > 250) { + break; } - } else if (buf[1] == (byte) STATUS_CMD_OK) { - return status; - } else if (buf[1] == (byte) STATUS_CMD_FAILED) { - Log.e(TAG, "STK500V2.command(): command failed"); - } else { - Log.e(TAG, - "STK500V2.command(): unknown status " - + Integer.toHexString((int) buf[1])); - } - return -1; } - } // end of if (status > 0) - - // otherwise try to sync up again - status = getsync(); - if (status != 0) { - if (tries > RETRIES) { - Log.e(TAG, - "STK500V2.command(): failed miserably to execute command " - + Integer.toHexString((int) buf[0])); - return -1; - } else { - bRetry = true; + return retval; + } + + private int send(byte[] data, int len) { + byte[] buf = new byte[275 + 6]; // max MESSAGE_BODY of 275 bytes, 6 bytes overhead + int i; + + /* + * if (PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || + * PDATA(pgm)->pgmtype == PGMTYPE_STK600) return + * stk500v2_send_mk2(pgm, data, len); else if + * (PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) return + * stk500v2_jtagmkII_send(pgm, data, len); + */ + buf[0] = MESSAGE_START; + buf[1] = (byte) mCommandSeqNum; + buf[2] = (byte) (len / 256); + buf[3] = (byte) (len % 256); + buf[4] = TOKEN; + System.arraycopy(data, 0, buf, 5, len); + + // calculate the XOR checksum + buf[5 + len] = 0; + for(i = 0; i < 5 + len; i++) { + buf[5 + len] ^= buf[i]; } - } - } // end of while(bRetry) - if (DEBUG_SHOW_COMMAND) { - Log.d(TAG, " = 0"); + return write(buf, len + 6); + } - return 0; - } // end of private int command() + private int command(byte[] buf, int len, int maxlen) { + int i; + int tries = 0; + int status; + boolean bRetry = true; - private boolean compareByteArrayWithString(byte[] buf,int bufPos, String str) { - byte[] tmpbuf = new byte[str.length()]; - System.arraycopy(buf, bufPos, tmpbuf, 0, str.length()); - if(Arrays.equals(tmpbuf, str.getBytes())) { - return true; - } - return false; - } - - private static final String[] PROGRAMMER_NAME = - { - "unknown", - "STK500", - "AVRISP", - "AVRISP mkII", - "JTAG ICE mkII", - "STK600", - }; - - @SuppressWarnings("unused") - private static final int sINIT = 0; - private static final int sSTART = 1; - private static final int sSEQNUM = 2; - private static final int sSIZE1 = 3; - private static final int sSIZE2 = 4; - private static final int sTOKEN = 5; - private static final int sDATA = 6; - private static final int sCSUM = 7; - private static final int sDONE = 8; - - private static final int SERIAL_TIMEOUT = 2; - - int recv(byte[] buf, int length) { - int state = sSTART; - int msglen = 0; - int curlen = 0; - byte[] c = new byte[1]; - c[0] = 0; - byte checksum = 0; - - long timeoutval = SERIAL_TIMEOUT; // seconds + if(DEBUG_SHOW_COMMAND) { + Log.d(TAG, "STK500V2.command(" + toHexStr(buf, len) + ", " + len + ")"); + } - /* - * if (mProgrammerType == PGMTYPE_AVRISP_MKII || mProgrammerType == - * PGMTYPE_STK600) return stk500v2_recv_mk2(pgm, msg, maxsize); else if - * (mProgrammerType == PGMTYPE_JTAGICE_MKII) return - * stk500v2_jtagmkII_recv(pgm, msg, maxsize); - */ - if (DEBUG_SHOW_RECV) { - Log.v(TAG, "STK500V2.recv(): "); - } + while(bRetry) { + bRetry = false; + tries++; + + // send the command to the programmer + send(buf, len); + // attempt to read the status back + // Need to zero buffer + Arrays.fill(buf, 0, maxlen, (byte) 0); + status = recv(buf, maxlen); + + if(DEBUG_SHOW_COMMAND_STATUS) { + Log.d(TAG, "STK500V2.command(): status:" + status + ",buf{" + toHexStr(buf, buf.length) + "}"); + } - long tstart = java.lang.System.currentTimeMillis(); + // if we got a successful readback, return + if(status > 0) { + if(DEBUG_SHOW_COMMAND_STATUS) { + Log.d(TAG, "status = " + status); + } + if(status < 2) { + Log.e(TAG, "STK500V2.command(): short reply\n"); + return -1; + } + if(buf[0] == CMD_XPROG_SETMODE || buf[0] == CMD_XPROG) { + /* + * Decode XPROG wrapper errors. + */ + String msg; + + /* + * For CMD_XPROG_SETMODE, the status is + * returned in buf[1]. For CMD_XPROG, + * buf[1] contains the XPRG_CMD_* + * command, and buf[2] contains the + * status. + */ + i = (buf[0] == CMD_XPROG_SETMODE) ? 1 : 2; + + if(buf[i] != XPRG_ERR_OK) { + switch(buf[i]) { + case XPRG_ERR_FAILED: + msg = "Failed"; + break; + case XPRG_ERR_COLLISION: + msg = "Collision"; + break; + case XPRG_ERR_TIMEOUT: + msg = "Timeout"; + break; + default: + msg = "Unknown"; + break; + } + Log.e(TAG, "STK500V2.command(): error in " + + (buf[0] == CMD_XPROG_SETMODE ? "CMD_XPROG_SETMODE" : "CMD_XPROG") + + ": " + msg); + return -1; + } + return 0; + } else { + /* + * Decode STK500v2 errors. + */ + if(buf[1] >= STATUS_CMD_TOUT && buf[1] < 0xa0) { + String msg; +// byte[] msgbuf = new byte[30]; + switch(buf[1]) { + case (byte) STATUS_CMD_TOUT: + msg = "Command timed out"; + break; + + case (byte) STATUS_RDY_BSY_TOUT: + msg = "Sampling of the RDY/nBSY pin timed out"; + break; + + case (byte) STATUS_SET_PARAM_MISSING: + msg = "The `Set Device Parameters' have not been " + + "executed in advance of this command"; + break; + default: + msg = "unknown, code " + Integer.toHexString((int) buf[1]); + break; + } + if(DEBUG_SHOW_COMMAND_STATUS) { + Log.v(TAG, "STK500V2.command(): warning: " + msg); + } + } else if(buf[1] == (byte) STATUS_CMD_OK) { + return status; + } else if(buf[1] == (byte) STATUS_CMD_FAILED) { + Log.e(TAG, "STK500V2.command(): command failed"); + } else { + Log.e(TAG, + "STK500V2.command(): unknown status " + + Integer.toHexString((int) buf[1])); + } + return -1; + } + } // end of if (status > 0) + + // otherwise try to sync up again + status = getsync(); + if(status != 0) { + if(tries > RETRIES) { + Log.e(TAG, + "STK500V2.command(): failed miserably to execute command " + + Integer.toHexString((int) buf[0])); + return -1; + } else { + bRetry = true; + } + } + } // end of while(bRetry) + + if(DEBUG_SHOW_COMMAND) { + Log.d(TAG, " = 0"); + } + return 0; + } // end of private int command() - while ((state != sDONE)) { - if (read(c, 1) <= 0) { - long tnow = java.lang.System.currentTimeMillis(); - if ((tnow - tstart) / 1000 > timeoutval) { // wuff - - // signed/unsigned/overflow - Log.e(TAG, "STK500V2.recv(): timeout"); - return -1; + private boolean compareByteArrayWithString(byte[] buf, int bufPos, String str) { + byte[] tmpbuf = new byte[str.length()]; + System.arraycopy(buf, bufPos, tmpbuf, 0, str.length()); + if(Arrays.equals(tmpbuf, str.getBytes())) { + return true; } - continue; - } - if (DEBUG_SHOW_RECV) { Log.d(TAG, "recv : "+toHexStr(c[0])); } - checksum ^= c[0]; - - switch (state) { - case sSTART: - if (DEBUG_SHOW_RECV) { Log.d(TAG, "hoping for start token..."); } - - if (c[0] == MESSAGE_START) { - if (DEBUG_SHOW_RECV) { Log.d(TAG, "got it\n"); } - checksum = MESSAGE_START; - state = sSEQNUM; - } else { - if (DEBUG_SHOW_RECV) { Log.d(TAG, "sorry\n"); } - } - break; - - case sSEQNUM: - if (DEBUG_SHOW_RECV) { Log.d(TAG, "hoping for sequence...\n"); } - - if (c[0] == mCommandSeqNum) { - if (DEBUG_SHOW_RECV) { Log.d(TAG, "got it, incrementing\n"); } - state = sSIZE1; - mCommandSeqNum++; - } else { - if (DEBUG_SHOW_RECV) { Log.d(TAG, "sorry\n"); } - state = sSTART; - } - break; - - case sSIZE1: - if (DEBUG_SHOW_RECV) { Log.d(TAG, "hoping for size LSB\n"); } - msglen = ((int) c[0]) * 256; - state = sSIZE2; - break; - - case sSIZE2: - if (DEBUG_SHOW_RECV) { Log.d(TAG, "hoping for size MSB..."); } - msglen += (int) c[0]; - if (DEBUG_SHOW_RECV) { Log.d(TAG, " msg is " + msglen + " bytes"); } - state = sTOKEN; - break; - - case sTOKEN: - if (c[0] == TOKEN) { - if (DEBUG_SHOW_RECV) { Log.d(TAG, "recv : sTOKEN : sDATA"); } - state = sDATA; - } else { - if (DEBUG_SHOW_RECV) { Log.d(TAG, "recv : sTOKEN : sSTART"); } - state = sSTART; - } - break; - - case sDATA: - if (DEBUG_SHOW_RECV) { Log.d(TAG, "recv | sDATA | msglen:"+msglen+", curlen:"+curlen+", length:"+length+", c[0]:"+toHexStr(c[0])); } - if (curlen < length) { - buf[curlen] = c[0]; - } else { - Log.e(TAG, "STK500V2.recv(): buffer too small, received " + curlen - + " byte into " + length + " byte buffer"); - return -2; - } - if ((curlen == 0) && (buf[0] == ANSWER_CKSUM_ERROR)) { - Log.e(TAG, "STK500V2.recv(): previous packet sent with wrong checksum"); - return -3; - } - curlen++; - if (curlen == msglen) { - state = sCSUM; - } - break; - - case sCSUM: - if (DEBUG_SHOW_RECV) { Log.d(TAG, "recv | sCSUM"); } - if (checksum == 0) { - state = sDONE; - } else { - state = sSTART; - Log.e(TAG, "STK500V2.recv(): checksum error"); - return -4; - } - break; - default: - Log.e(TAG, "STK500V2.recv(): unknown state"); - return -5; - } /* switch */ - } /* while */ - - return (int) (msglen + 6); - } - - int getsync() { - int tries = 0; - byte[] buf = new byte[1]; - byte[] resp = new byte[32]; - int status; - boolean bRetry = true; - - if (DEBUG_SHOW_GETSYNC) { - Log.d(TAG, "STK500V2.getsync()"); + return false; } + private static final String[] PROGRAMMER_NAME = { + "unknown", + "STK500", + "AVRISP", + "AVRISP mkII", + "JTAG ICE mkII", + "STK600",}; + @SuppressWarnings("unused") + private static final int sINIT = 0; + private static final int sSTART = 1; + private static final int sSEQNUM = 2; + private static final int sSIZE1 = 3; + private static final int sSIZE2 = 4; + private static final int sTOKEN = 5; + private static final int sDATA = 6; + private static final int sCSUM = 7; + private static final int sDONE = 8; + private static final int SERIAL_TIMEOUT = 2; + + int recv(byte[] buf, int length) { + int state = sSTART; + int msglen = 0; + int curlen = 0; + byte[] c = new byte[1]; + c[0] = 0; + byte checksum = 0; + + long timeoutval = SERIAL_TIMEOUT; // seconds + + /* + * if (mProgrammerType == PGMTYPE_AVRISP_MKII || mProgrammerType + * == PGMTYPE_STK600) return stk500v2_recv_mk2(pgm, msg, + * maxsize); else if (mProgrammerType == PGMTYPE_JTAGICE_MKII) + * return stk500v2_jtagmkII_recv(pgm, msg, maxsize); + */ + if(DEBUG_SHOW_RECV) { + Log.v(TAG, "STK500V2.recv(): "); + } - while (bRetry) { - bRetry = false; - tries++; - - // send the sync command and see if we can get there - buf[0] = CMD_SIGN_ON; - send(buf, 1); - - // try to get the response back and see where we got - status = recv(resp, resp.length); - - // if we got bytes returned, check to see what came back - if (status > 0) { - if ((resp[0] == CMD_SIGN_ON) && (resp[1] == STATUS_CMD_OK) && - (status > 3)) { - // success! - int siglen = resp[2]; - if (siglen >= "STK500_2".length() && - compareByteArrayWithString(resp, 3, "STK500_2")) { - mProgrammerType = PGMTYPE_STK500; - } else if (siglen >= "AVRISP_2".length() && - compareByteArrayWithString(resp, 3, "AVRISP_2")) { - mProgrammerType = PGMTYPE_AVRISP; - } else if (siglen >= "AVRISP_MK2".length() && - compareByteArrayWithString(resp, 3, "AVRISP_MK2")) { - mProgrammerType = PGMTYPE_AVRISP_MKII; - } else if (siglen >= "STK600".length() && - compareByteArrayWithString(resp, 3, "STK600")) { - mProgrammerType = PGMTYPE_STK600; - } else { - resp[siglen + 3] = 0; - byte[] tmpbuf = new byte[siglen]; - System.arraycopy(buf, 3, tmpbuf, 0, siglen); - mProgrammerType = PGMTYPE_STK500; - if (DEBUG_SHOW_GETSYNC) { - Log.e(TAG, - "STK500V2.getsync(): got response from unknown " - + "programmer " + PROGRAMMER_NAME[mProgrammerType] - + ", assuming STK500"); + long tstart = java.lang.System.currentTimeMillis(); + + while((state != sDONE)) { + if(read(c, 1) <= 0) { + long tnow = java.lang.System.currentTimeMillis(); + if((tnow - tstart) / 1000 > timeoutval) { // wuff - + // signed/unsigned/overflow + Log.e(TAG, "STK500V2.recv(): timeout"); + return -1; + } + continue; } - } - - if (DEBUG_SHOW_GETSYNC) { - Log.e(TAG, - "STK500V2.getsync(): found " + PROGRAMMER_NAME[mProgrammerType] - + " programmer"); - return 0; - } else { - if (tries > RETRIES) { - Log.e(TAG, - "STK500V2.getsync(): can't communicate with device: resp=" - + Integer.toHexString((int) resp[0])); - return -6; - } else { - bRetry = true; + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "recv : " + toHexStr(c[0])); } - } + checksum ^= c[0]; + + switch(state) { + case sSTART: + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "hoping for start token..."); + } + + if(c[0] == MESSAGE_START) { + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "got it\n"); + } + checksum = MESSAGE_START; + state = sSEQNUM; + } else { + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "sorry\n"); + } + } + break; + + case sSEQNUM: + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "hoping for sequence...\n"); + } + + if((0x00ff & c[0]) == mCommandSeqNum) { + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "got it, incrementing\n"); + } + state = sSIZE1; + mCommandSeqNum = 0x00ff & (++mCommandSeqNum); + } else { + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "sorry\n"); + } + state = sSTART; + } + break; + + case sSIZE1: + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "hoping for size LSB\n"); + } + msglen = ((int) c[0]) * 256; + state = sSIZE2; + break; + + case sSIZE2: + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "hoping for size MSB..."); + } + msglen += (int) c[0]; + if(DEBUG_SHOW_RECV) { + Log.d(TAG, " msg is " + msglen + " bytes"); + } + state = sTOKEN; + break; + + case sTOKEN: + if(c[0] == TOKEN) { + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "recv : sTOKEN : sDATA"); + } + state = sDATA; + } else { + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "recv : sTOKEN : sSTART"); + } + state = sSTART; + } + break; + + case sDATA: + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "recv | sDATA | msglen:" + msglen + ", curlen:" + curlen + ", length:" + length + ", c[0]:" + toHexStr(c[0])); + } + if(curlen < length) { + buf[curlen] = c[0]; + } else { + Log.e(TAG, "STK500V2.recv(): buffer too small, received " + curlen + + " byte into " + length + " byte buffer"); + return -2; + } + if((curlen == 0) && (buf[0] == ANSWER_CKSUM_ERROR)) { + Log.e(TAG, "STK500V2.recv(): previous packet sent with wrong checksum"); + return -3; + } + curlen++; + if(curlen == msglen) { + state = sCSUM; + } + break; + + case sCSUM: + if(DEBUG_SHOW_RECV) { + Log.d(TAG, "recv | sCSUM"); + } + if(checksum == 0) { + state = sDONE; + } else { + // value never used because we do a return. + // state = sSTART; + Log.e(TAG, "STK500V2.recv(): checksum error"); + return -4; + } + break; + default: + Log.e(TAG, "STK500V2.recv(): unknown state"); + return -5; + } /* + * switch + */ + } /* + * while + */ + + return /* + * redundant... (int) + */ (msglen + 6); + } - // or if we got a timeout - } else if (status == -1) { - if (tries > RETRIES) { - Log.e(TAG, "STK500V2.getsync(): timeout communicating with programmer"); - return -1; - } else { - bRetry = true; - } + int getsync() { + int tries = 0; + byte[] buf = new byte[1]; + byte[] resp = new byte[32]; + int status; + boolean bRetry = true; - // or any other error - } else { - if (tries > RETRIES) { - Log.e(TAG, "STK500V2.getsync(): error communicating with programmer: (" - + status + ")"); - } else { - bRetry = true; - } + if(DEBUG_SHOW_GETSYNC) { + Log.d(TAG, "STK500V2.getsync()"); + } + + while(bRetry) { + bRetry = false; + tries++; + + // send the sync command and see if we can get there + buf[0] = CMD_SIGN_ON; + send(buf, 1); + + // try to get the response back and see where we got + status = recv(resp, resp.length); + + // if we got bytes returned, check to see what came back + if(status > 0) { + if((resp[0] == CMD_SIGN_ON) && (resp[1] == STATUS_CMD_OK) + && (status > 3)) { + // success! + int siglen = resp[2]; + if(siglen >= "STK500_2".length() + && compareByteArrayWithString(resp, 3, "STK500_2")) { + mProgrammerType = PGMTYPE_STK500; + } else if(siglen >= "AVRISP_2".length() + && compareByteArrayWithString(resp, 3, "AVRISP_2")) { + mProgrammerType = PGMTYPE_AVRISP; + } else if(siglen >= "AVRISP_MK2".length() + && compareByteArrayWithString(resp, 3, "AVRISP_MK2")) { + mProgrammerType = PGMTYPE_AVRISP_MKII; + } else if(siglen >= "STK600".length() + && compareByteArrayWithString(resp, 3, "STK600")) { + mProgrammerType = PGMTYPE_STK600; + } else { + resp[siglen + 3] = 0; + byte[] tmpbuf = new byte[siglen]; + System.arraycopy(buf, 3, tmpbuf, 0, siglen); + mProgrammerType = PGMTYPE_STK500; + if(DEBUG_SHOW_GETSYNC) { + Log.e(TAG, + "STK500V2.getsync(): got response from unknown " + + "programmer " + PROGRAMMER_NAME[mProgrammerType] + + ", assuming STK500"); + } + } + + if(DEBUG_SHOW_GETSYNC) { + Log.e(TAG, + "STK500V2.getsync(): found " + PROGRAMMER_NAME[mProgrammerType] + + " programmer"); + } + } else { + if(tries > RETRIES) { + Log.e(TAG, + "STK500V2.getsync(): can't communicate with device: resp=" + + Integer.toHexString((int) resp[0])); + return -6; + } else { + bRetry = true; + } + } + + // or if we got a timeout + } else if(status == -1) { + if(tries > RETRIES) { + Log.e(TAG, "STK500V2.getsync(): timeout communicating with programmer"); + return -1; + } else { + bRetry = true; + } + + // or any other error + } else { + if(tries > RETRIES) { + Log.e(TAG, "STK500V2.getsync(): error communicating with programmer: (" + + status + ")"); + return -1; + } else { + bRetry = true; + } + } // end of if (status > 0) + } // end of while(bRetry) + return 0; + } // end of int getsync() + + public int open() { + setDtrRts(false); + try { + Thread.sleep(50); + } catch(InterruptedException e) { + } + setDtrRts(true); + try { + Thread.sleep(50); + } catch(InterruptedException e) { + } + + drain(); + if(getsync() < 0) { + return -1; } - } // end of if (status > 0) - } // end of while(bRetry) - return 0; - } // end of int getsync() - - public int open() { - setDtrRts(false); - try { Thread.sleep(50); } catch (InterruptedException e) {} - setDtrRts(true); - try { Thread.sleep(50); } catch (InterruptedException e) {} - - drain(); - if(getsync()<0) { return -1; } - return 0; - } - - public void enable() { - - } - - public int initialize() { -/* if ((PDATA(pgm)->pgmtype == PGMTYPE_STK600 || - PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || - PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) != 0 - && (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) != 0) { - /* - * This is an ATxmega device, must use XPROG protocol for the - * remaining actions. - * - stk600_setup_xprog(pgm); - } else { - - stk600_setup_isp(pgm); -// } - - if (p->flags & AVRPART_IS_AT90S1200) { - /* - * AT90S1200 needs a positive reset pulse after a chip erase. - * - pgm->disable(pgm); - usleep(10000); - } - - */ - return program_enable(); - - } - - public int program_enable() { - byte[] buf = new byte[16]; + return 0; + } + + public void enable() { + } + + public int initialize() { + /* + * if ((PDATA(pgm)->pgmtype == PGMTYPE_STK600 || + * PDATA(pgm)->pgmtype == PGMTYPE_AVRISP_MKII || + * PDATA(pgm)->pgmtype == PGMTYPE_JTAGICE_MKII) != 0 && + * (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) != 0) { /* + * This is an ATxmega device, must use XPROG protocol for the + * remaining actions. + * + * stk600_setup_xprog(pgm); } else { + * + * stk600_setup_isp(pgm); // } + * + * if (p->flags & AVRPART_IS_AT90S1200) { /* AT90S1200 needs a + * positive reset pulse after a chip erase. + * + * pgm->disable(pgm); usleep(10000); } + * + */ + return program_enable(); + + } + + public int program_enable() { + byte[] buf = new byte[16]; // String msg; /* see remarks above about size needed */ - int rv; + int rv; // PDATA(pgm)->lastpart = p; -/* if (p->op[AVR_OP_PGM_ENABLE] == NULL) { - fprintf(stderr, "%s: stk500v2_program_enable(): program enable instruction not defined for part \"%s\"\n", - progname, p->desc); - return -1; + /* + * if (p->op[AVR_OP_PGM_ENABLE] == NULL) { fprintf(stderr, "%s: + * stk500v2_program_enable(): program enable instruction not + * defined for part \"%s\"\n", progname, p->desc); return -1; } + */ + /* + * if (PDATA(pgm)->pgmtype == PGMTYPE_STK500 || + * PDATA(pgm)->pgmtype == PGMTYPE_STK600) /* Activate AVR-style + * (low active) RESET * stk500v2_setparm_real(pgm, + * PARAM_RESET_POLARITY, 0x01); + */ + + buf[0] = CMD_ENTER_PROGMODE_ISP; + buf[1] = mAVRConf.timeout; + buf[2] = mAVRConf.stabdelay; + buf[3] = mAVRConf.cmdexedelay; + buf[4] = mAVRConf.synchloops; + buf[5] = mAVRConf.bytedelay; + buf[6] = mAVRConf.pollvalue; + buf[7] = mAVRConf.pollindex; + /* + * byte[] tmpbuf = new byte[32]; + * avr_set_bits(mAVRMem.op[AVRMem.AVR_OP_PGM_ENABLE], tmpbuf); + * System.arraycopy(tmpbuf, 0, buf, 8, 2); + */ + buf[8] = (byte) 0xac; + buf[9] = 0x53; + buf[10] = 0; + buf[11] = 0; + + rv = command(buf, 12, buf.length); + + /* + * if (rv < 0) { switch (PDATA(pgm)->pgmtype) { case + * PGMTYPE_STK600: case PGMTYPE_AVRISP_MKII: if + * (stk500v2_getparm(pgm, PARAM_STATUS_TGT_CONN, &buf[0]) != 0) + * { fprintf(stderr, "%s: stk500v2_program_enable(): cannot get + * connection status\n", progname); } else { + * stk500v2_translate_conn_status(buf[0], msg); fprintf(stderr, + * "%s: stk500v2_program_enable():" " bad AVRISPmkII connection + * status: %s\n", progname, msg); } break; + * + * default: /* cannot report anything for other pgmtypes * + * break; } } + */ + + return rv; } -*/ -/* if (PDATA(pgm)->pgmtype == PGMTYPE_STK500 || - PDATA(pgm)->pgmtype == PGMTYPE_STK600) - /* Activate AVR-style (low active) RESET * - stk500v2_setparm_real(pgm, PARAM_RESET_POLARITY, 0x01); -*/ - - buf[0] = CMD_ENTER_PROGMODE_ISP; - buf[1] = mAVRConf.timeout; - buf[2] = mAVRConf.stabdelay; - buf[3] = mAVRConf.cmdexedelay; - buf[4] = mAVRConf.synchloops; - buf[5] = mAVRConf.bytedelay; - buf[6] = mAVRConf.pollvalue; - buf[7] = mAVRConf.pollindex; -/* byte[] tmpbuf = new byte[32]; - avr_set_bits(mAVRMem.op[AVRMem.AVR_OP_PGM_ENABLE], tmpbuf); - System.arraycopy(tmpbuf, 0, buf, 8, 2); -*/ - buf[8] = (byte)0xac; - buf[9] = 0x53; - buf[10] = 0; - buf[11] = 0; - - rv = command(buf, 12, buf.length); - -/* if (rv < 0) { - switch (PDATA(pgm)->pgmtype) - { - case PGMTYPE_STK600: - case PGMTYPE_AVRISP_MKII: - if (stk500v2_getparm(pgm, PARAM_STATUS_TGT_CONN, &buf[0]) != 0) { - fprintf(stderr, - "%s: stk500v2_program_enable(): cannot get connection status\n", - progname); - } else { - stk500v2_translate_conn_status(buf[0], msg); - fprintf(stderr, "%s: stk500v2_program_enable():" - " bad AVRISPmkII connection status: %s\n", - progname, msg); - } - break; - - default: - /* cannot report anything for other pgmtypes * - break; - } - } -*/ - - return rv; - } - - private static final int UINT_MAX = 65535; - /* - * avr_set_bits() - * - * Set instruction bits in the specified command based on the opcode. - */ - int avr_set_bits(AVRMem.OPCODE op , byte[] cmd) { - int i, j, bit; - byte mask; - - for (i=0; i<32; i++) { - if (op.bit[i].type == AVRMem.AVR_CMDBIT_VALUE) { - j = 3 - i / 8; - bit = i % 8; - mask = (byte) (1 << bit); - if (op.bit[i].value!=0) { - cmd[j] = (byte) (cmd[j] | mask); - } else { - cmd[j] = (byte) (cmd[j] & ~mask); + private static final int UINT_MAX = 65535; + /* + * avr_set_bits() + * + * Set instruction bits in the specified command based on the opcode. + */ + + int avr_set_bits(AVRMem.OPCODE op, byte[] cmd) { + int i, j, bit; + byte mask; + + for(i = 0; i < 32; i++) { + if(op.bit[i].type == AVRMem.AVR_CMDBIT_VALUE) { + j = 3 - i / 8; + bit = i % 8; + mask = (byte) (1 << bit); + if(op.bit[i].value != 0) { + cmd[j] = (byte) (cmd[j] | mask); + } else { + cmd[j] = (byte) (cmd[j] & ~mask); + } + } } - } + return 0; } - return 0; - } - public int paged_write() { - int addr; - int block_size; - int last_addr; + public int paged_write() { + int addr; + int block_size; + int last_addr; // int hiaddr; - int addrshift; - int use_ext_addr; - byte[] commandbuf = new byte[10]; - byte[] buf = new byte[266]; - byte[] cmds = new byte[4]; - int result; - AVRMem.OPCODE rop, wop; + int addrshift; + int use_ext_addr; + byte[] commandbuf = new byte[10]; + byte[] buf = new byte[266]; + byte[] cmds = new byte[4]; + int result; + AVRMem.OPCODE rop, wop; - int page_size = mAVRMem.page_size; - int n_bytes = mAVRMem.buf.length; + int page_size = mAVRMem.page_size; + int n_bytes = mAVRMem.buf.length; // Log.d(TAG,"STK500V2: STK500V2.paged_write(..,"+mAVRMem.desc+","+page_size+","+n_bytes+")"); - if (page_size == 0) { page_size = 256; } + if(page_size == 0) { + page_size = 256; + } // hiaddr = UINT_MAX; - addrshift = 0; - use_ext_addr = 0; - - // determine which command is to be used - if (mAVRMem.desc.compareTo("flash")==0) { - addrshift = 1; - commandbuf[0] = CMD_PROGRAM_FLASH_ISP; - /* - * If bit 31 is set, this indicates that the following read/write - * operation will be performed on a memory that is larger than - * 64KBytes. This is an indication to STK500 that a load extended - * address must be executed. - */ - if (mAVRMem.op[AVRMem.AVR_OP_LOAD_EXT_ADDR] != null) { - use_ext_addr = (1 << 31); - } - } else if (mAVRMem.desc.compareTo("eeprom") == 0) { - commandbuf[0] = CMD_PROGRAM_EEPROM_ISP; - } - commandbuf[4] = (byte) mAVRMem.delay; - - if (addrshift == 0) { - wop = mAVRMem.op[AVRMem.AVR_OP_WRITE]; - rop = mAVRMem.op[AVRMem.AVR_OP_READ]; - } else { - wop = mAVRMem.op[AVRMem.AVR_OP_WRITE_LO]; - rop = mAVRMem.op[AVRMem.AVR_OP_READ_LO]; - } + addrshift = 0; + use_ext_addr = 0; + + // determine which command is to be used + if(mAVRMem.desc.compareTo("flash") == 0) { + addrshift = 1; + commandbuf[0] = CMD_PROGRAM_FLASH_ISP; + /* + * If bit 31 is set, this indicates that the following + * read/write operation will be performed on a memory + * that is larger than 64KBytes. This is an indication + * to STK500 that a load extended address must be + * executed. + */ + if(mAVRMem.op[AVRMem.AVR_OP_LOAD_EXT_ADDR] != null) { + use_ext_addr = (1 << 31); + } + } else if(mAVRMem.desc.compareTo("eeprom") == 0) { + commandbuf[0] = CMD_PROGRAM_EEPROM_ISP; + } + commandbuf[4] = (byte) mAVRMem.delay; - // if the memory is paged, load the appropriate commands into the buffer - if ((mAVRMem.mode & 0x01) == 0x01) { - commandbuf[3] = (byte) (mAVRMem.mode | 0x80); // yes, write the page to flash - - if (mAVRMem.op[AVRMem.AVR_OP_LOADPAGE_LO] == null) { - Log.e(TAG, "STK500V2.paged_write: loadpage instruction not defined for part \""+mAVRMem.desc+"\""); - return -1; - } - avr_set_bits(mAVRMem.op[AVRMem.AVR_OP_LOADPAGE_LO], cmds); - commandbuf[5] = cmds[0]; - - if (mAVRMem.op[AVRMem.AVR_OP_WRITEPAGE] == null) { - Log.e(TAG, "STK500V2.paged_write: write page instruction not defined for part \""+mAVRMem.desc+"\""); - return -1; - } - avr_set_bits(mAVRMem.op[AVRMem.AVR_OP_WRITEPAGE], cmds); - commandbuf[6] = cmds[0]; - - // otherwise, we need to load different commands in - } else { - commandbuf[3] = (byte) (mAVRMem.mode | 0x80); // yes, write the words to flash - - if (wop == null) { - Log.e(TAG, "STK500V2.paged_write: write instruction not defined for part \""+mAVRMem.desc+"\""); - return -1; - } - avr_set_bits(wop, cmds); - commandbuf[5] = cmds[0]; - commandbuf[6] = 0; - } + if(addrshift == 0) { + wop = mAVRMem.op[AVRMem.AVR_OP_WRITE]; + rop = mAVRMem.op[AVRMem.AVR_OP_READ]; + } else { + wop = mAVRMem.op[AVRMem.AVR_OP_WRITE_LO]; + rop = mAVRMem.op[AVRMem.AVR_OP_READ_LO]; + } - // the read command is common to both methods - if (rop == null) { - Log.e(TAG, "STK500V2.paged_write: read instruction not defined for part \""+mAVRMem.desc+"\""); - return -1; - } - avr_set_bits(rop, cmds); - commandbuf[7] = cmds[0]; + // if the memory is paged, load the appropriate commands into the buffer + if((mAVRMem.mode & 0x01) == 0x01) { + commandbuf[3] = (byte) (mAVRMem.mode | 0x80); // yes, write the page to flash - commandbuf[8] = mAVRMem.readback[0]; - commandbuf[9] = mAVRMem.readback[1]; + if(mAVRMem.op[AVRMem.AVR_OP_LOADPAGE_LO] == null) { + Log.e(TAG, "STK500V2.paged_write: loadpage instruction not defined for part \"" + mAVRMem.desc + "\""); + return -1; + } + avr_set_bits(mAVRMem.op[AVRMem.AVR_OP_LOADPAGE_LO], cmds); + commandbuf[5] = cmds[0]; - last_addr=UINT_MAX; /* impossible address */ + if(mAVRMem.op[AVRMem.AVR_OP_WRITEPAGE] == null) { + Log.e(TAG, "STK500V2.paged_write: write page instruction not defined for part \"" + mAVRMem.desc + "\""); + return -1; + } + avr_set_bits(mAVRMem.op[AVRMem.AVR_OP_WRITEPAGE], cmds); + commandbuf[6] = cmds[0]; - for (addr=0; addr < n_bytes; addr += page_size) { - if(Thread.interrupted()) { - report_cancel(); - return 0; - } + // otherwise, we need to load different commands in + } else { + commandbuf[3] = (byte) (mAVRMem.mode | 0x80); // yes, write the words to flash + + if(wop == null) { + Log.e(TAG, "STK500V2.paged_write: write instruction not defined for part \"" + mAVRMem.desc + "\""); + return -1; + } + avr_set_bits(wop, cmds); + commandbuf[5] = cmds[0]; + commandbuf[6] = 0; + } + + // the read command is common to both methods + if(rop == null) { + Log.e(TAG, "STK500V2.paged_write: read instruction not defined for part \"" + mAVRMem.desc + "\""); + return -1; + } + avr_set_bits(rop, cmds); + commandbuf[7] = cmds[0]; + + commandbuf[8] = mAVRMem.readback[0]; + commandbuf[9] = mAVRMem.readback[1]; + + last_addr = UINT_MAX; /* + * impossible address + */ - report_progress((int)(addr*100/n_bytes)); + for(addr = 0; addr < n_bytes; addr += page_size) { + if(Thread.interrupted()) { + report_cancel(); + return 0; + } + + report_progress(/* + * redundant ...(int) + */(addr * 100 / n_bytes)); - if ((n_bytes-addr) < page_size) { - block_size = n_bytes - addr; - } else { - block_size = page_size; - } + if((n_bytes - addr) < page_size) { + block_size = n_bytes - addr; + } else { + block_size = page_size; + } // Log.d(TAG,"n_bytes "+n_bytes); // Log.d(TAG,"block_size at addr "+addr+" is "+block_size); - if(commandbuf[0] == CMD_PROGRAM_FLASH_ISP){ - if (is_page_empty(addr, block_size, mAVRMem.buf)) { - continue; - } - } + if(commandbuf[0] == CMD_PROGRAM_FLASH_ISP) { + if(is_page_empty(addr, block_size, mAVRMem.buf)) { + continue; + } + } - System.arraycopy(commandbuf, 0, buf, 0, commandbuf.length); + System.arraycopy(commandbuf, 0, buf, 0, commandbuf.length); - buf[1] = (byte) (block_size >> 8); - buf[2] = (byte) (block_size & 0xff); + buf[1] = (byte) (block_size >> 8); + buf[2] = (byte) (block_size & 0xff); - if((last_addr==UINT_MAX)||(last_addr+block_size != addr)){ - if (loadaddr(use_ext_addr | (addr >> addrshift)) < 0) - return -1; - } - last_addr=addr; + if((last_addr == UINT_MAX) || (last_addr + block_size != addr)) { + if(loadaddr(use_ext_addr | (addr >> addrshift)) < 0) { + return -1; + } + } + last_addr = addr; - System.arraycopy(mAVRMem.buf, addr, buf, 10, block_size); + System.arraycopy(mAVRMem.buf, addr, buf, 10, block_size); - result = command(buf,block_size+10, buf.length); - if (result < 0) { - Log.e(TAG, "STK500V2.paged_write: write command failed"); - return -1; - } - } + result = command(buf, block_size + 10, buf.length); + if(result < 0) { + Log.e(TAG, "STK500V2.paged_write: write command failed"); + return -1; + } + } - report_progress((int)(addr*100/n_bytes)); + report_progress(/* + * redundant...(int) + */(addr * 100 / n_bytes)); - return n_bytes; - } + return n_bytes; + } - boolean is_page_empty(int address, int page_size, byte[] buf) { - int i; + boolean is_page_empty(int address, int page_size, byte[] buf) { + int i; - for(i = 0; i < page_size; i++) { - if(buf[address + i] != 0xFF) { - /* Page is not empty. */ - return false; - } + for(i = 0; i < page_size; i++) { + if(buf[address + i] != 0xFF) { + /* + * Page is not empty. + */ + return false; + } + } + /* + * Page is empty. + */ + return true; } - /* Page is empty. */ - return true; - } - int loadaddr(int addr) { - byte[] buf = new byte[16]; - int result; + int loadaddr(int addr) { + byte[] buf = new byte[16]; + int result; // Log.d(TAG, "STK500V2.loadaddr("+addr+")"); - buf[0] = CMD_LOAD_ADDRESS; - buf[1] = (byte) ((addr >> 24) & 0xff); - buf[2] = (byte) ((addr >> 16) & 0xff); - buf[3] = (byte) ((addr >> 8) & 0xff); - buf[4] = (byte) ( addr & 0xff); + buf[0] = CMD_LOAD_ADDRESS; + buf[1] = (byte) ((addr >> 24) & 0xff); + buf[2] = (byte) ((addr >> 16) & 0xff); + buf[3] = (byte) ((addr >> 8) & 0xff); + buf[4] = (byte) (addr & 0xff); - result = command(buf, 5, buf.length); + result = command(buf, 5, buf.length); - if (result < 0) { - Log.e(TAG,"STK500V2.loadaddr(): failed to set load address"); - return -1; + if(result < 0) { + Log.e(TAG, "STK500V2.loadaddr(): failed to set load address"); + return -1; + } + return 0; } - return 0; - } - - private int read(byte[] buf, int length) { - int retval; - retval = mComm.read(buf,length); - if(DEBUG_SHOW_READ){ - if(retval>0){ - String str = ""; - for(int i=0; i 0) { + String str = ""; + for(int i = 0; i < retval; i++) { + str += Integer.toHexString((int) buf[i]) + " "; + } + Log.d(TAG, "read(" + retval + ") : " + str); + } } - Log.d(TAG, "read("+retval+") : "+str); - } + return retval; } - return retval; - } - - private int write(byte[] buf, int length) { - int retval; - retval = mComm.write(buf, length); - if(DEBUG_SHOW_WRITE){ - if(retval>0){ - Log.d(TAG, "write("+retval+") : "+toHexStr(buf, retval)); - } + + private int write(byte[] buf, int length) { + int retval; + retval = mComm.write(buf, length); + if(DEBUG_SHOW_WRITE) { + if(retval > 0) { + Log.d(TAG, "write(" + retval + ") : " + toHexStr(buf, retval)); + } + } + return retval; } - return retval; - } - - private void setDtrRts(boolean on) { - if(on) { - mComm.setDtrRts(true, true); - } else { - mComm.setDtrRts(false, false); + + private void setDtrRts(boolean on) { + if(on) { + mComm.setDtrRts(true, true); + } else { + mComm.setDtrRts(false, false); + } } - } - private String toHexStr(byte b) { - return String.format("0x%02x", b); - } + private String toHexStr(byte b) { + return String.format("0x%02x", b); + } - private String toHexStr(byte[] b, int length) { - String str=""; - for(int i=0; i= 31) { + mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent("USB_PERMISSION"), PendingIntent.FLAG_IMMUTABLE); + } else { + mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent("USB_PERMISSION"), 0); + } } } @@ -255,7 +258,7 @@ public String getSerial(int devNum) { /** * Gets an USB permission if no permission - * + * * @param device */ public void getPermission(UsbDevice device) { diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/usb/UsbCdcConnection.java b/PhysicaloidLibrary/src/com/physicaloid/lib/usb/UsbCdcConnection.java index 95d9dad..69e84e2 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/lib/usb/UsbCdcConnection.java +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/usb/UsbCdcConnection.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.physicaloid.lib.usb; import android.content.Context; @@ -24,178 +23,232 @@ import android.hardware.usb.UsbInterface; import android.util.Log; import android.util.SparseArray; - import com.physicaloid.BuildConfig; public class UsbCdcConnection { - private static final boolean DEBUG_SHOW = true && BuildConfig.DEBUG; - - private static final String TAG = UsbCdcConnection.class.getSimpleName(); - - private UsbAccessor mUsbAccess; - - private int mCdcAcmInterfaceNum; - - SparseArray mUsbConnectionEp; - - public UsbCdcConnection(Context context) { - mUsbAccess = UsbAccessor.INSTANCE; - mUsbAccess.init(context); - mCdcAcmInterfaceNum = 0; - mUsbConnectionEp = new SparseArray(); - } - - /** - * Open first device with VID and PID - * @param ids vid and pid - * @return true : open successful, false : open fail - */ - public boolean open(UsbVidPid ids) { - return open(ids,false, 0); - } - - /** - * Open first CDC-ACM device with VID and PID - * @param ids vid and pid - * @param isCdcAcm true then search only cdc-acm - * @return true : open successful, false : open fail - */ - public boolean open(UsbVidPid ids, boolean isCdcAcm) { - return open(ids, isCdcAcm, 0); - } - - /** - * Open channel-th device with VID and PID - * @param ids vid and pid - * @param ch channel - * @return true : open successful, false : open fail - */ - public boolean open(UsbVidPid ids, boolean isCdcAcm, int ch) { - if(ids == null) return false; - - int devNum = 0; - int chNum = 0; - for(UsbDevice usbdev : mUsbAccess.manager().getDeviceList().values()) { - if(usbdev.getVendorId() == ids.getVid()) { - if(ids.getPid() == 0 || ids.getPid() == usbdev.getProductId()) { - for(int intfNum=0; intfNum < usbdev.getInterfaceCount(); intfNum++) { - - if( (isCdcAcm && (usbdev.getInterface(intfNum).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA)) - || !isCdcAcm) { - if(ch == chNum) { - if(!mUsbAccess.deviceIsConnected(devNum)) { - if(mUsbAccess.openDevice(devNum,intfNum,ch)) { - if(DEBUG_SHOW){ Log.d(TAG, "Find VID:"+Integer.toHexString(usbdev.getVendorId())+", PID:"+Integer.toHexString(usbdev.getProductId())+", DevNum:"+devNum+", IntfNum:"+intfNum); } - mUsbConnectionEp.put(ch,new UsbCdcConnectionEp(mUsbAccess.connection(ch), getEndpoint(devNum, intfNum, UsbConstants.USB_DIR_IN), getEndpoint(devNum, intfNum, UsbConstants.USB_DIR_OUT))); - mCdcAcmInterfaceNum = intfNum; - return true; - } + + private static final boolean DEBUG_SHOW = true && BuildConfig.DEBUG; + private static final String TAG = UsbCdcConnection.class.getSimpleName(); + private UsbAccessor mUsbAccess; + private int mCdcAcmInterfaceNum; + private int pid; + SparseArray mUsbConnectionEp; + + public int getPID() { + return pid; + } + + public UsbCdcConnection(Context context) { + mUsbAccess = UsbAccessor.INSTANCE; + mUsbAccess.init(context); + mCdcAcmInterfaceNum = 0; + mUsbConnectionEp = new SparseArray(); + } + + /** + * Open first device with VID and PID + * + * @param ids vid and pid + * + * @return true : open successful, false : open fail + */ + public boolean open(UsbVidPid ids) { + return open(ids, false, 0); + } + + /** + * Open first CDC-ACM device with VID and PID + * + * @param ids vid and pid + * @param isCdcAcm true then search only cdc-acm + * + * @return true : open successful, false : open fail + */ + public boolean open(UsbVidPid ids, boolean isCdcAcm) { + return open(ids, isCdcAcm, 0); + } + + /** + * Open channel-th device with VID and PID + * + * @param ids vid and pid + * @param ch channel + * + * @return true : open successful, false : open fail + */ + public boolean open(UsbVidPid ids, boolean isCdcAcm, int ch) { + if(ids == null) { + return false; + } + + int devNum = 0; + int chNum = 0; + for(UsbDevice usbdev : mUsbAccess.manager().getDeviceList().values()) { + if(usbdev.getVendorId() == ids.getVid()) { + if(DEBUG_SHOW) { + Log.d(TAG, "VID PASS " + usbdev.getVendorId()); } - chNum++; - } // end of if - }// end of if - } // end of for - } // end of if - } // end of if - devNum++; - } //end of for - if(DEBUG_SHOW){ Log.d(TAG, "Cannot find VID:"+ids.getVid()+", PID:"+ids.getPid()); } - return false; - } - - private UsbEndpoint getEndpoint(int devNum, int intfNum, int usbDir) { - UsbInterface intf = mUsbAccess.intface(devNum, intfNum); - if(intf == null) {return null;} - - for(int i=0; i size) { + write_size = size - offset; + } + // optimization! + if(offset == 0) { + synchronized(DevLock) { + written_size = mConnection.bulkTransfer(mEndpointOut, buf, write_size, 100); + + } + } else { + System.arraycopy(buf, offset, wbuf, 0, write_size); + synchronized(DevLock) { + written_size = mConnection.bulkTransfer(mEndpointOut, wbuf, write_size, 100); + } + } + if(written_size < 0) { + return -1; + } + offset += written_size; + } - private UsbDeviceConnection mConnection; - private UsbEndpoint mEndpointIn; - private UsbEndpoint mEndpointOut; - private int mInterfaceNum; + return offset; + } - private boolean isOpened; + private void stopRead() { + mReadThreadStop = true; + } - public UartCdcAcm(Context context) { - super(context); - mUsbConnetionManager = new UsbCdcConnection(context); - mUartConfig = new UartConfig(); - mBuffer = new RingBuffer(RING_BUFFER_SIZE); - isOpened = false; - } + private void startRead() { + if(mReadThreadStop) { + mReadThreadStop = false; + new Thread(mLoop).start(); + } + } - @Override - public boolean open() { - for(UsbVidList id : UsbVidList.values()) { - if(open(new UsbVidPid(id.getVid(), 0))){ + private String toHexStr(byte[] b, int length) { + String str = ""; + for(int i = 0; i < length; i++) { + str += String.format("%02x ", b[i]); + } + return str; + } + private Runnable mLoop = new Runnable() { + + @Override + @SuppressWarnings("CallToThreadYield") + public void run() { + try { + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND); + } catch(Exception e) { + } + int len; + byte[] rbuf = new byte[mEndpointIn.getMaxPacketSize()]; + UsbRequest response; + UsbRequest request = new UsbRequest(); + request.initialize(mConnection, mEndpointIn); + ByteBuffer buf = ByteBuffer.wrap(rbuf); + for(;;) {// this is the main loop for transferring + len = 0; + if(request.queue(buf, rbuf.length)) { + response = mConnection.requestWait(); + if(response != null) { + len = buf.position(); + } + if(len > 0) { + if(DEBUG_SHOW) { + Log.e(TAG, "read(" + len + "): " + toHexStr(rbuf, len)); + } + + mBuffer.add(rbuf, len); + onRead(len); + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } + + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } + + if(mReadThreadStop) { + return; + } + } + } // end of run() + }; // end of runnable + + /** + * Sets Uart configurations + * + * @param config configurations + * + * @return true : successful, false : fail + */ + public boolean setUartConfig(UartConfig config) { + boolean res; + boolean ret = true; + res = setBaudrate(config.baudrate); + ret = ret && res; + + res = setDataBits(config.dataBits); + ret = ret && res; + + res = setParity(config.parity); + ret = ret && res; + + res = setStopBits(config.stopBits); + ret = ret && res; + + res = setDtrRts(config.dtrOn, config.rtsOn); + ret = ret && res; + + return ret; + } + + /** + * Initializes CDC communication + * + * @return true : successful, false : fail + */ + private boolean init() { + if(mConnection == null) { + return false; + } + int ret = mConnection.controlTransfer(0x21, 0x22, 0x00, mInterfaceNum, null, 0, 0); // init CDC + if(ret < 0) { + return false; + } return true; - } - } - return false; - } - - public boolean open(UsbVidPid ids) { - if(mUsbConnetionManager.open(ids,true)) { - mConnection = mUsbConnetionManager.getConnection(); - mEndpointIn = mUsbConnetionManager.getEndpointIn(); - mEndpointOut = mUsbConnetionManager.getEndpointOut(); - mInterfaceNum = mUsbConnetionManager.getCdcAcmInterfaceNum(); - if(!init()) { return false; } - if(!setBaudrate(DEFAULT_BAUDRATE)) {return false;} - mBuffer.clear(); - startRead(); - isOpened = true; - return true; - } - return false; - } - - @Override - public boolean close() { - stopRead(); - isOpened = false; - return mUsbConnetionManager.close(); - } - - @Override - public int read(byte[] buf, int size) { - return mBuffer.get(buf, size); - } - - @Override - public int write(byte[] buf, int size) { - if(buf == null) { return 0; } - int offset = 0; - int write_size; - int written_size; - byte[] wbuf = new byte[USB_WRITE_BUFFER_SIZE]; - - while (offset < size) { - write_size = USB_WRITE_BUFFER_SIZE; - - if (offset + write_size > size) { - write_size = size - offset; - } - System.arraycopy(buf, offset, wbuf, 0, write_size); - - written_size = mConnection.bulkTransfer(mEndpointOut, wbuf, write_size, 100); - - if (written_size < 0) { - return -1; - } - offset += written_size; - } - - return offset; - } - - private void stopRead() { - mReadThreadStop = true; - } - - private void startRead() { - if(mReadThreadStop) { - mReadThreadStop = false; - new Thread(mLoop).start(); - } - } - - private Runnable mLoop = new Runnable() { + } + @Override - public void run() { - int len=0; - byte[] rbuf = new byte[USB_READ_BUFFER_SIZE]; - for (;;) {// this is the main loop for transferring - - try { - len = mConnection.bulkTransfer(mEndpointIn, - rbuf, rbuf.length, 50); - } catch(Exception e) { - Log.e(TAG, e.toString()); + public boolean isOpened() { + return isOpened; + } + + /** + * Sets baudrate + * + * @param baudrate baudrate e.g. 9600 + * + * @return true : successful, false : fail + */ + public boolean setBaudrate(int baudrate) { + byte[] baudByte = new byte[4]; + + baudByte[0] = (byte) (baudrate & 0x000000FF); + baudByte[1] = (byte) ((baudrate & 0x0000FF00) >> 8); + baudByte[2] = (byte) ((baudrate & 0x00FF0000) >> 16); + baudByte[3] = (byte) ((baudrate & 0xFF000000) >> 24); + int ret = mConnection.controlTransfer(0x21, 0x20, 0, mInterfaceNum, new byte[] { + baudByte[0], baudByte[1], baudByte[2], baudByte[3], 0x00, 0x00, + 0x08}, 7, 100); + if(ret < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setBaudrate"); + } + return false; } + mUartConfig.baudrate = baudrate; + return true; + } - if (len > 0) { - mBuffer.add(rbuf, len); - onRead(len); + /** + * Sets Data bits + * + * @param dataBits data bits e.g. UartConfig.DATA_BITS8 + * + * @return true : successful, false : fail + */ + public boolean setDataBits(int dataBits) { + // TODO : implement + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setDataBits"); } + mUartConfig.dataBits = dataBits; + return false; + } - if (mReadThreadStop) { - return; + /** + * Sets Parity bit + * + * @param parity parity bits e.g. UartConfig.PARITY_NONE + * + * @return true : successful, false : fail + */ + public boolean setParity(int parity) { + // TODO : implement + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setParity"); } + mUartConfig.parity = parity; + return false; + } - try { - Thread.sleep(50); - } catch (InterruptedException e) { + /** + * Sets Stop bits + * + * @param stopBits stop bits e.g. UartConfig.STOP_BITS1 + * + * @return true : successful, false : fail + */ + public boolean setStopBits(int stopBits) { + // TODO : implement + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setStopBits"); } + mUartConfig.stopBits = stopBits; + return false; + } - } - } // end of run() - }; // end of runnable - - - /** - * Sets Uart configurations - * @param config configurations - * @return true : successful, false : fail - */ - public boolean setUartConfig(UartConfig config) { - boolean res = true; - boolean ret = true; - if(mUartConfig.baudrate != config.baudrate) { - res = setBaudrate(config.baudrate); - ret = ret && res; - } - - if(mUartConfig.dataBits != config.dataBits) { - res = setDataBits(config.dataBits); - ret = ret && res; - } - - if(mUartConfig.parity != config.parity) { - res = setParity(config.parity); - ret = ret && res; - } - - if(mUartConfig.stopBits != config.stopBits) { - res = setStopBits(config.stopBits); - ret = ret && res; - } - - if(mUartConfig.dtrOn != config.dtrOn || - mUartConfig.rtsOn != config.rtsOn) { - res = setDtrRts(config.dtrOn, config.rtsOn); - ret = ret && res; - } - - return ret; - } - - /** - * Initializes CDC communication - * @return true : successful, false : fail - */ - private boolean init() { - if(mConnection == null) return false; - int ret = mConnection.controlTransfer(0x21, 0x22, 0x00, mInterfaceNum, null, 0, 0); // init CDC - if(ret < 0) { return false; } - return true; - } - - @Override - public boolean isOpened() { - return isOpened; - } - - /** - * Sets baudrate - * @param baudrate baudrate e.g. 9600 - * @return true : successful, false : fail - */ - public boolean setBaudrate(int baudrate) { - byte[] baudByte = new byte[4]; - - baudByte[0] = (byte) (baudrate & 0x000000FF); - baudByte[1] = (byte) ((baudrate & 0x0000FF00) >> 8); - baudByte[2] = (byte) ((baudrate & 0x00FF0000) >> 16); - baudByte[3] = (byte) ((baudrate & 0xFF000000) >> 24); - int ret = mConnection.controlTransfer(0x21, 0x20, 0, mInterfaceNum, new byte[] { - baudByte[0], baudByte[1], baudByte[2], baudByte[3], 0x00, 0x00, - 0x08}, 7, 100); - if(ret < 0) { - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setBaudrate"); } - return false; - } - mUartConfig.baudrate = baudrate; - return true; - } - - /** - * Sets Data bits - * @param dataBits data bits e.g. UartConfig.DATA_BITS8 - * @return true : successful, false : fail - */ - public boolean setDataBits(int dataBits) { - // TODO : implement - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setDataBits"); } - mUartConfig.dataBits = dataBits; - return false; - } - - /** - * Sets Parity bit - * @param parity parity bits e.g. UartConfig.PARITY_NONE - * @return true : successful, false : fail - */ - public boolean setParity(int parity) { - // TODO : implement - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setParity"); } - mUartConfig.parity = parity; - return false; - } - - /** - * Sets Stop bits - * @param stopBits stop bits e.g. UartConfig.STOP_BITS1 - * @return true : successful, false : fail - */ - public boolean setStopBits(int stopBits) { - // TODO : implement - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setStopBits"); } - mUartConfig.stopBits = stopBits; - return false; - } - - @Override - public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { - int ctrlValue = 0x0000; - if(dtrOn) { - ctrlValue |= 0x0001; - } - if(rtsOn) { - ctrlValue |= 0x0002; - } - int ret = mConnection.controlTransfer(0x21, 0x22, ctrlValue, mInterfaceNum, null, 0, 100); - if(ret < 0) { - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setDtrRts"); } - return false; - } - mUartConfig.dtrOn = dtrOn; - mUartConfig.rtsOn = rtsOn; - return true; - } - - @Override - public UartConfig getUartConfig() { - return mUartConfig; - } - - @Override - public int getBaudrate() { - return mUartConfig.baudrate; - } - - @Override - public int getDataBits() { - return mUartConfig.dataBits; - } - - @Override - public int getParity() { - return mUartConfig.parity; - } - - @Override - public int getStopBits() { - return mUartConfig.stopBits; - } - - @Override - public boolean getDtr() { - return mUartConfig.dtrOn; - } - - @Override - public boolean getRts() { - return mUartConfig.rtsOn; - } - - @Override - public void clearBuffer() { - mBuffer.clear(); - } - - ////////////////////////////////////////////////////////// - // Listener for reading uart - ////////////////////////////////////////////////////////// - private List uartReadListenerList - = new ArrayList(); - private boolean mStopReadListener = false; - - @Override - public void addReadListener(ReadLisener listener) { - uartReadListenerList.add(listener); - } - - @Override - public void clearReadListener() { - uartReadListenerList.clear(); - } - - @Override - public void startReadListener() { - mStopReadListener = false; - } - - @Override - public void stopReadListener() { - mStopReadListener = true; - } - - private void onRead(int size) { - if(mStopReadListener) return; - for (ReadLisener listener: uartReadListenerList) { - listener.onRead(size); - } - } - ////////////////////////////////////////////////////////// + @Override + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { + int ctrlValue = 0x0000; + if(dtrOn) { + ctrlValue |= 0x0001; + } + if(rtsOn) { + ctrlValue |= 0x0002; + } + int ret = mConnection.controlTransfer(0x21, 0x22, ctrlValue, mInterfaceNum, null, 0, 100); + if(ret < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setDtrRts"); + } + return false; + } + mUartConfig.dtrOn = dtrOn; + mUartConfig.rtsOn = rtsOn; + return true; + } + @Override + public UartConfig getUartConfig() { + return mUartConfig; + } + + @Override + public int getBaudrate() { + return mUartConfig.baudrate; + } + + @Override + public int getDataBits() { + return mUartConfig.dataBits; + } + + @Override + public int getParity() { + return mUartConfig.parity; + } + + @Override + public int getStopBits() { + return mUartConfig.stopBits; + } + + @Override + public boolean getDtr() { + return mUartConfig.dtrOn; + } + + @Override + public boolean getRts() { + return mUartConfig.rtsOn; + } + + @Override + public void clearBuffer() { + mBuffer.clear(); + } + ////////////////////////////////////////////////////////// + // Listener for reading uart + ////////////////////////////////////////////////////////// + private List uartReadListenerList = new ArrayList(); + private boolean mStopReadListener = false; + + @Override + public void addReadListener(ReadListener listener) { + uartReadListenerList.add(listener); + } + + @Override + @Deprecated + public void addReadListener(ReadLisener listener) { + addReadListener((ReadListener)listener); + } + + @Override + public void clearReadListener() { + uartReadListenerList.clear(); + } + + @Override + public void startReadListener() { + mStopReadListener = false; + } + + @Override + public void stopReadListener() { + mStopReadListener = true; + } + + private void onRead(int size) { + if(mStopReadListener) { + return; + } + for(ReadListener listener : uartReadListenerList) { + listener.onRead(size); + } + } + ////////////////////////////////////////////////////////// + + @Override + public String getPhysicalConnectionName() { + return Physicaloid.USB_STRING; + } + + @Override + public int getPhysicalConnectionType() { + return Physicaloid.USB; + } + + @Override + public void setDebug(boolean flag) { + DEBUG_SHOW = flag; + } } diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/usb/driver/uart/UartCp210x.java b/PhysicaloidLibrary/src/com/physicaloid/lib/usb/driver/uart/UartCp210x.java index 1de5202..7a55e3d 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/lib/usb/driver/uart/UartCp210x.java +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/usb/driver/uart/UartCp210x.java @@ -3,689 +3,789 @@ import android.content.Context; import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbRequest; import android.util.Log; - import com.physicaloid.BuildConfig; +import com.physicaloid.lib.Physicaloid; import com.physicaloid.lib.UsbVidList; import com.physicaloid.lib.framework.SerialCommunicator; import com.physicaloid.lib.usb.UsbCdcConnection; import com.physicaloid.lib.usb.UsbVidPid; import com.physicaloid.misc.RingBuffer; - +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -public class UartCp210x extends SerialCommunicator{ - - private static final String TAG = UartCp210x.class.getSimpleName(); - - private static final boolean DEBUG_SHOW = false && BuildConfig.DEBUG; - private static final int DEFAULT_BAUDRATE = 9600; - - private UsbCdcConnection mUsbConnetionManager; - - private UartConfig mUartConfig; - private static final int RING_BUFFER_SIZE = 1024; - private static final int USB_READ_BUFFER_SIZE = 256; - private static final int USB_WRITE_BUFFER_SIZE = 256; - private RingBuffer mBuffer; - - private boolean mReadThreadStop = true; - - private UsbDeviceConnection mConnection; - private UsbEndpoint mEndpointIn; - private UsbEndpoint mEndpointOut; - - private boolean isOpened; - - /* Config request types */ - private static final byte REQTYPE_HOST_TO_INTERFACE = (byte)0x41; - private static final byte REQTYPE_INTERFACE_TO_HOST = (byte)0xc1; - @SuppressWarnings("unused") - private static final byte REQTYPE_HOST_TO_DEVICE = (byte)0x40; - @SuppressWarnings("unused") - private static final byte REQTYPE_DEVICE_TO_HOST = (byte)0xc0; - - /* Config request codes */ - private static final byte CP210X_IFC_ENABLE = 0x00; - @SuppressWarnings("unused") - private static final byte CP210X_SET_BAUDDIV = 0x01; - @SuppressWarnings("unused") - private static final byte CP210X_GET_BAUDDIV = 0x02; - @SuppressWarnings("unused") - private static final byte CP210X_SET_LINE_CTL = 0x03; - private static final byte CP210X_GET_LINE_CTL = 0x04; - @SuppressWarnings("unused") - private static final byte CP210X_SET_BREAK = 0x05; - @SuppressWarnings("unused") - private static final byte CP210X_IMM_CHAR = 0x06; - private static final byte CP210X_SET_MHS = 0x07; - @SuppressWarnings("unused") - private static final byte CP210X_GET_MDMSTS = 0x08; - @SuppressWarnings("unused") - private static final byte CP210X_SET_XON = 0x09; - @SuppressWarnings("unused") - private static final byte CP210X_SET_XOFF = 0x0A; - @SuppressWarnings("unused") - private static final byte CP210X_SET_EVENTMASK = 0x0B; - @SuppressWarnings("unused") - private static final byte CP210X_GET_EVENTMASK = 0x0C; - @SuppressWarnings("unused") - private static final byte CP210X_SET_CHAR = 0x0D; - @SuppressWarnings("unused") - private static final byte CP210X_GET_CHARS = 0x0E; - @SuppressWarnings("unused") - private static final byte CP210X_GET_PROPS = 0x0F; - @SuppressWarnings("unused") - private static final byte CP210X_GET_COMM_STATUS = 0x10; - @SuppressWarnings("unused") - private static final byte CP210X_RESET = 0x11; - @SuppressWarnings("unused") - private static final byte CP210X_PURGE = 0x12; - @SuppressWarnings("unused") - private static final byte CP210X_SET_FLOW = 0x13; - @SuppressWarnings("unused") - private static final byte CP210X_GET_FLOW = 0x14; - @SuppressWarnings("unused") - private static final byte CP210X_EMBED_EVENTS = 0x15; - @SuppressWarnings("unused") - private static final byte CP210X_GET_EVENTSTATE = 0x16; - @SuppressWarnings("unused") - private static final byte CP210X_SET_CHARS = 0x19; - @SuppressWarnings("unused") - private static final byte CP210X_GET_BAUDRATE = 0x1D; - private static final byte CP210X_SET_BAUDRATE = 0x1E; - - /* CP210X_IFC_ENABLE */ - private static final int UART_ENABLE = 0x0001; - private static final int UART_DISABLE = 0x0000; - - /* CP210X_(SET|GET)_BAUDDIV */ - @SuppressWarnings("unused") - private static final int BAUD_RATE_GEN_FREQ = 0x384000; - - /* CP210X_(SET|GET)_LINE_CTL */ - private static final int BITS_DATA_MASK = 0x0f00; - @SuppressWarnings("unused") - private static final int BITS_DATA_5 = 0x0500; - @SuppressWarnings("unused") - private static final int BITS_DATA_6 = 0x0600;; - private static final int BITS_DATA_7 = 0x0700; - private static final int BITS_DATA_8 = 0x0800; - @SuppressWarnings("unused") - private static final int BITS_DATA_9 = 0x0900; - - private static final int BITS_PARITY_MASK = 0x00f0; - private static final int BITS_PARITY_NONE = 0x0000; - private static final int BITS_PARITY_ODD = 0x0010; - private static final int BITS_PARITY_EVEN = 0x0020; - private static final int BITS_PARITY_MARK = 0x0030; - private static final int BITS_PARITY_SPACE = 0x0040; - - private static final int BITS_STOP_MASK = 0x000f; - private static final int BITS_STOP_1 = 0x0000; - private static final int BITS_STOP_1_5 = 0x0001; - private static final int BITS_STOP_2 = 0x0002; - - /* CP210X_SET_BREAK */ - @SuppressWarnings("unused") - private static final int BREAK_ON = 0x0001; - @SuppressWarnings("unused") - private static final int BREAK_OFF = 0x0000; - - /* CP210X_(SET_MHS|GET_MDMSTS) */ - private static final int CONTROL_DTR = 0x0001; - private static final int CONTROL_RTS = 0x0002; - @SuppressWarnings("unused") - private static final int CONTROL_CTS = 0x0010; - @SuppressWarnings("unused") - private static final int CONTROL_DSR = 0x0020; - @SuppressWarnings("unused") - private static final int CONTROL_RING = 0x0040; - @SuppressWarnings("unused") - private static final int CONTROL_DCD = 0x0080; - private static final int CONTROL_WRITE_DTR = 0x0100; - private static final int CONTROL_WRITE_RTS = 0x0200; - - public UartCp210x(Context context) { - super(context); - mUsbConnetionManager = new UsbCdcConnection(context); - mUartConfig = new UartConfig(); - mBuffer = new RingBuffer(RING_BUFFER_SIZE); - isOpened = false; - } - - @Override - public boolean open() { - for(UsbVidList id : UsbVidList.values()) { - if(open(new UsbVidPid(id.getVid(), 0))){ +public class UartCp210x extends SerialCommunicator { + + private static final String TAG = UartCp210x.class.getSimpleName(); + private boolean DEBUG_SHOW = false; + private static final int DEFAULT_BAUDRATE = 9600; + private UsbCdcConnection mUsbConnetionManager; + private UartConfig mUartConfig; + private static final int RING_BUFFER_SIZE = 1024; + private static final int USB_READ_BUFFER_SIZE = 256; + private static final int USB_WRITE_BUFFER_SIZE = 256; + private RingBuffer mBuffer; + private boolean mReadThreadStop = true; + private UsbDeviceConnection mConnection; + private UsbEndpoint mEndpointIn; + private UsbEndpoint mEndpointOut; + private boolean isOpened; + + /* + * Config request types + */ + private static final byte REQTYPE_HOST_TO_INTERFACE = (byte) 0x41; + private static final byte REQTYPE_INTERFACE_TO_HOST = (byte) 0xc1; + @SuppressWarnings("unused") + private static final byte REQTYPE_HOST_TO_DEVICE = (byte) 0x40; + @SuppressWarnings("unused") + private static final byte REQTYPE_DEVICE_TO_HOST = (byte) 0xc0; + + /* + * Config request codes + */ + private static final byte CP210X_IFC_ENABLE = 0x00; + @SuppressWarnings("unused") + private static final byte CP210X_SET_BAUDDIV = 0x01; + @SuppressWarnings("unused") + private static final byte CP210X_GET_BAUDDIV = 0x02; + @SuppressWarnings("unused") + private static final byte CP210X_SET_LINE_CTL = 0x03; + private static final byte CP210X_GET_LINE_CTL = 0x04; + @SuppressWarnings("unused") + private static final byte CP210X_SET_BREAK = 0x05; + @SuppressWarnings("unused") + private static final byte CP210X_IMM_CHAR = 0x06; + private static final byte CP210X_SET_MHS = 0x07; + @SuppressWarnings("unused") + private static final byte CP210X_GET_MDMSTS = 0x08; + @SuppressWarnings("unused") + private static final byte CP210X_SET_XON = 0x09; + @SuppressWarnings("unused") + private static final byte CP210X_SET_XOFF = 0x0A; + @SuppressWarnings("unused") + private static final byte CP210X_SET_EVENTMASK = 0x0B; + @SuppressWarnings("unused") + private static final byte CP210X_GET_EVENTMASK = 0x0C; + @SuppressWarnings("unused") + private static final byte CP210X_SET_CHAR = 0x0D; + @SuppressWarnings("unused") + private static final byte CP210X_GET_CHARS = 0x0E; + @SuppressWarnings("unused") + private static final byte CP210X_GET_PROPS = 0x0F; + @SuppressWarnings("unused") + private static final byte CP210X_GET_COMM_STATUS = 0x10; + @SuppressWarnings("unused") + private static final byte CP210X_RESET = 0x11; + @SuppressWarnings("unused") + private static final byte CP210X_PURGE = 0x12; + @SuppressWarnings("unused") + private static final byte CP210X_SET_FLOW = 0x13; + @SuppressWarnings("unused") + private static final byte CP210X_GET_FLOW = 0x14; + @SuppressWarnings("unused") + private static final byte CP210X_EMBED_EVENTS = 0x15; + @SuppressWarnings("unused") + private static final byte CP210X_GET_EVENTSTATE = 0x16; + @SuppressWarnings("unused") + private static final byte CP210X_SET_CHARS = 0x19; + @SuppressWarnings("unused") + private static final byte CP210X_GET_BAUDRATE = 0x1D; + private static final byte CP210X_SET_BAUDRATE = 0x1E; + + /* + * CP210X_IFC_ENABLE + */ + private static final int UART_ENABLE = 0x0001; + private static final int UART_DISABLE = 0x0000; + + /* + * CP210X_(SET|GET)_BAUDDIV + */ + @SuppressWarnings("unused") + private static final int BAUD_RATE_GEN_FREQ = 0x384000; + + /* + * CP210X_(SET|GET)_LINE_CTL + */ + private static final int BITS_DATA_MASK = 0x0f00; + @SuppressWarnings("unused") + private static final int BITS_DATA_5 = 0x0500; + @SuppressWarnings("unused") + private static final int BITS_DATA_6 = 0x0600; + ; + private static final int BITS_DATA_7 = 0x0700; + private static final int BITS_DATA_8 = 0x0800; + @SuppressWarnings("unused") + private static final int BITS_DATA_9 = 0x0900; + private static final int BITS_PARITY_MASK = 0x00f0; + private static final int BITS_PARITY_NONE = 0x0000; + private static final int BITS_PARITY_ODD = 0x0010; + private static final int BITS_PARITY_EVEN = 0x0020; + private static final int BITS_PARITY_MARK = 0x0030; + private static final int BITS_PARITY_SPACE = 0x0040; + private static final int BITS_STOP_MASK = 0x000f; + private static final int BITS_STOP_1 = 0x0000; + private static final int BITS_STOP_1_5 = 0x0001; + private static final int BITS_STOP_2 = 0x0002; + + /* + * CP210X_SET_BREAK + */ + @SuppressWarnings("unused") + private static final int BREAK_ON = 0x0001; + @SuppressWarnings("unused") + private static final int BREAK_OFF = 0x0000; + + /* + * CP210X_(SET_MHS|GET_MDMSTS) + */ + private static final int CONTROL_DTR = 0x0001; + private static final int CONTROL_RTS = 0x0002; + @SuppressWarnings("unused") + private static final int CONTROL_CTS = 0x0010; + @SuppressWarnings("unused") + private static final int CONTROL_DSR = 0x0020; + @SuppressWarnings("unused") + private static final int CONTROL_RING = 0x0040; + @SuppressWarnings("unused") + private static final int CONTROL_DCD = 0x0080; + private static final int CONTROL_WRITE_DTR = 0x0100; + private static final int CONTROL_WRITE_RTS = 0x0200; + + public UartCp210x(Context context) { + super(context); + mUsbConnetionManager = new UsbCdcConnection(context); + mUartConfig = new UartConfig(); + mBuffer = new RingBuffer(RING_BUFFER_SIZE); + isOpened = false; + } + + @Override + public boolean open() { + for(UsbVidList id : UsbVidList.values()) { + if(id.getVid() == 0x10C4) { + if(open(new UsbVidPid(id.getVid(), 0))) { + return true; + } + } + } + return false; + } + + public boolean open(UsbVidPid ids) { + if(mUsbConnetionManager.open(ids)) { + mConnection = mUsbConnetionManager.getConnection(); + mEndpointIn = mUsbConnetionManager.getEndpointIn(); + mEndpointOut = mUsbConnetionManager.getEndpointOut(); + if(!init()) { + return false; + } + if(!setBaudrate(DEFAULT_BAUDRATE)) { + return false; + } + mBuffer.clear(); + startRead(); + isOpened = true; + return true; + } + return false; + } + + @Override + public boolean close() { + stopRead(); + isOpened = false; + cp210xUsbDisable(); + return mUsbConnetionManager.close(); + } + + @Override + public int read(byte[] buf, int size) { + return mBuffer.get(buf, size); + } + + @Override + public int write(byte[] buf, int size) { + if(buf == null) { + return 0; + } + int offset = 0; + int write_size; + int written_size; + byte[] wbuf = new byte[USB_WRITE_BUFFER_SIZE]; + + while(offset < size) { + write_size = USB_WRITE_BUFFER_SIZE; + + if(offset + write_size > size) { + write_size = size - offset; + } + System.arraycopy(buf, offset, wbuf, 0, write_size); + + written_size = mConnection.bulkTransfer(mEndpointOut, wbuf, write_size, 100); + + if(written_size < 0) { + return -1; + } + offset += written_size; + } + + return offset; + } + + private void stopRead() { + mReadThreadStop = true; + } + + private void startRead() { + if(mReadThreadStop) { + mReadThreadStop = false; + new Thread(mLoop).start(); + } + } + private Runnable mLoop = new Runnable() { + + @Override + public void run() { + int len; + // byte[] rbuf = new byte[USB_READ_BUFFER_SIZE]; + byte[] rbuf = new byte[mEndpointIn.getMaxPacketSize()]; + android.os.Process.setThreadPriority(-20); + UsbRequest response; + UsbRequest request = new UsbRequest(); + request.initialize(mConnection, mEndpointIn); + ByteBuffer buf = ByteBuffer.wrap(rbuf); + for(;;) {// this is the main loop for transferring + len = 0; + if(request.queue(buf, rbuf.length)) { + response = mConnection.requestWait(); + if(response != null) { + len = buf.position(); + } + if(len > 0) { + mBuffer.add(rbuf, len); + onRead(len); + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } + + + } + + if(mReadThreadStop) { + return; + } + + try { + Thread.sleep(1); + } catch(InterruptedException e) { + } + + } + } // end of run() + }; // end of runnable + + @Override + public boolean setUartConfig(UartConfig config) { + boolean res; + boolean ret = true; + res = setBaudrate(config.baudrate); + ret = ret && res; + + res = setDataBits(config.dataBits); + ret = ret && res; + + res = setParity(config.parity); + ret = ret && res; + + res = setStopBits(config.stopBits); + ret = ret && res; + + res = setDtrRts(config.dtrOn, config.rtsOn); + ret = ret && res; + + return ret; + } + + /** + * Initializes CP210x communication + * + * @return true : successful, false : fail + */ + private boolean init() { + int ret = cp210xUsbEnable(); + if(ret < 0) { + return false; + } return true; - } - } - return false; - } - - public boolean open(UsbVidPid ids) { - if(mUsbConnetionManager.open(ids)) { - mConnection = mUsbConnetionManager.getConnection(); - mEndpointIn = mUsbConnetionManager.getEndpointIn(); - mEndpointOut = mUsbConnetionManager.getEndpointOut(); - if(!init()) { return false; } - if(!setBaudrate(DEFAULT_BAUDRATE)) {return false;} - mBuffer.clear(); - startRead(); - isOpened = true; - return true; - } - return false; - } - - @Override - public boolean close() { - stopRead(); - isOpened = false; - cp210xUsbDisable(); - return mUsbConnetionManager.close(); - } - - @Override - public int read(byte[] buf, int size) { - return mBuffer.get(buf, size); - } - - @Override - public int write(byte[] buf, int size) { - if(buf == null) { return 0; } - int offset = 0; - int write_size; - int written_size; - byte[] wbuf = new byte[USB_WRITE_BUFFER_SIZE]; - - while (offset < size) { - write_size = USB_WRITE_BUFFER_SIZE; - - if (offset + write_size > size) { - write_size = size - offset; - } - System.arraycopy(buf, offset, wbuf, 0, write_size); - - written_size = mConnection.bulkTransfer(mEndpointOut, wbuf, write_size, 100); - - if (written_size < 0) { - return -1; - } - offset += written_size; - } - - return offset; - } - - private void stopRead() { - mReadThreadStop = true; - } - - private void startRead() { - if(mReadThreadStop) { - mReadThreadStop = false; - new Thread(mLoop).start(); - } - } - - private Runnable mLoop = new Runnable() { + } + @Override - public void run() { - int len=0; - byte[] rbuf = new byte[USB_READ_BUFFER_SIZE]; - for (;;) {// this is the main loop for transferring - - try { - len = mConnection.bulkTransfer(mEndpointIn, - rbuf, rbuf.length, 50); - } catch(Exception e) { - Log.e(TAG, e.toString()); + public boolean isOpened() { + return isOpened; + } + + /** + * Enables CP210x + * + * @return positive value : successful, negative value : fail + */ + private int cp210xUsbEnable() { + if(mConnection == null) { + return -1; } + return mConnection.controlTransfer( + REQTYPE_HOST_TO_INTERFACE, + CP210X_IFC_ENABLE, + UART_ENABLE, + 0, + null, + 0, + 100); + } - if (len > 0) { - mBuffer.add(rbuf, len); - onRead(len); + /** + * Disables CP210x + * + * @return positive value : successful, negative value : fail + */ + private int cp210xUsbDisable() { + if(mConnection == null) { + return -1; } + return mConnection.controlTransfer( + REQTYPE_HOST_TO_INTERFACE, + CP210X_IFC_ENABLE, + UART_DISABLE, + 0, + null, + 0, + 100); + } - if (mReadThreadStop) { - return; + /** + * Gets configurations from CP210x + * + * @param request request id + * @param buf gotten buffer + * @param size size of getting buffer + * @return positive value : successful, negative value : fail + */ + private int cp210xGetConfig(int request, byte[] buf, int size) { + if(mConnection == null) { + return -1; } + int ret = mConnection.controlTransfer( + REQTYPE_INTERFACE_TO_HOST, + request, + 0x0000, + 0, + buf, + size, + 100); + return ret; + } - try { - Thread.sleep(50); - } catch (InterruptedException e) { + /** + * Sets configurations from CP210x + * + * @param request request id + * @param buf set buffer + * @param size size of sending buffer + * @return + */ + private int cp210xSetConfig(int request, byte[] buf, int size) { + if(mConnection == null) { + return -1; } + int ret = mConnection.controlTransfer( + REQTYPE_HOST_TO_INTERFACE, + request, + 0x0000, + 0, + buf, + size, + 100); + return ret; + } - } - } // end of run() - }; // end of runnable - - @Override - public boolean setUartConfig(UartConfig config) { - boolean res = true; - boolean ret = true; - if(mUartConfig.baudrate != config.baudrate) { - res = setBaudrate(config.baudrate); - ret = ret && res; - } - - if(mUartConfig.dataBits != config.dataBits) { - res = setDataBits(config.dataBits); - ret = ret && res; - } - - if(mUartConfig.parity != config.parity) { - res = setParity(config.parity); - ret = ret && res; - } - - if(mUartConfig.stopBits != config.stopBits) { - res = setStopBits(config.stopBits); - ret = ret && res; - } - - if(mUartConfig.dtrOn != config.dtrOn || - mUartConfig.rtsOn != config.rtsOn) { - res = setDtrRts(config.dtrOn, config.rtsOn); - ret = ret && res; - } - - return ret; - } - - /** - * Initializes CP210x communication - * @return true : successful, false : fail - */ - private boolean init() { - int ret = cp210xUsbEnable(); - if(ret < 0) { return false; } - return true; - } - - @Override - public boolean isOpened() { - return isOpened; - } - - - /** - * Enables CP210x - * @return positive value : successful, negative value : fail - */ - private int cp210xUsbEnable() { - if(mConnection == null) return -1; - return mConnection.controlTransfer( - REQTYPE_HOST_TO_INTERFACE, - CP210X_IFC_ENABLE, - UART_ENABLE, - 0, - null, - 0, - 100); - } - - /** - * Disables CP210x - * @return positive value : successful, negative value : fail - */ - private int cp210xUsbDisable() { - if(mConnection == null) return -1; - return mConnection.controlTransfer( - REQTYPE_HOST_TO_INTERFACE, - CP210X_IFC_ENABLE, - UART_DISABLE, - 0, - null, - 0, - 100); - } - - /** - * Gets configurations from CP210x - * @param request request id - * @param buf gotten buffer - * @param size size of getting buffer - * @return positive value : successful, negative value : fail - */ - private int cp210xGetConfig(int request, byte[] buf, int size) { - if(mConnection == null) return -1; - int ret = mConnection.controlTransfer( - REQTYPE_INTERFACE_TO_HOST, - request, - 0x0000, - 0, - buf, - size, - 100); - return ret; - } - - /** - * Sets configurations from CP210x - * @param request request id - * @param buf set buffer - * @param size size of sending buffer - * @return - */ - private int cp210xSetConfig(int request, byte[] buf, int size) { - if(mConnection == null) return -1; - int ret = mConnection.controlTransfer( - REQTYPE_HOST_TO_INTERFACE, - request, - 0x0000, - 0, - buf, - size, - 100); - return ret; - } - - @Override - public boolean setBaudrate(int baudrate) { - if (baudrate <= 300) baudrate = 300; - else if (baudrate <= 600) baudrate = 600; - else if (baudrate <= 1200) baudrate = 1200; - else if (baudrate <= 1800) baudrate = 1800; - else if (baudrate <= 2400) baudrate = 2400; - else if (baudrate <= 4000) baudrate = 4000; - else if (baudrate <= 4803) baudrate = 4800; - else if (baudrate <= 7207) baudrate = 7200; - else if (baudrate <= 9612) baudrate = 9600; - else if (baudrate <= 14428) baudrate = 14400; - else if (baudrate <= 16062) baudrate = 16000; - else if (baudrate <= 19250) baudrate = 19200; - else if (baudrate <= 28912) baudrate = 28800; - else if (baudrate <= 38601) baudrate = 38400; - else if (baudrate <= 51558) baudrate = 51200; - else if (baudrate <= 56280) baudrate = 56000; - else if (baudrate <= 58053) baudrate = 57600; - else if (baudrate <= 64111) baudrate = 64000; - else if (baudrate <= 77608) baudrate = 76800; - else if (baudrate <= 117028) baudrate = 115200; - else if (baudrate <= 129347) baudrate = 128000; - else if (baudrate <= 156868) baudrate = 153600; - else if (baudrate <= 237832) baudrate = 230400; - else if (baudrate <= 254234) baudrate = 250000; - else if (baudrate <= 273066) baudrate = 256000; - else if (baudrate <= 491520) baudrate = 460800; - else if (baudrate <= 567138) baudrate = 500000; - else if (baudrate <= 670254) baudrate = 576000; - else if (baudrate < 1000000) baudrate = 921600; - else if (baudrate > 2000000) baudrate = 2000000; - - byte[] baudBytes = new byte[4]; - intToLittleEndianBytes(baudrate, baudBytes); - int ret = cp210xSetConfig(CP210X_SET_BAUDRATE, baudBytes, 4); - if(ret < 0) { - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setBaudrate"); } - return false; - } - mUartConfig.baudrate = baudrate; - return true; - } - - @Override - public boolean setDataBits(int dataBits) { - int bits; - byte[] buf = new byte[2]; - - cp210xGetConfig(CP210X_GET_LINE_CTL, buf, buf.length); - bits = littleEndianBytesToInt(buf); - bits &= ~BITS_DATA_MASK; - - switch (dataBits) { - case UartConfig.DATA_BITS7: - bits |= BITS_DATA_7; - break; - - case UartConfig.DATA_BITS8: - bits |= BITS_DATA_8; - break; - - default: - bits |= BITS_DATA_8; - break; - } - - intToLittleEndianBytes(bits, buf); - int ret = cp210xSetConfig(CP210X_GET_LINE_CTL, buf, buf.length); - - if(ret < 0) { - if(DEBUG_SHOW) { Log.e(TAG, "Fail to setDataBits"); } - return false; - } - - mUartConfig.dataBits = dataBits; - return true; - } - - - @Override - public boolean setParity(int parity) { - int bits; - byte[] buf = new byte[2]; - - cp210xGetConfig(CP210X_GET_LINE_CTL, buf, buf.length); - bits = littleEndianBytesToInt(buf); - bits &= ~BITS_PARITY_MASK; - - switch (parity) { - - case UartConfig.PARITY_NONE: - bits |= BITS_PARITY_NONE; - break; - - case UartConfig.PARITY_ODD: - bits |= BITS_PARITY_ODD; - break; - - case UartConfig.PARITY_EVEN: - bits |= BITS_PARITY_EVEN; - break; - - case UartConfig.PARITY_MARK: - bits |= BITS_PARITY_MARK; - break; - - case UartConfig.PARITY_SPACE: - bits |= BITS_PARITY_SPACE; - break; + @Override + public boolean setBaudrate(int baudrate) { + // TO-DO: Allow any baud rate. Why isn't this possible here? + if(baudrate <= 300) { + baudrate = 300; + } else if(baudrate <= 600) { + baudrate = 600; + } else if(baudrate <= 1200) { + baudrate = 1200; + } else if(baudrate <= 1800) { + baudrate = 1800; + } else if(baudrate <= 2400) { + baudrate = 2400; + } else if(baudrate <= 4000) { + baudrate = 4000; + } else if(baudrate <= 4803) { + baudrate = 4800; + } else if(baudrate <= 7207) { + baudrate = 7200; + } else if(baudrate <= 9612) { + baudrate = 9600; + } else if(baudrate <= 14428) { + baudrate = 14400; + } else if(baudrate <= 16062) { + baudrate = 16000; + } else if(baudrate <= 19250) { + baudrate = 19200; + } else if(baudrate <= 28912) { + baudrate = 28800; + } else if(baudrate <= 38601) { + baudrate = 38400; + } else if(baudrate <= 51558) { + baudrate = 51200; + } else if(baudrate <= 56280) { + baudrate = 56000; + } else if(baudrate <= 58053) { + baudrate = 57600; + } else if(baudrate <= 64111) { + baudrate = 64000; + } else if(baudrate <= 77608) { + baudrate = 76800; + } else if(baudrate <= 117028) { + baudrate = 115200; + } else if(baudrate <= 129347) { + baudrate = 128000; + } else if(baudrate <= 156868) { + baudrate = 153600; + } else if(baudrate <= 237832) { + baudrate = 230400; + } else if(baudrate <= 254234) { + baudrate = 250000; + } else if(baudrate <= 273066) { + baudrate = 256000; + } else if(baudrate <= 491520) { + baudrate = 460800; + } else if(baudrate <= 567138) { + baudrate = 500000; + } else if(baudrate <= 670254) { + baudrate = 576000; + } else if(baudrate < 1000000) { + baudrate = 921600; + } else if(baudrate > 2000000) { + baudrate = 2000000; + } - default: - bits |= BITS_PARITY_NONE; - break; + byte[] baudBytes = new byte[4]; + intToLittleEndianBytes(baudrate, baudBytes); + int ret = cp210xSetConfig(CP210X_SET_BAUDRATE, baudBytes, 4); + if(ret < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setBaudrate"); + } + return false; + } + mUartConfig.baudrate = baudrate; + return true; } - intToLittleEndianBytes(bits, buf); - int ret = cp210xSetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + @Override + public boolean setDataBits(int dataBits) { + int bits; + byte[] buf = new byte[2]; + + cp210xGetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + bits = littleEndianBytesToInt(buf); + bits &= ~BITS_DATA_MASK; + + switch(dataBits) { + case UartConfig.DATA_BITS7: + bits |= BITS_DATA_7; + break; + + case UartConfig.DATA_BITS8: + bits |= BITS_DATA_8; + break; + + default: + bits |= BITS_DATA_8; + break; + } - if(ret < 0) { - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setParity"); } - return false; + intToLittleEndianBytes(bits, buf); + int ret = cp210xSetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + + if(ret < 0) { + if(DEBUG_SHOW) { + Log.e(TAG, "Fail to setDataBits"); + } + return false; + } + + mUartConfig.dataBits = dataBits; + return true; } - mUartConfig.parity = parity; - return true; - } + @Override + public boolean setParity(int parity) { + int bits; + byte[] buf = new byte[2]; + + cp210xGetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + bits = littleEndianBytesToInt(buf); + bits &= ~BITS_PARITY_MASK; + switch(parity) { - @Override - public boolean setStopBits(int stopBits) { - int bits; - byte[] buf = new byte[2]; + case UartConfig.PARITY_NONE: + bits |= BITS_PARITY_NONE; + break; - cp210xGetConfig(CP210X_GET_LINE_CTL, buf, buf.length); - bits = littleEndianBytesToInt(buf); - bits &= ~BITS_STOP_MASK; + case UartConfig.PARITY_ODD: + bits |= BITS_PARITY_ODD; + break; - switch (stopBits) { - case UartConfig.STOP_BITS1: - bits |= BITS_STOP_1; - break; + case UartConfig.PARITY_EVEN: + bits |= BITS_PARITY_EVEN; + break; - case UartConfig.STOP_BITS1_5: - bits |= BITS_STOP_1_5; - break; + case UartConfig.PARITY_MARK: + bits |= BITS_PARITY_MARK; + break; - case UartConfig.STOP_BITS2: - bits |= BITS_STOP_2; - break; + case UartConfig.PARITY_SPACE: + bits |= BITS_PARITY_SPACE; + break; - default: - bits |= BITS_STOP_1; - break; + default: + bits |= BITS_PARITY_NONE; + break; + } + + intToLittleEndianBytes(bits, buf); + int ret = cp210xSetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + + if(ret < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setParity"); + } + return false; + } + + mUartConfig.parity = parity; + return true; } - intToLittleEndianBytes(bits, buf); - int ret = cp210xSetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + @Override + public boolean setStopBits(int stopBits) { + int bits; + byte[] buf = new byte[2]; + + cp210xGetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + bits = littleEndianBytesToInt(buf); + bits &= ~BITS_STOP_MASK; + + switch(stopBits) { + case UartConfig.STOP_BITS1: + bits |= BITS_STOP_1; + break; + + case UartConfig.STOP_BITS1_5: + bits |= BITS_STOP_1_5; + break; + + case UartConfig.STOP_BITS2: + bits |= BITS_STOP_2; + break; + + default: + bits |= BITS_STOP_1; + break; + } - if(ret < 0) { - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setStopBits"); } - return false; + intToLittleEndianBytes(bits, buf); + int ret = cp210xSetConfig(CP210X_GET_LINE_CTL, buf, buf.length); + + if(ret < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setStopBits"); + } + return false; + } + + mUartConfig.stopBits = stopBits; + return true; + } + + @Override + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { + int ctrlValue = 0x0000; + byte[] buf = new byte[4]; + + if(dtrOn) { + ctrlValue |= CONTROL_DTR; + ctrlValue |= CONTROL_WRITE_DTR; + } else { + ctrlValue &= ~CONTROL_DTR; + ctrlValue |= CONTROL_WRITE_DTR; + } + + if(rtsOn) { + ctrlValue |= CONTROL_RTS; + ctrlValue |= CONTROL_WRITE_RTS; + } else { + ctrlValue &= ~CONTROL_RTS; + ctrlValue |= CONTROL_WRITE_RTS; + } + + intToLittleEndianBytes(ctrlValue, buf); + int ret = cp210xSetConfig(CP210X_SET_MHS, buf, buf.length); + + if(ret < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setDtrRts"); + } + return false; + } + mUartConfig.dtrOn = dtrOn; + mUartConfig.rtsOn = rtsOn; + return true; + } + + @Override + public UartConfig getUartConfig() { + return mUartConfig; + } + + @Override + public int getBaudrate() { + return mUartConfig.baudrate; + } + + @Override + public int getDataBits() { + return mUartConfig.dataBits; + } + + @Override + public int getParity() { + return mUartConfig.parity; + } + + @Override + public int getStopBits() { + return mUartConfig.stopBits; + } + + @Override + public boolean getDtr() { + return mUartConfig.dtrOn; + } + + @Override + public boolean getRts() { + return mUartConfig.rtsOn; + } + + @Override + public void clearBuffer() { + mBuffer.clear(); + } + ////////////////////////////////////////////////////////// + // Listener for reading uart + ////////////////////////////////////////////////////////// + private List uartReadListenerList = new ArrayList(); + private boolean mStopReadListener = false; + + @Override + public void addReadListener(ReadListener listener) { + uartReadListenerList.add(listener); + } + + @Override + @Deprecated + public void addReadListener(ReadLisener listener) { + addReadListener((ReadListener)listener); + } + + @Override + public void clearReadListener() { + uartReadListenerList.clear(); + } + + @Override + public void startReadListener() { + mStopReadListener = false; + } + + @Override + public void stopReadListener() { + mStopReadListener = true; } - mUartConfig.stopBits = stopBits; - return true; - } + private void onRead(int size) { + if(mStopReadListener) { + return; + } + for(ReadListener listener : uartReadListenerList) { + listener.onRead(size); + } + } + ////////////////////////////////////////////////////////// + + /** + * Transfers int to little endian byte array + * + * @param in integer value + * @param out 4 or less length byte array + */ + private void intToLittleEndianBytes(int in, byte[] out) { + if(out == null) { + return; + } + if(out.length > 4) { + return; + } + for(int i = 0; i < out.length; i++) { + out[i] = (byte) ((in >> (i * 8)) & 0x000000FF); + } + } - @Override - public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { - int ctrlValue = 0x0000; - byte[] buf = new byte[4]; + /** + * Transfers little endian byte array to int + * + * @param in 4 or less length byte array + * @return integer value + */ + private int littleEndianBytesToInt(byte[] in) { + if(in == null) { + return 0; + } + if(in.length > 4) { + return 0; + } + int ret = 0; + for(int i = 0; i < in.length; i++) { + ret |= (((int) in[i]) & 0x000000FF) << (i * 8); + } + return ret; + } - if(dtrOn) { - ctrlValue |= CONTROL_DTR; - ctrlValue |= CONTROL_WRITE_DTR; - } else { - ctrlValue &= ~CONTROL_DTR; - ctrlValue |= CONTROL_WRITE_DTR; + @Override + public String getPhysicalConnectionName() { + return Physicaloid.USB_STRING; } - if(rtsOn) { - ctrlValue |= CONTROL_RTS; - ctrlValue |= CONTROL_WRITE_RTS; - } else { - ctrlValue &= ~CONTROL_RTS; - ctrlValue |= CONTROL_WRITE_RTS; + @Override + public int getPhysicalConnectionType() { + return Physicaloid.USB; } - intToLittleEndianBytes(ctrlValue, buf); - int ret = cp210xSetConfig(CP210X_SET_MHS, buf, buf.length); - - if(ret < 0) { - if(DEBUG_SHOW) { Log.d(TAG, "Fail to setDtrRts"); } - return false; - } - mUartConfig.dtrOn = dtrOn; - mUartConfig.rtsOn = rtsOn; - return true; - } - - @Override - public UartConfig getUartConfig() { - return mUartConfig; - } - - @Override - public int getBaudrate() { - return mUartConfig.baudrate; - } - - @Override - public int getDataBits() { - return mUartConfig.dataBits; - } - - @Override - public int getParity() { - return mUartConfig.parity; - } - - @Override - public int getStopBits() { - return mUartConfig.stopBits; - } - - @Override - public boolean getDtr() { - return mUartConfig.dtrOn; - } - - @Override - public boolean getRts() { - return mUartConfig.rtsOn; - } - - @Override - public void clearBuffer() { - mBuffer.clear(); - } - - ////////////////////////////////////////////////////////// - // Listener for reading uart - ////////////////////////////////////////////////////////// - private List uartReadListenerList - = new ArrayList(); - private boolean mStopReadListener = false; - - @Override - public void addReadListener(ReadLisener listener) { - uartReadListenerList.add(listener); - } - - @Override - public void clearReadListener() { - uartReadListenerList.clear(); - } - - @Override - public void startReadListener() { - mStopReadListener = false; - } - - @Override - public void stopReadListener() { - mStopReadListener = true; - } - - private void onRead(int size) { - if(mStopReadListener) return; - for (ReadLisener listener: uartReadListenerList) { - listener.onRead(size); - } - } - ////////////////////////////////////////////////////////// - - - /** - * Transfers int to little endian byte array - * @param in integer value - * @param out 4 or less length byte array - */ - private void intToLittleEndianBytes(int in, byte[] out) { - if(out == null) return; - if(out.length > 4) return; - for(int i=0; i> (i*8)) & 0x000000FF); - } - } - - /** - * Transfers little endian byte array to int - * @param in 4 or less length byte array - * @return integer value - */ - private int littleEndianBytesToInt(byte[] in) { - if(in == null) return 0; - if(in.length > 4) return 0; - int ret=0; - for(int i=0; i 0) { - synchronized(ftDev) { - ftDev = ftD2xx.openByIndex(mContext, USB_OPEN_INDEX); + if(mConnection == null) { + return false; + } + int rv; + rv = control_out(FTDI_SIO_RESET, 0, 0); + if(rv < 0) { + return false; + } + rv = control_out(FTDI_SIO_SET_FLOW_CTRL, 0, 1); + if(rv < 0) { + return false; } - } + // set the latency timer to a very low number to improve performance. + rv = control_out(FTDI_SIO_SET_LATENCY_TIMER, 0, 1); + if(rv < 0) { + return false; + } + return true; } - if(ftDev.isOpen()) { - synchronized(ftDev) { - ftDev.resetDevice(); // flush any data from the device buffers - } - setBaudrate(mUartConfig.baudrate); - if(DEBUG_SHOW){ Log.d(TAG, "An FTDI device is opened."); } - startRead(); - return true; - } else { - if(DEBUG_SHOW){ Log.e(TAG, "Cannot open an FTDI device."); } + @Override + public boolean close() { + if(mUsbConnetionManager != null) { + stopRead(); + isOpened = false; + return mUsbConnetionManager.close(); + } + return true; } - return false; - } + @Override + public int read(byte[] buf, int size) { + return mBuffer.get(buf, size); + } - @Override - public boolean close() { - if(ftDev != null) { - stopRead(); - synchronized (ftDev) { - ftDev.close(); - } - if(DEBUG_SHOW){ Log.d(TAG, "An FTDI device is closed."); } + private int control_out(int request, int value, int index) { + if(mConnection == null) { + return -1; + } + if(DEBUG_SHOW) { + Log.d(TAG, "XXXXXXXXXXXXXXXXXXXXXXXXX CTRL r=" + String.format("0x%02X", request) + " v=" + String.format("0x%04X", value) + " i=" + String.format("0x%04X", index)); + } + int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_INTERFACE, request, value, index, null, 0, 100); + return ret; } - return true; - } + private int control_in(int request, int value, int index, byte buf[], int bufsize) { + if(mConnection == null) { + return -1; + } + int ret = mConnection.controlTransfer(REQTYPE_INTERFACE_TO_HOST, request, value, index, buf, bufsize, 100); + return ret; - @Override - public int read(byte[] buf, int size) { - return mBuffer.get(buf, size); - } + } + @Override + public int write(byte[] buf, int size) { + if(buf == null) { + return 0; + } + int offset = 0; + int write_size; + int written_size; + int len; - @Override - public int write(byte[] buf, int size) { - if(buf == null) { return 0; } - int offset = 0; - int write_size; - int written_size; - byte[] wbuf = new byte[USB_WRITE_BUFFER_SIZE]; + if(DEBUG_SHOW) { + Log.e(TAG, "write(" + size + "): " + toHexStr(buf, size)); + } - while (offset < size) { - write_size = USB_WRITE_BUFFER_SIZE; + // FTDI is crap, makes us work hard. + // We have to treat the chip as if it is an 8250 on the outbound + // otherwise it seems that characters don't always seem to make it. + while(offset < size) { + // check empty + while(true) { + len = 2; + written_size = control_in(FTDI_SIO_GET_MODEM_STATUS, 0, 0, wbuf, len); + if(written_size < 1) { + return -1; + } + if(written_size == 1) { + wbuf[1] = 0; + } + if((wbuf[1] & FTDI_RS_TEMT) == FTDI_RS_TEMT) { + break; + } + } + write_size = 1; + if(offset + write_size > size) { + write_size = size - offset; + } + // optimization! + if(offset == 0) { + //synchronized(DevLock) { + written_size = mConnection.bulkTransfer(mEndpointOut, buf, write_size, 100); + + //} + } else { + System.arraycopy(buf, offset, wbuf, 0, write_size); + //synchronized(DevLock) { + written_size = mConnection.bulkTransfer(mEndpointOut, wbuf, write_size, 100); + //} + } + if(written_size < 0) { + return -1; + } + offset += written_size; + } - if (offset + write_size > size) { - write_size = size - offset; - } - System.arraycopy(buf, offset, wbuf, 0, write_size); + return offset; + } - synchronized (ftDev) { - written_size = ftDev.write(wbuf, write_size); - } + private void stopRead() { + mReadThreadStop = true; + } - if (written_size < 0) { - return -1; - } - offset += written_size; + private void startRead() { + if(mReadThreadStop) { + mReadThreadStop = false; + new Thread(mLoop).start(); + } } + private Runnable mLoop = new Runnable() { + + @Override + @SuppressWarnings("CallToThreadYield") + public void run() { + try { + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND); + } catch(Exception e) { + } + int len; + //byte[] rbuf = new byte[USB_READ_BUFFER_SIZE]; + byte[] rbuf = new byte[mEndpointIn.getMaxPacketSize()]; + byte[] cbuf = new byte[mEndpointIn.getMaxPacketSize()]; + //android.os.Process.setThreadPriority(-20); + UsbRequest response; + UsbRequest request = new UsbRequest(); + request.initialize(mConnection, mEndpointIn); + ByteBuffer buf = ByteBuffer.wrap(rbuf); + for(;;) {// this is the main loop for transferring + len = 0; + //synchronized(DevLock) { + if(request.queue(buf, rbuf.length)) { + response = mConnection.requestWait(); + if(response != null) { + len = buf.position(); + } + } + //} + if(len > 1) { + if(len > 2) { + //if(DEBUG_SHOW) { + // Log.e(TAG, "read(" + len + "): " + toHexStr(rbuf, len)); + //} + // FTDI stuffs status in the first 2 bytes. + len -= 2; + System.arraycopy(rbuf, 2, cbuf, 0, len); + if(DEBUG_SHOW) { + Log.e(TAG, "read(" + len + "): " + toHexStr(cbuf, len)); + } + mBuffer.add(cbuf, len); + onRead(mBuffer.getBufferdLength()); + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } + + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } + + if(mReadThreadStop) { + return; + } + } + } // end of run() + }; // end of runnable + + @Override + public boolean setUartConfig(UartConfig config) { + boolean res; + boolean ret = true; + res = setBaudrate(config.baudrate); + ret = ret && res; - return offset; - } + res = setDataBits(config.dataBits); + ret = ret && res; + res = setParity(config.parity); + ret = ret && res; - private void stopRead() { - mReadThreadStop = true; - } + res = setStopBits(config.stopBits); + ret = ret && res; + res = setDtrRts(config.dtrOn, config.rtsOn); + ret = ret && res; - private void startRead() { - if(mReadThreadStop) { - mReadThreadStop = false; - new Thread(mLoop).start(); + return ret; } - } - - private Runnable mLoop = new Runnable() { @Override - public void run() { - int len=0; - byte[] rbuf = new byte[USB_READ_BUFFER_SIZE]; - for (;;) {// this is the main loop for transferring + public boolean isOpened() { + return isOpened; + } - synchronized (ftDev) { - len = ftDev.getQueueStatus(); + @Override + public boolean setBaudrate(int baudrate) { + if(mUsbConnetionManager == null) { + return false; } - - if(len > 0) { - if(len > MAX_READBUF_SIZE) len = MAX_READBUF_SIZE; - synchronized (ftDev) { - len = ftDev.read(rbuf,len,READ_WAIT_MS); // You might want to set wait_ms. - } - - if(DEBUG_SHOW){ Log.e(TAG, "read("+len+"): "+toHexStr(rbuf, len)); } - mBuffer.add(rbuf, len); - onRead(len); - + int divfrac[] = {0, 3, 2, 4, 1, 5, 6, 7}; + int baud_value = 0; // uint16_t + int baud_index = 0; // uint16_t + int divisor3; + divisor3 = 48000000 / 2 / baudrate; // divisor shifted 3 bits to the left + + if(mUsbConnetionManager.getPID() == FT232AM) { + if((divisor3 & 0x7) == 7) { + divisor3++; // round x.7/8 up to x+1 + } + baud_value = divisor3 >> 3; + divisor3 &= 0x7; + + if(divisor3 == 1) { + baud_value |= 0xc000; + } else // 0.125 + if(divisor3 >= 4) { + baud_value |= 0x4000; + } else // 0.5 + if(divisor3 != 0) { + baud_value |= 0x8000; // 0.25 + } + if(baud_value == 1) { + baud_value = 0; /* special case for maximum baud rate */ + } + } else { + + baud_value = divisor3 >> 3; + baud_value |= divfrac[divisor3 & 0x7] << 14; + //baud_index = divindex[divisor3 & 0x7]; + + /* Deal with special cases for highest baud rates. */ + if(baud_value == 1) { + baud_value = 0; + } else // 1.0 + if(baud_value == 0x4001) { + baud_value = 1; // 1.5 + } } - - if (mReadThreadStop) { - return; + baud_index = (baud_value >> 16) & 0xFFFF; + baud_value &= 0xFFFF; + + int rv = control_out(FTDI_SIO_SET_BAUD_RATE, baud_value, baud_index); + if(rv < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "setBaudrate failed " + rv); + } + return false; } + mUartConfig.baudrate = baudrate; + return true; + } - try { - Thread.sleep(50); - } catch (InterruptedException e) { + @Override + public boolean setDataBits(int dataBits) { + if(mUsbConnetionManager == null) { + return false; } - - } - } // end of run() - }; // end of runnable - - - @Override - public boolean setUartConfig(UartConfig config) { - boolean res = true; - boolean ret = true; - if(mUartConfig.baudrate != config.baudrate) { - res = setBaudrate(config.baudrate); - ret = ret && res; + int s = ((mUartConfig.stopBits) << 11) | ((mUartConfig.parity) << 8) | dataBits; + int rv = control_out(FTDI_SIO_SET_DATA, s, 1); + if(rv < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "setDataBits failed " + rv); + } + return false; + } + mUartConfig.dataBits = dataBits; + return true; } - if(mUartConfig.dataBits != config.dataBits) { - res = setDataBits(config.dataBits); - ret = ret && res; + @Override + public boolean setParity(int parity) { + if(mUsbConnetionManager == null) { + return false; + } + int s = ((mUartConfig.stopBits) << 11) | ((parity) << 8) | mUartConfig.dataBits; + int rv = control_out(FTDI_SIO_SET_DATA, s, 1); + if(rv < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "setParity failed " + rv); + } + return false; + } + mUartConfig.parity = parity; + return true; } - if(mUartConfig.parity != config.parity) { - res = setParity(config.parity); - ret = ret && res; + @Override + public boolean setStopBits(int stopBits) { + if(mUsbConnetionManager == null) { + return false; + } + int s = ((stopBits) << 11) | ((mUartConfig.parity) << 8) | mUartConfig.dataBits; + int rv = control_out(FTDI_SIO_SET_DATA, s, 1); + if(rv < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "setStopBits failed " + rv); + } + return false; + } + mUartConfig.stopBits = stopBits; + return true; } - if(mUartConfig.stopBits != config.stopBits) { - res = setStopBits(config.stopBits); - ret = ret && res; + @Override + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { + if(mUsbConnetionManager == null) { + return false; + } + if(DEBUG_SHOW) { + Log.d(TAG, "setDtrRts " + Boolean.toString(dtrOn) + ", " + Boolean.toString(rtsOn)); + } + int s = FTDI_SIO_SET_DTR_HIGH; + if(!dtrOn) { + s = FTDI_SIO_SET_DTR_LOW; + } + int rv = control_out(FTDI_SIO_MODEM_CTRL, s, 1); + if(rv < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "setDtr failed " + rv); + } + return false; + } + s = FTDI_SIO_SET_RTS_HIGH; + if(!rtsOn) { + s = FTDI_SIO_SET_RTS_LOW; + } + rv = control_out(FTDI_SIO_MODEM_CTRL, s, 1); + if(rv < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "setRts failed " + rv); + } + return false; + } + mUartConfig.dtrOn = dtrOn; + mUartConfig.rtsOn = rtsOn; + return true; } - if(mUartConfig.dtrOn != config.dtrOn || - mUartConfig.rtsOn != config.rtsOn) { - res = setDtrRts(config.dtrOn, config.rtsOn); - ret = ret && res; + @Override + public UartConfig getUartConfig() { + return mUartConfig; } - return ret; - } - - - @Override - public boolean isOpened() { - if(ftDev == null) { return false; } - synchronized (ftDev) { - return ftDev.isOpen(); + @Override + public int getBaudrate() { + return mUartConfig.baudrate; } - } - - @Override - public boolean setBaudrate(int baudrate) { - if(ftDev == null) { return false; } - boolean ret=false; - synchronized (ftDev) { - ret = ftDev.setBaudRate(baudrate); - } - if(ret) { - mUartConfig.baudrate = baudrate; + @Override + public int getDataBits() { + return mUartConfig.dataBits; } - return ret; - } - - @Override - public boolean setDataBits(int dataBits) { - if(ftDev == null) { return false; } - boolean ret = false; - byte ftdiDataBits = convertFtdiDataBits(dataBits); - byte ftdiStopBits = convertFtdiStopBits(mUartConfig.stopBits); - byte ftdiParity = convertFtdiParity(mUartConfig.parity); - synchronized (ftDev) { - ret = ftDev.setDataCharacteristics(ftdiDataBits, ftdiStopBits, ftdiParity); - } - if(ret) { - mUartConfig.dataBits = dataBits; + @Override + public int getParity() { + return mUartConfig.parity; } - return ret; - } - - @Override - public boolean setParity(int parity) { - if(ftDev == null) { return false; } - boolean ret = false; - byte ftdiDataBits = convertFtdiDataBits(mUartConfig.dataBits); - byte ftdiStopBits = convertFtdiStopBits(mUartConfig.stopBits); - byte ftdiParity = convertFtdiParity(parity); - synchronized (ftDev) { - ret = ftDev.setDataCharacteristics(ftdiDataBits, ftdiStopBits, ftdiParity); - } - if(ret) { - mUartConfig.parity = parity; + @Override + public int getStopBits() { + return mUartConfig.stopBits; } - return ret; - } - - @Override - public boolean setStopBits(int stopBits) { - if(ftDev == null) { return false; } - boolean ret = false; - byte ftdiDataBits = convertFtdiDataBits(mUartConfig.dataBits); - byte ftdiStopBits = convertFtdiStopBits(stopBits); - byte ftdiParity = convertFtdiParity(mUartConfig.parity); - synchronized (ftDev) { - ret = ftDev.setDataCharacteristics(ftdiDataBits, ftdiStopBits, ftdiParity); + @Override + public boolean getDtr() { + return mUartConfig.dtrOn; } - if(ret) { - mUartConfig.stopBits = stopBits; + + @Override + public boolean getRts() { + return mUartConfig.rtsOn; } - return ret; - } + @Override + public void clearBuffer() { + // clear ftdi chip buffer + //synchronized(ftDevLock) { + // ftDev.purge((byte) (D2xxManager.FT_PURGE_TX | D2xxManager.FT_PURGE_RX)); + //} - @Override - public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { - if(ftDev == null) { return false; } - boolean retDtr = false; - boolean retRts = false; - if(dtrOn) { - synchronized (ftDev) { - retDtr = ftDev.setDtr(); - } - } else { - synchronized (ftDev) { - retDtr = ftDev.clrDtr(); - } - } - if(retDtr) { - mUartConfig.dtrOn = dtrOn; + mBuffer.clear(); } + ////////////////////////////////////////////////////////// + // Listener for reading uart + ////////////////////////////////////////////////////////// + private List uartReadListenerList = new ArrayList(); + private boolean mStopReadListener = false; - if(rtsOn) { - synchronized (ftDev) { - retRts = ftDev.setRts(); - } - } else { - synchronized (ftDev) { - retRts = ftDev.clrRts(); - } - } - if(retRts) { - mUartConfig.rtsOn = rtsOn; + @Override + public void addReadListener(ReadListener listener) { + uartReadListenerList.add(listener); } - return retDtr&&retRts; - } - - - @Override - public UartConfig getUartConfig() { - return mUartConfig; - } - - - @Override - public int getBaudrate() { - return mUartConfig.baudrate; - } - - @Override - public int getDataBits() { - return mUartConfig.dataBits; - } - - - @Override - public int getParity() { - return mUartConfig.parity; - } - - - @Override - public int getStopBits() { - return mUartConfig.stopBits; - } - - - @Override - public boolean getDtr() { - return mUartConfig.dtrOn; - } - - - @Override - public boolean getRts() { - return mUartConfig.rtsOn; - } - - - @Override - public void clearBuffer() { - // clear ftdi chip buffer - synchronized (ftDev) { - ftDev.purge((byte) (D2xxManager.FT_PURGE_TX | D2xxManager.FT_PURGE_RX)); + @Override + @Deprecated + public void addReadListener(ReadLisener listener) { + addReadListener((ReadListener) listener); } - mBuffer.clear(); - } - - - ////////////////////////////////////////////////////////// - // Listener for reading uart - ////////////////////////////////////////////////////////// - private List uartReadListenerList - = new ArrayList(); - private boolean mStopReadListener = false; - - @Override - public void addReadListener(ReadLisener listener) { - uartReadListenerList.add(listener); - } - - @Override - public void clearReadListener() { - uartReadListenerList.clear(); - } - - @Override - public void startReadListener() { - mStopReadListener = false; - } - - @Override - public void stopReadListener() { - mStopReadListener = true; - } - private void onRead(int size) { - if(mStopReadListener) return; - for (ReadLisener listener: uartReadListenerList) { - listener.onRead(size); + @Override + public void clearReadListener() { + uartReadListenerList.clear(); } - } - ////////////////////////////////////////////////////////// - - private byte convertFtdiDataBits(int dataBits) { - switch (dataBits) { - case UartConfig.DATA_BITS7: - return D2xxManager.FT_DATA_BITS_7; - case UartConfig.DATA_BITS8: - return D2xxManager.FT_DATA_BITS_8; - default: - return D2xxManager.FT_DATA_BITS_8; + @Override + public void startReadListener() { + mStopReadListener = false; } - } + @Override + public void stopReadListener() { + mStopReadListener = true; + } - private byte convertFtdiStopBits(int stopBits) { - switch (stopBits) { - case UartConfig.STOP_BITS1: - return D2xxManager.FT_STOP_BITS_1; - case UartConfig.STOP_BITS2: - return D2xxManager.FT_STOP_BITS_2; - default: - return D2xxManager.FT_STOP_BITS_1; + private void onRead(int size) { + if(mStopReadListener) { + return; + } + for(ReadListener listener : uartReadListenerList) { + listener.onRead(size); + } } - } + ////////////////////////////////////////////////////////// + private String toHexStr(byte[] b, int length) { + String str = ""; + for(int i = 0; i < length; i++) { + str += String.format("%02x ", b[i]); + } + return str; + } - private byte convertFtdiParity(int parity) { - switch (parity) { - case UartConfig.PARITY_NONE: - return D2xxManager.FT_PARITY_NONE; - case UartConfig.PARITY_ODD: - return D2xxManager.FT_PARITY_ODD; - case UartConfig.PARITY_EVEN: - return D2xxManager.FT_PARITY_EVEN; - case UartConfig.PARITY_MARK: - return D2xxManager.FT_PARITY_MARK; - case UartConfig.PARITY_SPACE: - return D2xxManager.FT_PARITY_SPACE; - default: - return D2xxManager.FT_PARITY_NONE; + @Override + public String getPhysicalConnectionName() { + return Physicaloid.USB_STRING; } - } - private String toHexStr(byte[] b, int length) { - String str=""; - for(int i=0; i size) { + write_size = size - offset; + } + System.arraycopy(buf, offset, wbuf, 0, write_size); + + written_size = mConnection.bulkTransfer(mEndpointOut, wbuf, write_size, 100); + + if(written_size < 0) { + return -1; + } + offset += written_size; + } + + return offset; + } + + private void stopRead() { + mReadThreadStop = true; + } + + private void startRead() { + if(mReadThreadStop) { + mReadThreadStop = false; + new Thread(mLoop).start(); + } + } + private Runnable mLoop = new Runnable() { + + @Override + public void run() { + int len; + byte[] rbuf = new byte[mEndpointIn.getMaxPacketSize()]; + android.os.Process.setThreadPriority(-20); + UsbRequest response; + UsbRequest request = new UsbRequest(); + request.initialize(mConnection, mEndpointIn); + ByteBuffer buf = ByteBuffer.wrap(rbuf); + for(;;) {// this is the main loop for transferring + len = 0; + if(request.queue(buf, rbuf.length)) { + response = mConnection.requestWait(); + if(response != null) { + len = buf.position(); + } + if(len > 0) { + mBuffer.add(rbuf, len); + onRead(len); + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } else if(mBuffer.getBufferdLength() > 0) { + onRead(mBuffer.getBufferdLength()); + } + + + } + + if(mReadThreadStop) { + return; + } + + } + } // end of run() + }; // end of runnable + + @Override + public boolean setUartConfig(UartConfig config) { + boolean res; + boolean ret = true; + res = setBaudrate(config.baudrate); + ret = ret && res; + + res = setDataBits(config.dataBits); + ret = ret && res; + + res = setParity(config.parity); + ret = ret && res; + + res = setStopBits(config.stopBits); + ret = ret && res; + + res = setDtrRts(config.dtrOn, config.rtsOn); + ret = ret && res; + + return ret; + } + + /** + * Initializes UART communication + * + * @return true : successful, false : fail + */ + private boolean init() { + + int size = 8; + if(DEBUG_SHOW) { + Log.d(TAG, "init"); + } + byte[] buffer = new byte[size]; + + if(mConnection == null) { + if(DEBUG_SHOW) { + Log.d(TAG, "init mConnection == null"); + } + return false; + } + + /* expect two bytes */ + int r = ch341_control_in(CH341_REQ_READ_VERSION, 0, 0, buffer, size); + if(r != 2) { + if(DEBUG_SHOW) { + Log.d(TAG, "init r !=2 for 0x5f"); + } + return false; + } + + if(DEBUG_SHOW) { + Log.d(TAG, "Chip version " + buffer[0]); + } + + r = ch341_control_out(CH341_REQ_SERIAL_INIT, 0, 0); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "init fail on chip init"); + } + return false; + } + + r = ch341_get_status(); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "init status failed"); + } + return false; + } + + + if(!setBaudrate(mUartConfig.baudrate)) { + return false; + } + + if(!setDtrRts(mUartConfig.dtrOn, mUartConfig.rtsOn)) { + return false; + } + + /* expect 0x9f 0xee, not checked */ + r = ch341_get_status(); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "init final status failed"); + } + return false; + } + + return true; + } + + @Override + public boolean isOpened() { + return isOpened; + } + + private int ch341_control_out(int request, int value, int index) { + if(mConnection == null) { + return -1; + } + int ret = mConnection.controlTransfer(REQTYPE_HOST_TO_INTERFACE, request, value, index, null, 0, 100); + return ret; + } + /* + * int requestType, + * int request, + * int value, + * int index, + * byte[] buffer, + * int length, + * int timeout + */ + + private int ch341_control_in(int request, int value, int index, byte buf[], int bufsize) { + if(mConnection == null) { + return -1; + } + int ret = mConnection.controlTransfer(REQTYPE_INTERFACE_TO_HOST, request, value, index, buf, bufsize, 100); + return ret; + + } + + private int ch341_get_status() { + int size = 8; + long flags; + byte[] buffer = new byte[size]; + int r = ch341_control_in(0x95, 0x0706, 0, buffer, size); + if(r < 0) { + return r; + } + if(r == 2) { + r = 0; + line_status = (~buffer[0]) & CH341_BITS_MODEM_STAT; + } else { + r = -1; + } + return r; + } + + @Override + public boolean setBaudrate(int baudrate) { + + if(mConnection == null) { + return false; + } + long factor = CH341_BAUDBASE_FACTOR / baudrate; + short divisor = CH341_BAUDBASE_DIVMAX; + + while((factor > 0xfff0) && divisor != 0) { + factor >>= 3; + divisor--; + } + + if(factor > 0xfff0) { + return false; + } + factor = 0x10000 - factor; + int a = (int) (factor & 0xff00) | divisor | 0x80; // bit 7 needed for 341 + + int r = ch341_control_out(CH341_REQ_WRITE_REG, 0x1312, a); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setBaudrate"); + } + return false; + } + + r = ch341_control_out(CH341_REQ_WRITE_REG, 0x2518, lcr); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setBaudrate lcr"); + } + return false; + } + mUartConfig.baudrate = baudrate; + return true; + } + + @Override + public boolean setDataBits(int dataBits) { + int p; + switch(dataBits) { + case 5: + p = CH341_LCR_CS5; + break; + case 6: + p = CH341_LCR_CS6; + break; + case 7: + p = CH341_LCR_CS7; + break; + case 8: + p = CH341_LCR_CS8; + break; + default: + return false; + } + lcr &= ~(CH341_LCR_CS8); + lcr |= p; + int r = ch341_control_out(CH341_REQ_WRITE_REG, 0x2518, lcr); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to set data bits"); + } + return false; + } + mUartConfig.dataBits = dataBits; + return true; + } + + @Override + public boolean setParity(int parity) { + int p; + switch(parity) { + case UartConfig.PARITY_NONE: + p = 0x00; + break; + case UartConfig.PARITY_ODD: + p = CH341_LCR_ENABLE_PAR; + break; + case UartConfig.PARITY_EVEN: + p = CH341_LCR_ENABLE_PAR | CH341_LCR_PAR_EVEN; + break; + case UartConfig.PARITY_MARK: + p = CH341_LCR_ENABLE_PAR | CH341_LCR_MARK_SPACE; + break; + case UartConfig.PARITY_SPACE: + p = CH341_LCR_ENABLE_PAR | CH341_LCR_PAR_EVEN | CH341_LCR_MARK_SPACE; + break; + default: + return false; + } + lcr &= CH341_LCR_PAR_MASK; + lcr |= p; + int r = ch341_control_out(CH341_REQ_WRITE_REG, 0x2518, lcr); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to set parity"); + } + return false; + } + mUartConfig.parity = parity; + return true; + } + + @Override + public boolean setStopBits(int stopBits) { + if(stopBits < 1 || stopBits > 2) { + return false; + } + if(stopBits == 1) { + lcr &= ~CH341_LCR_STOP_BITS_2; + } else { + lcr |= CH341_LCR_STOP_BITS_2; + } + + int r = ch341_control_out(CH341_REQ_WRITE_REG, 0x2518, lcr); + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to set stop bits"); + } + return false; + } + + mUartConfig.stopBits = stopBits; + return true; + } + + @Override + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { + int ctrlValue = 0x0000; + + if(dtrOn) { + ctrlValue |= CH341_BIT_DTR; + } + + if(rtsOn) { + ctrlValue |= CH341_BIT_RTS; + } + + int r = ch341_control_out(0xa4, ~ctrlValue, 0); + + if(r < 0) { + if(DEBUG_SHOW) { + Log.d(TAG, "Fail to setDtrRts"); + } + return false; + } + mUartConfig.dtrOn = dtrOn; + mUartConfig.rtsOn = rtsOn; + return true; + } + + @Override + public UartConfig getUartConfig() { + return mUartConfig; + } + + @Override + public int getBaudrate() { + return mUartConfig.baudrate; + } + + @Override + public int getDataBits() { + return mUartConfig.dataBits; + } + + @Override + public int getParity() { + return mUartConfig.parity; + } + + @Override + public int getStopBits() { + return mUartConfig.stopBits; + } + + @Override + public boolean getDtr() { + return mUartConfig.dtrOn; + } + + @Override + public boolean getRts() { + return mUartConfig.rtsOn; + } + + @Override + public void clearBuffer() { + mBuffer.clear(); + } + ////////////////////////////////////////////////////////// + // Listener for reading uart + ////////////////////////////////////////////////////////// + private List uartReadListenerList = new ArrayList(); + private boolean mStopReadListener = false; + + @Override + public void addReadListener(ReadListener listener) { + uartReadListenerList.add(listener); + } + + @Override + @Deprecated + public void addReadListener(ReadLisener listener) { + addReadListener((ReadListener) listener); + } + + @Override + public void clearReadListener() { + uartReadListenerList.clear(); + } + + @Override + public void startReadListener() { + mStopReadListener = false; + } + + @Override + public void stopReadListener() { + mStopReadListener = true; + } + + private void onRead(int size) { + if(mStopReadListener) { + return; + } + for(ReadListener listener : uartReadListenerList) { + listener.onRead(size); + } + } + ////////////////////////////////////////////////////////// + + @Override + public String getPhysicalConnectionName() { + return Physicaloid.USB_STRING; + } + + @Override + public int getPhysicalConnectionType() { + return Physicaloid.USB; + } + + @Override + public void setDebug(boolean flag) { + DEBUG_SHOW = flag; + } +} diff --git a/PhysicaloidLibrary/src/com/physicaloid/lib/wifi/driver/uart/UartWifi.java b/PhysicaloidLibrary/src/com/physicaloid/lib/wifi/driver/uart/UartWifi.java new file mode 100644 index 0000000..b0a01ce --- /dev/null +++ b/PhysicaloidLibrary/src/com/physicaloid/lib/wifi/driver/uart/UartWifi.java @@ -0,0 +1,548 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.physicaloid.lib.wifi.driver.uart; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.util.Log; +import com.physicaloid.BuildConfig; +import com.physicaloid.lib.Physicaloid; +import com.physicaloid.lib.framework.SerialCommunicator; +import com.physicaloid.lib.usb.driver.uart.ReadLisener; +import com.physicaloid.lib.usb.driver.uart.ReadListener; +import com.physicaloid.lib.usb.driver.uart.UartConfig; +import com.physicaloid.misc.RingBuffer; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author xxxajk@gmail.com + */ +public class UartWifi extends SerialCommunicator { + + private static final String TAG = UartWifi.class.getSimpleName(); + private boolean DEBUG_SHOW = false; + private static final int DEFAULT_BAUDRATE = 9600; + private UartConfig mUartConfig; + private static final int RING_BUFFER_SIZE = 1024; + private static final int READ_BUFFER_SIZE = 256; + private static final int WRITE_BUFFER_SIZE = 256; + private RingBuffer mBuffer; + private boolean mReadThreadStop = true; + private boolean isOpened; + private String SERVER_IP = null; + private int DATA_PORT = 0; + private int CTRL_PORT = 0; + private Socket DATA_socket; + private Socket CTRL_socket; + private DataOutputStream CTRL_OUT; + private DataOutputStream DATA_OUT; + private DataInputStream DATA_IN; + volatile boolean CTRL_keep_going = false; + volatile boolean CTRL_still_going = false; + volatile boolean DATA_keep_going = false; + volatile boolean DATA_still_going = false; + volatile Context me; + + private boolean isNetworkConnected(Context context) { + //Log.d(TAG, "Network available?"); + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo netInfo = cm.getActiveNetworkInfo(); + if(netInfo == null) { + return false; + } + return (netInfo.isConnected() && netInfo.getType() == ConnectivityManager.TYPE_WIFI); + //return cm.getActiveNetworkInfo() != null; + } + + public UartWifi(Context context, String host, int Dport, int Cport) { + super(context); + SERVER_IP = host; + DATA_PORT = Dport; + CTRL_PORT = Cport; + mUartConfig = new UartConfig(); + mBuffer = new RingBuffer(RING_BUFFER_SIZE); + isOpened = false; + CTRL_socket = null; + DATA_socket = null; + CTRL_OUT = null; + DATA_OUT = null; + DATA_IN = null; + me = context; + } + + @Override + public boolean open() { + if(!isOpened) { + if(!init()) { + close(); + return false; + } + if(!setBaudrate(DEFAULT_BAUDRATE)) { + close(); + return false; + } + mBuffer.clear(); + startRead(); + isOpened = true; + } + return true; + } + private Runnable connect_CTRL = new Runnable() { + + InetAddress serverAddr; + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public void run() { + Log.d(TAG, "Network? " + isNetworkConnected(me)); + while(CTRL_keep_going && isNetworkConnected(me)) { + try { + serverAddr = InetAddress.getByName(SERVER_IP); + CTRL_socket = new Socket(serverAddr, CTRL_PORT); + CTRL_socket.setKeepAlive(true); + CTRL_socket.setTcpNoDelay(true); + CTRL_still_going = false; + CTRL_keep_going = false; + return; + } catch(Exception ex) { + //Log.d(TAG, ex.toString()); + //ex.printStackTrace(); + } + } + CTRL_still_going = false; + } + }; + private Runnable connect_DATA = new Runnable() { + + InetAddress serverAddr; + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public void run() { + while(DATA_keep_going && isNetworkConnected(me)) { + try { + serverAddr = InetAddress.getByName(SERVER_IP); + DATA_socket = new Socket(serverAddr, DATA_PORT); + DATA_socket.setKeepAlive(true); + DATA_socket.setTcpNoDelay(true); + DATA_keep_going = false; + DATA_still_going = false; + return; + } catch(Exception ex) { + //Log.d(TAG, ex.toString()); + //ex.printStackTrace(); + } + } + DATA_still_going = false; + } + }; + + @SuppressWarnings({"SleepWhileInLoop", "CallToThreadDumpStack"}) + private boolean init() { + + CTRL_keep_going = true; + CTRL_still_going = true; + DATA_keep_going = true; + DATA_still_going = true; + Log.d(TAG, "********************* WiFi Connecting CTRL **************"); + new Thread(connect_CTRL).start(); + Log.d(TAG, "********************* WiFi Connecting DATA **************"); + new Thread(connect_DATA).start(); + Log.d(TAG, "********************* WiFi WAITING **************"); + + // timeout after how many seconds? How about 30? + int timeout = (30 * 1000) / 50; + while(CTRL_still_going && DATA_still_going && (timeout > 0) && isNetworkConnected(me)) { + try { + // STALL APP :-) + Thread.sleep(50); + timeout--; + } catch(InterruptedException ex) { + } + } + if(timeout <= 0) { + // did not connect, kill threads. + DATA_keep_going = false; + CTRL_keep_going = false; + while(DATA_still_going && CTRL_still_going) { + try { + Thread.sleep(50); + } catch(InterruptedException ex) { + } + } + Log.d(TAG, "********************* WiFi Timed out! **************"); + return false; + } + try { + CTRL_OUT = new DataOutputStream(CTRL_socket.getOutputStream()); + DATA_OUT = new DataOutputStream(DATA_socket.getOutputStream()); + DATA_IN = new DataInputStream(DATA_socket.getInputStream()); + } catch(Exception ex) { + Log.d(TAG, "********************* WiFi DIED! **************"); + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + return false; + } + Log.d(TAG, "********************* WiFi Connected! **************"); + return true; + } + + @Override + @SuppressWarnings({"CallToThreadDumpStack", "SleepWhileInLoop"}) + public boolean close() { + stopRead(); + isOpened = false; + CTRL_keep_going = false; + DATA_keep_going = false; + while(DATA_still_going || CTRL_still_going) { + try { + Thread.sleep(50); + } catch(InterruptedException ex) { + } + } + if(CTRL_OUT != null) { + try { + CTRL_OUT.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + CTRL_OUT = null; + + } + if(DATA_OUT != null) { + try { + DATA_OUT.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + DATA_OUT = null; + } + if(DATA_IN != null) { + try { + DATA_IN.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + DATA_IN = null; + } + if(CTRL_socket != null) { + try { + CTRL_socket.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + CTRL_socket = null; + } + if(DATA_socket != null) { + try { + DATA_socket.close(); + } catch(Exception ex) { + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + } + DATA_socket = null; + } + return true; + } + + @Override + public int read(byte[] buf, int size) { + return mBuffer.get(buf, size); + } + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public int write(byte[] buf, int size) { + if(buf == null) { + return 0; + } + try { + DATA_OUT.write(buf, 0, size); + DATA_OUT.flush(); + } catch(Exception ex) { + close(); + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + return -1; + } + return size; + } + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public boolean setBaudrate(int baudrate) { + byte b[] = {0x40, (byte) (baudrate & 0xff), (byte) ((baudrate >> 8) & 0xff), (byte) ((baudrate >> 16) & 0xff), (byte) ((baudrate >> 24) & 0xff)}; + try { + CTRL_OUT.write(b, 0, 5); + CTRL_OUT.flush(); + } catch(Exception ex) { + close(); + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + return false; + } + mUartConfig.baudrate = baudrate; + return true; + } + + @Override + public boolean setDataBits(int dataBits) { + // We don't do this... + mUartConfig.dataBits = dataBits; + return true; + } + + @Override + public boolean setParity(int parity) { + // We don't do this... + mUartConfig.parity = parity; + return true; + } + + @Override + public boolean setStopBits(int stopBits) { + // We don't do this... + mUartConfig.stopBits = stopBits; + return true; + } + + @Override + @SuppressWarnings("CallToThreadDumpStack") + public boolean setDtrRts(boolean dtrOn, boolean rtsOn) { + try { + // TO-DO: rts... This is good enough for now, though. + if(dtrOn) { + byte b[] = {1}; + CTRL_OUT.write(b, 0, 1); + } else { + byte b[] = {0}; + CTRL_OUT.write(b, 0, 1); + } + CTRL_OUT.flush(); + } catch(Exception ex) { + close(); + Log.d(TAG, ex.toString()); + ex.printStackTrace(); + return false; + } + mUartConfig.dtrOn = dtrOn; + mUartConfig.rtsOn = rtsOn; + return true; + } + + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////// + /** + * Sets Uart configurations + * + * @param config configurations + * @return true : successful, false : fail + */ + public boolean setUartConfig(UartConfig config) { + boolean res; + boolean ret = true; + if(mUartConfig.baudrate != config.baudrate) { + res = setBaudrate(config.baudrate); + ret = ret && res; + } + + if(mUartConfig.dataBits != config.dataBits) { + res = setDataBits(config.dataBits); + ret = ret && res; + } + + if(mUartConfig.parity != config.parity) { + res = setParity(config.parity); + ret = ret && res; + } + + if(mUartConfig.stopBits != config.stopBits) { + res = setStopBits(config.stopBits); + ret = ret && res; + } + + if(mUartConfig.dtrOn != config.dtrOn + || mUartConfig.rtsOn != config.rtsOn) { + res = setDtrRts(config.dtrOn, config.rtsOn); + ret = ret && res; + } + + return ret; + } + + @Override + public boolean isOpened() { + return isOpened; + } + + @Override + public UartConfig getUartConfig() { + return mUartConfig; + } + + @Override + public int getBaudrate() { + return mUartConfig.baudrate; + } + + @Override + public int getDataBits() { + return mUartConfig.dataBits; + } + + @Override + public int getParity() { + return mUartConfig.parity; + } + + @Override + public int getStopBits() { + return mUartConfig.stopBits; + } + + @Override + public boolean getDtr() { + return mUartConfig.dtrOn; + } + + @Override + public boolean getRts() { + return mUartConfig.rtsOn; + } + + @Override + public void clearBuffer() { + mBuffer.clear(); + } + ////////////////////////////////////////////////////////// + // Listener for reading uart + ////////////////////////////////////////////////////////// + private List uartReadListenerList = new ArrayList(); + private boolean mStopReadListener = false; + + @Override + public void addReadListener(ReadListener listener) { + uartReadListenerList.add(listener); + } + + @Override + @Deprecated + public void addReadListener(ReadLisener listener) { + addReadListener((ReadListener)listener); + } + + + @Override + public void clearReadListener() { + uartReadListenerList.clear(); + } + + @Override + public void startReadListener() { + mStopReadListener = false; + } + + @Override + public void stopReadListener() { + mStopReadListener = true; + } + + private void onRead(int size) { + if(mStopReadListener) { + return; + } + for(ReadListener listener : uartReadListenerList) { + listener.onRead(size); + } + } + ////////////////////////////////////////////////////////// + + private void stopRead() { + mReadThreadStop = true; + } + + private void startRead() { + if(mReadThreadStop) { + mReadThreadStop = false; + new Thread(mLoop).start(); + } + } + private Runnable mLoop = new Runnable() { + + @Override + @SuppressWarnings("SleepWhileInLoop") + public void run() { + int len; + byte[] rbuf = new byte[READ_BUFFER_SIZE]; + android.os.Process.setThreadPriority(-20); + for(;;) { + if(mReadThreadStop) { + return; + } + if(CTRL_socket.isClosed() || DATA_socket.isClosed()) { + close(); + try { + Thread.sleep(50); + } catch(InterruptedException ex) { + } + } else { + try { + // this is the main loop for transferring + len = 0; + + while(DATA_IN.available() > 0 && len < READ_BUFFER_SIZE) { + DATA_IN.read(rbuf, len, 1); + len++; + } + if(len > 0) { + mBuffer.add(rbuf, len); + onRead(len); + } + + } catch(IOException ex) { + close(); + // TO-DO: Needs to broadcast that it has died + try { + Thread.sleep(50); + } catch(InterruptedException exx) { + } + return; + } + } + } + } // end of run() + }; // end of runnable + + @Override + public String getPhysicalConnectionName() { + return Physicaloid.WIFI_STRING; + } + + @Override + public int getPhysicalConnectionType() { + return Physicaloid.WIFI; + } + + @Override + public void setDebug(boolean flag) { + DEBUG_SHOW = flag; + } +} diff --git a/PhysicaloidLibrary/src/com/physicaloid/misc/RingBuffer.java b/PhysicaloidLibrary/src/com/physicaloid/misc/RingBuffer.java index 68b838a..8f31eb3 100644 --- a/PhysicaloidLibrary/src/com/physicaloid/misc/RingBuffer.java +++ b/PhysicaloidLibrary/src/com/physicaloid/misc/RingBuffer.java @@ -13,174 +13,272 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.physicaloid.misc; import android.util.Log; - import com.physicaloid.BuildConfig; -public class RingBuffer{ - private static final String TAG = RingBuffer.class.getSimpleName(); - - private static final boolean DEBUG_SHOW_ADD = false && BuildConfig.DEBUG; - private static final boolean DEBUG_SHOW_GET = false && BuildConfig.DEBUG; - - private int mRingBufSize; - private byte[] mRingBuf; - private int mAddIndex; // top of data index - private int mGetIndex; // tail of data index - - /** - * Ring buffer - * @param bufferSize buffer size. It needs enough size e.g.1024 - */ - public RingBuffer(int bufferSize) { - mRingBufSize = bufferSize+1; - mRingBuf = new byte[mRingBufSize]; - mAddIndex = 0; - mGetIndex = 0; - } - - /** - * Gets ring buffer size - * @return ring buffer size - */ - public int getRingBufferSize() { - return mRingBufSize-1; - } - - /** - * Gets buffered length - * @return buffered length - */ - public int getBufferdLength() { - if(mAddIndex >= mGetIndex) { - return mAddIndex - mGetIndex; - } else { - return mAddIndex + (mRingBufSize - mGetIndex); - } - } - - /** - * Adds byte array to ring buffer - * @param buf byte array - * @param length added length - * @return actually added length - */ - public synchronized int add(byte[] buf, int length) { - int addLen = length; - - if(mAddIndex > mGetIndex) { - if((mAddIndex + length) >= mRingBufSize) { // addした結果1周をまたぐ場合 - if((mRingBufSize - mAddIndex) + (mGetIndex - 1) < length ) { // 1周をまたいでなおlength以上になる場合 - addLen = (mRingBufSize - mAddIndex) + (mGetIndex-1); // 追い抜かないサイズに修正 - } - } - } else if(mAddIndex < mGetIndex){ // 1周をまたいでいる場合 - if((mGetIndex - 1) - mAddIndex < length) { - addLen = (mGetIndex - 1) - mAddIndex; - } +public class RingBuffer { + + private static final String TAG = RingBuffer.class.getSimpleName(); + private static final boolean DEBUG_SHOW_ADD = false && BuildConfig.DEBUG; + private static final boolean DEBUG_SHOW_GET = false && BuildConfig.DEBUG; + private int mRingBufSize; + private byte[] mRingBuf; + private int mAddIndex; // top of data index + private int mGetIndex; // tail of data index + + /** + * Ring buffer + * + * @param bufferSize buffer size. It needs enough size e.g.1024 + */ + public RingBuffer(int bufferSize) { + mRingBufSize = bufferSize + 1; + mRingBuf = new byte[mRingBufSize]; + mAddIndex = 0; + mGetIndex = 0; } - if(buf.length < addLen) { - addLen = buf.length; + /** + * Gets ring buffer size + * + * @return ring buffer size + */ + public int getRingBufferSize() { + return mRingBufSize - 1; } - if((mAddIndex+addLen) >= mRingBufSize) { // storeがバッファ終端をまたぐ場合 - int remain = mAddIndex + addLen - mRingBufSize; - int copyLen = addLen-remain; - if(copyLen != 0) { - System.arraycopy(buf, 0, mRingBuf, mAddIndex, copyLen); - if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : copy buf[0:"+(copyLen-1)+"] to mRingBuf["+mAddIndex+":"+(mAddIndex+copyLen-1)+"]"); } - } - - mAddIndex = 0; - - if(remain != 0) { - System.arraycopy(buf, copyLen, mRingBuf, mAddIndex, remain); - if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : copy buf["+(copyLen)+":"+(addLen-1)+"] to mRingBuf[0:"+(remain-1)+"]"); } - mAddIndex = remain; - } - - if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex); } - - return addLen; - } else { - System.arraycopy(buf, 0, mRingBuf, mAddIndex, addLen); - - if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : copy buf[0:"+(addLen-1)+"] to mRingBuf["+mAddIndex+":"+(mAddIndex+addLen-1)+"]"); } - - mAddIndex += addLen; - - if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex);} - - return addLen; - } - } - - /** - * Gets ring buffer to byte array - * @param buf byte array - * @param length gotten length - * @return actually gotten length - */ - public synchronized int get(byte[] buf, int length) { - int getLen = length; - if(mAddIndex == mGetIndex) { - return 0; - } else if(mGetIndex < mAddIndex) { // 通常 - if(mAddIndex - mGetIndex < length) { // get要求サイズがバッファされているサイズより大きい場合 - getLen = mAddIndex - mGetIndex; // 今バッファされているサイズを返す - } - } else {// インデックスが1周をまたいでいる場合 - if(mAddIndex + (mRingBufSize-mGetIndex) < length) { // get要求サイズがバッファされているサイズより大きい場合 - getLen = mAddIndex + (mRingBufSize - mGetIndex); // 今バッファされているサイズを返す - } - } - - if(buf.length < getLen) { - getLen = buf.length; + /** + * Gets buffered length + * + * @return buffered length + */ + public int getBufferdLength() { + if(mAddIndex >= mGetIndex) { + return mAddIndex - mGetIndex; + } else { + return mAddIndex + (mRingBufSize - mGetIndex); + } } - if((mGetIndex+getLen) >= mRingBufSize) { - int remain = mGetIndex + getLen - mRingBufSize; - int copyLen = getLen - remain; - if( copyLen != 0) { - System.arraycopy(mRingBuf, mGetIndex, buf, 0, copyLen); - if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : copy mRingBuf["+mGetIndex+":"+(mGetIndex+copyLen-1)+"] to buf[0:"+(copyLen-1)+"]"); } - } + /** + * Adds byte array to ring buffer + * + * @param buf byte array + * @param length added length + * + * @return actually added length + */ + public synchronized int add(byte[] buf, int length) { + int addLen = length; + if(buf == null) { + return 0; + } + if(mAddIndex > mGetIndex) { + if((mAddIndex + length) >= mRingBufSize) { // addした結果1周をまたぐ場合 + if((mRingBufSize - mAddIndex) + (mGetIndex - 1) < length) { // 1周をまたいでなおlength以上になる場合 + addLen = (mRingBufSize - mAddIndex) + (mGetIndex - 1); // 追い抜かないサイズに修正 + } + } + } else if(mAddIndex < mGetIndex) { // 1周をまたいでいる場合 + if((mGetIndex - 1) - mAddIndex < length) { + addLen = (mGetIndex - 1) - mAddIndex; + } + } - mGetIndex = 0; + if(buf.length < addLen) { + addLen = buf.length; + } - if(remain !=0) { - System.arraycopy(mRingBuf, mGetIndex, buf, copyLen, remain); - if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : copy mRingBuf[0:"+(remain-1)+"] to buf["+copyLen+":"+(remain-1)+"]"); } - mGetIndex = remain; - } + if((mAddIndex + addLen) >= mRingBufSize) { // storeがバッファ終端をまたぐ場合 + int remain = mAddIndex + addLen - mRingBufSize; + int copyLen = addLen - remain; + if(copyLen != 0) { + System.arraycopy(buf, 0, mRingBuf, mAddIndex, copyLen); + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : copy buf[0:" + (copyLen - 1) + "] to mRingBuf[" + mAddIndex + ":" + (mAddIndex + copyLen - 1) + "]"); + } + } + + mAddIndex = 0; + + if(remain != 0) { + System.arraycopy(buf, copyLen, mRingBuf, mAddIndex, remain); + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : copy buf[" + (copyLen) + ":" + (addLen - 1) + "] to mRingBuf[0:" + (remain - 1) + "]"); + } + mAddIndex = remain; + } + + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : addOffset = " + mAddIndex + ", getOffset = " + mGetIndex); + } + + return addLen; + } else { + System.arraycopy(buf, 0, mRingBuf, mAddIndex, addLen); + + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : copy buf[0:" + (addLen - 1) + "] to mRingBuf[" + mAddIndex + ":" + (mAddIndex + addLen - 1) + "]"); + } + + mAddIndex += addLen; + + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : addOffset = " + mAddIndex + ", getOffset = " + mGetIndex); + } + + return addLen; + } + } + /** + * Adds byte array to ring buffer with starting offset + * + * @param buf byte array + * @param length added length + * @param off offset to start from + * + * @return actually added length + */ + public synchronized int add(byte[] buf, int length, int off) { + int addLen = length; + if(buf == null) { + return 0; + } + if(mAddIndex > mGetIndex) { + if((mAddIndex + length) >= mRingBufSize) { // addした結果1周をまたぐ場合 + if((mRingBufSize - mAddIndex) + (mGetIndex - 1) < length) { // 1周をまたいでなおlength以上になる場合 + addLen = (mRingBufSize - mAddIndex) + (mGetIndex - 1); // 追い抜かないサイズに修正 + } + } + } else if(mAddIndex < mGetIndex) { // 1周をまたいでいる場合 + if((mGetIndex - 1) - mAddIndex < length) { + addLen = (mGetIndex - 1) - mAddIndex; + } + } - if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex); } - return getLen; - } else { - System.arraycopy(mRingBuf, mGetIndex, buf, 0, getLen); + if(buf.length < addLen) { + addLen = buf.length; + } - if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : copy mRingBuf["+mGetIndex+":"+(mGetIndex+getLen-1)+"] to buf[0:"+(getLen-1)+"]");} + if((mAddIndex + addLen) >= mRingBufSize) { // storeがバッファ終端をまたぐ場合 + int remain = mAddIndex + addLen - mRingBufSize; + int copyLen = addLen - remain; + if(copyLen != 0) { + System.arraycopy(buf, off, mRingBuf, mAddIndex, copyLen); + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : copy buf[0:" + (copyLen - 1) + "] to mRingBuf[" + mAddIndex + ":" + (mAddIndex + copyLen - 1) + "]"); + } + } + + mAddIndex = 0; + + if(remain != 0) { + System.arraycopy(buf, copyLen+off, mRingBuf, mAddIndex, remain); + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : copy buf[" + (copyLen) + ":" + (addLen - 1) + "] to mRingBuf[0:" + (remain - 1) + "]"); + } + mAddIndex = remain; + } + + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : addOffset = " + mAddIndex + ", getOffset = " + mGetIndex); + } + + return addLen; + } else { + System.arraycopy(buf, 0, mRingBuf, mAddIndex, addLen); + + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : copy buf[0:" + (addLen - 1) + "] to mRingBuf[" + mAddIndex + ":" + (mAddIndex + addLen - 1) + "]"); + } + + mAddIndex += addLen; + + if(DEBUG_SHOW_ADD) { + Log.d(TAG, "add(" + length + ") : addOffset = " + mAddIndex + ", getOffset = " + mGetIndex); + } + + return addLen; + } + } - mGetIndex += getLen; + /** + * Gets ring buffer to byte array + * + * @param buf byte array + * @param length gotten length + * + * @return actually gotten length + */ + public synchronized int get(byte[] buf, int length) { + if(buf == null) { + return 0; + } + int getLen = length; + if(mAddIndex == mGetIndex) { + return 0; + } else if(mGetIndex < mAddIndex) { // 通常 + if(mAddIndex - mGetIndex < length) { // get要求サイズがバッファされているサイズより大きい場合 + getLen = mAddIndex - mGetIndex; // 今バッファされているサイズを返す + } + } else {// インデックスが1周をまたいでいる場合 + if(mAddIndex + (mRingBufSize - mGetIndex) < length) { // get要求サイズがバッファされているサイズより大きい場合 + getLen = mAddIndex + (mRingBufSize - mGetIndex); // 今バッファされているサイズを返す + } + } - if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex); } + if(buf.length < getLen) { + getLen = buf.length; + } - return getLen; + if((mGetIndex + getLen) >= mRingBufSize) { + int remain = mGetIndex + getLen - mRingBufSize; + int copyLen = getLen - remain; + if(copyLen != 0) { + System.arraycopy(mRingBuf, mGetIndex, buf, 0, copyLen); + if(DEBUG_SHOW_GET) { + Log.d(TAG, "get(" + length + ") : copy mRingBuf[" + mGetIndex + ":" + (mGetIndex + copyLen - 1) + "] to buf[0:" + (copyLen - 1) + "]"); + } + } + + mGetIndex = 0; + + if(remain != 0) { + System.arraycopy(mRingBuf, mGetIndex, buf, copyLen, remain); + if(DEBUG_SHOW_GET) { + Log.d(TAG, "get(" + length + ") : copy mRingBuf[0:" + (remain - 1) + "] to buf[" + copyLen + ":" + (remain - 1) + "]"); + } + mGetIndex = remain; + } + + if(DEBUG_SHOW_GET) { + Log.d(TAG, "get(" + length + ") : addOffset = " + mAddIndex + ", getOffset = " + mGetIndex); + } + return getLen; + } else { + System.arraycopy(mRingBuf, mGetIndex, buf, 0, getLen); + + if(DEBUG_SHOW_GET) { + Log.d(TAG, "get(" + length + ") : copy mRingBuf[" + mGetIndex + ":" + (mGetIndex + getLen - 1) + "] to buf[0:" + (getLen - 1) + "]"); + } + + mGetIndex += getLen; + + if(DEBUG_SHOW_GET) { + Log.d(TAG, "get(" + length + ") : addOffset = " + mAddIndex + ", getOffset = " + mGetIndex); + } + + return getLen; + } } - } - - - /** - * Clear ring buffer - */ - public synchronized void clear() { - mAddIndex = 0; - mGetIndex = 0; - } + /** + * Clear ring buffer + */ + public synchronized void clear() { + mAddIndex = 0; + mGetIndex = 0; + } } diff --git a/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParser.java b/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParser.java index 6341bbb..2523b8c 100644 --- a/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParser.java +++ b/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParser.java @@ -1,175 +1,177 @@ /** - * @license - * Copyright (c) 2012, Jan Breuer - * All rights reserved. - * + * @license Copyright (c) 2012, Jan Breuer All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package cz.jaybee.intelhex; -import java.io.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; /** * - * @author Jan Breuer - * @license BSD 2-Clause + * @author Jan Breuer @license BSD 2-Clause */ public class IntelHexParser { - private BufferedReader reader = null; - private IntelHexDataListener dataListener = null; - private static final int HEX = 16; - private boolean eof = false; - private int recordIdx = 0; - private long upperAddress = 0; - - private class Record { - - int length; - int address; - IntelHexRecordType type; - byte[] data; - } - - public IntelHexParser(Reader reader) { - if (reader instanceof BufferedReader) { - this.reader = (BufferedReader) reader; - } else { - this.reader = new BufferedReader(reader); - } - } - - public IntelHexParser(InputStream stream) { - this.reader = new BufferedReader(new InputStreamReader(stream)); - } - - public void setDataListener(IntelHexDataListener listener) { - this.dataListener = listener; - } - - private Record parseRecord(String record) throws Exception { - Record result = new Record(); - // check, if there wasn an accidential EOF record - if (eof) { - throw new Exception("Data after eof (" + recordIdx + ")"); - } - - // every IntelHEX record must start with ":" - if (!record.startsWith(":")) { - throw new Exception("Invalid Intel HEX record (" + recordIdx + ")"); - } + private BufferedReader reader = null; + private IntelHexDataListener dataListener = null; + private static final int HEX = 16; + private boolean eof = false; + private int recordIdx = 0; + private long upperAddress = 0; - int lineLength = record.length(); - byte[] hexRecord = new byte[lineLength / 2]; + private class Record { - // sum of all bytes modulo 256 (including checksum) shuld be 0 - int sum = 0; - for (int i = 0; i < hexRecord.length; i++) { - String num = record.substring(2 * i + 1, 2 * i + 3); - hexRecord[i] = (byte) Integer.parseInt(num, HEX); - sum += hexRecord[i] & 0xff; + int length; + int address; + IntelHexRecordType type; + byte[] data; } - sum &= 0xff; - if (sum != 0) { - throw new Exception("Invalid checksum (" + recordIdx + ")"); + public IntelHexParser(Reader reader) { + if(reader instanceof BufferedReader) { + this.reader = (BufferedReader) reader; + } else { + this.reader = new BufferedReader(reader); + } } - // if the length field does not correspond with line length - result.length = hexRecord[0]; - if ((result.length + 5) != hexRecord.length) { - throw new Exception("Invalid record length (" + recordIdx + ")"); + public IntelHexParser(InputStream stream) { + this.reader = new BufferedReader(new InputStreamReader(stream)); } - // length is OK, copy data - result.data = new byte[result.length]; - System.arraycopy(hexRecord, 4, result.data, 0, result.length); - - // build lower part of data address - result.address = ((hexRecord[1] & 0xFF) << 8) + (hexRecord[2] & 0xFF); - // determine record type - result.type = IntelHexRecordType.fromInt(hexRecord[3] & 0xFF); - if (result.type == IntelHexRecordType.UNKNOWN) { - throw new Exception("Unsupported record type " + (hexRecord[3] & 0xFF) + " (" + recordIdx + ")"); + public void setDataListener(IntelHexDataListener listener) { + this.dataListener = listener; } - return result; - } + private Record parseRecord(String record) throws Exception { + Record result = new Record(); + // Check if there was an EOF record. If so, ignore the remainder of the file as per spec. + if(eof) { + // throw new Exception("Data after eof (" + recordIdx + ")"); + result.type = IntelHexRecordType.EOF; - private void processRecord(Record record) throws Exception { - // build full address - long addr = record.address | upperAddress; - switch (record.type) { - case DATA: - if (dataListener != null) { - dataListener.data(addr, record.data); - } - break; - case EOF: - if (dataListener != null) { - dataListener.eof(); - } - eof = true; - break; - case EXT_LIN: - if (record.length == 2) { - upperAddress = ((record.data[0] & 0xFF) << 8) + (record.data[1] & 0xFF); - upperAddress <<= 16; // ELA is bits 16-31 of the segment base address (SBA), so shift left 16 bits } else { - throw new Exception("Invalid EXT_LIN record (" + recordIdx + ")"); + // every IntelHEX record must start with ":" + if(!record.startsWith(":")) { + throw new Exception("Invalid Intel HEX record (" + recordIdx + ")"); + } + + int lineLength = record.length(); + byte[] hexRecord = new byte[lineLength / 2]; + + // sum of all bytes modulo 256 (including checksum) should be 0 + int sum = 0; + for(int i = 0; i < hexRecord.length; i++) { + String num = record.substring(2 * i + 1, 2 * i + 3); + hexRecord[i] = (byte) Integer.parseInt(num, HEX); + sum += hexRecord[i] & 0xff; + } + sum &= 0xff; + + if(sum != 0) { + throw new Exception("Invalid checksum (" + recordIdx + ")"); + } + + // if the length field does not correspond with line length + result.length = hexRecord[0]; + if((result.length + 5) != hexRecord.length) { + throw new Exception("Invalid record length (" + recordIdx + ")"); + } + // length is OK, copy data + result.data = new byte[result.length]; + System.arraycopy(hexRecord, 4, result.data, 0, result.length); + + // build lower part of data address + result.address = ((hexRecord[1] & 0xFF) << 8) + (hexRecord[2] & 0xFF); + + // determine record type + result.type = IntelHexRecordType.fromInt(hexRecord[3] & 0xFF); + if(result.type == IntelHexRecordType.UNKNOWN) { + throw new Exception("Unsupported record type " + (hexRecord[3] & 0xFF) + " (" + recordIdx + ")"); + } } + return result; + } - break; - case EXT_SEG: - if (record.length == 2) { - upperAddress = ((record.data[0] & 0xFF) << 8) + (record.data[1] & 0xFF); - upperAddress <<= 4; // ESA is bits 4-19 of the segment base address (SBA), so shift left 4 bits - } else { - throw new Exception("Invalid EXT_SEG record (" + recordIdx + ")"); + private void processRecord(Record record) throws Exception { + // build full address + long addr = record.address | upperAddress; + switch(record.type) { + case DATA: + if(dataListener != null) { + dataListener.data(addr, record.data); + } + break; + case EOF: + if(dataListener != null) { + dataListener.eof(); + } + eof = true; + break; + case EXT_LIN: + if(record.length == 2) { + upperAddress = ((record.data[0] & 0xFF) << 8) + (record.data[1] & 0xFF); + upperAddress <<= 16; // ELA is bits 16-31 of the segment base address (SBA), so shift left 16 bits + } else { + throw new Exception("Invalid EXT_LIN record (" + recordIdx + ")"); + } + + break; + case EXT_SEG: + if(record.length == 2) { + upperAddress = ((record.data[0] & 0xFF) << 8) + (record.data[1] & 0xFF); + upperAddress <<= 4; // ESA is bits 4-19 of the segment base address (SBA), so shift left 4 bits + } else { + throw new Exception("Invalid EXT_SEG record (" + recordIdx + ")"); + } + break; + case START_SEG: + throw new Exception(record.type + " record not implemented (" + recordIdx + ")"); + case START_LIN: + case UNKNOWN: + break; } - break; - case START_SEG: - case START_LIN: - throw new Exception(record.type + " record not implemented (" + recordIdx + ")"); - case UNKNOWN: - break; + } - } + public void parse() throws IOException, Exception { + recordIdx = 1; + upperAddress = 0; + String recordStr; - public void parse() throws IOException, Exception { - recordIdx = 1; - upperAddress = 0; - String recordStr; + while((recordStr = reader.readLine()) != null) { + Record record = parseRecord(recordStr); + processRecord(record); + recordIdx++; + } - while ((recordStr = reader.readLine()) != null) { - Record record = parseRecord(recordStr); - processRecord(record); - recordIdx++; - } - - if (!eof) { - throw new Exception("No eof at the end of file"); + if(!eof) { + throw new Exception("No eof at the end of file"); + } } - } } diff --git a/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParserRun.java b/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParserRun.java index 9ecb074..d793451 100644 --- a/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParserRun.java +++ b/PhysicaloidLibrary/src/cz/jaybee/intelhex/IntelHexParserRun.java @@ -2,27 +2,27 @@ * @license * Copyright (c) 2012, Jan Breuer * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this + * + * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - * + * * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package cz.jaybee.intelhex; @@ -32,7 +32,7 @@ /** * * @author Jan Breuer - * @license BSD 2-Clause + * @license BSD 2-Clause */ public class IntelHexParserRun implements IntelHexDataListener { @@ -72,12 +72,12 @@ public boolean isEOF() { @Override public void data(long address, byte[] data) { if ((address >= addressStart) && (address <= addressStop)) { - int length = data.length; - if ((address + length) > addressStop) { - length = (int) (addressStop - address + 1); + int dlength = data.length; + if ((address + dlength) > addressStop) { + dlength = (int) (addressStop - address + 1); } - System.arraycopy(data, 0, buffer, (int) (address - addressStart), length); - totalLength += length; + System.arraycopy(data, 0, buffer, (int) (address - addressStart), dlength); + totalLength += dlength; } } diff --git a/README.md b/README.md index 2975df8..054df08 100644 --- a/README.md +++ b/README.md @@ -3,29 +3,31 @@ Physicaloid Library Android Library for communicating with physical-computing boards (e.g.Arduino, mbed) -![Android x Arduino](https://lh5.googleusercontent.com/-weC-lA-1rdw/UeaCzIrWR3I/AAAAAAAACno/u-ZapAmzkz8/s640/android_arduino.jpg) - - -Users does not need to download an Arduino sketch from a web site. -![Download sketch](https://lh3.googleusercontent.com/-Hh-vISkTL6w/UeaC5moml2I/AAAAAAAACn8/g7Dozio1QrE/s640/physicaloid_download.png) - - -You (developer) can include Arduino firmwares in your Android app and upload to Google Play. -![Upload to Google Play](https://lh6.googleusercontent.com/-lzDrLOSohUY/UeaC5p7Z0uI/AAAAAAAACoA/hcqRjLUe6JQ/s640/physicaloid_upload.png) - - Features ----------------- +- **NEW! No closed source slow and buggy D2XX drivers are required.** - Android Java library project - USB-Serial communication +- WiFi-Serial communication to ESP8266 - upload a firmware to an Arduino - support on Android 3.1 or higher (need USB Host API feature) - **does not require ROOT** -- support USB-Serial protocols : CDC-ACM, FTDI, Silicon Labs CP210x -- support uploading firmware protocols : STK500, STK500V2 +- supports USB-Serial protocols : CDC-ACM, FTDI, Silicon Labs CP210x and WinChipHead CH34X +- supports uploading firmware protocols : STK500, STK500V2, Binary blob ESP8266 OTA - open-source(Apache License 2.0) +![Android x Arduino](https://lh5.googleusercontent.com/-weC-lA-1rdw/UeaCzIrWR3I/AAAAAAAACno/u-ZapAmzkz8/s640/android_arduino.jpg) + + +Users do not need to download an Arduino sketch from a web site. +![Download sketch](https://lh3.googleusercontent.com/-Hh-vISkTL6w/UeaC5moml2I/AAAAAAAACn8/g7Dozio1QrE/s640/physicaloid_download.png) + + +You (developer) can include Arduino firmwares in your Android app and upload to Google Play. +![Upload to Google Play](https://lh6.googleusercontent.com/-lzDrLOSohUY/UeaC5p7Z0uI/AAAAAAAACoA/hcqRjLUe6JQ/s640/physicaloid_upload.png) + + Code example ----------------- @@ -40,9 +42,9 @@ mPhysicaloid.upload(Boards.ARDUINO_UNO, "/sdcard/arduino/Blink.hex"); ```java Physicaloid mPhysicaloid = new Physicaloid(this); if(mPhysicaloid.open()) { - byte[] buf = "moemoe".getBytes(); - mPhysicaloid.write(buf, buf.length); - mPhysicaloid.close() + byte[] buf = "moemoe".getBytes(); + mPhysicaloid.write(buf, buf.length); + mPhysicaloid.close() } ``` @@ -53,13 +55,13 @@ Physicaloid mPhysicaloid = new Physicaloid(this); TextView TextView1 = (TextView) findViewById(R.id.TextView1);// Android TextView if(mPhysicaloid.open()) { - byte[] buf = new byte[256]; + byte[] buf = new byte[256]; - mPhysicaloid.read(buf, buf.length); - String str = new String(buf); - TextView1.append(str); + mPhysicaloid.read(buf, buf.length); + String str = new String(buf); + TextView1.append(str); - mPhysicaloid.close(); + mPhysicaloid.close(); } ``` diff --git a/SampleProjects/PhysicaloidTest/build.properties b/SampleProjects/PhysicaloidTest/build.properties new file mode 100644 index 0000000..e69de29 diff --git a/SampleProjects/PhysicaloidTest/build.xml b/SampleProjects/PhysicaloidTest/build.xml new file mode 100644 index 0000000..9b7a1f0 --- /dev/null +++ b/SampleProjects/PhysicaloidTest/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SampleProjects/PhysicaloidTest/default.properties b/SampleProjects/PhysicaloidTest/default.properties new file mode 100644 index 0000000..e69de29 diff --git a/SampleProjects/PhysicaloidTest/nbandroid/private.properties b/SampleProjects/PhysicaloidTest/nbandroid/private.properties new file mode 100644 index 0000000..9d0798f --- /dev/null +++ b/SampleProjects/PhysicaloidTest/nbandroid/private.properties @@ -0,0 +1,5 @@ +auxiliary.config.active= +auxiliary.config.names= +auxiliary.emulator.options.= +auxiliary.launch.action.=main +auxiliary.launch.target.=AUTO diff --git a/SampleProjects/PhysicaloidTest/project.properties b/SampleProjects/PhysicaloidTest/project.properties index 01e5cf6..a29a07f 100644 --- a/SampleProjects/PhysicaloidTest/project.properties +++ b/SampleProjects/PhysicaloidTest/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-12 +target=android-18 android.library.reference.1=../../PhysicaloidLibrary diff --git a/SampleProjects/PhysicaloidTest/src/com/example/physicaloidtest/PhysicaloidTestActivity.java b/SampleProjects/PhysicaloidTest/src/com/example/physicaloidtest/PhysicaloidTestActivity.java index 2d18429..fc99a70 100644 --- a/SampleProjects/PhysicaloidTest/src/com/example/physicaloidtest/PhysicaloidTestActivity.java +++ b/SampleProjects/PhysicaloidTest/src/com/example/physicaloidtest/PhysicaloidTestActivity.java @@ -1,9 +1,5 @@ package com.example.physicaloidtest; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; @@ -21,341 +17,342 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; - import com.physicaloid.lib.Boards; import com.physicaloid.lib.Physicaloid; import com.physicaloid.lib.Physicaloid.UploadCallBack; import com.physicaloid.lib.fpga.PhysicaloidFpga; import com.physicaloid.lib.programmer.avr.UploadErrors; -import com.physicaloid.lib.usb.driver.uart.ReadLisener; +import com.physicaloid.lib.usb.driver.uart.ReadListener; +import com.physicaloid.lib.usb.driver.uart.UartConfig; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; public class PhysicaloidTestActivity extends Activity { - private static final String TAG = PhysicaloidTestActivity.class.getSimpleName(); - - // The serialtest.*.hex is an echo-back program. - // http://www.physicaloid.com/hexfiles/serialtest.ino - // You can download those hex files from - // http://www.physicaloid.com/hexfiles/serialtest.uno.hex - // http://www.physicaloid.com/hexfiles/serialtest.mega.hex - @SuppressLint("SdCardPath") - private static final String UPLOAD_FILE_UNO = "/sdcard/arduino/serialtest.uno.hex"; - @SuppressLint("SdCardPath") - private static final String UPLOAD_FILE_MEGA = "/sdcard/arduino/serialtest.mega.hex"; - @SuppressLint("SdCardPath") - private static final String UPLOAD_FILE_BALANDUINO = "/sdcard/arduino/serialtest.balanduino.hex"; - @SuppressLint("SdCardPath") - private static final String UPLOAD_FILE_FPGA = "/sdcard/fpga/testtop.rbf"; - - private static final String ASSET_FILE_NAME_UNO = "Blink.uno.hex"; - private static final String ASSET_FILE_NAME_MEGA = "Blink.mega.hex"; - private static final String ASSET_FILE_NAME_BALANDUINO = "Blink.balanduino.hex"; - private static final String ASSET_FILE_NAME_FPGA = "testtop.rbf"; - - Physicaloid mPhysicaloid; - PhysicaloidFpga mPhysicaloidFpga; - Boards mSelectedBoard; - - Button btOpen; - Button btClose; - Button btWrite; - Button btRead; - Button btReadCallback; - Button btUpload; - EditText etWrite; - TextView tvRead; - TextView tvSelectedBoard; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_physicaloid_test); - - btOpen = (Button) findViewById(R.id.btOpen); - btClose = (Button) findViewById(R.id.btClose); - btWrite = (Button) findViewById(R.id.btWrite); - btRead = (Button) findViewById(R.id.btRead); - btReadCallback = (Button) findViewById(R.id.btReadCallback); - btUpload = (Button) findViewById(R.id.btUpload); - etWrite = (EditText) findViewById(R.id.etWrite); - tvRead = (TextView) findViewById(R.id.tvRead); - tvSelectedBoard = (TextView) findViewById(R.id.tvSelectedBoard); - - updateViews(false); - - mPhysicaloid = new Physicaloid(this); - - // Shows last selected board - mBoardList = new ArrayList(); - for(Boards board : Boards.values()) { - if(board.support>0) { - mBoardList.add(board); - } + + private static final String TAG = PhysicaloidTestActivity.class.getSimpleName(); + // The serialtest.*.hex is an echo-back program. + // http://www.physicaloid.com/hexfiles/serialtest.ino + // You can download those hex files from + // http://www.physicaloid.com/hexfiles/serialtest.uno.hex + // http://www.physicaloid.com/hexfiles/serialtest.mega.hex + @SuppressLint("SdCardPath") + private static final String UPLOAD_FILE_UNO = "/sdcard/arduino/serialtest.uno.hex"; + @SuppressLint("SdCardPath") + private static final String UPLOAD_FILE_MEGA = "/sdcard/arduino/serialtest.mega.hex"; + @SuppressLint("SdCardPath") + private static final String UPLOAD_FILE_BALANDUINO = "/sdcard/arduino/serialtest.balanduino.hex"; + @SuppressLint("SdCardPath") + private static final String UPLOAD_FILE_FPGA = "/sdcard/fpga/testtop.rbf"; + private static final String ASSET_FILE_NAME_UNO = "Blink.uno.hex"; + private static final String ASSET_FILE_NAME_MEGA = "Blink.mega.hex"; + private static final String ASSET_FILE_NAME_BALANDUINO = "Blink.balanduino.hex"; + private static final String ASSET_FILE_NAME_FPGA = "testtop.rbf"; + Physicaloid mPhysicaloid; + PhysicaloidFpga mPhysicaloidFpga; + Boards mSelectedBoard; + Button btOpen; + Button btClose; + Button btWrite; + Button btRead; + Button btReadCallback; + Button btUpload; + EditText etWrite; + TextView tvRead; + TextView tvSelectedBoard; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_physicaloid_test); + + btOpen = (Button) findViewById(R.id.btOpen); + btClose = (Button) findViewById(R.id.btClose); + btWrite = (Button) findViewById(R.id.btWrite); + btRead = (Button) findViewById(R.id.btRead); + btReadCallback = (Button) findViewById(R.id.btReadCallback); + btUpload = (Button) findViewById(R.id.btUpload); + etWrite = (EditText) findViewById(R.id.etWrite); + tvRead = (TextView) findViewById(R.id.tvRead); + tvSelectedBoard = (TextView) findViewById(R.id.tvSelectedBoard); + + updateViews(false); + + mPhysicaloid = new Physicaloid(this); + + // Shows last selected board + mBoardList = new ArrayList(); + for(Boards board : Boards.values()) { + if(board.support > 0) { + mBoardList.add(board); + } + } + int lastBoard = getSelectedBoard(); + tvSelectedBoard.setText(mBoardList.get(lastBoard).text); + mSelectedBoard = mBoardList.get(lastBoard); } - int lastBoard = getSelectedBoard(); - tvSelectedBoard.setText(mBoardList.get(lastBoard).text); - mSelectedBoard = mBoardList.get(lastBoard); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - close(); - } - - public void onClickOpen(View v) { - if(mPhysicaloid.open()) { - updateViews(true); - } else { - Toast.makeText(this, "Cannot open", Toast.LENGTH_LONG).show(); + + @Override + protected void onDestroy() { + super.onDestroy(); + close(); } - } - public void onClickClose(View v) { - close(); - } + public void onClickOpen(View v) { + UartConfig uartConfig = new UartConfig(115200, UartConfig.DATA_BITS8, UartConfig.STOP_BITS1, UartConfig.PARITY_NONE, true, false); + if(mPhysicaloid.open()) { + mPhysicaloid.setConfig(uartConfig); + updateViews(true); + } else { + Toast.makeText(this, "Cannot open", Toast.LENGTH_LONG).show(); + } + } - private void close() { - if(mPhysicaloid.close()) { - updateViews(false); + public void onClickClose(View v) { + close(); } - } - - public void onClickWrite(View v) { - String str = etWrite.getText().toString(); - byte[] buf = str.getBytes(); - mPhysicaloid.write(buf, buf.length); - } - - public void onClickRead(View v) { - byte[] buf = new byte[256]; - mPhysicaloid.read(buf, buf.length); - String str = new String(buf); - tvRead.append(Html.fromHtml(""+str+"")); - } - - private boolean readCallbackOn = false; - public void onClickReadCallback(View v) { - if(readCallbackOn) { - mPhysicaloid.clearReadListener(); - btReadCallback.setText("ReadCallbackOff"); - btRead.setEnabled(true); - readCallbackOn = false; - } else { - mPhysicaloid.addReadListener(new ReadLisener() { - @Override - public void onRead(int size) { - byte[] buf = new byte[size]; - mPhysicaloid.read(buf, size); - tvAppend(tvRead, Html.fromHtml(""+new String(buf)+"")); + + private void close() { + if(mPhysicaloid.close()) { + updateViews(false); } - }); - btReadCallback.setText("ReadCallbackOn"); - btRead.setEnabled(false); - readCallbackOn = true; } - } - - public void onClickUpload(View v) { - String fileName; - if(mSelectedBoard == Boards.ARDUINO_MEGA_2560_ADK) { - fileName = UPLOAD_FILE_MEGA; - } else if(mSelectedBoard == Boards.BALANDUINO) { - fileName = UPLOAD_FILE_BALANDUINO; - } else { - fileName = UPLOAD_FILE_UNO; + + public void onClickWrite(View v) { + String str = etWrite.getText().toString(); + byte[] buf = str.getBytes(); + mPhysicaloid.write(buf, buf.length); } - mPhysicaloid.upload(mSelectedBoard, fileName, - mUploadCallback); - } - - public void onClickUploadAsset(View v) { - String assetFileName; - if(mSelectedBoard == Boards.ARDUINO_MEGA_2560_ADK) { - assetFileName = ASSET_FILE_NAME_MEGA; - } else if(mSelectedBoard == Boards.BALANDUINO) { - assetFileName = ASSET_FILE_NAME_BALANDUINO; - } else if(mSelectedBoard == Boards.PERIDOT) { - assetFileName = ASSET_FILE_NAME_FPGA; - PhysicaloidFpga physicaloidFpga = new PhysicaloidFpga(this); - try { - physicaloidFpga.upload(mSelectedBoard, getResources().getAssets().open(assetFileName), mUploadCallback); - } catch (RuntimeException e) { - Log.e(TAG, e.toString()); - } catch (IOException e) { - Log.e(TAG, e.toString()); - } - return; - } else { - assetFileName = ASSET_FILE_NAME_UNO; + + public void onClickRead(View v) { + byte[] buf = new byte[256]; + mPhysicaloid.read(buf, buf.length); + String str = new String(buf); + tvRead.append(Html.fromHtml("" + str + "")); } - try { - mPhysicaloid.upload(mSelectedBoard, getResources().getAssets().open(assetFileName), mUploadCallback); - } catch (RuntimeException e) { - Log.e(TAG, e.toString()); - } catch (IOException e) { - Log.e(TAG, e.toString()); + private boolean readCallbackOn = false; + + public void onClickReadCallback(View v) { + if(readCallbackOn) { + mPhysicaloid.clearReadListener(); + btReadCallback.setText("ReadCallbackOff"); + btRead.setEnabled(true); + readCallbackOn = false; + } else { + mPhysicaloid.addReadListener(new ReadListener() { + + @Override + public void onRead(int size) { + byte[] buf = new byte[size]; + mPhysicaloid.read(buf, size); + tvAppend(tvRead, Html.fromHtml("" + new String(buf) + "")); + //Log.d(TAG, "*********** " +new String(buf)); + } + }); + btReadCallback.setText("ReadCallbackOn"); + btRead.setEnabled(false); + readCallbackOn = true; + } } - } - - public void onClickCancelUpload(View v) { - mPhysicaloid.cancelUpload(); - } - UploadCallBack mUploadCallback = new UploadCallBack() { - - @Override - public void onUploading(int value) { - tvAppend(tvRead, "Upload : "+value+" %\n"); - } - - @Override - public void onPreUpload() { - tvAppend(tvRead, "Upload : Start\n"); + public void onClickUpload(View v) { + String fileName; + if(mSelectedBoard == Boards.ARDUINO_MEGA_2560_ADK) { + fileName = UPLOAD_FILE_MEGA; + } else if(mSelectedBoard == Boards.BALANDUINO) { + fileName = UPLOAD_FILE_BALANDUINO; + } else { + fileName = UPLOAD_FILE_UNO; + } + mPhysicaloid.upload(mSelectedBoard, fileName, + mUploadCallback); } - - @Override - public void onPostUpload(boolean success) { - if(success) { - tvAppend(tvRead, "Upload : Successful\n"); - } else { - tvAppend(tvRead, "Upload fail\n"); - } + + public void onClickUploadAsset(View v) { + String assetFileName; + if(mSelectedBoard == Boards.ARDUINO_MEGA_2560_ADK) { + assetFileName = ASSET_FILE_NAME_MEGA; + } else if(mSelectedBoard == Boards.BALANDUINO) { + assetFileName = ASSET_FILE_NAME_BALANDUINO; + } else if(mSelectedBoard == Boards.PERIDOT) { + assetFileName = ASSET_FILE_NAME_FPGA; + PhysicaloidFpga physicaloidFpga = new PhysicaloidFpga(this); + try { + physicaloidFpga.upload(mSelectedBoard, getResources().getAssets().open(assetFileName), mUploadCallback); + } catch(RuntimeException e) { + Log.e(TAG, e.toString()); + } catch(IOException e) { + Log.e(TAG, e.toString()); + } + return; + } else { + assetFileName = ASSET_FILE_NAME_UNO; + } + try { + mPhysicaloid.upload(mSelectedBoard, getResources().getAssets().open(assetFileName), mUploadCallback); + } catch(RuntimeException e) { + Log.e(TAG, e.toString()); + } catch(IOException e) { + Log.e(TAG, e.toString()); + } } - @Override - public void onCancel() { - tvAppend(tvRead, "Cancel uploading\n"); + public void onClickCancelUpload(View v) { + mPhysicaloid.cancelUpload(); } + UploadCallBack mUploadCallback = new UploadCallBack() { - @Override - public void onError(UploadErrors err) { - tvAppend(tvRead, "Error : "+err.toString()+"\n"); + @Override + public void onUploading(int value) { + tvAppend(tvRead, "Upload : " + value + " %\n"); + } + + @Override + public void onPreUpload() { + tvAppend(tvRead, "Upload : Start\n"); + } + + @Override + public void onPostUpload(boolean success) { + if(success) { + tvAppend(tvRead, "Upload : Successful\n"); + } else { + tvAppend(tvRead, "Upload fail\n"); + } + } + + @Override + public void onCancel() { + tvAppend(tvRead, "Cancel uploading\n"); + } + + @Override + public void onError(UploadErrors err) { + tvAppend(tvRead, "Error : " + err.toString() + "\n"); + } + }; + + private void updateViews(boolean on) { + if(on) { + btOpen.setEnabled(false); + btClose.setEnabled(true); + btWrite.setEnabled(true); + btRead.setEnabled(true); + btReadCallback.setEnabled(true); + etWrite.setEnabled(true); + } else { + btOpen.setEnabled(true); + btClose.setEnabled(false); + btWrite.setEnabled(false); + btRead.setEnabled(false); + btReadCallback.setEnabled(false); + etWrite.setEnabled(false); + } } - }; - - private void updateViews(boolean on) { - if(on) { - btOpen.setEnabled(false); - btClose.setEnabled(true); - btWrite.setEnabled(true); - btRead.setEnabled(true); - btReadCallback.setEnabled(true); - etWrite.setEnabled(true); - } else { - btOpen.setEnabled(true); - btClose.setEnabled(false); - btWrite.setEnabled(false); - btRead.setEnabled(false); - btReadCallback.setEnabled(false); - etWrite.setEnabled(false); + Handler mHandler = new Handler(); + + private void tvAppend(TextView tv, CharSequence text) { + final TextView ftv = tv; + final CharSequence ftext = text; + mHandler.post(new Runnable() { + + @Override + public void run() { + ftv.append(ftext); + } + }); } - } - - Handler mHandler = new Handler(); - private void tvAppend(TextView tv, CharSequence text) { - final TextView ftv = tv; - final CharSequence ftext = text; - mHandler.post(new Runnable() { - @Override - public void run() { - ftv.append(ftext); - } - }); - } - - - @SuppressWarnings("unused") - private String toHexStr(byte[] b, int length) { - String str=""; - for(int i=0; i mBoardList; - private int mItemPos = 0; + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch(item.getItemId()) { + case MENU_ID_BOARD: + showSelectBoardDialog(); + return true; + default: + return false; + } + } + private ArrayList mBoardList; + private int mItemPos = 0; - private void showSelectBoardDialog() { + private void showSelectBoardDialog() { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("Select a board"); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("Select a board"); - // get from Boards list - List items = new ArrayList(); - for(Boards board : Boards.values()) { - if(board.support>0) { - items.add(board.text); - } - } - String[] itemStr = (String[])items.toArray(new String[0]); - builder.setSingleChoiceItems(itemStr, getSelectedBoard(), mItemListener); - - builder.setPositiveButton("OK", mButtonListener ); - builder.setNeutralButton ("Cancel", mButtonListener ); + // get from Boards list + List items = new ArrayList(); + for(Boards board : Boards.values()) { + if(board.support > 0) { + items.add(board.text); + } + } + String[] itemStr = (String[]) items.toArray(new String[0]); + builder.setSingleChoiceItems(itemStr, getSelectedBoard(), mItemListener); - AlertDialog dialog = builder.create(); - dialog.show(); - } + builder.setPositiveButton("OK", mButtonListener); + builder.setNeutralButton("Cancel", mButtonListener); - DialogInterface.OnClickListener mItemListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - mItemPos = which; + AlertDialog dialog = builder.create(); + dialog.show(); } - }; - - DialogInterface.OnClickListener mButtonListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - switch( which ){ - case AlertDialog.BUTTON_POSITIVE: // OK pressed - saveSelectedBoard(mItemPos); - mSelectedBoard = mBoardList.get(mItemPos); - tvSelectedBoard.setText(mBoardList.get(mItemPos).text); - break; - case AlertDialog.BUTTON_NEUTRAL: // Cancel pressed - break; - } + DialogInterface.OnClickListener mItemListener = new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + mItemPos = which; + } + }; + DialogInterface.OnClickListener mButtonListener = new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + switch(which) { + case AlertDialog.BUTTON_POSITIVE: // OK pressed + saveSelectedBoard(mItemPos); + mSelectedBoard = mBoardList.get(mItemPos); + tvSelectedBoard.setText(mBoardList.get(mItemPos).text); + break; + case AlertDialog.BUTTON_NEUTRAL: // Cancel pressed + break; + } + } + }; + + // Saves selected board position + private void saveSelectedBoard(int pos) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + sp.edit().putInt("SelectedBoardPosition", pos).commit(); } - }; - - // Saves selected board position - private void saveSelectedBoard(int pos) { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); - sp.edit().putInt("SelectedBoardPosition", pos).commit(); - } - - // Gets selected board position - private int getSelectedBoard() { - int pos; - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); - pos = sp.getInt("SelectedBoardPosition", 0); - return pos; - } - ///////////////////////////////////////////////////////////////// - // End of board select menu - ///////////////////////////////////////////////////////////////// + // Gets selected board position + private int getSelectedBoard() { + int pos; + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + pos = sp.getInt("SelectedBoardPosition", 0); + return pos; + } + ///////////////////////////////////////////////////////////////// + // End of board select menu + ///////////////////////////////////////////////////////////////// }