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