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