• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 #include "guest/commands/usbforward/transport_request.h"
18 
19 #include <log/log.h>
20 
21 namespace usb_forward {
22 
TransportRequest(std::shared_ptr<libusb_device_handle> handle,CallbackType callback,const ControlTransfer & transfer)23 TransportRequest::TransportRequest(std::shared_ptr<libusb_device_handle> handle,
24                                    CallbackType callback,
25                                    const ControlTransfer& transfer)
26     : handle_{std::move(handle)},
27       callback_{std::move(callback)},
28       is_control_{true},
29       transfer_{libusb_alloc_transfer(0), libusb_free_transfer} {
30   // NOTE: libusb places setup structure as part of user data!
31   buffer_.reset(new uint8_t[transfer.length + LIBUSB_CONTROL_SETUP_SIZE]);
32 
33   // NOTE: libusb places a structure of size LIBUSB_CONTROL_SETUP_SIZE directly
34   // in the data buffer.
35   libusb_fill_control_setup(buffer_.get(), transfer.type, transfer.cmd,
36                             transfer.value, transfer.index, transfer.length);
37 
38   // NOTE: despite libusb requires user to allocate buffer large enough to
39   // accommodate SETUP structure and actual data, it requires user to provide
40   // only data length here, while setup length is added internally.
41   libusb_fill_control_transfer(transfer_.get(), handle_.get(), buffer_.get(),
42                                OnTransferComplete, this, transfer.timeout);
43 }
44 
TransportRequest(std::shared_ptr<libusb_device_handle> handle,CallbackType callback,const DataTransfer & transfer)45 TransportRequest::TransportRequest(std::shared_ptr<libusb_device_handle> handle,
46                                    CallbackType callback,
47                                    const DataTransfer& transfer)
48     : handle_{std::move(handle)},
49       callback_{std::move(callback)},
50       is_control_{false},
51       transfer_{libusb_alloc_transfer(0), libusb_free_transfer} {
52   buffer_.reset(new uint8_t[transfer.length]);
53   libusb_fill_bulk_transfer(
54       transfer_.get(), handle_.get(),
55       transfer.endpoint_id | (transfer.is_host_to_device ? LIBUSB_ENDPOINT_OUT
56                                                          : LIBUSB_ENDPOINT_IN),
57       buffer_.get(), transfer.length, OnTransferComplete, this,
58       transfer.timeout);
59 }
60 
Buffer()61 uint8_t* TransportRequest::Buffer() {
62   if (is_control_) {
63     return &buffer_[LIBUSB_CONTROL_SETUP_SIZE];
64   } else {
65     return buffer_.get();
66   }
67 }
68 
Submit()69 bool TransportRequest::Submit() {
70   if (handle_) {
71     auto err = libusb_submit_transfer(transfer_.get());
72     if (err != 0) {
73       ALOGE("libusb transfer failed: %d", err);
74     }
75     return err == 0;
76   } else {
77     ALOGE("Initiated transfer, but device not opened.");
78     return false;
79   }
80 }
81 
OnTransferComplete(libusb_transfer * req)82 void TransportRequest::OnTransferComplete(libusb_transfer* req) {
83   auto treq = static_cast<TransportRequest*>(req->user_data);
84   treq->callback_(req->status == 0, treq->Buffer(), req->actual_length);
85 }
86 
87 }  // namespace usb_forward
88