下面列出了怎么用android.hardware.usb.UsbRequest的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public boolean queue(ByteBuffer buffer, int length)
{
Field usbRequestBuffer;
Field usbRequestLength;
try
{
usbRequestBuffer = UsbRequest.class.getDeclaredField(usbRqBufferField);
usbRequestLength = UsbRequest.class.getDeclaredField(usbRqLengthField);
usbRequestBuffer.setAccessible(true);
usbRequestLength.setAccessible(true);
usbRequestBuffer.set(this, buffer);
usbRequestLength.set(this, length);
} catch (Exception e)
{
throw new RuntimeException(e);
}
return super.queue(buffer, length);
}
@Override
public void open(UsbDeviceConnection connection) throws IOException {
if (mConnection != null) {
throw new IOException("Already open");
}
mConnection = connection;
try {
openInt(connection);
if (mReadEndpoint == null || mWriteEndpoint == null) {
throw new IOException("Could not get read & write endpoints");
}
mUsbRequest = new UsbRequest();
mUsbRequest.initialize(mConnection, mReadEndpoint);
} catch(Exception e) {
close();
throw e;
}
}
private void messageWrite(final Message msg) {
final int msg_size = msg.getSerializedSize();
final String msg_name = msg.getClass().getSimpleName();
final int msg_id = MessageType.valueOf("MessageType_" + msg_name).getNumber();
Log.d(TAG, String.format("Got message: %s (%d bytes)", msg_name, msg_size));
final ByteBuffer data = ByteBuffer.allocate(32768);
data.put((byte)'#');
data.put((byte)'#');
data.put((byte)((msg_id >> 8) & 0xFF));
data.put((byte)(msg_id & 0xFF));
data.put((byte)((msg_size >> 24) & 0xFF));
data.put((byte)((msg_size >> 16) & 0xFF));
data.put((byte)((msg_size >> 8) & 0xFF));
data.put((byte)(msg_size & 0xFF));
data.put(msg.toByteArray());
while (data.position() % 63 > 0)
data.put((byte)0);
final UsbRequest request = new UsbRequest();
request.initialize(mConn, mWriteEndpoint);
final int chunks = data.position() / 63;
Log.d(TAG, String.format("Writing %d chunks", chunks));
data.rewind();
for (int i = 0; i < chunks; ++i) {
final byte[] buffer = new byte[64];
buffer[0] = (byte)'?';
data.get(buffer, 1, 63);
//logData("chunk:", buffer);
request.queue(ByteBuffer.wrap(buffer), 64);
mConn.requestWait();
}
request.close();
}
@Override
public byte[] exchange(byte[] command) {
ByteArrayOutputStream response = new ByteArrayOutputStream();
byte[] responseData = null;
int offset = 0;
if (debug) {
Timber.d("=> %s", Dump.dump(command));
}
command = LedgerHelper.wrapCommandAPDU(LEDGER_DEFAULT_CHANNEL, command, HID_BUFFER_SIZE);
UsbRequest requestOut = new UsbRequest();
requestOut.initialize(connection, out);
while (offset != command.length) {
int blockSize = (command.length - offset > HID_BUFFER_SIZE ? HID_BUFFER_SIZE : command.length - offset);
System.arraycopy(command, offset, transferBuffer, 0, blockSize);
requestOut.queue(ByteBuffer.wrap(transferBuffer), HID_BUFFER_SIZE);
connection.requestWait();
offset += blockSize;
}
requestOut.close();
ByteBuffer responseBuffer = ByteBuffer.allocate(HID_BUFFER_SIZE);
UsbRequest requestIn = new UsbRequest();
requestIn.initialize(connection, in);
while ((responseData = LedgerHelper.unwrapResponseAPDU(LEDGER_DEFAULT_CHANNEL, response.toByteArray(), HID_BUFFER_SIZE)) == null) {
responseBuffer.clear();
requestIn.queue(responseBuffer, HID_BUFFER_SIZE);
connection.requestWait();
responseBuffer.rewind();
responseBuffer.get(transferBuffer, 0, HID_BUFFER_SIZE);
response.write(transferBuffer, 0, HID_BUFFER_SIZE);
}
requestIn.close();
if (debug) {
Timber.d("<= %s", Dump.dump(responseData));
}
return responseData;
}
private void messageWrite(final Message msg) {
final int msg_size = msg.getSerializedSize();
final String msg_name = msg.getClass().getSimpleName();
final int msg_id = MessageType.valueOf("MessageType_" + msg_name).getNumber();
Log.i(TAG, String.format("Got message: %s (%d bytes)", msg_name, msg_size));
final ByteBuffer data = ByteBuffer.allocate(32768);
data.put((byte)'#');
data.put((byte)'#');
data.put((byte)((msg_id >> 8) & 0xFF));
data.put((byte)(msg_id & 0xFF));
data.put((byte)((msg_size >> 24) & 0xFF));
data.put((byte)((msg_size >> 16) & 0xFF));
data.put((byte)((msg_size >> 8) & 0xFF));
data.put((byte)(msg_size & 0xFF));
data.put(msg.toByteArray());
while (data.position() % 63 > 0)
data.put((byte)0);
final UsbRequest request = new UsbRequest();
request.initialize(mConn, mWriteEndpoint);
final int chunks = data.position() / 63;
Log.i(TAG, String.format("Writing %d chunks", chunks));
data.rewind();
for (int i = 0; i < chunks; ++i) {
final byte[] buffer = new byte[64];
buffer[0] = (byte)'?';
data.get(buffer, 1, 63);
logData("chunk:", buffer);
request.queue(ByteBuffer.wrap(buffer), 64);
mConn.requestWait();
}
request.close();
}
/**
* Constructs a UsbMidiDeviceAndroid.
* @param manager
* @param device The USB device which this object is assocated with.
*/
UsbMidiDeviceAndroid(UsbManager manager, UsbDevice device) {
mConnection = manager.openDevice(device);
mEndpointMap = new SparseArray<UsbEndpoint>();
mRequestMap = new HashMap<UsbEndpoint, UsbRequest>();
mHandler = new Handler();
mUsbDevice = device;
mIsClosed = false;
mHasInputThread = false;
mNativePointer = 0;
for (int i = 0; i < device.getInterfaceCount(); ++i) {
UsbInterface iface = device.getInterface(i);
if (iface.getInterfaceClass() != UsbConstants.USB_CLASS_AUDIO
|| iface.getInterfaceSubclass() != MIDI_SUBCLASS) {
continue;
}
mConnection.claimInterface(iface, true);
for (int j = 0; j < iface.getEndpointCount(); ++j) {
UsbEndpoint endpoint = iface.getEndpoint(j);
if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
mEndpointMap.put(endpoint.getEndpointNumber(), endpoint);
}
}
}
// Start listening for input endpoints.
// This function will create and run a thread if there is USB-MIDI endpoints in the
// device. Note that because UsbMidiDevice is shared among all tabs and the thread
// will be terminated when the device is disconnected, at most one thread can be created
// for each connected USB-MIDI device.
startListen(device);
}
/**
* Closes the device connection.
*/
@CalledByNative
void close() {
mEndpointMap.clear();
for (UsbRequest request : mRequestMap.values()) {
request.close();
}
mRequestMap.clear();
mConnection.close();
mNativePointer = 0;
mIsClosed = true;
}
@Override
public boolean open()
{
boolean ret = openCH34X();
if(ret)
{
// Initialize UsbRequest
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
restartWorkingThread();
restartWriteThread();
// Create Flow control thread but it will only be started if necessary
createFlowControlThread();
// Pass references to the threads
setThreadsParams(requestIN, outEndpoint);
asyncMode = true;
isOpen = true;
return true;
}else
{
isOpen = false;
return false;
}
}
@Override
public void doRun()
{
UsbRequest request = connection.requestWait();
if(request != null && request.getEndpoint().getType() == UsbConstants.USB_ENDPOINT_XFER_BULK
&& request.getEndpoint().getDirection() == UsbConstants.USB_DIR_IN)
{
byte[] data = serialBuffer.getDataReceived();
// FTDI devices reserves two first bytes of an IN endpoint with info about
// modem and Line.
if(isFTDIDevice())
{
((FTDISerialDevice) usbSerialDevice).ftdiUtilities.checkModemStatus(data); //Check the Modem status
serialBuffer.clearReadBuffer();
if(data.length > 2)
{
data = FTDISerialDevice.adaptArray(data);
onReceivedData(data);
}
}else
{
// Clear buffer, execute the callback
serialBuffer.clearReadBuffer();
onReceivedData(data);
}
// Queue a new request
requestIN.queue(serialBuffer.getReadBuffer(), SerialBuffer.DEFAULT_READ_BUFFER_SIZE);
}
}
protected void setThreadsParams(UsbRequest request, UsbEndpoint endpoint)
{
writeThread.setUsbEndpoint(endpoint);
if(mr1Version)
{
workerThread.setUsbRequest(request);
}else
{
readThread.setUsbEndpoint(request.getEndpoint());
}
}
@Override
public boolean open()
{
boolean ret = openCP2102();
if(ret)
{
// Initialize UsbRequest
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
restartWorkingThread();
restartWriteThread();
// Create Flow control thread but it will only be started if necessary
createFlowControlThread();
// Pass references to the threads
setThreadsParams(requestIN, outEndpoint);
asyncMode = true;
isOpen = true;
return true;
}else
{
isOpen = false;
return false;
}
}
@Override
public boolean open()
{
boolean ret = openPL2303();
if(ret)
{
// Initialize UsbRequest
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
restartWorkingThread();
restartWriteThread();
// Pass references to the threads
setThreadsParams(requestIN, outEndpoint);
asyncMode = true;
isOpen = true;
return true;
}else
{
isOpen = false;
return false;
}
}
@Override
public boolean open()
{
boolean ret = openCDC();
if(ret)
{
// Initialize UsbRequest
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
restartWorkingThread();
restartWriteThread();
// Pass references to the threads
setThreadsParams(requestIN, outEndpoint);
asyncMode = true;
isOpen = true;
return true;
}else
{
isOpen = false;
return false;
}
}
@Override
public boolean open()
{
boolean ret = openFTDI();
if(ret)
{
// Initialize UsbRequest
UsbRequest requestIN = new SafeUsbRequest();
requestIN.initialize(connection, inEndpoint);
// Restart the working thread if it has been killed before and get and claim interface
restartWorkingThread();
restartWriteThread();
// Pass references to the threads
setThreadsParams(requestIN, outEndpoint);
asyncMode = true;
isOpen = true;
return true;
}else
{
isOpen = false;
return false;
}
}
@Override
public int read(final byte[] dest, final int timeout) throws IOException {
if(mConnection == null) {
throw new IOException("Connection closed");
}
final int nread;
if (timeout != 0) {
// bulkTransfer will cause data loss with short timeout + high baud rates + continuous transfer
// https://stackoverflow.com/questions/9108548/android-usb-host-bulktransfer-is-losing-data
// but mConnection.requestWait(timeout) available since Android 8.0 es even worse,
// as it crashes with short timeout, e.g.
// A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x276a in tid 29846 (pool-2-thread-1), pid 29618 (.usbserial.test)
// /system/lib64/libusbhost.so (usb_request_wait+192)
// /system/lib64/libandroid_runtime.so (android_hardware_UsbDeviceConnection_request_wait(_JNIEnv*, _jobject*, long)+84)
// data loss / crashes were observed with timeout up to 200 msec
int readMax = Math.min(dest.length, MAX_READ_SIZE);
nread = mConnection.bulkTransfer(mReadEndpoint, dest, readMax, timeout);
} else {
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!mUsbRequest.queue(buf, dest.length)) {
throw new IOException("Queueing USB request failed");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Waiting for USB request failed");
}
nread = buf.position();
}
if (nread > 0) {
return readFilter(dest, nread);
} else {
return 0;
}
}
public UsbRequest createInRequest() {
UsbRequest r = new UsbRequest();
r.initialize(connection, bulkIn);
return r;
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt, timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, null);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(null, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, null);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(null, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
public byte[] exchange(byte tag, byte[] command) throws IOException {
ByteArrayOutputStream response = new ByteArrayOutputStream();
byte[] responseData = null;
int offset = 0;
int responseSize;
if (debug) {
Log.d(LOG_TAG, "=> " + Dump.dump(command));
}
command = helper.wrapCommandAPDU(tag, command, HID_BUFFER_SIZE);
UsbRequest requestWrite = new UsbRequest();
if (!requestWrite.initialize(connection, out)) {
throw new IOException();
}
while (offset != command.length) {
int blockSize = (command.length - offset > HID_BUFFER_SIZE ? HID_BUFFER_SIZE : command.length - offset);
System.arraycopy(command, offset, transferBuffer, 0, blockSize);
if (debug) {
Log.d(LOG_TAG, "wire => " + Dump.dump(transferBuffer));
}
if (!requestWrite.queue(ByteBuffer.wrap(transferBuffer), HID_BUFFER_SIZE)) {
requestWrite.close();
throw new IOException();
}
connection.requestWait();
offset += blockSize;
}
ByteBuffer responseBuffer = ByteBuffer.allocate(HID_BUFFER_SIZE);
UsbRequest requestRead = new UsbRequest();
if (!requestRead.initialize(connection, in)) {
requestRead.close();
requestWrite.close();
throw new IOException();
}
while ((responseData = helper.unwrapResponseAPDU(tag, response.toByteArray(), HID_BUFFER_SIZE)) == null) {
responseBuffer.clear();
if (!requestRead.queue(responseBuffer, HID_BUFFER_SIZE)) {
requestRead.close();
requestWrite.close();
throw new IOException();
}
connection.requestWait();
responseBuffer.rewind();
responseBuffer.get(transferBuffer, 0, HID_BUFFER_SIZE);
if (debug) {
Log.d(LOG_TAG, "wire <= " + Dump.dump(transferBuffer));
}
response.write(transferBuffer, 0, HID_BUFFER_SIZE);
}
if (debug) {
Log.d(LOG_TAG, "<= " + Dump.dump(responseData));
}
requestWrite.close();
requestRead.close();
return responseData;
}
public int read(byte[] dest, int timeoutMillis, UsbDeviceConnection connection) throws IOException {
if (false) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(connection, null);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = connection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = connection.bulkTransfer(null, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}
@Override
public int read(byte[] dest, int timeoutMillis) throws IOException {
if (mEnableAsyncReads) {
final UsbRequest request = new UsbRequest();
try {
request.initialize(mConnection, mReadEndpoint);
final ByteBuffer buf = ByteBuffer.wrap(dest);
if (!request.queue(buf, dest.length)) {
throw new IOException("Error queueing request.");
}
final UsbRequest response = mConnection.requestWait();
if (response == null) {
throw new IOException("Null response");
}
final int nread = buf.position();
if (nread > 0) {
//Log.d(TAG, HexDump.dumpHexString(dest, 0, Math.min(32, dest.length)));
return nread;
} else {
return 0;
}
} finally {
request.close();
}
}
final int numBytesRead;
synchronized (mReadBufferLock) {
int readAmt = Math.min(dest.length, mReadBuffer.length);
numBytesRead = mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
timeoutMillis);
if (numBytesRead < 0) {
// This sucks: we get -1 on timeout, not 0 as preferred.
// We *should* use UsbRequest, except it has a bug/api oversight
// where there is no way to determine the number of bytes read
// in response :\ -- http://b.android.com/28023
if (timeoutMillis == Integer.MAX_VALUE) {
// Hack: Special case "~infinite timeout" as an error.
return -1;
}
return 0;
}
System.arraycopy(mReadBuffer, 0, dest, 0, numBytesRead);
}
return numBytesRead;
}