• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AdbWinUsbEndpointObject(AdbWinUsbInterfaceObject * parent_interf,UCHAR endpoint_id,UCHAR endpoint_index)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 
~AdbWinUsbEndpointObject()33 AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() {
34 }
35 
Release()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 
CommonAsyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,HANDLE event_handle,ULONG time_out)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 
CommonSyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,ULONG time_out)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 
SetTimeout(ULONG timeout)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