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 AdbWinUsbEndpointObject that 19 encapsulates a handle opened to a WinUsb endpoint on our device. 20 */ 21 22 #include "stdafx.h" 23 #include "adb_winusb_endpoint_object.h" 24 #include "adb_winusb_io_completion.h" 25 26 AdbWinUsbEndpointObject::AdbWinUsbEndpointObject( 27 AdbWinUsbInterfaceObject* parent_interf, 28 UCHAR endpoint_id, 29 UCHAR endpoint_index) 30 : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index) { 31 } 32 33 AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() { 34 } 35 36 LONG AdbWinUsbEndpointObject::Release() { 37 ATLASSERT(ref_count_ > 0); 38 LONG ret = InterlockedDecrement(&ref_count_); 39 ATLASSERT(ret >= 0); 40 if (0 == ret) { 41 LastReferenceReleased(); 42 delete this; 43 } 44 return ret; 45 } 46 47 ADBAPIHANDLE AdbWinUsbEndpointObject::CommonAsyncReadWrite( 48 bool is_read, 49 void* buffer, 50 ULONG bytes_to_transfer, 51 ULONG* bytes_transferred, 52 HANDLE event_handle, 53 ULONG time_out) { 54 if (!SetTimeout(time_out)) 55 return false; 56 57 // Create completion i/o object 58 AdbIOCompletion* adb_io_completion = NULL; 59 60 try { 61 adb_io_completion = new AdbWinUsbIOCompletion(this, 62 bytes_to_transfer, 63 event_handle); 64 } catch (... ) { 65 SetLastError(ERROR_OUTOFMEMORY); 66 return NULL; 67 } 68 69 // Create a handle for it 70 ADBAPIHANDLE ret = adb_io_completion->CreateHandle(); 71 ULONG transferred = 0; 72 if (NULL != ret) { 73 BOOL res = TRUE; 74 // Go the read / write file way 75 res = is_read ? 76 WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(), 77 endpoint_id(), 78 reinterpret_cast<PUCHAR>(buffer), 79 bytes_to_transfer, 80 &transferred, 81 adb_io_completion->overlapped()) : 82 WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(), 83 endpoint_id(), 84 reinterpret_cast<PUCHAR>(buffer), 85 bytes_to_transfer, 86 &transferred, 87 adb_io_completion->overlapped()); 88 89 if (NULL != bytes_transferred) 90 *bytes_transferred = transferred; 91 92 ULONG error = GetLastError(); 93 if (!res && (ERROR_IO_PENDING != error)) { 94 // I/O failed immediatelly. We need to close i/o completion object 95 // before we return NULL to the caller. 96 adb_io_completion->CloseHandle(); 97 ret = NULL; 98 SetLastError(error); 99 } 100 } 101 102 // Offseting 'new' 103 adb_io_completion->Release(); 104 105 return ret; 106 } 107 108 bool AdbWinUsbEndpointObject::CommonSyncReadWrite(bool is_read, 109 void* buffer, 110 ULONG bytes_to_transfer, 111 ULONG* bytes_transferred, 112 ULONG time_out) { 113 if (!SetTimeout(time_out)) 114 return false; 115 116 // This is synchronous I/O. Since we always open I/O items for 117 // overlapped I/O we're obligated to always provide OVERLAPPED 118 // structure to read / write routines. Prepare it now. 119 OVERLAPPED overlapped; 120 ZeroMemory(&overlapped, sizeof(overlapped)); 121 overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 122 123 BOOL ret = TRUE; 124 ULONG transferred = 0; 125 // Go the read / write file way 126 ret = is_read ? 127 WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(), 128 endpoint_id(), 129 reinterpret_cast<PUCHAR>(buffer), 130 bytes_to_transfer, 131 &transferred, 132 &overlapped) : 133 WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(), 134 endpoint_id(), 135 reinterpret_cast<PUCHAR>(buffer), 136 bytes_to_transfer, 137 &transferred, 138 &overlapped); 139 140 // Lets see the result 141 if (!ret && (ERROR_IO_PENDING != GetLastError())) { 142 // I/O failed. 143 if (NULL != overlapped.hEvent) 144 ::CloseHandle(overlapped.hEvent); 145 return false; 146 } 147 148 // Lets wait till I/O completes 149 ret = WinUsb_GetOverlappedResult(parent_winusb_interface()->winusb_handle(), &overlapped, 150 &transferred, TRUE); 151 if (ret && (NULL != bytes_transferred)) { 152 *bytes_transferred = transferred; 153 } 154 155 if (NULL != overlapped.hEvent) 156 ::CloseHandle(overlapped.hEvent); 157 158 return ret ? true : false; 159 } 160 161 bool AdbWinUsbEndpointObject::SetTimeout(ULONG timeout) { 162 if (!WinUsb_SetPipePolicy(parent_winusb_interface()->winusb_handle(), 163 endpoint_id(), PIPE_TRANSFER_TIMEOUT, 164 sizeof(ULONG), &timeout)) { 165 return false; 166 } 167 168 return true; 169 } 170