1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.adb; 18 19 import android.hardware.usb.UsbRequest; 20 21 import java.nio.ByteBuffer; 22 import java.nio.ByteOrder; 23 24 /* This class encapsulates and adb command packet */ 25 public class AdbMessage { 26 27 // command names 28 public static final int A_SYNC = 0x434e5953; 29 public static final int A_CNXN = 0x4e584e43; 30 public static final int A_OPEN = 0x4e45504f; 31 public static final int A_OKAY = 0x59414b4f; 32 public static final int A_CLSE = 0x45534c43; 33 public static final int A_WRTE = 0x45545257; 34 35 // ADB protocol version 36 public static final int A_VERSION = 0x01000000; 37 38 public static final int MAX_PAYLOAD = 4096; 39 40 private final ByteBuffer mMessageBuffer; 41 private final ByteBuffer mDataBuffer; 42 AdbMessage()43 public AdbMessage() { 44 mMessageBuffer = ByteBuffer.allocate(24); 45 mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD); 46 mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN); 47 mDataBuffer.order(ByteOrder.LITTLE_ENDIAN); 48 } 49 50 // sets the fields in the command header set(int command, int arg0, int arg1, byte[] data)51 public void set(int command, int arg0, int arg1, byte[] data) { 52 mMessageBuffer.putInt(0, command); 53 mMessageBuffer.putInt(4, arg0); 54 mMessageBuffer.putInt(8, arg1); 55 mMessageBuffer.putInt(12, (data == null ? 0 : data.length)); 56 mMessageBuffer.putInt(16, (data == null ? 0 : checksum(data))); 57 mMessageBuffer.putInt(20, command ^ 0xFFFFFFFF); 58 if (data != null) { 59 mDataBuffer.put(data, 0, data.length); 60 } 61 } 62 set(int command, int arg0, int arg1)63 public void set(int command, int arg0, int arg1) { 64 set(command, arg0, arg1, (byte[])null); 65 } set(int command, int arg0, int arg1, String data)66 public void set(int command, int arg0, int arg1, String data) { 67 // add trailing zero 68 data += "\0"; 69 set(command, arg0, arg1, data.getBytes()); 70 } 71 72 // returns the command's message ID getCommand()73 public int getCommand() { 74 return mMessageBuffer.getInt(0); 75 } 76 77 // returns command's first argument getArg0()78 public int getArg0() { 79 return mMessageBuffer.getInt(4); 80 } 81 82 // returns command's second argument getArg1()83 public int getArg1() { 84 return mMessageBuffer.getInt(8); 85 } 86 87 // returns command's data buffer getData()88 public ByteBuffer getData() { 89 return mDataBuffer; 90 } 91 92 // returns command's data length getDataLength()93 public int getDataLength() { 94 return mMessageBuffer.getInt(12); 95 } 96 97 // returns command's data as a string getDataString()98 public String getDataString() { 99 int length = getDataLength(); 100 if (length == 0) return null; 101 // trim trailing zero 102 return new String(mDataBuffer.array(), 0, length - 1); 103 } 104 105 write(AdbDevice device)106 public boolean write(AdbDevice device) { 107 synchronized (device) { 108 UsbRequest request = device.getOutRequest(); 109 request.setClientData(this); 110 if (request.queue(mMessageBuffer, 24)) { 111 int length = getDataLength(); 112 if (length > 0) { 113 request = device.getOutRequest(); 114 request.setClientData(this); 115 if (request.queue(mDataBuffer, length)) { 116 return true; 117 } else { 118 device.releaseOutRequest(request); 119 return false; 120 } 121 } 122 return true; 123 } else { 124 device.releaseOutRequest(request); 125 return false; 126 } 127 } 128 } 129 readCommand(UsbRequest request)130 public boolean readCommand(UsbRequest request) { 131 request.setClientData(this); 132 return request.queue(mMessageBuffer, 24); 133 } 134 readData(UsbRequest request, int length)135 public boolean readData(UsbRequest request, int length) { 136 request.setClientData(this); 137 return request.queue(mDataBuffer, length); 138 } 139 extractString(ByteBuffer buffer, int offset, int length)140 private static String extractString(ByteBuffer buffer, int offset, int length) { 141 byte[] bytes = new byte[length]; 142 for (int i = 0; i < length; i++) { 143 bytes[i] = buffer.get(offset++); 144 } 145 return new String(bytes); 146 } 147 148 @Override toString()149 public String toString() { 150 String commandName = extractString(mMessageBuffer, 0, 4); 151 int dataLength = getDataLength(); 152 String result = "Adb Message: " + commandName + " arg0: " + getArg0() + 153 " arg1: " + getArg1() + " dataLength: " + dataLength; 154 if (dataLength > 0) { 155 result += (" data: \"" + getDataString() + "\""); 156 } 157 return result; 158 } 159 checksum(byte[] data)160 private static int checksum(byte[] data) { 161 int result = 0; 162 for (int i = 0; i < data.length; i++) { 163 int x = data[i]; 164 // dang, no unsigned ints in java 165 if (x < 0) x += 256; 166 result += x; 167 } 168 return result; 169 } 170 }