Home | History | Annotate | Download | only in handler
      1 /**
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
      5  * except in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * <p>http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * <p>Unless required by applicable law or agreed to in writing, software distributed under the
     10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     11  * express or implied. See the License for the specific language governing permissions and
     12  * limitations under the License.
     13  */
     14 package android.car.usb.handler;
     15 
     16 import android.hardware.usb.UsbConstants;
     17 import android.hardware.usb.UsbDevice;
     18 import android.hardware.usb.UsbDeviceConnection;
     19 import android.util.Log;
     20 import java.io.IOException;
     21 
     22 final class AoapInterface {
     23     /**
     24      * Use Google Vendor ID when in accessory mode
     25      */
     26     public static final int USB_ACCESSORY_VENDOR_ID = 0x18D1;
     27 
     28     /**
     29      * Product ID to use when in accessory mode
     30      */
     31     public static final int USB_ACCESSORY_PRODUCT_ID = 0x2D00;
     32 
     33     /**
     34      * Product ID to use when in accessory mode and adb is enabled
     35      */
     36     public static final int USB_ACCESSORY_ADB_PRODUCT_ID = 0x2D01;
     37 
     38     /**
     39      * Indexes for strings sent by the host via ACCESSORY_SEND_STRING
     40      */
     41     public static final int ACCESSORY_STRING_MANUFACTURER = 0;
     42     public static final int ACCESSORY_STRING_MODEL = 1;
     43     public static final int ACCESSORY_STRING_DESCRIPTION = 2;
     44     public static final int ACCESSORY_STRING_VERSION = 3;
     45     public static final int ACCESSORY_STRING_URI = 4;
     46     public static final int ACCESSORY_STRING_SERIAL = 5;
     47 
     48     /**
     49      * Control request for retrieving device's protocol version
     50      *
     51      *  requestType:    USB_DIR_IN | USB_TYPE_VENDOR
     52      *  request:        ACCESSORY_GET_PROTOCOL
     53      *  value:          0
     54      *  index:          0
     55      *  data            version number (16 bits little endian)
     56      *                     1 for original accessory support
     57      *                     2 adds HID and device to host audio support
     58      */
     59     public static final int ACCESSORY_GET_PROTOCOL = 51;
     60 
     61     /**
     62      * Control request for host to send a string to the device
     63      *
     64      *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
     65      *  request:        ACCESSORY_SEND_STRING
     66      *  value:          0
     67      *  index:          string ID
     68      *  data            zero terminated UTF8 string
     69      *
     70      *  The device can later retrieve these strings via the
     71      *  ACCESSORY_GET_STRING_* ioctls
     72      */
     73     public static final int ACCESSORY_SEND_STRING = 52;
     74 
     75     /**
     76      * Control request for starting device in accessory mode.
     77      * The host sends this after setting all its strings to the device.
     78      *
     79      *  requestType:    USB_DIR_OUT | USB_TYPE_VENDOR
     80      *  request:        ACCESSORY_START
     81      *  value:          0
     82      *  index:          0
     83      *  data            none
     84      */
     85     public static final int ACCESSORY_START = 53;
     86 
     87     /**
     88      * Max payload size for AOAP. Limited by driver.
     89      */
     90     public static final int MAX_PAYLOAD_SIZE = 16384;
     91 
     92     /**
     93      * Accessory write timeout.
     94      */
     95     public static final int AOAP_TIMEOUT_MS = 2000;
     96 
     97     private static final String TAG = AoapInterface.class.getSimpleName();
     98 
     99     public static int getProtocol(UsbDeviceConnection conn) {
    100         byte[] buffer = new byte[2];
    101         int len = conn.controlTransfer(
    102                 UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_VENDOR,
    103                 ACCESSORY_GET_PROTOCOL, 0, 0, buffer, 2, AOAP_TIMEOUT_MS);
    104         if (len != 2) {
    105             return -1;
    106         }
    107         return (buffer[1] << 8) | buffer[0];
    108     }
    109 
    110     public static boolean isSupported(UsbDeviceConnection conn) {
    111         return getProtocol(conn) >= 1;
    112     }
    113 
    114     public static void sendString(UsbDeviceConnection conn, int index, String string)
    115             throws IOException {
    116         byte[] buffer = (string + "\0").getBytes();
    117         int len = conn.controlTransfer(
    118                 UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
    119                 ACCESSORY_SEND_STRING, 0, index,
    120                 buffer, buffer.length, AOAP_TIMEOUT_MS);
    121         if (len != buffer.length) {
    122             throw new IOException("Failed to send string " + index + ": \"" + string + "\"");
    123         } else {
    124             Log.i(TAG, "Sent string " + index + ": \"" + string + "\"");
    125         }
    126     }
    127 
    128     public static void sendAoapStart(UsbDeviceConnection conn) throws IOException {
    129         int len = conn.controlTransfer(
    130                 UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
    131                 ACCESSORY_START, 0, 0, null, 0, AOAP_TIMEOUT_MS);
    132         if (len < 0) {
    133             throw new IOException("Control transfer for accessory start failed: " + len);
    134         }
    135     }
    136 
    137     public static boolean isDeviceInAoapMode(UsbDevice device) {
    138         if (device == null) {
    139             return false;
    140         }
    141         final int vid = device.getVendorId();
    142         final int pid = device.getProductId();
    143         return vid == USB_ACCESSORY_VENDOR_ID
    144                 && (pid == USB_ACCESSORY_PRODUCT_ID || pid == USB_ACCESSORY_ADB_PRODUCT_ID);
    145     }
    146 }
    147