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 
AdbLegacyEndpointObject(AdbLegacyInterfaceObject * parent_interf,UCHAR endpoint_id,UCHAR endpoint_index)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 
~AdbLegacyEndpointObject()37 AdbLegacyEndpointObject::~AdbLegacyEndpointObject() {
38   if (INVALID_HANDLE_VALUE != usb_handle_) {
39     ::CloseHandle(usb_handle_);
40   }
41 }
42 
CommonAsyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,HANDLE event_handle,ULONG time_out)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 
CommonSyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,ULONG time_out)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 
CreateHandle(const wchar_t * item_path,AdbOpenAccessType access_type,AdbOpenSharingMode share_mode)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 
CloseHandle()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