| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.adb; |
| |
| import android.hardware.usb.UsbRequest; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.ByteOrder; |
| |
| /* This class encapsulates and adb command packet */ |
| public class AdbMessage { |
| |
| // command names |
| public static final int A_SYNC = 0x434e5953; |
| public static final int A_CNXN = 0x4e584e43; |
| public static final int A_OPEN = 0x4e45504f; |
| public static final int A_OKAY = 0x59414b4f; |
| public static final int A_CLSE = 0x45534c43; |
| public static final int A_WRTE = 0x45545257; |
| |
| // ADB protocol version |
| public static final int A_VERSION = 0x01000000; |
| |
| public static final int MAX_PAYLOAD = 4096; |
| |
| private final ByteBuffer mMessageBuffer; |
| private final ByteBuffer mDataBuffer; |
| |
| public AdbMessage() { |
| mMessageBuffer = ByteBuffer.allocate(24); |
| mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD); |
| mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN); |
| mDataBuffer.order(ByteOrder.LITTLE_ENDIAN); |
| } |
| |
| // sets the fields in the command header |
| public void set(int command, int arg0, int arg1, byte[] data) { |
| mMessageBuffer.putInt(0, command); |
| mMessageBuffer.putInt(4, arg0); |
| mMessageBuffer.putInt(8, arg1); |
| mMessageBuffer.putInt(12, (data == null ? 0 : data.length)); |
| mMessageBuffer.putInt(16, (data == null ? 0 : checksum(data))); |
| mMessageBuffer.putInt(20, command ^ 0xFFFFFFFF); |
| if (data != null) { |
| mDataBuffer.put(data, 0, data.length); |
| } |
| } |
| |
| public void set(int command, int arg0, int arg1) { |
| set(command, arg0, arg1, (byte[])null); |
| } |
| public void set(int command, int arg0, int arg1, String data) { |
| // add trailing zero |
| data += "\0"; |
| set(command, arg0, arg1, data.getBytes()); |
| } |
| |
| // returns the command's message ID |
| public int getCommand() { |
| return mMessageBuffer.getInt(0); |
| } |
| |
| // returns command's first argument |
| public int getArg0() { |
| return mMessageBuffer.getInt(4); |
| } |
| |
| // returns command's second argument |
| public int getArg1() { |
| return mMessageBuffer.getInt(8); |
| } |
| |
| // returns command's data buffer |
| public ByteBuffer getData() { |
| return mDataBuffer; |
| } |
| |
| // returns command's data length |
| public int getDataLength() { |
| return mMessageBuffer.getInt(12); |
| } |
| |
| // returns command's data as a string |
| public String getDataString() { |
| int length = getDataLength(); |
| if (length == 0) return null; |
| // trim trailing zero |
| return new String(mDataBuffer.array(), 0, length - 1); |
| } |
| |
| |
| public boolean write(AdbDevice device) { |
| synchronized (device) { |
| UsbRequest request = device.getOutRequest(); |
| request.setClientData(this); |
| if (request.queue(mMessageBuffer, 24)) { |
| int length = getDataLength(); |
| if (length > 0) { |
| request = device.getOutRequest(); |
| request.setClientData(this); |
| if (request.queue(mDataBuffer, length)) { |
| return true; |
| } else { |
| device.releaseOutRequest(request); |
| return false; |
| } |
| } |
| return true; |
| } else { |
| device.releaseOutRequest(request); |
| return false; |
| } |
| } |
| } |
| |
| public boolean readCommand(UsbRequest request) { |
| request.setClientData(this); |
| return request.queue(mMessageBuffer, 24); |
| } |
| |
| public boolean readData(UsbRequest request, int length) { |
| request.setClientData(this); |
| return request.queue(mDataBuffer, length); |
| } |
| |
| private static String extractString(ByteBuffer buffer, int offset, int length) { |
| byte[] bytes = new byte[length]; |
| for (int i = 0; i < length; i++) { |
| bytes[i] = buffer.get(offset++); |
| } |
| return new String(bytes); |
| } |
| |
| @Override |
| public String toString() { |
| String commandName = extractString(mMessageBuffer, 0, 4); |
| int dataLength = getDataLength(); |
| String result = "Adb Message: " + commandName + " arg0: " + getArg0() + |
| " arg1: " + getArg1() + " dataLength: " + dataLength; |
| if (dataLength > 0) { |
| result += (" data: \"" + getDataString() + "\""); |
| } |
| return result; |
| } |
| |
| private static int checksum(byte[] data) { |
| int result = 0; |
| for (int i = 0; i < data.length; i++) { |
| int x = data[i]; |
| // dang, no unsigned ints in java |
| if (x < 0) x += 256; |
| result += x; |
| } |
| return result; |
| } |
| } |