/* @file DistoXComm.java
*
* @author marco corvi
* @date nov 2011
*
* @brief TopoDroid-DistoX BlueTooth communication
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
import java.nio.ByteBuffer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.EOFException;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
// import android.os.Parcelable;
import android.os.ParcelUuid;
// import android.os.AsyncTask;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
// import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.database.DataSetObserver;
// import android.widget.Toast;
import android.util.Log;
public class DistoXComm extends TopoDroidComm
{
private BluetoothDevice mBTDevice;
private BluetoothSocket mBTSocket;
private String mAddress;
// private static final byte CALIB_BIT = (byte)0x08;
// public byte[] mCoeff;
// -----------------------------------------------------------
// Bluetooth receiver
private BroadcastReceiver mBTReceiver = null;
private void resetBTReceiver()
{
if ( mBTReceiver == null ) return;
// TDLog.Log( TDLog.LOG_COMM, "reset BT receiver");
try {
mApp.unregisterReceiver( mBTReceiver );
} catch ( IllegalArgumentException e ) {
TDLog.Error( "unregister BT receiver error " + e.getMessage() );
}
mBTReceiver = null;
}
// called only by connectSocket
private void setupBTReceiver()
{
resetBTReceiver();
// TDLog.Log( TDLog.LOG_COMM, "setup BT receiver");
mBTReceiver = new BroadcastReceiver()
{
@Override
public void onReceive( Context ctx, Intent data )
{
String action = data.getAction();
BluetoothDevice bt_device = data.getParcelableExtra( BluetoothDevice.EXTRA_DEVICE );
String device = ( bt_device != null )? bt_device.getAddress() : "undefined";
// if ( BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals( action ) ) {
// } else if ( BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals( action ) ) {
// } else if ( BluetoothDevice.ACTION_FOUND.equals( action ) ) {
if ( BluetoothDevice.ACTION_ACL_CONNECTED.equals( action ) ) {
TDLog.Log( TDLog.LOG_BT, "[C] ACL_CONNECTED " + device + " addr " + mAddress );
if ( device.equals(mAddress) ) // FIXME ACL_DISCONNECT
{
mApp.mDataDownloader.setConnected( true );
mApp.notifyStatus();
}
} else if ( BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals( action ) ) {
TDLog.Log( TDLog.LOG_BT, "[C] ACL_DISCONNECT_REQUESTED " + device + " addr " + mAddress );
if ( device.equals(mAddress) ) // FIXME ACL_DISCONNECT
{
mApp.mDataDownloader.setConnected( false );
mApp.notifyStatus();
closeSocket( );
}
} else if ( BluetoothDevice.ACTION_ACL_DISCONNECTED.equals( action ) ) {
TDLog.Log( TDLog.LOG_BT, "[C] ACL_DISCONNECTED " + device + " addr " + mAddress );
if ( device.equals(mAddress) ) // FIXME ACL_DISCONNECT
{
mApp.mDataDownloader.setConnected( false );
mApp.notifyStatus();
closeSocket( );
mApp.notifyDisconnected();
}
} else if ( BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals( action ) ) { // NOT USED
final int state = data.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
final int prevState = data.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, BluetoothDevice.ERROR);
if (state == BluetoothDevice.BOND_BONDED && prevState == BluetoothDevice.BOND_BONDING) {
TDLog.Log( TDLog.LOG_BT, "BOND STATE CHANGED paired (BONDING --> BONDED) " + device );
} else if (state == BluetoothDevice.BOND_NONE && prevState == BluetoothDevice.BOND_BONDED){
TDLog.Log( TDLog.LOG_BT, "BOND STATE CHANGED unpaired (BONDED --> NONE) " + device );
} else if (state == BluetoothDevice.BOND_BONDING && prevState == BluetoothDevice.BOND_BONDED) {
TDLog.Log( TDLog.LOG_BT, "BOND STATE CHANGED unpaired (BONDED --> BONDING) " + device );
if ( mBTSocket != null ) {
TDLog.Error( "[*] socket is not null: close and retry connect ");
mApp.mDataDownloader.setConnected( false );
mApp.notifyStatus();
closeSocket( );
mApp.notifyDisconnected();
connectSocket( mAddress ); // returns immediately if mAddress == null
}
} else {
TDLog.Log( TDLog.LOG_BT, "BOND STATE CHANGED " + prevState + " --> " + state + " " + device );
}
// DeviceUtil.bind2Device( data );
// } else if ( BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action) ) {
// Log.v("DistoX", "PAIRING REQUEST");
// // BluetoothDevice device = getDevice();
// // //To avoid the popup notification:
// // device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
// // device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device, true);
// // byte[] pin = ByteBuffer.allocate(4).putInt(0000).array();
// // //Entering pin programmatically:
// // Method ms = device.getClass().getMethod("setPin", byte[].class);
// // //Method ms = device.getClass().getMethod("setPasskey", int.class);
// // ms.invoke(device, pin);
//
// //Bonding the device:
// // Method mm = device.getClass().getMethod("createBond", (Class[]) null);
// // mm.invoke(device, (Object[]) null);
}
}
};
// mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothDevice.ACTION_FOUND ) );
// mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_STARTED ) );
// mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_FINISHED ) );
mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothDevice.ACTION_ACL_CONNECTED ) );
mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED ) );
mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothDevice.ACTION_ACL_DISCONNECTED ) );
// mApp.registerReceiver( mBTReceiver, uuidFilter = new IntentFilter( myUUIDaction ) );
mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothDevice.ACTION_BOND_STATE_CHANGED ) );
// mApp.registerReceiver( mBTReceiver, new IntentFilter( BluetoothDevice.ACTION_PAIRING_REQUEST ) );
}
// --------------------------------------------------
DistoXComm( TopoDroidApp app )
{
super( app );
mAddress = null;
mBTSocket = null;
// TDLog.Log( TDLog.LOG_COMM, "DistoX Comm cstr");
}
// public void resume()
// {
// // if ( mRfcommThread != null ) { mRfcommThread.resume(); }
// }
// public void suspend()
// {
// // if ( mRfcommThread != null ) { mRfcommThread.suspend(); }
// }
// --------------------------------------------------------
// SOCKET
/** close the socket (and the RFcomm thread) but don't delete it
* alwasy called with wait_thread
*/
private synchronized void closeSocket( )
{
if ( mBTSocket == null ) return;
// TDLog.Log( TDLog.LOG_COMM, "close socket() address " + mAddress );
for ( int k=0; k<1 && mBTSocket != null; ++k ) {
// TDLog.Error( "try close socket nr " + k );
cancelRfcommThread();
closeProtocol();
try {
mBTSocket.close();
mBTSocket = null;
} catch ( IOException e ) {
TDLog.Error( "close socket IOexception " + e.getMessage() );
// TDLog.LogStackTrace( e );
} finally {
mBTConnected = false;
}
}
mBTConnected = false;
}
/** close the socket and delete it
* the connection becomes unusable
* As a matter of fact this is alwyas called with wait_thread = true
*/
private void destroySocket( ) // boolean wait_thread )
{
if ( mBTSocket == null ) return;
// TDLog.Log( TDLog.LOG_COMM, "destroy socket() address " + mAddress );
// closeProtocol(); // already in closeSocket()
closeSocket();
// mBTSocket = null;
resetBTReceiver();
}
/** create a socket (not connected)
* and a connection protocol on it
*/
private void createSocket( String address, int port )
{
if ( address == null ) return;
// TDLog.Log( TDLog.LOG_COMM, "create Socket() addr " + address + " mAddress " + mAddress);
if ( mProtocol == null || ! address.equals( mAddress ) ) {
if ( mProtocol != null && ! address.equals( mAddress ) ) {
disconnectRemoteDevice();
}
if ( mBTSocket != null ) {
// TDLog.Log( TDLog.LOG_COMM, "create Socket() BTSocket not null ... closing");
try {
mBTSocket.close();
} catch ( IOException e ) {
TDLog.Error( "close Socket IO " + e.getMessage() );
}
mBTSocket = null;
}
mBTDevice = mApp.mBTAdapter.getRemoteDevice( address );
// FIXME PAIRING
// TDLog.Log( TDLog.LOG_BT, "[1] device state " + mBTDevice.getBondState() );
if ( ! DeviceUtil.isPaired( mBTDevice ) ) {
int ret = DeviceUtil.pairDevice( mBTDevice );
// TDLog.Log( TDLog.LOG_BT, "[1] pairing device " + ret );
// }
// TDLog.Log( TDLog.LOG_BT, "[2] device state " + mBTDevice.getBondState() );
// // if ( mBTDevice.getBondState() == BluetoothDevice.BOND_NONE )
// if ( ! DeviceUtil.isPaired( mBTDevice ) )
// {
// TDLog.Log( TDLog.LOG_BT, "bind device " );
DeviceUtil.bindDevice( mBTDevice );
}
// wait "delay" seconds
if ( ! DeviceUtil.isPaired( mBTDevice ) ) {
for ( int n=0; n < TDSetting.mConnectSocketDelay; ++n ) {
try {
Thread.yield();
Thread.sleep( 100 );
} catch ( InterruptedException e ) { }
if ( DeviceUtil.isPaired( mBTDevice ) ) {
// TDLog.Log( TDLog.LOG_BT, "device paired at time " + n );
break;
}
}
}
if ( DeviceUtil.isPaired( mBTDevice ) ) {
try {
Class[] classes1 = new Class[]{ int.class };
Class[] classes2 = new Class[]{ UUID.class };
if ( TDSetting.mSockType == TDSetting.TD_SOCK_DEFAULT ) {
// TDLog.Log( TDLog.LOG_COMM, "create Socket() createRfcommSocketToServiceRecord " );
mBTSocket = mBTDevice.createRfcommSocketToServiceRecord( UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") );
} else if ( TDSetting.mSockType == TDSetting.TD_SOCK_INSEC ) {
// TDLog.Log( TDLog.LOG_COMM, "create Socket() createInsecureRfcommSocketToServiceRecord " );
Method m3 = mBTDevice.getClass().getMethod( "createInsecureRfcommSocketToServiceRecord", classes2 );
mBTSocket = (BluetoothSocket) m3.invoke( mBTDevice, UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") );
} else if ( TDSetting.mSockType == TDSetting.TD_SOCK_INSEC_PORT ) {
// TDLog.Log( TDLog.LOG_COMM, "create Socket() invoke createInsecureRfcommSocket " );
Method m1 = mBTDevice.getClass().getMethod( "createInsecureRfcommSocket", classes1 );
mBTSocket = (BluetoothSocket) m1.invoke( mBTDevice, port );
// mBTSocket = mBTDevice.createInsecureRfcommSocket( port );
// mBTSocket = (BluetoothSocket) m1.invoke( mBTDevice, UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") );
} else if ( TDSetting.mSockType == TDSetting.TD_SOCK_PORT ) {
// TDLog.Log( TDLog.LOG_COMM, "create Socket() invoke createRfcommSocket " );
Method m2 = mBTDevice.getClass().getMethod( "createRfcommSocket", classes1 );
mBTSocket = (BluetoothSocket) m2.invoke( mBTDevice, port );
}
} catch ( InvocationTargetException e ) {
TDLog.Error( "create Socket invoke target " + e.getMessage() );
if ( mBTSocket != null ) { mBTSocket = null; }
} catch ( UnsupportedEncodingException e ) {
TDLog.Error( "create Socket encoding " + e.getMessage() );
if ( mBTSocket != null ) { mBTSocket = null; }
} catch ( NoSuchMethodException e ) {
TDLog.Error( "create Socket no method " + e.getMessage() );
if ( mBTSocket != null ) { mBTSocket = null; }
} catch ( IllegalAccessException e ) {
TDLog.Error( "create Socket access " + e.getMessage() );
if ( mBTSocket != null ) { mBTSocket = null; }
} catch ( IOException e ) {
TDLog.Error( "create Socket IO " + e.getMessage() );
if ( mBTSocket != null ) { mBTSocket = null; }
}
} else {
// TDLog.Log( TDLog.LOG_BT, "device not paired. state " + mBTDevice.getBondState() );
}
mProtocol = null;
if ( mBTSocket != null ) {
// TDLog.Log( TDLog.LOG_COMM, "create Socket OK");
// mBTSocket.setSoTimeout( 200 ); // BlueToothSocket does not have timeout
try {
DataInputStream in = new DataInputStream( mBTSocket.getInputStream() );
DataOutputStream out = new DataOutputStream( mBTSocket.getOutputStream() );
mProtocol = new DistoXProtocol( in, out, mApp.mDevice );
mAddress = address;
} catch ( IOException e ) {
mAddress = null;
}
} else {
TDLog.Error( "create Socket fail");
if ( mProtocol != null ) mProtocol.closeIOstreams();
mProtocol = null;
mAddress = null;
}
mBTConnected = false; // socket is created but not connected
}
}
/** get the list of UUIDs supported by the remote device (for the DistoX only SPP uuid)
*/
private void getUuids()
{
if ( mBTDevice == null ) return;
try {
Class cl = Class.forName("android.bluetooth.BluetoothDevice");
Class[] pars = {};
Method m0 = cl.getMethod( "getUuids", pars );
Object[] args = {};
ParcelUuid[] uuids = (ParcelUuid[]) m0.invoke( mBTDevice, args );
// if ( uuids != null ) {
// for ( ParcelUuid uid : uuids ) {
// TDLog.Log( TDLog.LOG_COMM, "uuid " + uid.toString() );
// }
// }
} catch ( Exception e ) {
TDLog.Error( "get uuids error " + e.getMessage() );
}
}
/** connect the socket to the device
*/
private boolean connectSocket( String address )
{
if ( address == null ) return false;
// TDLog.Log( TDLog.LOG_COMM, "connect socket(): " + address );
createSocket( address, 1 ); // default port == 1
// DEBUG
getUuids();
if ( mBTSocket != null ) {
mApp.mBTAdapter.cancelDiscovery();
setupBTReceiver();
int port = 0;
while ( ! mBTConnected && port < TDSetting.mCommRetry ) {
++ port;
if ( mBTSocket != null ) {
// TDLog.Log( TDLog.LOG_COMM, "connect socket() try port " + port );
try {
// TDLog.Log( TDLog.LOG_BT, "[3] device state " + mBTDevice.getBondState() );
mBTSocket.connect();
mBTConnected = true;
} catch ( IOException e ) {
TDLog.Error( "connect socket() (port " + port + ") IO error " + e.getMessage() );
// TDLog.LogStackTrace( e );
closeSocket();
// mBTSocket = null;
}
}
if ( mBTSocket == null && port < TDSetting.mCommRetry ) {
createSocket( address, port );
}
// TDLog.Log( TDLog.LOG_COMM, "connect socket() port " + port + " connected " + mBTConnected );
}
} else {
TDLog.Error( "connect socket() null socket");
}
// TDLog.Log( TDLog.LOG_COMM, "connect socket() result " + mBTConnected );
return mBTConnected;
}
protected boolean startRfcommThread( int to_read, Handler /* ILister */ lister ) // FIXME LISTER
{
// TDLog.Log( TDLog.LOG_COMM, "start RFcomm thread: to_read " + to_read );
if ( mBTSocket != null ) {
if ( mRfcommThread == null ) {
mRfcommThread = new RfcommThread( mProtocol, to_read, lister );
mRfcommThread.start();
// TDLog.Log( TDLog.LOG_COMM, "startRFcommThread started");
} else {
TDLog.Error( "startRFcommThread already running");
}
return true;
} else {
mRfcommThread = null;
TDLog.Error( "startRFcommThread: null socket");
return false;
}
}
// --------------------------------------------------------
// public boolean connectRemoteDevice( String address, Handler /* ArrayList<ILister> */ lister ) // FIXME LISTER
// {
// // TDLog.Log( TDLog.LOG_COMM, "connect remote device: address " + address );
// if ( connectSocket( address ) ) {
// if ( mProtocol != null ) {
// return startRfcommThread( -1, lister );
// }
// TDLog.Error( "connect RemoteDevice null protocol");
// } else {
// TDLog.Error( "connect RemoteDevice failed on connectSocket()" );
// }
// destroySocket( );
// return false;
// }
public void disconnectRemoteDevice( )
{
// TDLog.Log( TDLog.LOG_COMM, "disconnect remote device ");
super.disconnectRemoteDevice();
// cancelRfcommThread();
// closeProtocol();
destroySocket( );
}
/**
* nothing to read (only write) --> no AsyncTask
*/
public void setX310Laser( String address, int what, Handler /* ILister */ lister ) // FIXME LISTER
{
if ( connectSocket( address ) ) {
switch ( what ) {
case 0: // LASER OFF
sendCommand( 0x37 );
break;
case 1: // LASER ON
sendCommand( 0x36 );
break;
case 2: // MEASURE
case 3: // MEASURE and DOWNLAOD
sendCommand( 0x38 );
if ( what == 3 ) {
if ( mRfcommThread == null ) {
// Log.v("DistoX", "RF comm thread start ... ");
startRfcommThread( -1, lister );
while ( mRfcommThread != null ) {
try { Thread.sleep( 100 ); } catch ( InterruptedException e ) { }
}
} else {
// Log.v("DistoX", "RF comm thread not null ");
}
}
break;
}
}
destroySocket( );
}
/** send the set/unset calib-mode command
* @note called within connectSocket()
* nothing to read (only write) --> no AsyncTask
*/
private boolean setX310CalibMode( boolean turn_on )
{
boolean ret = false;
if ( turn_on ) {
ret = sendCommand( 0x31 ); // TOGGLE CALIB ON
} else {
ret = sendCommand( 0x30 ); // TOGGLE CALIB OFF
}
// TDLog.Log( TDLog.LOG_COMM, "set X310 CalibMode ret " + ret );
return ret;
}
/** Toggle device calibration mode
* @param address device address
* @param type device type
* @return
*/
public boolean toggleCalibMode( String address, int type )
{
if ( ! checkRfcommThreadNull( "toggle Calib Mode: address " + address + " type " + type ) ) {
TDLog.Error( "toggle Calib Mode address " + address + " not null RFcomm thread" );
return false;
}
boolean ret = false;
if ( connectSocket( address ) ) {
switch ( type ) {
case Device.DISTO_A3:
byte[] result = new byte[4];
if ( ! mProtocol.read8000( result ) ) { // FIXME ASYNC
TDLog.Error( "toggle Calib Mode A3 failed read8000" );
destroySocket( );
return false;
}
// TDLog.Log( TDLog.LOG_COMM, "toggle Calib Mode A3 result " + result[0] );
if ( (result[0] & CALIB_BIT) == 0 ) {
ret = mProtocol.sendCommand( (byte)0x31 ); // TOGGLE CALIB ON
} else {
ret = mProtocol.sendCommand( (byte)0x30 ); // TOGGLE CALIB OFF
}
break;
case Device.DISTO_X310:
mCalibMode = ! mCalibMode;
// TDLog.Log( TDLog.LOG_COMM, "toggle Calib Mode X310 setX310CalibMode " + mCalibMode );
ret = setX310CalibMode( mCalibMode );
break;
}
}
destroySocket();
return ret;
}
public boolean writeCoeff( String address, byte[] coeff )
{
if ( ! checkRfcommThreadNull( "write coeff: address " + address ) ) return false;
boolean ret = false;
if ( coeff != null ) {
mCoeff = coeff;
if ( connectSocket( address ) ) {
ret = mProtocol.writeCalibration( mCoeff );
// FIXME ASYNC new CommandThread( mProtocol, WRITE_CALIBRATION, mCoeff );
}
destroySocket( );
}
return ret;
}
// called only by CalibReadTask
public boolean readCoeff( String address, byte[] coeff )
{
if ( ! checkRfcommThreadNull( "read coeff: address " + address ) ) return false;
boolean ret = false;
if ( coeff != null ) {
if ( connectSocket( address ) ) {
ret = mProtocol.readCalibration( coeff );
// FIXME ASYNC new CommandThread( mProtocol, READ_CALIBRATION, coeff );
// int k;
// for ( k=0; k<48; k+=8 ) {
// Log.v( TopoDroidApp.TAG,
// String.format( "%02x %02x %02x %02x %02x %02x %02x %02x",
// coeff[k+0], coeff[k+1], coeff[k+2], coeff[k+3], coeff[k+4], coeff[k+5], coeff[k+6], coeff[k+7] ) );
// }
}
destroySocket( );
}
return ret;
}
public String readHeadTail( String address, int[] head_tail )
{
String res = null;
if ( mApp.distoType() == Device.DISTO_A3 ) {
if ( ! checkRfcommThreadNull( "read HeadTail: address " + address ) ) return null;
if ( connectSocket( address ) ) {
res = mProtocol.readHeadTailA3( head_tail );
// FIXME ASYNC new CommandThread( mProtocol, READ_HEAD_TAIL, haed_tail ); NOTE int[] instead of byte[]
// TDLog.Log( TDLog.LOG_COMM, "readHeadTail() result " + res );
}
destroySocket( );
}
return res;
}
// X310 data memory is read-only
// public int resetX310Memory( String address, int from, int to )
// {
// if ( ! checkRfcommThreadNull( "reset X310 memory: address " + address ) ) return -1;
// int n = 0;
// if ( connectSocket( address ) ) {
// n = mProtocol.resetX310Memory( from, to );
// }
// destroySocket( );
// return n;
// }
public int readX310Memory( String address, int from, int to, List< MemoryOctet > memory )
{
if ( ! checkRfcommThreadNull( "read X310 memory: address " + address ) ) return -1;
int n = 0;
if ( connectSocket( address ) ) {
n = mProtocol.readX310Memory( from, to, memory );
// FIXME ASYNC new CommandThread( mProtocol, READ_X310_MEMORY, memory ) Note...
}
destroySocket( );
return n;
}
public int readA3Memory( String address, int from, int to, List< MemoryOctet > memory )
{
if ( ! checkRfcommThreadNull( "read A3 memory: address " + address ) ) return -1;
from &= 0x7ff8;
to &= 0xfff8;
if ( from >= 0x8000 ) from = 0;
if ( to >= 0x8000 ) to &= 0x8000;
int n = 0;
if ( from < to ) {
if ( connectSocket( address ) ) {
n = mProtocol.readMemory( from, to, memory );
// FIXME ASYNC new CommandThread( mProtocol, READ_MEMORY, memory ) Note...
}
destroySocket( );
}
return n;
}
// low-level memory read
// called by TopoDroidApp.readMemory
byte[] readMemory( String address, int addr )
{
byte[] ret = null;
if ( connectSocket( address ) ) {
ret = mProtocol.readMemory( addr );
// FIXME ASYNC new CommandThread( mProtocol, READ_MEMORY_LOWLEVEL, addr ) Note...
}
destroySocket( );
return ret;
}
/** swap hot bit in the range [from, to) [only A3]
*/
public int swapHotBit( String address, int from, int to )
{
if ( ! checkRfcommThreadNull( "swap hot bit: address " + address ) ) return -1;
if ( mApp.distoType() != Device.DISTO_A3 ) return -2;
from &= 0x7ff8;
to &= 0xfff8;
if ( from >= 0x8000 ) from = 0;
if ( to >= 0x8000 ) to &= 0x8000;
int n = 0;
if ( from != to ) {
if ( connectSocket( address ) ) {
do {
if ( to == 0 ) {
to = 0x8000 - 8;
} else {
to -= 8;
}
// Log.v( TopoDroidApp.TAG, "comm swap hot bit at addr " + to/8 );
if ( ! mProtocol.swapHotBit( to ) ) break;
++ n;
} while ( to != from );
// FIXME ASYNC new CommandThread( mProtocol, SWAP_HOT_BITS, from, to ) Note...
// TDLog.Log( TDLog.LOG_COMM, "swap Hot Bit swapped " + n + "data" );
}
destroySocket( );
}
return n;
}
// ------------------------------------------------------------------------------------
// CONTINUOUS DATA DOWNLOAD
public boolean connectDevice( String address, Handler /* ILister */ lister ) // FIXME LISTER
{
if ( mRfcommThread != null ) {
TDLog.Log( TDLog.LOG_COMM, "DistoX Comm connect: already connected");
return true;
}
if ( ! connectSocket( address ) ) {
return false;
}
startRfcommThread( -2, lister );
return true;
}
public void disconnect()
{
// TDLog.Log( TDLog.LOG_COMM, "disconnect");
cancelRfcommThread();
destroySocket( );
}
// -------------------------------------------------------------------------------------
// ON-DEMAND DATA DOWNLOAD
public int downloadData( String address, Handler /* ILister */ lister ) // FIXME LISTER
{
if ( ! checkRfcommThreadNull( "download data: address " + address ) ) {
TDLog.Error( "download data: RFcomm thread not null");
return DistoXProtocol.DISTOX_ERR_CONNECTED;
}
int ret = -1; // failure
if ( connectSocket( address ) ) {
// if ( mApp.distoType() == Device.DISTO_A3 ) {
// int prev_read = -1;
// int to_read = mProtocol.readToReadA3();
// TDLog.Log( TDLog.LOG_COMM, "download data: A3 to-read " + to_read );
// if ( to_read <= 0 ) {
// ret = to_read;
// } else {
// // FIXME asyncTask ?
// // nReadPackets = 0; // done in RfcommThread cstr
// startRfcommThread( to_read, lister );
// while ( mRfcommThread != null && nReadPackets < to_read ) {
// if ( nReadPackets != prev_read ) {
// TDLog.Log( TDLog.LOG_COMM, "download data: A3 read " + nReadPackets + " / " + to_read );
// prev_read = nReadPackets;
// }
// try { Thread.sleep( 100 ); } catch ( InterruptedException e ) { }
// }
// TDLog.Log( TDLog.LOG_COMM, "download done: A3 read " + nReadPackets );
// }
// } else if ( mApp.distoType() == Device.DISTO_X310 ) {
startRfcommThread( -1, lister );
while ( mRfcommThread != null ) {
try { Thread.sleep( 100 ); } catch ( InterruptedException e ) { }
}
// TDLog.Log( TDLog.LOG_COMM, "download done: read " + nReadPackets );
// } else {
// TDLog.Error( "download data: unknown DistoType " + mApp.distoType() );
// }
// cancelRfcommThread(); // called by closeSocket() which is called by destroySocket()
ret = nReadPackets;
} else {
TDLog.Error( "download data: fail to connect socket");
}
destroySocket( );
return ret;
}
// ====================================================================================
// FIRMWARE
// int readFirmwareHardware( String address )
// {
// int ret = 0;
// if ( connectSocket( address ) ) {
// ret = mProtocol.readFirmwareAddress( );
// }
// destroySocket( );
// return ret;
// }
public int dumpFirmware( String address, String filepath )
{
int ret = 0;
if ( connectSocket( address ) ) {
ret = mProtocol.dumpFirmware( filepath );
}
destroySocket( );
return ret;
}
public int uploadFirmware( String address, String filepath )
{
int ret = 0;
if ( connectSocket( address ) ) {
TDLog.LogFile( "Firmware upload: socket is ready " );
ret = mProtocol.uploadFirmware( filepath );
}
destroySocket( );
return ret;
}
};