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