Home | History | Annotate | Download | only in adb
      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 
     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
     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 
     63     public void set(int command, int arg0, int arg1) {
     64         set(command, arg0, arg1, (byte[])null);
     65     }
     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
     73     public int getCommand() {
     74         return mMessageBuffer.getInt(0);
     75     }
     76 
     77     // returns command's first argument
     78     public int getArg0() {
     79         return mMessageBuffer.getInt(4);
     80     }
     81 
     82     // returns command's second argument
     83     public int getArg1() {
     84         return mMessageBuffer.getInt(8);
     85     }
     86 
     87     // returns command's data buffer
     88     public ByteBuffer getData() {
     89         return mDataBuffer;
     90     }
     91 
     92     // returns command's data length
     93     public int getDataLength() {
     94         return mMessageBuffer.getInt(12);
     95     }
     96 
     97     // returns command's data as a string
     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 
    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 
    130     public boolean readCommand(UsbRequest request) {
    131         request.setClientData(this);
    132         return request.queue(mMessageBuffer, 24);
    133     }
    134 
    135     public boolean readData(UsbRequest request, int length) {
    136         request.setClientData(this);
    137         return request.queue(mDataBuffer, length);
    138     }
    139 
    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
    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 
    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 }