1 /* 2 * Copyright (C) 2009 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 /** \file 18 This file consists of implementation of class AdbLegacyEndpointObject that 19 encapsulates a handle opened to an endpoint on our device controlled by 20 a custom (legacy) USB driver. 21 */ 22 23 #include "stdafx.h" 24 #include "adb_api_legacy.h" 25 #include "adb_legacy_endpoint_object.h" 26 #include "adb_legacy_io_completion.h" 27 #include "adb_helper_routines.h" 28 29 AdbLegacyEndpointObject::AdbLegacyEndpointObject( 30 AdbLegacyInterfaceObject* parent_interf, 31 UCHAR endpoint_id, 32 UCHAR endpoint_index) 33 : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index), 34 usb_handle_(INVALID_HANDLE_VALUE) { 35 } 36 37 AdbLegacyEndpointObject::~AdbLegacyEndpointObject() { 38 if (INVALID_HANDLE_VALUE != usb_handle_) { 39 ::CloseHandle(usb_handle_); 40 } 41 } 42 43 ADBAPIHANDLE AdbLegacyEndpointObject::CommonAsyncReadWrite( 44 bool is_read, 45 void* buffer, 46 ULONG bytes_to_transfer, 47 ULONG* bytes_transferred, 48 HANDLE event_handle, 49 ULONG time_out) { 50 if (NULL != bytes_transferred) { 51 *bytes_transferred = 0; 52 } 53 54 if (!IsOpened()) { 55 SetLastError(ERROR_INVALID_HANDLE); 56 return false; 57 } 58 59 bool is_ioctl_write = is_read ? false : (0 != time_out); 60 61 // Create completion i/o object 62 AdbLegacyIOCompletion* adb_io_completion = NULL; 63 64 try { 65 adb_io_completion = new AdbLegacyIOCompletion(this, 66 bytes_to_transfer, 67 event_handle, 68 is_ioctl_write); 69 } catch (... ) { 70 // We don't expect exceptions other than OOM thrown here. 71 SetLastError(ERROR_OUTOFMEMORY); 72 return NULL; 73 } 74 75 // Create a handle for it 76 ADBAPIHANDLE ret = adb_io_completion->CreateHandle(); 77 ULONG transferred = 0; 78 if (NULL != ret) { 79 BOOL res = TRUE; 80 if (0 == time_out) { 81 // Go the read / write file way 82 res = is_read ? ReadFile(usb_handle(), 83 buffer, 84 bytes_to_transfer, 85 &transferred, 86 adb_io_completion->overlapped()) : 87 WriteFile(usb_handle(), 88 buffer, 89 bytes_to_transfer, 90 &transferred, 91 adb_io_completion->overlapped()); 92 } else { 93 // Go IOCTL way 94 AdbBulkTransfer transfer_param; 95 transfer_param.time_out = time_out; 96 transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer; 97 transfer_param.SetWriteBuffer(is_read ? NULL : buffer); 98 99 res = DeviceIoControl(usb_handle(), 100 is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE, 101 &transfer_param, sizeof(transfer_param), 102 is_read ? buffer : adb_io_completion->transferred_bytes_ptr(), 103 is_read ? bytes_to_transfer : sizeof(ULONG), 104 &transferred, 105 adb_io_completion->overlapped()); 106 } 107 108 if (NULL != bytes_transferred) { 109 *bytes_transferred = transferred; 110 } 111 112 ULONG error = GetLastError(); 113 if (!res && (ERROR_IO_PENDING != error)) { 114 // I/O failed immediatelly. We need to close i/o completion object 115 // before we return NULL to the caller. 116 adb_io_completion->CloseHandle(); 117 ret = NULL; 118 SetLastError(error); 119 } 120 } 121 122 // Offseting 'new' 123 adb_io_completion->Release(); 124 125 return ret; 126 } 127 128 bool AdbLegacyEndpointObject::CommonSyncReadWrite(bool is_read, 129 void* buffer, 130 ULONG bytes_to_transfer, 131 ULONG* bytes_transferred, 132 ULONG time_out) { 133 if (NULL != bytes_transferred) { 134 *bytes_transferred = 0; 135 } 136 137 if (!IsOpened()) { 138 SetLastError(ERROR_INVALID_HANDLE); 139 return false; 140 } 141 142 bool is_ioctl_write = is_read ? false : (0 != time_out); 143 144 // This is synchronous I/O. Since we always open I/O items for 145 // overlapped I/O we're obligated to always provide OVERLAPPED 146 // structure to read / write routines. Prepare it now. 147 OVERLAPPED overlapped; 148 ZeroMemory(&overlapped, sizeof(overlapped)); 149 150 BOOL ret = TRUE; 151 ULONG ioctl_write_transferred = 0; 152 if (0 == time_out) { 153 // Go the read / write file way 154 ret = is_read ? 155 ReadFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped) : 156 WriteFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped); 157 } else { 158 // Go IOCTL way 159 AdbBulkTransfer transfer_param; 160 transfer_param.time_out = time_out; 161 transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer; 162 transfer_param.SetWriteBuffer(is_read ? NULL : buffer); 163 164 ULONG tmp; 165 ret = DeviceIoControl(usb_handle(), 166 is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE, 167 &transfer_param, sizeof(transfer_param), 168 is_read ? buffer : &ioctl_write_transferred, 169 is_read ? bytes_to_transfer : sizeof(ULONG), 170 &tmp, 171 &overlapped); 172 } 173 174 // Lets see the result 175 if (!ret && (ERROR_IO_PENDING != GetLastError())) { 176 // I/O failed. 177 return false; 178 } 179 180 // Lets wait till I/O completes 181 ULONG transferred = 0; 182 ret = GetOverlappedResult(usb_handle(), &overlapped, &transferred, TRUE); 183 if (ret && (NULL != bytes_transferred)) { 184 *bytes_transferred = is_ioctl_write ? ioctl_write_transferred : 185 transferred; 186 } 187 188 return ret ? true : false; 189 } 190 191 ADBAPIHANDLE AdbLegacyEndpointObject::CreateHandle( 192 const wchar_t* item_path, 193 AdbOpenAccessType access_type, 194 AdbOpenSharingMode share_mode) { 195 // Convert access / share parameters into CreateFile - compatible 196 ULONG desired_access; 197 ULONG desired_sharing; 198 199 if (!GetSDKComplientParam(access_type, share_mode, 200 &desired_access, &desired_sharing)) { 201 return NULL; 202 } 203 204 // Open USB handle 205 usb_handle_ = CreateFile(item_path, 206 desired_access, 207 share_mode, 208 NULL, 209 OPEN_EXISTING, 210 FILE_FLAG_OVERLAPPED, // Always overlapped! 211 NULL); 212 if (INVALID_HANDLE_VALUE == usb_handle_) { 213 return NULL; 214 } 215 216 // Create ADB handle 217 ADBAPIHANDLE ret = AdbObjectHandle::CreateHandle(); 218 219 if (NULL == ret) { 220 // If creation of ADB handle failed we have to close USB handle too. 221 ULONG error = GetLastError(); 222 ::CloseHandle(usb_handle()); 223 usb_handle_ = INVALID_HANDLE_VALUE; 224 SetLastError(error); 225 } 226 227 return ret; 228 } 229 230 bool AdbLegacyEndpointObject::CloseHandle() { 231 if (INVALID_HANDLE_VALUE != usb_handle_) { 232 ::CloseHandle(usb_handle_); 233 usb_handle_ = INVALID_HANDLE_VALUE; 234 } 235 236 return AdbEndpointObject::CloseHandle(); 237 } 238