views:

42

answers:

1

Hello everyone,

we've got some legacy hardware which connects to cell phones over Bluetooth using the DUN profile. It then issues AT commands to read SMS for monitoring purposes.

Android phones do not support AT over DUN. That's why I'm writing this application. The problem is: while the legacy hardware will connect to the phone, it will not accept my responses to its commands. Specifically, it seems not to accept my answer to the AT+CGMI command. I assume there is something wrong with my usage of the CR and LF control characters, but I can't figure out what's going on.

Here's an example chat log:

10-14 14:14:49.674: DEBUG/PROG(2663): Server started, object is android.bluetooth.BluetoothServerSocket@44f102f8
10-14 14:17:07.264: DEBUG/PROG(2663): From Device:ATE0
10-14 14:17:07.264: DEBUG/PROG(2663): To Device: 
10-14 14:17:07.264: DEBUG/PROG(2663): OK
10-14 14:17:07.868: DEBUG/PROG(2663): From Device:ATE0
10-14 14:17:07.868: DEBUG/PROG(2663): To Device: 
10-14 14:17:07.868: DEBUG/PROG(2663): OK
10-14 14:17:10.774: DEBUG/PROG(2663): From Device:AT+CGMI
10-14 14:17:10.774: DEBUG/PROG(2663): To Device: 
10-14 14:17:10.774: DEBUG/PROG(2663): "Sony Ericsson"
10-14 14:17:10.774: DEBUG/PROG(2663): 
10-14 14:17:10.774: DEBUG/PROG(2663): OK
10-14 14:17:11.434: DEBUG/PROG(2663): From Device:ATE0
10-14 14:17:11.434: DEBUG/PROG(2663): To Device: 
10-14 14:17:11.434: DEBUG/PROG(2663): OK
10-14 14:17:12.025: DEBUG/PROG(2663): From Device:ATE0
10-14 14:17:12.025: DEBUG/PROG(2663): To Device: 
10-14 14:17:12.025: DEBUG/PROG(2663): OK
10-14 14:17:14.827: DEBUG/PROG(2663): From Device:AT+CGMI
10-14 14:17:14.827: DEBUG/PROG(2663): To Device: 
10-14 14:17:14.827: DEBUG/PROG(2663): "Sony Ericsson"
10-14 14:17:14.827: DEBUG/PROG(2663): 
10-14 14:17:14.827: DEBUG/PROG(2663): OK
10-14 14:17:15.454: DEBUG/PROG(2663): From Device:ATE0
10-14 14:17:15.454: DEBUG/PROG(2663): To Device: 
10-14 14:17:15.454: DEBUG/PROG(2663): OK
10-14 14:17:16.084: DEBUG/PROG(2663): From Device:ATE0
10-14 14:17:16.084: DEBUG/PROG(2663): To Device: 
10-14 14:17:16.084: DEBUG/PROG(2663): OK
10-14 14:17:18.444: DEBUG/PROG(2663): IOException: all aboard the failboat!
10-14 14:17:18.444: DEBUG/PROG(2663): java.io.IOException: Connection reset by peer
10-14 14:17:18.444: DEBUG/PROG(2663):     at android.bluetooth.BluetoothSocket.readNative(Native Method)
10-14 14:17:18.444: DEBUG/PROG(2663):     at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:307)
10-14 14:17:18.444: DEBUG/PROG(2663):     at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:96)
10-14 14:17:18.444: DEBUG/PROG(2663):     at java.io.InputStreamReader.read(InputStreamReader.java:275)
10-14 14:17:18.444: DEBUG/PROG(2663):     at java.io.BufferedReader.fillBuf(BufferedReader.java:155)
10-14 14:17:18.444: DEBUG/PROG(2663):     at java.io.BufferedReader.readLine(BufferedReader.java:404)

The exception happens as the device resets the connection.

Here's some code:

private static final String REPLY_OK = "\r\nOK\r\n";
private static final String REPLY_MANUFACTURER = "\r\n\"Sony Ericsson\"\r\n\r\nOK\r\n";
private static final String ECHO_OFF = "ATE0";
private static final String GET_MANUFACTURER = "AT+CGMI";
public static String handleCommand(String command) {

if (command.equals(ECHO_OFF)) {
   return REPLY_OK;
} else if (command.equals(GET_MANUFACTURER)) {
   return REPLY_MANUFACTURER;
}
// base case
return REPLY_OK;
}
// bts is a BluetoothSocket instance
OutputStream out = this.bts.getOutputStream();
InputStream is = this.bts.getInputStream();
InputStreamReader isr  = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String currentLine = null;
while ((currentLine = br.readLine()) != null) {
    Log.d(LOGTAG, "From Device:" +  currentLine);
    String response = handleCommand(currentLine);
    Log.d(LOGTAG, "To Device: " + response);
    out.write(response.getBytes("ASCII"));
    //out.flush();
}
A: 

How about turning things around and using the android device to emulate the legacy hardware device, connect to a legacy bluetooth phone, and do a hexdump of exactly what that phone gives in response?

Or maybe you could even use the android phone to make a sort of man-in-the-middle proxy and record and hexdump the whole exchange?

Chris Stratton
Good catch. I've got a N95. I'll connect from my laptop to the DUN profile on the N95 and dump what's going on.
MHaas
Yeah.. I hooked up my Laptop over rfcomm and immediately saw the problem. Kids, be smart about using BufferedReader::readLine().Apparently, that only returned when the legacy device was sending the second command. So it needed an additional character after the command sent by the device.I'm now read()'ing from the BufferedReader instead and do my own line splitting. Works like a charm.Thanks again!
MHaas