1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-02 10:24:11 +01:00

AndroidGCS: Get HID working properly for PipX

This commit is contained in:
James Cotton 2012-08-11 02:29:26 -05:00
parent de2f6a64e2
commit 5addc15f60
3 changed files with 178 additions and 71 deletions

View File

@ -10,6 +10,8 @@ import java.nio.ByteBuffer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import junit.framework.Assert;
import org.openpilot.uavtalk.UAVObjectManager; import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk; import org.openpilot.uavtalk.UAVTalk;
@ -31,10 +33,9 @@ import android.util.Log;
public class HidUAVTalk { public class HidUAVTalk {
private static final String TAG = HidUAVTalk.class.getSimpleName(); private static final String TAG = HidUAVTalk.class.getSimpleName();
public static int LOGLEVEL = 2; public static int LOGLEVEL = 0;
public static boolean DEBUG = LOGLEVEL > 1; public static boolean WARN = LOGLEVEL > 1;
public static boolean WARN = LOGLEVEL > 0; public static boolean DEBUG = LOGLEVEL > 0;
Service hostDisplayActivity; Service hostDisplayActivity;
@ -377,44 +378,24 @@ public class HidUAVTalk {
return true; return true;
} }
private int byteToInt(byte b) { return b & 0x000000ff; }
private class TalkInputStream extends InputStream { private class TalkInputStream extends InputStream {
ByteBuffer data = null;
ByteFifo data = new ByteFifo();
boolean stopped = false; boolean stopped = false;
private static final int SIZE = 1024;
int readPosition = 0;
TalkInputStream() { TalkInputStream() {
data = ByteBuffer.allocate(SIZE);
data.limit(SIZE);
data.clear();
} }
@Override @Override
public int read() throws IOException { public int read() {
while(!stopped) {
synchronized(data) {
if(data.capacity() > readPosition)
return data.get(readPosition++);
else
try { try {
data.wait(50); return data.getByteBlocking();
} catch (InterruptedException e) { } catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} return -1;
}
throw new IOException();
}
void compress() {
if (readPosition > (data.capacity() * 3.0 / 4.0)) {
synchronized(data) {
data.position(readPosition);
data.compact();
readPosition = 0;
if (DEBUG) Log.d(TAG, "Compact() Capacity: " + data.capacity() + " Position: " + data.position() + " Available: " + data.remaining() + " Limit: " + data.limit());
}
}
} }
public void stop() { public void stop() {
@ -422,42 +403,89 @@ public class HidUAVTalk {
} }
public void put(byte b) { public void put(byte b) {
synchronized(data) {
if(data.hasRemaining()) {
data.compact();
data.put(b);
data.notify();
}
}
} }
public void write(byte[] b) { public void write(byte[] b) {
synchronized(data) {
int available = data.remaining();
if(available >= b.length) {
if (DEBUG) Log.d(TAG, "Size: " + b.length + " Capacity: " + data.capacity() + " Position: " + data.position() + " Available: " + available + " Limit: " + data.limit());
//data.compact();
data.put(b); data.put(b);
data.notify();
}
}
} }
}; };
private final TalkInputStream inStream = new TalkInputStream(); private final TalkInputStream inStream = new TalkInputStream();
private class ByteFifo {
//! The maximum size of the fifo
private final int MAX_SIZE = 1024;
//! The number of bytes in the buffer
private int size = 0;
//! Internal buffer
private final ByteBuffer buf;
ByteFifo() {
buf = ByteBuffer.allocate(MAX_SIZE);
size = 0;
}
public boolean put(byte[] dat) {
if ((size + dat.length) > MAX_SIZE)
return false;
// Place data at the end of the buffer
synchronized(buf) {
buf.position(size);
buf.put(dat);
size = size + dat.length;
buf.notify();
}
return true;
}
public byte[] get(int size) throws InterruptedException {
size = Math.min(size, this.size);
if (size > 0) {
synchronized(buf) {
byte[] dst = new byte[size];
buf.position(0);
buf.get(dst,0,size);
buf.compact();
this.size = this.size - size;
Assert.assertEquals(this.size, buf.position());
buf.wait();
}
}
return new byte[0];
}
public int getByteBlocking() throws InterruptedException {
synchronized(buf) {
if (size == 0)
buf.wait();
int val = byteToInt(buf.get(0));
buf.position(1);
buf.compact();
size--;
return val;
}
}
}
/** /**
* Gets a report from HID, extract the meaningful data and push * Gets a report from HID, extract the meaningful data and push
* it to the input stream * it to the input stream
*/ */
UsbRequest readRequest = null;
public int readData() { public int readData() {
int bufferDataLength = usbEndpointRead.getMaxPacketSize(); int bufferDataLength = usbEndpointRead.getMaxPacketSize();
ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1); ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1);
UsbRequest request = new UsbRequest();
request.initialize(connectionRead, usbEndpointRead);
if(readRequest == null) {
readRequest = new UsbRequest();
readRequest.initialize(connectionRead, usbEndpointRead);
}
// queue a request on the interrupt endpoint // queue a request on the interrupt endpoint
if(!request.queue(buffer, bufferDataLength)) { if(!readRequest.queue(buffer, bufferDataLength)) {
if (DEBUG) Log.d(TAG, "Failed to queue request"); if (DEBUG) Log.d(TAG, "Failed to queue request");
return 0; return 0;
} }
@ -466,7 +494,7 @@ public class HidUAVTalk {
int dataSize; int dataSize;
// wait for status event // wait for status event
if (connectionRead.requestWait() == request) { if (connectionRead.requestWait() == readRequest) {
// Packet format: // Packet format:
// 0: Report ID (1) // 0: Report ID (1)
// 1: Number of valid bytes // 1: Number of valid bytes
@ -482,21 +510,30 @@ public class HidUAVTalk {
byte[] dst = new byte[dataSize]; byte[] dst = new byte[dataSize];
buffer.position(2); buffer.position(2);
buffer.get(dst, 0, dataSize); buffer.get(dst, 0, dataSize);
if (DEBUG) Log.d(TAG, "Entered read");
inStream.write(dst); inStream.write(dst);
if (DEBUG) Log.d(TAG, "Got read: " + dataSize + " bytes"); if (DEBUG) Log.d(TAG, "Got read: " + dataSize + " bytes");
} }
} else } else
return 0; return 0;
if(false) {
readRequest.cancel();
readRequest.close();
}
return dataSize; return dataSize;
} }
private class TalkOutputStream extends OutputStream { private class TalkOutputStream extends OutputStream {
ByteBuffer data = ByteBuffer.allocate(128); ByteBuffer data = ByteBuffer.allocate(1024);
boolean stopped = false; boolean stopped = false;
int writePosition = 0;
public int read() throws IOException { public int read() throws IOException {
if (stopped) if (!stopped)
while(!stopped) { while(!stopped) {
synchronized(data) { synchronized(data) {
if(data.hasRemaining()) if(data.hasRemaining())
@ -523,6 +560,7 @@ public class HidUAVTalk {
if (stopped) if (stopped)
throw new IOException(); throw new IOException();
synchronized(data) { synchronized(data) {
data.put((byte) oneByte); data.put((byte) oneByte);
data.notify(); data.notify();
} }
@ -534,37 +572,88 @@ public class HidUAVTalk {
throw new IOException(); throw new IOException();
synchronized(data) { synchronized(data) {
//data.put(b); // Move the cursor to the end of the byte array to append
data.position(writePosition);
if (b.length < data.remaining()) {
data.put(b);
writePosition = data.position();
}
data.notify(); data.notify();
} }
} }
public void packetizeData() {
ByteBuffer packet;
synchronized(data) {
// Determine how much data to put in the packet
int size = Math.min(writePosition, MAX_HID_PACKET_SIZE - 2);
if (size <= 0)
return;
// Format into a HID packet
packet = ByteBuffer.allocate(MAX_HID_PACKET_SIZE);
packet.put(0,(byte) 2); // Report ID
packet.put(1,(byte) size); // The number of bytes of data
data.position(0);
data.get(packet.array(), 2, size); // Copy data into the other array
// Remove that data from the write buffer
data.compact();
writePosition -= size;
}
WriteToDevice(packet);
}
}; };
private final TalkOutputStream outStream = new TalkOutputStream(); private final TalkOutputStream outStream = new TalkOutputStream();
private static final int MAX_HID_PACKET_SIZE = 64;
/**
* Send a packet or wait for data to be available
*/
public void send() {
synchronized(outStream.data){
if (outStream.writePosition > 0)
outStream.packetizeData();
else {
outStream.data.notify();
outStream.packetizeData();
}
}
}
UsbRequest writeRequest = null;
boolean WriteToDevice(ByteBuffer DataToSend) { boolean WriteToDevice(ByteBuffer DataToSend) {
//The report must be formatted correctly for the device being connected to. On some devices, this requires that a specific value must be the first byte in the report. This can be followed by the length of the data in the report. This format is determined by the device, and isn't specified here. //The report must be formatted correctly for the device being connected to. On some devices, this requires that a specific value must be the first byte in the report. This can be followed by the length of the data in the report. This format is determined by the device, and isn't specified here.
int bufferDataLength = usbEndpointWrite.getMaxPacketSize(); int bufferDataLength = usbEndpointWrite.getMaxPacketSize();
ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1); ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1);
UsbRequest request = new UsbRequest();
if(writeRequest == null) {
writeRequest = new UsbRequest();
writeRequest.initialize(connectionWrite, usbEndpointWrite);
}
buffer.put(DataToSend); buffer.put(DataToSend);
request.initialize(connectionWrite, usbEndpointWrite); writeRequest.queue(buffer, bufferDataLength);
request.queue(buffer, bufferDataLength);
try try
{ {
if (request.equals(connectionWrite.requestWait())) if (writeRequest.equals(connectionWrite.requestWait()))
{
return true; return true;
} }
}
catch (Exception ex) catch (Exception ex)
{ {
// An exception has occured // An exception has occured
return false; return false;
} }
if (false) {
writeRequest.cancel();
writeRequest.close();
}
return false; return false;
} }

View File

@ -523,11 +523,6 @@ public class OPTelemetryService extends Service {
return; return;
} }
hid.readData();
hid.readData();
hid.readData();
hid.readData();
uavTalk = hid.getUavtalk(); uavTalk = hid.getUavtalk();
tel = new Telemetry(uavTalk, objMngr); tel = new Telemetry(uavTalk, objMngr);
mon = new TelemetryMonitor(objMngr,tel); mon = new TelemetryMonitor(objMngr,tel);
@ -549,11 +544,30 @@ public class OPTelemetryService extends Service {
public void run() { public void run() {
while(!terminate) { while(!terminate) {
hid.readData(); hid.readData();
hid.send();
} }
Log.e(TAG, "TERMINATED");
} }
}; };
t.start(); t.start();
// Read data from HID and push it ont the UAVTalk input stream
Thread t2 = new Thread(this) {
@Override
public void run() {
while(!terminate) {
hid.send();
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
//t2.start();
// Process any bytes that have been pushed onto the UAVTalk stream // Process any bytes that have been pushed onto the UAVTalk stream
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop"); if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
while( !terminate ) { while( !terminate ) {
@ -584,6 +598,8 @@ public class OPTelemetryService extends Service {
e.printStackTrace(); e.printStackTrace();
} }
hid.disconnect(); hid.disconnect();
// Shut down all the attached // Shut down all the attached

View File

@ -38,7 +38,7 @@ import android.util.Log;
public class UAVTalk { public class UAVTalk {
static final String TAG = "UAVTalk"; static final String TAG = "UAVTalk";
public static int LOGLEVEL = 4; public static int LOGLEVEL = 0;
public static boolean VERBOSE = LOGLEVEL > 3; public static boolean VERBOSE = LOGLEVEL > 3;
public static boolean WARN = LOGLEVEL > 2; public static boolean WARN = LOGLEVEL > 2;
public static boolean DEBUG = LOGLEVEL > 1; public static boolean DEBUG = LOGLEVEL > 1;
@ -227,6 +227,8 @@ public class UAVTalk {
//inStream.wait(); //inStream.wait();
val = inStream.read(); val = inStream.read();
if (VERBOSE) Log.v(TAG, "Read: " + val);
if (val == -1) { if (val == -1) {
return false; return false;
} }
@ -357,7 +359,7 @@ public class UAVTalk {
rxCS = updateCRC(rxCS, rxbyte); rxCS = updateCRC(rxCS, rxbyte);
if ((rxbyte & TYPE_MASK) != TYPE_VER) { if ((rxbyte & TYPE_MASK) != TYPE_VER) {
Log.e(TAG, "Unknown UAVTalk type:" + rxbyte); if (ERROR) Log.e(TAG, "Unknown UAVTalk type:" + rxbyte);
rxState = RxStateType.STATE_SYNC; rxState = RxStateType.STATE_SYNC;
break; break;
} }