1 /* 2 * Copyright (C) 2019 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 #include <err.h> 18 #include <stdio.h> 19 #include <unistd.h> 20 21 #include <optional> 22 #include <string> 23 #include <vector> 24 25 #include <libusb/libusb.h> 26 27 static bool is_adb_device(libusb_device* device) { 28 libusb_device_descriptor device_desc; 29 libusb_get_device_descriptor(device, &device_desc); 30 if (device_desc.bDeviceClass != 0) { 31 return false; 32 } 33 34 libusb_config_descriptor* config_desc; 35 int rc = libusb_get_active_config_descriptor(device, &config_desc); 36 if (rc != 0) { 37 fprintf(stderr, "failed to get config descriptor for device %u:%u: %s\n", 38 libusb_get_bus_number(device), libusb_get_port_number(device), 39 libusb_error_name(rc)); 40 return false; 41 } 42 43 for (size_t i = 0; i < config_desc->bNumInterfaces; ++i) { 44 const libusb_interface* interface = &config_desc->interface[i]; 45 for (int j = 0; j < interface->num_altsetting; ++j) { 46 const libusb_interface_descriptor* interface_descriptor = &interface->altsetting[j]; 47 if (interface_descriptor->bInterfaceClass == 0xff && 48 interface_descriptor->bInterfaceSubClass == 0x42 && 49 interface_descriptor->bInterfaceProtocol == 1) { 50 return true; 51 } 52 } 53 } 54 55 return false; 56 } 57 58 static std::optional<std::vector<uint8_t>> get_descriptor(libusb_device_handle* handle, 59 uint8_t type, uint8_t index, 60 uint16_t length) { 61 std::vector<uint8_t> result; 62 result.resize(length); 63 int rc = libusb_get_descriptor(handle, type, index, result.data(), result.size()); 64 if (rc < 0) { 65 fprintf(stderr, "libusb_get_descriptor failed: %s\n", libusb_error_name(rc)); 66 return std::nullopt; 67 } 68 result.resize(rc); 69 return result; 70 } 71 72 static std::optional<std::string> get_string_descriptor(libusb_device_handle* handle, 73 uint8_t index) { 74 std::string result; 75 result.resize(4096); 76 int rc = libusb_get_string_descriptor_ascii( 77 handle, index, reinterpret_cast<uint8_t*>(result.data()), result.size()); 78 if (rc < 0) { 79 fprintf(stderr, "libusb_get_string_descriptor_ascii failed: %s\n", libusb_error_name(rc)); 80 return std::nullopt; 81 } 82 result.resize(rc); 83 return result; 84 } 85 86 static void check_ms_os_desc_v1(libusb_device_handle* device_handle, const std::string& serial) { 87 auto os_desc = get_descriptor(device_handle, 0x03, 0xEE, 0x12); 88 if (!os_desc) { 89 errx(1, "failed to retrieve MS OS descriptor"); 90 } 91 92 if (os_desc->size() != 0x12) { 93 errx(1, "os descriptor size mismatch"); 94 } 95 96 if (memcmp(os_desc->data() + 2, u"MSFT100\0", 14) != 0) { 97 errx(1, "os descriptor signature mismatch"); 98 } 99 100 uint8_t vendor_code = (*os_desc)[16]; 101 uint8_t pad = (*os_desc)[17]; 102 103 if (pad != 0) { 104 errx(1, "os descriptor padding non-zero"); 105 } 106 107 std::vector<uint8_t> data; 108 data.resize(0x10); 109 int rc = libusb_control_transfer(device_handle, 0xC0, vendor_code, 0x00, 0x04, data.data(), 110 data.size(), 0); 111 if (rc != 0x10) { 112 errx(1, "failed to retrieve MS OS v1 compat descriptor header: %s", libusb_error_name(rc)); 113 } 114 115 struct __attribute__((packed)) ms_os_desc_v1_header { 116 uint32_t dwLength; 117 uint16_t bcdVersion; 118 uint16_t wIndex; 119 uint8_t bCount; 120 uint8_t reserved[7]; 121 }; 122 static_assert(sizeof(ms_os_desc_v1_header) == 0x10); 123 124 ms_os_desc_v1_header hdr; 125 memcpy(&hdr, data.data(), data.size()); 126 127 data.resize(hdr.dwLength); 128 rc = libusb_control_transfer(device_handle, 0xC0, vendor_code, 0x00, 0x04, data.data(), 129 data.size(), 0); 130 if (static_cast<size_t>(rc) != data.size()) { 131 errx(1, "failed to retrieve MS OS v1 compat descriptor: %s", libusb_error_name(rc)); 132 } 133 134 struct __attribute__((packed)) ms_os_desc_v1_function { 135 uint8_t bFirstInterfaceNumber; 136 uint8_t reserved1; 137 uint8_t compatibleID[8]; 138 uint8_t subCompatibleID[8]; 139 uint8_t reserved2[6]; 140 }; 141 142 if (sizeof(ms_os_desc_v1_header) + hdr.bCount * sizeof(ms_os_desc_v1_function) != data.size()) { 143 errx(1, "MS OS v1 compat descriptor size mismatch"); 144 } 145 146 for (int i = 0; i < hdr.bCount; ++i) { 147 ms_os_desc_v1_function function; 148 memcpy(&function, 149 data.data() + sizeof(ms_os_desc_v1_header) + i * sizeof(ms_os_desc_v1_function), 150 sizeof(function)); 151 if (memcmp("WINUSB\0\0", function.compatibleID, 8) == 0) { 152 return; 153 } 154 } 155 156 errx(1, "failed to find v1 MS OS descriptor specifying WinUSB for device %s", serial.c_str()); 157 } 158 159 static void check_ms_os_desc_v2(libusb_device_handle* device_handle, const std::string& serial) { 160 libusb_bos_descriptor* bos; 161 int rc = libusb_get_bos_descriptor(device_handle, &bos); 162 163 if (rc != 0) { 164 fprintf(stderr, "failed to get bos descriptor for device %s\n", serial.c_str()); 165 return; 166 } 167 168 for (size_t i = 0; i < bos->bNumDeviceCaps; ++i) { 169 libusb_bos_dev_capability_descriptor* desc = bos->dev_capability[i]; 170 if (desc->bDescriptorType != LIBUSB_DT_DEVICE_CAPABILITY) { 171 errx(1, "invalid BOS descriptor type: %d", desc->bDescriptorType); 172 } 173 174 if (desc->bDevCapabilityType != 0x05 /* PLATFORM */) { 175 fprintf(stderr, "skipping non-platform dev capability: %#02x\n", 176 desc->bDevCapabilityType); 177 continue; 178 } 179 180 if (desc->bLength < sizeof(*desc) + 16) { 181 errx(1, "received device capability descriptor not long enough to contain a UUID?"); 182 } 183 184 char uuid[16]; 185 memcpy(uuid, desc->dev_capability_data, 16); 186 187 constexpr uint8_t ms_os_uuid[16] = {0xD8, 0xDD, 0x60, 0xDF, 0x45, 0x89, 0x4C, 0xC7, 188 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F}; 189 if (memcmp(uuid, ms_os_uuid, 16) != 0) { 190 fprintf(stderr, "skipping unknown UUID\n"); 191 continue; 192 } 193 194 size_t data_length = desc->bLength - sizeof(*desc) - 16; 195 fprintf(stderr, "found MS OS 2.0 descriptor, length = %zu\n", data_length); 196 197 // Linux does not appear to support MS OS 2.0 Descriptors. 198 // TODO: If and when it does, verify that we're emitting them properly. 199 } 200 } 201 202 int main(int argc, char** argv) { 203 libusb_context* ctx; 204 if (libusb_init(&ctx) != 0) { 205 errx(1, "failed to initialize libusb context"); 206 } 207 208 libusb_device** device_list = nullptr; 209 ssize_t device_count = libusb_get_device_list(ctx, &device_list); 210 if (device_count < 0) { 211 errx(1, "libusb_get_device_list failed"); 212 } 213 214 const char* expected_serial = getenv("ANDROID_SERIAL"); 215 bool found = false; 216 217 for (ssize_t i = 0; i < device_count; ++i) { 218 libusb_device* device = device_list[i]; 219 if (!is_adb_device(device)) { 220 continue; 221 } 222 223 libusb_device_handle* device_handle = nullptr; 224 int rc = libusb_open(device, &device_handle); 225 if (rc != 0) { 226 fprintf(stderr, "failed to open device %u:%u: %s\n", libusb_get_bus_number(device), 227 libusb_get_port_number(device), libusb_error_name(rc)); 228 continue; 229 } 230 231 libusb_device_descriptor device_desc; 232 libusb_get_device_descriptor(device, &device_desc); 233 234 std::optional<std::string> serial = 235 get_string_descriptor(device_handle, device_desc.iSerialNumber); 236 if (!serial) { 237 errx(1, "failed to get serial for device %u:%u", libusb_get_bus_number(device), 238 libusb_get_port_number(device)); 239 } 240 241 if (expected_serial && *serial != expected_serial) { 242 fprintf(stderr, "skipping %s (wanted %s)\n", serial->c_str(), expected_serial); 243 continue; 244 } 245 246 // Check for MS OS Descriptor v1. 247 // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeusb/c2f351f9-84d2-4a1b-9fe3-a6ca195f84d0 248 fprintf(stderr, "fetching v1 OS descriptor from device %s\n", serial->c_str()); 249 check_ms_os_desc_v1(device_handle, *serial); 250 fprintf(stderr, "found v1 OS descriptor for device %s\n", serial->c_str()); 251 252 // Read BOS for MS OS Descriptor 2.0 descriptors: 253 // http://download.microsoft.com/download/3/5/6/3563ED4A-F318-4B66-A181-AB1D8F6FD42D/MS_OS_2_0_desc.docx 254 fprintf(stderr, "fetching v2 OS descriptor from device %s\n", serial->c_str()); 255 check_ms_os_desc_v2(device_handle, *serial); 256 257 found = true; 258 } 259 260 if (expected_serial && !found) { 261 errx(1, "failed to find device with serial %s", expected_serial); 262 } 263 return 0; 264 } 265