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