Home | History | Annotate | Download | only in winusb
      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